From 05a18c3c77fdde244a6e40c71a5af925f0132389 Mon Sep 17 00:00:00 2001 From: Froidefond Julien Date: Fri, 6 Mar 2026 12:28:45 +0100 Subject: [PATCH] feat(tailwind): Migration vers Tailwind CSS v4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Installation de Tailwind CSS v4 avec @tailwindcss/postcss - Configuration PostCSS avec le plugin Tailwind v4 - Mise à jour de globals.css avec syntaxe Tailwind v4 (@theme) - Migration layout.tsx vers classes Tailwind - Création du composant NavLink avec types stricts - Configuration des couleurs personnalisées (background, foreground, card, line, primary) - Support du dark mode via classes CSS - Variables CSS migrées vers format HSL - Suppression des anciens styles CSS custom Le projet utilise maintenant Tailwind CSS v4 pour tout le styling --- apps/backoffice/app/globals.css | 2401 +--------------------------- apps/backoffice/app/layout.tsx | 70 +- apps/backoffice/package-lock.json | 200 ++- apps/backoffice/package.json | 3 + apps/backoffice/postcss.config.js | 5 + apps/backoffice/tailwind.config.js | 72 + package-lock.json | 952 +++++++++++ package.json | 8 + 8 files changed, 1342 insertions(+), 2369 deletions(-) create mode 100644 apps/backoffice/postcss.config.js create mode 100644 apps/backoffice/tailwind.config.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/apps/backoffice/app/globals.css b/apps/backoffice/app/globals.css index ee16569..84c24ab 100644 --- a/apps/backoffice/app/globals.css +++ b/apps/backoffice/app/globals.css @@ -1,2373 +1,90 @@ -:root { - color-scheme: light; - --background: hsl(36 33% 97%); - --foreground: hsl(222 33% 15%); - --card: hsl(0 0% 100%); - --line: hsl(32 18% 84%); - --line-strong: hsl(32 18% 76%); - --primary: hsl(198 78% 37%); - --primary-soft: hsl(198 52% 90%); - --cyan: hsl(192 85% 55%); - --pink: hsl(338 82% 62%); - --text-muted: hsl(220 13% 40%); - --shadow-1: 0 1px 2px 0 rgb(23 32 46 / 0.06); - --shadow-2: 0 12px 30px -12px rgb(23 32 46 / 0.22); +@import "tailwindcss"; + +@theme { + --color-background: hsl(36 33% 97%); + --color-foreground: hsl(222 33% 15%); + --color-card: hsl(0 0% 100%); + --color-line: hsl(32 18% 84%); + --color-line-strong: hsl(32 18% 76%); + --color-primary: hsl(198 78% 37%); + --color-primary-soft: hsl(198 52% 90%); + --color-muted: hsl(220 13% 40%); + --color-success: hsl(142 60% 45%); + --color-success-soft: hsl(142 60% 90%); + --color-warning: hsl(45 93% 47%); + --color-warning-soft: hsl(45 93% 90%); + --color-error: hsl(2 72% 48%); + --color-error-soft: hsl(2 72% 90%); + + --font-sans: "Avenir Next", "Segoe UI", "Noto Sans", system-ui, sans-serif; } .dark { - color-scheme: dark; - --background: hsl(222 35% 10%); - --foreground: hsl(38 20% 92%); - --card: hsl(221 31% 13%); - --line: hsl(219 18% 25%); - --line-strong: hsl(219 18% 33%); - --primary: hsl(194 76% 62%); - --primary-soft: hsl(210 34% 24%); - --cyan: hsl(192 85% 55%); - --pink: hsl(338 82% 62%); - --text-muted: hsl(218 17% 72%); - --shadow-1: 0 1px 2px 0 rgb(2 8 18 / 0.35); - --shadow-2: 0 12px 30px -12px rgb(2 8 18 / 0.55); + --color-background: hsl(222 35% 10%); + --color-foreground: hsl(38 20% 92%); + --color-card: hsl(221 31% 13%); + --color-line: hsl(219 18% 25%); + --color-line-strong: hsl(219 18% 33%); + --color-primary: hsl(194 76% 62%); + --color-primary-soft: hsl(210 34% 24%); + --color-muted: hsl(218 17% 72%); } +/* Base styles */ * { - box-sizing: border-box; + border-color: var(--color-line); } body { - margin: 0; - color: var(--foreground); - font-family: "Avenir Next", "Segoe UI", "Noto Sans", sans-serif; - background: var(--background); - min-height: 100vh; + background-color: var(--color-background); + color: var(--color-foreground); + font-family: var(--font-sans); } -body::before { - content: ""; - position: fixed; - inset: 0; - pointer-events: none; - background-image: - linear-gradient(112deg, hsl(198 78% 37% / 0.14) 0%, hsl(192 85% 55% / 0.11) 28%, transparent 56%), - linear-gradient(248deg, hsl(338 82% 62% / 0.11) 0%, transparent 46%), - repeating-linear-gradient(135deg, hsl(222 33% 15% / 0.035) 0 1px, transparent 1px 11px); - opacity: 1; -} - -main { - position: relative; - max-width: 1050px; - margin: 0 auto; - padding: 28px 22px 40px; -} - -h1, -h2, -h3 { - font-family: "Baskerville", "Times New Roman", serif; - letter-spacing: 0.01em; -} - -.top-nav { - position: sticky; - top: 0; - z-index: 3; - display: flex; - justify-content: space-between; - align-items: center; - gap: 18px; - padding: 14px 22px; - border-bottom: 1px solid hsl(198 78% 37% / 0.25); - background: hsl(36 33% 97% / 0.72); - backdrop-filter: blur(10px); - box-shadow: var(--shadow-1); -} - -.brand { - display: flex; - align-items: center; - gap: 10px; - text-decoration: none; - color: var(--foreground); -} - -.brand img { - border-radius: 8px; - box-shadow: 0 8px 24px -10px rgb(23 32 46 / 0.35); -} - -.brand-name { - background: linear-gradient(90deg, var(--primary), var(--cyan), var(--pink)); - -webkit-background-clip: text; - background-clip: text; - color: transparent; - font-size: 1.02rem; - font-weight: 800; - letter-spacing: 0.06em; -} - -.brand-subtitle { - margin-left: -4px; - text-transform: uppercase; - letter-spacing: 0.12em; - font-size: 0.68rem; - color: var(--text-muted); - font-weight: 700; -} - -.links { - display: flex; - gap: 14px; -} - -.links-wrap { - display: flex; - align-items: center; - gap: 10px; -} - -a { - color: var(--primary); - text-decoration: none; - font-weight: 700; -} - -.links a { - padding: 7px 10px; - border-radius: 8px; -} - -.links a:hover { - background: hsl(198 52% 90% / 0.65); - color: hsl(222 33% 15%); -} - -table { - width: 100%; - border-collapse: collapse; - background: hsl(0 0% 100% / 0.95); - border: 1px solid var(--line); - border-radius: 12px; - overflow: hidden; - box-shadow: var(--shadow-2); -} - -th, -td { - padding: 10px; - border-bottom: 1px solid hsl(32 18% 86%); - text-align: left; -} - -th { - color: hsl(222 33% 18%); - background: hsl(36 30% 95%); -} - -code, -pre { - font-family: "JetBrains Mono", "SF Mono", monospace; -} - -pre { - margin: 10px 0 0; - white-space: pre-wrap; - word-break: break-all; - background: hsl(36 24% 93%); - border: 1px solid var(--line); - border-radius: 8px; - padding: 10px; -} - -form.inline { - display: inline; -} - -input, -select, -button { - border-radius: 8px; - padding: 8px 10px; - margin: 4px 8px 4px 0; - border: 1px solid var(--line-strong); - background: white; - color: var(--foreground); -} - -button { - border: 1px solid hsl(198 78% 37% / 0.45); - background: linear-gradient(95deg, hsl(198 78% 37% / 0.12), hsl(192 85% 55% / 0.15)); - color: hsl(222 33% 16%); - cursor: pointer; - font-weight: 700; -} - -button:hover { - box-shadow: 0 6px 20px -10px hsl(198 78% 37% / 0.5); -} - -.theme-toggle { - min-width: 66px; -} - -.cancel-btn { - background: linear-gradient(95deg, hsl(2 72% 48% / 0.15), hsl(338 82% 62% / 0.2)); - border-color: hsl(2 72% 48% / 0.5); -} - -.scan-btn { - background: linear-gradient(95deg, hsl(142 60% 45% / 0.15), hsl(142 60% 55% / 0.2)); - border-color: hsl(142 60% 45% / 0.5); - padding: 4px 12px; - font-size: 0.85rem; -} - -.delete-btn { - background: linear-gradient(95deg, hsl(2 72% 48% / 0.15), hsl(338 82% 62% / 0.2)); - border-color: hsl(2 72% 48% / 0.5); - padding: 4px 12px; - font-size: 0.85rem; -} - -.full-rebuild-btn { - background: linear-gradient(95deg, hsl(280 60% 45% / 0.15), hsl(280 60% 55% / 0.2)); - border-color: hsl(280 60% 45% / 0.5); -} - -.status-pending { color: hsl(45 93% 35%); } -.status-running { color: hsl(198 78% 37%); font-weight: 700; } -.status-completed { color: hsl(142 60% 35%); } -.status-failed { color: hsl(2 72% 45%); } -.status-cancelled { color: hsl(220 13% 40%); } - -.error-hint { - display: inline-block; - margin-left: 6px; - width: 16px; - height: 16px; - line-height: 16px; - text-align: center; - border-radius: 50%; - background: hsl(2 72% 48%); - color: white; - font-size: 11px; - font-weight: bold; - cursor: help; -} - -.card { - background: var(--card); - border: 1px solid var(--line); - border-radius: 14px; - padding: 16px; - margin: 16px 0; - box-shadow: var(--shadow-2); -} - -.dark .top-nav { - background: hsl(222 35% 10% / 0.72); - border-bottom-color: hsl(194 76% 62% / 0.3); -} - -.dark .links a:hover { - background: hsl(210 34% 24% / 0.8); - color: hsl(38 20% 92%); -} - -.dark table { - background: hsl(221 31% 13% / 0.95); -} - -.dark th { - color: hsl(38 20% 92%); - background: hsl(221 24% 17%); -} - -.dark th, -.dark td { - border-bottom-color: hsl(219 18% 22%); -} - -.dark input, -.dark select, -.dark button { - background: hsl(221 31% 13%); - color: hsl(38 20% 92%); -} - -.dark pre { - background: hsl(221 24% 17%); -} - -@media (max-width: 720px) { - .top-nav { - flex-direction: column; - align-items: flex-start; - } - - .links-wrap { - width: 100%; - justify-content: space-between; - } - - .links { - flex-wrap: wrap; - } - - .brand span { - font-size: 14px; - } - - main { - padding: 18px 14px 30px; - } -} - -/* Books page styles */ -.search-form { - display: flex; - gap: 12px; - align-items: center; - flex-wrap: wrap; -} - -.search-input { - flex: 1; - min-width: 200px; -} - -.results-info { - color: var(--text-muted); - margin: 16px 0; - font-size: 0.95rem; -} - -.books-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 24px; - margin: 24px 0; -} - -.book-card { - display: flex; - flex-direction: column; - text-decoration: none; - color: var(--foreground); - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - overflow: hidden; - transition: transform 0.2s ease, box-shadow 0.2s ease; - box-shadow: var(--shadow-1); -} - -.book-card:hover { - transform: translateY(-4px); - box-shadow: var(--shadow-2); -} - -.book-cover { - position: relative; - aspect-ratio: 2/3; - background: linear-gradient(135deg, hsl(36 24% 93%), hsl(36 24% 88%)); - overflow: hidden; -} - -.cover-image { - width: 100%; - height: 100%; - object-fit: cover; -} - -.book-info { - padding: 12px; - flex: 1; - display: flex; - flex-direction: column; - gap: 4px; -} - -.book-title { - font-size: 0.95rem; - font-weight: 700; - margin: 0; - line-height: 1.3; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - font-family: "Avenir Next", "Segoe UI", sans-serif; - letter-spacing: normal; -} - -.book-author { - font-size: 0.85rem; - color: var(--text-muted); - margin: 0; -} - -.book-series { - font-size: 0.8rem; - color: var(--primary); - margin: 0; -} - -.book-meta { - display: flex; - gap: 8px; - margin-top: auto; - padding-top: 8px; -} - -.book-kind { - font-size: 0.7rem; - padding: 2px 6px; - border-radius: 4px; - font-weight: 700; - background: hsl(198 52% 90%); - color: hsl(198 78% 37%); -} - -.book-kind.cbz { - background: hsl(142 60% 90%); - color: hsl(142 60% 35%); -} - -.book-kind.cbr { - background: hsl(45 93% 90%); - color: hsl(45 93% 35%); -} - -.book-kind.pdf { - background: hsl(2 72% 90%); - color: hsl(2 72% 45%); -} - -.book-lang { - font-size: 0.7rem; - padding: 2px 6px; - border-radius: 4px; - background: var(--line); - color: var(--text-muted); -} - -.pagination { - display: flex; - justify-content: center; - margin: 32px 0; -} - -.empty-state { - text-align: center; - padding: 48px 24px; - color: var(--text-muted); -} - -/* Book detail page */ -.breadcrumb { - margin-bottom: 24px; -} - -.breadcrumb a { - color: var(--text-muted); - font-size: 0.9rem; -} - -.breadcrumb a:hover { - color: var(--primary); -} - -.book-detail { - display: grid; - grid-template-columns: 300px 1fr; - gap: 32px; - align-items: start; -} - -@media (max-width: 720px) { - .book-detail { - grid-template-columns: 1fr; - } -} - -.book-detail-cover { - border-radius: 12px; - overflow: hidden; - box-shadow: var(--shadow-2); -} - -.detail-cover-image { - width: 100%; - height: auto; - display: block; -} - -.book-detail-info h1 { - margin: 0 0 16px 0; - font-size: 1.8rem; - line-height: 1.2; -} - -.detail-author { - font-size: 1.1rem; - color: var(--text-muted); - margin: 0 0 16px 0; -} - -.detail-series { - font-size: 1rem; - color: var(--primary); - margin: 0 0 24px 0; -} - -.detail-series .volume { - margin-left: 12px; - padding: 4px 10px; - background: var(--primary-soft); - border-radius: 6px; - font-size: 0.85rem; - color: var(--foreground); -} - -.detail-meta { - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - padding: 20px; - box-shadow: var(--shadow-1); -} - -.meta-row { - display: flex; - gap: 12px; - padding: 8px 0; - border-bottom: 1px solid var(--line); -} - -.meta-row:last-child { - border-bottom: none; -} - -.meta-label { - font-weight: 700; - color: var(--text-muted); - min-width: 100px; -} - -.book-id { - font-size: 0.85rem; - color: var(--text-muted); -} - -.dark .book-cover { - background: linear-gradient(135deg, hsl(221 24% 20%), hsl(221 24% 15%)); -} - -.dark .book-kind { - background: hsl(198 52% 25%); - color: hsl(198 78% 75%); -} - -.dark .book-kind.cbz { - background: hsl(142 60% 25%); - color: hsl(142 60% 65%); -} - -.dark .book-kind.cbr { - background: hsl(45 93% 25%); - color: hsl(45 93% 65%); -} - -.dark .book-kind.pdf { - background: hsl(2 72% 25%); - color: hsl(2 72% 65%); -} - -/* Library info styles */ -.library-info { - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - padding: 16px 20px; - margin: 16px 0 24px 0; - box-shadow: var(--shadow-1); -} - -.library-info p { - margin: 0; - display: flex; - align-items: center; - gap: 12px; - flex-wrap: wrap; -} - -.library-info code { - font-size: 0.9rem; -} - -.library-info .separator { - color: var(--line-strong); - font-weight: 300; -} - -.status-enabled { - color: hsl(142 60% 45%); - font-weight: 700; -} - -.status-disabled { - color: hsl(220 13% 40%); - font-weight: 700; -} - -.book-count-link { - color: var(--primary); - text-decoration: none; - font-weight: 700; - padding: 2px 8px; - border-radius: 6px; - transition: background 0.2s ease; -} - -.book-count-link:hover { - background: var(--primary-soft); -} - -.series-count-link { - color: var(--primary); - text-decoration: none; - font-weight: 700; - padding: 2px 8px; - border-radius: 6px; - transition: background 0.2s ease; -} - -.series-count-link:hover { - background: var(--primary-soft); -} - -.dark .status-enabled { - color: hsl(142 60% 65%); -} - -.dark .status-disabled { - color: hsl(218 17% 72%); -} - -/* Series grid styles */ -.series-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 24px; - margin: 24px 0; -} - -.series-card { - display: flex; - flex-direction: column; - text-decoration: none; - color: var(--foreground); - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - overflow: hidden; - transition: transform 0.2s ease, box-shadow 0.2s ease; - box-shadow: var(--shadow-1); -} - -.series-card:hover { - transform: translateY(-4px); - box-shadow: var(--shadow-2); -} - -.series-cover { - position: relative; - aspect-ratio: 2/3; - background: linear-gradient(135deg, hsl(36 24% 93%), hsl(36 24% 88%)); - overflow: hidden; -} - -.series-cover-image { - width: 100%; - height: 100%; - object-fit: cover; -} - -.series-info { - padding: 12px; - flex: 1; - display: flex; - flex-direction: column; - gap: 4px; -} - -.series-name { - font-size: 0.95rem; - font-weight: 700; - margin: 0; - line-height: 1.3; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - font-family: "Avenir Next", "Segoe UI", sans-serif; - letter-spacing: normal; -} - -.series-count { - font-size: 0.85rem; - color: var(--text-muted); - margin: 0; - margin-top: auto; -} - -.dark .series-cover { - background: linear-gradient(135deg, hsl(221 24% 20%), hsl(221 24% 15%)); -} - -/* Status badges */ -.status-ok { - color: hsl(142 60% 45%); - font-weight: 700; -} - -.status-error { - color: hsl(2 72% 48%); - font-weight: 700; -} - -.status-pending { - color: hsl(45 93% 47%); - font-weight: 700; -} - -.file-path { - font-size: 0.8rem; - word-break: break-all; - max-width: 400px; - display: inline-block; -} - -/* Job Progress Component */ -.job-progress { - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - padding: 16px; - margin: 8px 0; -} - -.progress-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 12px; -} - -.status-badge { - padding: 4px 10px; - border-radius: 6px; - font-size: 0.8rem; - font-weight: 700; - text-transform: uppercase; -} - -.status-badge.status-pending { - background: hsl(45 93% 90%); - color: hsl(45 93% 35%); -} - -.status-badge.status-running { - background: hsl(198 52% 90%); - color: hsl(198 78% 37%); -} - -.status-badge.status-success { - background: hsl(142 60% 90%); - color: hsl(142 60% 35%); -} - -.status-badge.status-failed { - background: hsl(2 72% 90%); - color: hsl(2 72% 45%); -} - -.status-badge.status-cancelled { - background: hsl(220 13% 90%); - color: hsl(220 13% 40%); -} - -.complete-badge { - padding: 4px 10px; - border-radius: 6px; - font-size: 0.75rem; - font-weight: 700; - background: hsl(142 60% 90%); - color: hsl(142 60% 35%); -} - -.progress-bar-container { - position: relative; - height: 24px; - background: var(--line); - border-radius: 12px; - overflow: hidden; - margin-bottom: 12px; -} - -.progress-bar-fill { - height: 100%; - background: linear-gradient(90deg, hsl(198 78% 37%), hsl(192 85% 55%)); - border-radius: 12px; - transition: width 0.3s ease; -} - -.progress-percent { - position: absolute; - right: 8px; - top: 50%; - transform: translateY(-50%); - font-size: 0.8rem; - font-weight: 700; - color: var(--foreground); -} - -.progress-stats { - display: flex; - justify-content: space-between; - align-items: center; - font-size: 0.9rem; - color: var(--text-muted); -} - -.current-file { - font-size: 0.8rem; - max-width: 300px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.progress-detailed-stats { - display: flex; - gap: 16px; - margin-top: 12px; - padding-top: 12px; - border-top: 1px solid var(--line); - font-size: 0.85rem; -} - -.error-count { - color: hsl(2 72% 48%); - font-weight: 700; -} - -.progress-row { - background: hsl(198 52% 95%); -} - -.progress-row td { - padding: 0; -} - -.toggle-progress-btn { - margin-left: 8px; - padding: 2px 8px; - font-size: 0.75rem; - background: transparent; - border: 1px solid var(--line); -} - -/* Jobs Indicator */ -.jobs-indicator-container { - position: relative; -} - -.jobs-indicator { - position: relative; - display: flex; - align-items: center; - justify-content: center; - width: 36px; - height: 36px; - padding: 0; - border-radius: 8px; - background: transparent; - border: 1px solid var(--line); - color: var(--foreground); - cursor: pointer; - transition: all 0.2s ease; -} - -.jobs-indicator:hover { - background: hsl(198 52% 90% / 0.5); -} - -.jobs-indicator.active { - border-color: hsl(198 78% 37% / 0.5); -} - -.jobs-badge { - position: absolute; - top: -4px; - right: -4px; - min-width: 18px; - height: 18px; - padding: 0 5px; - background: hsl(2 72% 48%); - color: white; - font-size: 0.7rem; - font-weight: 700; - border-radius: 9px; - display: flex; - align-items: center; - justify-content: center; -} - -.jobs-pulse { - position: absolute; - bottom: 2px; - left: 2px; +/* Custom scrollbar */ +::-webkit-scrollbar { width: 8px; height: 8px; - background: hsl(142 60% 45%); - border-radius: 50%; - animation: pulse 2s infinite; } -@keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.5; } +::-webkit-scrollbar-track { + background: transparent; } -.jobs-dropdown { - position: absolute; - top: 100%; - right: 0; - margin-top: 8px; - min-width: 320px; - max-width: 400px; - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - box-shadow: var(--shadow-2); - z-index: 100; - padding: 16px; -} - -.jobs-dropdown-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 12px; - padding-bottom: 12px; - border-bottom: 1px solid var(--line); -} - -.jobs-dropdown-header a { - font-size: 0.85rem; -} - -.jobs-empty { - text-align: center; - color: var(--text-muted); - padding: 16px; -} - -.jobs-list { - list-style: none; - margin: 0; - padding: 0; - max-height: 300px; - overflow-y: auto; -} - -.job-item { - padding: 12px; - border-bottom: 1px solid var(--line); -} - -.job-item:last-child { - border-bottom: none; -} - -.job-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 8px; -} - -.job-id { - font-size: 0.75rem; - color: var(--text-muted); -} - -.job-status { - font-size: 0.7rem; - padding: 2px 6px; +::-webkit-scrollbar-thumb { + background: var(--color-line); border-radius: 4px; - font-weight: 700; - text-transform: uppercase; } -.job-status.status-pending { - background: hsl(45 93% 90%); - color: hsl(45 93% 35%); +::-webkit-scrollbar-thumb:hover { + background: var(--color-line-strong); } -.job-status.status-running { - background: hsl(198 52% 90%); - color: hsl(198 78% 37%); -} - -.job-mini-progress { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 4px; -} - -.job-progress-bar { - flex: 1; - height: 6px; - background: hsl(198 78% 37%); - border-radius: 3px; -} - -.job-mini-progress span { - font-size: 0.75rem; - color: var(--text-muted); - min-width: 35px; -} - -.job-file { - margin: 0; - font-size: 0.75rem; - color: var(--text-muted); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.progress-loading, -.progress-error { - padding: 16px; - text-align: center; - color: var(--text-muted); -} - -.progress-error { - color: hsl(2 72% 48%); -} - -/* Dark mode overrides for new components */ -.dark .status-badge.status-pending { - background: hsl(45 93% 25%); - color: hsl(45 93% 65%); -} - -.dark .status-badge.status-running { - background: hsl(198 52% 25%); - color: hsl(198 78% 75%); -} - -.dark .status-badge.status-success { - background: hsl(142 60% 25%); - color: hsl(142 60% 65%); -} - -.dark .status-badge.status-failed { - background: hsl(2 72% 25%); - color: hsl(2 72% 65%); -} - -.dark .status-badge.status-cancelled { - background: hsl(220 13% 25%); - color: hsl(220 13% 65%); -} - -.dark .complete-badge { - background: hsl(142 60% 25%); - color: hsl(142 60% 65%); -} - -.dark .progress-row { - background: hsl(198 52% 15%); -} - -.dark .jobs-indicator:hover { - background: hsl(210 34% 24% / 0.5); -} - -.dark .job-status.status-pending { - background: hsl(45 93% 25%); - color: hsl(45 93% 65%); -} - -.dark .job-status.status-running { - background: hsl(198 52% 25%); - color: hsl(198 78% 75%); -} - -/* Dark mode status colors for job list - couleurs plus soutenues */ -.dark .status-running { - color: hsl(192 85% 55%); - font-weight: 700; - text-shadow: 0 0 10px hsl(192 85% 55% / 0.3); -} - -.dark .status-pending { - color: hsl(45 100% 55%); - font-weight: 600; -} - -.dark .status-completed { - color: hsl(142 70% 55%); - font-weight: 600; -} - -.dark .status-failed { - color: hsl(2 80% 60%); - font-weight: 600; -} - -.dark .status-cancelled { - color: hsl(220 20% 65%); -} - -/* Progress bar visibility fix */ -.job-progress { - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - padding: 16px; - margin: 8px 0; - min-height: 120px; -} - -.progress-bar-container { - position: relative; - height: 24px; - background: hsl(220 13% 90%); - border-radius: 12px; - overflow: hidden; - margin: 12px 0; -} - -.progress-bar-fill { - height: 100%; - background: linear-gradient(90deg, hsl(198 78% 37%), hsl(192 85% 55%)); - border-radius: 12px; - transition: width 0.5s ease; - min-width: 2px; -} - -.progress-percent { - position: absolute; - right: 8px; - top: 50%; - transform: translateY(-50%); - font-size: 0.85rem; - font-weight: 700; - color: var(--foreground); - text-shadow: 0 0 2px rgba(255,255,255,0.5); -} - -.progress-row { - background: hsl(198 52% 95%); -} - -.progress-row td { - padding: 0; -} - -/* Highlighted job row */ -tr.job-highlighted { - background: hsl(198 78% 95%); - box-shadow: inset 0 0 0 2px hsl(198 78% 37%); -} - -tr.job-highlighted td { - animation: pulse-border 2s ease-in-out infinite; -} - -@keyframes pulse-border { - 0%, 100% { box-shadow: inset 0 0 0 1px hsl(198 78% 37% / 0.3); } - 50% { box-shadow: inset 0 0 0 2px hsl(198 78% 37% / 0.6); } -} - -/* Dark mode for highlighted job row */ -.dark tr.job-highlighted { - background: hsl(198 52% 20%); - box-shadow: inset 0 0 0 2px hsl(198 78% 50%); -} - -.dark tr.job-highlighted td { - animation: pulse-border-dark 2s ease-in-out infinite; -} - -@keyframes pulse-border-dark { - 0%, 100% { box-shadow: inset 0 0 0 1px hsl(198 78% 50% / 0.3); } - 50% { box-shadow: inset 0 0 0 2px hsl(198 78% 50% / 0.6); } -} - -/* Monitoring styles */ -.monitoring-cell { - display: flex; - flex-direction: column; - gap: 4px; -} - -.monitor-badge { - display: inline-block; - padding: 2px 8px; - border-radius: 4px; - font-size: 0.75rem; - font-weight: 700; - text-transform: uppercase; -} - -.monitor-auto { - background: hsl(142 60% 45% / 0.2); - color: hsl(142 60% 35%); - border: 1px solid hsl(142 60% 45% / 0.5); -} - -.monitor-manual { - background: hsl(220 13% 80% / 0.2); - color: hsl(220 13% 40%); - border: 1px solid hsl(220 13% 80% / 0.5); -} - -.scan-mode { - font-size: 0.7rem; - color: var(--text-muted); - text-transform: capitalize; -} - -.next-scan { - font-size: 0.7rem; - color: hsl(198 78% 37%); -} - -.monitoring-form { - display: flex; - align-items: center; - gap: 8px; - margin-top: 4px; -} - -.monitor-toggle { - display: flex; - align-items: center; - gap: 4px; - font-size: 0.8rem; - cursor: pointer; -} - -.monitor-toggle input[type="checkbox"] { - cursor: pointer; -} - -.monitoring-form select { - font-size: 0.75rem; - padding: 2px 4px; -} - -/* Watcher toggle styles */ -.watcher-toggle { - background: hsl(45 93% 90% / 0.3); - border: 1px solid hsl(45 93% 47% / 0.3); - border-radius: 4px; - padding: 2px 6px; -} - -.watcher-toggle.active { - background: hsl(45 93% 90% / 0.6); - border-color: hsl(45 93% 47% / 0.6); -} - -.toggle-hint { - margin-left: 4px; - cursor: help; -} - -.monitor-options { - display: flex; - gap: 8px; - flex-wrap: wrap; -} - -/* Job Detail Page Styles */ -.page-header { - margin-bottom: 24px; -} - -.back-link { - display: inline-block; - margin-bottom: 12px; - color: hsl(198 78% 37%); - text-decoration: none; -} - -.back-link:hover { - text-decoration: underline; -} - -.job-detail-grid { - display: grid; - grid-template-columns: 1fr; - gap: 20px; -} - -@media (min-width: 768px) { - .job-detail-grid { - grid-template-columns: repeat(2, 1fr); - } - - .job-progress-detail, - .job-statistics, - .job-errors, - .job-error-message { - grid-column: 1 / -1; - } -} - -.job-meta { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 12px; -} - -.meta-item { - display: flex; - flex-direction: column; - gap: 4px; -} - -.meta-label { - font-size: 0.75rem; - color: var(--text-muted); - text-transform: uppercase; -} - -.meta-value { - font-weight: 600; -} - -.job-type { - text-transform: uppercase; - font-size: 0.8rem; -} - -.job-type.full_rebuild { - color: hsl(280 60% 45%); -} - -.job-type.rebuild { - color: hsl(198 78% 37%); -} - -/* Timeline */ -.timeline { - position: relative; - padding-left: 24px; -} - -.timeline::before { - content: ''; - position: absolute; - left: 7px; - top: 8px; - bottom: 8px; - width: 2px; - background: var(--line); -} - -.timeline-item { - position: relative; - padding-bottom: 16px; - display: flex; - align-items: flex-start; - gap: 12px; -} - -.timeline-item:last-child { - padding-bottom: 0; -} - -.timeline-dot { - position: absolute; - left: -20px; - width: 12px; - height: 12px; - border-radius: 50%; - background: var(--line); - border: 2px solid var(--card); - margin-top: 4px; -} - -.timeline-item.completed .timeline-dot { - background: hsl(142 60% 45%); -} - -.timeline-item.active .timeline-dot { - background: hsl(198 78% 37%); - animation: pulse-dot 2s infinite; -} - -.timeline-item.pending .timeline-dot { - background: var(--line); -} - -@keyframes pulse-dot { - 0%, 100% { box-shadow: 0 0 0 0 hsl(198 78% 37% / 0.4); } - 50% { box-shadow: 0 0 0 6px hsl(198 78% 37% / 0); } -} - -.timeline-content { - display: flex; - flex-direction: column; - gap: 2px; -} - -.timeline-label { - font-weight: 600; - font-size: 0.9rem; -} - -.timeline-time { - font-size: 0.8rem; - color: var(--text-muted); -} - -.duration-badge { - margin-top: 16px; - padding: 8px 12px; - background: hsl(198 52% 90%); - border-radius: 6px; - font-weight: 600; - color: hsl(198 78% 37%); -} - -/* Progress */ -.progress-bar-large { - position: relative; - height: 32px; - background: var(--line); - border-radius: 16px; - overflow: hidden; - margin-bottom: 16px; -} - -.progress-fill { - height: 100%; - background: linear-gradient(90deg, hsl(198 78% 37%), hsl(192 85% 55%)); - border-radius: 16px; - transition: width 0.3s ease; -} - -.progress-text { - position: absolute; - right: 12px; - top: 50%; - transform: translateY(-50%); - font-weight: 700; - font-size: 0.9rem; -} - -.progress-stats-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 12px; - margin-bottom: 16px; -} - -.stat-box { - text-align: center; - padding: 12px; - background: hsl(198 52% 95%); - border-radius: 8px; -} - -.stat-box .stat-value { - display: block; - font-size: 1.5rem; - font-weight: 700; - color: hsl(198 78% 37%); -} - -.stat-box .stat-label { - font-size: 0.75rem; - color: var(--text-muted); -} - -.current-file-box { - padding: 12px; - background: hsl(45 93% 90% / 0.3); - border: 1px solid hsl(45 93% 47% / 0.3); - border-radius: 8px; -} - -.current-file-box .label { - display: block; - font-size: 0.75rem; - color: var(--text-muted); - margin-bottom: 4px; -} - -.current-file-box .file-path { - font-size: 0.85rem; - word-break: break-all; -} - -/* Statistics */ -.stats-grid { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 16px; - margin-bottom: 16px; -} - -.stat-item { - text-align: center; -} - -.stat-number { - display: block; - font-size: 2rem; - font-weight: 700; - color: var(--foreground); -} - -.stat-number.success { color: hsl(142 60% 45%); } -.stat-number.primary { color: hsl(198 78% 37%); } -.stat-number.warning { color: hsl(45 93% 47%); } -.stat-number.error { color: hsl(2 72% 48%); } - -.speed-stat { - text-align: center; - padding-top: 12px; - border-top: 1px solid var(--line); -} - -.speed-label { - font-size: 0.85rem; - color: var(--text-muted); -} - -.speed-value { - font-weight: 700; - font-size: 1.1rem; - margin-left: 8px; -} - -/* Errors */ -.errors-list { - display: flex; - flex-direction: column; - gap: 12px; -} - -.error-item { - padding: 12px; - background: hsl(2 72% 48% / 0.05); - border: 1px solid hsl(2 72% 48% / 0.2); - border-radius: 8px; -} - -.error-file { - display: block; - font-size: 0.8rem; - margin-bottom: 4px; - word-break: break-all; -} - -.error-message { - display: block; - font-size: 0.85rem; - color: hsl(2 72% 48%); - margin-bottom: 4px; -} - -.error-time { - font-size: 0.75rem; - color: var(--text-muted); -} - -.error-details { - padding: 16px; - background: hsl(2 72% 48% / 0.05); - border: 1px solid hsl(2 72% 48% / 0.2); - border-radius: 8px; - overflow-x: auto; - font-size: 0.85rem; -} - -/* Job list enhancements */ -.job-id-link { - text-decoration: none; - color: inherit; -} - -.job-id-link:hover code { - background: hsl(198 52% 90%); - color: hsl(198 78% 37%); -} - -.view-btn { - padding: 4px 10px; - font-size: 0.8rem; - background: hsl(198 78% 37% / 0.1); - border: 1px solid hsl(198 78% 37% / 0.3); - border-radius: 4px; - color: hsl(198 78% 37%); - text-decoration: none; -} - -.view-btn:hover { +/* Selection */ +::selection { background: hsl(198 78% 37% / 0.2); + color: var(--color-foreground); } -/* Libraries Grid - Modern Card Layout */ -.libraries-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); - gap: 20px; - margin-top: 24px; +/* Focus visible */ +:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; } -.library-card { - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - padding: 20px; - display: flex; - flex-direction: column; - gap: 16px; - transition: box-shadow 0.2s ease, transform 0.2s ease; +/* Smooth scrolling */ +html { + scroll-behavior: smooth; } -.library-card:hover { - box-shadow: var(--shadow-2); - transform: translateY(-2px); -} - -/* Library Header */ -.library-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 12px; -} - -.library-name { - margin: 0; - font-size: 1.25rem; - font-weight: 700; - color: var(--foreground); - line-height: 1.3; - flex: 1; -} - -.library-badges { - display: flex; - gap: 6px; - flex-shrink: 0; -} - -.badge-disabled { - background: hsl(220 13% 80%); - color: hsl(220 13% 40%); - padding: 2px 8px; - border-radius: 4px; - font-size: 0.7rem; - font-weight: 700; - text-transform: uppercase; -} - -.badge-watcher { - background: hsl(45 93% 90%); - padding: 2px 6px; - border-radius: 4px; - font-size: 0.9rem; -} - -/* Library Path */ -.library-path { - font-size: 0.8rem; - color: var(--text-muted); - background: hsl(220 13% 95%); - padding: 6px 10px; - border-radius: 6px; - word-break: break-all; -} - -.dark .library-path { - background: hsl(220 13% 20%); -} - -/* Library Stats */ -.library-stats { - display: flex; - gap: 12px; -} - -.stat-box { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - padding: 12px; - background: hsl(198 52% 95%); - border-radius: 8px; - text-decoration: none; - color: inherit; - transition: background 0.2s ease; -} - -.stat-box:hover { - background: hsl(198 52% 90%); -} - -.stat-number { - font-size: 1.5rem; - font-weight: 700; - color: hsl(198 78% 37%); -} - -.stat-label { - font-size: 0.75rem; - color: var(--text-muted); - text-transform: uppercase; - margin-top: 2px; -} - -.dark .stat-box { - background: hsl(198 52% 20%); -} - -.dark .stat-box:hover { - background: hsl(198 52% 25%); -} - -.dark .stat-number { - color: hsl(198 78% 65%); -} - -/* Library Monitoring */ -.library-monitoring { - background: hsl(220 13% 97%); - border-radius: 8px; - padding: 12px; -} - -.dark .library-monitoring { - background: hsl(220 13% 18%); -} - -.monitor-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 8px; -} - -.monitor-status { - font-size: 0.85rem; - font-weight: 600; -} - -.monitor-status.active { - color: hsl(142 60% 45%); -} - -.monitor-status.inactive { - color: var(--text-muted); -} - -.next-scan-badge { - font-size: 0.75rem; - background: hsl(198 52% 90%); - color: hsl(198 78% 37%); - padding: 2px 8px; - border-radius: 12px; - font-weight: 600; -} - -.dark .next-scan-badge { - background: hsl(198 52% 25%); - color: hsl(198 78% 65%); -} - -/* Library Actions */ -.library-actions { - display: flex; - gap: 8px; -} - -.action-btn { - flex: 1; - padding: 8px 12px; - border: none; - border-radius: 6px; - font-size: 0.85rem; - font-weight: 600; - cursor: pointer; - transition: opacity 0.2s ease; -} - -.action-btn:hover { - opacity: 0.8; -} - -.index-btn { - background: hsl(142 60% 45% / 0.15); - color: hsl(142 60% 35%); - border: 1px solid hsl(142 60% 45% / 0.3); -} - -.full-btn { - background: hsl(280 60% 45% / 0.15); - color: hsl(280 60% 45%); - border: 1px solid hsl(280 60% 45% / 0.3); -} - -.delete-btn { - flex: 0 0 auto; - background: hsl(2 72% 48% / 0.1); - color: hsl(2 72% 48%); - border: 1px solid hsl(2 72% 48% / 0.3); - padding: 8px; -} - -.delete-form { - margin-left: auto; -} - -/* Add Library Form */ -.library-add-form { - margin-bottom: 8px; -} - -.library-add-form h2 { - margin: 0 0 16px 0; - font-size: 1.1rem; - color: var(--foreground); -} - -.form-row { - display: flex; - gap: 12px; - align-items: stretch; -} - -.library-name-input { - flex: 1; - min-width: 200px; -} - -.library-folder-select { - flex: 2; - min-width: 250px; -} - -.add-btn { - padding: 10px 24px; - background: hsl(198 78% 37%); - color: white; - border: none; - border-radius: 8px; - font-weight: 600; - cursor: pointer; - transition: background 0.2s ease; -} - -.add-btn:hover { - background: hsl(198 78% 32%); -} - -/* Responsive */ -@media (max-width: 768px) { - .libraries-grid { - grid-template-columns: 1fr; - } - - .form-row { - flex-direction: column; - } - - .library-name-input, - .library-folder-select { - width: 100%; +/* Reduced motion */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; } } - -/* Compact Monitoring Form */ -.monitoring-form-compact { - margin-top: 8px; -} - -.monitor-row { - display: flex; - gap: 8px; - align-items: center; -} - -.monitor-checkbox { - display: flex; - align-items: center; - gap: 4px; - padding: 4px 8px; - background: hsl(220 13% 95%); - border-radius: 6px; - cursor: pointer; - font-size: 0.8rem; - transition: background 0.2s ease; -} - -.monitor-checkbox:hover { - background: hsl(220 13% 90%); -} - -.monitor-checkbox input[type="checkbox"] { - cursor: pointer; -} - -.monitor-checkbox.watcher.active { - background: hsl(45 93% 90%); -} - -.dark .monitor-checkbox { - background: hsl(220 13% 25%); -} - -.dark .monitor-checkbox:hover { - background: hsl(220 13% 30%); -} - -.dark .monitor-checkbox.watcher.active { - background: hsl(45 93% 25%); -} - -.scan-mode-select { - flex: 1; - padding: 4px 8px; - font-size: 0.8rem; - border: 1px solid var(--line); - border-radius: 6px; - background: var(--card); -} - -.save-btn { - padding: 4px 10px; - background: hsl(198 78% 37%); - color: white; - border: none; - border-radius: 6px; - cursor: pointer; - font-size: 0.9rem; -} - -.save-btn:hover:not(:disabled) { - background: hsl(198 78% 32%); -} - -.save-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -/* ===== Jobs Indicator - Modern Version ===== */ - -.jobs-indicator-wrapper { - position: relative; -} - -/* Button */ -.jobs-indicator-button { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - background: var(--card); - border: 1px solid var(--line); - border-radius: 8px; - cursor: pointer; - transition: all 0.2s ease; - color: var(--foreground); -} - -.jobs-indicator-button:hover { - background: hsl(198 52% 95%); - border-color: hsl(198 78% 37% / 0.5); -} - -.jobs-indicator-button.has-running { - background: hsl(198 52% 95%); - border-color: hsl(198 78% 37%); - animation: jobs-button-pulse 2s infinite; -} - -@keyframes jobs-button-pulse { - 0%, 100% { box-shadow: 0 0 0 0 hsl(198 78% 37% / 0.4); } - 50% { box-shadow: 0 0 0 4px hsl(198 78% 37% / 0); } -} - -.jobs-indicator-button.open { - background: hsl(198 52% 90%); -} - -/* Spinner */ -.jobs-spinner { - width: 18px; - height: 18px; - animation: spin 1s linear infinite; - color: hsl(198 78% 37%); -} - -@keyframes spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -/* Icon */ -.jobs-icon { - color: var(--text-muted); -} - -.has-running .jobs-icon { - color: hsl(198 78% 37%); -} - -/* Count Badge */ -.jobs-count-badge { - background: hsl(2 72% 48%); - color: white; - font-size: 0.75rem; - font-weight: 700; - min-width: 20px; - height: 20px; - border-radius: 10px; - display: flex; - align-items: center; - justify-content: center; - padding: 0 6px; -} - -.has-running .jobs-count-badge { - background: hsl(198 78% 37%); -} - -/* Chevron */ -.jobs-chevron { - transition: transform 0.2s ease; - color: var(--text-muted); -} - -.jobs-chevron.open { - transform: rotate(180deg); -} - -/* Empty state (no jobs) */ -.jobs-indicator-empty { - display: flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - color: var(--text-muted); - border-radius: 8px; - transition: all 0.2s ease; -} - -.jobs-indicator-empty:hover { - background: hsl(198 52% 95%); - color: hsl(198 78% 37%); -} - -/* ===== Popin/Dropdown ===== */ - -.jobs-popin { - position: absolute; - top: calc(100% + 8px); - right: 0; - width: 420px; - max-width: calc(100vw - 32px); - background: var(--card); - border: 1px solid var(--line); - border-radius: 12px; - box-shadow: var(--shadow-2); - z-index: 1000; - overflow: hidden; -} - -/* Header */ -.jobs-popin-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - padding: 16px; - border-bottom: 1px solid var(--line); - background: hsl(198 52% 97%); -} - -.dark .jobs-popin-header { - background: hsl(198 52% 15%); -} - -.jobs-popin-title { - display: flex; - align-items: center; - gap: 12px; -} - -.jobs-icon-large { - font-size: 1.5rem; -} - -.jobs-popin-title h3 { - margin: 0; - font-size: 1rem; -} - -.jobs-subtitle { - margin: 2px 0 0 0; - font-size: 0.8rem; - color: var(--text-muted); -} - -.jobs-view-all { - padding: 6px 12px; - background: hsl(198 78% 37%); - color: white; - border-radius: 6px; - font-size: 0.8rem; - font-weight: 600; - text-decoration: none; - transition: background 0.2s ease; -} - -.jobs-view-all:hover { - background: hsl(198 78% 32%); -} - -/* Overall Progress */ -.jobs-overall-progress { - padding: 16px; - border-bottom: 1px solid var(--line); - background: hsl(198 52% 95%); -} - -.dark .jobs-overall-progress { - background: hsl(198 52% 12%); -} - -.progress-header { - display: flex; - justify-content: space-between; - margin-bottom: 8px; - font-size: 0.85rem; - font-weight: 600; -} - -.progress-percent { - color: hsl(198 78% 37%); -} - -.progress-bar { - height: 8px; - background: var(--line); - border-radius: 4px; - overflow: hidden; -} - -.progress-fill { - height: 100%; - background: linear-gradient(90deg, hsl(198 78% 37%), hsl(192 85% 55%)); - border-radius: 4px; - transition: width 0.3s ease; -} - -/* List Container */ -.jobs-list-container { - max-height: 400px; - overflow-y: auto; -} - -/* Empty State */ -.jobs-empty-state { - display: flex; - flex-direction: column; - align-items: center; - padding: 32px; - color: var(--text-muted); -} - -.empty-icon { - font-size: 2rem; - margin-bottom: 8px; -} - -/* Detailed List */ -.jobs-detailed-list { - list-style: none; - margin: 0; - padding: 0; -} - -.job-detailed-item { - border-bottom: 1px solid var(--line); -} - -.job-detailed-item:last-child { - border-bottom: none; -} - -.job-link { - display: block; - padding: 12px 16px; - text-decoration: none; - color: inherit; - transition: background 0.2s ease; -} - -.job-link:hover { - background: hsl(198 52% 95%); -} - -.dark .job-link:hover { - background: hsl(198 52% 15%); -} - -.job-info-row { - display: flex; - gap: 12px; - align-items: flex-start; -} - -.job-status-icon { - font-size: 1.2rem; - flex-shrink: 0; - margin-top: 2px; -} - -.spinning { - display: inline-block; - animation: spin 2s linear infinite; -} - -.job-details { - flex: 1; - min-width: 0; -} - -.job-main-info { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 6px; -} - -.job-id-short { - font-size: 0.8rem; - color: var(--text-muted); - background: hsl(220 13% 90%); - padding: 2px 6px; - border-radius: 4px; -} - -.dark .job-id-short { - background: hsl(220 13% 25%); -} - -.job-type-badge { - font-size: 0.7rem; - font-weight: 700; - text-transform: uppercase; - padding: 2px 6px; - border-radius: 4px; -} - -.job-type-badge.full_rebuild { - background: hsl(280 60% 45% / 0.15); - color: hsl(280 60% 45%); -} - -.job-type-badge.rebuild { - background: hsl(198 78% 37% / 0.15); - color: hsl(198 78% 37%); -} - -/* Progress Row */ -.job-progress-row { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 6px; -} - -.job-mini-progress-bar { - flex: 1; - height: 4px; - background: var(--line); - border-radius: 2px; - overflow: hidden; -} - -.job-mini-progress-fill { - height: 100%; - background: hsl(198 78% 37%); - border-radius: 2px; - transition: width 0.3s ease; -} - -.job-progress-text { - font-size: 0.75rem; - font-weight: 700; - color: hsl(198 78% 37%); - min-width: 35px; - text-align: right; -} - -/* Current File */ -.job-current-file { - margin: 4px 0; - font-size: 0.8rem; - color: var(--text-muted); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -/* Mini Stats */ -.job-mini-stats { - display: flex; - gap: 12px; - font-size: 0.75rem; - color: hsl(142 60% 45%); -} - -.error-stat { - color: hsl(2 72% 48%); -} - -/* Footer */ -.jobs-popin-footer { - padding: 8px 16px; - border-top: 1px solid var(--line); - background: hsl(220 13% 97%); -} - -.dark .jobs-popin-footer { - background: hsl(220 13% 15%); -} - -.jobs-auto-refresh { - margin: 0; - font-size: 0.7rem; - color: var(--text-muted); - text-align: center; -} diff --git a/apps/backoffice/app/layout.tsx b/apps/backoffice/app/layout.tsx index e429c52..9d44803 100644 --- a/apps/backoffice/app/layout.tsx +++ b/apps/backoffice/app/layout.tsx @@ -13,34 +13,64 @@ export const metadata: Metadata = { }; export default function RootLayout({ children }: { children: ReactNode }) { - const apiBaseUrl = process.env.API_BASE_URL || "http://api:8080"; - const apiToken = process.env.API_BOOTSTRAP_TOKEN || ""; - return ( - + -