/* ── 基础变量 ───────────────────────────────────────────── */ :root { --bg: #faf9f7; --bg-card: #ffffff; --bg-hover: #f5f4f2; --ink: #1a1816; --muted: #7a756e; --border: #e8e5e0; --border-focus: #c4a882; --accent: #b45309; --accent-hover: #92400e; --accent-light: #fef3c7; --success: #0f766e; --success-bg: #f0fdfa; --error: #dc2626; --error-bg: #fef2f2; --radius: 10px; --radius-sm: 6px; --shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04); --shadow-lg: 0 10px 40px rgba(0,0,0,0.06), 0 2px 10px rgba(0,0,0,0.04); --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; --font-mono: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace; --transition: 0.2s ease; } /* ── 重置 ───────────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html { font-size: 16px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } body { font-family: var(--font); color: var(--ink); background: var(--bg); min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 2rem 1rem; line-height: 1.6; } /* ── 容器 ───────────────────────────────────────────────── */ .container { width: 100%; max-width: 520px; } /* ── 头部 ───────────────────────────────────────────────── */ .header { text-align: center; margin-bottom: 2rem; } .header-icon { display: inline-flex; align-items: center; justify-content: center; width: 56px; height: 56px; border-radius: 14px; background: linear-gradient(135deg, var(--accent), #d97706); color: white; margin-bottom: 1rem; box-shadow: 0 4px 14px rgba(180, 83, 9, 0.25); } .header h1 { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); margin-bottom: 0.25rem; } .subtitle { font-size: 0.9rem; color: var(--muted); } /* ── 表单卡片 ───────────────────────────────────────────── */ .form { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.75rem; box-shadow: var(--shadow); } .form-group { margin-bottom: 1.25rem; } .form-group:last-of-type { margin-bottom: 1rem; } .form-group label { display: flex; align-items: center; gap: 6px; font-size: 0.85rem; font-weight: 600; color: var(--ink); margin-bottom: 0.5rem; } .form-group label svg { color: var(--muted); } .form-hint { display: block; font-size: 0.75rem; color: var(--muted); margin-top: 0.35rem; } /* ── 输入框 ─────────────────────────────────────────────── */ input[type="text"] { width: 100%; padding: 0.65rem 0.9rem; font-size: 0.9rem; font-family: var(--font); color: var(--ink); background: var(--bg); border: 1.5px solid var(--border); border-radius: var(--radius-sm); outline: none; transition: border-color var(--transition), box-shadow var(--transition); } input[type="text"]::placeholder { color: #b5b0a8; } input[type="text"]:focus { border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(196, 168, 130, 0.15); } input[type="text"].input-error { border-color: var(--error); box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1); } /* ── 验证码行 ───────────────────────────────────────────── */ .captcha-row { display: flex; gap: 10px; align-items: stretch; } .captcha-row input { flex: 1; min-width: 0; letter-spacing: 0.15em; text-transform: uppercase; } .captcha-img { height: 42px; width: 140px; border-radius: var(--radius-sm); border: 1.5px solid var(--border); cursor: pointer; object-fit: cover; transition: opacity var(--transition); flex-shrink: 0; } .captcha-img:hover { opacity: 0.85; } .btn-icon { display: flex; align-items: center; justify-content: center; width: 42px; height: 42px; border: 1.5px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); color: var(--muted); cursor: pointer; transition: all var(--transition); flex-shrink: 0; } .btn-icon:hover { border-color: var(--border-focus); color: var(--accent); background: var(--accent-light); } /* ── 拖拽区 ─────────────────────────────────────────────── */ .dropzone { border: 2px dashed var(--border); border-radius: var(--radius); padding: 2rem 1.5rem; text-align: center; cursor: pointer; transition: all var(--transition); background: var(--bg); } .dropzone:hover, .dropzone.dragover { border-color: var(--accent); background: var(--accent-light); } .dropzone.dragover { transform: scale(1.01); } .dropzone-content { pointer-events: none; } .dropzone-icon { color: var(--muted); margin-bottom: 0.5rem; transition: color var(--transition); } .dropzone:hover .dropzone-icon, .dropzone.dragover .dropzone-icon { color: var(--accent); } .dropzone-text { font-size: 0.9rem; color: var(--muted); margin-bottom: 0.35rem; } .dropzone-link { color: var(--accent); font-weight: 600; text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 2px; } .dropzone-hint { font-size: 0.75rem; color: #b5b0a8; line-height: 1.5; } /* ── 文件列表 ───────────────────────────────────────────── */ .file-list { margin-bottom: 1rem; } .file-item { display: flex; align-items: center; gap: 10px; padding: 0.6rem 0.85rem; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: 6px; animation: slideIn 0.25s ease; } @keyframes slideIn { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } } .file-item-icon { flex-shrink: 0; color: var(--muted); } .file-item-info { flex: 1; min-width: 0; } .file-item-name { font-size: 0.85rem; font-weight: 500; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .file-item-meta { font-size: 0.72rem; color: var(--muted); margin-top: 1px; } .file-item-status { flex-shrink: 0; font-size: 0.78rem; font-weight: 600; } .file-item-status.status-waiting { color: var(--muted); } .file-item-status.status-uploading { color: var(--accent); } .file-item-status.status-done { color: var(--success); } .file-item-status.status-error { color: var(--error); } .file-item-remove { flex-shrink: 0; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; border: none; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer; transition: all var(--transition); } .file-item-remove:hover { background: var(--error-bg); color: var(--error); } /* 进度条 */ .progress-bar { width: 100%; height: 3px; background: var(--border); border-radius: 2px; margin-top: 6px; overflow: hidden; } .progress-bar-fill { height: 100%; background: linear-gradient(90deg, var(--accent), #d97706); border-radius: 2px; transition: width 0.3s ease; width: 0%; } /* ── 按钮 ───────────────────────────────────────────────── */ .form-actions { display: flex; gap: 10px; } .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 0.7rem 1.5rem; font-size: 0.9rem; font-weight: 600; font-family: var(--font); border: none; border-radius: var(--radius-sm); cursor: pointer; transition: all var(--transition); white-space: nowrap; } .btn:disabled { opacity: 0.5; cursor: not-allowed; } .btn-primary { flex: 1; background: linear-gradient(135deg, var(--accent), #d97706); color: white; box-shadow: 0 2px 8px rgba(180, 83, 9, 0.2); } .btn-primary:hover:not(:disabled) { box-shadow: 0 4px 14px rgba(180, 83, 9, 0.35); transform: translateY(-1px); } .btn-primary:active:not(:disabled) { transform: translateY(0); } .btn-secondary { background: var(--bg); color: var(--muted); border: 1.5px solid var(--border); } .btn-secondary:hover { border-color: var(--border-focus); color: var(--ink); background: var(--bg-hover); } /* ── 结果面板 ───────────────────────────────────────────── */ .result-panel { margin-top: 1.25rem; animation: slideIn 0.3s ease; } .result-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.25rem; box-shadow: var(--shadow); } .result-header { display: flex; align-items: center; gap: 10px; margin-bottom: 0.75rem; } .result-icon { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; } .result-icon.icon-success { background: var(--success-bg); color: var(--success); } .result-icon.icon-error { background: var(--error-bg); color: var(--error); } .result-title { font-size: 1rem; font-weight: 700; } .result-title.text-success { color: var(--success); } .result-title.text-error { color: var(--error); } .result-detail { font-size: 0.85rem; color: var(--muted); line-height: 1.7; } .result-detail strong { color: var(--ink); font-weight: 600; } .result-files { margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--border); } .result-file-item { display: flex; align-items: center; gap: 8px; padding: 0.35rem 0; font-size: 0.82rem; } .result-file-item svg { flex-shrink: 0; } .result-file-item.file-success { color: var(--success); } .result-file-item.file-error { color: var(--error); } /* ── 弹窗 ───────────────────────────────────────────────── */ .modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); backdrop-filter: blur(4px); z-index: 1000; align-items: center; justify-content: center; padding: 1rem; } .modal-overlay.active { display: flex; animation: fadeIn 0.2s ease; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .modal { background: var(--bg-card); border-radius: 14px; width: 100%; max-width: 380px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 4px 20px rgba(0, 0, 0, 0.08); animation: modalSlideUp 0.25s ease; } @keyframes modalSlideUp { from { opacity: 0; transform: translateY(20px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 1.1rem 1.25rem 0; } .modal-header h3 { font-size: 1.05rem; font-weight: 700; color: var(--ink); } .modal-close { display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer; transition: all var(--transition); } .modal-close:hover { background: var(--bg-hover); color: var(--ink); } .modal-body { padding: 1rem 1.25rem; } .modal-desc { font-size: 0.85rem; color: var(--muted); margin-bottom: 1rem; } .modal-captcha-row { display: flex; gap: 10px; align-items: center; margin-bottom: 0.75rem; } .modal-captcha-img { height: 46px; flex: 1; border-radius: var(--radius-sm); border: 1.5px solid var(--border); cursor: pointer; object-fit: contain; background: var(--bg); transition: opacity var(--transition); } .modal-captcha-img:hover { opacity: 0.85; } .modal-captcha-input { width: 100%; padding: 0.7rem 0.9rem; font-size: 1.1rem; font-family: var(--font); color: var(--ink); background: var(--bg); border: 1.5px solid var(--border); border-radius: var(--radius-sm); outline: none; letter-spacing: 0.2em; text-transform: uppercase; text-align: center; transition: border-color var(--transition), box-shadow var(--transition); } .modal-captcha-input::placeholder { letter-spacing: normal; text-transform: none; font-size: 0.85rem; color: #b5b0a8; } .modal-captcha-input:focus { border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(196, 168, 130, 0.15); } .modal-error { font-size: 0.8rem; color: var(--error); min-height: 1.2rem; margin-top: 0.4rem; } .modal-footer { display: flex; gap: 10px; padding: 0 1.25rem 1.25rem; } .modal-footer .btn { flex: 1; padding: 0.65rem 1rem; } /* ── 页脚 ───────────────────────────────────────────────── */ .footer { margin-top: 2rem; text-align: center; font-size: 0.78rem; color: #b5b0a8; } /* ── 响应式 ─────────────────────────────────────────────── */ @media (max-width: 560px) { body { padding: 1rem 0.75rem; } .header { margin-bottom: 1rem; } .header-icon { width: 40px; height: 40px; border-radius: 10px; margin-bottom: 0.5rem; } .header-icon svg { width: 22px; height: 22px; } .header h1 { font-size: 1.2rem; } .subtitle { font-size: 0.8rem; } .form { padding: 1.25rem; } .dropzone { padding: 1.5rem 1rem; } .btn-icon { width: 38px; height: 38px; } .form-actions { flex-direction: column; } } /* ── 工具类 ─────────────────────────────────────────────── */ .hidden { display: none !important; } .shake { animation: shake 0.4s ease; } @keyframes shake { 0%, 100% { transform: translateX(0); } 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }