Hugo.V commited on
Commit
81288b1
·
1 Parent(s): 0cf1082

utl ytb, com main, innovation

Browse files
.gitignore CHANGED
@@ -1,6 +1,7 @@
1
  __pycache__/
2
  *.egg-info/
3
  build/
 
4
  *.mp4
5
  *.png
6
  *.task
 
1
  __pycache__/
2
  *.egg-info/
3
  build/
4
+ projects/
5
  *.mp4
6
  *.png
7
  *.task
README.md CHANGED
@@ -1,11 +1,11 @@
1
  ---
2
  title: Jericho
3
- emoji: 👋
4
- colorFrom: red
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
8
- short_description: Write your description here
9
  tags:
10
  - reachy_mini
11
  - reachy_mini_python_app
 
1
  ---
2
  title: Jericho
3
+ emoji: 🦾
4
+ colorFrom: green
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ short_description: Make your Reachy Mini trully alive
9
  tags:
10
  - reachy_mini
11
  - reachy_mini_python_app
index.html CHANGED
@@ -1,40 +1,177 @@
1
- <!doctype html>
2
- <html>
3
-
4
  <head>
5
- <meta charset="utf-8" />
6
- <meta name="viewport" content="width=device-width" />
7
- <title> Jericho </title>
8
- <link rel="stylesheet" href="style.css" />
 
 
 
 
9
  </head>
10
-
11
  <body>
12
- <div class="hero">
13
- <div class="hero-content">
14
- <div class="app-icon">🤖⚡</div>
15
- <h1> Jericho </h1>
16
- <p class="tagline">Enter your tagline here</p>
17
- </div>
18
- </div>
19
-
20
- <div class="container">
21
- <div class="main-card">
22
- <div class="app-preview">
23
- <div class="preview-image">
24
- <div class="camera-feed">🛠️</div>
25
- </div>
26
- </div>
27
- </div>
28
- </div>
29
-
30
- <div class="footer">
31
- <p>
32
- 🤖 Jericho
33
- <a href="https://github.com/pollen-robotics" target="_blank" rel="noopener noreferrer">Pollen Robotics</a> •
34
- <a href="https://huggingface.co/spaces/pollen-robotics/reachy-mini-landing-page#apps" target="_blank" rel="noopener noreferrer">Browse More
35
- Apps</a>
36
- </p>
37
- </div>
38
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
 
3
  <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Jericho | Reachy Mini Video Mimic App</title>
7
+ <meta
8
+ name="description"
9
+ content="Jericho is a community app that helps your Reachy Mini mimic the main person in a video using MediaPipe."
10
+ />
11
+ <link rel="stylesheet" href="style.css" />
12
  </head>
 
13
  <body>
14
+ <header class="hero">
15
+ <nav class="nav" aria-label="Primary navigation">
16
+ <a class="logo" href="#top" aria-label="Jericho home">Jericho</a>
17
+ <div class="nav-links">
18
+ <a href="#about">What it does</a>
19
+ <a href="#requirements">Requirements</a>
20
+ <a href="#installation">Installation</a>
21
+ <a href="#run">Run</a>
22
+ </div>
23
+ </nav>
24
+
25
+ <section class="hero-content" id="top">
26
+ <p class="eyebrow">Reachy Mini Community App</p>
27
+ <h1>Give life to your Reachy Mini.</h1>
28
+ <p class="hero-text">
29
+ Jericho makes your Reachy Mini mimic the main person in a video using MediaPipe.
30
+ Import an MP4 file or paste a YouTube link, then let your robot follow along.
31
+ </p>
32
+ <div class="hero-actions">
33
+ <a class="button primary" href="#installation">Get started</a>
34
+ <a class="button secondary" href="https://huggingface.co/Jarilo-Project/Jericho/tree/main" target="_blank" rel="noopener noreferrer">
35
+ View repository
36
+ </a>
37
+ </div>
38
+ </section>
39
+ </header>
40
+
41
+ <main>
42
+ <section class="section intro" id="about">
43
+ <div>
44
+ <p class="section-label">What it does</p>
45
+ <h2>Turn video motion into robot behaviour.</h2>
46
+ </div>
47
+ <p>
48
+ Jericho analyses a video with MediaPipe and helps Reachy Mini act like the main person in that video.
49
+ It works with a local video file or a YouTube URL.
50
+ </p>
51
+ </section>
52
+
53
+ <section class="section" id="requirements">
54
+ <p class="section-label">Requirements</p>
55
+ <h2>Before you begin</h2>
56
+ <div class="card-grid">
57
+ <article class="card">
58
+ <span class="card-number">01</span>
59
+ <h3>Reachy Mini</h3>
60
+ <p>
61
+ Set up an instance of Reachy Mini and follow the official installation requirements.
62
+ </p>
63
+ <a href="https://huggingface.co/docs/reachy_mini/index" target="_blank" rel="noopener noreferrer">Read the Reachy Mini docs</a>
64
+ </article>
65
+
66
+ <article class="card">
67
+ <span class="card-number">02</span>
68
+ <h3>PowerShell on Windows</h3>
69
+ <p>
70
+ Windows users should install PowerShell before running the commands.
71
+ </p>
72
+ <a href="https://learn.microsoft.com/fr-fr/powershell/scripting/install/install-powershell-on-windows?view=powershell-7.6" target="_blank" rel="noopener noreferrer">Install PowerShell</a>
73
+ </article>
74
+
75
+ <article class="card">
76
+ <span class="card-number">03</span>
77
+ <h3>A video source</h3>
78
+ <p>
79
+ Use either a YouTube URL or a local MP4 video file.
80
+ </p>
81
+ <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank" rel="noopener noreferrer">Example video URL</a>
82
+ </article>
83
+ </div>
84
+ </section>
85
 
86
+ <section class="section split" id="installation">
87
+ <div>
88
+ <p class="section-label">Setup</p>
89
+ <h2>Prepare Reachy Mini</h2>
90
+ <ol class="steps">
91
+ <li>
92
+ <span>Open a terminal.</span>
93
+ </li>
94
+ <li>
95
+ <span>Navigate to your Reachy Mini installation.</span>
96
+ <code>C:\reachy_mini</code>
97
+ </li>
98
+ <li>
99
+ <span>Activate the Reachy Mini environment.</span>
100
+ <code>reachy_mini_env\Scripts\activate</code>
101
+ </li>
102
+ <li>
103
+ <span>Open the simulation. Remove <code>--sim</code> if you are connected to Reachy Mini.</span>
104
+ <code>reachy-mini-daemon --sim</code>
105
+ </li>
106
+ </ol>
107
+ </div>
108
+
109
+ <aside class="notice">
110
+ <h3>Dashboard URL</h3>
111
+ <p>Open the Reachy Mini dashboard in your browser:</p>
112
+ <div class="code-stack">
113
+ <code>http://localhost:8000/</code>
114
+ <code>http://127.0.0.1:8000/</code>
115
+ </div>
116
+ </aside>
117
+ </section>
118
+
119
+ <section class="section install-options">
120
+ <p class="section-label">Installation</p>
121
+ <h2>Choose an installation method</h2>
122
+
123
+ <div class="option-grid">
124
+ <article class="option-card">
125
+ <h3>Install through the Reachy Mini dashboard</h3>
126
+ <ol class="steps compact">
127
+ <li>Open <code>http://localhost:8000/</code> or <code>http://127.0.0.1:8000/</code>.</li>
128
+ <li>Tick <strong>Show community apps</strong>.</li>
129
+ <li>Search for <strong>jericho</strong> and tick <strong>Install</strong>.</li>
130
+ </ol>
131
+ </article>
132
+
133
+ <article class="option-card">
134
+ <h3>Manual installation</h3>
135
+ <ol class="steps compact">
136
+ <li>
137
+ Clone or download the repository:
138
+ <a href="https://huggingface.co/Jarilo-Project/Jericho" target="_blank" rel="noopener noreferrer">Jarilo-Project/Jericho</a>
139
+ </li>
140
+ <li>
141
+ Open a new terminal in the first <code>jericho</code> folder, where <code>jericho.egg-info</code> is located.
142
+ <code>C:\reachy_mini\my_apps\jericho</code>
143
+ </li>
144
+ <li>
145
+ Activate the Reachy Mini environment.
146
+ <code>..\..\reachy_mini_env\Scripts\activate</code>
147
+ </li>
148
+ <li>
149
+ Install the app.
150
+ <code>pip install -e .</code>
151
+ </li>
152
+ <li>Open <code>http://localhost:8000/</code> or <code>http://127.0.0.1:8000/</code>.</li>
153
+ </ol>
154
+ </article>
155
+ </div>
156
+ </section>
157
+
158
+ <section class="section final-step" id="run">
159
+ <div>
160
+ <p class="section-label">Final step</p>
161
+ <h2>Run Jericho</h2>
162
+ <ol class="steps">
163
+ <li>Tick <strong>On</strong> on the <strong>Jericho</strong> app.</li>
164
+ <li>Click the gear icon to open the app in a new tab.</li>
165
+ <li>Import an MP4 video or paste a YouTube link.</li>
166
+ <li>Click <strong>Run</strong> and Reachy Mini will start mimicking the person in your video.</li>
167
+ </ol>
168
+ </div>
169
+ </section>
170
+ </main>
171
+
172
+ <footer class="footer">
173
+ <p>Jericho — an app for Reachy Mini powered by MediaPipe.</p>
174
+ <a href="#top">Back to top</a>
175
+ </footer>
176
+ </body>
177
+ </html>
jericho/main.py CHANGED
@@ -272,7 +272,14 @@ class PlaybackPayload(BaseModel): # struct payload synchro lecture
272
  playing: bool | None = None
273
  action: str = "sync"
274
 
275
- class RobotAudioStreamer: # classe envoi audio robot
 
 
 
 
 
 
 
276
  SAMPLE_RATE = 16000
277
  CHANNELS = 2
278
  CHUNK_SECONDS = 0.08
 
272
  playing: bool | None = None
273
  action: str = "sync"
274
 
275
+ class RobotAudioStreamer:
276
+ """Stream l'audio de la vidéo vers le haut-parleur Reachy Mini.
277
+
278
+ Le navigateur garde la vidéo pour l'image uniquement. L'audio est extrait
279
+ depuis output_annotated.mp4, converti en float32 16 kHz stéréo, puis poussé
280
+ par petits blocs dans mini.media.push_audio_sample().
281
+ """
282
+
283
  SAMPLE_RATE = 16000
284
  CHANNELS = 2
285
  CHUNK_SECONDS = 0.08
jericho/projects/fish/signals.json DELETED
@@ -1,195 +0,0 @@
1
- {
2
- "video": "C:\\Users\\hugov\\reachy_mini\\my_apps\\jericho\\jericho\\projects\\fish\\input.mp4",
3
- "output_video": "C:\\Users\\hugov\\reachy_mini\\my_apps\\jericho\\jericho\\projects\\fish\\output_annotated.mp4",
4
- "fps": 29.97,
5
- "width": 256,
6
- "height": 144,
7
- "total_frames": 6812,
8
- "output_total_frames": 7,
9
- "skipped_no_face_frames": 6800,
10
- "timeline": "compact_face_only",
11
- "frames": [
12
- {
13
- "frame": 0,
14
- "timestamp_s": 0.0,
15
- "face_detected": true,
16
- "face_cx": 0.5041,
17
- "face_cy": 0.5993,
18
- "face_w": 0.1426,
19
- "face_h": 0.2724,
20
- "bbox_xmin": 0.4328,
21
- "bbox_ymin": 0.4631,
22
- "bbox_xmax": 0.5754,
23
- "bbox_ymax": 0.7355,
24
- "yaw": 20.61,
25
- "pitch": -5.88,
26
- "roll": -24.4,
27
- "ear_left": 0.3552,
28
- "ear_right": 0.3423,
29
- "mar": 0.4183,
30
- "smile": 0.9454,
31
- "brow_raise_left": 0.0973,
32
- "brow_raise_right": 0.1283,
33
- "brow_furrow": 0.3575,
34
- "emotion": "CONTENT",
35
- "original_frame": 362,
36
- "original_timestamp_s": 12.0787
37
- },
38
- {
39
- "frame": 1,
40
- "timestamp_s": 0.0334,
41
- "face_detected": true,
42
- "face_cx": 0.4867,
43
- "face_cy": 0.5864,
44
- "face_w": 0.1723,
45
- "face_h": 0.2947,
46
- "bbox_xmin": 0.4005,
47
- "bbox_ymin": 0.439,
48
- "bbox_xmax": 0.5729,
49
- "bbox_ymax": 0.7337,
50
- "yaw": 19.71,
51
- "pitch": -2.08,
52
- "roll": -39.22,
53
- "ear_left": 0.3216,
54
- "ear_right": 0.3117,
55
- "mar": 0.3816,
56
- "smile": 0.7823,
57
- "brow_raise_left": 0.0676,
58
- "brow_raise_right": 0.1177,
59
- "brow_furrow": 0.3827,
60
- "emotion": "NEUTRE",
61
- "original_frame": 2441,
62
- "original_timestamp_s": 81.448
63
- },
64
- {
65
- "frame": 2,
66
- "timestamp_s": 0.0667,
67
- "face_detected": true,
68
- "face_cx": 0.4762,
69
- "face_cy": 0.5905,
70
- "face_w": 0.1745,
71
- "face_h": 0.2462,
72
- "bbox_xmin": 0.3889,
73
- "bbox_ymin": 0.4674,
74
- "bbox_xmax": 0.5634,
75
- "bbox_ymax": 0.7136,
76
- "yaw": 43.6,
77
- "pitch": 9.84,
78
- "roll": -60.06,
79
- "ear_left": 0.3956,
80
- "ear_right": 0.3608,
81
- "mar": 0.3857,
82
- "smile": 1.0639,
83
- "brow_raise_left": 0.0065,
84
- "brow_raise_right": 0.0484,
85
- "brow_furrow": 0.5031,
86
- "emotion": "JOIE",
87
- "original_frame": 2501,
88
- "original_timestamp_s": 83.45
89
- },
90
- {
91
- "frame": 3,
92
- "timestamp_s": 0.1001,
93
- "face_detected": true,
94
- "face_cx": 0.4605,
95
- "face_cy": 0.5879,
96
- "face_w": 0.1804,
97
- "face_h": 0.2179,
98
- "bbox_xmin": 0.3703,
99
- "bbox_ymin": 0.4789,
100
- "bbox_xmax": 0.5508,
101
- "bbox_ymax": 0.6969,
102
- "yaw": 51.33,
103
- "pitch": 1.17,
104
- "roll": -72.7,
105
- "ear_left": 0.4808,
106
- "ear_right": 0.5752,
107
- "mar": 0.3477,
108
- "smile": 0.8995,
109
- "brow_raise_left": 0.0225,
110
- "brow_raise_right": 0.0464,
111
- "brow_furrow": 0.4005,
112
- "emotion": "PEUR",
113
- "original_frame": 5331,
114
- "original_timestamp_s": 177.8777
115
- },
116
- {
117
- "frame": 4,
118
- "timestamp_s": 0.1335,
119
- "face_detected": true,
120
- "face_cx": 0.4809,
121
- "face_cy": 0.604,
122
- "face_w": 0.1627,
123
- "face_h": 0.2473,
124
- "bbox_xmin": 0.3996,
125
- "bbox_ymin": 0.4803,
126
- "bbox_xmax": 0.5622,
127
- "bbox_ymax": 0.7276,
128
- "yaw": 28.46,
129
- "pitch": -2.9,
130
- "roll": -43.45,
131
- "ear_left": 0.3534,
132
- "ear_right": 0.4038,
133
- "mar": 0.4107,
134
- "smile": 0.8494,
135
- "brow_raise_left": 0.0586,
136
- "brow_raise_right": 0.0748,
137
- "brow_furrow": 0.4035,
138
- "emotion": "NEUTRE",
139
- "original_frame": 5662,
140
- "original_timestamp_s": 188.9221
141
- },
142
- {
143
- "frame": 5,
144
- "timestamp_s": 0.1668,
145
- "face_detected": true,
146
- "face_cx": 0.4915,
147
- "face_cy": 0.6195,
148
- "face_w": 0.1447,
149
- "face_h": 0.2324,
150
- "bbox_xmin": 0.4192,
151
- "bbox_ymin": 0.5033,
152
- "bbox_xmax": 0.5639,
153
- "bbox_ymax": 0.7357,
154
- "yaw": 27.66,
155
- "pitch": -3.79,
156
- "roll": -36.34,
157
- "ear_left": 0.3412,
158
- "ear_right": 0.448,
159
- "mar": 0.3767,
160
- "smile": 0.764,
161
- "brow_raise_left": 0.0665,
162
- "brow_raise_right": 0.099,
163
- "brow_furrow": 0.3344,
164
- "emotion": "NEUTRE",
165
- "original_frame": 6053,
166
- "original_timestamp_s": 201.9684
167
- },
168
- {
169
- "frame": 6,
170
- "timestamp_s": 0.2002,
171
- "face_detected": true,
172
- "face_cx": 0.4813,
173
- "face_cy": 0.5952,
174
- "face_w": 0.1594,
175
- "face_h": 0.2209,
176
- "bbox_xmin": 0.4016,
177
- "bbox_ymin": 0.4848,
178
- "bbox_xmax": 0.561,
179
- "bbox_ymax": 0.7057,
180
- "yaw": 45.55,
181
- "pitch": 5.15,
182
- "roll": -64.75,
183
- "ear_left": 0.3412,
184
- "ear_right": 0.4439,
185
- "mar": 0.3823,
186
- "smile": 0.8951,
187
- "brow_raise_left": 0.0063,
188
- "brow_raise_right": 0.0339,
189
- "brow_furrow": 0.4389,
190
- "emotion": "NEUTRE",
191
- "original_frame": 6777,
192
- "original_timestamp_s": 226.1259
193
- }
194
- ]
195
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
jericho/projects/fish/status.txt DELETED
@@ -1 +0,0 @@
1
- ERROR: NO_FACE_DETECTED
 
 
jericho/projects/hugo/signals.json DELETED
The diff for this file is too large to render. See raw diff
 
jericho/projects/hugo/status.txt DELETED
@@ -1 +0,0 @@
1
- DONE
 
 
jericho/static/index.html CHANGED
@@ -10,11 +10,15 @@
10
  <header>
11
  <h1>【⚙】Jericho projet : Reachy Mini【⚙】</h1>
12
  <div id="conteneurHeader">
 
13
  <img
14
  src="static/images/logoReachyMini.png"
15
  alt="Photo de Reachy"
16
  width="10%"
17
  />
 
 
 
18
  <div id="robot-status">Prêt</div>
19
  </div>
20
  </header>
@@ -45,6 +49,7 @@
45
  </section>
46
 
47
  <section class="card">
 
48
  <h2>[▶] Importer depuis YouTube</h2>
49
  <div class="form-group">
50
  <label>Nom du projet :</label>
@@ -69,6 +74,8 @@
69
  </section>
70
 
71
  <section class="card">
 
 
72
  <h2>►► Votre bibliothèque</h2>
73
  <div id="video-library" class="grid-library">
74
  <p class="empty-text">Aucune vidéo enregistrée.</p>
@@ -106,9 +113,12 @@
106
  <div class="sync-controls">
107
  <button id="launch-sync-btn" class="btn-success">
108
  [►] Lire vidéo + robot synchronisés
 
109
  </button>
110
  <button id="launch-seq-btn" class="btn-success" style="display: none">
111
  [►] Lire la séquence (sans vidéo)
 
 
112
  </button>
113
  <p class="sync-hint">
114
  Les pauses, reprises et déplacements dans la vidéo sont envoyés au
@@ -120,6 +130,7 @@
120
  <section class="card">
121
  <h2>☻ Les émotions</h2>
122
  <div id="listeEmotions">
 
123
  <button id="joie">Joie</button>
124
  <button id="content">Content</button>
125
  <button id="surprise">Surprise</button>
@@ -127,6 +138,29 @@
127
  <button id="peur">Peur</button>
128
  <button id="tristesse">Tristesse</button>
129
  <button id="neutre">Neutre</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  </div>
131
  </section>
132
  </main>
 
10
  <header>
11
  <h1>【⚙】Jericho projet : Reachy Mini【⚙】</h1>
12
  <div id="conteneurHeader">
13
+ <<<<<<< HEAD
14
  <img
15
  src="static/images/logoReachyMini.png"
16
  alt="Photo de Reachy"
17
  width="10%"
18
  />
19
+ =======
20
+ <img src="static/images/logoReachyMini.png" alt="Photo de Reachy" width="10%" />
21
+ >>>>>>> abc461f5bd956c99158acc406f426086d1d49797
22
  <div id="robot-status">Prêt</div>
23
  </div>
24
  </header>
 
49
  </section>
50
 
51
  <section class="card">
52
+ <<<<<<< HEAD
53
  <h2>[▶] Importer depuis YouTube</h2>
54
  <div class="form-group">
55
  <label>Nom du projet :</label>
 
74
  </section>
75
 
76
  <section class="card">
77
+ =======
78
+ >>>>>>> abc461f5bd956c99158acc406f426086d1d49797
79
  <h2>►► Votre bibliothèque</h2>
80
  <div id="video-library" class="grid-library">
81
  <p class="empty-text">Aucune vidéo enregistrée.</p>
 
113
  <div class="sync-controls">
114
  <button id="launch-sync-btn" class="btn-success">
115
  [►] Lire vidéo + robot synchronisés
116
+ <<<<<<< HEAD
117
  </button>
118
  <button id="launch-seq-btn" class="btn-success" style="display: none">
119
  [►] Lire la séquence (sans vidéo)
120
+ =======
121
+ >>>>>>> abc461f5bd956c99158acc406f426086d1d49797
122
  </button>
123
  <p class="sync-hint">
124
  Les pauses, reprises et déplacements dans la vidéo sont envoyés au
 
130
  <section class="card">
131
  <h2>☻ Les émotions</h2>
132
  <div id="listeEmotions">
133
+ <<<<<<< HEAD
134
  <button id="joie">Joie</button>
135
  <button id="content">Content</button>
136
  <button id="surprise">Surprise</button>
 
138
  <button id="peur">Peur</button>
139
  <button id="tristesse">Tristesse</button>
140
  <button id="neutre">Neutre</button>
141
+ =======
142
+ <button id="joie">
143
+ Joie
144
+ </button>
145
+ <button id="content">
146
+ Content
147
+ </button>
148
+ <button id="surprise">
149
+ Surprise
150
+ </button>
151
+ <button id="colere">
152
+ Colère
153
+ </button>
154
+ <button id="peur">
155
+ Peur
156
+ </button>
157
+ <button id="tristesse">
158
+ Tristesse
159
+ </button>
160
+ <button id="neutre">
161
+ Neutre
162
+ </button>
163
+ >>>>>>> abc461f5bd956c99158acc406f426086d1d49797
164
  </div>
165
  </section>
166
  </main>
jericho/static/main.js CHANGED
@@ -564,4 +564,4 @@ document.getElementById('save-seq-btn').onclick = async function() {
564
  msg.textContent = 'Erreur réseau.';
565
  msg.style.color = 'red';
566
  }
567
- };
 
564
  msg.textContent = 'Erreur réseau.';
565
  msg.style.color = 'red';
566
  }
567
+ };
style.css CHANGED
@@ -1,411 +1,338 @@
1
- * {
2
- margin: 0;
3
- padding: 0;
4
- box-sizing: border-box;
5
- }
6
-
7
- body {
8
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
9
- line-height: 1.6;
10
- color: #333;
11
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
12
- min-height: 100vh;
13
- }
14
-
15
- .hero {
16
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
- color: white;
18
- padding: 4rem 2rem;
19
- text-align: center;
20
- }
21
-
22
- .hero-content {
23
- max-width: 800px;
24
- margin: 0 auto;
25
- }
26
-
27
- .app-icon {
28
- font-size: 4rem;
29
- margin-bottom: 1rem;
30
- display: inline-block;
31
- }
32
-
33
- .hero h1 {
34
- font-size: 3rem;
35
- font-weight: 700;
36
- margin-bottom: 1rem;
37
- background: linear-gradient(45deg, #fff, #f0f9ff);
38
- background-clip: text;
39
- -webkit-background-clip: text;
40
- -webkit-text-fill-color: transparent;
41
- }
42
-
43
- .tagline {
44
- font-size: 1.25rem;
45
- opacity: 0.9;
46
- max-width: 600px;
47
- margin: 0 auto;
48
- }
49
-
50
- .container {
51
- max-width: 1200px;
52
- margin: 0 auto;
53
- padding: 0 2rem;
54
- position: relative;
55
- z-index: 2;
56
- }
57
-
58
- .main-card {
59
- background: white;
60
- border-radius: 20px;
61
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
62
- margin-top: -2rem;
63
- overflow: hidden;
64
- margin-bottom: 3rem;
65
- }
66
-
67
- .app-preview {
68
- background: linear-gradient(135deg, #1e3a8a, #3b82f6);
69
- padding: 3rem;
70
- color: white;
71
- text-align: center;
72
- position: relative;
73
- }
74
-
75
- .preview-image {
76
- background: #000;
77
- border-radius: 15px;
78
- padding: 2rem;
79
- max-width: 500px;
80
- margin: 0 auto;
81
- position: relative;
82
- overflow: hidden;
83
  }
84
 
85
- .camera-feed {
86
- font-size: 4rem;
87
- margin-bottom: 1rem;
88
- opacity: 0.7;
89
- }
90
-
91
- .detection-overlay {
92
- position: absolute;
93
- top: 50%;
94
- left: 50%;
95
- transform: translate(-50%, -50%);
96
- width: 100%;
97
  }
98
 
99
- .bbox {
100
- background: rgba(34, 197, 94, 0.9);
101
- color: white;
102
- padding: 0.5rem 1rem;
103
- border-radius: 8px;
104
- font-size: 0.9rem;
105
- font-weight: 600;
106
- margin: 0.5rem;
107
- display: inline-block;
108
- border: 2px solid #22c55e;
109
  }
110
 
111
- .app-details {
112
- padding: 3rem;
 
 
 
 
 
 
113
  }
114
 
115
- .app-details h2 {
116
- font-size: 2rem;
117
- color: #1e293b;
118
- margin-bottom: 2rem;
119
- text-align: center;
120
  }
121
 
122
- .template-info {
123
- display: grid;
124
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
125
- gap: 2rem;
126
- margin-bottom: 3rem;
127
  }
128
 
129
- .info-box {
130
- background: #f0f9ff;
131
- border: 2px solid #e0f2fe;
132
- border-radius: 12px;
133
- padding: 2rem;
 
 
 
 
 
 
 
134
  }
135
 
136
- .info-box h3 {
137
- color: #0c4a6e;
138
- margin-bottom: 1rem;
139
- font-size: 1.2rem;
 
140
  }
141
 
142
- .info-box p {
143
- color: #0369a1;
144
- line-height: 1.6;
 
 
 
 
 
145
  }
146
 
147
- .how-to-use {
148
- background: #fefce8;
149
- border: 2px solid #fde047;
150
- border-radius: 12px;
151
- padding: 2rem;
152
- margin-top: 3rem;
153
  }
154
 
155
- .how-to-use h3 {
156
- color: #a16207;
157
- margin-bottom: 1.5rem;
158
- font-size: 1.3rem;
159
- text-align: center;
 
160
  }
161
 
162
- .steps {
163
- display: flex;
164
- flex-direction: column;
165
- gap: 1.5rem;
166
  }
167
 
168
- .step {
169
- display: flex;
170
- align-items: flex-start;
171
- gap: 1rem;
172
  }
173
 
174
- .step-number {
175
- background: #eab308;
176
- color: white;
177
- width: 2rem;
178
- height: 2rem;
179
- border-radius: 50%;
180
- display: flex;
181
- align-items: center;
182
- justify-content: center;
183
- font-weight: bold;
184
- flex-shrink: 0;
185
  }
186
 
187
- .step h4 {
188
- color: #a16207;
189
- margin-bottom: 0.5rem;
190
- font-size: 1.1rem;
 
 
 
 
191
  }
192
 
193
- .step p {
194
- color: #ca8a04;
 
 
 
195
  }
196
 
197
- .download-card {
198
- background: white;
199
- border-radius: 20px;
200
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
201
- padding: 3rem;
202
- text-align: center;
203
  }
204
 
205
- .download-card h2 {
206
- font-size: 2rem;
207
- color: #1e293b;
208
- margin-bottom: 1rem;
 
209
  }
210
 
211
- .download-card>p {
212
- color: #64748b;
213
- font-size: 1.1rem;
214
- margin-bottom: 2rem;
215
  }
216
 
217
- .dashboard-config {
218
- margin-bottom: 2rem;
219
- text-align: left;
220
- max-width: 400px;
221
- margin-left: auto;
222
- margin-right: auto;
223
  }
224
 
225
- .dashboard-config label {
226
- display: block;
227
- color: #374151;
228
- font-weight: 600;
229
- margin-bottom: 0.5rem;
230
  }
231
 
232
- .dashboard-config input {
233
- width: 100%;
234
- padding: 0.75rem 1rem;
235
- border: 2px solid #e5e7eb;
236
- border-radius: 8px;
237
- font-size: 0.95rem;
238
- transition: border-color 0.2s;
 
 
 
239
  }
240
 
241
- .dashboard-config input:focus {
242
- outline: none;
243
- border-color: #667eea;
244
  }
245
 
246
- .install-btn {
247
- background: linear-gradient(135deg, #667eea, #764ba2);
248
- color: white;
249
- border: none;
250
- padding: 1.25rem 3rem;
251
- border-radius: 16px;
252
- font-size: 1.2rem;
253
- font-weight: 700;
254
- cursor: pointer;
255
- transition: all 0.3s ease;
256
- display: inline-flex;
257
- align-items: center;
258
- gap: 0.75rem;
259
- margin-bottom: 2rem;
260
- box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
261
  }
262
 
263
- .install-btn:hover:not(:disabled) {
264
- transform: translateY(-3px);
265
- box-shadow: 0 15px 35px rgba(102, 126, 234, 0.4);
266
  }
267
 
268
- .install-btn:disabled {
269
- opacity: 0.7;
270
- cursor: not-allowed;
271
- transform: none;
272
  }
273
 
274
- .manual-option {
275
- background: #f8fafc;
276
- border-radius: 12px;
277
- padding: 2rem;
278
- margin-top: 2rem;
 
 
 
279
  }
280
 
281
- .manual-option h3 {
282
- color: #1e293b;
283
- margin-bottom: 1rem;
284
- font-size: 1.2rem;
 
 
 
285
  }
286
 
287
- .manual-option>p {
288
- color: #64748b;
289
- margin-bottom: 1rem;
 
 
 
290
  }
291
 
292
- .btn-icon {
293
- font-size: 1.1rem;
 
 
 
 
294
  }
295
 
296
- .install-status {
297
- padding: 1rem;
298
- border-radius: 8px;
299
- font-size: 0.9rem;
300
- text-align: center;
301
- display: none;
302
- margin-top: 1rem;
303
  }
304
 
305
- .install-status.success {
306
- background: #dcfce7;
307
- color: #166534;
308
- border: 1px solid #bbf7d0;
 
 
 
309
  }
310
 
311
- .install-status.error {
312
- background: #fef2f2;
313
- color: #dc2626;
314
- border: 1px solid #fecaca;
 
 
 
 
 
 
 
 
 
315
  }
316
 
317
- .install-status.loading {
318
- background: #dbeafe;
319
- color: #1d4ed8;
320
- border: 1px solid #bfdbfe;
 
321
  }
322
 
323
- .install-status.info {
324
- background: #e0f2fe;
325
- color: #0369a1;
326
- border: 1px solid #7dd3fc;
327
  }
328
 
329
- .manual-install {
330
- background: #1f2937;
331
- border-radius: 8px;
332
- padding: 1rem;
333
- margin-bottom: 1rem;
334
- display: flex;
335
- align-items: center;
336
- gap: 1rem;
337
  }
338
 
339
- .manual-install code {
340
- color: #10b981;
341
- font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
342
- font-size: 0.85rem;
343
- flex: 1;
344
- overflow-x: auto;
345
  }
346
 
347
- .copy-btn {
348
- background: #374151;
349
- color: white;
350
- border: none;
351
- padding: 0.5rem 1rem;
352
- border-radius: 6px;
353
- font-size: 0.8rem;
354
- cursor: pointer;
355
- transition: background-color 0.2s;
356
  }
357
 
358
- .copy-btn:hover {
359
- background: #4b5563;
 
360
  }
361
 
362
- .manual-steps {
363
- color: #6b7280;
364
- font-size: 0.9rem;
365
- line-height: 1.8;
366
  }
367
 
368
  .footer {
369
- text-align: center;
370
- padding: 2rem;
371
- color: white;
372
- opacity: 0.8;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
373
  }
374
-
375
- .footer a {
376
- color: white;
377
- text-decoration: none;
378
- font-weight: 600;
379
- }
380
-
381
- .footer a:hover {
382
- text-decoration: underline;
383
- }
384
-
385
- /* Responsive Design */
386
- @media (max-width: 768px) {
387
- .hero {
388
- padding: 2rem 1rem;
389
- }
390
-
391
- .hero h1 {
392
- font-size: 2rem;
393
- }
394
-
395
- .container {
396
- padding: 0 1rem;
397
- }
398
-
399
- .app-details,
400
- .download-card {
401
- padding: 2rem;
402
- }
403
-
404
- .features-grid {
405
- grid-template-columns: 1fr;
406
- }
407
-
408
- .download-options {
409
- grid-template-columns: 1fr;
410
- }
411
- }
 
1
+ :root {
2
+ --background: #0e1020;
3
+ --surface: #171a2f;
4
+ --surface-soft: #20243d;
5
+ --text: #f7f8ff;
6
+ --muted: #bac0d9;
7
+ --accent: #7c6cff;
8
+ --accent-light: #b6aeff;
9
+ --border: rgba(255, 255, 255, 0.12);
10
+ --shadow: 0 24px 80px rgba(0, 0, 0, 0.35);
11
+ --radius: 24px;
12
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
 
15
+ * {
16
+ box-sizing: border-box;
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
+ html {
20
+ scroll-behavior: smooth;
 
 
 
 
 
 
 
 
21
  }
22
 
23
+ body {
24
+ margin: 0;
25
+ color: var(--text);
26
+ background:
27
+ radial-gradient(circle at top left, rgba(124, 108, 255, 0.35), transparent 34rem),
28
+ radial-gradient(circle at bottom right, rgba(54, 216, 216, 0.18), transparent 28rem),
29
+ var(--background);
30
+ line-height: 1.6;
31
  }
32
 
33
+ a {
34
+ color: var(--accent-light);
35
+ text-decoration: none;
 
 
36
  }
37
 
38
+ a:hover,
39
+ a:focus-visible {
40
+ color: var(--text);
 
 
41
  }
42
 
43
+ code {
44
+ display: inline-block;
45
+ max-width: 100%;
46
+ margin-top: 0.4rem;
47
+ padding: 0.35rem 0.55rem;
48
+ overflow-x: auto;
49
+ color: #fff;
50
+ background: rgba(0, 0, 0, 0.28);
51
+ border: 1px solid var(--border);
52
+ border-radius: 10px;
53
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
54
+ font-size: 0.9rem;
55
  }
56
 
57
+ .hero {
58
+ min-height: 86vh;
59
+ padding: 1.5rem;
60
+ display: flex;
61
+ flex-direction: column;
62
  }
63
 
64
+ .nav {
65
+ width: min(1120px, 100%);
66
+ margin: 0 auto;
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: space-between;
70
+ gap: 1rem;
71
+ padding: 1rem 0;
72
  }
73
 
74
+ .logo {
75
+ color: var(--text);
76
+ font-size: 1.15rem;
77
+ font-weight: 800;
78
+ letter-spacing: 0.04em;
 
79
  }
80
 
81
+ .nav-links {
82
+ display: flex;
83
+ flex-wrap: wrap;
84
+ justify-content: flex-end;
85
+ gap: 0.75rem 1.2rem;
86
+ font-size: 0.95rem;
87
  }
88
 
89
+ .nav-links a {
90
+ color: var(--muted);
 
 
91
  }
92
 
93
+ .nav-links a:hover,
94
+ .nav-links a:focus-visible {
95
+ color: var(--text);
 
96
  }
97
 
98
+ .hero-content {
99
+ width: min(1120px, 100%);
100
+ margin: auto;
101
+ padding: 5rem 0 7rem;
 
 
 
 
 
 
 
102
  }
103
 
104
+ .eyebrow,
105
+ .section-label {
106
+ margin: 0 0 0.75rem;
107
+ color: var(--accent-light);
108
+ font-size: 0.78rem;
109
+ font-weight: 800;
110
+ letter-spacing: 0.14em;
111
+ text-transform: uppercase;
112
  }
113
 
114
+ h1,
115
+ h2,
116
+ h3,
117
+ p {
118
+ margin-top: 0;
119
  }
120
 
121
+ h1 {
122
+ max-width: 850px;
123
+ margin-bottom: 1.25rem;
124
+ font-size: clamp(3.2rem, 9vw, 7rem);
125
+ line-height: 0.92;
126
+ letter-spacing: -0.07em;
127
  }
128
 
129
+ h2 {
130
+ margin-bottom: 1rem;
131
+ font-size: clamp(2rem, 5vw, 3.4rem);
132
+ line-height: 1;
133
+ letter-spacing: -0.045em;
134
  }
135
 
136
+ h3 {
137
+ margin-bottom: 0.65rem;
138
+ font-size: 1.2rem;
139
+ line-height: 1.25;
140
  }
141
 
142
+ .hero-text {
143
+ max-width: 700px;
144
+ color: var(--muted);
145
+ font-size: clamp(1.05rem, 2vw, 1.35rem);
 
 
146
  }
147
 
148
+ .hero-actions {
149
+ display: flex;
150
+ flex-wrap: wrap;
151
+ gap: 0.9rem;
152
+ margin-top: 2rem;
153
  }
154
 
155
+ .button {
156
+ display: inline-flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ min-height: 3rem;
160
+ padding: 0.8rem 1.15rem;
161
+ border: 1px solid var(--border);
162
+ border-radius: 999px;
163
+ font-weight: 800;
164
+ transition: transform 180ms ease, border-color 180ms ease, background 180ms ease;
165
  }
166
 
167
+ .button:hover,
168
+ .button:focus-visible {
169
+ transform: translateY(-2px);
170
  }
171
 
172
+ .button.primary {
173
+ color: #111327;
174
+ background: var(--accent-light);
 
 
 
 
 
 
 
 
 
 
 
 
175
  }
176
 
177
+ .button.secondary {
178
+ color: var(--text);
179
+ background: rgba(255, 255, 255, 0.08);
180
  }
181
 
182
+ main {
183
+ width: min(1120px, calc(100% - 2rem));
184
+ margin: 0 auto;
 
185
  }
186
 
187
+ .section {
188
+ margin-bottom: 1.5rem;
189
+ padding: clamp(1.35rem, 4vw, 3rem);
190
+ background: rgba(23, 26, 47, 0.78);
191
+ border: 1px solid var(--border);
192
+ border-radius: var(--radius);
193
+ box-shadow: var(--shadow);
194
+ backdrop-filter: blur(16px);
195
  }
196
 
197
+ .intro,
198
+ .split,
199
+ .final-step {
200
+ display: grid;
201
+ grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
202
+ gap: 2rem;
203
+ align-items: start;
204
  }
205
 
206
+ .intro p:last-child,
207
+ .notice p,
208
+ .card p,
209
+ .option-card p,
210
+ .footer p {
211
+ color: var(--muted);
212
  }
213
 
214
+ .card-grid,
215
+ .option-grid {
216
+ display: grid;
217
+ grid-template-columns: repeat(3, minmax(0, 1fr));
218
+ gap: 1rem;
219
+ margin-top: 1.5rem;
220
  }
221
 
222
+ .option-grid {
223
+ grid-template-columns: repeat(2, minmax(0, 1fr));
 
 
 
 
 
224
  }
225
 
226
+ .card,
227
+ .option-card,
228
+ .notice {
229
+ padding: 1.25rem;
230
+ background: var(--surface-soft);
231
+ border: 1px solid var(--border);
232
+ border-radius: 20px;
233
  }
234
 
235
+ .card-number {
236
+ display: inline-flex;
237
+ width: 2.25rem;
238
+ height: 2.25rem;
239
+ align-items: center;
240
+ justify-content: center;
241
+ margin-bottom: 1rem;
242
+ color: var(--accent-light);
243
+ background: rgba(124, 108, 255, 0.14);
244
+ border: 1px solid rgba(182, 174, 255, 0.28);
245
+ border-radius: 50%;
246
+ font-size: 0.82rem;
247
+ font-weight: 900;
248
  }
249
 
250
+ .steps {
251
+ display: grid;
252
+ gap: 1rem;
253
+ margin: 1rem 0 0;
254
+ padding-left: 1.25rem;
255
  }
256
 
257
+ .steps li {
258
+ padding-left: 0.35rem;
 
 
259
  }
260
 
261
+ .steps li::marker {
262
+ color: var(--accent-light);
263
+ font-weight: 900;
 
 
 
 
 
264
  }
265
 
266
+ .steps.compact {
267
+ gap: 0.85rem;
 
 
 
 
268
  }
269
 
270
+ .notice {
271
+ position: sticky;
272
+ top: 1rem;
 
 
 
 
 
 
273
  }
274
 
275
+ .code-stack {
276
+ display: grid;
277
+ gap: 0.5rem;
278
  }
279
 
280
+ .final-step {
281
+ grid-template-columns: 1fr;
282
+ background: linear-gradient(135deg, rgba(124, 108, 255, 0.28), rgba(23, 26, 47, 0.9));
 
283
  }
284
 
285
  .footer {
286
+ width: min(1120px, calc(100% - 2rem));
287
+ margin: 0 auto;
288
+ padding: 2rem 0 3rem;
289
+ display: flex;
290
+ justify-content: space-between;
291
+ gap: 1rem;
292
+ color: var(--muted);
293
+ }
294
+
295
+ @media (max-width: 820px) {
296
+ .nav {
297
+ align-items: flex-start;
298
+ flex-direction: column;
299
+ }
300
+
301
+ .nav-links {
302
+ justify-content: flex-start;
303
+ }
304
+
305
+ .hero-content {
306
+ padding: 4rem 0;
307
+ }
308
+
309
+ .intro,
310
+ .split,
311
+ .card-grid,
312
+ .option-grid {
313
+ grid-template-columns: 1fr;
314
+ }
315
+
316
+ .notice {
317
+ position: static;
318
+ }
319
+
320
+ .footer {
321
+ flex-direction: column;
322
+ }
323
+ }
324
+
325
+ @media (max-width: 520px) {
326
+ .hero {
327
+ min-height: auto;
328
+ }
329
+
330
+ h1 {
331
+ font-size: 3.5rem;
332
+ }
333
+
334
+ .hero-actions,
335
+ .button {
336
+ width: 100%;
337
+ }
338
  }