/* 全局样式 */
:root {
    --primary-color: #3B82F6;
    --secondary-color: #007bff;
    --accent-color: #1a1a1a;
    --text-color: #ffffff;
    --light-text: #b0b0b0;
    --card-bg: #2a2a2a;
    --hover-color: rgba(59, 130, 246, 0.2);
    --text-primary: #ffffff;
    --text-secondary: #b0b0b0;
    --border-color: #3a3a3a;
    --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 8px 16px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 12px 24px rgba(0, 0, 0, 0.5);
    --border-radius: 12px;
    --transition: all 0.3s ease;
}

@keyframes processing-pulse {
    0%, 100% {
        opacity: 1;
        box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);
    }
    50% {
        opacity: 0.85;
        box-shadow: 0 0 0 8px rgba(59, 130, 246, 0);
    }
}

@keyframes processing-glow {
    0%, 100% {
        border-color: rgba(59, 130, 246, 0.5);
    }
    50% {
        border-color: rgba(59, 130, 246, 1);
    }
}

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

html, body {
    font-family: 'PingFang SC', 'Microsoft YaHei', -apple-system, BlinkMacSystemFont, sans-serif;
    background: #121212;
    color: var(--text-color);
    min-height: 100%;
    overflow-x: hidden;
    overflow-y: auto;
    /* 始终预留滚动条空间，防止滚动条出现/消失导致页面宽度抖动（grid 列数跳变引发的高度循环） */
    scrollbar-gutter: stable;
}

/* 导航栏样式 */
.navbar {
    background-color: rgba(26, 26, 26, 0.95);
    backdrop-filter: blur(10px);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
    border-bottom: 1px solid rgba(59, 130, 246, 0.2);
    transition: all 0.3s ease;
    position: relative;
    z-index: 1000;
}

/* 汉堡按钮样式 */
.navbar-toggler {
    border: 2px solid var(--primary-color) !important;
    border-radius: 8px !important;
    padding: 0.75rem !important;
    transition: all 0.3s ease !important;
}

.navbar-toggler:hover {
    background-color: rgba(59, 130, 246, 0.1) !important;
    transform: scale(1.05) !important;
}

.navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%233B82F6' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") !important;
    width: 1em !important;
    height: 1em !important;
}

.navbar:hover {
    box-shadow: 0 2px 15px rgba(59, 130, 246, 0.3);
}

.navbar-brand {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--primary-color);
    transition: all 0.3s ease;
}

.navbar-brand:hover {
    color: var(--primary-color);
}

.nav-link {
    font-size: 1rem;
    font-weight: 500;
    margin-right: 1.5rem;
    color: var(--text-color) !important;
    transition: all 0.3s ease;
}

.nav-link:hover {
    color: var(--primary-color) !important;
}

/* ===== 导航滑动指示条 ===== */
.jm-nav-primary {
    position: relative;
}

/* 指示条：底部彩色滑动条 */
.jm-nav-indicator {
    position: absolute;
    bottom: 2px;
    left: 0;
    height: 2px;
    width: 0;
    background: linear-gradient(90deg, #818cf8, #6366f1);
    border-radius: 2px;
    opacity: 0;
    transition: transform 0.35s cubic-bezier(0.4, 0.0, 0.2, 1),
                width 0.35s cubic-bezier(0.4, 0.0, 0.2, 1),
                opacity 0.25s ease;
    pointer-events: none;
    box-shadow: 0 0 8px rgba(129, 140, 248, 0.5);
}

/* active 状态：文字变主题色 */
.jm-nav-primary .nav-link.jm-nav-active {
    color: var(--primary-color) !important;
    font-weight: 600;
}

/* 平板端以下折叠时隐藏指示条 */
@media (max-width: 767.98px) {
    .jm-nav-indicator {
        display: none;
    }
}

/* 内容容器 */
.content-container {
    animation: fadeInUp 0.6s ease-out;
    display: flex;
    gap: 1rem;
    height: 100%;
    width: 100%;
    padding: 1rem 1rem 1rem 2rem;
}

/* 容器样式 */
.container {
    height: 100%;
    width: 100%;
    max-width: 100%;
    padding: 0 1rem 0 1rem;
}

.operation-area {
    width: 25%;
    background-color: var(--card-bg);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-md);
    padding: 2rem;
    padding-bottom: 100px;
    border: 1px solid var(--border-color);
    height: 100%;
    margin-top: 1rem;
    overflow-y: auto;
}

/* 小屏幕设备适配 */
@media (max-width: 768px) {
    .operation-area {
        width: 40%;
    }
    
    .task-area {
        width: 60%;
    }
}

@media (max-width: 480px) {
    .operation-area {
        width: 100%;
        margin-bottom: 1rem;
    }
    
    .task-area {
        width: 100%;
    }
    
    .content-container {
        flex-direction: column;
    }
}

.task-area {
    flex: 1;
    background-color: var(--card-bg);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-md);
    padding: 1.5rem;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    height: 100%;
    margin-top: 1rem;
}

/* 展示区域 */
.showcase-section {
    text-align: center;
    margin-bottom: 1rem;
}

.showcase-title {
    font-size: 2.5rem;
    font-weight: bold;
    color: var(--text-primary);
    margin-bottom: 1rem;
}

.showcase-subtitle {
    font-size: 1.2rem;
    color: var(--text-secondary);
    margin-bottom: 2rem;
    max-width: 800px;
    margin-left: auto;
    margin-right: auto;
}

/* 操作框样式 */
.operation-box {
    background-color: var(--card-bg);
    padding: 2rem;
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-md);
    margin-bottom: 2rem;
    border: 1px solid var(--border-color);
}

/* 提示词输入区域 */
.prompt-input {
    position: relative;
    margin-bottom: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.upload-icon {
    font-size: 1rem;
    font-weight: bold;
    color: var(--primary-color);
    width: auto;
    height: 48px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--primary-color);
    cursor: pointer;
    flex-shrink: 0;
    line-height: 36px;
    padding: 0 1rem;
    margin: 0;
    text-align: center;
    align-self: flex-start;
    transition: var(--transition);
}

.upload-icon:hover {
    border-color: var(--primary-color);
}

.input-container {
    flex: 1;
    width: 100%;
}

.input-container textarea {
    width: 100%;
    min-height: 100px;
    max-height: 200px;
    padding: 1rem;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    font-size: 1rem;
    line-height: 1.5;
    transition: var(--transition);
    resize: none;
    overflow-y: auto;
    background-color: #3a3a3a;
    color: var(--text-color);
    box-sizing: border-box;
    font-family: inherit;
}

.input-container textarea:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
}

/* 倒计时圆圈进度条 - 方案1：双层渐变圆环 */
.countdown-overlay {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    flex: 1;
    min-height: 120px;
    background: radial-gradient(ellipse at center, rgba(99,102,241,0.06) 0%, rgba(0,0,0,0) 70%);
    border-radius: 8px;
    margin: 0 auto 0.5rem;
    box-sizing: border-box;
    position: relative;
    overflow: hidden;
}

/* 原 .countdown-overlay::before（conic-gradient 浅紫光斑 + cd-rotate 8s 旋转）已于 2026-09-16 移除：
   它在倒计时圆环背后叠了一层持续自转的浅色方块，用户反馈干扰阅读，处理中卡片只保留圆环进度 + 剩余时间。
   如需重新加回，请同步恢复 @keyframes cd-rotate（当前已无任何引用）。 */

.countdown-overlay svg {
    flex-shrink: 0;
    width: 100px;
    height: 100px;
    position: relative;
    z-index: 1;
    filter: drop-shadow(0 0 6px rgba(99,102,241,0.4));
}

.countdown-overlay .cd-arc {
    transition: stroke-dashoffset 0.5s ease-out;
}

.countdown-overlay .cd-arc-inner {
    transition: stroke-dashoffset 0.5s ease-out;
}

.task-item.processing .countdown-overlay .cd-time {
    font-variant-numeric: tabular-nums;
}

.image-preview-thumbnail {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    min-height: 60px;
    margin-bottom: 0.5rem;
}

.thumbnail-item {
    position: relative;
    width: 60px;
    height: 60px;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--border-color);
}

.thumbnail-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.thumbnail-item .remove-btn {
    position: absolute;
    top: -5px;
    right: -5px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #dc3545;
    color: white;
    border: none;
    font-size: 12px;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    transition: all 0.2s ease;
}

.thumbnail-item .remove-btn:hover {
    background-color: #c82333;
    transform: scale(1.1);
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4);
}

/* 选项区域 */
.options {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.option-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.option-label {
    font-size: 0.9rem;
    color: var(--text-secondary);
    white-space: nowrap;
    min-width: 56px;
}

.btn-group {
    display: inline-flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.btn-group-sm .btn-option {
    padding: 0.4rem 0.8rem;
    font-size: 0.85rem;
}

.btn-option {
    padding: 0.5rem 1rem;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background-color: transparent;
    color: var(--text-secondary);
    font-size: 0.9rem;
    cursor: pointer;
    transition: all 0.25s ease;
    white-space: nowrap;
    user-select: none;
}

.btn-option:hover {
    border-color: var(--primary-color);
    color: var(--text-color);
    background-color: rgba(59, 130, 246, 0.08);
}

.btn-option.active {
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    border-color: transparent;
    color: white;
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.35);
}

.option-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.option-group select {
    padding: 0.75rem 1rem;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    font-size: 1rem;
    transition: var(--transition);
    background-color: #3a3a3a;
    color: var(--text-color);
}

.option-group select:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
}

/* 执行按钮区域 */
.execute-section {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 1rem;
}

.free-times {
    font-size: 0.9rem;
    color: var(--text-secondary);
}

.execute-btn {
    width: 100%;
    height: 50px;
    border-radius: 8px;
    background-color: var(--primary-color);
    border: none;
    color: white;
    font-size: 1rem;
    font-weight: bold;
    cursor: pointer;
    transition: var(--transition);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
    padding: 0 2rem;
    margin-top: 1rem;
    position: sticky;
    bottom: 2rem;
    z-index: 1;
}

.execute-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(59, 130, 246, 0.4);
    background-color: #2563eb;
}

/* 提交中状态 - 按钮变为进度条 */
.execute-btn.loading {
    overflow: hidden;
    background-color: #1e3a5f;
    cursor: not-allowed;
    transform: none;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
    color: rgba(255, 255, 255, 0.9);
}

.execute-btn.loading:hover {
    transform: none;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
    background-color: #1e3a5f;
}

.execute-btn .btn-progress-bar {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, #3B82F6, #6366f1, #8b5cf6);
    border-radius: 8px;
    transition: width 0.3s ease-out;
    z-index: 0;
}

.execute-btn .btn-progress-bar::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
    animation: progress-shimmer 1.5s ease-in-out infinite;
    border-radius: 8px;
}

@keyframes progress-shimmer {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

.execute-btn .btn-progress-text {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}

.execute-btn .btn-progress-text .spinner {
    width: 16px;
    height: 16px;
    border: 2px solid rgba(255,255,255,0.3);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

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

/* 模态框样式 */
.modal-content {
    background-color: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(59, 130, 246, 0.2);
    overflow: hidden;
    animation: modalFadeIn 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    position: relative;
}

.modal-content::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(90deg, #3B82F6, #6c757d, #28a745, #ffc107);
    border-radius: 20px 20px 0 0;
}

.modal-header {
    border-bottom: 1px solid var(--border-color);
    padding: 2rem 2rem 1rem;
    background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(59, 130, 246, 0.05));
    position: relative;
}

.modal-title {
    color: var(--text-color);
    font-weight: 700;
    font-size: 1.5rem;
    text-align: center;
    width: 100%;
    margin: 0;
}

.modal-body {
    color: var(--text-color);
    padding: 2rem;
}

.modal-footer {
    border-top: 1px solid var(--border-color);
    padding: 1rem 2rem 2rem;
    background: linear-gradient(135deg, rgba(59, 130, 246, 0.05), rgba(59, 130, 246, 0.1));
    justify-content: center;
    gap: 1rem;
}

/* 模态框动画 */
@keyframes modalFadeIn {
    from {
        opacity: 0;
        transform: translateY(-30px) scale(0.9);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* 动画效果 */
@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* 任务区域样式 */
.view-toggle {
    display: flex;
    gap: 0.5rem;
}

.view-toggle button {
    padding: 0.5rem 1rem;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background-color: #3a3a3a;
    color: var(--text-color);
    cursor: pointer;
    transition: var(--transition);
}

.view-toggle button.active {
    background-color: var(--primary-color);
    border-color: var(--primary-color);
}

/* 列表模式 */
.task-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.task-list.grid {
    position: relative;
    display: grid;
    /* 卡片至少 180px 并弹性拉伸填满行宽，避免列右侧空隙 */
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 24px;
}

/* 2K/4K 大屏：图片卡片同步放大（虚拟滚动按容器宽度计算列数，自动适配） */
@media (min-width: 1600px) {
    .task-list.grid {
        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
        gap: 28px;
    }
}

@media (min-width: 2200px) {
    .task-list.grid {
        grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
        gap: 32px;
    }
}

.task-list.grid .virtual-scroll-spacer,
.task-list.grid #virtualScrollSpacer {
    grid-column: 1 / -1;
}

.task-item {
    background: #3a3a3a;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 1rem;
    box-shadow: var(--shadow-sm);
    transition: transform 0.2s ease;
}

.task-list.grid .task-item {
    display: flex;
    flex-direction: column;
    padding: 0.75rem;
}

.task-item:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}

.task-item.processing {
    animation: processing-pulse 2s ease-in-out infinite, processing-glow 1.5s ease-in-out infinite;
    border-width: 2px;
}

.task-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
}

.task-list.grid .task-header {
    display: none;
}

.task-id {
    font-size: 0.85rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.task-status {
    font-size: 0.8rem;
    padding: 0.25rem 0.75rem;
    border-radius: 12px;
    font-weight: 500;
}

.task-status.completed {
    background-color: rgba(16, 185, 129, 0.1);
    color: #10b981;
}

.task-status.processing {
    background-color: rgba(59, 130, 246, 0.1);
    color: #3b82f6;
}

.task-prompt {
    font-size: 0.9rem;
    color: var(--text-color);
    margin-bottom: 0.75rem;
    line-height: 1.4;
}

.task-list.grid .task-prompt {
    display: none;
}

.task-thumbnail {
    position: relative;  /* 备注角标（absolute）以缩略图为定位基准，显示在其左下角 */
    border-radius: 8px;
    overflow: hidden;
    margin-top: 0.5rem;
}

.task-list.grid .task-thumbnail {
    flex: 1;
    margin-top: 0;
    margin-bottom: 0.75rem;
}

.task-thumbnail img {
    width: 100%;
    height: 80px;
    object-fit: cover;
}

.task-list.grid .task-thumbnail img {
    width: 100%;
    height: 180px;
    object-fit: cover;
}

.task-list.grid .task-content {
    display: flex;
    flex-direction: column;
    height: 100%;
    position: relative;
}

/* 任务卡片预览区左上角模型别名小字 */
.model-alias {
    position: absolute;
    top: 6px;
    left: 6px;
    font-size: 10px;
    line-height: 1.2;
    color: rgba(255, 255, 255, 0.85);
    background: rgba(0, 0, 0, 0.5);
    padding: 2px 6px;
    border-radius: 4px;
    z-index: 2;
    pointer-events: none;
    max-width: calc(100% - 12px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.task-list.grid .task-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;
    font-size: 0.75rem;
    color: var(--text-secondary);
}

.task-list.grid .task-status {
    font-size: 0.7rem;
    padding: 0.2rem 0.6rem;
    min-width: 50px;
    text-align: center;
    white-space: nowrap;
}

.task-list.grid .task-buttons {
    display: flex;
    gap: 6px;
    margin-top: auto;
}

.task-list.grid .view-btn, .task-list.grid .copy-btn, .task-list.grid .note-btn {
    flex: 1;
    padding: 0.35rem;
    border: none;
    border-radius: 6px;
    font-size: 0.7rem;
    cursor: pointer;
    transition: var(--transition);
}

.task-list.grid .note-btn {
    background-color: #6366f1;
    color: white;
}

.task-list.grid .note-btn:hover {
    background-color: #4f46e5;
}

.task-list.grid .view-btn {
    background-color: var(--primary-color);
    color: white;
}

.task-list.grid .view-btn:hover {
    background-color: #2563eb;
}

.task-list.grid .copy-btn {
    background-color: #10b981;
    color: white;
}

.task-list.grid .copy-btn:hover {
    background-color: #059669;
}

.task-list.grid .delete-btn {
    flex: 1;
    padding: 0.35rem;
    border: none;
    border-radius: 6px;
    font-size: 0.7rem;
    cursor: pointer;
    transition: var(--transition);
    background-color: #ef4444;
    color: white;
}

.task-list.grid .delete-btn:hover {
    background-color: #dc2626;
}

.task-progress {
    width: 100%;
    height: 6px;
    background-color: #4a4a4a;
    border-radius: 3px;
    overflow: hidden;
    margin-top: 0.5rem;
}

.task-list.grid .task-progress {
    margin-top: 0.5rem;
}

.progress-bar {
    height: 100%;
    background-color: #3b82f6;
    border-radius: 3px;
    transition: width 0.3s ease;
}

/* 响应式设计 */
@media (max-width: 380px) {
    .navbar {
        background-color: rgba(255, 255, 255, 0.95);
        backdrop-filter: blur(10px);
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        border-bottom: 1px solid rgba(0, 123, 255, 0.1);
    }
    
    .content-container {
        margin-top: 2rem;
        margin-bottom: 2rem;
    }
    
    .showcase-title {
        font-size: 2rem;
    }
    
    .features-section {
        grid-template-columns: 1fr;
    }
    
    .operation-box {
        padding: 1.5rem;
    }
    
    .options {
        flex-direction: column;
        align-items: stretch;
    }

    .option-row {
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
    }

    .option-label {
        min-width: auto;
    }

    .btn-group {
        justify-content: flex-start;
    }
    
    .option-group {
        justify-content: space-between;
    }
    
    .option-group select {
        flex: 1;
    }
}

.task-float-btn {
    display: none;
    position: fixed;
    right: 0;
    top: 80px;
    padding: 12px 16px;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    color: white;
    border: none;
    border-radius: 8px 0 0 8px;
    box-shadow: -2px 0 10px rgba(0, 0, 0, 0.15);
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    z-index: 1000;
    transition: all 0.3s ease;
    writing-mode: vertical-rl;
    letter-spacing: 2px;
}

.task-float-btn:hover {
    padding-right: 20px;
    box-shadow: -4px 0 15px rgba(0, 0, 0, 0.2);
}

.task-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1001;
}

.task-overlay.active {
    display: block;
}

.task-sidebar-mobile {
    display: block;
    position: fixed;
    top: 0;
    right: -400px;
    width: 400px;
    height: 100%;
    background: var(--card-bg);
    box-shadow: -2px 0 10px rgba(0, 0, 0, 0.3);
    z-index: 1002;
    transition: right 0.3s ease;
    overflow-y: auto;
    border-left: 1px solid var(--border-color);
}

.task-sidebar-mobile.active {
    right: 0;
}

.task-sidebar-mobile .card {
    border-radius: 0;
    height: 100%;
    background-color: #1a1a1a;
}

.task-sidebar-mobile .card-header {
    position: sticky;
    top: 0;
    z-index: 1;
    background-color: #2a2a2a;
    border-bottom: 1px solid #3a3a3a;
}

.task-sidebar-mobile .close-btn {
    position: absolute;
    top: 1rem;
    right: 1rem;
    background: rgba(255, 255, 255, 0.2);
    border: none;
    color: white;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.task-sidebar-mobile .close-btn:hover {
    background: rgba(255, 255, 255, 0.3);
}

.task-sidebar-mobile .task-list.grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
}

.task-sidebar-mobile .task-list.grid .task-item {
    background: #3a3a3a;
    border: 1px solid #3a3a3a;
    border-radius: 12px;
    padding: 0.75rem;
}

.task-sidebar-mobile .task-list.grid .view-btn {
    background-color: var(--primary-color);
    color: white;
}

.task-sidebar-mobile .task-list.grid .copy-btn {
    background-color: #10b981;
    color: white;
}

.task-sidebar-mobile .task-list.grid .task-content {
    display: flex;
    flex-direction: column;
    height: 100%;
    position: relative;
}

/* 任务卡片预览区左上角模型别名小字 */
.model-alias {
    position: absolute;
    top: 6px;
    left: 6px;
    font-size: 10px;
    line-height: 1.2;
    color: rgba(255, 255, 255, 0.85);
    background: rgba(0, 0, 0, 0.5);
    padding: 2px 6px;
    border-radius: 4px;
    z-index: 2;
    pointer-events: none;
    max-width: calc(100% - 12px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.task-sidebar-mobile .task-list.grid .task-thumbnail {
    flex: 1;
    margin-top: 0;
    margin-bottom: 0.75rem;
    aspect-ratio: 1/1;
}

.task-sidebar-mobile .task-list.grid .task-thumbnail img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.task-sidebar-mobile .task-list.grid .task-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.task-sidebar-mobile .task-list.grid .task-buttons {
    display: flex;
    gap: 6px;
    margin-top: auto;
}

.task-sidebar-mobile .task-list.grid .view-btn, .task-sidebar-mobile .task-list.grid .copy-btn {
    flex: 1;
    padding: 0.35rem;
    border: none;
    border-radius: 6px;
    font-size: 0.7rem;
    cursor: pointer;
    transition: background-color 0.2s;
}

.task-sidebar-mobile .task-list.grid .view-btn {
    background-color: var(--primary-color);
    color: white;
}

.task-sidebar-mobile .task-list.grid .view-btn:hover {
    background-color: #2563eb;
}

.task-sidebar-mobile .task-list.grid .copy-btn {
    background-color: #10b981;
    color: white;
}

.task-sidebar-mobile .task-list.grid .copy-btn:hover {
    background-color: #059669;
}

.task-sidebar-mobile .task-list.grid .delete-btn {
    flex: 1;
    padding: 0.35rem;
    border: none;
    border-radius: 6px;
    font-size: 0.7rem;
    background-color: #dc3545;
    color: white;
    cursor: pointer;
    transition: background-color 0.2s;
}

.task-sidebar-mobile .task-list.grid .delete-btn:hover {
    background-color: #dc2626;
}

@media (max-width: 480px) {
    .task-float-btn {
        display: block !important;
    }

    .task-area {
        display: none !important;
    }
}

/* 上传素材预览项 */
.preview-container {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    min-height: 10px;
}

.preview-item {
    position: relative;
    width: 80px;
    height: 80px;
    flex-shrink: 0;
    border-radius: 6px;
    overflow: hidden;
    background-color: var(--bg-secondary, #f3f4f6);
    border: 1px solid var(--border-color, #e5e7eb);
}

.preview-item img,
.preview-item video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.preview-item audio {
    width: 100%;
    height: 32px;
}

.preview-item .remove-btn {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background-color: rgba(0, 0, 0, 0.6);
    color: #fff;
    border: none;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}

.preview-item .remove-btn:hover {
    background-color: rgba(220, 38, 38, 0.9);
}

/* ========================================
   即梦风格 - AI 视频创作页面（jm- 前缀）
   ======================================== */

/* 页面容器：覆盖默认 content-container 的 flex 布局，改为居中单列。
   宽度自适应：4K(3840px) 屏利用大部分宽度，上限 2560px 防止超宽屏卡片过度拉伸 */
.jm-page {
    width: 100%;
    max-width: 2560px;
    margin: 0 auto;
    padding: 2rem clamp(0.75rem, 2.5vw, 3rem) 4rem;
    min-height: calc(100vh - 60px);
}

/* 顶部标题区 */
.jm-hero {
    text-align: center;
    margin-bottom: 2rem;
    animation: fadeInUp 0.6s ease-out;
}

.jm-tutorial-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: rgba(129, 140, 248, 0.12);
    border: 1px solid rgba(129, 140, 248, 0.35);
    border-radius: 12px;
    color: #a5b4fc;
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
    margin-left: auto;
    align-self: center;
    white-space: nowrap;
}

.jm-tutorial-btn:hover {
    background: rgba(129, 140, 248, 0.22);
    border-color: rgba(129, 140, 248, 0.6);
    color: #c7d2fe;
}

/* 使用教程模态框 */
.jm-tutorial-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.25s ease, visibility 0.25s ease;
}

.jm-tutorial-overlay.show {
    opacity: 1;
    visibility: visible;
}

.jm-tutorial-modal {
    position: relative;
    width: min(900px, 92vw);
    max-height: 90vh;
    background: #1a1a1a;
    border-radius: 16px;
    box-shadow: 0 25px 60px rgba(0, 0, 0, 0.5);
    overflow: hidden;
    transform: scale(0.92);
    transition: transform 0.25s ease;
}

.jm-tutorial-overlay.show .jm-tutorial-modal {
    transform: scale(1);
}

.jm-tutorial-title {
    padding: 14px 20px;
    font-size: 1rem;
    font-weight: 600;
    color: #e5e7eb;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(129, 140, 248, 0.08);
}

.jm-tutorial-modal video {
    display: block;
    width: 100%;
    max-height: calc(90vh - 50px);
    background: #000;
}

.jm-tutorial-close {
    position: absolute;
    top: 10px;
    right: 12px;
    z-index: 2;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 50%;
    color: #fff;
    cursor: pointer;
    transition: all 0.2s ease;
}

.jm-tutorial-close:hover {
    background: rgba(239, 68, 68, 0.6);
    border-color: rgba(239, 68, 68, 0.8);
}

/* 首次打开页面的新手引导遮罩（全屏挡住点击，仅高亮按钮可点） */
.jm-onboard-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.72);
    backdrop-filter: blur(2px);
    z-index: 10002;
    opacity: 0;
    transition: opacity 0.3s ease;
    cursor: pointer;
}

.jm-onboard-overlay:not(.hide) {
    opacity: 1;
}

.jm-onboard-overlay.hide {
    opacity: 0;
}

/* 教程按钮高亮：提升 z-index 让它浮在遮罩之上可点击 */
.jm-onboard-highlight {
    position: relative;
    z-index: 10003 !important;
    box-shadow: 0 0 0 4px rgba(129, 140, 248, 0.55), 0 0 28px rgba(129, 140, 248, 0.6) !important;
    animation: jm-onboard-pulse 1.8s ease-in-out infinite;
}

@keyframes jm-onboard-pulse {
    0%, 100% { box-shadow: 0 0 0 4px rgba(129, 140, 248, 0.55), 0 0 28px rgba(129, 140, 248, 0.6); }
    50% { box-shadow: 0 0 0 6px rgba(129, 140, 248, 0.35), 0 0 36px rgba(129, 140, 248, 0.85); }
}

/* 指引气泡 */
.jm-onboard-tip {
    position: fixed;
    z-index: 10004;
    width: 280px;
    background: rgba(28, 28, 30, 0.98);
    border: 1px solid rgba(129, 140, 248, 0.45);
    border-radius: 16px;
    padding: 22px 22px 20px;
    box-shadow: 0 12px 44px rgba(0, 0, 0, 0.55);
    opacity: 0;
    transform: translateY(8px) scale(0.96);
    transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.jm-onboard-tip:not(.hide) {
    opacity: 1;
    transform: translateY(0) scale(1);
}

.jm-onboard-tip.hide {
    opacity: 0;
    transform: translateY(8px) scale(0.96);
}

/* 气泡箭头（在气泡右上角，指向右上的教程按钮） */
.jm-onboard-tip::before {
    content: '';
    position: absolute;
    top: -7px;
    right: 22px;
    width: 14px;
    height: 14px;
    background: rgba(28, 28, 30, 0.98);
    border-left: 1px solid rgba(129, 140, 248, 0.45);
    border-top: 1px solid rgba(129, 140, 248, 0.45);
    transform: rotate(45deg);
}

/* 气泡在按钮上方时，箭头转到底部右侧 */
.jm-onboard-tip.above::before {
    top: auto;
    bottom: -7px;
    border-left: none;
    border-top: none;
    border-right: 1px solid rgba(129, 140, 248, 0.45);
    border-bottom: 1px solid rgba(129, 140, 248, 0.45);
}

.jm-onboard-tip-dot {
    position: absolute;
    top: -12px;
    left: 22px;
    width: 26px;
    height: 26px;
    background: linear-gradient(135deg, #818cf8, #c084fc);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 700;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(129, 140, 248, 0.5);
}

.jm-onboard-tip-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: #e5e7eb;
    margin-bottom: 8px;
}

.jm-onboard-tip-desc {
    font-size: 0.88rem;
    color: var(--text-secondary, #9ca3af);
    line-height: 1.6;
    margin-bottom: 18px;
    text-align: center;
}

.jm-onboard-tip-btn {
    width: 100%;
    padding: 10px;
    background: linear-gradient(135deg, #818cf8, #c084fc);
    color: #fff;
    border: none;
    border-radius: 10px;
    font-size: 0.9rem;
    font-weight: 500;
    cursor: pointer;
    transition: filter 0.2s ease;
}

.jm-onboard-tip-btn:hover {
    filter: brightness(1.12);
}

@media (max-width: 640px) {
    .jm-onboard-tip {
        width: calc(100vw - 24px);
    }
}

@media (max-width: 640px) {
    .jm-tutorial-btn span {
        display: none;
    }
    .jm-tutorial-btn {
        padding: 8px 10px;
    }
}

.jm-hero-title {
    font-size: 2rem;
    font-weight: 700;
    background: linear-gradient(135deg, #818cf8, #c084fc, #f0abfc);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    margin-bottom: 0.5rem;
}

.jm-hero-subtitle {
    font-size: 0.95rem;
    color: var(--text-secondary);
}

/* 创作对话框主容器 */
.jm-composer {
    background: rgba(42, 42, 42, 0.94);
    border: 1px solid rgba(99, 102, 241, 0.15);
    border-radius: 20px;
    padding: 1.5rem;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
    transition: border-color 0.3s ease;
}

.jm-composer:focus-within {
    border-color: rgba(99, 102, 241, 0.4);
}

/* 拖拽上传：整个操作区高亮反馈 */
.jm-composer.drag-over {
    border-color: rgba(99, 102, 241, 0.6);
    background: rgba(99, 102, 241, 0.06);
    outline: 2px dashed rgba(99, 102, 241, 0.5);
    outline-offset: -4px;
}

/* 上传按钮行 */
.jm-upload-row {
    position: relative;
    display: flex;
    gap: 0.6rem;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}

.jm-upload-btn {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0.9rem;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    color: var(--text-secondary);
    font-size: 0.85rem;
    cursor: pointer;
    transition: all 0.2s ease;
}

.jm-upload-btn:hover {
    background: rgba(99, 102, 241, 0.1);
    border-color: rgba(99, 102, 241, 0.4);
    color: #a5b4fc;
}

.jm-upload-btn svg {
    flex-shrink: 0;
    opacity: 0.8;
}

.jm-upload-btn span {
    font-weight: 500;
}

.jm-upload-btn small {
    font-size: 0.7rem;
    opacity: 0.6;
    margin-left: 0.2rem;
}

/* 拖拽上传视觉反馈 */
.jm-upload-row.drag-over {
    background: rgba(99, 102, 241, 0.08);
    border-radius: 12px;
    outline: 2px dashed rgba(99, 102, 241, 0.6);
    outline-offset: 2px;
}

.jm-upload-row.drag-over .jm-upload-btn {
    background: rgba(99, 102, 241, 0.15);
    border-color: rgba(99, 102, 241, 0.5);
    color: #a5b4fc;
}

.prompt-input.drag-over .upload-icon {
    background: rgba(99, 102, 241, 0.12);
    border-color: var(--primary-color);
    border-style: solid;
}

.prompt-input.drag-over {
    outline: 2px dashed var(--primary-color);
    outline-offset: 4px;
    border-radius: 8px;
}

/* 拖拽上传说明小字：紧邻音频按钮右侧，只把文案左对齐贴在按钮后面，
   盒子仍占满剩余空间，因此行尾的「一分钟学会」按钮位置不变。
   与音频按钮的间距 = 行内 gap(0.6rem) + 下面 margin-left，略大于按钮之间的 0.6rem，
   做到挨着但不贴住。
   ⚠️ align-self: center 不能删：.jm-upload-row 是 flex 且未设 align-items，
   默认 stretch 会把这个 span 拉到整行高度（按钮因为有 padding，文字仍居中，
   小字则会贴到行顶部）——去掉就会「文字偏上、与按钮不水平对齐」。 */
.jm-drag-hint {
    flex: 1 1 auto;
    align-self: center;
    margin: 0 0 0 0.85rem;
    padding: 0;
    font-size: 0.75rem;
    color: var(--text-muted);
    opacity: 0.7;
    white-space: nowrap;
    text-align: left;
    pointer-events: none;
}

/* 预览容器：所有素材缩略图同一行 */
.jm-previews {
    margin-bottom: 1rem;
    padding: 0.6rem;
    background: rgba(0, 0, 0, 0.2);
    border-radius: 12px;
    animation: fadeInUp 0.3s ease-out;
}

/* 三种素材的预览容器合并为一行 */
.jm-preview-row {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    min-height: 0;
    margin: 0;
    vertical-align: top;
}

/* 预览项在即梦风格下稍小 */
.jm-previews .preview-item {
    width: 56px;
    height: 56px;
    border-radius: 8px;
}

/* 提示词输入框 */
.jm-prompt-box {
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 1rem;
    transition: border-color 0.3s ease;
    margin-bottom: 1rem;
}

.jm-prompt-box:focus-within {
    border-color: rgba(99, 102, 241, 0.5);
    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}

.jm-prompt-box textarea {
    width: 100%;
    min-height: 100px;
    max-height: calc(0.95rem * 1.6 * 15); /* 最多15行文字高度 */
    overflow-y: auto;
    background: transparent;
    border: none;
    outline: none;
    resize: none;
    color: var(--text-color);
    font-size: 0.95rem;
    line-height: 1.6;
    font-family: inherit;
    padding: 0;
}

.jm-prompt-box textarea::placeholder {
    color: rgba(176, 176, 176, 0.5);
}

/* 生成按钮
   ⚠️ 尺寸不变量：按钮在「生成视频 / 提交中（含上传中 n/N）/ 已提交」三个阶段必须一样大。
   进入提交阶段时 #costDisplay 被摘除、#btnSpinner 被显示、文案也变短，内容宽度/高度都会变，
   因此尺寸由 JS 在点击瞬间量好写进内联 min-width / min-height（lockGenerateBtnSize），
   这里配合做两件事：
     · justify-content: center —— 锁宽后多出来的空间均分两侧，文案保持居中不再忽左忽右；
     · position: relative —— 给 #btnSpinner 的绝对定位当包含块（见下方规则）。
   改这里的 padding / gap / font-size 都要重新核对三个阶段的内容是否仍 ≤ 常态宽度。 */
.jm-generate-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    gap: 0.5rem;
    padding: 0.6rem 1.5rem;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    border: none;
    border-radius: 12px;
    color: white;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.25s ease;
    box-shadow: 0 4px 14px rgba(99, 102, 241, 0.35);
    white-space: nowrap;
}

.jm-generate-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 6px 20px rgba(99, 102, 241, 0.5);
    background: linear-gradient(135deg, #7c3aed, #a855f7);
}

.jm-generate-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.jm-generate-btn #costDisplay {
    background: rgba(255, 255, 255, 0.15);
    padding: 2px 8px;
    border-radius: 8px;
    font-size: 0.8rem;
}

/* 参数选择区：纵向两行布局 */
.jm-params {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

/* 每行：横向排列 */
.jm-param-row {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    flex-wrap: wrap;
}

.jm-param-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* 比例行：占满剩余宽度，生成按钮推到最右 */
.jm-param-group-ratio {
    flex: 1;
    min-width: 0;
}

/* 时长滑块组：横向布局，标签+数值+滑块同一排 */
.jm-param-group-slider {
    flex: 0 0 auto;
    min-width: auto;
    align-items: center;
    gap: 0.6rem;
}

.jm-param-group-slider .jm-param-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

.jm-slider-value {
    font-size: 0.8rem;
    color: var(--text-primary);
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    padding: 0.1rem 0.5rem;
    border-radius: 6px;
    min-width: 38px;
    text-align: center;
}

/* 任务数量滑块组：复用时长滑块布局 */
.jm-param-group-count {
    flex: 0 0 auto;
    min-width: auto;
    align-items: center;
    gap: 0.6rem;
}

.jm-count-slider {
    width: 100px;
}

/* 批量提交进度提示（按钮内显示 ×N） */
.jm-batch-progress {
    font-size: 0.8rem;
    font-weight: 600;
    color: #fff;
    background: rgba(255, 255, 255, 0.2);
    padding: 0.1rem 0.45rem;
    border-radius: 6px;
    margin-left: 0.3rem;
}

/* 生成按钮上传进度条效果：背景按 --upload-progress 比例从左到右填充 */
.jm-generate-btn.jm-uploading {
    --upload-progress: 0%;
    background: linear-gradient(
        to right,
        rgba(255, 255, 255, 0.35) 0%,
        rgba(255, 255, 255, 0.35) var(--upload-progress),
        rgba(99, 102, 241, 0.6) var(--upload-progress),
        rgba(99, 102, 241, 0.6) 100%
    ) !important;
    transition: background 0.3s ease;
}

/* 生成按钮「已提交」3 秒倒计时：一层成功绿高亮覆盖按钮，随时间从右向左退去，
   退完露出底部常态渐变。动画时长由 JS 写入 --jm-countdown（与 SUBMIT_COOLDOWN_MS 同源），
   这里的 3s 只是兜底默认值。 */
.jm-generate-btn.jm-countdown {
    --jm-countdown: 3s;
    position: relative;
    overflow: hidden;
    background: linear-gradient(135deg, #6366f1, #8b5cf6) !important;
}

/* 文案/图标压在高亮层之上（::after 在 DOM 顺序上晚于 span，需显式提层）。
   ⚠️ 必须排除 #btnSpinner：它是绝对定位的（见下方规则），若被这条改回 relative 就会重新
   回到 flex 文档流，凭空多出一个子项、多吃一个 gap，把按钮撑宽 —— 尺寸不变量当场失效。 */
.jm-generate-btn.jm-countdown > span:not(.loading-spinner) {
    position: relative;
    z-index: 1;
}

.jm-generate-btn.jm-countdown::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(135deg, #10b981, #059669);
    animation: jmCountdownDrain var(--jm-countdown) linear forwards;
}

/* 倒计时期间按钮处于禁用态，但需保持满亮度让倒计时清晰可见（覆盖 :disabled 的 0.6） */
.jm-generate-btn.jm-countdown:disabled {
    opacity: 1;
    cursor: default;
}

/* 用 clip-path 而非 scaleX 收窄：渐变不会被横向压缩，且走合成层不触发布局 */
@keyframes jmCountdownDrain {
    from { clip-path: inset(0 0 0 0); }
    to   { clip-path: inset(0 100% 0 0); }
}

/* #btnSpinner 全项目没有任何样式定义（.loading-spinner 在 CSS 里搜不到），是个 0×0 的空 span。
   但 JS 从「提交中」开始会把它 display 成 inline-block —— 它就成了 flex 子项，
   即便宽高为 0 也会**吃掉一个 gap(0.5rem)**，把按钮内容撑宽 8px；
   而且它一旦回到文档流，min-height 锁也就被它的行盒影响。
   把它移出文档流（无偏移、无尺寸）即彻底与布局解耦：视觉上依旧不可见，
   想给它补真实转圈样式时也不会再牵动按钮尺寸。 */
.jm-generate-btn > .loading-spinner {
    position: absolute;
}

.jm-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 160px;
    height: 6px;
    border-radius: 3px;
    background: rgba(99, 102, 241, 0.2);
    outline: none;
    cursor: pointer;
}

.jm-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    border: 2px solid #fff;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(99, 102, 241, 0.5);
    transition: transform 0.15s ease;
}

.jm-slider::-webkit-slider-thumb:hover {
    transform: scale(1.15);
}

.jm-slider::-moz-range-thumb {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    border: 2px solid #fff;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(99, 102, 241, 0.5);
}

.jm-slider::-moz-range-track {
    height: 6px;
    border-radius: 3px;
    background: rgba(99, 102, 241, 0.2);
}

.jm-param-label {
    font-size: 0.78rem;
    color: var(--text-secondary);
    font-weight: 500;
    white-space: nowrap;
}

.jm-chip-group {
    display: flex;
    gap: 0.35rem;
    flex-wrap: wrap;
}

/* 模型说明：紧邻上传按钮右侧的纯文字 */
.jm-model-desc {
    margin-left: 0.4rem;
    align-self: center;
    font-size: 0.78rem;
    line-height: 1.4;
    color: var(--text-secondary);
    white-space: pre-wrap;
    word-break: break-word;
}

/* Chip 按钮（即梦风格药丸按钮） */
.jm-chip {
    padding: 0.35rem 0.85rem;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    color: var(--text-secondary);
    font-size: 0.82rem;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.jm-chip:hover {
    background: rgba(99, 102, 241, 0.1);
    border-color: rgba(99, 102, 241, 0.3);
    color: #a5b4fc;
}

.jm-chip.active {
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    border-color: transparent;
    color: white;
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.35);
}

/* 比例可视化图标 */
.jm-ratio {
    padding: 0.3rem 0.7rem;
}

.jm-ratio-icon {
    display: inline-block;
    border: 1.5px solid currentColor;
    border-radius: 2px;
    flex-shrink: 0;
    opacity: 0.8;
}

/* ===== 作品展示区 ===== */
.jm-tasks {
    margin-top: 2.5rem;
}

.jm-tasks-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1rem;
}

.jm-tasks-title {
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--text-color);
}

/* 分类标签 */
.jm-tasks-tabs {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.jm-tab {
    padding: 0.45rem 0.95rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    color: var(--text-secondary);
    font-size: 0.88rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
}

.jm-tab:hover {
    background: rgba(99, 102, 241, 0.08);
    color: #a5b4fc;
}

.jm-tab.active {
    background: rgba(99, 102, 241, 0.15);
    border-color: rgba(99, 102, 241, 0.3);
    color: #c7d2fe;
    font-weight: 600;
}

.jm-share-filter {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.jm-share-filter.active {
    background: rgba(16, 185, 129, 0.16);
    border-color: rgba(52, 211, 153, 0.42);
    color: #a7f3d0;
}

.jm-share-filter.active:hover {
    background: rgba(16, 185, 129, 0.22);
    color: #d1fae5;
}

/* 操作指引切换按钮 */
.jm-guide-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.75rem;
    background: rgba(99, 102, 241, 0.12);
    border: 1px solid rgba(99, 102, 241, 0.3);
    border-radius: 8px;
    color: #a5b4fc;
    font-size: 0.78rem;
    cursor: pointer;
    transition: all 0.2s ease;
}

.jm-guide-toggle:hover {
    background: rgba(99, 102, 241, 0.2);
    border-color: rgba(99, 102, 241, 0.5);
    color: #c7d2fe;
}

/* 操作指引板块 */
.jm-guide {
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.08), rgba(139, 92, 246, 0.05));
    border: 1px solid rgba(99, 102, 241, 0.2);
    border-radius: 14px;
    padding: 1.25rem;
    margin-bottom: 1.25rem;
}

.jm-guide-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1rem;
}

.jm-guide-head h4 {
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-color);
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.jm-guide-head h4::before {
    content: "💡";
    font-size: 1rem;
}

.jm-guide-close {
    background: transparent;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    padding: 0.25rem;
    border-radius: 6px;
    display: flex;
    align-items: center;
    transition: all 0.2s ease;
}

.jm-guide-close:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-color);
}

/* 4 步指引横向排列 */
.jm-guide-steps {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.85rem;
}

.jm-guide-step {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 0.85rem;
    background: rgba(0, 0, 0, 0.25);
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.05);
}

.jm-guide-icon {
    position: relative;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.25), rgba(139, 92, 246, 0.15));
    display: flex;
    align-items: center;
    justify-content: center;
    color: #a5b4fc;
}

.jm-guide-num {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(99, 102, 241, 0.5);
}

.jm-guide-body h5 {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-color);
    margin: 0 0 0.25rem 0;
}

.jm-guide-body p {
    font-size: 0.72rem;
    color: var(--text-secondary);
    line-height: 1.5;
    margin: 0;
}

.jm-guide-body code {
    background: rgba(99, 102, 241, 0.2);
    color: #c7d2fe;
    padding: 0.05rem 0.3rem;
    border-radius: 4px;
    font-size: 0.7rem;
    font-family: 'SF Mono', Consolas, monospace;
}

/* 示例提示词区 */
.jm-guide-tip {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1rem;
    padding: 0.65rem 0.85rem;
    background: rgba(0, 0, 0, 0.3);
    border-radius: 8px;
    font-size: 0.78rem;
    color: var(--text-secondary);
    flex-wrap: wrap;
}

.jm-guide-tip svg {
    color: #fbbf24;
    flex-shrink: 0;
}

.jm-guide-tip em {
    color: var(--text-primary);
    font-style: normal;
    flex: 1;
    min-width: 200px;
}

.jm-guide-fill {
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    border: none;
    color: #fff;
    padding: 0.35rem 0.85rem;
    border-radius: 6px;
    font-size: 0.75rem;
    cursor: pointer;
    transition: all 0.2s ease;
    flex-shrink: 0;
}

.jm-guide-fill:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 10px rgba(99, 102, 241, 0.4);
}

.jm-task-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1rem;
}

/* 私密笔记图标（卡片预览区右下角，常驻；有笔记=紫色，无=半透明黑） */
.jm-pnote-badge:hover {
    background: rgba(139, 92, 246, 0.95) !important;
    transform: scale(1.12);
}

.jm-empty {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem 1rem;
    color: var(--text-secondary);
    opacity: 0.4;
    text-align: center;
}

.jm-empty p {
    margin-top: 0.75rem;
    font-size: 0.9rem;
}

/* 任务卡片 */
.jm-task-card {
    background: rgba(42, 42, 42, 0.5);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    overflow: hidden;
    /* 屏幕外卡片跳过布局与绘制（作品多时滚动/插入/回顶重绘的主要降本手段）；
       contain-intrinsic-size 提供屏外占位估算，进入视口后浏览器自动用真实尺寸替换。
       2026-10-01：卡片高度改为按断点锁定（见各 @media），估算值必须与锁定值严格相等，
       否则下滑时「估算→真实」的尺寸差会让下方内容整体位移，表现为卡片跳动、顺序像变了。 */
    content-visibility: auto;
    contain-intrinsic-size: auto 400px;
    /* 仅对视觉属性做过渡，避免布局跳变被动画化放大 */
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
    /* 锁定高度：缩略图 flex 弹性吸收余量，信息区自然高度，整卡高度恒定 */
    display: flex;
    flex-direction: column;
    height: 400px;
}

.jm-task-card:hover {
    border-color: rgba(99, 102, 241, 0.3);
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}

.jm-task-thumb {
    position: relative;
    width: 100%;
    /* 2026-10-01：原 aspect-ratio 3/4 使卡片高度随列宽浮动（content-visibility 估算
       永远对不准 → 下滑跳动）。改为 flex 填满「卡片锁定高度 − 信息区」的余量，
       裁切交 object-fit: cover，视觉比例由卡片锁定高度控制。 */
    flex: 1 1 0;
    min-height: 0;
    background: #1a1a1a;
    overflow: hidden;
}

.jm-task-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.jm-task-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: white;
    font-size: 0.8rem;
}

/* 失败任务预览区提示块（中性灰，无图标） */
.jm-task-failed-hint {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.35);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    text-align: center;
}
.jm-task-failed-hint p {
    color: #94a3b8;
    font-size: 0.82rem;
    line-height: 1.6;
    margin: 0;
}

/* 结果文件已过期：任务成功但本地/上游都拿不到文件（上游链接被删），
   不能给播放按钮，否则用户点开只能看到播放失败 */
.jm-task-expired-hint {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.62);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    text-align: center;
}
.jm-task-expired-hint p {
    color: #cbd5e1;
    font-size: 0.78rem;
    line-height: 1.6;
    margin: 0;
}

/* ===== 处理中卡片：霓虹能量液注满动画（替换转圈环）===== */
.jm-liquid-wrap {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: radial-gradient(120% 90% at 50% 112%, #0e1d34 0%, #0a1424 45%, #03050b 100%);
}

.jm-liq-grid {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(56, 189, 248, 0.065) 1px, transparent 1px),
        linear-gradient(90deg, rgba(56, 189, 248, 0.065) 1px, transparent 1px);
    background-size: 34px 34px;
    -webkit-mask-image: radial-gradient(120% 100% at 50% 62%, #000 32%, transparent 78%);
    mask-image: radial-gradient(120% 100% at 50% 62%, #000 32%, transparent 78%);
}

.jm-liq-liquid {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 0%;
    overflow: hidden;
    background: linear-gradient(180deg, rgba(34, 211, 238, 0.33), rgba(14, 90, 140, 0.5) 40%, rgba(8, 47, 90, 0.64));
    box-shadow: inset 0 16px 28px -14px rgba(165, 243, 252, 0.35);
}

/* 液体内部气泡：相对液体高度百分比上升，纯 CSS 循环（JS 零参与） */
.jm-liq-bub {
    position: absolute;
    bottom: 2%;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 35%, rgba(224, 253, 255, 0.9), rgba(34, 211, 238, 0.25));
    animation: jm-liq-rise linear infinite;
}

@keyframes jm-liq-rise {
    0% { bottom: 2%; transform: translateX(0); opacity: 0; }
    12% { opacity: 0.85; }
    90% { opacity: 0.85; }
    100% { bottom: 92%; transform: translateX(6px); opacity: 0; }
}

.jm-liq-glow {
    position: absolute;
    left: 0;
    right: 0;
    height: 46px;
    pointer-events: none;
    background: linear-gradient(to top, rgba(34, 211, 238, 0.2), transparent);
}

/* 液面波浪：双层 SVG 波形错速反向平移，形成涌动视差；bottom 由 JS 随水位同步 */
.jm-liq-waves {
    position: absolute;
    left: 0;
    right: 0;
    height: 12px;
    bottom: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 2;
}

.jm-liq-wave {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 200%;
    height: 100%;
    display: block;
}

/* 前层：亮色，向左涌 */
.jm-liq-wave.w1 path {
    fill: rgba(26, 130, 178, 0.95);
}
.jm-liq-wave.w1 {
    animation: jm-liq-wave 3.2s linear infinite;
}

/* 后层：浅透，向右涌，错相慢速 */
.jm-liq-wave.w2 path {
    fill: rgba(34, 211, 238, 0.4);
}
.jm-liq-wave.w2 {
    bottom: 1px;
    opacity: 0.75;
    animation: jm-liq-wave 5.4s linear infinite reverse;
}

@keyframes jm-liq-wave {
    from { transform: translateX(0); }
    to { transform: translateX(-50%); }
}

.jm-liq-surface {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg, rgba(103, 232, 249, 0.5), #dcfcff 32%, rgba(103, 232, 249, 0.5));
}

/* 光轨粒子层：铺满卡片；粒子从卡片顶部坠落到液面。
   液面位置（--liq-lvl）与下落距离（--fall-dist=液面到卡片顶）由 JS 随水位每帧同步 */
.jm-liq-falls {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 3;
}

.jm-liq-dot {
    position: absolute;
    bottom: var(--liq-lvl, 0%);   /* 静态位置=液面：动画终点即落水点（保住末段摊开淡出的涟漪） */
    width: 5px;
    height: 5px;
    margin-left: -2.5px;
    border-radius: 50%;
    background: radial-gradient(circle, #eafcff 0 28%, rgba(34, 211, 238, 0.85) 55%, transparent 75%);
    opacity: 0;
    animation: jm-liq-fall linear infinite;
}

/* 尾迹：细长光带，随粒子整体缩放变形 */
.jm-liq-dot::before {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 55%;
    width: 1.8px;
    height: 44px;
    transform: translateX(-50%);
    background: linear-gradient(to top, rgba(165, 243, 252, 0.7), rgba(34, 211, 238, 0.2) 55%, transparent);
    border-radius: 2px;
}

/* 稀有白核粒子：更大更亮 */
.jm-liq-dot.w {
    width: 7px;
    height: 7px;
    margin-left: -3.5px;
    background: radial-gradient(circle, #fff 0 32%, rgba(224, 253, 255, 0.9) 55%, rgba(103, 232, 249, 0.4) 75%, transparent);
}

@keyframes jm-liq-fall {
    /* 起点=卡片顶部：下落距离由 JS 设为「液面到卡片顶」的像素值，随水位动态变化 */
    0% { transform: translateY(calc(-1 * var(--fall-dist, 160px))) scaleY(0.6); opacity: 0; }
    8% { opacity: 1; }
    86% { transform: translateY(0) scaleY(1.4); opacity: 1; }
    /* 末段：坠入液面摊开淡出，等效涟漪效果 */
    100% { transform: translateY(4px) scaleY(2.4) scaleX(2.2); opacity: 0; }
}

.jm-liq-pct {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 30px;
    font-weight: 650;
    letter-spacing: 0.02em;
    color: #eafcff;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 18px rgba(34, 211, 238, 0.8), 0 0 40px rgba(34, 211, 238, 0.45);
    pointer-events: none;
    z-index: 5;
}

/* 尊重「减少动态效果」系统设置：关停装饰动画（粒子/气泡为纯 CSS 动画，直接隐藏） */
@media (prefers-reduced-motion: reduce) {
    .jm-liq-grid,
    .jm-liq-wave {
        animation: none;
    }
    .jm-liq-dot,
    .jm-liq-bub {
        animation: none;
        opacity: 0;
    }
}

/* 加载动画：双层旋转环 */
.jm-loading-ring {
    position: relative;
    width: 44px;
    height: 44px;
}

.jm-loading-ring::before,
.jm-loading-ring::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 3px solid transparent;
    box-sizing: border-box;
}

/* 外环：顺时针，品牌紫 */
.jm-loading-ring::before {
    border-top-color: #818cf8;
    border-right-color: #818cf8;
    animation: jm-spin 1.1s linear infinite;
}

/* 内环：逆时针，辅色绿 */
.jm-loading-ring::after {
    inset: 8px;
    border-bottom-color: #34d399;
    border-left-color: #34d399;
    animation: jm-spin-reverse 1.4s linear infinite;
}

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

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

/* 尊重「减少动态效果」系统设置 */
@media (prefers-reduced-motion: reduce) {
    .jm-loading-ring::before,
    .jm-loading-ring::after {
        animation: none;
    }
    /* 播放框尺寸过渡与加载环降级 */
    .jm-video-modal-box {
        transition: none;
    }
    .jm-video-modal-loading::before {
        animation: none;
        border-top-color: rgba(255, 255, 255, 0.22);
    }
}

/* 播放按钮 */
.jm-task-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: rgba(99, 102, 241, 0.94);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2rem;
    padding-left: 4px;
    transition: all 0.2s ease;
}

.jm-task-thumb:hover .jm-task-play {
    background: rgba(99, 102, 241, 1);
    transform: translate(-50%, -50%) scale(1.1);
}

.jm-task-info {
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    flex: 0 0 auto;  /* 不参与伸缩，缩略图独自吸收锁定高度的余量 */
}

.jm-task-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
}

.jm-task-date {
    font-size: 0.72rem;
    color: var(--text-secondary);
    opacity: 0.7;
}

.jm-task-status {
    font-size: 0.7rem;
    padding: 2px 8px;
    border-radius: 10px;
    font-weight: 500;
}

.jm-task-prompt {
    font-size: 0.82rem;
    color: var(--text-color);
    line-height: 1.4;
    /* 单行显示，超出省略 */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0.85;
    flex: 1;
}

.jm-task-actions {
    display: flex;
    gap: 0.4rem;
    margin-top: auto;
}

.jm-action-btn {
    flex: 1;
    padding: 0.35rem 0.5rem;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-secondary);
    font-size: 0.75rem;
    cursor: pointer;
    transition: all 0.2s ease;
    text-align: center;
}

.jm-action-btn:hover {
    background: rgba(99, 102, 241, 0.1);
    border-color: rgba(99, 102, 241, 0.3);
    color: #a5b4fc;
}

.jm-action-primary {
    background: rgba(99, 102, 241, 0.15);
    border-color: rgba(99, 102, 241, 0.3);
    color: #a5b4fc;
}

.jm-action-primary:hover {
    background: rgba(99, 102, 241, 0.25);
    color: #c7d2fe;
}

/* 隐藏按钮：低强调，避免误触 */
.jm-action-hide {
    flex: 0 0 auto;
    width: auto;
    min-width: 48px;
    padding: 0.35rem 0.6rem;
    background: transparent;
    border-color: rgba(148, 163, 184, 0.25);
    color: rgba(148, 163, 184, 0.8);
    font-size: 0.72rem;
}

.jm-action-hide:hover {
    background: rgba(148, 163, 184, 0.12);
    border-color: rgba(148, 163, 184, 0.4);
    color: #cbd5e1;
}

/* 删除按钮：红色危险操作，仅在失败任务上显示 */
.jm-action-danger {
    flex: 0 0 auto;
    width: auto;
    min-width: 48px;
    padding: 0.35rem 0.6rem;
    background: transparent;
    border-color: rgba(239, 68, 68, 0.25);
    color: #f87171;
}

.jm-action-danger:hover {
    background: rgba(239, 68, 68, 0.12);
    border-color: rgba(239, 68, 68, 0.5);
    color: #fca5a5;
}

/* 头部按钮容器 */
.jm-tasks-header-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* 已隐藏入口按钮：与操作指引按钮风格一致但更柔和 */
.jm-hidden-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.75rem;
    background: rgba(148, 163, 184, 0.1);
    border: 1px solid rgba(148, 163, 184, 0.25);
    border-radius: 8px;
    color: #94a3b8;
    font-size: 0.78rem;
    cursor: pointer;
    transition: all 0.2s ease;
}

.jm-hidden-toggle:hover {
    background: rgba(148, 163, 184, 0.18);
    border-color: rgba(148, 163, 184, 0.45);
    color: #cbd5e1;
}

/* ===== 已隐藏任务模态框 ===== */
.jm-hidden-modal-box {
    position: relative;
    width: 100%;
    max-width: 960px;
    max-height: 88vh;
    background: #1a1a1a;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}

.jm-hidden-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.jm-hidden-modal-head h4 {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: #f1f5f9;
}

.jm-hidden-modal-head .jm-video-modal-close {
    position: static;
    background: transparent;
}

.jm-hidden-modal-head .jm-video-modal-close:hover {
    background: rgba(255, 255, 255, 0.08);
}

.jm-hidden-modal-tip {
    padding: 0.6rem 1.25rem;
    font-size: 0.78rem;
    color: #94a3b8;
    background: rgba(148, 163, 184, 0.06);
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

#hiddenTaskList {
    padding: 1rem 1.25rem;
    overflow-y: auto;
    gap: 1rem;
}

.jm-hidden-empty {
    padding: 3rem 1.25rem;
    text-align: center;
    color: #64748b;
    font-size: 0.9rem;
}

.jm-task-card-hidden {
    opacity: 0.85;
}

.jm-task-card-hidden:hover {
    opacity: 1;
}

/* ===== 视频播放模态框 ===== */
.jm-video-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: rgba(0, 0, 0, 0.85);
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.jm-video-modal.active {
    display: flex;
}

.jm-video-modal-box {
    position: relative;
    width: 100%;
    max-width: 960px;
    max-height: 90vh;
    background: #000;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
    /* 尺寸变化（预设比例 → 视频真实比例）平滑过渡，取代原来的硬跳变。
       打开瞬间不参与过渡：此时元素刚从 display:none 变为可见，首次布局不触发 transition。 */
    transition: width 0.28s ease, height 0.28s ease,
                max-width 0.28s ease, max-height 0.28s ease;
}

.jm-video-modal-box video {
    display: block;
    width: 100%;
    max-height: 90vh;
    object-fit: contain;
    background: #000;
}

/* 元数据就绪前的加载提示：此前定义了却从未被显示，导致等待期间是一块纯黑空框。
   显示/隐藏由 playVideoModal / closeVideoModal 用 inline display 控制。 */
.jm-video-modal-loading {
    position: absolute;
    inset: 0;
    z-index: 2;
    flex-direction: column;
    gap: 0.6rem;
    align-items: center;
    justify-content: center;
    /* 半透明压暗，让下面的首帧占位图（poster）仍能透出来 */
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.62));
    color: #e2e8f0;
    font-size: 0.9rem;
    letter-spacing: 0.02em;
    pointer-events: none;   /* 不挡底部控制条与关闭按钮 */
}

/* 旋转环：用伪元素，避开 JS 设置 textContent 时把结构冲掉 */
.jm-video-modal-loading::before {
    content: '';
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2.5px solid rgba(255, 255, 255, 0.22);
    border-top-color: #ffffff;
    animation: jm-spin 0.85s linear infinite;
}

.jm-video-modal-close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    border: none;
    border-radius: 50%;
    color: #fff;
    cursor: pointer;
    transition: background 0.2s ease;
    z-index: 1;
}

.jm-video-modal-close:hover {
    background: rgba(0, 0, 0, 0.85);
}

.jm-loading {
    grid-column: 1 / -1;
    text-align: center;
    padding: 2rem;
    color: var(--text-secondary);
    font-size: 0.85rem;
}

/* ===== 响应式适配 ===== */
@media (max-width: 640px) {
    .jm-page {
        padding: 1rem 0.75rem 3rem;
    }

    .jm-hero-title {
        font-size: 1.5rem;
    }

    .jm-composer {
        padding: 1rem;
        border-radius: 16px;
    }

    .jm-param-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.75rem;
    }

    .jm-param-group {
        width: 100%;
    }

    .jm-chip-group {
        width: 100%;
    }

    .jm-param-row .jm-generate-btn {
        width: 100%;
        justify-content: center;
        padding: 0.7rem 1.5rem;
    }

    .jm-task-grid {
        grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
        gap: 0.75rem;
    }

    /* 卡片锁定高度（与 contain-intrinsic-size 严格相等，防下滑跳动） */
    .jm-task-card {
        height: 360px;
        contain-intrinsic-size: auto 360px;
    }

    /* 移动端：指引改为 1 列纵向堆叠 */
    .jm-guide-steps {
        grid-template-columns: 1fr;
    }

    .jm-guide-step {
        padding: 0.7rem;
    }

    .jm-task-info {
        padding: 0.5rem;
    }

    .jm-task-prompt {
        font-size: 0.75rem;
    }
}

/* 平板适配 */
@media (min-width: 641px) and (max-width: 900px) {
    .jm-page {
        max-width: 100%;
        padding: 1.5rem 1rem 3rem;
    }

    .jm-task-grid {
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }

    .jm-task-card {
        height: 400px;
        contain-intrinsic-size: auto 400px;
    }
}

/* 2K/4K 大屏适配：任务卡片随屏幕适度放大（多列小卡，不放大成大卡片）；创作区限宽保持表单可读性 */
@media (min-width: 1600px) {
    .jm-task-grid {
        grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    }

    .jm-task-card {
        height: 460px;
        contain-intrinsic-size: auto 460px;
    }

    .jm-composer {
        max-width: 1400px;
        margin-left: auto;
        margin-right: auto;
    }
}

@media (min-width: 2200px) {
    .jm-task-grid {
        grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    }

    .jm-task-card {
        height: 520px;
        contain-intrinsic-size: auto 520px;
    }

    .jm-composer {
        max-width: 1600px;
    }
}

/* 图片预览模态框（任务卡片点击查看大图） */
.image-preview-modal {
    display: none; position: fixed; inset: 0; z-index: 1080;
    background: rgba(0,0,0,0.9); align-items: center; justify-content: center;
    cursor: zoom-out;
}
.image-preview-modal.show { display: flex; }
.image-preview-content {
    position: relative; max-width: 92vw; max-height: 92vh; cursor: default;
}
.image-preview-content img {
    max-width: 92vw; max-height: 92vh; display: block; border-radius: 6px;
    box-shadow: 0 8px 40px rgba(0,0,0,0.6);
}
.image-preview-close {
    position: absolute; top: -44px; right: 0;
    width: 36px; height: 36px; border-radius: 50%;
    background: rgba(255,255,255,0.15); color: #fff; border: none;
    font-size: 22px; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: background 0.15s;
}
.image-preview-close:hover { background: rgba(255,255,255,0.3); }

/* =====================================================================
   任务备注行（原先是一串内联样式，2026-09-20 提取成 class 以便移动端重排）
   ===================================================================== */
.task-note-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.6rem;
}
.task-note-label {
    flex-shrink: 0;
    font-size: 0.78rem;
    color: #f5b95c;
}
.task-note-input {
    flex: 1;
    min-width: 0;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 8px;
    padding: 0.42rem 0.75rem;
    color: #e8d5b0;
    font-size: 0.8rem;
    outline: none;
}
.task-note-count {
    flex-shrink: 0;
    font-size: 0.7rem;
    color: #7a7a7a;
}

/* =====================================================================
   ★ 移动端布局（≤640px）· 2026-09-20 重构

   背景：本文件此前只有「把宽度从 25% 改成 100%」这一档适配，
   手机上实际是桌面布局被压扁 —— 设置项占满首屏、生成按钮在首屏之外、
   内边距 2rem（390px 屏上左右各吃掉 8%）、可点元素普遍 35~40px。

   三条目标（只动排版与尺寸，配色与功能保持不变）：
     ① 首屏可用：提示词输入在最前，生成按钮固定在视口底部
     ② 触摸友好：可点元素一律 ≥44×44
     ③ 零无效留白：收紧内边距、取消 100% 高度拉伸、隐藏手机端无意义文案
   ===================================================================== */
@media (max-width: 640px) {

    /* ---- 1. 容器与卡片：单列、收紧边距、取消高度拉伸 ---- */
    .container.content-container {
        flex-direction: column;
        padding: 0 12px;
        height: auto;
        gap: 0;
    }
    .operation-area {
        display: flex;
        flex-direction: column;
        gap: 14px;
        width: 100%;
        height: auto;
        min-height: 0;
        margin-top: 8px;
        padding: 14px 14px 96px;   /* 底部留出「固定生成按钮」的高度 */
        overflow: visible;
    }
    .task-area {
        display: none;             /* 手机端统一走任务抽屉，不再并排挤 */
    }

    /* ---- 2. 顺序重排：提示词 → 设置 → （生成按钮已固定在底部） ---- */
    .operation-area > .prompt-input { order: 1; }
    .operation-area > .options      { order: 2; }

    /* ---- 3. 提示词区 ---- */
    .prompt-input {
        gap: 10px;
        margin-bottom: 0 !important;   /* 覆盖模板里的内联 margin-bottom: 1rem */
    }
    .prompt-input > div:first-child {
        gap: 10px;
        margin-bottom: 0;
    }
    .jm-drag-hint {
        display: none;                 /* 手机端没有拖拽，这条提示是噪音 */
    }
    .image-preview-thumbnail {
        /* 桌面端 min-height: 60px 是为了留出预览位；手机上没图时这 60px 就是纯空白，
           改成由内容撑开（有缩略图时 .thumbnail-item 自带 60×60）。 */
        min-height: 0;
        margin-bottom: 0;
    }
    .input-container textarea {
        min-height: 96px;
        max-height: 34vh;
        padding: 12px;
        font-size: 16px;               /* ≥16px：避免 iOS 聚焦时整页自动放大 */
    }
    .upload-icon {
        height: 44px;
        min-height: 44px;
        padding: 0 0.9rem;
        font-size: 0.9rem;
        line-height: 1;
    }

    /* ---- 4. 备注行：标签与计数同一行，输入框独占下一行（原本挤成一行） ---- */
    .task-note-row {
        flex-wrap: wrap;
        gap: 6px 8px;
        margin-top: 10px;
    }
    .task-note-label { order: 1; }
    .task-note-count { order: 2; margin-left: auto; font-size: 12px; }
    .task-note-input {
        order: 3;
        flex-basis: 100%;
        min-height: 44px;
        font-size: 16px;
    }

    /* ---- 5. 设置区：标签与按钮组分两行，按钮一律 ≥44px ---- */
    .options {
        gap: 12px;
        margin-bottom: 0;
    }
    .option-row {
        flex-direction: column;
        align-items: stretch;
        gap: 6px;
    }
    .option-label {
        min-width: 0;
        font-size: 0.8rem;
    }
    .btn-group { gap: 8px; }
    .btn-option,
    .btn-group-sm .btn-option {
        min-height: 44px;
        padding: 0 0.85rem;
        font-size: 0.875rem;
    }

    /* ---- 6. 生成按钮：固定在视口底部，随时可点 ---- */
    .operation-area > div:last-child {
        position: fixed;
        left: 12px;
        right: 12px;
        bottom: 12px;
        z-index: 900;
        padding-top: 0;
    }
    .execute-btn {
        height: 52px;
        min-height: 52px;
        margin-top: 0;
        position: static;              /* 原来的 sticky 在手机上不起作用，改由外层 fixed 承担 */
        font-size: 1rem;
    }

    /* ---- 7. 浮动按钮：竖排文字改横向胶囊，与回到顶部错开 ---- */
    .task-float-btn {
        display: inline-flex !important;   /* 覆盖 480px 档的 display:block */
        top: 78px;
        right: 12px;
        bottom: auto;
        align-items: center;
        justify-content: center;
        gap: 6px;
        min-height: 48px;
        padding: 0 16px;
        border-radius: 24px;
        writing-mode: horizontal-tb;       /* 原样式是 vertical-rl，手机上字被挤成竖排 */
        letter-spacing: 0;
        font-size: 0.875rem;
        box-shadow: 0 6px 20px rgba(99, 102, 241, 0.34);
    }
    .task-float-btn:hover { padding: 0 16px; }

    /* ---- 8. 任务列表：取消右侧抽屉，改成操作区下方的内联瀑布流（2026-09-20 改） ---- */
    /* 浮动按钮与遮罩两页都下掉 —— 原来点浮按钮从右侧滑出抽屉 */
    .task-float-btn,
    .task-overlay {
        display: none !important;
    }
    /* 抽屉本体变成文档流里的普通区块：它在本模板里紧跟 .task-area 之后，
       而手机端 .task-area 是 display:none，所以它自然落在操作区下方。
       ⚠️ 必须用 body.page-image 限定：styles.css 是生图页/视频页共用的，
       视频页区块里另有一条 .task-sidebar-mobile 的规则（那边是 display:none），
       不限定的话后者会把生图页的列表一起隐藏（这个坑已经踩过一次）。
       ⚠️ 原样式是 position:fixed + right:-400px，且 JS toggleTaskSidebar 还会改内联 right，
       所以这里必须全部 !important 才压得住。 */
    body.page-image .task-sidebar-mobile {
        position: static !important;
        right: auto !important;
        top: auto !important;
        width: 100% !important;
        height: auto !important;
        max-height: none !important;
        overflow: visible !important;
        background: transparent !important;
        border: none !important;
        box-shadow: none !important;
        z-index: auto !important;
        padding-bottom: 84px;          /* 给固定在视口底部的生成按钮留出空间 */
    }
    .task-sidebar-mobile .card {
        border-radius: var(--border-radius);
        overflow: hidden;
    }
    /* 瀑布流：手机上两列、卡片高度各自自适应 */
    #taskListMobile {
        max-height: none !important;   /* 覆盖模板里的内联 max-height: calc(100vh - 120px) */
        overflow: visible !important;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 10px;
    }
    #taskListMobile > .text-center {
        grid-column: 1 / -1;           /* 「暂无任务」占满整行 */
    }
    /* 卡片内部沿用桌面尺寸：模型别名只有 10px、复制/笔记按钮只有 30px 高，手机端抬到下限 */
    #taskListMobile .model-alias,
    #taskListMobile .task-meta,
    #taskListMobile .copy-btn,
    #taskListMobile .note-btn {
        font-size: 12px;
    }
    #taskListMobile .copy-btn,
    #taskListMobile .note-btn {
        min-height: 44px;
    }
    /* 列表常驻页面，不再需要抽屉的「收起」按钮 */
    .task-sidebar-mobile .close-btn {
        display: none;
    }
}

/* =====================================================================
   ★ 移动端布局（≤640px）· 视频页 sd2 · 2026-09-20

   改动前的实测问题（390×844）：
     · 横向溢出 255px —— 任务页签行把「两个页签 + 提示文字 + 搜索框 + 有笔记」
       硬排成一行（合计 608px），手机上要左右拖动才能看全
     · 触摸目标 <44px 共 22 处，其中两个滑块的可点高度只有 6px
     · 字号 <12px 共 12 处（上传计数、操作指引正文与步骤号）
   注意：页签行内部大量样式是模板里的**内联 style**，只能用 !important 覆盖。
   ===================================================================== */
@media (max-width: 640px) {

    /* ---- 0. 任务列表：取消右侧抽屉与浮动按钮（作品列表本来就在页面主体里） ---- */
    /* 2026-09-20 改：原来手机上点浮按钮从右侧滑出抽屉，与页面内的作品区重复，
       这里统一以下方的作品区为准。
       ⚠️ 必须用 body.page-video 限定，否则这条 display:none 会把生图页那份
       「改成内联瀑布流」的列表一起隐藏（生图页区块在它前面，压不过它）。 */
    body.page-video .task-float-btn,
    body.page-video .task-overlay,
    body.page-video .task-sidebar-mobile {
        display: none !important;
    }

    /* ---- 1. 任务页签行：允许换行 + 重排顺序，消除横向溢出 ---- */
    .jm-tasks-tabs {
        flex-wrap: wrap;
        row-gap: 8px;
    }
    .jm-tab {
        min-height: 44px;
        padding: 0 1rem;
        font-size: 0.9rem;
    }
    /* 「作品仅保留一个月…」：原先夹在页签与搜索框之间把整行撑爆，改为独占一行放最后 */
    .jm-tasks-tabs > span:not([id]) {
        order: 3;
        flex-basis: 100%;
        margin: 0 !important;
        font-size: 12px !important;
        white-space: normal !important;
        line-height: 1.5;
    }
    #taskSearchBox {
        order: 2;
        flex: 1 1 140px !important;
        min-width: 0 !important;
    }
    #taskSearchInput {
        min-height: 44px !important;
        font-size: 0.875rem !important;
    }
    #sharedFilterBtn {
        order: 1;
        min-height: 44px !important;
        padding: 0 0.9rem !important;
        font-size: 0.85rem !important;
    }
    #pnoteFilterBtn {
        order: 2;
        margin-left: 0 !important;
        min-height: 44px !important;
        padding: 0 0.9rem !important;
        font-size: 0.85rem !important;
    }

    /* ---- 2. 上传按钮与参数按钮：一律 ≥44px ---- */
    .jm-upload-btn {
        min-height: 44px;
        padding: 0 0.85rem;
        font-size: 0.85rem;
    }
    .jm-upload-btn small {
        font-size: 12px !important;
    }
    .jm-chip {
        min-height: 44px;
        padding: 0 0.9rem;
        font-size: 0.85rem;
    }
    .jm-tutorial-btn,
    .jm-guide-toggle {
        min-height: 44px;
        padding: 0 0.9rem;
        font-size: 0.85rem;
    }
    /* AI 帮写是关键入口，但本文件较前面的 640px 规则写了 `.jm-tutorial-btn span{display:none}`
       （本意是给「教程」按钮省空间），连带把它的文字也藏了 → 手机上只剩一个图标。
       这里单独把它的文字放回来，并保留图标+文字的内边距。 */
    .jm-tutorial-btn.ai-chat-open-btn span {
        display: inline;
    }
    .jm-tutorial-btn.ai-chat-open-btn {
        padding: 0 0.85rem;
        gap: 0.35rem;
    }

    /* ---- 3. 滑块：外观不变，把可点高度从 6px 提到 44px ---- */
    .jm-slider {
        width: 100%;
        height: 44px !important;
        background: transparent;          /* 轨道改由下面的伪元素绘制 */
        border-radius: 0;
    }
    .jm-slider::-webkit-slider-runnable-track {
        height: 6px;
        border-radius: 3px;
        background: rgba(99, 102, 241, 0.2);
    }
    .jm-slider::-webkit-slider-thumb {
        width: 24px;
        height: 24px;
        margin-top: -9px;                 /* (24-6)/2：让球形滑块在 6px 轨道上居中 */
    }
    .jm-slider::-moz-range-track {
        height: 6px;
        border-radius: 3px;
        background: rgba(99, 102, 241, 0.2);
    }
    .jm-slider::-moz-range-thumb {
        width: 24px;
        height: 24px;
    }

    /* ---- 4. 备注输入：≥44px，字号 16px 避免 iOS 聚焦时整页放大 ---- */
    #taskNote {
        min-height: 44px !important;
        font-size: 16px !important;
    }
    #taskNoteCount {
        font-size: 12px !important;
    }

    /* ---- 5. 操作指引：正文/步骤号字号提到 12px，收起按钮 ≥44px ---- */
    .jm-guide {
        padding: 1rem;
        margin-bottom: 1rem;
    }
    .jm-guide p {
        font-size: 12px;
        line-height: 1.55;
    }
    .jm-guide-num {
        width: 20px;
        height: 20px;
        font-size: 12px;
        line-height: 20px;
    }
    .jm-guide-close {
        width: 44px;
        height: 44px;
    }

    /* ---- 6. 教程弹窗：窄屏不超出视口 ---- */
    .jm-tutorial-modal {
        width: min(560px, 92vw);
        margin: 0 auto;
    }
}



/* ===== 素材缩略图上传进度遮罩（预上传可视化，2026-10-06） =====
   挂在 .preview-item（视频页素材区）与 .thumbnail-item（生图页参考图）上，
   容器自带 position:relative + overflow:hidden，遮罩 inset:0 即可铺满。 */
.jm-upl-mask {
    position: absolute;
    inset: 0;
    z-index: 3;
    background: rgba(15, 23, 42, 0.55);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    pointer-events: none;
}
.jm-upl-bar {
    width: 68%;
    height: 5px;
    background: rgba(255, 255, 255, 0.28);
    border-radius: 3px;
    overflow: hidden;
}
.jm-upl-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, #3B82F6, #6366f1);
    transition: width 0.15s linear;
}
.jm-upl-pct {
    color: #fff;
    font-size: 11px;
    line-height: 1;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.jm-upl-mask.failed .jm-upl-fill { background: #ef4444; }
.jm-upl-mask.failed .jm-upl-pct { color: #fecaca; }
