Harshit Ghosh
feat: implement robust security middleware, authentication system, and frontend UI components
e4fd6e0 | /* ββ Detail page βββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .breadcrumb { | |
| padding: 8px 0; | |
| font-size: 0.88rem; | |
| color: var(--muted); | |
| } | |
| .breadcrumb a { | |
| color: var(--accent); | |
| text-decoration: none; | |
| } | |
| .sep { | |
| margin: 0 8px; | |
| opacity: 0.4; | |
| } | |
| .detail-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-start; | |
| gap: 16px; | |
| flex-wrap: wrap; | |
| margin: 6px 0 10px; | |
| } | |
| .detail-header h1 { | |
| font-size: 1.5rem; | |
| } | |
| .detail-actions { | |
| display: flex; | |
| gap: 8px; | |
| } | |
| .detail-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 16px; | |
| margin-top: 8px; | |
| } | |
| .kv-group { | |
| } | |
| .kv { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 9px 0; | |
| border-bottom: 1px solid rgba(36, 51, 86, 0.6); | |
| font-size: 0.92rem; | |
| gap: 12px; | |
| } | |
| .kv span { | |
| color: var(--muted); | |
| } | |
| .heatmap-img { | |
| width: 100%; | |
| border-radius: 12px; | |
| border: 1px solid var(--line); | |
| } | |
| .empty-state { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 48px 16px; | |
| gap: 12px; | |
| } | |
| /* Probability bar */ | |
| .prob-bar-wrap { | |
| margin-top: 20px; | |
| } | |
| .prob-bar-label { | |
| display: flex; | |
| justify-content: space-between; | |
| font-size: 0.78rem; | |
| color: var(--muted); | |
| margin-bottom: 4px; | |
| } | |
| .prob-bar { | |
| position: relative; | |
| height: 24px; | |
| border-radius: 12px; | |
| background: var(--bg2); | |
| border: 1px solid var(--line); | |
| overflow: visible; | |
| } | |
| .prob-fill { | |
| height: 100%; | |
| border-radius: 12px; | |
| transition: width 0.4s; | |
| } | |
| .fill-high { | |
| background: linear-gradient(90deg, #3b82f6, #6366f1); | |
| } | |
| .fill-medium { | |
| background: linear-gradient(90deg, #f59e0b, #f97316); | |
| } | |
| .fill-low { | |
| background: linear-gradient(90deg, #6b7280, #9ca3af); | |
| } | |
| .prob-marker { | |
| position: absolute; | |
| top: -22px; | |
| transform: translateX(-50%); | |
| font-size: 0.76rem; | |
| font-weight: 700; | |
| color: var(--text); | |
| } | |
| .json-pre { | |
| background: #080e1d; | |
| border: 1px solid var(--line); | |
| border-radius: 12px; | |
| padding: 16px; | |
| overflow: auto; | |
| max-height: 500px; | |
| font-size: 0.82rem; | |
| line-height: 1.5; | |
| } | |
| /* Disclaimer */ | |
| .disclaimer-box { | |
| margin-top: 16px; | |
| padding: 16px 20px; | |
| border-radius: var(--radius); | |
| background: rgba(251, 191, 36, 0.06); | |
| border: 1px solid rgba(251, 191, 36, 0.2); | |
| font-size: 0.9rem; | |
| line-height: 1.6; | |
| color: var(--muted); | |
| } | |
| .disclaimer-box strong { | |
| color: var(--orange); | |
| } | |
| /* ββ Evaluation page βββββββββββββββββββββββββββββββββββββββββ */ | |
| .eval-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 16px; | |
| margin-top: 16px; | |
| } | |
| .metric-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 10px; | |
| } | |
| .metric-card { | |
| background: var(--bg2); | |
| border: 1px solid var(--line); | |
| border-radius: 10px; | |
| padding: 14px; | |
| text-align: center; | |
| } | |
| .metric-label { | |
| font-size: 0.78rem; | |
| color: var(--muted); | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| } | |
| .metric-value { | |
| font-size: 1.3rem; | |
| font-weight: 800; | |
| margin-top: 2px; | |
| color: var(--accent); | |
| } | |
| /* Band analysis */ | |
| .band-grid { | |
| display: grid; | |
| grid-template-columns: repeat(3, 1fr); | |
| gap: 12px; | |
| margin-top: 12px; | |
| } | |
| .band-card { | |
| background: var(--bg2); | |
| border: 1px solid var(--line); | |
| border-radius: 12px; | |
| padding: 14px; | |
| } | |
| .band-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 12px; | |
| } | |
| .band-total { | |
| color: var(--muted); | |
| font-size: 0.85rem; | |
| } | |
| .band-bar-row { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| margin-bottom: 6px; | |
| } | |
| .band-bar-label { | |
| width: 60px; | |
| font-size: 0.8rem; | |
| color: var(--muted); | |
| } | |
| .band-bar { | |
| flex: 1; | |
| height: 14px; | |
| border-radius: 7px; | |
| background: var(--panel); | |
| overflow: hidden; | |
| } | |
| .band-bar-fill { | |
| height: 100%; | |
| border-radius: 7px; | |
| transition: width 0.4s; | |
| } | |
| .fill-red { | |
| background: var(--red); | |
| } | |
| .fill-green { | |
| background: var(--green); | |
| } | |
| .band-bar-val { | |
| width: 36px; | |
| font-size: 0.82rem; | |
| text-align: right; | |
| } | |
| /* Histogram */ | |
| .histogram { | |
| display: flex; | |
| align-items: flex-end; | |
| gap: 6px; | |
| margin-top: 12px; | |
| padding: 8px 0; | |
| min-height: 220px; | |
| } | |
| .hist-col { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| .hist-bar { | |
| width: 100%; | |
| border-radius: 6px 6px 0 0; | |
| background: linear-gradient(180deg, var(--accent), #3b82f6); | |
| min-height: 2px; | |
| position: relative; | |
| } | |
| .hist-count { | |
| position: absolute; | |
| top: -20px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| font-size: 0.72rem; | |
| font-weight: 600; | |
| color: var(--muted); | |
| } | |
| .hist-label { | |
| font-size: 0.72rem; | |
| color: var(--muted); | |
| margin-top: 4px; | |
| } | |
| /* ββ About page ββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .about-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 16px; | |
| margin-top: 16px; | |
| } | |
| /* Architecture flow */ | |
| .arch-flow { | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| flex-wrap: wrap; | |
| margin-top: 16px; | |
| padding: 12px 0; | |
| } | |
| .arch-step { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| background: var(--bg2); | |
| border: 1px solid var(--line); | |
| border-radius: 10px; | |
| padding: 10px 14px; | |
| } | |
| .arch-num { | |
| width: 26px; | |
| height: 26px; | |
| border-radius: 50%; | |
| background: var(--accent); | |
| color: var(--bg); | |
| font-weight: 800; | |
| font-size: 0.82rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .arch-label { | |
| font-size: 0.85rem; | |
| font-weight: 500; | |
| } | |
| .arch-arrow { | |
| color: var(--muted); | |
| font-size: 1.2rem; | |
| } | |
| /* Triage cards */ | |
| .triage-grid { | |
| display: grid; | |
| grid-template-columns: repeat(3, 1fr); | |
| gap: 12px; | |
| margin-top: 12px; | |
| } | |
| .triage-card { | |
| background: var(--bg2); | |
| border: 1px solid var(--line); | |
| border-radius: 12px; | |
| padding: 16px; | |
| } | |
| .triage-card p { | |
| font-size: 0.88rem; | |
| margin-top: 6px; | |
| color: var(--muted); | |
| } | |
| .triage-card p strong { | |
| color: var(--text); | |
| } | |
| .triage-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 8px; | |
| font-size: 0.85rem; | |
| color: var(--muted); | |
| } | |
| /* Ethics */ | |
| .ethics-columns { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 24px; | |
| margin-top: 12px; | |
| } | |
| .ethics-columns h4 { | |
| font-size: 0.95rem; | |
| margin-bottom: 8px; | |
| } | |
| .check-list, | |
| .cross-list { | |
| list-style: none; | |
| padding: 0; | |
| } | |
| .check-list li, | |
| .cross-list li { | |
| padding: 5px 0; | |
| padding-left: 24px; | |
| position: relative; | |
| font-size: 0.9rem; | |
| color: var(--muted); | |
| } | |
| .check-list li::before { | |
| content: "β"; | |
| position: absolute; | |
| left: 0; | |
| color: var(--green); | |
| font-weight: 700; | |
| } | |
| .cross-list li::before { | |
| content: "β"; | |
| position: absolute; | |
| left: 0; | |
| color: var(--red); | |
| font-weight: 700; | |
| } | |
| /* Tech tags */ | |
| .tech-tags { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 8px; | |
| margin-top: 4px; | |
| } | |
| .tech-tag { | |
| padding: 5px 14px; | |
| border-radius: 999px; | |
| font-size: 0.82rem; | |
| font-weight: 500; | |
| background: rgba(110, 168, 254, 0.08); | |
| border: 1px solid rgba(110, 168, 254, 0.2); | |
| color: var(--accent); | |
| } | |
| /* ββ Footer ββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .footer { | |
| margin-top: 48px; | |
| padding: 20px 0; | |
| border-top: 1px solid var(--line); | |
| text-align: center; | |
| font-size: 0.85rem; | |
| color: var(--muted); | |
| } | |
| .footer p + p { | |
| margin-top: 4px; | |
| } | |
| /* ββ Home Page βββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .home-hero { | |
| text-align: center; | |
| padding: 48px 0 12px; | |
| } | |
| .home-hero h1 { | |
| font-size: 2.2rem; | |
| font-weight: 800; | |
| } | |
| .home-hero p { | |
| color: var(--muted); | |
| margin-top: 8px; | |
| max-width: 600px; | |
| margin-left: auto; | |
| margin-right: auto; | |
| } | |
| .home-cards { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| margin-top: 32px; | |
| } | |
| .home-card { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| text-align: center; | |
| padding: 40px 32px; | |
| border-radius: var(--radius); | |
| border: 1px solid var(--line); | |
| background: linear-gradient(180deg, var(--panel2), var(--panel)); | |
| text-decoration: none; | |
| color: var(--text); | |
| transition: all 0.2s; | |
| } | |
| .home-card:hover { | |
| border-color: var(--accent); | |
| transform: translateY(-2px); | |
| box-shadow: 0 8px 32px rgba(110, 168, 254, 0.1); | |
| } | |
| .home-card-icon { | |
| color: var(--accent); | |
| margin-bottom: 16px; | |
| } | |
| .home-card h2 { | |
| font-size: 1.3rem; | |
| font-weight: 700; | |
| margin-bottom: 8px; | |
| } | |
| .home-card p { | |
| color: var(--muted); | |
| font-size: 0.92rem; | |
| line-height: 1.5; | |
| } | |
| .home-card-action { | |
| margin-top: 16px; | |
| color: var(--accent); | |
| font-weight: 600; | |
| font-size: 0.9rem; | |
| } | |
| .home-cards-secondary { | |
| grid-template-columns: repeat(3, 1fr); | |
| margin-top: 16px; | |
| } | |
| .home-card-sm { | |
| padding: 28px 24px; | |
| } | |
| .home-card-sm h3 { | |
| font-size: 1.05rem; | |
| font-weight: 700; | |
| margin-bottom: 4px; | |
| } | |
| /* ββ Page Header βββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .page-header { | |
| margin-bottom: 24px; | |
| } | |
| .page-header h1 { | |
| font-size: 1.8rem; | |
| font-weight: 800; | |
| } | |
| .page-header p { | |
| color: var(--muted); | |
| margin-top: 6px; | |
| line-height: 1.5; | |
| } | |
| /* ββ Logs βββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .log-summary { | |
| margin-bottom: 12px; | |
| } | |
| .logs-table td code { | |
| font-family: "SF Mono", "Cascadia Code", monospace; | |
| font-size: 0.85rem; | |
| color: var(--accent); | |
| } | |
| .log-actions { | |
| display: flex; | |
| gap: 6px; | |
| } | |
| /* ββ Upload Page βββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .upload-hero { | |
| padding: 8px 0 6px; | |
| } | |
| .upload-hero h1 { | |
| font-size: 1.8rem; | |
| font-weight: 800; | |
| } | |
| .upload-hero p { | |
| color: var(--muted); | |
| margin-top: 6px; | |
| } | |
| .upload-panel { | |
| position: relative; | |
| } | |
| .dropzone { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 48px 24px; | |
| border: 2px dashed var(--line); | |
| border-radius: 12px; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| color: var(--muted); | |
| } | |
| .dropzone:hover, | |
| .dropzone.dragover { | |
| border-color: var(--accent); | |
| background: rgba(110, 168, 254, 0.04); | |
| } | |
| .dropzone-text { | |
| font-size: 1.05rem; | |
| font-weight: 600; | |
| margin-top: 12px; | |
| color: var(--text); | |
| } | |
| .file-info { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding: 14px 16px; | |
| border: 1px solid var(--accent); | |
| border-radius: 10px; | |
| background: rgba(110, 168, 254, 0.06); | |
| color: var(--accent); | |
| font-weight: 500; | |
| } | |
| .file-info span { | |
| flex: 1; | |
| } | |
| .btn-primary { | |
| margin-top: 16px; | |
| width: 100%; | |
| justify-content: center; | |
| padding: 12px 24px; | |
| background: linear-gradient(135deg, #3b82f6, #6366f1); | |
| border-color: #3b82f6; | |
| font-weight: 600; | |
| font-size: 0.95rem; | |
| } | |
| .btn-primary:hover { | |
| background: linear-gradient(135deg, #2563eb, #4f46e5); | |
| } | |
| .btn-primary:disabled { | |
| opacity: 0.4; | |
| cursor: not-allowed; | |
| } | |
| .loading-overlay { | |
| position: absolute; | |
| inset: 0; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| background: rgba(17, 28, 51, 0.95); | |
| border-radius: var(--radius); | |
| z-index: 10; | |
| gap: 16px; | |
| } | |
| .spinner { | |
| width: 48px; | |
| height: 48px; | |
| border: 3px solid var(--line); | |
| border-top-color: var(--accent); | |
| border-radius: 50%; | |
| animation: spin 0.8s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { | |
| transform: rotate(360deg); | |
| } | |
| } | |
| .user-menu { | |
| position: relative; | |
| display: flex; | |
| align-items: center; | |
| } | |
| .user-button { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| padding: 8px 16px; | |
| background: none; | |
| border: 1px solid #e5e7eb; | |
| border-radius: 6px; | |
| color: #374151; | |
| font-size: 14px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| } | |
| .user-button:hover { | |
| background-color: #f9fafb; | |
| border-color: #d1d5db; | |
| } | |
| .user-menu-dropdown { | |
| display: none; | |
| position: absolute; | |
| top: 100%; | |
| right: 0; | |
| margin-top: 8px; | |
| background: white; | |
| border: 1px solid #e5e7eb; | |
| border-radius: 6px; | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| min-width: 160px; | |
| z-index: 1000; | |
| } | |
| .user-menu-dropdown.active { | |
| display: block; | |
| } | |
| .menu-item { | |
| display: block; | |
| width: 100%; | |
| padding: 12px 16px; | |
| text-align: left; | |
| color: #374151; | |
| text-decoration: none; | |
| font-size: 14px; | |
| transition: all 0.2s; | |
| border: none; | |
| background: none; | |
| cursor: pointer; | |
| } | |
| .menu-item:hover { | |
| background-color: #f3f4f6; | |
| color: #111827; | |
| } | |
| .menu-item:first-child { | |
| border-radius: 5px 5px 0 0; | |
| } | |
| .logout-btn { | |
| color: #dc2626; | |
| } | |
| .logout-btn:hover { | |
| background-color: #fef2f2; | |
| color: #991b1b; | |
| } | |
| .logout-form { | |
| width: 100%; | |
| margin: 0; | |
| } | |
| .user-menu-dropdown hr { | |
| margin: 4px 0; | |
| border: none; | |
| border-top: 1px solid #e5e7eb; | |
| } | |
| .auth-buttons { | |
| display: flex; | |
| gap: 10px; | |
| align-items: center; | |
| } | |
| .profile-container { | |
| display: flex; | |
| justify-content: center; | |
| padding: 40px 20px; | |
| max-width: 600px; | |
| margin: 0 auto; | |
| } | |
| .profile-card { | |
| background: white; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | |
| padding: 40px; | |
| width: 100%; | |
| } | |
| .profile-card h1 { | |
| margin-bottom: 30px; | |
| color: #333; | |
| } | |
| .profile-section { | |
| margin-bottom: 30px; | |
| padding-bottom: 20px; | |
| border-bottom: 1px solid #eee; | |
| } | |
| .profile-section h3 { | |
| color: #333; | |
| margin-bottom: 15px; | |
| } | |
| .profile-item { | |
| display: flex; | |
| justify-content: space-between; | |
| padding: 12px 0; | |
| border-bottom: 1px solid #f5f5f5; | |
| } | |
| .profile-label { | |
| font-weight: 500; | |
| color: #666; | |
| } | |
| .profile-value { | |
| color: #333; | |
| } | |
| .profile-footer { | |
| margin-top: 30px; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| z-index: 1000; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(0, 0, 0, 0.4); | |
| } | |
| .modal-content { | |
| background-color: white; | |
| margin: 10% auto; | |
| padding: 30px; | |
| border-radius: 8px; | |
| width: 90%; | |
| max-width: 400px; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); | |
| } | |
| .close { | |
| color: #aaa; | |
| float: right; | |
| font-size: 28px; | |
| font-weight: bold; | |
| cursor: pointer; | |
| background: none; | |
| border: none; | |
| padding: 0; | |
| } | |
| .close:hover { | |
| color: #000; | |
| } | |
| .form-group { | |
| display: flex; | |
| flex-direction: column; | |
| margin-bottom: 15px; | |
| } | |
| .form-group label { | |
| margin-bottom: 8px; | |
| font-weight: 500; | |
| color: #333; | |
| } | |
| .form-group small { | |
| font-size: 12px; | |
| color: #666; | |
| margin-top: 4px; | |
| } | |
| @media (max-width: 768px) { | |
| .user-button { | |
| padding: 8px 12px; | |
| font-size: 13px; | |
| } | |
| .user-button svg { | |
| width: 18px; | |
| height: 18px; | |
| } | |
| .auth-buttons { | |
| gap: 8px; | |
| } | |
| .profile-container { | |
| padding: 24px 16px; | |
| } | |
| .profile-card { | |
| padding: 24px 18px; | |
| } | |
| .profile-item { | |
| flex-direction: column; | |
| gap: 4px; | |
| } | |
| } | |
| .steps-grid { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 16px; | |
| margin-top: 12px; | |
| } | |
| .step { | |
| display: flex; | |
| align-items: flex-start; | |
| gap: 12px; | |
| } | |
| .step-num { | |
| width: 28px; | |
| height: 28px; | |
| border-radius: 50%; | |
| background: var(--accent); | |
| color: var(--bg); | |
| font-weight: 800; | |
| font-size: 0.82rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| flex-shrink: 0; | |
| } | |
| .step-text strong { | |
| font-size: 0.92rem; | |
| } | |
| /* ββ Flash Messages ββββββββββββββββββββββββββββββββββββββββββ */ | |
| .flash-messages { | |
| margin-bottom: 16px; | |
| } | |
| .flash { | |
| padding: 12px 16px; | |
| border-radius: 10px; | |
| font-size: 0.9rem; | |
| margin-bottom: 8px; | |
| } | |
| .flash-error { | |
| background: rgba(251, 113, 133, 0.1); | |
| border: 1px solid rgba(251, 113, 133, 0.3); | |
| color: var(--red); | |
| } | |
| .flash-success { | |
| background: rgba(52, 211, 153, 0.1); | |
| border: 1px solid rgba(52, 211, 153, 0.3); | |
| color: var(--green); | |
| } | |
| /* ββ Upload Tabs βββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .upload-tabs { | |
| display: flex; | |
| gap: 4px; | |
| margin-bottom: 0; | |
| border-bottom: 2px solid var(--line); | |
| padding-bottom: 0; | |
| } | |
| .upload-tab { | |
| padding: 10px 20px; | |
| background: none; | |
| border: none; | |
| color: var(--muted); | |
| font-size: 0.9rem; | |
| font-weight: 600; | |
| font-family: inherit; | |
| cursor: pointer; | |
| border-bottom: 2px solid transparent; | |
| margin-bottom: -2px; | |
| transition: all 0.15s; | |
| } | |
| .upload-tab:hover { | |
| color: var(--text); | |
| } | |
| .upload-tab.active { | |
| color: var(--accent); | |
| border-bottom-color: var(--accent); | |
| } | |
| .tab-panel { | |
| display: none; | |
| margin-top: 16px; | |
| } | |
| .tab-panel.active { | |
| display: block; | |
| } | |
| /* ββ Directory Input βββββββββββββββββββββββββββββββββββββββββ */ | |
| .dir-label { | |
| display: block; | |
| font-weight: 600; | |
| margin-bottom: 8px; | |
| font-size: 0.92rem; | |
| } | |
| .dir-input-row { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .dir-input-row .input { | |
| flex: 1; | |
| padding: 10px 14px; | |
| font-size: 0.92rem; | |
| font-family: "SF Mono", "Cascadia Code", monospace; | |
| background: var(--panel); | |
| border: 1px solid var(--line); | |
| border-radius: var(--radius); | |
| color: var(--text); | |
| outline: none; | |
| transition: border-color 0.15s; | |
| } | |
| .dir-input-row .input:focus { | |
| border-color: var(--accent); | |
| } | |
| .dir-input-row .btn-primary { | |
| margin-top: 0; | |
| width: auto; | |
| white-space: nowrap; | |
| } | |
| /* ββ Batch Progress Page βββββββββββββββββββββββββββββββββββββ */ | |
| .batch-header { | |
| margin-bottom: 20px; | |
| } | |
| .batch-header h1 { | |
| font-size: 1.6rem; | |
| font-weight: 800; | |
| } | |
| .batch-panel { | |
| padding: 24px; | |
| } | |
| .batch-stats-row { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 12px; | |
| margin-bottom: 20px; | |
| } | |
| .batch-stat { | |
| text-align: center; | |
| } | |
| .batch-stat-label { | |
| display: block; | |
| font-size: 0.78rem; | |
| color: var(--muted); | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 0.04em; | |
| } | |
| .batch-stat-value { | |
| display: block; | |
| font-size: 1.6rem; | |
| font-weight: 800; | |
| margin-top: 2px; | |
| } | |
| .batch-stat.accent-green .batch-stat-value { | |
| color: var(--green); | |
| } | |
| .batch-stat.accent-red .batch-stat-value { | |
| color: var(--red); | |
| } | |
| .progress-track { | |
| width: 100%; | |
| height: 12px; | |
| background: var(--panel); | |
| border: 1px solid var(--line); | |
| border-radius: 6px; | |
| overflow: hidden; | |
| } | |
| .progress-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, #3b82f6, #6366f1); | |
| border-radius: 6px; | |
| transition: width 0.4s ease; | |
| } | |
| .progress-text { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-top: 8px; | |
| font-size: 0.88rem; | |
| font-weight: 600; | |
| } | |
| .batch-feed { | |
| list-style: none; | |
| padding: 0; | |
| margin: 0; | |
| } | |
| .batch-feed li { | |
| padding: 6px 0; | |
| border-bottom: 1px solid var(--line); | |
| font-size: 0.88rem; | |
| } | |
| .batch-feed li a { | |
| color: var(--accent); | |
| text-decoration: none; | |
| } | |
| .batch-feed li a:hover { | |
| text-decoration: underline; | |
| } | |
| .batch-done-panel { | |
| text-align: center; | |
| padding: 40px 24px; | |
| } | |
| .batch-done-icon { | |
| margin-bottom: 16px; | |
| } | |
| .batch-done-panel h2 { | |
| font-size: 1.5rem; | |
| font-weight: 800; | |
| margin-bottom: 8px; | |
| } | |
| .batch-done-actions { | |
| display: flex; | |
| gap: 12px; | |
| justify-content: center; | |
| margin-top: 20px; | |
| } | |
| .batch-done-actions .btn-primary { | |
| width: auto; | |
| margin-top: 0; | |
| } | |
| .batch-fail-list { | |
| padding-left: 20px; | |
| } | |
| .batch-fail-list li { | |
| color: var(--red); | |
| font-family: "SF Mono", "Cascadia Code", monospace; | |
| font-size: 0.85rem; | |
| padding: 3px 0; | |
| } | |
| .text-red { | |
| color: var(--red); | |
| } | |