        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        :root {
            /* CAA-inspired Gold Theme */
            --primary: #D4AF37;
            --primary-dark: #B8962F;
            --primary-bg: rgba(212, 175, 55, 0.08);
            --gradient-primary: linear-gradient(135deg, #D4AF37 0%, #B8962F 100%);

            --primary-text: #0F172A;
            --secondary-text: #475569;
            --message-bg: #F1F5F9;
            --sidebar-bg: #ffffff;
            --border-light: #E2E8F0;
            --border-lighter: #E2E8F0;
            --white: #ffffff;
            --hover-bg: #E2E8F0;

            --user-msg-bg: rgba(212, 175, 55, 0.10);
            --user-msg-text: #0F172A;
            --ai-msg-bg: #F0F4F8;

            --btn-primary: #D4AF37;
            --btn-hover: #B8962F;
            --pdf-viewer-bg: #F8FAFC;
            --header-bg: #ffffff;
            --input-border: #CBD5E1;
        }

        body {
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            margin: 0;
            padding: 0;
            height: 100vh;
            background: var(--white);
            color: var(--primary-text);
            overflow: hidden;
        }

        .container {
            display: flex;
            height: 100vh;
            overflow: hidden;
        }

        /* Chat Panel - v1.71.11: Increased to 45% for more chat space */
        .chat-panel {
            flex: 0 0 auto;
            width: 25%;
            min-width: 360px;
            display: flex;
            flex-direction: column;
            background: var(--white);
        }

        .panel-resizer {
            width: 1px;
            background: var(--border-light);
            cursor: col-resize;
            flex-shrink: 0;
            position: relative;
            transition: background 0.2s;
        }

        .panel-resizer::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 2px;
            height: 40px;
            background: var(--secondary-text);
            border-radius: 1px;
            opacity: 0.6;
        }

        .panel-resizer:hover,
        body.resizing .panel-resizer {
            background: rgba(25, 195, 125, 0.2);
        }

        body.resizing {
            cursor: col-resize;
            user-select: none;
        }

        body.resizing * {
            cursor: col-resize !important;
        }

        /* v1.71.10: Disable iframe pointer events during resize to prevent blocking */
        body.resizing iframe {
            pointer-events: none !important;
        }

        .chat-header {
            padding: 18px 24px;
            border-bottom: 1px solid var(--border-light);
            background: var(--header-bg);
            display: flex;
            justify-content: space-between;
            align-items: center;
            height: 60px;
            box-sizing: border-box;
        }

        .chat-header h1 {
            font-size: 18px;
            font-weight: 600;
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            color: var(--primary-text);
            display: flex;
            align-items: center;
        }

        .chat-header h1::before {
            display: none;
        }

        .chat-header button {
            padding: 8px 16px;
            background: var(--white);
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            color: var(--secondary-text);
            font-weight: 500;
            transition: all 0.2s;
        }

        .chat-header button:hover {
            background: var(--hover-bg);
            border-color: var(--primary-text);
        }

        /* Progress Indicator */
        .progress-container {
            padding: 12px 24px;
            background: var(--white);
            border-top: 1px solid var(--border-light);
            display: none;
        }

        .progress-container.active {
            display: block;
        }

        .progress-steps {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
        }

        .progress-step {
            flex: 1;
            text-align: center;
            position: relative;
            font-size: 12px;
            color: var(--secondary-text);
        }

        .progress-step.active {
            color: var(--btn-primary);
            font-weight: 600;
        }

        .progress-step.completed {
            color: var(--btn-primary);
        }

        .progress-step::before {
            content: '';
            display: block;
            width: 24px;
            height: 24px;
            margin: 0 auto 6px;
            border-radius: 50%;
            background: var(--border-light);
            border: 2px solid var(--border-light);
        }

        .progress-step.active::before {
            background: var(--white);
            border-color: var(--btn-primary);
            animation: pulse 2s infinite;
        }

        .progress-step.completed::before {
            background: var(--btn-primary);
            border-color: var(--btn-primary);
            content: '✓';
            color: white;
            line-height: 20px;
            font-size: 14px;
        }

        .progress-step:not(:last-child)::after {
            content: '';
            position: absolute;
            top: 12px;
            left: 60%;
            width: 80%;
            height: 2px;
            background: var(--border-light);
        }

        .progress-step.completed:not(:last-child)::after {
            background: var(--btn-primary);
        }

        @keyframes pulse {
            0%, 100% { transform: scale(1); }
            50% { transform: scale(1.1); }
        }

        .progress-bar {
            height: 4px;
            background: var(--border-light);
            border-radius: 2px;
            overflow: hidden;
        }

        .progress-bar-fill {
            height: 100%;
            background: linear-gradient(90deg, var(--btn-primary), var(--btn-hover));
            width: 0%;
            transition: width 0.5s ease;
        }

        /* Messages Area */
        .chat-messages {
            flex: 1;
            overflow-y: auto;
            padding: 24px;
            background: var(--white);
        }

        .message {
            margin-bottom: 24px;
            display: flex;
            gap: 16px;
            align-items: flex-start;
            width: 100%;
            flex-wrap: wrap;  /* lets .message-meta drop onto its own row */
        }

        /* Hover meta row: send time + copy button, hidden by default,
           revealed on hover. Sits below the bubble on a fresh flex row. */
        .message-meta {
            flex-basis: 100%;
            display: flex;
            align-items: center;
            gap: 6px;
            margin-top: 2px;
            padding: 0 4px;
            font-size: 10px;
            color: var(--fg-muted, #6b7280);
            opacity: 0;
            transition: opacity 0.15s ease;
            pointer-events: none;  /* avoid stealing hover when invisible */
        }

        .message:hover .message-meta {
            opacity: 1;
            pointer-events: auto;
        }

        /* Right-align the meta row under user messages, left-align under AI */
        .message-user .message-meta { justify-content: flex-end; }
        .message-assistant .message-meta { justify-content: flex-start; }

        .message-meta-time {
            font-variant-numeric: tabular-nums;
        }

        .message-meta-btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 18px;
            height: 18px;
            padding: 0;
            border: 0;
            border-radius: 4px;
            background: transparent;
            color: inherit;
            cursor: pointer;
            transition: background 0.12s ease, color 0.12s ease;
        }

        .message-meta-btn svg {
            width: 11px;
            height: 11px;
        }

        .message-meta-btn:hover {
            background: rgba(0, 0, 0, 0.06);
            color: var(--fg, #111216);
        }

        .message-meta-btn.copied {
            color: #16a34a;  /* green tick */
        }

        /* ChatGPT-style: user gray bubble on right, AI plain text on left */
        .message-avatar {
            display: none;
        }

        .message-content {
            max-width: 85%;
            font-size: 15px;
            line-height: 1.6;
            white-space: pre-wrap;
            word-wrap: break-word;
            text-align: left;
            padding: 12px 16px;
        }

        .message-user {
            justify-content: flex-end;
            padding: 0;
        }

        .message-user .message-content {
            background: var(--user-msg-bg);
            color: var(--user-msg-text);
            border-radius: 16px 16px 6px 16px;
            margin-left: auto;
            white-space: pre-wrap;
        }

        .message-assistant {
            justify-content: flex-start;
            padding: 0;
        }

        .message-assistant .message-content {
            background: var(--ai-msg-bg);
            color: var(--primary-text);
            border-radius: 16px 16px 16px 6px;
            padding: 12px 16px;
            overflow: hidden;
        }

        /* Hide empty streaming/tools bubbles before content arrives */
        .message-assistant:has(.msg-text:empty) {
            display: none;
        }
        .message-assistant:has(.activity-chips:empty) {
            display: none;
        }

        .message-process .message-content {
            background: #f8fafc;
            color: #475569;
            border: 1px solid #e2e8f0;
        }

        .thinking-block {
            margin-bottom: 8px;
            max-width: 85%;
        }

        .thinking-summary {
            cursor: pointer;
            color: #9ca3af;
            font-size: 13px;
            padding: 6px 12px;
            border-radius: 8px;
            background: #f9fafb;
            user-select: none;
            list-style: none;
        }

        .thinking-summary::-webkit-details-marker {
            display: none;
        }

        .thinking-summary::before {
            content: '▶ ';
            font-size: 10px;
            margin-right: 4px;
        }

        .thinking-block[open] .thinking-summary::before {
            content: '▼ ';
        }

        .thinking-body {
            padding: 8px 14px;
            margin-top: 4px;
            background: #f9fafb;
            border-radius: 8px;
            color: #6b7280;
            font-size: 13px;
            line-height: 1.5;
            white-space: pre-wrap;
        }

        /* Active thinking block: pulsing summary while streaming */
        .thinking-block-active .thinking-summary {
            animation: thinking-summary-pulse 1.5s ease-in-out infinite;
        }

        .thinking-block-active .thinking-body:empty {
            display: none;
        }

        @keyframes thinking-summary-pulse {
            0%, 100% { opacity: 0.5; }
            50% { opacity: 1; }
        }

        .message-content p {
            margin: 0;
        }

        .message-content p:empty {
            display: none;
        }

        .msg-text > br:first-child,
        .msg-text > br:last-child {
            display: none;
        }

        .message-content ol,
        .message-content ul {
            padding-left: 1.4em;
            margin: 2px 0;
        }

        .message-content li {
            margin: 0;
        }

        .message-content h3, .message-content h4 {
            margin: 4px 0 1px;
            font-size: 15px;
        }

        .message-content blockquote {
            margin: 4px 0;
            padding-left: 10px;
            border-left: 3px solid #d1d5db;
            color: #6b7280;
        }

        .message-content table {
            margin: 4px 0;
        }

        .message-content hr {
            border: none;
            border-top: 1px solid #e5e7eb;
            margin: 6px 0;
        }

        /* Thinking indicator */
        .thinking-indicator {
            display: flex;
            align-items: center;
            color: var(--secondary-text);
            font-size: 14px;
            padding: 4px 0;
        }

        .thinking-dots {
            display: inline-block;
            animation: thinking-pulse 1.5s ease-in-out infinite;
        }

        .thinking-dots:empty::after {
            content: '●●●';
            letter-spacing: 2px;
        }

        @keyframes thinking-pulse {
            0%, 100% { opacity: 0.3; }
            50% { opacity: 1; }
        }

        /* Welcome Message - Centered and styled */
        .welcome-message {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: flex-start;
            text-align: center;
            padding: 20px 20px 8px 20px;
            min-height: auto;
            margin-bottom: 8px;
        }

        /* Fresh chat (welcome is the only message): center it vertically AND
           horizontally by turning the SCROLL CONTAINER itself into a flex
           centerer. Centering via min-height:100% on the child overflowed the
           container's 22px padding (~18px) and showed a spurious scrollbar on
           the "Good morning" welcome screen. */
        .chat-messages:has(.welcome-message:only-child) {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }
        .welcome-message:only-child {
            display: flex !important;
            flex-direction: column !important;
            align-items: center !important;
            justify-content: center !important;
            width: 100%;
            min-height: 0;     /* was 100% — overflowed padding, caused scrollbar */
            padding-top: 0;
            padding-bottom: 0;
            margin-bottom: 0;
        }

        .welcome-message .message-content {
            max-width: 520px;
            background: transparent;
            /* Override theme-b2-light's blanket .message-content rule that
               spans full width with text-align:left for AI bubbles. The
               welcome state is a centered hero block, not a chat reply. */
            width: auto !important;
            text-align: center !important;
            margin-left: auto !important;
            margin-right: auto !important;
        }

        .welcome-message h2 {
            font-size: 28px;
            font-weight: 500;
            color: var(--primary-text);
            margin: 0 0 16px 0;
            letter-spacing: -0.5px;
        }

        .welcome-message p {
            font-size: 16px;
            color: var(--secondary-text);
            margin: 0;
            line-height: 1.7;
        }

        .welcome-message .greeting-text {
            font-size: 15px;
            color: var(--secondary-text);
            margin: 0 0 8px 0;
            opacity: 0;
            transition: opacity 0.3s ease-in;
        }

        .welcome-message .greeting-text.show {
            opacity: 1;
        }

        .welcome-message .typewriter-hint {
            font-size: 14px;
            color: var(--secondary-text);
            margin-top: 24px;
            opacity: 0;
            transition: opacity 0.5s ease-in 0.3s;
        }

        .welcome-message .typewriter-subtitle.show ~ .typewriter-hint {
            opacity: 0.7;
        }

        /* Typewriter effect */
        .typewriter-text {
            display: inline;
            border-right: 2px solid var(--primary-text);
            animation: blink-caret 0.75s step-end infinite;
        }

        .typewriter-text.typing-complete {
            border-right: none;
            animation: none;
        }

        .typewriter-subtitle {
            opacity: 0;
            transition: opacity 0.5s ease-in;
        }

        .typewriter-subtitle.show {
            opacity: 1;
        }

        @keyframes blink-caret {
            from, to { border-color: transparent; }
            50% { border-color: var(--primary-text); }
        }

        .welcome-message .welcome-icon {
            font-size: 48px;
            margin-bottom: 16px;
        }

        /* Attachment chip rendered inside the user message bubble.
         * Quiet meta-footer: no surface fill, no icon, no hairline rule
         * (the cream bubble's own edge already terminates the message
         * visually — adding a divider doubles the boundary). Mono digits
         * in a soft mid-amber so the line registers as data, not a label. */
        .file-attachment {
            display: block;
            margin-top: 4px;
            padding: 0;
            background: transparent;
            border: 0;
            border-radius: 0;
            font-family: var(--f-mono, 'JetBrains Mono', monospace);
            font-size: 10.5px;
            font-weight: 400;
            letter-spacing: 0;
            text-transform: none;
            color: rgba(181, 91, 0, 0.65);
            font-variant-numeric: tabular-nums;
            opacity: 0.85;
        }

        /* Status Messages — Discord/Slack-style system notes.
           Centered, small, subtle so they read as a system event rather
           than competing with user/AI message bubbles for visual weight.
           Thin hairline dividers on each side mark them as a separator. */
        .status-message {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 12px;
            margin: 14px auto;
            padding: 0;
            background: transparent;
            border: 0;
            border-radius: 0;
            font-family: var(--f-mono, ui-monospace, monospace);
            font-size: 11.5px;
            font-weight: 500;
            letter-spacing: 0.02em;
            line-height: 1.4;
            color: var(--b2-ink-3, #6B7280);
            text-align: center;
        }
        .status-message::before,
        .status-message::after {
            content: "";
            flex: 1 1 60px;
            height: 1px;
            background: var(--b2-line, #E5E7EB);
            opacity: 0.7;
            max-width: 88px;
        }

        .status-message.error {
            color: #B91C1C;
        }
        .status-message.error::before,
        .status-message.error::after {
            background: rgba(185, 28, 28, 0.25);
        }

        .status-message.processing {
            color: #B45309;
        }
        .status-message.processing::before,
        .status-message.processing::after {
            background: rgba(180, 83, 9, 0.25);
        }

        /* Input Area */
        .chat-input-container {
            padding: 16px 24px 24px;
            border-top: 1px solid var(--border-light);
            background: var(--white);
        }

        .input-wrapper {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px 16px;
            background: var(--white);
            border: 1px solid var(--border-light);
            border-radius: 16px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
            transition: all 0.2s ease;
            position: relative;  /* For dropdown positioning */
        }

        .input-wrapper:focus-within {
            border-color: var(--primary);
            box-shadow: 0 4px 16px rgba(212, 175, 55, 0.15);
        }

        .attach-btn {
            width: 32px;
            height: 32px;
            padding: 6px;
            background: none;
            border: none;
            cursor: pointer;
            color: var(--secondary-text);
            transition: color 0.2s;
            flex-shrink: 0;
        }

        .attach-btn:hover {
            color: var(--primary-text);
        }

        #chatInput {
            flex: 1;
            border: none;
            outline: none;
            font-size: 14px;
            resize: none;
            min-height: 60px;
            max-height: 200px;
            line-height: 1.5;
            padding: 18px 0 16px;
            font-family: inherit;
            background: transparent;
            display: block;
        }

        .attach-btn,
        .send-btn {
            align-self: center;
        }

        .send-btn {
            width: 28px;
            height: 28px;
            padding: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--white);
            border: 1px solid var(--secondary-text);
            border-radius: 50%;
            cursor: pointer;
            color: var(--secondary-text);
            transition: all 0.2s ease;
            flex-shrink: 0;
        }

        .send-btn svg {
            width: 14px;
            height: 14px;
        }

        .send-btn:hover {
            background: var(--hover-bg);
        }

        .send-btn:disabled {
            background: var(--border-light);
            color: var(--secondary-text);
            cursor: not-allowed;
        }

        .send-btn.stop-mode {
            background: var(--white);
            color: var(--secondary-text);
        }

        .send-btn.stop-mode:hover {
            background: var(--hover-bg);
        }

        /* Command Dropdown */
        .command-dropdown {
            position: absolute;
            bottom: 100%;
            left: 12px;
            right: 12px;
            background: var(--white);
            border: 1px solid var(--border-light);
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            max-height: 300px;
            overflow-y: auto;
            z-index: 1000;
            margin-bottom: 8px;
        }

        .command-item {
            display: flex;
            align-items: center;
            padding: 10px 12px;
            cursor: pointer;
            transition: background 0.15s;
            gap: 10px;
        }

        .command-item:hover,
        .command-item.selected {
            background: var(--hover-bg);
        }

        .command-item:first-child {
            border-radius: 8px 8px 0 0;
        }

        .command-item:last-child {
            border-radius: 0 0 8px 8px;
        }

        .cmd-icon {
            font-size: 18px;
            width: 24px;
            text-align: center;
        }

        .cmd-content {
            display: flex;
            flex-direction: column;
            gap: 2px;
        }

        .cmd-name {
            font-weight: 600;
            font-size: 14px;
            color: var(--primary-text);
        }

        .cmd-desc {
            font-size: 12px;
            color: var(--secondary-text);
        }

        /* PDF Viewer Panel - Responsive width */
        .pdf-panel {
            flex: 1 1 auto;   /* Allow grow and shrink */
            width: auto;      /* Auto width based on flex */
            min-width: 400px; /* Minimum width */
            max-width: none;  /* No max limit */
            background: #f7f7f8;
            display: flex;
            flex-direction: column;
            border-left: 1px solid var(--border-light);
        }

        .pdf-header {
            padding: 18px 24px;
            background: var(--white);
            border-bottom: 1px solid var(--border-light);
            display: flex;
            flex-direction: column;
            justify-content: center;
            height: 60px;
            box-sizing: border-box;
            gap: 0;
        }

        .pdf-title {
            font-size: 18px;  /* 与左侧标题大小一致 */
            font-weight: 600;  /* 与左侧标题粗细一致 */
            color: var(--primary-text);
            display: flex;
            align-items: center;
            gap: 16px;
        }

        /* View toggle buttons */
        .view-toggle {
            display: flex;
            gap: 8px;
            background: transparent;
            padding: 4px;
            border-radius: 8px;
        }

        .view-toggle button {
            padding: 6px 16px !important;
            background: transparent !important;
            border: none !important;
            border-radius: 6px !important;
            cursor: pointer;
            font-size: 14px !important;
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace !important;
            color: var(--secondary-text) !important;
            transition: all 0.2s;
            font-weight: 500;
        }

        .view-toggle button.active {
            background: var(--white) !important;
            color: var(--primary-text) !important;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }

        .view-toggle button:hover:not(.active) {
            color: var(--primary-text) !important;
        }

        .view-toggle button[disabled],
        .view-toggle button.unavailable {
            opacity: 0.4 !important;
            cursor: not-allowed !important;
            color: var(--border-light) !important;
            box-shadow: none !important;
        }

        .pdf-controls {
            display: flex;
            gap: 8px;
            align-items: center;
        }

        .pdf-controls button {
            padding: 6px 12px;
            background: var(--white);
            border: 1px solid var(--border-light);
            border-radius: 4px;
            cursor: pointer;
            font-size: 13px;
            transition: all 0.2s;
            white-space: nowrap;
            min-width: fit-content;
        }
        
        /* 缩放按钮特殊样式 */
        #zoomInBtn, #zoomOutBtn {
            padding: 6px 10px;
            font-weight: bold;
        }
        
        #fitBtn {
            padding: 6px 10px;
        }
        
        #zoomLevel {
            font-weight: bold;
            min-width: 50px;
            text-align: center;
        }

        .pdf-controls button:hover:not(:disabled) {
            background: var(--hover-bg);
        }

        .pdf-controls button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .page-info {
            font-size: 13px;
            color: var(--secondary-text);
            padding: 0 12px;
        }

        /* File Upload Area */
        .file-upload-area {
            margin-bottom: 12px;
            padding: 12px;
            background: var(--message-bg);
            border-radius: 12px;
            border: 1px dashed var(--border-light);
        }
        
        /* Dropdown menu for upload button */
        .upload-dropdown {
            position: relative;
            display: inline-block;
        }
        
        .upload-menu {
            display: none;
            position: absolute;
            bottom: 100%;
            left: 0;
            background: var(--white);
            border: 1px solid var(--border-light);
            border-radius: 6px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
            margin-bottom: 4px;
            min-width: 180px;  /* 增大最小宽度，防止换行 */
            z-index: 1000;
        }
        
        .upload-menu.show {
            display: block;
        }
        
        .upload-menu button {
            display: block;
            width: 100%;
            padding: 12px 16px;  /* 增大内边距 */
            border: none;
            background: none;
            text-align: left;
            cursor: pointer;
            font-size: 15px;  /* 增大字体 */
            color: var(--primary-text);
            white-space: nowrap;  /* 防止文字换行 */
        }
        
        .upload-menu button:hover {
            background: var(--hover-bg);
        }
        
        /* Drag and drop overlay */
        .drag-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(25, 195, 125, 0.1);
            border: 3px dashed var(--btn-primary);
            display: none;
            align-items: center;
            justify-content: center;
            z-index: 9999;
            pointer-events: none;
        }
        
        .drag-overlay.active {
            display: flex;
        }
        
        .drag-overlay-content {
            background: var(--white);
            padding: 20px 40px;
            border-radius: 12px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.1);
            text-align: center;
        }
        
        .drag-overlay-content svg {
            width: 48px;
            height: 48px;
            color: var(--btn-primary);
            margin-bottom: 12px;
        }
        
        .drag-overlay-content p {
            font-size: 16px;
            color: var(--primary-text);
            margin: 0;
        }

        .file-list {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
        }

        .file-item {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 6px 12px;
            background: var(--white);
            border: 1px solid var(--border-light);
            border-radius: 6px;
            font-size: 13px;
        }

        .file-item button {
            background: none;
            border: none;
            color: var(--secondary-text);
            cursor: pointer;
            padding: 0;
            margin-left: 4px;
        }

        .file-item button:hover {
            color: #dc3545;
        }

        /* Canvas - 优化显示质量 */
        #pdfCanvas {
            max-width: 100%;
            height: auto;
            display: block;
            margin: 0 auto;
            image-rendering: crisp-edges;
            image-rendering: -webkit-optimize-contrast;
            -ms-interpolation-mode: nearest-neighbor;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }

        /* All-pages scroll container */
        .pdf-all-pages {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 16px;
            width: 100%;
        }

        .pdf-all-pages canvas {
            max-width: 100%;
            height: auto;
            display: block;
            image-rendering: crisp-edges;
            image-rendering: -webkit-optimize-contrast;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
            border-radius: 2px;
        }

        #pdfViewer {
            flex: 1;
            display: flex;
            background: #f7f7f8;
            overflow: hidden;
        }

        .pdf-content-area {
            flex: 1;
            min-width: 0;
            overflow-y: auto;
            overflow-x: auto;
            padding: 20px;
            display: flex;
            align-items: flex-start;
            justify-content: center;
            position: relative;
            order: 1;
        }

        .empty-state {
            text-align: center;
            color: #999;
            padding: 40px;
        }

        .empty-state svg {
            width: 64px;
            height: 64px;
            margin-bottom: 16px;
            opacity: 0.3;
        }

        /* File Browser */
        #fileBrowser {
            display: none;
            flex: 1;
            background: var(--white);
            overflow: hidden;
        }

        /* Help Table Styles */
        .help-table {
            border-collapse: collapse;
            margin: 10px 0;
            font-size: 13px;
            width: 100%;
        }

        .help-table td {
            border: 1px solid var(--border-light);
            padding: 6px 10px;
        }

        .help-table tr:first-child td {
            background: var(--message-bg);
            font-weight: 600;
        }

        .help-table code {
            background: var(--sidebar-bg);
            padding: 2px 6px;
            border-radius: 4px;
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        }

        /* Version folder in file tree */
        .file-tree-item.version-folder {
            font-weight: 600;
            font-size: 14px;
            border-bottom: 1px solid var(--border-light);
            margin-bottom: 4px;
            padding-bottom: 6px;
            user-select: none;
            cursor: pointer;
        }

        .file-tree-item.version-folder.version-current {
            color: var(--primary);
        }

        /* Report file tree (right side of PDF viewer) */
        #reportFileTree {
            width: fit-content;
            min-width: 220px;
            flex-shrink: 0;
            order: 3;
        }

        #reportFileTreeResizer {
            order: 2;
        }

        /* Report in-page file content viewer */
        .report-file-content {
            flex: 1;
            min-width: 0;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            order: 1;
            background: var(--white);
        }

        .report-file-content-header {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 8px 14px;
            border-bottom: 1px solid var(--border-light);
            background: var(--sidebar-bg);
            font-size: 13px;
            font-weight: 600;
            flex-shrink: 0;
        }

        .report-file-content-header button {
            background: none;
            border: 1px solid var(--border-light);
            border-radius: 4px;
            padding: 3px 10px;
            font-size: 12px;
            cursor: pointer;
            color: var(--primary);
            white-space: nowrap;
        }

        .report-file-content-header button:hover {
            background: var(--hover-bg);
        }

        .report-file-content-body {
            flex: 1;
            overflow: auto;
            padding: 0;
        }

        .report-file-content-body pre {
            margin: 0;
            padding: 14px;
            font-size: 12px;
            line-height: 1.5;
            white-space: pre-wrap;
            word-break: break-all;
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        }

        .report-version-item {
            width: 100%;
            min-height: 34px;
            display: flex;
            align-items: center;
            justify-content: flex-start;
            font-size: 11px;
            font-weight: 600;
            color: var(--secondary-text);
            background: var(--white);
            border: 1px solid var(--border-light);
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.15s;
            padding: 4px 8px;
            white-space: nowrap;
            word-break: normal;
            overflow-wrap: normal;
            line-height: 1.3;
        }

        .report-version-item:hover {
            background: var(--hover-bg);
            border-color: var(--primary);
            color: var(--primary);
        }

        .report-version-item.active {
            background: rgba(212, 175, 55, 0.12);
            border-color: var(--primary);
            color: var(--primary);
        }

        .report-version-item.no-report {
            opacity: 0.45;
        }

        .trame-case-list {
            border-bottom: 1px solid var(--border-light);
            padding: 8px;
            width: max-content;
            min-width: 100%;
        }

        .report-case-sidebar {
            flex: 0 0 auto;
            width: max-content;
            min-width: 220px;
            max-width: 42vw;
            border-left: 1px solid var(--border-light);
            overflow-x: auto;
            overflow-y: auto;
            background: var(--sidebar-bg);
            order: 2;
        }

        .file-browser-container {
            display: flex;
            width: 100%;
            height: 100%;
            min-width: 0;
        }

        .file-browser-container.pdf-mode .file-tree {
            display: block;
        }

        .file-browser-container.pdf-mode .file-content-viewer {
            flex: 1 1 0%;
        }

        /* v1.71.2: File tree on RIGHT side for symmetric layout */
        .file-tree {
            width: fit-content;
            min-width: 200px;
            max-width: 50%;
            flex-shrink: 0;
            border-left: 1px solid var(--border-light);
            overflow-y: auto;
            overflow-x: auto;  /* v1.71.16: Allow horizontal scroll for deep nesting */
            padding: 12px;
            background: var(--sidebar-bg);
            order: 3;  /* Put on right side */
        }

        /* Vertical splitter between .file-tree-panel and .file-content-viewer.
         * Wired by frontend/js/panels/panel-resize.js: mousedown -> drag ->
         * persist width to localStorage. The 4 px hit target stays invisible
         * until hover; matches VS Code's sash. */
        .file-tree-resizer {
            flex: 0 0 4px;
            width: 4px;
            cursor: col-resize;
            background: transparent;
            position: relative;
            z-index: 5;
            user-select: none;
            -webkit-user-select: none;
            transition: background 120ms ease-out;
            /* Sits between content-viewer (order:1) and tree-panel (order:3)
             * within .file-browser-container (flex-direction: row-reverse). */
            order: 2;
        }
        .file-tree-resizer:hover,
        body.resizing .file-tree-resizer { background: var(--acc); }

        .file-tree-item {
            padding: 6px 8px;
            cursor: pointer;
            border-radius: 6px;
            font-size: 14px;
            display: flex;
            align-items: center;
            gap: 6px;
            user-select: none;
            white-space: nowrap;
            min-width: 0;       /* allow shrink below intrinsic size for ellipsis */
            width: 100%;
        }

        /* VS Code-style ellipsis: hidden + ellipsis + nowrap, with min-width: 0
         * on a flex child so flex can actually compress it below content width.
         * The full filename stays accessible via title="" set in file-browser.js. */
        .file-tree-item .file-name {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            min-width: 0;
            flex: 1 1 auto;
        }

        /* Raw case_id sub-label shown next to a RENAMED case folder — keeps
         * log/path cross-referencing possible without hovering. */
        .file-tree-item .file-name-idsub {
            flex: 0 1 auto;
            min-width: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-left: 6px;
            font-size: 10.5px;
            font-family: var(--font-mono, ui-monospace, monospace);
            color: var(--text-muted, #8a8f98);
            opacity: 0.75;
        }

        /* Default document template — gold chip after the folder name. */
        .file-tree-item .file-name-defbadge {
            flex: 0 0 auto;
            margin-left: 6px;
            font-size: 9px;
            font-weight: 600;
            letter-spacing: 0.04em;
            color: #8A6D1A;
            background: rgba(212, 175, 55, 0.16);
            border: 1px solid rgba(212, 175, 55, 0.45);
            border-radius: 999px;
            padding: 0 6px;
            line-height: 14px;
        }

        .file-tree-item:hover {
            background: var(--hover-bg);
        }

        .file-tree-item.selected {
            background: var(--message-bg);
            color: var(--btn-primary);
            font-weight: 500;
        }

        /* Row marked as "cut" — faded until pasted (or the mark is cleared). */
        .file-tree-cut,
        .file-tree-cut .file-name {
            opacity: 0.45;
        }

        .file-tree-item.directory {
            font-weight: 500;
        }

        .file-tree-children {
            margin-left: 16px;
        }

        .file-tree-toggle {
            width: 16px;
            height: 16px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            font-size: 10px;
            transition: transform 0.2s;
        }

        .file-tree-toggle.expanded {
            transform: rotate(90deg);
        }

        /* v1.71.2: File content on LEFT side - takes remaining space */
        .file-content-viewer {
            flex: 1 1 0%;
            min-width: 0;
            display: flex;
            flex-direction: column;
            background: var(--white);
            order: 1;  /* Put on left side */
        }

        .file-content-header {
            padding: 12px 16px;
            border-bottom: 1px solid var(--border-light);
            background: var(--message-bg);
            font-size: 13px;
            color: var(--secondary-text);
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        .file-content-body {
            flex: 1;
            overflow: auto;
            padding: 16px;
        }

        .file-content-body.pdf-render-mode {
            padding: 12px;
            background: #eef2f7;
        }

        .file-header-main {
            flex: 1 1 auto;
            min-width: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-right: 12px;
        }

        .file-header-actions {
            display: inline-flex;
            align-items: center;
            justify-content: flex-end;
            gap: 8px;
            flex: 0 0 auto;
            flex-wrap: wrap;
        }

        .file-header-refresh-btn {
            width: 28px;
            height: 28px;
            padding: 0;
            border: 1px solid var(--border-light);
            border-radius: 6px;
            background: var(--white);
            color: var(--secondary-text);
            font-size: 15px;
            line-height: 1;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            flex: 0 0 auto;
        }

        .file-header-refresh-btn:hover:not(:disabled) {
            background: var(--hover-bg);
        }

        .file-header-refresh-btn:disabled {
            opacity: 0.45;
            cursor: not-allowed;
        }

        .file-header-refresh-btn.is-loading {
            opacity: 0.7;
        }

        .file-pdf-toolbar {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            flex-wrap: wrap;
        }

        .file-pdf-toolbar-sep {
            color: var(--border-light);
            font-size: 12px;
            padding: 0 2px;
        }

        .file-pdf-toolbar button {
            border: 1px solid var(--border-light);
            background: var(--white);
            color: var(--secondary-text);
            border-radius: 6px;
            padding: 4px 10px;
            font-size: 12px;
            cursor: pointer;
            min-width: 30px;
        }

        .file-pdf-open-btn {
            min-width: 120px !important;
        }

        .file-pdf-toolbar button:hover {
            background: var(--hover-bg);
        }

        .file-pdf-zoom-label {
            min-width: 48px;
            text-align: center;
            font-size: 12px;
            color: var(--secondary-text);
        }

        .file-pdf-loading {
            color: var(--secondary-text);
            font-size: 13px;
            padding: 12px;
        }

        .file-pdf-pages {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 14px;
            width: 100%;
        }

        .file-pdf-page {
            width: 100%;
            display: flex;
            justify-content: center;
        }

        .file-pdf-page canvas {
            background: #fff;
            box-shadow: 0 1px 8px rgba(15, 23, 42, 0.12);
            border-radius: 4px;
            max-width: none;
        }

        .pdf-overlay {
            position: fixed;
            inset: 0;
            z-index: 10050;
            display: flex;
            flex-direction: column;
            background: #eef2f7;
        }

        .pdf-overlay-header {
            height: 52px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 14px;
            border-bottom: 1px solid var(--border-light);
            background: var(--white);
            flex-shrink: 0;
        }

        .pdf-overlay-title {
            font-size: 14px;
            color: var(--primary-text);
            font-weight: 600;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-right: 12px;
        }

        .pdf-overlay-actions {
            display: inline-flex;
            align-items: center;
            gap: 8px;
            flex-shrink: 0;
        }

        .pdf-overlay-btn {
            border: 1px solid var(--border-light);
            background: var(--white);
            color: var(--secondary-text);
            border-radius: 6px;
            padding: 5px 10px;
            font-size: 12px;
            cursor: pointer;
        }

        .pdf-overlay-btn:hover {
            background: var(--hover-bg);
        }

        .pdf-overlay-body {
            flex: 1;
            min-height: 0;
            padding: 10px;
        }

        .pdf-overlay-frame {
            width: 100%;
            height: 100%;
            border: 0;
            background: #fff;
            border-radius: 8px;
        }

        .file-content-code {
            background: #f6f8fa;
            border: 1px solid var(--border-light);
            border-radius: 6px;
            padding: 16px;
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            font-size: 13px;
            line-height: 1.6;
            white-space: pre-wrap;
            word-wrap: break-word;
            color: #24292f;
        }

        /* Rendered markdown documents (.md) in the file preview. Wrapped in
           .message-content so the themes' code/table/quote styling applies;
           this block restores the document heading hierarchy (the chat bubble
           flattens h3/h4 to one size with !important — hence !important here,
           with the extra .md-doc class winning specificity in both themes).
           Both themes force .file-content-body to 12px mono !important (code
           panes), so the document face is restored explicitly. */
        .file-content-body .md-doc {
            padding: 8px 12px 32px;
            white-space: normal !important;
            font-family: var(--f-sans, -apple-system, 'Segoe UI', sans-serif) !important;
            font-size: 13.5px !important;
            line-height: 1.6 !important;
        }
        /* Paragraphs come from the doc-mode line merger (formatAssistantMessage
           docHeadings) — vertical rhythm is carried by the emitted <br>s, same
           as the chat bubble, so the <p> itself stays margin-free. */
        .message-content.md-doc p {
            margin: 0;
        }
        .message-content.md-doc code {
            font-family: var(--f-mono, ui-monospace, monospace) !important;
            font-size: 12px !important;
            background: rgba(128, 128, 128, 0.14) !important;
            padding: 1px 5px !important;
            border-radius: 4px !important;
        }
        .message-content.md-doc pre code {
            background: transparent !important;
            padding: 0 !important;
        }
        .message-content.md-doc h2 {
            font-size: 18px !important;
            font-weight: 650 !important;
            margin: 6px 0 12px !important;
            letter-spacing: -0.01em !important;
        }
        .message-content.md-doc h3 {
            font-size: 15.5px !important;
            margin: 20px 0 8px !important;
        }
        .message-content.md-doc h4 {
            font-size: 13.5px !important;
            margin: 16px 0 6px !important;
        }
        .message-content.md-doc h5 {
            font-size: 12.5px !important;
            font-weight: 600 !important;
            margin: 14px 0 6px !important;
        }
        .message-content.md-doc .help-table {
            display: block;
            overflow-x: auto;
        }

        .file-icon {
            width: 16px;
            height: 16px;
        }

        /* VTK Viewer */
        #vtkViewer {
            flex: 1;
            background: var(--white);
            overflow: hidden;
        }

        .vtk-viewer-container {
            display: grid;
            grid-template-columns: 264px 1fr;
            grid-template-rows: auto 1fr;
            width: 100%;
            height: 100%;
            gap: 0;
        }

        /* VTK左侧文件列表 */
        .vtk-file-list {
            grid-column: 1;
            grid-row: 1 / 3;
            border-right: 1px solid var(--border-light);
            background: var(--sidebar-bg);
            overflow-y: auto;
            display: flex;
            flex-direction: column;
        }

        .vtk-file-list-header {
            padding: 12px 16px;
            border-bottom: 1px solid var(--border-light);
            background: var(--white);
            display: flex;
            justify-content: space-between;
            align-items: center;
            height: 47px;
            box-sizing: border-box;
        }

        .vtk-file-list-header h3 {
            font-size: 14px;
            font-weight: 600;
            margin: 0;
            color: var(--primary-text);
        }

        .vtk-file-list-header span {
            font-size: 12px;
            color: var(--secondary-text);
        }

        .vtk-file-tree {
            flex: 1;
            padding: 8px;
        }

        .vtk-file-item {
            padding: 8px 12px;
            margin: 2px 0;
            cursor: pointer;
            border-radius: 6px;
            font-size: 13px;
            display: flex;
            align-items: center;
            gap: 8px;
            transition: background 0.2s;
        }

        .vtk-file-item:hover {
            background: var(--hover-bg);
        }

        .vtk-file-item.selected {
            background: var(--message-bg);
            color: var(--btn-primary);
            font-weight: 500;
        }

        /* VTK渲染窗口 */
        .vtk-render-window {
            grid-column: 2;
            grid-row: 2;
            position: relative;
            background: #f7f7f8;
        }

        .vtk-container {
            width: 100%;
            height: 100%;
        }

        .vtk-loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
            color: white;
            display: none;
        }

        .vtk-loading.active {
            display: block;
        }

        .spinner {
            display: flex;
            gap: 8px;
            justify-content: center;
            align-items: center;
            height: 40px;
            margin: 0 auto 16px;
        }

        .spinner::before {
            content: 'Generating...';
            color: #666;
            font-size: 14px;
            animation: none;
        }

        .spinner::after {
            display: none;
        }

        @keyframes bounce {
            0%, 80%, 100% {
                transform: scale(0);
                opacity: 0.5;
            }
            40% {
                transform: scale(1);
                opacity: 1;
            }
        }

        .panel-loading {
            display: none !important;  /* 使用骨架屏代替，不再显示旧的spinner */
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 10px;
            width: 100%;
            padding: 32px 16px;
            color: var(--secondary-text);
            text-align: center;
        }

        .panel-loading.active {
            display: none !important;  /* 强制隐藏，使用骨架屏 */
        }

        .panel-loading .spinner {
            height: 22px;
            margin: 0;
        }

        .panel-loading .spinner::before,
        .panel-loading .spinner::after {
            width: 8px;
            height: 8px;
            background: var(--btn-primary);
        }

        /* File-tree loading overlay.
         * setPanelLoading('files', true) toggles `.loading` on
         * `.file-tree-panel`. Without this rule the class was inert and the
         * panel briefly went visually blank between "old tree cleared" and
         * "new tree painted". The overlay is scoped to the tree itself so
         * the Explorer title bar (and its refresh button) stay visible and
         * the "Loading…" label is centered on the tree area, not on the
         * whole panel including the title. */
        .file-tree-panel .file-tree {
            position: relative;
        }
        .file-tree-panel.loading .file-tree::after {
            content: 'Loading…';
            position: absolute;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 13px;
            color: var(--secondary-text);
            background: var(--white);
            z-index: 5;
            pointer-events: none;
        }

        /* Skeleton Loading Styles */
        .skeleton {
            background: linear-gradient(
                90deg,
                var(--message-bg) 0%,
                var(--border-lighter) 50%,
                var(--message-bg) 100%
            );
            background-size: 200% 100%;
            animation: skeleton-loading 1.5s ease-in-out infinite;
            border-radius: 6px;
        }

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

        .skeleton-container {
            padding: 20px;
            display: none;
        }

        .skeleton-container.active {
            display: block;
        }

        /* PDF Report Skeleton */
        .skeleton-pdf {
            width: 100%;
            max-width: 800px;
            margin: 0 auto;
            display: flex;
            flex-direction: column;
            gap: 16px;
        }

        .skeleton-pdf-header {
            height: 40px;
            width: 60%;
            margin-bottom: 20px;
        }

        .skeleton-pdf-page {
            height: 600px;
            width: 100%;
        }

        .skeleton-pdf-footer {
            height: 20px;
            width: 40%;
            margin: 20px auto 0;
        }

        /* File Browser Skeleton */
        .skeleton-files {
            display: flex;
            gap: 16px;
            height: 100%;
        }

        .skeleton-files-tree {
            width: 300px;
            display: flex;
            flex-direction: column;
            gap: 8px;
            padding: 12px;
        }

        .skeleton-file-item {
            height: 32px;
            width: 100%;
        }

        .skeleton-file-item:nth-child(2),
        .skeleton-file-item:nth-child(4) {
            width: 90%;
            margin-left: 20px;
        }

        .skeleton-file-item:nth-child(3),
        .skeleton-file-item:nth-child(6) {
            width: 85%;
            margin-left: 20px;
        }

        .skeleton-files-content {
            flex: 1;
            padding: 16px;
            display: flex;
            flex-direction: column;
            gap: 12px;
        }

        .skeleton-file-content-header {
            height: 40px;
            width: 50%;
        }

        .skeleton-file-content-line {
            height: 16px;
            width: 100%;
        }

        .skeleton-file-content-line:nth-child(2) {
            width: 95%;
        }

        .skeleton-file-content-line:nth-child(3) {
            width: 88%;
        }

        .skeleton-file-content-line:nth-child(4) {
            width: 92%;
        }

        .skeleton-file-content-line:nth-child(5) {
            width: 80%;
        }

        /* VTK Viewer Skeleton */
        .skeleton-vtk {
            display: flex;
            height: 100%;
            gap: 0;
        }

        .skeleton-vtk-sidebar {
            width: 264px;
            border-right: 1px solid var(--border-light);
            padding: 16px;
            display: flex;
            flex-direction: column;
            gap: 12px;
        }

        .skeleton-vtk-file {
            height: 36px;
            width: 100%;
        }

        .skeleton-vtk-viewer {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            background: #f7f7f8;
        }

        .skeleton-vtk-3d {
            width: 300px;
            height: 300px;
            border-radius: 12px;
        }

        #pdfViewer.loading .pdf-content-area {
            align-items: center;
        }

        #pdfViewer.loading .pdf-content-area .empty-state,
        #pdfViewer.loading .pdf-content-area canvas {
            display: none !important;
        }

        /* v1.71.2: Removed display: flex !important to let JavaScript control visibility */
        /* This prevents loading states from overriding switchView() display: none */
        #fileBrowser.loading,
        #vtkViewer.loading {
            flex-direction: column;
        }

        #fileBrowser.loading .file-browser-container,
        #vtkViewer.loading .vtk-viewer-container {
            display: none;
        }

        /* VTK顶部控制面板 */
        .vtk-controls {
            grid-column: 2;
            grid-row: 1;
            border-bottom: 1px solid var(--border-light);
            background: var(--white);
            padding: 12px 16px;
            display: flex;
            align-items: center;
            gap: 12px;
            overflow-x: auto;
            height: 47px;
            box-sizing: border-box;
        }

        .vtk-controls button {
            padding: 6px 16px;
            background: var(--white);
            border: 1px solid var(--border-light);
            border-radius: 6px;
            cursor: pointer;
            font-size: 13px;
            transition: all 0.2s;
            white-space: nowrap;
        }

        .vtk-controls button:hover {
            background: var(--hover-bg);
            border-color: var(--btn-primary);
        }

        .vtk-controls select {
            padding: 6px 12px;
            border: 1px solid var(--border-light);
            border-radius: 6px;
            font-size: 13px;
            background: var(--white);
            cursor: pointer;
            min-width: 150px;
        }

        .vtk-controls .control-group {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .vtk-controls .control-label {
            font-size: 13px;
            color: var(--secondary-text);
            font-weight: 500;
        }

        /* VTK Mode Button Active State */
        .vtk-controls .control-group button.active {
            background: var(--btn-primary);
            color: white;
            border-color: var(--btn-primary);
        }

        .vtk-controls .control-group button.active:hover {
            background: var(--btn-hover);
            border-color: var(--btn-hover);
        }

        /* VTK Toast Notification */
        .vtk-toast {
            position: fixed;
            bottom: 80px;
            left: 50%;
            transform: translateX(-50%) translateY(100px);
            background: rgba(0, 0, 0, 0.85);
            color: white;
            padding: 12px 24px;
            border-radius: 8px;
            font-size: 14px;
            font-weight: 500;
            z-index: 10001;
            pointer-events: none;
            opacity: 0;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
            white-space: nowrap;
        }

        .vtk-toast.show {
            opacity: 1;
            transform: translateX(-50%) translateY(0);
        }

        /* VTK Help Overlay */
        .vtk-help-overlay {
            position: fixed;
            top: 80px;
            right: 20px;
            background: white;
            border: 1px solid var(--border-light);
            border-radius: 12px;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
            padding: 20px 24px;
            max-width: 400px;
            z-index: 10002;
            opacity: 0;
            visibility: hidden;
            transform: scale(0.95) translateY(-10px);
            transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .vtk-help-overlay.show {
            opacity: 1;
            visibility: visible;
            transform: scale(1) translateY(0);
        }

        .vtk-help-content {
            position: relative;
        }

        .vtk-help-close {
            position: absolute;
            top: -8px;
            right: -8px;
            background: var(--border-light);
            border: none;
            border-radius: 50%;
            width: 28px;
            height: 28px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            color: var(--secondary-text);
            font-size: 16px;
            transition: all 0.2s;
        }

        .vtk-help-close:hover {
            background: var(--btn-primary);
            color: white;
        }

        .vtk-help-content h4 {
            margin: 0 0 16px 0;
            font-size: 16px;
            color: var(--primary-text);
            font-weight: 600;
        }

        .vtk-help-content ul {
            list-style: none;
            padding: 0;
            margin: 0 0 16px 0;
        }

        .vtk-help-content ul li {
            padding: 8px 0;
            font-size: 14px;
            line-height: 1.6;
            color: var(--primary-text);
            border-bottom: 1px solid var(--border-lighter);
        }

        .vtk-help-content ul li:last-child {
            border-bottom: none;
        }

        .vtk-help-content ul li strong {
            color: var(--btn-primary);
            font-weight: 600;
            display: inline-block;
            min-width: 60px;
        }

        .vtk-help-tip {
            background: var(--message-bg);
            padding: 10px 12px;
            border-radius: 6px;
            font-size: 13px;
            line-height: 1.5;
            color: var(--secondary-text);
            margin: 8px 0;
            border-left: 3px solid var(--btn-primary);
        }

        .vtk-help-tip:last-child {
            margin-bottom: 0;
        }

        /* VTK Quick Hint Button */
        .vtk-quick-hint {
            position: absolute;
            bottom: 20px;
            right: 20px;
            z-index: 1000;
        }

        .vtk-quick-hint button {
            width: 48px;
            height: 48px;
            border-radius: 50%;
            background: var(--btn-primary);
            color: white;
            border: none;
            cursor: pointer;
            font-size: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 4px 12px rgba(25, 195, 125, 0.3);
            transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .vtk-quick-hint button:hover {
            background: var(--btn-hover);
            transform: scale(1.1);
            box-shadow: 0 6px 16px rgba(25, 195, 125, 0.4);
        }

        .vtk-quick-hint button:active {
            transform: scale(0.95);
        }

        /* VTK浮动控制面板 */
        .vtk-floating-panel {
            position: absolute;
            top: 60px;
            right: 20px;
            background: white;
            border: 1px solid var(--border-light);
            border-radius: 12px;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
            padding: 16px;
            min-width: 320px;
            z-index: 1001;
            opacity: 0;
            visibility: hidden;
            transform: scale(0.95) translateY(-10px);
            transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .vtk-floating-panel.show {
            opacity: 1;
            visibility: visible;
            transform: scale(1) translateY(0);
        }

        .panel-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 16px;
            padding-bottom: 12px;
            border-bottom: 1px solid var(--border-lighter);
        }

        .panel-title {
            font-size: 15px;
            font-weight: 600;
            color: var(--primary-text);
        }

        .panel-close {
            background: var(--border-light);
            border: none;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            color: var(--secondary-text);
            font-size: 14px;
            transition: all 0.2s;
        }

        .panel-close:hover {
            background: #dc3545;
            color: white;
        }

        .panel-body {
            display: flex;
            flex-direction: column;
            gap: 16px;
        }

        .panel-row {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }

        .panel-row label {
            font-size: 13px;
            font-weight: 500;
            color: var(--secondary-text);
        }

        .panel-inputs {
            display: flex;
            gap: 8px;
        }

        .panel-inputs input {
            flex: 1;
            padding: 8px 10px;
            border: 1px solid var(--border-light);
            border-radius: 6px;
            font-size: 13px;
            transition: border-color 0.2s;
        }

        .panel-inputs input:focus {
            outline: none;
            border-color: var(--btn-primary);
        }

        .panel-inputs input::placeholder {
            color: var(--secondary-text);
            opacity: 0.6;
        }

        .panel-apply {
            padding: 10px 16px;
            background: var(--btn-primary);
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: background 0.2s;
        }

        .panel-apply:hover {
            background: var(--btn-hover);
        }

        .panel-apply:active {
            transform: scale(0.98);
        }

        /* Slice/Clip按钮激活状态 */
        #sliceBtn.active,
        #clipBtn.active {
            background: var(--primary-bg);
            border-color: var(--primary);
            color: var(--primary);
        }

        /* Scrollbar styling */
        ::-webkit-scrollbar {
            width: 4px;
            height: 4px;
        }

        ::-webkit-scrollbar-track {
            background: transparent;
        }

        ::-webkit-scrollbar-thumb {
            background: rgba(0, 0, 0, 0.1);
            border-radius: 4px;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: rgba(0, 0, 0, 0.2);
        }

        /* SVG Icons */
        svg {
            width: 20px;
            height: 20px;
        }

        /* Responsive */
        @media (max-width: 768px) {
            .container {
                flex-direction: column;
            }
            
            .panel-resizer {
                display: none;
            }

            .pdf-panel {
                display: none;
            }
            
            .chat-panel {
                min-width: unset;
            }
        }

        /* ================================================================
         * Login Modal — quiet, book-like surface.
         * ----------------------------------------------------------------
         * A warm cream page, a pure-white card with one hairline + one
         * soft shadow, and a terracotta/rust (#C96442) primary CTA.
         * No breathing pulse, no blueprint grid, no radial gradient.
         * Silence is the design.
         * ================================================================ */
        .login-modal,
        .provisioning-overlay {
            /* Login palette mirrors the main UI's user-message bubble:
             * cream surface (--b2-user-bg #FBF5E9) + amber-gold rule
             * (--b2-user-rule #E0B65E). Form inputs stay on the white
             * card surface, but the primary CTA picks up the amber rule
             * so the login button reads as the same warm-cream/gold
             * vocabulary the user sees in their own chat bubbles. */
            --login-canvas:   var(--b2-bg, #FAFAF9);
            --login-surface:  var(--b2-surface, #FFFFFF);
            --login-line:     var(--b2-line, #E5E7EB);
            --login-ink:      var(--b2-ink, #111216);
            --login-ink-2:    var(--b2-ink-2, #4B5563);
            --login-ink-3:    var(--b2-ink-3, #6B7280);
            --login-ink-4:    var(--b2-ink-4, #9CA3AF);

            /* Amber-gold accent (lifted from --b2-user-rule). Idle on
             * the saturated rule; hover/active step into deeper amber.
             * Dark ink text keeps contrast ≥ 6:1 on amber. */
            --login-acc:       var(--b2-user-rule, #E0B65E);   /* idle  */
            --login-acc-ink:   #C99E48;                         /* hover */
            --login-acc-hover: #B48835;                         /* active*/
            --login-acc-soft:  rgba(224, 182, 94, 0.12);
            --login-acc-line:  rgba(224, 182, 94, 0.45);
            --login-acc-focus: rgba(224, 182, 94, 0.32);
        }

        .login-modal {
            position: fixed;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 10000;
            background: var(--login-canvas, #FAF9F5);
        }

        .login-container {
            /* Match the main UI's flat hairline aesthetic: no rounded card
             * shape, no drop-shadow, no peach. Single thin hairline +
             * surface-on-paper contrast carries the whole card. */
            background: var(--login-surface, #FFFFFF);
            border: 1px solid var(--login-line, #E5E7EB);
            border-radius: 8px;
            padding: 36px 36px 32px;
            width: 100%;
            max-width: 380px;
            color: var(--login-ink, #111216);
            font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
            box-shadow: none;
            animation: login-rise 0.4s cubic-bezier(0.2, 0.7, 0.25, 1) both;
        }

        @keyframes login-rise {
            from { opacity: 0; transform: translateY(6px); }
            to   { opacity: 1; transform: translateY(0);   }
        }

        @media (prefers-reduced-motion: reduce) {
            .login-container { animation: none; }
        }

        .login-header {
            text-align: center;
            margin-bottom: 28px;
            /* Subtle hairline under the title to match the main UI's
             * panel-header divider pattern (file-tree-title, conv-section). */
            padding-bottom: 18px;
            border-bottom: 1px solid var(--login-line, #E5E7EB);
        }

        .login-header h2 {
            color: var(--login-ink, #111216);
            font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
            font-size: 18px;
            font-weight: 500;
            letter-spacing: -0.01em;
            line-height: 1.25;
            margin: 0;
        }
        /* Optional subtitle slot — subtle context line below the title.
         * Pulled from .login-header .login-subtitle if present in markup. */
        .login-header .login-subtitle {
            margin-top: 6px;
            font-family: var(--f-mono, 'JetBrains Mono', monospace);
            font-size: 10px;
            font-weight: 500;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            color: var(--login-ink-3, #6B7280);
        }

        .login-form {
            margin-bottom: 20px;
        }

        .form-group {
            margin-bottom: 16px;
        }

        /* Labels: mono uppercase tracked — same idiom as the main UI's
         * panel headers (.file-tree-title-label, .time-group-title) so the
         * login form reads as a section of the same app, not a separate
         * marketing page. */
        .form-group label {
            display: block;
            color: var(--login-ink-3, #6B7280);
            font-family: var(--f-mono, 'JetBrains Mono', monospace);
            font-size: 10px;
            font-weight: 500;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            margin-bottom: 6px;
        }

        .form-group input {
            width: 100%;
            padding: 10px 12px;
            background: var(--login-surface, #FFFFFF);
            border: 1px solid var(--login-line, #E5E7EB);
            border-radius: 6px;
            color: var(--login-ink, #111216);
            font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
            font-size: 14px;
            line-height: 1.4;
            transition: border-color 0.15s ease, box-shadow 0.15s ease;
            box-sizing: border-box;
        }

        .form-group input::placeholder {
            color: var(--login-ink-4, #A8A69D);
        }

        /* Scoped to .login-modal because theme-b2-light.css has a global
         * `input:focus-visible` rule with !important that forces the
         * cool-blue accent on every input app-wide. We need to win that
         * cascade for the login form so the focus ring matches the
         * gold Sign In button instead of clashing blue. */
        .login-modal .form-group input:focus,
        .login-modal .form-group input:focus-visible,
        .provisioning-overlay .form-group input:focus,
        .provisioning-overlay .form-group input:focus-visible {
            outline: none !important;
            border-color: var(--b2-user-rule, #E0B65E) !important;
            box-shadow: 0 0 0 3px rgba(224, 182, 94, 0.28) !important;
        }

        /* Primary CTA — mirrors the user message bubble:
         *   cream fill (--b2-user-bg) + thin gold rule (--b2-user-rule)
         *   + dark-amber text (--b2-user-code-fg).
         * Saturated #E0B65E is used ONLY as a 1px hairline (same way the
         * main UI uses it on the user bubble). Filling the entire button
         * with that gold reads as muddy "土黄"; we keep the surface in
         * the pale cream → light-honey range so the button stays
         * refined and elegant ("淡雅/秀气"). Same 6px radius as inputs. */
        .login-button {
            width: 100%;
            padding: 10px 14px;
            background: var(--b2-user-bg, #FBF5E9);
            color: var(--b2-user-code-fg, #B55B00);
            border: 1px solid var(--b2-user-rule, #E0B65E);
            border-radius: 6px;
            font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
            font-size: 13px;
            font-weight: 600;
            line-height: 1.25;
            letter-spacing: 0.01em;
            text-transform: none;
            cursor: pointer;
            transition:
                background-color 0.15s ease,
                border-color 0.15s ease,
                color 0.15s ease,
                box-shadow 0.15s ease,
                transform 0.12s ease;
            margin-top: 4px;
        }

        .login-button:hover {
            /* Soft honey — barely darker than cream, never crosses
             * into saturated-gold fill territory. Border + text stay
             * the same so the eye registers just a small breathing
             * tonal lift. */
            background: #F5E5BC;
            border-color: var(--b2-user-rule, #E0B65E);
            color: var(--b2-user-code-fg, #B55B00);
        }

        .login-button:active {
            /* Press — same tone as hover, paired with the existing
             * translateY(0.5px) (line ~2538) for tactile feedback.
             * Earlier iterations stepped to saturated #E0B65E or even
             * deeper #C99E48 here, which both read as 土黄. */
            background: #F0DBA8;
            border-color: var(--b2-user-rule, #E0B65E);
            color: var(--b2-user-code-fg, #B55B00);
        }

        .login-button:focus-visible {
            outline: none;
            box-shadow: 0 0 0 3px var(--login-acc-focus, rgba(201, 100, 66, 0.22));
        }

        .login-error {
            color: var(--b2-err, #DC2626);
            font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
            font-size: 13px;
            letter-spacing: 0;
            text-align: center;
            min-height: 18px;
            margin: 8px 0 12px;
        }

        /* Micro-interaction: when an error appears (JS sets textContent),
           shake it once to confirm "we rejected your input".              */
        .login-error:not(:empty) {
            animation: login-shake 0.34s cubic-bezier(0.36, 0.07, 0.19, 0.97);
        }

        @keyframes login-shake {
            10%, 90% { transform: translateX(-1px); }
            20%, 80% { transform: translateX(2px);  }
            30%, 50%, 70% { transform: translateX(-4px); }
            40%, 60% { transform: translateX(4px);  }
        }

        @media (prefers-reduced-motion: reduce) {
            .login-error:not(:empty) { animation: none; }
        }

        /* Subtle press feedback on the primary action — 1 px settle that
           mirrors the composer send button's `transform: translateY` idiom. */
        .login-button:active:not(:disabled) {
            transform: translateY(0.5px);
        }
        
        /* Header button styles */
        .header-btn {
            background: none !important;
            border: none !important;
            color: #888 !important;
            font-size: 18px !important;
            font-weight: normal !important;
            cursor: pointer !important;
            padding: 0 !important;
            transition: color 0.3s !important;
        }
        
        .header-btn:hover {
            color: #ccc !important;
        }

        /* History Sidebar Styles */
        .history-sidebar {
            width: 176px;
            background: var(--white);
            color: #202123;
            display: flex;
            flex-direction: column;
            border-right: 1px solid #e5e5e7;
        }

        /* Drag-collapse: panel-resize.js sets the width inline while dragging the
           #sidebarResizer handle, and adds .is-collapsed when dragged to the
           edge to hide the sidebar fully (no button — pure drag). */
        .history-sidebar.is-collapsed {
            width: 0 !important;
            border-right: none !important;
            overflow: hidden !important;
        }

        /* Collapsed → make the resizer a slim but VISIBLE reopen tab with a ›
           chevron, so there's an obvious thing to click/drag to expand again
           (the bare divider is theme hover-only = invisible at rest). Click,
           drag, or double-click it to reopen. !important overrides the theme's
           .panel-resizer (width:4px / ::before content:"" / opacity:0). */
        .history-sidebar.is-collapsed + .sidebar-resizer {
            width: 16px !important;
            flex: 0 0 16px !important;
            background: var(--b2-sunken, #f3f4f6) !important;
            border-right: 1px solid var(--b2-line, #e5e7eb) !important;
            cursor: pointer !important;
        }
        .history-sidebar.is-collapsed + .sidebar-resizer::before {
            content: '\203A' !important;   /* › */
            width: auto !important;
            height: auto !important;
            background: transparent !important;
            color: var(--b2-ink-3, #6b7280) !important;
            font: 700 15px var(--f-sans, system-ui, sans-serif) !important;
            opacity: 1 !important;
        }
        .history-sidebar.is-collapsed + .sidebar-resizer:hover {
            background: var(--b2-line, #e5e7eb) !important;
        }

        .sidebar-header {
            padding: 12px;
            border-bottom: 1px solid #e5e5e7;
            height: 60px;
            box-sizing: border-box;
            display: flex;
            align-items: center;
        }

        .new-chat-btn {
            width: 100%;
            padding: 12px;
            /* background: rgba(212, 175, 55, 0.15); */
            /* border: 1px solid rgba(212, 175, 55, 0.3); */
            background: transparent;
            border: 1px solid var(--border-light);
            border-radius: 8px;
            color: var(--secondary-text);
            cursor: pointer;
            font-size: 14px;
            font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            font-weight: 500;
            transition: all 0.2s ease;
        }

        .new-chat-btn:hover {
            /* background: rgba(212, 175, 55, 0.25); */
            background: var(--hover-bg);
            border-color: var(--primary);
        }

        .conversation-list {
            flex: 1;
            overflow-y: auto;
            padding: 12px;
        }

        .time-group {
            margin-bottom: 20px;
        }

        .time-group-title {
            font-size: 12px;
            color: #6e6e80;
            margin-bottom: 8px;
            padding: 0 8px;
        }

        .conversation-item {
            padding: 10px 12px;
            border-radius: 6px;
            cursor: pointer;
            margin-bottom: 4px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            transition: all 0.15s ease;
            user-select: none;
            -webkit-tap-highlight-color: transparent;
        }

        .conversation-item:hover {
            background: #e5e5e7;
            transform: translateX(2px);
        }

        .conversation-item:active {
            background: #d9d9e3;
            transform: scale(0.98);
        }

        .conversation-item.active {
            background: var(--primary-bg);
            border-left: 3px solid var(--primary);
            font-weight: 500;
        }

        .conversation-item:focus {
            outline: 2px solid var(--primary);
            outline-offset: 1px;
        }

        .conversation-title {
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-right: 8px;
            pointer-events: none;
            font-size: 13px;
        }

        .conversation-menu-btn {
            opacity: 0;
            padding: 4px 8px;
            border: none;
            background: transparent;
            cursor: pointer;
            font-size: 16px;
            color: #565869;
            transition: opacity 0.2s;
        }

        .conversation-item:hover .conversation-menu-btn {
            opacity: 1;
        }

        .conversation-hover-tooltip {
            position: fixed;
            z-index: 20000;
            max-width: min(420px, 70vw);
            padding: 8px 10px;
            border-radius: 6px;
            background: rgba(24, 24, 28, 0.96);
            color: #f3f4f6;
            font-size: 12px;
            line-height: 1.45;
            pointer-events: none;
            opacity: 0;
            transform: translateY(2px);
            transition: opacity 0.12s ease, transform 0.12s ease;
            white-space: normal;
            word-break: break-word;
            box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
            border: 1px solid rgba(255, 255, 255, 0.12);
        }

        .conversation-hover-tooltip.visible {
            opacity: 1;
            transform: translateY(0);
        }

        .conversation-menu-btn:hover {
            background: #d9d9e3;
            border-radius: 4px;
        }

        .conversation-menu {
            position: absolute;
            right: 12px;
            top: 100%;
            margin-top: 4px;
            background: white;
            border: 1px solid #d9d9e3;
            border-radius: 6px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            z-index: 10005;
            display: none;
            min-width: 150px;
        }

        .conversation-menu.active {
            display: block;
        }

        /* Lift the item above later siblings whose transforms create their own
         * stacking contexts, so the menu paints on top of the whole list.    */
        .conversation-item:has(.conversation-menu.active) {
            z-index: 10005;
        }

        .conversation-menu-item {
            padding: 10px 16px;
            cursor: pointer;
            font-size: 14px;
            color: #202123;
            border: none;
            background: transparent;
            width: 100%;
            text-align: left;
        }

        .conversation-menu-item:hover {
            background: #f7f7f8;
        }

        .conversation-menu-item:first-child {
            border-radius: 6px 6px 0 0;
        }

        .conversation-menu-item:last-child {
            border-radius: 0 0 6px 6px;
        }

        .conversation-menu-item.delete {
            color: #d11a2a;
        }

        .version-badge {
            display: none;
        }

        /* 鼠标尾巴效果 - 前粗后细蓝色流线 */
        /* Toast 通知系统 */
        .toast-container {
            position: fixed;
            top: 80px;
            right: 24px;
            z-index: 10000;
            display: flex;
            flex-direction: column;
            gap: 12px;
            pointer-events: none;
        }

        .toast {
            background: white;
            border-radius: 12px;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.1);
            padding: 16px 20px;
            display: flex;
            align-items: flex-start;
            gap: 12px;
            min-width: 320px;
            max-width: 420px;
            border-left: 4px solid;
            opacity: 0;
            transform: translateX(400px);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            pointer-events: all;
            position: relative;
            overflow: hidden;
        }

        .toast.show {
            opacity: 1;
            transform: translateX(0);
        }

        .toast.hiding {
            opacity: 0;
            transform: translateX(400px) scale(0.95);
        }

        /* Toast 类型样式 */
        .toast.success {
            border-left-color: #10b981;
        }

        .toast.error {
            border-left-color: #ef4444;
        }

        .toast.warning {
            border-left-color: #f59e0b;
        }

        .toast.info {
            border-left-color: #3b82f6;
        }

        /* Toast 图标 */
        .toast-icon {
            flex-shrink: 0;
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 50%;
            font-size: 14px;
            font-weight: bold;
        }

        .toast.success .toast-icon {
            background: #d1fae5;
            color: #10b981;
        }

        .toast.error .toast-icon {
            background: #fee2e2;
            color: #ef4444;
        }

        .toast.warning .toast-icon {
            background: #fef3c7;
            color: #f59e0b;
        }

        .toast.info .toast-icon {
            background: #dbeafe;
            color: #3b82f6;
        }

        /* Toast 内容 */
        .toast-content {
            flex: 1;
            display: flex;
            flex-direction: column;
            gap: 4px;
        }

        .toast-title {
            font-size: 14px;
            font-weight: 600;
            color: var(--primary-text);
            line-height: 1.4;
        }

        .toast-message {
            font-size: 13px;
            color: var(--secondary-text);
            line-height: 1.5;
        }

        /* Compact variant — quiet, transient notices (viewer export flow).
         * Standard toasts stay big; these shrink to the rail's type scale. */
        .toast.compact {
            padding: 9px 12px;
            min-width: 220px;
            max-width: 320px;
            gap: 8px;
            border-radius: 8px;
        }
        .toast.compact .toast-title {
            font-size: 12px;
        }
        .toast.compact .toast-message {
            font-size: 11px;
        }
        .toast.compact .toast-icon {
            width: 17px;
            height: 17px;
            font-size: 10px;
        }
        .toast.compact .toast-close {
            font-size: 11px;
        }

        /* Toast 关闭按钮 */
        .toast-close {
            flex-shrink: 0;
            width: 20px;
            height: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            border: none;
            background: transparent;
            color: var(--secondary-text);
            cursor: pointer;
            border-radius: 4px;
            font-size: 18px;
            line-height: 1;
            padding: 0;
            transition: all 0.2s;
        }

        .toast-close:hover {
            background: var(--hover-bg);
            color: var(--primary-text);
        }

        /* Toast 进度条 */
        .toast-progress {
            position: absolute;
            bottom: 0;
            left: 0;
            height: 3px;
            background: linear-gradient(90deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.15));
            transform-origin: left;
            transition: transform linear;
        }

        .toast.success .toast-progress {
            background: linear-gradient(90deg, #10b981, #059669);
        }

        .toast.error .toast-progress {
            background: linear-gradient(90deg, #ef4444, #dc2626);
        }

        .toast.warning .toast-progress {
            background: linear-gradient(90deg, #f59e0b, #d97706);
        }

        .toast.info .toast-progress {
            background: linear-gradient(90deg, #3b82f6, #2563eb);
        }

        /* Toast 图标内容 */
        .toast-icon-content {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 100%;
            height: 100%;
        }

        /* 响应式：移动端调整 */
        @media (max-width: 768px) {
            .toast-container {
                right: 12px;
                left: 12px;
                top: 70px;
            }

            .toast {
                min-width: unset;
                max-width: unset;
                width: 100%;
            }
        }

        /* ============================================ */
        /* Trame Viewer - Full Height Optimization */
        /* ============================================ */
        /* v1.70.10: Maximize Trame iframe to fill available screen space */

        #trameViewer {
            flex: 1 !important;              /* Fill remaining parent container space */
            overflow: hidden !important;     /* Prevent scrollbars */
            /* display controlled by JavaScript - removed display: flex !important */
            flex-direction: column !important;
            min-height: 0 !important;        /* Allow flex to shrink */
            height: 100% !important;         /* Full height */
        }

        /* v1.71.2: Trame viewer container - sidebar on RIGHT (using flexbox) */
        #trameViewer .trame-viewer-container {
            display: flex !important;
            flex-direction: row !important;
            flex: 1 1 0% !important;  /* Expand in parent's column direction */
            width: 100% !important;
            min-height: 0 !important;  /* Allow flex shrink */
            overflow: hidden !important;
        }

        /* Trame iframe (3D view) - fills remaining space */
        #trameIframe {
            flex: 1 1 0% !important;
            height: 100% !important;
            min-width: 0;
            border: none;
            background: #ffffff;  /* v1.71.33: White background to avoid gray flash */
        }

        /* Trame file list (RIGHT sidebar - fixed 240px) */
        .trame-file-list {
            flex: 0 0 240px !important;
            height: 100% !important;
            border-left: 1px solid var(--border-light);
            background: #f8f9fa;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
        }

        .trame-file-list-header {
            padding: 12px;
            border-bottom: 1px solid var(--border-light);
            background: #f8f9fa;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .trame-file-list-header h3 {
            margin: 0;
            font-size: 14px;
            font-weight: 600;
            color: #666;
        }

        .trame-file-list-header span {
            font-size: 12px;
            color: #666;
        }

        .trame-file-tree {
            flex: 1;
            overflow-y: auto;
            padding: 8px;
            background: #f8f9fa;
            color: #666;
        }

        /* ==== Timestep playback deck (single row, no text) ====
         * ⏮ ▶ ⏭ + the scrub track (cached-frames layer + fill + knob) in ONE
         * 24px row. No frame counter / time readout by user decision — the
         * TIME select above shows the exact time. Buffering = a thin arc
         * orbiting the play button rim (.pb-buffering, set by JS).
         * Themes restyle it by re-pointing the --pb-* tokens (theme-b2-light,
         * theme-plex-dark) — don't hardcode colors below this line. */
        #tramePlaybackBar {
            /* Quiet gray play button — #DCE1E8 is the lightest value that still
             * reads against the #f8f9fa/#F3F4F6 control strip behind the deck.
             * Light button ⇒ --pb-play-hover darkens; dark themes flip it. */
            --pb-play-bg: #DCE1E8;
            --pb-play-fg: #0F172A;
            --pb-play-hover: brightness(0.94);
            --pb-step-fg: #5B6472;
            --pb-step-fg-hover: #0F172A;
            --pb-hover-bg: rgba(15, 23, 42, 0.05);
            --pb-track-bg: #E3E7ED;
            --pb-cached-bg: #CDD5DF;
            --pb-fill-bg: #2563eb;
            --pb-knob-bg: #ffffff;
            --pb-knob-ring: rgba(15, 23, 42, 0.22);
            --pb-ring: var(--pb-fill-bg);
            display: flex;
            align-items: center;
            gap: 8px;
            height: 24px;
            margin-top: 8px;
        }
        #tramePlaybackBar button {
            -webkit-tap-highlight-color: transparent;
        }
        #tramePlaybackBar button:focus-visible {
            outline: 2px solid var(--pb-fill-bg);
            outline-offset: 1.5px;
        }
        #tramePlaybackBar .pb-step {
            flex: 0 0 auto;
            width: 18px;
            height: 18px;
            padding: 0;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            background: transparent;
            border: none;
            border-radius: 50%;
            color: var(--pb-step-fg);
            cursor: pointer;
        }
        #tramePlaybackBar .pb-step:hover {
            color: var(--pb-step-fg-hover);
            background: var(--pb-hover-bg);
        }
        #tramePlaybackBar .pb-step svg {
            display: block;
            width: 9px;
            height: 9px;
        }
        /* 24px play: WCAG 2.5.8 minimum target, 2:1 over the 12px knob, same
         * visual band height as the TIME select row above. 12px icon keeps
         * integer centering ((24-12)/2 = 6). */
        #tramePlaybackBar .pb-play {
            flex: 0 0 auto;
            position: relative;
            width: 24px;
            height: 24px;
            padding: 0;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            background: var(--pb-play-bg);
            border: none;
            border-radius: 50%;
            color: var(--pb-play-fg);
            cursor: pointer;
        }
        #tramePlaybackBar .pb-play svg {
            display: block;
            width: 12px;
            height: 12px;
        }
        #tramePlaybackBar .pb-play .pb-ic-play { margin-left: 1px; } /* optical centering of the triangle */
        #tramePlaybackBar .pb-play:hover { filter: var(--pb-play-hover, brightness(1.18)); }
        #tramePlaybackBar .pb-play .pb-ic-pause { display: none; }
        #tramePlaybackBar .pb-play.playing .pb-ic-play { display: none; }
        #tramePlaybackBar .pb-play.playing .pb-ic-pause { display: block; }
        /* Buffering: a 2px arc orbits the play button rim. The pause glyph
         * stays visible — still playing, still click-to-pause; the knob no
         * longer pulses (the signal lives on the play button alone). */
        #tramePlaybackBar .pb-play::after {
            content: '';
            position: absolute;
            inset: -4px;
            border-radius: 50%;
            border: 2px solid transparent;
            opacity: 0;
            pointer-events: none;
        }
        #tramePlaybackBar.pb-buffering .pb-play::after {
            opacity: 1;
            border-top-color: var(--pb-ring);
            animation: loading-spin 0.8s linear infinite;
        }
        /* 14px hit area around a 3px visual track (the ::before strip) — the
         * same track height as the rail's Opacity slider (.slice-slider). */
        #tramePlayTrack {
            position: relative;
            flex: 1;
            height: 14px;
            cursor: pointer;
            touch-action: none;
        }
        #tramePlayTrack::before {
            content: '';
            position: absolute;
            left: 0;
            right: 0;
            top: 5.5px;
            bottom: 5.5px;
            border-radius: 2px;
            background: var(--pb-track-bg);
        }
        #tramePlayCached {
            position: absolute;
            left: 0;
            right: 0;
            top: 5.5px;
            bottom: 5.5px;
            pointer-events: none;
        }
        #tramePlayCached .pb-cseg {
            position: absolute;
            top: 0;
            bottom: 0;
            border-radius: 2px;
            background: var(--pb-cached-bg);
        }
        #tramePlayFill {
            position: absolute;
            left: 0;
            top: 5.5px;
            bottom: 5.5px;
            width: 0%;
            border-radius: 2px;
            background: var(--pb-fill-bg);
            pointer-events: none;
        }
        #tramePlayKnob {
            position: absolute;
            top: 50%;
            left: 0%;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: var(--pb-knob-bg);
            box-shadow: 0 0 0 1px var(--pb-knob-ring), 0 1px 2px rgba(0, 0, 0, 0.2);
            transform: translate(-50%, -50%);
            pointer-events: none;
            transition: width 0.12s ease, height 0.12s ease;
        }
        /* Knob is a constant 12px — the same size as the rail's Opacity
         * slider thumb (user request; the old 14px hover-grow also crowded
         * the export ring at the track's right end). */

        /* ==== Animation export: deck ⤓ button + popover ====
         * The ⤓ is a fourth ghost button right of the track; while an export
         * runs a conic ring (JS-painted background on .pb-export-ring, masked
         * to a 2.5px rim) fills clockwise around it — deliberately distinct
         * from the buffering arc (spin = waiting, fill = progress). The
         * popover opens UNDER the deck, full rail width, notch to the button.
         * Collapsed shows Format/Size + estimate; .xp-more expands the
         * .xp-adv block (frame-range trimmer + frame rate) in place. Themes
         * re-point the --xp-* tokens next to their --pb-* blocks. */
        #tramePlaybackBar .pb-export {
            position: relative;
            /* extra clearance: at 100% the knob overhangs the track end and
             * sat almost touching the progress ring (ring reaches 3.5px
             * outside the button). */
            margin-left: 6px;
        }
        #tramePlaybackBar .pb-export .pb-export-ring {
            position: absolute;
            inset: -3.5px;
            border-radius: 50%;
            pointer-events: none;
            -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2px));
                    mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2px));
        }
        #tramePlaybackBar .pb-export.exporting {
            color: var(--pb-fill-bg);
        }
        /* While exporting the glyph flips ⤓ → ■ (click = cancel). */
        #tramePlaybackBar .pb-export .pb-ic-stop {
            display: none;
        }
        #tramePlaybackBar .pb-export.exporting .pb-ic-dl {
            display: none;
        }
        #tramePlaybackBar .pb-export.exporting .pb-ic-stop {
            display: block;
        }
        #trameTimestepControls {
            position: relative; /* anchors #trameExportPop */
        }
        #trameExportPop {
            /* Self-contained tokens: the --pb-* set is scoped to
             * #tramePlaybackBar and does NOT reach this sibling — referencing
             * it here silently resolves to nothing (invisible accent button). */
            --xp-surface: #FFFFFF;
            --xp-line: #D3D8E0;
            --xp-ink: #16181D;
            --xp-muted: #5C6470;
            --xp-dim: #9AA1AC;
            --xp-sel-bg: #0F172A;
            --xp-sel-fg: #FFFFFF;
            --xp-acc: #2563eb;
            --xp-track: #E3E7ED;
            position: absolute;
            z-index: 60;
            left: 8px;
            right: 8px;
            top: calc(100% - 4px);
            background: var(--xp-surface);
            border: 1px solid var(--xp-line);
            border-radius: 10px;
            box-shadow: 0 10px 32px -8px rgba(0, 0, 0, 0.3);
            padding: 11px 12px 12px;
            color: var(--xp-ink);
        }
        #trameExportPop::before {
            content: '';
            position: absolute;
            right: 11px;
            top: -5px;
            width: 9px;
            height: 9px;
            background: var(--xp-surface);
            border-left: 1px solid var(--xp-line);
            border-top: 1px solid var(--xp-line);
            transform: rotate(45deg);
        }
        #trameExportPop button:focus-visible {
            outline: 2px solid var(--xp-acc);
            outline-offset: 1.5px;
        }
        #trameExportPop .xp-row + .xp-row,
        #trameExportPop .xp-adv .xp-row {
            margin-top: 10px;
        }
        #trameExportPop .xp-k {
            font-size: 9.5px;
            font-weight: 680;
            letter-spacing: 0.1em;
            text-transform: uppercase;
            color: var(--xp-dim);
            margin-bottom: 5px;
        }
        #trameExportPop .xp-seg {
            display: flex;
            border: 1px solid var(--xp-line);
            border-radius: 6px;
            overflow: hidden;
        }
        #trameExportPop .xp-seg button {
            flex: 1;
            font-size: 11px;
            font-weight: 600;
            padding: 5px 0;
            border: none;
            border-left: 1px solid var(--xp-line);
            background: transparent;
            color: var(--xp-muted);
            cursor: pointer;
        }
        #trameExportPop .xp-seg button:first-child {
            border-left: none;
        }
        #trameExportPop .xp-seg button:disabled {
            color: var(--xp-dim);
            opacity: 0.55;
            cursor: not-allowed;
        }
        #trameExportPop .xp-seg button.sel {
            background: var(--xp-sel-bg);
            color: var(--xp-sel-fg);
        }
        #trameExportPop .xp-adv {
            display: none;
        }
        #trameExportPop.xp-more .xp-adv {
            display: block;
        }
        /* Frame-range trimmer: same 14px hit / 3px strip geometry as the deck
         * track, two round handles, selected span in the accent. */
        #trameExportPop .xp-range {
            position: relative;
            height: 14px;
            cursor: pointer;
            touch-action: none;
        }
        #trameExportPop .xp-range::before {
            content: '';
            position: absolute;
            left: 0;
            right: 0;
            top: 5.5px;
            bottom: 5.5px;
            border-radius: 2px;
            background: var(--xp-track);
        }
        #trameExportPop .xp-rsel {
            position: absolute;
            top: 5.5px;
            bottom: 5.5px;
            border-radius: 2px;
            background: var(--xp-acc);
            opacity: 0.45;
            pointer-events: none;
        }
        #trameExportPop .xp-rh {
            position: absolute;
            top: 50%;
            width: 11px;
            height: 11px;
            border-radius: 50%;
            background: var(--xp-surface);
            border: 2px solid var(--xp-acc);
            transform: translate(-50%, -50%);
            pointer-events: none;
        }
        #trameExportPop .xp-rlabel {
            font-family: 'Geist Mono', ui-monospace, monospace;
            font-size: 9.5px;
            color: var(--xp-muted);
            margin-top: 4px;
            font-variant-numeric: tabular-nums;
        }
        /* One row, never wraps: the estimate ellipsizes before the More
         * toggle ever gets pushed to a second line (224px is tight). */
        #trameExportPop .xp-foot {
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 8px;
            flex-wrap: nowrap;
            margin: 10px 0 8px;
        }
        #trameExportPop .xp-est {
            font-family: 'Geist Mono', ui-monospace, monospace;
            font-size: 9px;
            color: var(--xp-dim);
            font-variant-numeric: tabular-nums;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            flex: 1 1 auto;
            min-width: 0;
        }
        #trameExportPop .xp-more {
            font-size: 10.5px;
            font-weight: 600;
            color: var(--xp-acc);
            background: none;
            border: none;
            padding: 0;
            cursor: pointer;
            flex: none;
            white-space: nowrap;
        }
        #trameExportPop .xp-go {
            width: 100%;
            font-size: 11.5px;
            font-weight: 650;
            color: #FFFFFF;
            background: var(--xp-acc);
            border: none;
            border-radius: 7px;
            padding: 7px 0;
            cursor: pointer;
        }
        #trameExportPop .xp-go:hover {
            filter: brightness(1.08);
        }
        /* Done view: filename + size, explicit Download confirmation. */
        #trameExportPop .xp-file {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            gap: 8px;
            margin: 2px 0 10px;
        }
        #trameExportPop #xpDoneName {
            font-family: 'Geist Mono', ui-monospace, monospace;
            font-size: 10px;
            font-weight: 600;
            color: var(--xp-ink);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            min-width: 0;
            flex: 1 1 auto;
        }
        #trameExportPop #xpDoneSize {
            font-family: 'Geist Mono', ui-monospace, monospace;
            font-size: 9.5px;
            color: var(--xp-dim);
            font-variant-numeric: tabular-nums;
            flex: none;
        }
        #trameExportPop .xp-discard {
            width: 100%;
            font-size: 10px;
            font-weight: 600;
            color: var(--xp-muted);
            background: none;
            border: none;
            padding: 6px 0 1px;
            cursor: pointer;
        }
        #trameExportPop .xp-discard:hover {
            color: var(--xp-ink);
        }

        /* When there are no VTU files the tree is emptied (innerHTML=''), so
         * collapse it entirely — otherwise its flex:1 (+ the theme's divider
         * line and padding) leaves a tall blank strip below the Opacity panel
         * at the bottom of the rail. ID + :empty + !important beats the
         * theme's `.trame-file-list > .trame-file-tree` border/padding rules. */
        #trameFileTree:empty {
            display: none !important;
        }

        /* Geometry Files Section (STL) - v1.71.15 ParaView-style */
        .geometry-files-section {
            border-bottom: 1px solid var(--border-light);
        }

        .geometry-file-tree {
            padding: 4px 8px;
            max-height: 200px;
            overflow-y: auto;
        }

        .geometry-file-item {
            padding: 4px 6px;
            border-radius: 4px;
            transition: background 0.2s;
            display: flex;
            align-items: center;
            gap: 6px;
            font-family: inherit;
            font-size: 13px;
            color: var(--primary-text);
        }

        .geometry-file-item:hover {
            background: var(--hover-bg);
        }

        /* v1.71.27: Selected STL file highlight (softer yellow) */
        .geometry-file-item.selected {
            background: #fffbeb;  /* Softer yellow background */
            border: 1px solid #fcd34d;  /* Softer yellow border */
            margin: -1px;  /* Compensate for border */
        }

        /* v1.72: Slice control bar */
        .slice-control-bar {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 8px 12px;
            background: #f8fafc;
            border-bottom: 1px solid #e2e8f0;
            font-size: 13px;
        }

        .slice-toggle {
            display: flex;
            align-items: center;
            gap: 6px;
            cursor: pointer;
            user-select: none;
        }

        .slice-toggle input[type="checkbox"] {
            width: 16px;
            height: 16px;
            cursor: pointer;
        }

        .slice-controls {
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .slice-controls select {
            padding: 4px 8px;
            border: 1px solid #d1d5db;
            border-radius: 4px;
            background: white;
            font-size: 13px;
            cursor: pointer;
        }

        .slice-controls input[type="range"] {
            width: 120px;
            cursor: pointer;
        }

        #slicePositionLabel {
            min-width: 36px;
            text-align: right;
            color: #64748b;
        }

        /* v1.71.20: Eye icon button for visibility toggle (ParaView-style) */
        .geometry-file-item .stl-visibility-btn {
            width: 20px;
            height: 20px;
            padding: 2px;
            margin: 0;
            border: none;
            background: transparent;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 3px;
            transition: background 0.2s, opacity 0.2s;
        }

        .geometry-file-item .stl-visibility-btn:hover {
            background: var(--hover-bg);
        }

        .geometry-file-item .stl-visibility-btn.visible {
            color: var(--b2-acc) !important;
            opacity: 1 !important;
        }

        .geometry-file-item .stl-visibility-btn.hidden {
            color: var(--b2-ink-4) !important;
            opacity: 0.62 !important;    /* keep dim but let the slash read clearly */
        }

        .geometry-file-item .stl-visibility-btn .eye-icon {
            width: 16px;
            height: 16px;
        }

        .geometry-file-item .file-name {
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            cursor: pointer;
        }

        .geometry-file-item .file-name:hover {
            color: var(--primary);
        }

        .geometry-file-item .stl-delete-btn {
            width: 18px;
            height: 18px;
            border: none;
            background: transparent;
            color: #999;
            font-size: 16px;
            line-height: 1;
            cursor: pointer;
            border-radius: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            opacity: 0;
            transition: opacity 0.2s, background 0.2s, color 0.2s;
        }

        .geometry-file-item:hover .stl-delete-btn {
            opacity: 1;
        }

        .geometry-file-item .stl-delete-btn:hover {
            background: #fee2e2;
            color: #dc2626;
        }

        /* Derived-geometry row buttons (isolate ⊙, info ⓘ).
           Same dimensions as .stl-delete-btn so rows line up with the
           Uploads section. All colors come from B² Modern Light tokens
           (theme-b2-light.css) — no new RGB triples here. */
        .geometry-file-item .stl-isolate-btn {
            width: 18px;
            height: 18px;
            border: none;
            background: transparent;
            color: var(--b2-ink-4);
            font-family: inherit;
            font-size: 13px;
            line-height: 1;
            cursor: pointer;
            border-radius: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            opacity: 0;
            transition: opacity 0.2s, background 0.2s, color 0.2s;
        }
        .geometry-file-item:hover .stl-isolate-btn { opacity: 1; }
        .geometry-file-item .stl-isolate-btn:hover {
            background: var(--b2-acc-soft);
            color: var(--b2-acc);
        }

        .geometry-file-item .stl-info-btn {
            width: 18px;
            height: 18px;
            border: none;
            background: transparent;
            color: var(--b2-ink-4);
            font-size: 13px;
            line-height: 1;
            cursor: help;
            display: flex;
            align-items: center;
            justify-content: center;
            opacity: 0;
            transition: opacity 0.2s, color 0.2s;
        }
        .geometry-file-item:hover .stl-info-btn { opacity: 1; }
        .geometry-file-item .stl-info-btn:hover { color: var(--b2-acc); }

        /* The Derived section reuses .geometry-files-section, but its rows
           never delete (files belong to the case, not the user). Hide the
           delete-btn slot defensively in case the render fn ever emits one. */
        .derived-geometry-section .stl-delete-btn { display: none !important; }

        /* ---------- Scene-mode lockdown ----------
           When the body has .scene-mode, only the GEOMETRY-related
           legacy sections (Cases, Uploads, Derived) are hidden — the
           Scene tree replaces them. The standalone VTU FILES header
           and Field/Color/Range / TIME controls stay visible in their
           original spot below the tree because the Scene tree is
           geometry-only (no Results / fields / colormap nodes). */
        body.scene-mode #trameCaseSection,
        body.scene-mode #geometryFilesSection {
            display: none !important;
        }

        /* ---------- Scene tree (Phase 2) — STL/STEP only ----------
           Every row is a `.file-tree-item` — identical DOM contract to
           the left-hand Files explorer. The theme already styles
           .file-tree-item / .file-tree-toggle / .file-tree-toggle::before,
           so this block only adds what the narrower 240 px right rail
           needs on top: tighter padding, smaller mono font on file
           names, right-aligned count badge, eye-button slot. */
        #sceneTree {
            padding: 6px 4px 8px;
        }
        #sceneTree .file-tree-item {
            font-size: 12px;
            padding-top: 2px;
            padding-bottom: 2px;
            padding-right: 8px;
            gap: 4px;
            border-radius: 4px;
        }
        #sceneTree .file-tree-item .file-name {
            font-family: var(--f-mono);
            font-size: 11px;
        }
        /* Group header rows ("Uploads", "Cases") — sticky: pin to the top
           of the scrolling rail while their .scene-group is in view. The
           wrapper bounds the sticky range, so the next group's header
           pushes the previous one away instead of overlapping. Opaque
           background so tree rows don't show through while pinned. */
        #sceneTree .scene-group-row {
            position: sticky;
            top: 0;
            z-index: 2;
            background: var(--b2-bg, #f8f9fa);
        }
        /* Group header rows ("Uploads", "Cases") — render the label with
           the same compact uppercase mono styling the theme uses on its
           own .trame-file-list-header h3. */
        #sceneTree .scene-group-row .scene-group-label {
            font-family: var(--f-mono);
            font-size: 10px;
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--b2-ink-2);
        }
        #sceneTree .scene-count {
            margin-left: auto;
            font-family: var(--f-mono);
            font-size: 9.5px;
            font-weight: 500;
            color: var(--b2-ink-4);
            letter-spacing: 0.06em;
            font-variant-numeric: tabular-nums;
            flex: 0 0 auto;
        }
        /* Active case row — soft blue background (--b2-acc-soft), no left
           rail, no hairline border. Matches the same selected-row treatment
           used elsewhere in the rail. !important is required because the
           theme's `.file-tree-item.selected` rule sets a cream background
           with !important that would otherwise win.
           Also need to suppress the theme's `.file-tree-item.selected::before`
           pseudo-element which paints a 2 px blue absolute bar on the left. */
        #sceneTree .scene-case-row.selected {
            background: var(--b2-acc-soft) !important;
            box-shadow: none !important;
            color: var(--b2-acc-ink) !important;
        }
        #sceneTree .scene-case-row.selected::before {
            content: none !important;
            display: none !important;
        }
        /* Inactive case row hover — gives a clickable affordance that
           was missing (P0-C from audit). Soft sunken bg matches the
           rest of the rail's hover treatment. */
        #sceneTree .scene-case-row:not(.selected):hover {
            background: var(--b2-sunken) !important;
            cursor: pointer;
        }
        /* Eye-icon button — fixed 18 px slot so all rows line up. */
        #sceneTree .trame-visibility-btn {
            width: 18px;
            height: 18px;
            padding: 0;
            margin: 0;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            background: transparent;
            border: 0;
            cursor: pointer;
            flex: 0 0 18px;
        }
        #sceneTree .trame-visibility-btn.visible,
        #sceneTree .trame-visibility-btn.visible .eye-icon {
            color: var(--b2-acc) !important;
            opacity: 1 !important;
        }
        #sceneTree .trame-visibility-btn.hidden,
        #sceneTree .trame-visibility-btn.hidden .eye-icon,
        #sceneTree .file-tree-item.trame-hidden .trame-visibility-btn,
        #sceneTree .file-tree-item.trame-hidden .trame-visibility-btn .eye-icon {
            color: var(--b2-ink-4) !important;
            opacity: 0.62 !important;
        }
        /* Hidden-state file rows pick up the existing trame-hidden mute. */
        #sceneTree .file-tree-item.trame-hidden .file-name {
            color: var(--b2-ink-4);
        }
        /* Chevron column — narrowed from the file explorer's 14 px to 10 px
           (the 240 px rail is too tight for wide gutters), and the leaf-row
           placeholder is pinned to the SAME width so eyes/names align across
           expandable and leaf siblings without wobble. !important because
           theme-b2-light.css pins `.file-tree-toggle { width/flex 14px }`
           with !important for the left file explorer. */
        #sceneTree .file-tree-toggle,
        #sceneTree .scene-chevron-placeholder {
            width: 10px !important;
            flex: 0 0 10px !important;
            display: inline-flex !important;
            align-items: center;
            justify-content: center;
        }
        #sceneTree .scene-chevron-placeholder { visibility: hidden; }
        /* Filter row — persistent input above the tree body (VS Code-style
           tree filter; matching rows keep their ancestor chain visible). */
        #sceneTree .scene-filter-row {
            padding: 0 4px 6px;
        }
        #sceneTree .scene-filter {
            width: 100%;
            box-sizing: border-box;
            padding: 3px 8px;
            font-family: var(--f-mono);
            font-size: 11px;
            color: var(--b2-ink-1);
            background: var(--b2-sunken, rgba(0, 0, 0, 0.04));
            border: 1px solid var(--b2-line, rgba(0, 0, 0, 0.12));
            border-radius: 4px;
            outline: none;
        }
        #sceneTree .scene-filter:focus {
            border-color: var(--b2-acc);
        }
        #sceneTree .scene-tree-empty {
            padding: 8px 10px;
            font-family: var(--f-mono);
            font-size: 10.5px;
            color: var(--b2-ink-4);
        }


        /* ----- Boundary section container (right rail) -----
           Header + list both control their own padding, so wipe any padding
           the rail-unification rule pushed onto the section itself. The
           rail rule also paints a `border-top` on the section, AND the inner
           .trame-file-list-header has its own ::before hairline — suppress
           the inner one to avoid two stacked separators.

           Horizontal padding (12px) is matched to .slice-panel-header /
           .slice-panel-content above so the BOUNDARIES list lines up
           visually with the OPACITY row directly above it.

           Specificity bump: theme-b2-light.css ships #boundaryVisibilitySection
           with `padding: 12px 14px !important` and is loaded AFTER main.css,
           so a same-specificity override loses the cascade. Combine class +
           id below to pull ahead. */
        .trame-file-list #boundaryVisibilitySection {
            padding: 0 !important;
        }
        .trame-file-list #boundaryVisibilitySection .trame-file-list-header {
            padding: 14px 12px 8px !important;
        }
        .trame-file-list #boundaryVisibilitySection .trame-file-list-header::before {
            display: none !important;
        }
        .boundary-toggle-list {
            display: flex;
            flex-direction: column;
            gap: 2px;
            padding: 4px 12px 14px;
        }

        /* Sub-group divider inside the rail list ("Particles"): lagrangian
           clouds are scene objects, not boundary patches, so they sit under
           their own heading — a miniature of .trame-file-list-header. */
        .boundary-group-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 8px 0 2px;
            padding: 6px 8px 4px;
            border-top: 1px solid var(--b2-line, #E5E7EB);
        }
        .boundary-group-header h3 {
            margin: 0;
            font-size: 11px;
            font-weight: 600;
            letter-spacing: 0.04em;
            color: var(--b2-ink-3, #6B7280);
        }
        .boundary-group-header span {
            font-size: 10.5px;
            color: var(--b2-ink-3, #6B7280);
            background: var(--b2-sunken, #F3F4F6);
            padding: 0 7px;
            border-radius: 999px;
        }

        /* Ghost-view toggle in the Particles group header (STIHL-style
           fade-the-surfaces shortcut). Mono mini-pill matching rail text. */
        .particles-ghost-btn {
            font-family: var(--f-mono, ui-monospace, monospace);
            font-size: 10px;
            line-height: 16px;
            padding: 0 8px;
            margin-left: auto;
            margin-right: 8px;
            border: 1px solid var(--b2-line-2, #D1D5DB);
            border-radius: 999px;
            background: #fff;
            color: var(--b2-ink-3, #6B7280);
            cursor: pointer;
            transition: color 120ms ease-out, border-color 120ms ease-out, background 120ms ease-out;
        }
        .particles-ghost-btn:hover {
            border-color: var(--b2-acc, #2A78D6);
            color: var(--b2-acc-ink, #1E5AA8);
        }
        .particles-ghost-btn.on {
            background: var(--b2-acc-soft, rgba(42,120,214,0.10));
            border-color: var(--b2-acc-line, rgba(42,120,214,0.28));
            color: var(--b2-acc-ink, #1E5AA8);
        }

        /* ----- Boundary patch rows (View 3D right rail) -----
           Active-row drawer pattern: each patch collapses to
           [eye | name | %], and clicking the row promotes it to .active
           which paints the soft-blue acc-soft tint used elsewhere in the
           rail (Generate button, focus rings) — matches the platform's
           accent color rather than the user-message cream. The opacity
           slider drawer reveals beneath the active row. */
        .boundary-row {
            display: flex;
            flex-direction: column;
            padding: 4px 8px;
            border-radius: 5px;
            background: transparent;
            transition: background 120ms ease-out;
        }
        .boundary-row:hover {
            background: var(--b2-sunken, #F4F5F7);
        }
        .boundary-row.active {
            background: var(--b2-acc-soft, rgba(42,120,214,0.10));
        }
        .boundary-row.hidden .boundary-name,
        .boundary-row.hidden .boundary-pct {
            color: var(--b2-ink-4, #9CA3AF);
        }

        .boundary-row-header {
            display: flex;
            align-items: center;
            gap: 8px;
            cursor: pointer;
            user-select: none;
            min-height: 26px;
        }

        .boundary-eye {
            width: 22px;
            height: 22px;
            padding: 3px;
            border: 0;
            background: transparent;
            color: var(--b2-ink-3, #6B7280);
            cursor: pointer;
            border-radius: 4px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            transition: background 120ms ease-out, color 120ms ease-out;
            flex-shrink: 0;
        }
        .boundary-eye:hover {
            background: rgba(17, 18, 22, 0.06);
            color: var(--b2-ink, #111216);
        }
        .boundary-row.active .boundary-eye {
            color: var(--b2-acc-ink, #1E5AA8);
        }
        .boundary-row.hidden .boundary-eye {
            color: var(--b2-ink-4, #9CA3AF);
        }

        /* Mono font + size matches the OPACITY value (1.00) and other rail
           text controls — keeps the rail visually coherent. Patch names
           preserve original case (camelCase) for readability. */
        .boundary-name {
            flex: 1 1 auto;
            font-family: var(--f-mono, ui-monospace, monospace);
            font-size: 11px;
            font-weight: 500;
            color: var(--b2-ink, #111216);
            letter-spacing: 0.01em;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .boundary-row.active .boundary-name {
            color: var(--b2-acc-ink, #1E5AA8);
        }

        .boundary-pct {
            font-family: var(--f-mono, ui-monospace, monospace);
            font-size: 10.5px;
            font-variant-numeric: tabular-nums;
            color: var(--b2-ink-3, #6B7280);
            letter-spacing: 0.02em;
            flex-shrink: 0;
            min-width: 30px;
            text-align: right;
        }
        .boundary-row.active .boundary-pct {
            color: var(--b2-acc-ink, #1E5AA8);
        }

        /* Drawer collapses out of the layout when the row is not active. */
        .boundary-row-drawer {
            display: none;
            padding: 6px 2px 4px 30px;
        }
        .boundary-row.active .boundary-row-drawer {
            display: block;
        }

        /* Inherits the shared .slice-slider tokens (3 px track, 12 px blue
           thumb) from theme-b2-light.css so per-patch sliders match the
           global opacity slider exactly. Only width/margin live here. */
        .boundary-opacity-slider {
            width: 100%;
            margin: 0;
            display: block;
        }

        /* Trame file items (reuse VTK styles) */
        .trame-file-item {
            cursor: pointer;
            padding: 6px 8px;
            border-radius: 4px;
            transition: background 0.2s;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .trame-file-item:hover {
            background: var(--hover-bg);
        }

        .trame-file-item.selected {
            background: rgba(37, 99, 235, 0.08);
            color: #2563eb;
            font-weight: 500;
        }

        /* Eye icon visibility toggle button */
        .trame-visibility-btn {
            border: none;
            background: none;
            padding: 2px;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            border-radius: 3px;
            transition: background 0.15s;
            flex-shrink: 0;
        }

        .trame-visibility-btn:hover {
            background: rgba(0, 0, 0, 0.08);
        }

        .trame-visibility-btn.hidden .eye-icon {
            opacity: 0.4;
        }

        .eye-icon {
            display: block;
            width: 16px;
            height: 16px;
        }

        /* Hidden (invisible) file items */
        .trame-file-item.trame-hidden {
            opacity: 0.45;
        }

        .trame-file-item.trame-hidden .file-name {
            text-decoration: none;
        }

        /* Trame iframe (right panel) */
        #trameViewer iframe,
        #trameIframe {
            grid-column: 2;
            width: 100% !important;
            height: 100% !important;
            border: none;
            background: #1a1a1a;
        }

        /* ===== Library Modal ===== */
        .library-modal {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: #1a1a1a;
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 1000;
        }

        .library-modal-content {
            background: var(--b2-surface);
            border-radius: 6px;
            border: 1px solid var(--b2-line);
            width: 92%;
            max-width: 880px;
            max-height: 86vh;
            display: flex;
            flex-direction: column;
            box-shadow: 0 8px 24px rgba(17,18,22,0.10);
            font-family: var(--f-sans);
        }

        .library-modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 14px 18px;
            border-bottom: 1px solid var(--b2-line);
            background: var(--b2-surface);
        }

        .library-modal-header h3 {
            margin: 0;
            font-size: 14px;
            font-weight: 600;
            letter-spacing: -0.005em;
            color: var(--b2-ink);
        }

        .library-close-btn {
            background: none;
            border: none;
            font-size: 18px;
            line-height: 1;
            color: var(--b2-ink-3);
            cursor: pointer;
            padding: 4px 8px;
            border-radius: 4px;
            transition: background 120ms ease-out, color 120ms ease-out;
        }

        .library-close-btn:hover {
            color: var(--b2-ink);
            background: var(--b2-sunken);
        }

        .library-modal-body {
            flex: 1;
            overflow-y: auto;
            padding: 12px 18px 18px;
            background: var(--b2-bg);
        }

        .library-file-list {
            display: flex;
            flex-direction: column;
            gap: 6px;
        }

        /* Session row — analogous to a conversation row in the sidebar */
        .library-group {
            border: 1px solid var(--b2-line);
            border-radius: 5px;
            overflow: hidden;
            background: var(--b2-surface);
            transition: box-shadow 120ms ease-out;
        }
        .library-group:hover { box-shadow: 0 2px 6px rgba(17,18,22,0.06); }

        .library-group-header {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 9px 12px;
            background: var(--b2-surface);
            cursor: pointer;
            user-select: none;
            font-family: var(--f-sans);
        }

        .library-group-header:hover {
            background: var(--b2-sunken);
        }

        .library-group-icon {
            font-size: 9px;
            color: var(--b2-ink-3);
            width: 10px;
            text-align: center;
        }

        .library-group-name {
            font-size: 12.5px;
            font-weight: 600;
            color: var(--b2-ink);
            letter-spacing: -0.005em;
        }

        .library-group-count {
            font-size: 11.5px;
            color: var(--b2-ink-3);
            margin-left: auto;
            font-family: var(--f-mono);
            font-weight: 400;
        }

        .library-group-time {
            font-size: 11px;
            color: var(--b2-ink-4);
            margin-left: 8px;
            font-family: var(--f-mono);
        }

        .library-group-files {
            padding: 0 8px 8px;
            background: var(--b2-surface);
            border-top: 1px solid var(--b2-line);
        }

        .library-file-item {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 7px 10px;
            border-radius: 4px;
            cursor: pointer;
            margin-top: 4px;
            transition: background 120ms ease-out;
        }

        .library-file-item:hover {
            background: var(--b2-sunken);
        }

        .library-file-item.selected {
            background: var(--b2-user-bg);
            box-shadow: inset 2px 0 0 var(--b2-user-rule);
        }

        .library-checkbox {
            width: 14px;
            height: 14px;
            accent-color: var(--b2-user-rule);
            flex-shrink: 0;
            margin: 0;
        }

        .library-file-info {
            display: flex;
            align-items: center;
            justify-content: space-between;
            flex: 1;
            min-width: 0;
            gap: 12px;
        }

        .library-file-name {
            font-size: 12.5px;
            color: var(--b2-ink);
            font-family: var(--f-mono);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .library-file-meta {
            font-size: 11px;
            color: var(--b2-ink-4);
            font-family: var(--f-mono);
            white-space: nowrap;
            flex-shrink: 0;
        }

        /* Batch variant folder in file tree */
        .file-tree-item.batch-variant-folder {
            font-weight: 600;
            color: var(--primary);
            border-left: 3px solid var(--primary);
            margin-left: 0;
            padding-left: 5px;
            margin-bottom: 2px;
        }

        .file-tree-item.batch-variant-folder .file-name::after {
            content: ' [variant]';
            font-size: 11px;
            font-weight: 400;
            color: var(--secondary-text);
            opacity: 0.7;
        }

        .file-tree-item.batch-base-case {
            font-weight: 600;
            color: var(--primary);
            border-left: 3px solid var(--primary);
            margin-left: 0;
            padding-left: 5px;
            margin-bottom: 2px;
        }

        .file-tree-item.batch-base-case .file-name::after {
            content: ' [base]';
            font-size: 11px;
            font-weight: 400;
            color: var(--secondary-text);
            opacity: 0.7;
        }

        .library-loading,
        .library-error,
        .library-empty {
            text-align: center;
            padding: 36px 20px;
            color: var(--b2-ink-3);
            font-size: 12.5px;
            font-family: var(--f-sans);
        }

        .library-error {
            color: var(--b2-err);
        }

        .library-modal-footer {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 18px;
            border-top: 1px solid var(--b2-line);
            background: var(--b2-surface);
        }

        #librarySelectedCount {
            font-size: 12.5px;
            color: var(--b2-ink-3);
            font-family: var(--f-mono);
        }

        .library-actions {
            display: flex;
            gap: 6px;
        }

        .library-btn-cancel,
        .library-btn-confirm {
            padding: 6px 14px;
            border-radius: 5px;
            font-size: 12.5px;
            font-family: var(--f-sans);
            font-weight: 500;
            letter-spacing: -0.005em;
            cursor: pointer;
            transition: background 120ms ease-out, border-color 120ms ease-out;
        }

        .library-btn-cancel {
            background: var(--b2-surface);
            color: var(--b2-ink-2);
            border: 1px solid var(--b2-line);
        }

        .library-btn-cancel:hover {
            background: var(--b2-sunken);
            color: var(--b2-ink);
            border-color: var(--b2-line-2);
        }

        /* Confirm — cream + amber rule, matches active conversation row +
           user message bubble accent. */
        .library-btn-confirm {
            background: var(--b2-user-bg);
            color: var(--b2-ink);
            border: 1px solid var(--b2-user-rule);
        }

        .library-btn-confirm:hover {
            background: #F5EBD3;
            border-color: #C99E48;
        }
        .library-btn-confirm:active {
            background: #EFDFC4;
        }

        /* ===== Library: tabs (text-only, amber underline for active) ===== */
        .library-tabs {
            display: flex;
            gap: 4px;
            padding: 0 18px;
            border-bottom: 1px solid var(--b2-line);
            background: var(--b2-surface);
        }
        .library-tab {
            background: transparent;
            border: none;
            padding: 10px 12px 9px;
            font-size: 12.5px;
            font-family: var(--f-sans);
            font-weight: 500;
            color: var(--b2-ink-3);
            cursor: pointer;
            border-bottom: 2px solid transparent;
            margin-bottom: -1px;
            transition: color 120ms ease-out, border-color 120ms ease-out;
        }
        .library-tab:hover { color: var(--b2-ink); }
        .library-tab.active {
            color: var(--b2-ink);
            border-bottom-color: var(--b2-user-rule);
            font-weight: 600;
        }

        .library-toolbar {
            padding: 12px 18px 0;
            background: var(--b2-bg);
        }
        #librarySearch {
            width: 100%;
            padding: 7px 11px;
            border: 1px solid var(--b2-line);
            border-radius: 5px;
            font-size: 12.5px;
            font-family: var(--f-sans);
            color: var(--b2-ink);
            background: var(--b2-surface);
            transition: border-color 120ms ease-out, box-shadow 120ms ease-out;
        }
        #librarySearch:focus {
            outline: none;
            border-color: var(--b2-user-rule);
            box-shadow: 0 0 0 3px rgba(224,182,94,0.18);
        }
        #librarySearch::placeholder { color: var(--b2-ink-4); }

        .library-session-cb { margin: 0; }
        .library-dup-badge {
            background: var(--b2-user-bg);
            color: var(--b2-warn);
            border: 1px solid var(--b2-user-rule);
            border-radius: 3px;
            padding: 0 5px;
            font-size: 10.5px;
            font-weight: 600;
            font-family: var(--f-mono);
            margin-left: 6px;
            line-height: 1.5;
        }
        .library-type-icon {
            font-size: 13px;
            opacity: 0.6;
            line-height: 1;
        }
        .library-tag {
            background: var(--b2-sunken);
            color: var(--b2-ink-2);
            border: 1px solid var(--b2-line);
            border-radius: 3px;
            padding: 0 5px;
            font-size: 10.5px;
            font-weight: 500;
            font-family: var(--f-mono);
            line-height: 1.6;
        }

        /* ===== Library: Public — card grid ===== */
        .library-public-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
            gap: 10px;
            padding-top: 4px;
        }
        .library-card {
            display: flex;
            flex-direction: column;
            border: 1px solid var(--b2-line);
            border-radius: 5px;
            background: var(--b2-surface);
            cursor: pointer;
            transition: background 120ms ease-out, box-shadow 120ms ease-out;
            overflow: hidden;
            position: relative;
            font-family: var(--f-sans);
        }
        .library-card:hover {
            background: var(--b2-sunken);
            box-shadow: 0 2px 6px rgba(17,18,22,0.06);
        }
        /* Selected card mirrors the conversation-item.active treatment:
           cream surface + 2px amber inset edge + hairline outer border. */
        .library-card:has(input:checked) {
            background: var(--b2-user-bg);
            box-shadow: inset 2px 0 0 var(--b2-user-rule),
                        0 0 0 1px var(--b2-line);
        }
        .library-card input[type="checkbox"] {
            position: absolute;
            top: 8px;
            right: 8px;
            width: 14px;
            height: 14px;
            accent-color: var(--b2-user-rule);
            margin: 0;
            z-index: 1;
        }
        .library-card-thumb {
            width: 100%;
            height: 96px;
            object-fit: cover;
            background: var(--b2-sunken);
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--b2-ink-3);
            border-bottom: 1px solid var(--b2-line);
        }
        .library-card-thumb svg {
            width: 56px;
            height: 56px;
            stroke-width: 1.6;
        }
        .library-card-body {
            padding: 9px 11px 11px;
            display: flex;
            flex-direction: column;
            gap: 3px;
        }
        .library-card-title {
            font-weight: 600;
            font-size: 12.5px;
            color: var(--b2-ink);
            letter-spacing: -0.005em;
        }
        .library-card-desc {
            font-size: 11.5px;
            color: var(--b2-ink-3);
            line-height: 1.45;
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
            overflow: hidden;
            margin-top: 1px;
        }
        .library-card-meta {
            display: flex;
            justify-content: space-between;
            font-size: 10.5px;
            color: var(--b2-ink-4);
            font-family: var(--f-mono);
            margin-top: 6px;
            text-transform: uppercase;
            letter-spacing: 0.02em;
        }
        .library-card-tags {
            display: flex;
            flex-wrap: nowrap;
            gap: 3px;
            margin-top: 5px;
            overflow: hidden;
        }
        .library-card-tags .library-tag {
            flex-shrink: 0;
            white-space: nowrap;
        }

        .library-pane { padding: 0; }

/* =============================================================================
   Provisioning Overlay (per-user isolation)
   ============================================================================= */

/* ================================================================
 * Provisioning Overlay — shares the "Luminous CFD Workbench" canvas
 * with the login modal so the login → provision transition reads as
 * one continuous screen, just with a new card swapped in.
 * ================================================================ */
.provisioning-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    background: var(--login-canvas, #FAF9F5);
}

.provisioning-container {
    background: var(--login-surface, #FFFFFF);
    border: 1px solid var(--login-line, #E9E6D9);
    border-radius: 14px;
    padding: 48px 44px 40px;
    max-width: 420px;
    width: 100%;
    color: var(--login-ink, #141413);
    font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
    text-align: center;
    box-shadow:
        0 1px 2px rgba(20, 20, 19, 0.04),
        0 12px 32px -12px rgba(20, 20, 19, 0.08);
    animation: login-rise 0.4s cubic-bezier(0.2, 0.7, 0.25, 1) both;
}

@media (prefers-reduced-motion: reduce) {
    .provisioning-container { animation: none; }
}

.provisioning-icon {
    margin-bottom: 24px;
    display: flex;
    justify-content: center;
}

.provisioning-spinner {
    width: 40px;
    height: 40px;
    border: 2px solid var(--login-line, #E9E6D9);
    border-top-color: var(--login-acc, #C96442);
    border-radius: 50%;
    animation: provisioning-spin 0.8s linear infinite;
}

@keyframes provisioning-spin {
    to { transform: rotate(360deg); }
}

.provisioning-title {
    color: var(--login-ink, #141413);
    font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
    font-size: 20px;
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.25;
    margin: 0 0 10px;
}

.provisioning-status {
    color: var(--login-ink-3, #7B7873);
    font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
    font-size: 14px;
    margin: 0 0 24px;
    min-height: 1.4em;
}

.provisioning-progress {
    width: 100%;
    height: 3px;
    background: var(--login-line, #E9E6D9);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: 14px;
}

.provisioning-progress-bar {
    height: 100%;
    background: var(--login-acc, #C96442);
    border-radius: 2px;
    width: 0%;
    animation: provisioning-indeterminate 2s ease-in-out infinite;
}

@keyframes provisioning-indeterminate {
    0%   { width: 0%;  margin-left: 0; }
    50%  { width: 40%; margin-left: 30%; }
    100% { width: 0%;  margin-left: 100%; }
}

.provisioning-elapsed {
    color: var(--login-ink-4, #A8A69D);
    font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
    font-size: 12px;
    letter-spacing: 0;
    margin: 0;
}

.provisioning-error {
    margin-top: 20px;
    padding: 12px 14px;
    /* rgba(220, 38, 38, …) mirrors var(--b2-err) = #DC2626 at reduced alpha.
       `rgb(from var())` would be cleaner but isn't widely supported yet. */
    background: rgba(220, 38, 38, 0.06);
    border: 1px solid rgba(220, 38, 38, 0.20);
    border-radius: 8px;
    text-align: left;
}

.provisioning-error-text {
    color: var(--b2-err, #DC2626);
    font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
    font-size: 13px;
    line-height: 1.4;
    margin: 0 0 12px;
}

.provisioning-error-actions {
    display: flex;
    gap: 8px;
    justify-content: center;
}

.provisioning-btn {
    padding: 9px 16px;
    border-radius: 10px;
    font-family: var(--f-sans, 'Geist', -apple-system, system-ui, sans-serif);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.005em;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.provisioning-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--login-acc-focus, rgba(201, 100, 66, 0.22));
}

.provisioning-btn-retry {
    background: var(--login-acc, #E9A28E);
    color: var(--login-ink, #141413);
    border: 1px solid var(--login-acc, #E9A28E);
}

.provisioning-btn-retry:hover {
    background: var(--login-acc-ink, #DA7756);
    border-color: var(--login-acc-ink, #DA7756);
}

.provisioning-btn-cancel {
    background: var(--login-surface, #FFFFFF);
    color: var(--login-ink-2, #363632);
    border: 1px solid var(--login-line, #E9E6D9);
}

.provisioning-btn-cancel:hover {
    background: var(--login-canvas, #FAF9F5);
    color: var(--login-ink, #141413);
}

/* ── Right-click context menu (file tree) ─────────────────────────────────
   Floating overlay in the app's design language: theme surface, hairline
   border, overlay-tier 8px radius (same as toasts), single accent. Colors
   ride the GENERIC theme tokens (--white/--primary/--border-light/…) that
   both theme-b2-light and theme-plex-dark re-point, so the menu restyles
   with the theme; literal fallbacks are the B² palette. Hover = 2px accent
   rail (approved design B) — the same language as the tree's selected row. */
.file-ctx-menu {
    position: fixed;
    z-index: 10000;
    min-width: 132px;
    max-width: 320px;
    max-height: calc(100vh - 16px);
    overflow-y: auto;
    padding: 4px;
    /* Same plate as the right file/code panel (.file-browser-container):
       b2-light --b2-bg, plex-dark --bg-editor. */
    background: var(--b2-bg, var(--bg-editor, #FAFAF9));
    color: var(--primary-text, #111216);
    border: 1px solid var(--border-light, #E5E7EB);
    border-radius: 8px;
    box-shadow: 0 1px 2px rgba(17, 18, 22, 0.05), 0 12px 32px rgba(17, 18, 22, 0.16);
    font-family: var(--f-sans);
    font-size: 13px;
    font-weight: 400;
    line-height: 1.3;
    user-select: none;
    outline: none;
    transform-origin: top left;
    animation: file-ctx-in 110ms cubic-bezier(0.16, 1, 0.3, 1);
}
/* When the popup is pushed back from a viewport edge, showContextMenu()
   overrides transform-origin inline so it scales in from that edge. */
@keyframes file-ctx-in {
    from { opacity: 0; transform: translateY(-2px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .file-ctx-menu { animation: none; }
}
.file-ctx-menu-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 3px 12px 3px 10px;
    margin: 0;
    background: transparent;
    color: inherit;
    border: none;
    border-radius: 5px;
    text-align: left;
    cursor: default;
    font: inherit;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background .1s ease-out, color .1s ease-out;
}
/* Accent rail (approved design B): a 2px cursor on the hovered row's left
   edge — the same language as the tree's selected row and the card's
   why-item hover line. */
.file-ctx-menu-item::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 4px;
    bottom: 4px;
    width: 2px;
    border-radius: 2px;
    background: transparent;
    transition: background .1s ease-out;
}
.file-ctx-menu-item:hover:not(:disabled),
.file-ctx-menu-item:focus-visible {
    background: var(--primary-bg, rgba(42, 120, 214, 0.10));
    color: var(--primary-dark, #1E5AA8);
    outline: none;
}
.file-ctx-menu-item:hover:not(:disabled)::before,
.file-ctx-menu-item:focus-visible::before {
    background: var(--primary, #2A78D6);
}
.file-ctx-menu-item:hover:not(:disabled) .file-ctx-menu-icon,
.file-ctx-menu-item:focus-visible .file-ctx-menu-icon {
    color: var(--primary, #2A78D6);
}
.file-ctx-menu-item:disabled {
    opacity: 0.45;
    cursor: default;
}
.file-ctx-menu-item.danger {
    color: var(--sem-err, var(--b2-err, #DC2626));
}
.file-ctx-menu-item.danger .file-ctx-menu-icon {
    color: var(--sem-err, var(--b2-err, #DC2626));
}
.file-ctx-menu-item.danger:hover:not(:disabled),
.file-ctx-menu-item.danger:focus-visible {
    background: rgba(220, 38, 38, 0.08);
    color: var(--sem-err, var(--b2-err, #DC2626));
}
.file-ctx-menu-item.danger:hover:not(:disabled)::before,
.file-ctx-menu-item.danger:focus-visible::before {
    background: var(--sem-err, var(--b2-err, #DC2626));
}
.file-ctx-menu-item.danger:hover:not(:disabled) .file-ctx-menu-icon,
.file-ctx-menu-item.danger:focus-visible .file-ctx-menu-icon {
    color: var(--sem-err, var(--b2-err, #DC2626));
}
.file-ctx-menu-icon {
    width: 16px;
    flex: 0 0 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--secondary-text, #6B7280);
    transition: color .1s ease-out;
}
/* Icons ship at mixed intrinsic sizes (some 20px); pin them so they don't
   drive the row height. */
.file-ctx-menu-icon svg {
    width: 14px;
    height: 14px;
}
/* SVG icons (Download/Cut/Copy/Paste/Delete/...) sized to match the text
   glyphs (e.g. the Rename pencil) so mixed menus read as one icon set. */
.file-ctx-menu-icon svg {
    width: 12px;
    height: 12px;
    vertical-align: -1px;
}
.file-ctx-menu-label {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}
.file-ctx-menu-sep {
    height: 1px;
    margin: 3px 8px;
    background: var(--border-light, #E5E7EB);
}
/* Theme escape hatch — theme-b2-light's global focus rules
   ([tabindex]:focus-visible and *:focus-visible:not(...)) are !important and
   would repaint the focused popup with an accent border, a 3px halo and a
   4px radius. Inside the menu the focus affordance is the row's backdrop +
   accent rail (above); container and rows keep their own chrome. The :not()
   chain only lifts specificity above the theme's (0,4,0). */
.file-ctx-menu:focus-visible:not(input):not(textarea):not(select) {
    outline: none !important;
    border-color: var(--border-light, #E5E7EB) !important;
    border-radius: 8px !important;
    box-shadow: 0 1px 2px rgba(17, 18, 22, 0.05), 0 12px 32px rgba(17, 18, 22, 0.16) !important;
}
.file-ctx-menu-item:focus-visible:not(input):not(textarea):not(select) {
    outline: none !important;
    border-color: transparent !important;
    border-radius: 5px !important;
    box-shadow: none !important;
}

/* ── Template card: document-flow layout ───────────────────────────────────
   One white sheet, read like a lab report: identity header over a heavy
   rule, borderless hero figure (renders are self-labelled — compact baked
   scalar bar bottom-right, °C), a plain key-numbers strip, then sections
   in document flow. Monochrome by design. */
.tpl-poster { margin: -16px; width: calc(100% + 32px); background: var(--b2-bg, #FAFAF9); padding: 18px; container-type: inline-size; }
.tpl-doc { background: var(--b2-surface, #fff); border: 1px solid var(--b2-line, #E5E7EB); border-radius: 8px; padding: 24px 28px 28px; }
.tpl-hd { display: grid; gap: 8px; padding-bottom: 16px; border-bottom: 2px solid var(--b2-ink, #111216); }
.tpl-hd-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.tpl-hd-id { min-width: 0; }
.tpl-scope { display: block; font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--b2-ink-4, #9CA3AF); margin-bottom: 5px; }
.tpl-hd h1 { margin: 0; font-size: 25px; line-height: 1.12; font-weight: 720; letter-spacing: -0.01em; color: var(--b2-ink, #111216); overflow-wrap: anywhere; }
.tpl-desc, .tpl-desc2 { margin: 0; font-size: 13px; line-height: 1.55; color: var(--b2-ink-2, #4B5563); }
.tpl-metaline { margin: 0; font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 11.5px; font-weight: 500; color: var(--b2-ink-3, #6B7280); overflow-wrap: anywhere; }

/* Hero = V1 融纸: borderless, no letterbox fill — renders are white-bg, so
   they fuse with the sheet (a gray box read as "cropped + two-tone"). The
   figcaption keeps flex only for LEGACY cards whose json still carries
   hero_range (HTML colorbar right); new heroes are self-labelled. */
.tpl-heroF { margin: 20px 0 0; }
.tpl-heroF img { display: block; width: 100%; max-height: 480px; object-fit: contain; }
.tpl-heroF figcaption { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 11.5px; font-weight: 500; color: var(--b2-ink-3, #6B7280); padding: 8px 2px 2px; }
.tpl-heroF figcaption.ctr { justify-content: center; gap: 6px; }
.tpl-fno { font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em; color: var(--b2-ink, #111216); margin-right: 2px; }
.tpl-sno { font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 11px; font-weight: 700; color: var(--b2-ink-4, #9CA3AF); margin-right: 8px; }
.tpl-foot { margin-top: 26px; border-top: 2px solid var(--b2-ink, #111216); padding-top: 8px; font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 10.5px; color: var(--b2-ink-4, #9CA3AF); overflow-wrap: anywhere; }
.tpl-cb { display: inline-flex; align-items: center; gap: 6px; }
.tpl-cb .g { width: 110px; height: 7px; border: 1px solid var(--b2-line-2, #D1D5DB); border-radius: 2px; background: linear-gradient(90deg, #3B4CC0, #8DB0FE, #DDDDDD, #F49A7B, #B40426); }
.tpl-cb .n { font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 9.5px; color: var(--b2-ink-3, #6B7280); }

.tpl-btwrap { margin: 22px 0 4px; overflow-x: auto; }
.tpl-btcap { text-align: center; font-size: 11.5px; color: var(--b2-ink-3, #6B7280); margin-bottom: 8px; }
.tpl-booktabs { width: 100%; border-collapse: collapse; border-top: 2px solid var(--b2-ink, #111216); border-bottom: 2px solid var(--b2-ink, #111216); }
.tpl-booktabs th { border-bottom: 1px solid var(--b2-ink, #111216); text-align: left; font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--b2-ink-3, #6B7280); padding: 7px 12px 6px; }
.tpl-booktabs td { padding: 8px 12px; font-size: 12.5px; vertical-align: middle; }
.tpl-booktabs tbody tr + tr td { border-top: 1px solid var(--b2-line, #E5E7EB); }
.tpl-booktabs .bl { color: var(--b2-ink, #111216); font-weight: 600; white-space: nowrap; }
.tpl-booktabs .bv { font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-weight: 720; color: var(--b2-ink, #111216); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tpl-booktabs .bs { color: var(--b2-ink-3, #6B7280); font-size: 11.5px; }

.tpl-bar-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tpl-btn { display: inline-flex; align-items: center; justify-content: center; min-height: 30px; font-size: 12px; border-radius: 6px; padding: 6px 13px; white-space: nowrap; cursor: pointer; border: 1px solid var(--b2-line-2, #D1D5DB); background: var(--b2-surface, #fff); color: var(--b2-ink-2, #4B5563); font-family: inherit; transition: background .12s ease-out, border-color .12s ease-out; }
.tpl-ibtn { width: 30px; height: 30px; border-radius: 6px; border: 1px solid var(--b2-line-2, #D1D5DB); background: var(--b2-surface, #fff); color: var(--b2-ink-2, #4B5563); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background .12s ease-out; }
.tpl-ibtn:hover, .tpl-btn:hover { background: var(--b2-sunken, #F3F4F6); }
.tpl-ibtn.danger { color: var(--b2-err, #DC2626); border-color: rgba(220, 38, 38, 0.35); }
.tpl-ibtn.danger:hover { background: rgba(220, 38, 38, 0.06); }
.tpl-ibtn:focus-visible, .tpl-btn:focus-visible { outline: 2px solid var(--b2-acc-focus, rgba(42, 120, 214, 0.22)); outline-offset: 1px; }
.tpl-btn.primary { background: var(--b2-ink, #111216); border-color: var(--b2-ink, #111216); color: #fff; font-weight: 620; }
.tpl-btn.primary:hover { background: #2B2F36; border-color: #2B2F36; }

/* ── Case summary card (case-card.js) — soft-card skin (style review A,
      2026-08-05): rounded panel, status badge, 2×2 facts grid. Deliberately
      NOT the tpl-* academic skin — that stays exclusive to templates.
      SUPERSEDED 2026-08-07 by the report-cover skin below; the markup no
      longer emits cc-card/cc-top/cc-headline/cc-badge/cc-facts, only the
      shared rules here (cc-poster/cc-id/cc-sum/cc-actions/cc-btn) are
      still live. Unreferenced rules kept as the documented previous skin;
      sweep in a later cleanup pass. ──────────────────────────────────── */
.cc-poster { margin: -16px; width: calc(100% + 32px); background: var(--b2-bg, #FAFAF9); padding: 24px 18px; }
.cc-card { background: #fff; border: 1px solid var(--b2-line, #E5E7EB); border-radius: 14px; padding: 22px 24px; max-width: 680px; margin: 0 auto; box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06), 0 8px 24px rgba(15, 23, 42, 0.05);
  /* The app body is Geist Mono; the approved soft-card mock is sans-serif.
     Without this override the whole card (title, summary, buttons) inherits
     mono and looks nothing like the review sample ("太丑了" 2026-08-05).
     Mono stays only where the mock had it: .cc-id and .cc-fact .v. */
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Arial, sans-serif; }
.cc-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.cc-headline { min-width: 0; }
.cc-card h1 { margin: 0; font-size: 19px; line-height: 1.25; font-weight: 700; letter-spacing: -0.01em; color: var(--b2-ink, #111216); overflow-wrap: anywhere; }
.cc-id { font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 11px; color: var(--b2-ink-4, #9CA3AF); margin-top: 3px; overflow-wrap: anywhere; }
.cc-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; padding: 4px 10px; border-radius: 999px; white-space: nowrap; flex: none; }
.cc-badge .cc-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; display: inline-block; flex: none; }
.cc-badge.ok { background: #ECFDF5; color: #059669; border: 1px solid #A7F3D0; }
.cc-badge.fail { background: #FEF2F2; color: #DC2626; border: 1px solid #FECACA; }
.cc-badge.run { background: #FFFBEB; color: #D97706; border: 1px solid #FDE68A; }
.cc-badge.na { background: var(--b2-sunken, #F3F4F6); color: var(--b2-ink-3, #6B7280); border: 1px solid var(--b2-line, #E5E7EB); }
.cc-sum { font-size: 13.5px; line-height: 1.65; color: #374151; margin: 14px 0 0; }
.cc-nosummary { color: var(--b2-ink-4, #9CA3AF); font-style: italic; }
.cc-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--b2-line, #E5E7EB); border: 1px solid var(--b2-line, #E5E7EB); border-radius: 10px; overflow: hidden; margin-top: 16px; }
.cc-fact { background: #FAFBFC; padding: 10px 14px; min-width: 0; }
.cc-fact .k { font-size: 10.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--b2-ink-4, #9CA3AF); }
.cc-fact .v { font-size: 12.5px; font-weight: 400; color: var(--b2-ink, #111216); margin-top: 2px; font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); overflow-wrap: anywhere; }
.cc-actions { display: flex; gap: 8px; margin-top: 16px; flex-wrap: wrap; }
.cc-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 30px; font-size: 12.5px; font-weight: 500; border-radius: 8px; padding: 6px 14px; white-space: nowrap; cursor: pointer; border: 1px solid var(--b2-line-2, #D1D5DB); background: #fff; color: var(--b2-ink-2, #4B5563); font-family: inherit; transition: background .12s ease-out, border-color .12s ease-out; }
.cc-btn:hover { background: var(--b2-sunken, #F3F4F6); }
/* Soft-gold primary (G5, user-picked 2026-08-05): tinted platform gold —
   light gold fill, gold hairline, bronze text; hover deepens the tint. */
.cc-btn.primary { background: rgba(212, 175, 55, 0.14); border-color: rgba(212, 175, 55, 0.45); color: #8A6D1A; font-weight: 600; }
.cc-btn.primary:hover { background: rgba(212, 175, 55, 0.24); border-color: rgba(212, 175, 55, 0.6); }
.cc-btn:focus-visible { outline: 2px solid rgba(212, 175, 55, 0.35); outline-offset: 1px; }
@media (max-width: 560px) { .cc-facts { grid-template-columns: 1fr; } }
/* ── Case summary card — "report cover" skin (user-picked 2026-08-07,
      style review v3 direction 2; supersedes the soft-card skin above,
      whose card/badge/facts-grid rules are no longer referenced — the
      shared cc-poster/cc-id/cc-sum/cc-actions/cc-btn rules still apply):
      flat warm paper sheet, mono eyebrow with coloured status word (no
      badge pill), big title, gold hairline, full-width summary, and a
      title-block facts band — ruled grid cells (1px gaps over the line
      colour so vertical and horizontal seams join), labels pinned at
      their seams, values centered, 4 → 2×2 → 1 columns via container
      queries on the sheet. Fixture: static/dev_card_live.html. ───────── */
.cc-poster { padding: 24px 24px 28px; }
.cc-sheet { background: #FCFAF5; border: 1px solid #EAE4D6; border-radius: 10px; padding: 30px 40px 26px; font-family: var(--f-sans, 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif); }
.cc-eyebrow { font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 10.5px; letter-spacing: 0.1em; text-transform: uppercase; color: #8A6D1A; }
.cc-eyebrow .ok { color: #059669; }
.cc-eyebrow .fail { color: #DC2626; }
.cc-eyebrow .run { color: #D97706; }
.cc-eyebrow .na { color: var(--b2-ink-3, #6B7280); }
.cc-sheet h1 { margin: 10px 0 0; font-size: 26px; font-weight: 680; letter-spacing: -0.02em; line-height: 1.15; color: var(--b2-ink, #111216); overflow-wrap: anywhere; }
.cc-sheet .cc-id { margin-top: 6px; }
.cc-rule { height: 2px; margin-top: 18px; border-radius: 2px; background: linear-gradient(90deg, rgba(212, 175, 55, 0.85), rgba(212, 175, 55, 0.15) 55%, transparent); }
.cc-sheet .cc-sum { font-size: 14.5px; line-height: 1.75; max-width: none; margin: 16px 0 0; }
/* Summary bullets (user 2026-08-07: summary at the card bottom, one bullet
   per parameter/conclusion) — gold-ruled list, emphasised labels. */
.cc-sum-list { list-style: none; margin: 16px 0 0; padding: 0; border-left: 2px solid rgba(212, 175, 55, 0.55); }
.cc-sum-list li { font-size: 14px; line-height: 1.6; color: #374151; padding: 4px 0 4px 14px; overflow-wrap: anywhere; }
.cc-sum-list li strong { font-weight: 600; color: var(--b2-ink, #111216); }
.cc-sum-list + .cc-sum-list { margin-top: 6px; }
/* Title-block grid: shared column tracks, so when the band wraps on narrow
   panes the labels align vertically across rows (flex wrap gave each row its
   own widths — user 2026-08-07). Seams are 1px grid gaps showing the line
   colour through opaque paper cells, so vertical and horizontal seams join
   into one continuous ruled block. Column count steps 4 → 2×2 → 1 via
   container queries on the sheet; in 2×2 the long fields (solver, report)
   share the wide column and the short ones (created, variants) the narrow. */
.cc-sheet { container-type: inline-size; }
.cc-foot { display: grid; grid-template-columns: 1.6fr 1fr 1.4fr 1fr; gap: 1px; background: rgba(17, 18, 22, 0.09); font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-size: 13px; line-height: 1.7; color: var(--b2-ink, #111216); margin-top: 18px; border-top: 1px solid rgba(17, 18, 22, 0.09); border-bottom: 1px solid rgba(17, 18, 22, 0.09); }
@container (max-width: 920px) { .cc-foot { grid-template-columns: 1.55fr 1fr; } .cc-foot-item:nth-child(odd) { padding-left: 0; } }
@container (max-width: 500px) {
    .cc-foot { grid-template-columns: 1fr; }
    /* Stacked rows share one alignment axis: fixed-width labels, left-set
       values — the per-cell centered look only works side by side (user
       report 2026-08-07: "four rows, nothing lines up"). nth-child guards
       needed: BOTH container queries apply below 500px, and the 920px
       block's nth-child(odd) rule outranks a bare class selector, leaving
       even rows indented 14px. */
    .cc-foot-item,
    .cc-foot-item:nth-child(odd),
    .cc-foot-item:nth-child(even) { padding-left: 0; }
    .cc-foot .k { width: 74px; }
    /* Extra .cc-foot ancestor: the base centered .v rule sits AFTER these
       container blocks in source order and ties on specificity otherwise. */
    .cc-foot .cc-foot-item .v { text-align: left; }
}
.cc-foot-item { display: flex; align-items: baseline; min-width: 0; padding: 10px 12px 10px 14px; background: #FCFAF5; }
.cc-foot-item:first-child { padding-left: 0; }
.cc-foot-item:last-child { padding-right: 0; }
.cc-foot .k { flex: none; font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--b2-ink-4, #9CA3AF); }
.cc-foot-item .v { flex: 1 1 auto; min-width: 0; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 8px; }
.cc-sheet .cc-actions { margin-top: 18px; }
/* ── end TRY-ON ─────────────────────────────────────────────────────── */
.tpl-btn.danger { color: var(--b2-err, #DC2626); border-color: rgba(220, 38, 38, 0.35); }
.tpl-btn.danger:hover { background: rgba(220, 38, 38, 0.06); }

.tpl-sec { margin-top: 20px; border-top: 1px solid var(--b2-line, #E5E7EB); padding-top: 12px; min-width: 0; }
.tpl-sec > h3 { margin: 0 0 8px; font-size: 13.5px; font-weight: 720; letter-spacing: 0; color: var(--b2-ink, #111216); }
.tpl-sec > h3 code { font-size: .85em; }

.tpl-md { font-size: 13px; line-height: 1.58; color: var(--b2-ink-2, #4B5563); }
.tpl-md p { margin: 6px 0; max-width: 68ch; }
.tpl-md ol, .tpl-md ul { padding-left: 20px; margin: 6px 0; }
.tpl-md li { margin: 0 0 10px; }
.tpl-md code { font-family: var(--f-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); background: var(--b2-sunken, #F3F4F6); border: 1px solid var(--b2-line, #E5E7EB); border-radius: 4px; padding: 0 4px; font-size: 11.5px; }
.tpl-md table { border-collapse: collapse; width: 100%; margin: 8px 0; }
.tpl-md th, .tpl-md td { border: 1px solid var(--b2-line, #E5E7EB); padding: 6px 12px; text-align: left; font-size: 12.5px; color: var(--b2-ink-2, #4B5563); }
.tpl-md th { background: var(--b2-sunken, #F3F4F6); font-weight: 600; }
.tpl-sec.cols2 .tpl-md > ol, .tpl-sec.cols2 .tpl-md > ul { columns: 2; column-gap: 34px; }
.tpl-sec.cols2 .tpl-md > ol > li, .tpl-sec.cols2 .tpl-md > ul > li { break-inside: avoid; }

.tpl-figrow { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 20px; }
.tpl-figrow .tpl-fig:last-child:nth-child(odd) { grid-column: 1 / -1; }
.tpl-fig { margin: 0; min-width: 0; }
.tpl-fig img { display: block; width: 100%; height: auto; border: 1px solid var(--b2-line, #E5E7EB); }
.tpl-fig figcaption { font-size: 11.5px; line-height: 1.5; color: var(--b2-ink-3, #6B7280); padding: 6px 2px 0; }

.tpl-invite { margin-top: 20px; display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; background: var(--b2-sunken, #F3F4F6); border: 1px dashed var(--b2-line-2, #D1D5DB); border-radius: 6px; padding: 16px 18px; }
.tpl-invite-txt { display: grid; gap: 4px; flex: 1 1 320px; min-width: 0; }
.tpl-invite-txt strong { font-size: 13.5px; color: var(--b2-ink, #111216); }
.tpl-invite-txt span { font-size: 12.5px; line-height: 1.55; color: var(--b2-ink-2, #4B5563); }
.tpl-sec.tpl-gh h3 { color: var(--b2-ink-4, #9CA3AF); }
.tpl-gh-l { height: 9px; border-radius: 4px; background: var(--b2-sunken, #F3F4F6); margin: 10px 0; }

.tpl-config { margin-top: 20px; border: 1px solid var(--b2-line, #E5E7EB); border-radius: 6px; overflow: hidden; background: var(--b2-surface, #fff); }
.tpl-config summary { cursor: pointer; padding: 8px 12px; font-size: 12px; font-weight: 600; color: var(--b2-ink-2, #4B5563); background: var(--b2-sunken, #F3F4F6); }
.tpl-config summary:focus-visible { outline: 2px solid var(--b2-acc, #2A78D6); outline-offset: -2px; }
.tpl-config .tpl-md { padding: 12px 16px; }

@container (max-width: 640px) {
  .tpl-poster { padding: 12px; }
  .tpl-doc { padding: 16px 16px 20px; }
  .tpl-figrow { grid-template-columns: 1fr; }
  .tpl-sec.cols2 .tpl-md > ol, .tpl-sec.cols2 .tpl-md > ul { columns: 1; }
}
.file-tree-item.tpl-tip-host { position: relative; }
.tpl-tip { display: none; position: absolute; left: 24px; top: calc(100% + 2px); z-index: 30; background: #1e293b; color: #f1f5f9; font-size: 11.5px; line-height: 1.45; padding: 6px 9px; border-radius: 6px; max-width: 230px; white-space: normal; box-shadow: 0 6px 20px rgba(17, 18, 22, 0.35); pointer-events: none; }
.file-tree-item.tpl-tip-host:hover .tpl-tip { display: block; }
.tpl-desc-edit { border: 0; background: none; color: var(--b2-ink-4, #9CA3AF); cursor: pointer; font-size: 12px; padding: 0 3px; }
.tpl-desc-edit:hover { color: var(--b2-acc, #2A78D6); }
.tpl-desc-add { border: 1px dashed var(--b2-line-2, #D1D5DB); background: none; color: var(--b2-ink-3, #6B7280); cursor: pointer; font-size: 12px; border-radius: 6px; padding: 4px 10px; font-family: inherit; }
.tpl-desc-add:hover { color: var(--b2-acc, #2A78D6); border-color: var(--b2-acc-line, rgba(42, 120, 214, 0.28)); }
.tpl-desc-editor { margin: 0 0 4px; max-width: 56ch; }
.tpl-desc-editor textarea { width: 100%; box-sizing: border-box; padding: 7px 10px; border: 1px solid var(--b2-line-2, #D1D5DB); border-radius: 6px; font-size: 13px; font-family: inherit; resize: vertical; }
.tpl-desc-editor textarea:focus { outline: none; border-color: var(--b2-acc, #2A78D6); box-shadow: 0 0 0 3px var(--b2-acc-focus, rgba(42, 120, 214, 0.22)); }
.tpl-desc-editor-row { display: flex; gap: 8px; margin-top: 6px; }

/* ── Save-as-template dialog (b2 three-part: head / body / sunken foot) ── */
.tpl-save-overlay { position: fixed; inset: 0; background: rgba(17, 18, 22, 0.30); z-index: 10000; display: flex; align-items: center; justify-content: center; }
.tpl-save-box { background: var(--b2-surface, #fff); border: 1px solid var(--b2-line, #E5E7EB); border-radius: 6px; box-shadow: 0 6px 20px rgba(17, 18, 22, 0.08); width: min(420px, 92vw); font-size: 13px; overflow: hidden; font-family: var(--f-sans); }
.tpl-save-head { padding: 14px 18px 12px; border-bottom: 1px solid var(--b2-line, #E5E7EB); }
.tpl-save-title { font-size: 14px; font-weight: 600; color: var(--b2-ink, #111216); letter-spacing: -.005em; }
.tpl-save-sub { color: var(--b2-ink-3, #6B7280); margin-top: 3px; font-size: 12.5px; }
.tpl-save-sub code { font-family: var(--f-mono, ui-monospace, Menlo, Consolas, monospace); font-size: 11px; background: var(--b2-user-code-bg, #FBF1E6); color: var(--b2-user-code-fg, #B55B00); border-radius: 4px; padding: 1px 5px; }
.tpl-save-body { padding: 14px 18px 4px; }
.tpl-save-label { display: block; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--b2-ink-3, #6B7280); margin: 0 0 5px; }
.tpl-save-label .opt { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--b2-ink-4, #9CA3AF); }
.tpl-save-body input[type="text"], .tpl-save-body textarea { width: 100%; box-sizing: border-box; padding: 7px 10px; border: 1px solid var(--b2-line-2, #D1D5DB); border-radius: 6px; font-size: 13px; font-family: inherit; color: var(--b2-ink, #111216); background: var(--b2-surface, #fff); margin-bottom: 13px; transition: border-color .12s ease-out, box-shadow .12s ease-out; }
.tpl-save-body input:focus, .tpl-save-body textarea:focus { outline: none; border-color: var(--b2-acc, #2A78D6); box-shadow: 0 0 0 3px var(--b2-acc-focus, rgba(42, 120, 214, 0.22)); }
.tpl-save-body textarea { resize: vertical; }
.tpl-save-body ::placeholder { color: var(--b2-ink-4, #9CA3AF); }
.tpl-save-chk { display: flex; align-items: center; gap: 8px; color: var(--b2-ink-2, #4B5563); margin: 1px 0 8px; cursor: pointer; }
.tpl-save-chk input { accent-color: var(--b2-acc, #2A78D6); width: 14px; height: 14px; }
.tpl-save-err { display: none; color: var(--b2-err, #DC2626); margin: 0 0 8px; font-size: 12.5px; }
.tpl-save-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 18px 14px; background: var(--b2-bg, #FAFAF9); border-top: 1px solid var(--b2-line, #E5E7EB); margin-top: 10px; }
.tpl-save-btn { padding: 6px 14px; border: 1px solid var(--b2-line-2, #D1D5DB); background: var(--b2-surface, #fff); color: var(--b2-ink-2, #4B5563); border-radius: 6px; font-size: 13px; font-family: inherit; cursor: pointer; transition: background .12s ease-out; }
.tpl-save-btn:hover { background: var(--b2-sunken, #F3F4F6); }
.tpl-save-btn.primary { border-color: var(--b2-acc, #2A78D6); background: var(--b2-acc, #2A78D6); color: #fff; font-weight: 500; }
.tpl-save-btn.primary:hover { background: var(--b2-acc-hover, #1F61B8); border-color: var(--b2-acc-hover, #1F61B8); }
.tpl-save-btn:focus-visible { outline: 2px solid var(--b2-acc-focus, rgba(42, 120, 214, 0.22)); outline-offset: 1px; }
