stream-fusion-better/stream_fusion/static/index.html
2026-04-01 23:05:45 -04:00

2668 lines
No EOL
164 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr" class="h-full">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
<script>
const secretKey = "{{ session_key }}";
window.__CSRF_TOKEN__ = "{{ csrf_token }}";
</script>
<title>Stream-Fusion — Configuration</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&family=Sora:wght@400;600;700&display=swap" rel="stylesheet">
<style>
:root {
--accent: #6366f1;
--accent-light: #818cf8;
--accent-dark: #4f46e5;
--accent-glow: rgba(99, 102, 241, 0.3);
--orange: #f97316;
--orange-light: #fb923c;
--red: #ef4444;
--green: #22c55e;
--cyan: #06b6d4;
--surface: rgba(12, 12, 22, 0.6);
--surface-card: rgba(16, 16, 30, 0.65);
--surface-inner: rgba(255, 255, 255, 0.025);
--border: rgba(255, 255, 255, 0.07);
--border-hover: rgba(255, 255, 255, 0.14);
--text: #f1f5f9;
--text-dim: #94a3b8;
--text-muted: #64748b;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Outfit', sans-serif;
background: #050510;
color: var(--text);
overflow-x: hidden;
min-height: 100vh;
}
.bg-scene {
position: fixed; inset: 0; z-index: 0;
background-image:
linear-gradient(175deg, rgba(5,5,16,0.88) 0%, rgba(5,5,16,0.75) 50%, rgba(5,5,16,0.92) 100%),
url('https://images.wallpapersden.com/image/download/4k-artistic-landscape_bWpoZWiUmZqaraWkpJRobWllrWdma2U.jpg');
background-size: cover; background-position: center;
}
.bg-orbs {
position: fixed; inset: 0; z-index: 0; pointer-events: none;
background:
radial-gradient(ellipse 500px 400px at 15% 15%, rgba(99,102,241,0.08), transparent),
radial-gradient(ellipse 400px 350px at 85% 85%, rgba(249,115,22,0.06), transparent),
radial-gradient(ellipse 300px 300px at 60% 40%, rgba(6,182,212,0.04), transparent);
}
/* noise removed for GPU performance */
.glass-form {
background: rgba(12, 12, 22, 0.82);
border: 1px solid var(--border);
border-radius: 24px;
box-shadow: 0 40px 120px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.05);
}
.card {
background: rgba(16, 16, 30, 0.85);
border: 1px solid var(--border);
border-radius: 16px;
padding: 24px 28px;
transition: border-color 0.4s, box-shadow 0.4s;
position: relative; overflow: visible;
}
.card::before {
content: ''; position: absolute; top: 0; left: 0; right: 0; height: 1px;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.08), transparent);
}
.card:hover { border-color: var(--border-hover); box-shadow: 0 12px 40px rgba(0,0,0,0.25); }
.card-header { display: flex; align-items: center; gap: 14px; margin-bottom: 0px; }
.card-icon {
width: 40px; height: 40px; border-radius: 12px;
display: flex; align-items: center; justify-content: center;
font-size: 18px; flex-shrink: 0;
}
.card-title { font-family: 'Sora', sans-serif; font-size: 1.05rem; font-weight: 600; }
.card-desc { color: var(--text-dim); font-size: 0.83rem; margin-left: 54px; margin-bottom: 20px; line-height: 1.5; }
.tog-row {
display: flex; align-items: flex-start; gap: 14px;
padding: 12px 14px; border-radius: 12px;
transition: background 0.25s;
}
.tog-row:hover { background: rgba(255,255,255,0.025); }
.tog { position: relative; width: 46px; height: 26px; flex-shrink: 0; margin-top: 1px; }
.tog input { opacity: 0; width: 0; height: 0; position: absolute; }
.tog-track {
position: absolute; inset: 0; border-radius: 999px;
background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.06);
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer;
}
.tog-track::after {
content: ''; position: absolute;
width: 20px; height: 20px; border-radius: 50%;
top: 2px; left: 2px; background: #475569;
transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.35s, box-shadow 0.35s;
}
.tog input:checked + .tog-track {
background: var(--accent); border-color: var(--accent-light);
box-shadow: 0 0 16px var(--accent-glow), 0 0 4px var(--accent-glow);
}
.tog input:checked + .tog-track::after {
transform: translateX(20px); background: white;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
.tog input:disabled + .tog-track { opacity: 0.7; cursor: not-allowed; }
.tog-name {
font-weight: 500; font-size: 0.92rem; color: var(--text);
display: flex; align-items: center; gap: 8px;
}
.tog-name img { width: 22px; height: 22px; object-fit: contain; border-radius: 4px; }
.tog-sub { font-size: 0.8rem; color: var(--text-dim); margin-top: 3px; line-height: 1.4; }
/* Indexer search phase selector */
.indexer-category-row { margin-top: 8px; margin-left: -14px; }
.category-label { display: block; font-size: 0.75rem; color: var(--text-dim); margin-bottom: 4px; font-weight: 500; letter-spacing: 0.02em; }
.category-select { max-width: 280px; padding: 5px 10px; font-size: 0.8rem; }
/* "Requires API Key" icon indicator */
.api-key-indicator {
position: relative;
width: 32px; height: 32px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
background: linear-gradient(135deg, rgba(234,179,8,0.1), rgba(249,115,22,0.08));
border: 1px solid rgba(234,179,8,0.2);
color: #fbbf24; flex-shrink: 0; cursor: help;
transition: all 0.35s;
}
.api-key-indicator svg { width: 17px; height: 17px; }
.api-key-indicator:hover {
background: linear-gradient(135deg, rgba(234,179,8,0.18), rgba(249,115,22,0.15));
border-color: rgba(234,179,8,0.4);
box-shadow: 0 0 16px rgba(234,179,8,0.15);
transform: scale(1.1);
}
.tog-row:has(input:checked) .api-key-indicator {
background: linear-gradient(135deg, rgba(234,179,8,0.18), rgba(249,115,22,0.15));
border-color: rgba(234,179,8,0.4);
box-shadow: 0 0 14px rgba(234,179,8,0.12);
animation: apiPulse 2s ease-in-out 1;
}
@keyframes apiPulse {
0% { transform: scale(1); }
30% { transform: scale(1.12); }
60% { transform: scale(0.97); }
100% { transform: scale(1); }
}
.api-key-indicator .api-key-tooltip {
position: absolute; bottom: calc(100% + 10px); right: 0;
padding: 8px 14px; border-radius: 9px;
background: rgba(10,10,25,0.97);
border: 1px solid rgba(234,179,8,0.25);
box-shadow: 0 14px 36px rgba(0,0,0,0.5), 0 0 20px rgba(234,179,8,0.06);
font-family: 'Outfit', sans-serif; font-size: 0.76rem; font-weight: 500;
color: #fbbf24; white-space: nowrap;
opacity: 0; pointer-events: none; z-index: 50;
transform: translateY(4px);
transition: opacity 0.25s, transform 0.25s;
}
.api-key-indicator .api-key-tooltip::after {
content: ''; position: absolute; top: 100%; right: 14px;
border: 6px solid transparent; border-top-color: rgba(234,179,8,0.25);
}
.api-key-indicator:hover .api-key-tooltip {
opacity: 1; pointer-events: auto; transform: translateY(0);
}
/* ═══ TAG INPUT ═══ */
.tag-input-wrap {
display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
padding: 10px 14px; min-height: 48px;
background: rgba(0,0,0,0.3);
border: 1px solid var(--border);
border-radius: 11px;
cursor: text;
transition: border-color 0.3s, box-shadow 0.3s;
}
.tag-input-wrap:focus-within {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-glow), 0 0 20px rgba(99,102,241,0.08);
}
.tag-chip {
display: inline-flex; align-items: center; gap: 6px;
padding: 5px 8px 5px 12px; border-radius: 8px;
background: linear-gradient(135deg, rgba(239,68,68,0.1), rgba(239,68,68,0.06));
border: 1px solid rgba(239,68,68,0.2);
font-size: 0.82rem; font-weight: 500; color: #fca5a5;
animation: chipIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) both;
user-select: none;
}
@keyframes chipIn {
from { opacity: 0; transform: scale(0.7); }
to { opacity: 1; transform: scale(1); }
}
.tag-chip-x {
display: flex; align-items: center; justify-content: center;
width: 18px; height: 18px; border-radius: 5px;
background: rgba(239,68,68,0.15);
cursor: pointer; transition: all 0.2s;
flex-shrink: 0;
}
.tag-chip-x:hover {
background: rgba(239,68,68,0.35);
color: white;
}
.tag-chip-x svg { width: 10px; height: 10px; }
.tag-ghost-input {
flex: 1; min-width: 120px; border: none; outline: none;
background: transparent; color: var(--text);
font-family: 'Outfit', sans-serif; font-size: 0.88rem;
}
.tag-ghost-input::placeholder { color: var(--text-muted); }
.tag-hint {
font-size: 0.72rem; color: var(--text-muted); margin-top: 8px;
display: flex; align-items: center; gap: 6px;
}
.tag-hint kbd {
display: inline-flex; align-items: center; justify-content: center;
padding: 1px 6px; border-radius: 4px; font-size: 0.68rem;
background: rgba(255,255,255,0.06);
border: 1px solid rgba(255,255,255,0.1);
font-family: 'JetBrains Mono', monospace;
color: var(--text-dim);
}
/* YGG Locked */
.ygg-locked {
position: relative;
background: linear-gradient(135deg, rgba(99,102,241,0.06), rgba(6,182,212,0.06));
border: 1px solid rgba(99,102,241,0.15);
border-radius: 14px; padding: 16px 18px;
display: flex; align-items: flex-start; gap: 14px;
}
.ygg-locked::after {
content: ''; position: absolute; inset: -1px; border-radius: 15px; z-index: -1;
background: linear-gradient(135deg, rgba(99,102,241,0.2), rgba(6,182,212,0.2));
opacity: 0; transition: opacity 0.4s;
}
.ygg-locked:hover::after { opacity: 1; }
.ygg-badge {
display: inline-flex; align-items: center; gap: 5px;
padding: 3px 10px; border-radius: 999px;
background: linear-gradient(135deg, rgba(99,102,241,0.18), rgba(6,182,212,0.18));
border: 1px solid rgba(99,102,241,0.3);
font-size: 0.67rem; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.08em; color: var(--accent-light);
box-shadow: 0 0 10px 1px rgba(99,102,241,0.1);
}
.ygg-tw { position: relative; display: inline-flex; }
.ygg-tw .ygg-tip {
position: absolute; top: calc(100% + 14px); left: 50%; transform: translateX(-50%) translateY(-8px);
width: 300px; padding: 18px 20px; border-radius: 14px;
background: rgba(10,10,25,0.97);
border: 1px solid rgba(99,102,241,0.3);
box-shadow: 0 24px 64px rgba(0,0,0,0.6), 0 0 40px rgba(99,102,241,0.08);
opacity: 0; pointer-events: none;
transition: opacity 0.35s, transform 0.35s; z-index: 50;
}
.ygg-tw .ygg-tip::after {
content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
border: 8px solid transparent; border-bottom-color: rgba(99,102,241,0.3);
}
.ygg-tw:hover .ygg-tip { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.ygg-tip h4 {
font-family: 'Sora',sans-serif; font-weight: 700; font-size: 0.85rem;
color: var(--accent-light); margin-bottom: 10px;
display: flex; align-items: center; gap: 7px;
}
.ygg-tip p { font-size: 0.79rem; color: var(--text-dim); line-height: 1.6; }
.ygg-tip strong { color: var(--text); font-weight: 600; }
.rad-group { display: flex; flex-direction: column; gap: 8px; }
.rad-card {
display: flex; align-items: center; gap: 12px;
padding: 13px 16px; border-radius: 12px;
border: 1px solid var(--border); background: var(--surface-inner);
cursor: pointer; transition: all 0.3s; position: relative; overflow: hidden;
}
.rad-card:hover { border-color: var(--border-hover); background: rgba(255,255,255,0.035); }
.rad-card:has(input:checked) {
border-color: var(--accent); background: rgba(99,102,241,0.07);
box-shadow: 0 0 0 1px rgba(99,102,241,0.3), 0 0 20px rgba(99,102,241,0.08);
}
.rad-card:has(input:checked)::before {
content: ''; position: absolute; top: 0; left: 0; bottom: 0; width: 3px;
background: linear-gradient(180deg, var(--accent), var(--cyan)); border-radius: 0 2px 2px 0;
}
.rad-dot {
width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
border: 2px solid rgba(255,255,255,0.15);
display: flex; align-items: center; justify-content: center; transition: all 0.3s;
}
.rad-card:has(input:checked) .rad-dot {
border-color: var(--accent); background: var(--accent); box-shadow: 0 0 8px var(--accent-glow);
}
.rad-dot::after {
content: ''; width: 8px; height: 8px; border-radius: 50%;
background: white; transform: scale(0); transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1);
}
.rad-card:has(input:checked) .rad-dot::after { transform: scale(1); }
.rad-card input { position: absolute; opacity: 0; pointer-events: none; }
.rad-text { font-size: 0.88rem; font-weight: 450; }
.pill-group { display: flex; flex-wrap: wrap; gap: 10px; }
.pill {
display: inline-flex; align-items: center; gap: 8px;
padding: 9px 18px; border-radius: 999px;
border: 1px solid var(--border); background: var(--surface-inner);
cursor: pointer; transition: all 0.3s; user-select: none;
font-size: 0.88rem; font-weight: 450;
}
.pill:hover { border-color: var(--border-hover); background: rgba(255,255,255,0.04); }
.pill:has(input:checked) {
border-color: var(--accent); background: rgba(99,102,241,0.1); color: var(--accent-light);
box-shadow: 0 0 12px rgba(99,102,241,0.1);
}
.pill input { display: none; }
.pill .pd {
width: 8px; height: 8px; border-radius: 50%;
background: rgba(255,255,255,0.15); transition: all 0.3s;
}
.pill:has(input:checked) .pd { background: var(--accent-light); box-shadow: 0 0 6px var(--accent-glow); }
.pill-hint { font-size: 0.7rem; color: var(--text-muted); }
.chk-row {
display: flex; align-items: center; gap: 11px;
padding: 9px 12px; border-radius: 10px; cursor: pointer; transition: background 0.2s;
}
.chk-row:hover { background: rgba(255,255,255,0.025); }
.chk-box {
width: 20px; height: 20px; border-radius: 6px; flex-shrink: 0;
border: 1.5px solid rgba(255,255,255,0.15);
display: flex; align-items: center; justify-content: center; transition: all 0.3s;
}
.chk-row:has(input:checked) .chk-box {
background: var(--accent); border-color: var(--accent-light);
box-shadow: 0 0 8px rgba(99,102,241,0.25);
}
.chk-box svg { opacity: 0; transition: opacity 0.25s; width: 12px; height: 12px; }
.chk-row:has(input:checked) .chk-box svg { opacity: 1; }
.chk-row input { position: absolute; opacity: 0; pointer-events: none; }
.chk-text { font-size: 0.87rem; color: var(--text); }
.fi-group { position: relative; }
.fi-group label {
display: block; font-size: 0.75rem; font-weight: 600;
color: var(--text-dim); margin-bottom: 7px;
text-transform: uppercase; letter-spacing: 0.06em;
}
.fi {
width: 100%; padding: 12px 16px;
background: rgba(0,0,0,0.3); border: 1px solid var(--border);
border-radius: 11px; color: var(--text);
font-family: 'Outfit',sans-serif; font-size: 0.9rem;
transition: border-color 0.3s, box-shadow 0.3s; outline: none;
}
.fi::placeholder { color: var(--text-muted); }
.fi:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow), 0 0 20px rgba(99,102,241,0.08); }
.fi.mono { font-family: 'JetBrains Mono',monospace; font-size: 0.84rem; letter-spacing: -0.02em; }
.fi-hint { font-size: 0.73rem; color: var(--text-muted); margin-top: 6px; }
.fi-hint a {
color: var(--accent-light); text-decoration: none; font-weight: 600;
transition: color 0.2s;
}
.fi-hint a:hover { color: #a5b4fc; text-decoration: underline; }
/* ═══ EN SVOIR PLUS (FLAIR) ═══ */
.slider-label-row {
display: flex !important; align-items: center; gap: 10px; flex-wrap: wrap;
}
.hint-flair {
display: inline-flex; align-items: center; gap: 4px;
padding: 2px 9px; border-radius: 999px;
background: rgba(6,182,212,0.08); border: 1px solid rgba(6,182,212,0.2);
font-family: 'Outfit', sans-serif; font-size: 0.62rem; font-weight: 600;
text-transform: uppercase; letter-spacing: 0.04em;
color: var(--cyan); cursor: pointer;
transition: all 0.25s;
}
.hint-flair svg { width: 10px; height: 10px; flex-shrink: 0; }
.hint-flair:hover {
background: rgba(6,182,212,0.15); border-color: rgba(6,182,212,0.35);
box-shadow: 0 0 12px rgba(6,182,212,0.1);
}
/* ═══ MODAL INFO ═══ */
.hint-modal-overlay {
position: fixed; inset: 0; z-index: 9999;
background: rgba(0,0,0,0);
backdrop-filter: blur(0px);
display: flex; align-items: center; justify-content: center;
opacity: 0; visibility: hidden;
transition: opacity 0.3s, backdrop-filter 0.3s, background 0.3s, visibility 0s 0.3s;
}
.hint-modal-overlay.show {
opacity: 1; visibility: visible;
background: rgba(0,0,0,0.55);
backdrop-filter: blur(8px);
transition: opacity 0.3s, backdrop-filter 0.3s, background 0.3s, visibility 0s 0s;
}
.hint-modal-box {
position: relative; width: 90%; max-width: 420px;
background: rgba(16,16,30,0.97);
border: 1px solid rgba(6,182,212,0.2);
border-radius: 20px; padding: 0; overflow: hidden;
box-shadow: 0 40px 100px rgba(0,0,0,0.6), 0 0 60px rgba(6,182,212,0.06);
transform: translateY(20px) scale(0.95);
transition: transform 0.35s cubic-bezier(0.34,1.56,0.64,1);
}
.hint-modal-overlay.show .hint-modal-box {
transform: translateY(0) scale(1);
}
.hint-modal-accent {
height: 3px;
background: linear-gradient(90deg, var(--accent), var(--cyan), var(--accent));
background-size: 200% 100%;
animation: hintAccent 4s ease-in-out infinite;
}
@keyframes hintAccent {
0%,100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
.hint-modal-body { padding: 28px 24px 24px; text-align: center; }
.hint-modal-icon {
width: 48px; height: 48px; border-radius: 14px; margin: 0 auto 16px;
background: linear-gradient(135deg, rgba(6,182,212,0.1), rgba(99,102,241,0.1));
border: 1px solid rgba(6,182,212,0.2);
display: flex; align-items: center; justify-content: center;
color: var(--cyan);
box-shadow: 0 0 24px rgba(6,182,212,0.08);
}
.hint-modal-icon svg { width: 22px; height: 22px; }
.hint-modal-title {
font-family: 'Sora', sans-serif; font-weight: 700; font-size: 1.05rem;
color: var(--text); margin-bottom: 12px;
}
.hint-modal-text {
font-size: 0.85rem; color: var(--text-dim); line-height: 1.7; margin-bottom: 0;
text-align: left;
}
.hint-modal-footer { text-align: center; margin-top: 20px; }
.hint-modal-btn {
display: inline-flex; align-items: center; justify-content: center;
padding: 10px 28px; border-radius: 11px; border: none; cursor: pointer;
font-family: 'Sora', sans-serif; font-weight: 600; font-size: 0.85rem;
color: white;
background: linear-gradient(135deg, var(--accent), var(--cyan));
box-shadow: 0 4px 16px rgba(6,182,212,0.2);
transition: all 0.3s;
}
.hint-modal-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 24px rgba(6,182,212,0.3);
}
@media (max-width: 640px) {
.hint-modal-box { width: 94%; max-width: 360px; border-radius: 16px; }
.hint-modal-body { padding: 22px 18px 20px; }
.hint-modal-title { font-size: 0.95rem; }
.hint-modal-text { font-size: 0.8rem; }
.hint-flair { font-size: 0.58rem; padding: 2px 7px; }
}
div[id$="-fields"] .fi-group + .fi-group { margin-top: 14px; }
/* ═══ ICONE TOOLTIP ═══ */
.info-tip-wrap { position: relative; display: inline-flex; align-items: center; }
.info-tip-bubble {
position: absolute; top: calc(100% + 12px); left: 50%; transform: translateX(-50%) translateY(-6px);
width: 300px; padding: 14px 16px; border-radius: 12px;
background: rgba(10,10,25,0.97);
border: 1px solid rgba(99,102,241,0.25);
box-shadow: 0 20px 50px rgba(0,0,0,0.5), 0 0 30px rgba(99,102,241,0.06);
font-size: 0.78rem; font-weight: 400; color: var(--text-dim); line-height: 1.55;
text-transform: none; letter-spacing: 0;
opacity: 0; pointer-events: none; z-index: 50;
transition: opacity 0.3s, transform 0.3s;
}
.info-tip-bubble::after {
content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
border: 7px solid transparent; border-bottom-color: rgba(99,102,241,0.25);
}
.info-tip-wrap:hover .info-tip-bubble {
opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0);
}
.info-tip-bubble strong { color: var(--text); font-weight: 600; }
.status-flair.info-tip-wrap { cursor: help; }
/* ═══ STATUS FLAIR (Actif / Inactif) ═══ */
.status-flair {
display: inline-flex; align-items: center; gap: 5px;
padding: 3px 10px; border-radius: 999px;
font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.06em;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.status-flair .status-dot {
width: 6px; height: 6px; border-radius: 50%;
transition: all 0.4s;
}
.status-flair.active {
background: rgba(34,197,94,0.12); border: 1px solid rgba(34,197,94,0.3);
color: #4ade80;
}
.status-flair.active .status-dot {
background: #4ade80; box-shadow: 0 0 8px rgba(34,197,94,0.5);
}
.status-flair.inactive {
background: rgba(239,68,68,0.1); border: 1px solid rgba(239,68,68,0.25);
color: #f87171;
}
.status-flair.inactive .status-dot {
background: #f87171; box-shadow: 0 0 6px rgba(239,68,68,0.4);
}
.priority-select-wrap { position: relative; max-width: 320px; }
.priority-select-wrap select { display: none; }
.priority-select-label {
display: flex; align-items: center; gap: 8px;
font-size: 0.75rem; font-weight: 600; color: var(--text-dim);
margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.04em;
}
.priority-select-label svg { width: 13px; height: 13px; color: var(--text-muted); }
.prio-trigger {
display: flex; align-items: center; gap: 10px;
width: 100%; padding: 10px 14px;
background: rgba(0,0,0,0.35);
border: 1px solid var(--border);
border-radius: 10px; color: var(--text);
font-family: 'Outfit', sans-serif; font-size: 0.82rem; font-weight: 500;
cursor: pointer; outline: none; user-select: none;
transition: border-color 0.3s, box-shadow 0.3s, background 0.3s;
}
.prio-trigger:hover {
border-color: var(--border-hover); background: rgba(0,0,0,0.45);
}
.prio-trigger.open {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-glow), 0 0 16px rgba(99,102,241,0.06);
border-radius: 10px 10px 0 0;
}
.prio-trigger .prio-dot {
width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
transition: all 0.35s;
}
.prio-trigger .prio-arrow {
margin-left: auto; width: 16px; height: 16px; color: var(--text-muted);
transition: transform 0.3s, color 0.3s; flex-shrink: 0;
}
.prio-trigger.open .prio-arrow { transform: rotate(180deg); color: var(--accent-light); }
.prio-trigger .prio-label { flex: 1; }
.prio-trigger .prio-rank {
font-size: 0.65rem; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.06em; padding: 2px 8px; border-radius: 999px;
flex-shrink: 0;
}
/* Dropdown */
.prio-dropdown {
position: absolute; top: 100%; left: 0; right: 0;
background: rgba(12,12,22,0.97);
border: 1px solid var(--accent);
border-top: none;
border-radius: 0 0 10px 10px;
box-shadow: 0 16px 48px rgba(0,0,0,0.5), 0 0 20px rgba(99,102,241,0.06);
z-index: 60; overflow: hidden;
max-height: 0; opacity: 0;
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s;
}
.prio-dropdown.open {
max-height: 200px; opacity: 1;
}
.prio-option {
display: flex; align-items: center; gap: 10px;
padding: 11px 14px;
font-family: 'Outfit', sans-serif; font-size: 0.82rem; font-weight: 450;
color: var(--text-dim); cursor: pointer;
transition: all 0.2s; position: relative;
}
.prio-option:not(:last-child) {
border-bottom: 1px solid rgba(255,255,255,0.04);
}
.prio-option:hover {
background: rgba(255,255,255,0.04); color: var(--text);
}
.prio-option.selected {
color: var(--text); font-weight: 500;
}
.prio-option.selected::before {
content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 3px;
border-radius: 0 2px 2px 0;
}
.prio-option .prio-dot {
width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
}
.prio-option .prio-rank {
font-size: 0.65rem; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.06em; padding: 2px 8px; border-radius: 999px;
flex-shrink: 0; margin-left: auto;
}
.prio-option .prio-desc {
font-size: 0.72rem; color: var(--text-muted); font-weight: 400;
}
/* COULEUR PRIORITAIRE */
.prio-priority .prio-dot { background: #4ade80; box-shadow: 0 0 8px rgba(34,197,94,0.5); }
.prio-priority .prio-rank { background: rgba(34,197,94,0.12); color: #4ade80; border: 1px solid rgba(34,197,94,0.25); }
.prio-option.prio-priority.selected::before { background: #4ade80; }
.prio-option.prio-priority:hover { background: rgba(34,197,94,0.06); }
/* COULEUR INTERMEDIAIRE */
.prio-intermediary .prio-dot { background: #fbbf24; box-shadow: 0 0 8px rgba(234,179,8,0.5); }
.prio-intermediary .prio-rank { background: rgba(234,179,8,0.12); color: #fbbf24; border: 1px solid rgba(234,179,8,0.25); }
.prio-option.prio-intermediary.selected::before { background: #fbbf24; }
.prio-option.prio-intermediary:hover { background: rgba(234,179,8,0.06); }
/* COULEUR FALLBACK */
.prio-fallback .prio-dot { background: #f87171; box-shadow: 0 0 8px rgba(239,68,68,0.5); }
.prio-fallback .prio-rank { background: rgba(239,68,68,0.1); color: #f87171; border: 1px solid rgba(239,68,68,0.25); }
.prio-option.prio-fallback.selected::before { background: #f87171; }
.prio-option.prio-fallback:hover { background: rgba(239,68,68,0.06); }
.priority-select-wrap[data-level="priority"] .prio-trigger {
border-color: rgba(34,197,94,0.25); background: rgba(34,197,94,0.04);
}
.priority-select-wrap[data-level="priority"] .prio-trigger:hover {
border-color: rgba(34,197,94,0.4);
box-shadow: 0 0 16px rgba(34,197,94,0.1), 0 0 4px rgba(34,197,94,0.08);
}
.priority-select-wrap[data-level="intermediary"] .prio-trigger {
border-color: rgba(234,179,8,0.25); background: rgba(234,179,8,0.04);
}
.priority-select-wrap[data-level="intermediary"] .prio-trigger:hover {
border-color: rgba(234,179,8,0.4);
box-shadow: 0 0 16px rgba(234,179,8,0.1), 0 0 4px rgba(234,179,8,0.08);
}
.priority-select-wrap[data-level="fallback"] .prio-trigger {
border-color: rgba(239,68,68,0.2); background: rgba(239,68,68,0.04);
}
.priority-select-wrap[data-level="fallback"] .prio-trigger:hover {
border-color: rgba(239,68,68,0.35);
box-shadow: 0 0 16px rgba(239,68,68,0.1), 0 0 4px rgba(239,68,68,0.08);
}
/* ═══ API KEY VALIDATION INDICATOR ═══ */
.api-key-wrap { position: relative; }
.api-key-wrap .fi { padding-right: 48px; }
.api-key-status {
position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
width: 28px; height: 28px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
opacity: 0; transform: translateY(-50%) scale(0.5);
transition: opacity 0.35s, transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
pointer-events: none;
}
.api-key-status.invalid {
opacity: 1; transform: translateY(-50%) scale(1);
background: rgba(239,68,68,0.15); color: #fca5a5;
}
.api-key-status svg { width: 14px; height: 14px; }
.api-key-msg {
margin-top: 8px; font-size: 0.78rem; font-weight: 500;
display: flex; align-items: center; gap: 6px;
opacity: 0; max-height: 0; overflow: hidden;
transition: opacity 0.3s, max-height 0.3s;
}
.api-key-msg.show { opacity: 1; max-height: 40px; }
.api-key-msg.invalid { color: #fca5a5; }
.api-key-msg svg { width: 14px; height: 14px; flex-shrink: 0; }
/* ═══ CREDENTIAL PAIR ═══ */
.cred-pair {
display: flex; gap: 10px; align-items: flex-end;
}
.cred-pair .fi-group { flex: 1; }
.cred-pair .fi-group.email-field { flex: 1.2; }
@media (max-width: 480px) { .cred-pair { flex-direction: column; } }
.cred-pair-label {
font-size: 0.75rem; font-weight: 600;
color: var(--text-dim); margin-bottom: 10px;
text-transform: uppercase; letter-spacing: 0.06em;
display: flex; align-items: center; gap: 6px;
}
.cred-pair-label svg { width: 14px; height: 14px; color: var(--text-muted); }
.fi[type="number"]::-webkit-inner-spin-button,
.fi[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.fi[type="number"] { -moz-appearance: textfield; }
/* ═══ SLIDER NUMBER CONTROL ═══ */
.slider-control { display: flex; flex-direction: column; gap: 0; }
.slider-control label {
font-size: 0.75rem; font-weight: 600;
color: var(--text-dim); margin-bottom: 10px;
text-transform: uppercase; letter-spacing: 0.06em;
}
.slider-row {
display: flex; align-items: center; gap: 14px;
}
.slider-track-wrap {
flex: 1; position: relative; height: 40px;
display: flex; align-items: center;
}
.slider-range {
-webkit-appearance: none; appearance: none;
width: 100%; height: 8px; border-radius: 4px;
background: rgba(255,255,255,0.06);
outline: none; cursor: pointer;
position: relative; z-index: 2;
}
.slider-range::-webkit-slider-thumb {
-webkit-appearance: none; appearance: none;
width: 24px; height: 24px; border-radius: 50%;
background: linear-gradient(135deg, var(--accent-light), var(--accent));
box-shadow: 0 0 12px var(--accent-glow), 0 2px 6px rgba(0,0,0,0.4);
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.slider-range::-webkit-slider-thumb:hover {
transform: scale(1.15);
box-shadow: 0 0 20px var(--accent-glow), 0 2px 8px rgba(0,0,0,0.5);
}
.slider-range::-webkit-slider-thumb:active {
transform: scale(1.05);
}
.slider-range::-moz-range-thumb {
width: 24px; height: 24px; border-radius: 50%; border: none;
background: linear-gradient(135deg, var(--accent-light), var(--accent));
box-shadow: 0 0 12px var(--accent-glow), 0 2px 6px rgba(0,0,0,0.4);
cursor: pointer;
}
.slider-range::-moz-range-track {
height: 8px; border-radius: 4px;
background: rgba(255,255,255,0.06);
border: none;
}
.slider-fill {
position: absolute; left: 0; top: 50%; transform: translateY(-50%);
height: 8px; border-radius: 4px;
background: linear-gradient(90deg, var(--accent), var(--cyan));
pointer-events: none; z-index: 1;
transition: none;
}
.slider-val {
width: 75px; padding: 8px 0; text-align: center;
border-radius: 10px;
background: rgba(0,0,0,0.3); border: 1px solid var(--border);
font-family: 'JetBrains Mono', monospace;
font-size: 0.92rem; font-weight: 600;
color: var(--accent-light);
transition: border-color 0.3s;
}
.slider-val:focus-within { border-color: var(--accent); }
.slider-val input {
width: 120%; text-align: center;
background: transparent; border: none; outline: none;
color: var(--accent-light);
font-family: 'JetBrains Mono', monospace;
font-size: 0.92rem; font-weight: 600;
}
.slider-val input::placeholder { color: var(--text-muted); }
.slider-grid {
display: flex; flex-direction: column; gap: 24px;
}
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
padding: 14px 32px; border-radius: 14px;
font-family: 'Sora',sans-serif; font-weight: 600; font-size: 0.92rem;
border: none; cursor: pointer; transition: all 0.35s;
text-decoration: none; color: white; position: relative; overflow: hidden;
}
.btn::before {
content: ''; position: absolute; inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.1), transparent);
opacity: 0; transition: opacity 0.3s;
}
.btn:hover::before { opacity: 1; }
.btn-primary {
background: linear-gradient(135deg, var(--accent), #7c3aed);
box-shadow: 0 4px 24px var(--accent-glow), 0 0 0 1px rgba(99,102,241,0.3);
}
.btn-primary:hover {
transform: translateY(-3px);
box-shadow: 0 8px 32px rgba(99,102,241,0.5), 0 0 0 1px rgba(99,102,241,0.5);
}
.btn-secondary {
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1);
}
.btn-secondary:hover { background: rgba(255,255,255,0.1); transform: translateY(-3px); }
.btn-oauth {
padding: 10px 20px; border-radius: 10px;
font-family: 'Outfit',sans-serif; font-weight: 600; font-size: 0.84rem;
border: none; cursor: pointer; color: white; transition: all 0.3s;
}
.btn-oauth-indigo { background: var(--accent); }
.btn-oauth-indigo:hover { background: var(--accent-light); box-shadow: 0 4px 20px var(--accent-glow); }
.btn-oauth-orange { background: var(--orange); }
.btn-oauth-orange:hover { background: var(--orange-light); box-shadow: 0 4px 20px rgba(249,115,22,0.3); }
.auth-box {
padding: 14px 18px; border-radius: 11px;
background: rgba(255,255,255,0.03); border: 1px solid var(--border);
font-size: 0.85rem; color: var(--text-dim);
}
.auth-box a { color: var(--accent-light); text-decoration: none; font-weight: 500; }
.auth-box a:hover { text-decoration: underline; }
.auth-box strong { color: var(--text); }
.err-msg {
padding: 10px 16px; border-radius: 10px;
background: rgba(239,68,68,0.08); border: 1px solid rgba(239,68,68,0.2);
color: #fca5a5; font-size: 0.84rem; text-align: center;
}
/* ═══ RD DEPRECATION MODAL ═══ */
.rd-modal-overlay {
position: fixed; inset: 0; z-index: 9999;
background: rgba(0,0,0,0);
backdrop-filter: blur(0px);
display: flex; align-items: center; justify-content: center;
opacity: 0; visibility: hidden;
transition: opacity 0.35s, backdrop-filter 0.35s, background 0.35s, visibility 0s 0.35s;
}
.rd-modal-overlay.show {
opacity: 1; visibility: visible;
background: rgba(0,0,0,0.6);
backdrop-filter: blur(8px);
transition: opacity 0.35s, backdrop-filter 0.35s, background 0.35s, visibility 0s 0s;
}
.rd-modal-box {
position: relative; width: 90%; max-width: 440px;
background: rgba(16,16,30,0.97);
border: 1px solid rgba(249,115,22,0.25);
border-radius: 20px; padding: 0; overflow: hidden;
box-shadow: 0 40px 100px rgba(0,0,0,0.6), 0 0 60px rgba(249,115,22,0.08);
transform: translateY(20px) scale(0.95);
transition: transform 0.4s cubic-bezier(0.34,1.56,0.64,1);
}
.rd-modal-overlay.show .rd-modal-box {
transform: translateY(0) scale(1);
}
.rd-modal-accent {
height: 4px;
background: linear-gradient(90deg, var(--orange), var(--red), var(--orange));
background-size: 200% 100%;
animation: rdAccentShift 3s ease-in-out infinite;
}
@keyframes rdAccentShift {
0%,100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
.rd-modal-body { padding: 32px 28px 28px; text-align: left; }
.rd-modal-icon {
width: 56px; height: 56px; border-radius: 16px; margin: 0 auto 18px;
background: linear-gradient(135deg, rgba(249,115,22,0.12), rgba(239,68,68,0.1));
border: 1px solid rgba(249,115,22,0.2);
display: flex; align-items: center; justify-content: center;
color: var(--orange-light);
box-shadow: 0 0 30px rgba(249,115,22,0.1);
}
.rd-modal-icon svg { width: 26px; height: 26px; }
.rd-modal-title {
font-family: 'Sora', sans-serif; font-weight: 700; font-size: 1.15rem;
color: var(--orange-light); margin-bottom: 12px; text-align: center;
}
.rd-modal-text {
font-size: 0.88rem; color: var(--text-dim); line-height: 1.65; margin-bottom: 0;
}
.rd-modal-text strong { color: var(--text); font-weight: 600; }
.rd-modal-footer { text-align: center; margin-top: 24px; }
.rd-modal-btn {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
padding: 12px 32px; border-radius: 12px; border: none; cursor: pointer;
font-family: 'Sora', sans-serif; font-weight: 600; font-size: 0.88rem;
color: white; position: relative; overflow: hidden;
background: linear-gradient(135deg, var(--orange), #ea580c);
box-shadow: 0 4px 20px rgba(249,115,22,0.3);
transition: all 0.3s;
}
.rd-modal-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 28px rgba(249,115,22,0.4);
}
.rd-modal-btn::before {
content: ''; position: absolute; inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.12), transparent);
opacity: 0; transition: opacity 0.3s;
}
.rd-modal-btn:hover::before { opacity: 1; }
.sep { height: 1px; background: var(--border); margin: 6px 0; }
.sec-label {
font-size: 0.73rem; font-weight: 600; text-transform: uppercase;
letter-spacing: 0.07em; color: var(--text-muted); margin-bottom: 10px;
}
.discord-bar {
display: flex; align-items: center; justify-content: center; gap: 8px;
padding: 10px 16px; border-radius: 12px;
background: linear-gradient(135deg, rgba(88,101,242,0.1), rgba(88,101,242,0.05));
border: 1px solid rgba(88,101,242,0.2);
font-size: 0.84rem; color: var(--text-dim);
}
.discord-bar a { color: #7289da; font-weight: 600; text-decoration: none; }
.discord-bar a:hover { color: #99aab5; }
@keyframes fadeUp {
from { opacity: 0; transform: translateY(28px); }
to { opacity: 1; transform: translateY(0); }
}
.anim { animation: fadeUp 0.65s ease-out both; }
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }
/* ═══ DEBRID DOWNLOADER RADIO CARDS ═══ */
#debridDownloaderOptions { display: flex; flex-direction: column; gap: 8px; }
#debridDownloaderOptions > div {
display: flex !important; align-items: center !important; gap: 12px !important;
padding: 13px 16px !important; border-radius: 12px !important;
border: 1px solid var(--border) !important; background: var(--surface-inner) !important;
cursor: pointer; transition: all 0.3s; position: relative; overflow: hidden;
width: auto !important; margin: 0 !important;
}
#debridDownloaderOptions > div:hover {
border-color: var(--border-hover) !important; background: rgba(255,255,255,0.035) !important;
}
#debridDownloaderOptions > div:has(input:checked) {
border-color: var(--accent) !important; background: rgba(99,102,241,0.07) !important;
box-shadow: 0 0 0 1px rgba(99,102,241,0.3), 0 0 20px rgba(99,102,241,0.08);
}
#debridDownloaderOptions > div:has(input:checked)::before {
content: ''; position: absolute; top: 0; left: 0; bottom: 0; width: 3px;
background: linear-gradient(180deg, var(--accent), var(--cyan)); border-radius: 0 2px 2px 0;
}
#debridDownloaderOptions > div input[type="radio"] {
-webkit-appearance: none; appearance: none;
width: 20px !important; height: 20px !important; border-radius: 50% !important;
border: 2px solid rgba(255,255,255,0.15) !important;
background: transparent !important; cursor: pointer;
display: flex !important; align-items: center; justify-content: center;
position: relative; flex-shrink: 0;
transition: all 0.3s; box-shadow: none !important; outline: none !important;
}
#debridDownloaderOptions > div input[type="radio"]::after {
content: ''; width: 8px; height: 8px; border-radius: 50%;
background: white; position: absolute;
transform: scale(0); transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1);
}
#debridDownloaderOptions > div input[type="radio"]:checked {
border-color: var(--accent) !important; background: var(--accent) !important;
box-shadow: 0 0 8px var(--accent-glow) !important;
}
#debridDownloaderOptions > div input[type="radio"]:checked::after { transform: scale(1); }
#debridDownloaderOptions > div label {
font-family: 'Outfit', sans-serif !important; font-size: 0.88rem !important;
font-weight: 450 !important; color: var(--text) !important;
margin: 0 !important; padding: 0 !important; cursor: pointer;
}
/* ═══ DEBRID ORDER LIST ═══ */
#debridOrderList {
display: flex; flex-direction: column; gap: 6px;
padding: 0; list-style: none;
position: relative;
}
#debridOrderList.hidden { display: none !important; }
#debridOrderList li {
display: flex !important; align-items: center !important; gap: 0 !important;
padding: 0 !important; border-radius: 12px !important; width: auto !important;
background: var(--surface-inner) !important; border: 1px solid var(--border) !important;
color: var(--text) !important; font-family: 'Outfit', sans-serif;
font-size: 0.88rem !important; font-weight: 450;
cursor: grab;
position: relative; margin: 0 !important;
box-shadow: none !important;
-webkit-user-select: none; user-select: none;
}
#debridOrderList li::before { display: none !important; }
#debridOrderList li:hover {
border-color: var(--border-hover) !important; background: rgba(255,255,255,0.04) !important;
}
/* Lifted item following cursor */
#debridOrderList li.dol-lifted {
position: fixed !important; z-index: 9999; pointer-events: none;
border-color: var(--accent) !important;
background: rgba(16,16,30,0.96) !important;
box-shadow: 0 20px 50px rgba(0,0,0,0.5), 0 0 30px rgba(99,102,241,0.12), 0 0 0 1px rgba(99,102,241,0.3) !important;
cursor: grabbing; transform: scale(1.03);
transition: box-shadow 0.2s, transform 0.15s !important;
}
#debridOrderList li.dol-lifted .dol-handle { color: var(--accent-light); }
#debridOrderList li.dol-lifted .dol-arrows { opacity: 0; }
/* Placeholder gap */
.dol-placeholder {
border-radius: 12px;
background: rgba(99,102,241,0.04);
border: 2px dashed rgba(99,102,241,0.2);
transition: none;
pointer-events: none;
}
/* Items sliding around */
#debridOrderList li.dol-shifting {
transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1) !important;
}
/* Snap back after drop */
#debridOrderList li.dol-snap {
transition: top 0.2s cubic-bezier(0.22, 1, 0.36, 1), left 0.2s cubic-bezier(0.22, 1, 0.36, 1), transform 0.2s cubic-bezier(0.22, 1, 0.36, 1) !important;
}
/* Drag handle */
.dol-handle {
display: flex; align-items: center; justify-content: center;
width: 42px; align-self: stretch;
color: var(--text-muted);
transition: color 0.2s;
flex-shrink: 0;
}
#debridOrderList li:hover .dol-handle { color: var(--accent-light); }
.dol-handle svg { width: 16px; height: 16px; }
/* Position badge */
.dol-pos {
width: 26px; height: 26px; border-radius: 8px;
display: flex; align-items: center; justify-content: center;
font-family: 'JetBrains Mono', monospace; font-size: 0.72rem; font-weight: 700;
flex-shrink: 0; transition: all 0.3s;
}
#debridOrderList li:nth-child(1) .dol-pos {
background: rgba(34,197,94,0.12); color: #4ade80; border: 1px solid rgba(34,197,94,0.25);
}
#debridOrderList li:nth-child(2) .dol-pos {
background: rgba(99,102,241,0.12); color: var(--accent-light); border: 1px solid rgba(99,102,241,0.25);
}
#debridOrderList li:nth-child(3) .dol-pos {
background: rgba(234,179,8,0.1); color: #fbbf24; border: 1px solid rgba(234,179,8,0.25);
}
#debridOrderList li:nth-child(n+4) .dol-pos {
background: rgba(255,255,255,0.05); color: var(--text-muted); border: 1px solid var(--border);
}
/* Content area */
.dol-content {
flex: 1; display: flex; align-items: center; gap: 10px;
padding: 12px 0; min-width: 0;
}
.dol-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Up/down buttons */
.dol-arrows {
display: flex; flex-direction: column; gap: 2px;
padding: 4px 10px; flex-shrink: 0; align-self: stretch;
justify-content: center;
}
.dol-arrow {
display: flex; align-items: center; justify-content: center;
width: 26px; height: 20px; border-radius: 5px;
background: transparent; border: 1px solid transparent;
color: var(--text-muted); cursor: pointer;
transition: all 0.2s;
}
.dol-arrow:hover {
background: rgba(99,102,241,0.1); border-color: rgba(99,102,241,0.25);
color: var(--accent-light);
}
.dol-arrow:active { transform: scale(0.9); }
.dol-arrow.disabled { opacity: 0.15; pointer-events: none; }
.dol-arrow svg { width: 12px; height: 12px; }
/* Landing glow */
#debridOrderList li.dol-landing {
border-color: var(--accent) !important;
box-shadow: 0 0 20px rgba(99,102,241,0.15), 0 0 0 1px rgba(99,102,241,0.2) !important;
}
.dol-pos.dol-pos-pop {
animation: dolPosPop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes dolPosPop {
0% { transform: scale(1); }
40% { transform: scale(1.3); }
100% { transform: scale(1); }
}
@media (max-width: 640px) {
.dol-handle { width: 36px; }
.dol-pos { width: 22px; height: 22px; font-size: 0.65rem; border-radius: 6px; }
.dol-content { padding: 10px 0; gap: 8px; font-size: 0.82rem; }
.dol-arrows { padding: 4px 6px; }
.dol-arrow { width: 28px; height: 22px; }
}
#debridDownloaderOptions:empty::after {
content: 'Aucun service de débridage sélectionné';
display: block; padding: 12px 16px; border-radius: 10px;
background: rgba(239,68,68,0.06); border: 1px solid rgba(239,68,68,0.18);
color: #fca5a5; font-size: 0.84rem; text-align: center;
}
.hidden { display: none; }
.multipleSelection { width: 150px; }
.selectBox { position: relative; }
.overSelect { position: absolute; left: 0; right: 0; top: 0; bottom: 0; }
/* ═══ COLLAPSIBLE CARDS ═══ */
.card-header[onclick] { cursor: pointer; user-select: none; }
.card-header .card-chevron {
margin-left: auto; width: 20px; height: 20px; color: var(--text-muted);
transition: transform 0.3s ease;
flex-shrink: 0;
}
.card.collapsed .card-header .card-chevron { transform: rotate(-90deg); }
.card.collapsed > :not(.card-header) {
max-height: 0; overflow: hidden; opacity: 0;
margin-top: 0 !important; margin-bottom: 0 !important;
padding-top: 0 !important; padding-bottom: 0 !important;
transition: max-height 0.3s cubic-bezier(0, 0.9, 0.3, 1), opacity 0.3s ease;
}
.card > :not(.card-header) {
overflow: hidden; opacity: 1;
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
}
/* ═══ WIZARD STEPPER ═══ */
.wizard-stepper {
display: flex; align-items: center; justify-content: center;
gap: 0; padding: 0; flex-wrap: wrap;
}
.wiz-step-item {
display: flex; align-items: center; gap: 0;
}
.wiz-dot {
width: 38px; height: 38px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
border: 2px solid rgba(255,255,255,0.1);
color: var(--text-muted);
background: transparent;
cursor: pointer; transition: all 0.4s;
position: relative; flex-shrink: 0;
}
.wiz-dot svg { width: 16px; height: 16px; }
.wiz-dot:hover { border-color: rgba(255,255,255,0.2); color: var(--text-dim); }
.wiz-dot.active {
border-color: var(--accent);
color: var(--accent-light);
background: rgba(99,102,241,0.12);
box-shadow: 0 0 16px var(--accent-glow), inset 0 0 12px rgba(99,102,241,0.1);
transform: scale(1.12);
}
.wiz-dot.done {
border-color: rgba(34,197,94,0.5);
color: #4ade80;
background: rgba(34,197,94,0.1);
box-shadow: 0 0 10px rgba(34,197,94,0.15);
}
.wiz-dot::after {
content: attr(title);
position: absolute; bottom: calc(100% + 10px); left: 50%;
transform: translateX(-50%) translateY(4px);
padding: 5px 12px; border-radius: 8px;
background: rgba(10,10,25,0.95);
border: 1px solid var(--border);
color: var(--text-dim); font-family: 'Outfit',sans-serif;
font-size: 0.7rem; font-weight: 500;
white-space: nowrap; pointer-events: none;
opacity: 0; transition: opacity 0.25s, transform 0.25s;
z-index: 10;
}
.wiz-dot:hover::after {
opacity: 1; transform: translateX(-50%) translateY(0);
}
.wiz-line {
width: 24px; height: 2px; background: rgba(255,255,255,0.08);
transition: background 0.4s; flex-shrink: 0;
}
.wiz-line.done { background: rgba(34,197,94,0.45); }
@media (max-width: 520px) {
.wiz-dot { width: 32px; height: 32px; }
.wiz-dot svg { width: 13px; height: 13px; }
.wiz-line { width: 12px; }
.wiz-btn { padding: 10px 18px; font-size: 0.82rem; }
.wiz-nav { padding: 12px 14px; }
}
.wiz-step-label {
display: none;
}
.wiz-title {
margin-top: 14px; margin-bottom: 0;
font-family: 'Sora', sans-serif; font-weight: 700;
font-size: 1.15rem;
background: linear-gradient(135deg, var(--text), var(--accent-light));
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
}
.wiz-subtitle {
font-size: 0.78rem;
color: var(--text-muted); margin-top: 1px; margin-bottom: 8px;
}
/* ═══ WIZARD STEPS ═══ */
.wizard-step {
display: none;
}
.wizard-step.active { display: block; animation: stepIn 0.4s ease-out both; }
.wizard-step.slide-left { animation: slideLeft 0.4s ease-out both; }
.wizard-step.slide-right { animation: slideRight 0.4s ease-out both; }
@keyframes stepIn {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes slideLeft {
from { opacity: 0; transform: translateX(40px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes slideRight {
from { opacity: 0; transform: translateX(-40px); }
to { opacity: 1; transform: translateX(0); }
}
.wizard-step .card { animation: none; }
.wizard-step .card.anim, .wizard-step .anim { animation: none; }
.wizard-step > .card,
.wizard-step > div { margin-bottom: 16px; }
/* ═══ PROGRESS BAR ═══ */
.wiz-progress {
width: 100%; height: 3px; border-radius: 2px;
background: rgba(255,255,255,0.05);
margin-top: 16px; margin-bottom: -4px;
overflow: hidden;
}
.wiz-progress-fill {
height: 100%; border-radius: 2px;
background: linear-gradient(90deg, var(--accent), var(--cyan));
transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
/* ═══ WIZARD NAV BUTTONS ═══ */
.wiz-nav {
display: flex; justify-content: center; align-items: center;
margin-top: 20px;
}
.wiz-stepper-row {
display: flex; align-items: center; gap: 14px; justify-content: center;
}
.wiz-arrow {
width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
background: rgba(255,255,255,0.04);
border: 1px solid var(--border);
color: var(--text-muted); cursor: pointer;
transition: all 0.3s;
}
.wiz-arrow:hover {
background: rgba(99,102,241,0.1); border-color: rgba(99,102,241,0.3);
color: var(--accent-light);
}
.wiz-arrow:disabled, .wiz-arrow[disabled] {
opacity: 0.2; pointer-events: none;
}
.wiz-arrow svg { width: 18px; height: 18px; }
.wiz-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 12px 28px; border-radius: 12px;
font-family: 'Sora', sans-serif; font-weight: 600; font-size: 0.88rem;
border: none; cursor: pointer; transition: all 0.3s;
color: var(--text);
}
.wiz-btn svg { width: 16px; height: 16px; }
.wiz-btn-prev {
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
}
.wiz-btn-prev:hover {
background: rgba(255,255,255,0.1);
transform: translateX(-2px);
}
.wiz-btn-next {
background: linear-gradient(135deg, var(--accent), #7c3aed);
color: white;
box-shadow: 0 4px 20px var(--accent-glow);
}
.wiz-btn-next:hover {
transform: translateY(-2px);
box-shadow: 0 6px 28px rgba(99,102,241,0.5);
}
.wiz-btn:disabled {
opacity: 0.3; pointer-events: none;
}
.wiz-counter {
font-size: 0.75rem; color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
padding: 0 20px;
}
.wiz-nav {
display: flex; align-items: center; margin-top: 24px;
}
/* ═══ VALIDATION ERROR DOT ═══ */
.wiz-dot.error {
border-color: rgba(239,68,68,0.6);
color: #fca5a5;
background: rgba(239,68,68,0.12);
box-shadow: 0 0 12px rgba(239,68,68,0.2), inset 0 0 10px rgba(239,68,68,0.08);
animation: dotShake 0.4s ease;
}
@keyframes dotShake {
0%, 100% { transform: translateX(0); }
20% { transform: translateX(-3px); }
40% { transform: translateX(3px); }
60% { transform: translateX(-2px); }
80% { transform: translateX(2px); }
}
.field-error-hint {
padding: 8px 14px; border-radius: 8px; margin-top: 8px;
background: rgba(239,68,68,0.08); border: 1px solid rgba(239,68,68,0.2);
border-left: 3px solid var(--red);
color: #fca5a5; font-size: 0.78rem; font-weight: 500;
display: flex; align-items: center; gap: 8px;
animation: hintIn 0.3s ease-out;
}
@keyframes hintIn {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: translateY(0); }
}
.field-error-hint svg { width: 14px; height: 14px; flex-shrink: 0; color: #f87171; }
/* ═══ PASSWORD TOGGLE ═══ */
.pw-wrap { position: relative; }
.pw-wrap .fi { padding-right: 44px; }
.pw-eye {
position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
width: 30px; height: 30px; border-radius: 8px;
display: flex; align-items: center; justify-content: center;
background: transparent; border: none;
color: var(--text-muted); cursor: pointer;
transition: color 0.2s, background 0.2s;
}
.pw-eye:hover { color: var(--text-dim); background: rgba(255,255,255,0.05); }
.pw-eye svg { width: 16px; height: 16px; }
/* ═══ TOAST ═══ */
.toast {
position: fixed; bottom: 32px; left: 50%; transform: translateX(-50%) translateY(20px);
padding: 12px 24px; border-radius: 12px;
background: rgba(34,197,94,0.15); border: 1px solid rgba(34,197,94,0.3);
color: #4ade80; font-weight: 600; font-size: 0.88rem;
display: flex; align-items: center; gap: 8px;
box-shadow: 0 12px 40px rgba(0,0,0,0.4);
opacity: 0; pointer-events: none; z-index: 100;
transition: opacity 0.35s, transform 0.35s;
max-width: 90vw; text-align: center;
}
.toast.show {
opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto;
}
.toast svg { width: 18px; height: 18px; flex-shrink: 0; }
.toast.error {
background: rgba(239,68,68,0.15); border-color: rgba(239,68,68,0.3);
color: #fca5a5;
}
.toast.warning {
background: rgba(234,179,8,0.15); border-color: rgba(234,179,8,0.3);
color: #fbbf24;
}
/* ═══ MANIFEST GENERATOR ═══ */
.manifest-box {
text-align: center;
padding-top: 40px;
}
.manifest-box .btn-generate {
display: inline-flex; align-items: center; justify-content: center; gap: 10px;
padding: 16px 40px; border-radius: 14px;
font-family: 'Sora',sans-serif; font-weight: 700; font-size: 1rem;
border: none; cursor: pointer; color: white;
background: linear-gradient(135deg, var(--accent), #7c3aed);
box-shadow: 0 4px 24px var(--accent-glow), 0 0 0 1px rgba(99,102,241,0.3);
transition: all 0.35s; position: relative; overflow: hidden;
}
.manifest-box .btn-generate::before {
content: ''; position: absolute; inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.12), transparent);
opacity: 0; transition: opacity 0.3s;
}
.manifest-box .btn-generate:hover::before { opacity: 1; }
.manifest-box .btn-generate:hover {
transform: translateY(-3px);
box-shadow: 0 8px 36px rgba(99,102,241,0.5), 0 0 0 1px rgba(99,102,241,0.5);
}
.manifest-box .btn-generate:active { transform: translateY(-1px); }
.manifest-box .btn-generate svg { width: 20px; height: 20px; }
.manifest-box .btn-generate.loading { pointer-events: none; opacity: 0.8; }
.btn-spinner {
width: 20px; height: 20px; border-radius: 50%;
border: 2px solid rgba(255,255,255,0.2);
border-top-color: white;
animation: spin 0.6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.manifest-result {
max-height: 0; overflow: hidden; opacity: 0;
transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease, margin 0.4s;
margin-top: 0;
}
.manifest-result.show {
max-height: 300px; opacity: 1; margin-top: 20px;
}
.manifest-result-inner {
padding: 20px; border-radius: 14px;
background: rgba(34,197,94,0.04);
border: 1px solid rgba(34,197,94,0.15);
}
.manifest-result-check {
display: inline-flex; align-items: center; justify-content: center;
width: 36px; height: 36px; border-radius: 50%;
background: rgba(34,197,94,0.12); color: #4ade80;
margin-bottom: 10px;
animation: popIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes popIn {
from { transform: scale(0); } to { transform: scale(1); }
}
.manifest-result-check svg { width: 20px; height: 20px; }
.manifest-result-label {
font-size: 0.82rem; font-weight: 600; color: #4ade80; margin-bottom: 12px;
}
.manifest-url-wrap {
display: flex; align-items: stretch; gap: 0;
border-radius: 11px; overflow: hidden;
border: 1px solid var(--border);
background: rgba(0,0,0,0.3);
transition: border-color 0.3s;
}
.manifest-url-wrap:focus-within {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-glow);
}
.manifest-url-input {
flex: 1; padding: 12px 16px;
background: transparent; border: none; outline: none;
color: var(--text); font-family: 'JetBrains Mono',monospace;
font-size: 0.78rem; min-width: 0;
}
.manifest-url-copy {
padding: 0 16px; border: none;
background: rgba(99,102,241,0.1);
border-left: 1px solid var(--border);
color: var(--accent-light); cursor: pointer;
font-family: 'Outfit',sans-serif; font-weight: 600; font-size: 0.78rem;
display: flex; align-items: center; gap: 6px;
transition: background 0.2s;
white-space: nowrap;
}
.manifest-url-copy:hover { background: rgba(99,102,241,0.2); }
.manifest-url-copy svg { width: 14px; height: 14px; }
.btn-stremio {
display: inline-flex; align-items: center; justify-content: center; gap: 10px;
padding: 14px 32px; border-radius: 12px; margin-top: 14px;
font-family: 'Sora',sans-serif; font-weight: 600; font-size: 0.9rem;
border: 1px solid rgba(99,102,241,0.25);
background: rgba(99,102,241,0.08);
color: var(--accent-light); cursor: pointer;
transition: all 0.3s; text-decoration: none;
}
.btn-stremio:hover {
background: rgba(99,102,241,0.15); border-color: rgba(99,102,241,0.4);
transform: translateY(-2px);
box-shadow: 0 4px 20px rgba(99,102,241,0.15);
}
.btn-stremio svg { width: 18px; height: 18px; }
/* ═══ MOBILE RESPONSIVE ═══ */
@media (max-width: 640px) {
/* Layout */
.relative.z-10 { padding: 8px 6px 20px; }
.glass-form { border-radius: 18px; padding: 16px 14px !important; }
/* Logo */
.glass-form > .flex.flex-col img { width: 90px !important; height: 90px !important; }
.glass-form > .flex.flex-col h1 { font-size: 1.3rem !important; }
.glass-form > .flex.flex-col .discord-bar { font-size: 0.76rem; padding: 8px 12px; }
/* Wizard stepper */
.wiz-stepper-row { gap: 8px; }
.wiz-arrow { width: 32px; height: 32px; min-width: 32px; }
.wiz-arrow svg { width: 15px; height: 15px; }
.wiz-dot { width: 28px; height: 28px; }
.wiz-dot svg { width: 12px; height: 12px; }
.wiz-dot.active { transform: scale(1.08); }
.wiz-line { width: 8px; }
.wiz-dot::after { display: none; }
.wiz-title { font-size: 1rem; }
.wiz-subtitle { font-size: 0.72rem; }
/* Cards */
.card { padding: 16px 14px; border-radius: 14px; }
.card-header { gap: 10px; }
.card-icon { width: 34px; height: 34px; border-radius: 10px; }
.card-icon svg { width: 15px !important; height: 15px !important; }
.card-title { font-size: 0.92rem; }
.card-desc { margin-left: 0; font-size: 0.78rem; margin-bottom: 14px; }
/* Toggle rows */
.tog-row { padding: 10px 8px; gap: 10px; }
.tog { width: 42px; height: 24px; }
.tog-track::after { width: 18px; height: 18px; }
.tog input:checked + .tog-track::after { transform: translateX(18px); }
.tog-name { font-size: 0.85rem; }
.tog-name img { width: 20px; height: 20px; }
.tog-sub { font-size: 0.75rem; }
.api-key-indicator { width: 28px; height: 28px; border-radius: 8px; }
.api-key-indicator svg { width: 14px; height: 14px; }
/* Form inputs */
.fi { padding: 10px 12px; font-size: 0.84rem; border-radius: 10px; }
.fi-group label { font-size: 0.7rem; }
.fi-hint { font-size: 0.68rem; }
.cred-pair { flex-direction: column; }
div[style*="margin-left:54px"], div[style*="margin-left:60px"] {
margin-left: 0 !important;
}
/* Pill group (languages) */
.pill-group { gap: 6px; }
.pill { padding: 7px 14px; font-size: 0.8rem; }
.pill-hint { font-size: 0.62rem; }
/* Radio cards */
.rad-card { padding: 10px 12px; gap: 10px; }
.rad-dot { width: 18px; height: 18px; }
.rad-text { font-size: 0.82rem; }
#debridDownloaderOptions > div { padding: 10px 12px !important; gap: 10px !important; }
#debridDownloaderOptions > div input[type="radio"] { width: 18px !important; height: 18px !important; }
#debridDownloaderOptions > div label { font-size: 0.82rem !important; }
/* Debrid order list */
#debridOrderList li { font-size: 0.82rem !important; }
/* Slider controls */
.slider-grid { gap: 18px; }
.slider-val { min-width: 50px; }
.slider-val input { font-size: 0.82rem; }
.slider-range::-webkit-slider-thumb { width: 20px; height: 20px; }
/* Tag input (exclusion keywords) */
.tag-input-wrap { padding: 8px 10px; min-height: 42px; }
.tag-chip { font-size: 0.76rem; padding: 4px 6px 4px 10px; }
.tag-ghost-input { font-size: 0.82rem; min-width: 80px; }
.tag-hint { font-size: 0.66rem; }
/* Checkboxes */
.chk-row { padding: 7px 8px; gap: 9px; }
.chk-text { font-size: 0.82rem; }
/* Auth boxes */
.auth-box { padding: 10px 12px; font-size: 0.78rem; }
.btn-oauth { padding: 8px 16px; font-size: 0.78rem; }
/* Bottom nav */
.wiz-nav { margin-top: 16px; }
.wiz-btn { padding: 10px 20px; font-size: 0.82rem; border-radius: 10px; }
.wiz-btn svg { width: 14px; height: 14px; }
.wiz-counter { padding: 0 10px; font-size: 0.7rem; }
/* Manifest box */
.manifest-box { padding-top: 24px; }
.manifest-box .btn-generate { padding: 14px 28px; font-size: 0.88rem; }
.manifest-box .btn-generate svg { width: 18px; height: 18px; }
.manifest-url-wrap { flex-direction: column; }
.manifest-url-input { font-size: 0.72rem; padding: 10px 12px; }
.manifest-url-copy {
border-left: none; border-top: 1px solid var(--border);
padding: 10px 16px; justify-content: center;
}
.btn-stremio { padding: 12px 24px; font-size: 0.82rem; width: 100%; }
/* API key validation */
.api-key-wrap .fi { padding-right: 42px; }
.api-key-status { width: 24px; height: 24px; right: 10px; }
.api-key-msg { font-size: 0.72rem; }
/* Error hints */
.field-error-hint { padding: 6px 10px; font-size: 0.72rem; }
/* Info tooltip on mobile */
.info-tip-bubble { width: 240px; font-size: 0.72rem; padding: 10px 12px; }
.status-flair { font-size: 0.6rem; padding: 2px 8px; }
.priority-select-wrap { max-width: 100%; }
.prio-trigger { font-size: 0.78rem; padding: 9px 12px; }
.prio-option { font-size: 0.78rem; padding: 10px 12px; }
.prio-rank { font-size: 0.6rem !important; }
/* Toast */
.toast { bottom: 16px; padding: 10px 18px; font-size: 0.8rem; border-radius: 10px; }
/* Modal */
.rd-modal-box { width: 94%; max-width: 380px; border-radius: 16px; }
.rd-modal-body { padding: 24px 20px 22px; }
.rd-modal-icon { width: 48px; height: 48px; border-radius: 14px; }
.rd-modal-icon svg { width: 22px; height: 22px; }
.rd-modal-title { font-size: 1rem; }
.rd-modal-text { font-size: 0.82rem; }
.rd-modal-btn { padding: 10px 28px; font-size: 0.82rem; }
/* YGG locked tooltip */
.ygg-locked { padding: 12px 14px; gap: 10px; flex-direction: column; }
.ygg-tw .ygg-tip { width: 260px; padding: 14px 16px; }
/* Sep */
.sep { margin: 4px 0; }
}
@media (max-width: 380px) {
.glass-form { padding: 12px 10px !important; }
.wiz-dot { width: 24px; height: 24px; }
.wiz-dot svg { width: 10px; height: 10px; }
.wiz-line { width: 5px; }
.wiz-arrow { width: 28px; height: 28px; min-width: 28px; }
.card { padding: 12px 10px; }
.wiz-btn { padding: 8px 14px; font-size: 0.78rem; }
.manifest-box .btn-generate { padding: 12px 20px; font-size: 0.82rem; }
}
</style>
</head>
<body class="h-full">
<div class="bg-scene"></div>
<div class="bg-orbs"></div>
<div class="relative z-10 min-h-screen flex items-start justify-center px-4 py-10">
<form class="glass-form w-full max-w-2xl mx-auto p-7 md:p-10 space-y-7" style="animation:fadeUp 0.8s ease-out both;">
<!-- LOGO -->
<div class="flex flex-col items-center gap-5 anim" style="animation-delay:0.05s">
<img src="https://i.ibb.co/ZRZcVBLd/SF-modern.png" alt="Stream-Fusion" class="w-[130px] h-[130px]" style="filter:drop-shadow(0 0 30px rgba(99,102,241,0.25));">
<h1 style="font-family:'Sora',sans-serif;font-size:1.6rem;font-weight:700;background:linear-gradient(135deg,#e2e8f0,#818cf8,#06b6d4);-webkit-background-clip:text;-webkit-text-fill-color:transparent;">Stream-Fusion</h1>
<p style="font-size:0.82rem;font-weight:500;letter-spacing:0.15em;text-transform:uppercase;color:var(--text-muted);margin-top:-8px;">Optimisé pour le contenu francophone</p>
<div class="discord-bar">
<svg width="18" height="18" viewBox="0 0 24 24" fill="#7289da"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.373-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/></svg>
Support &amp; questions :
<a href="https://discord.gg/KN3vRqTHDa" target="_blank">Rejoindre le Discord</a>
</div>
</div>
<!-- WIZARD STEPPER WITH ARROWS -->
<div class="wiz-stepper-row">
<button type="button" class="wiz-arrow" id="wizArrowPrev" onclick="prevStep()" disabled>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
</button>
<div class="wizard-stepper" id="wizStepper">
<div class="wiz-step-item">
<div class="wiz-dot" data-step="0" onclick="goToStep(0)" title="Authentification"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg></div>
<div class="wiz-line" data-line="0"></div>
</div>
<div class="wiz-step-item">
<div class="wiz-dot" data-step="1" onclick="goToStep(1)" title="Débridage"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></svg></div>
<div class="wiz-line" data-line="1"></div>
</div>
<div class="wiz-step-item">
<div class="wiz-dot" data-step="2" onclick="goToStep(2)" title="Sources"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg></div>
<div class="wiz-line" data-line="2"></div>
</div>
<div class="wiz-step-item">
<div class="wiz-dot" data-step="3" onclick="goToStep(3)" title="Services & Contenu"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg></div>
<div class="wiz-line" data-line="3"></div>
</div>
<div class="wiz-step-item">
<div class="wiz-dot" data-step="4" onclick="goToStep(4)" title="Tri & Exclusions"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M7 12h10"/><path d="M10 18h4"/></svg></div>
<div class="wiz-line" data-line="4"></div>
</div>
<div class="wiz-step-item">
<div class="wiz-dot" data-step="5" onclick="goToStep(5)" title="Langues & Résultats"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg></div>
<div class="wiz-line" data-line="5"></div>
</div>
<div class="wiz-step-item">
<div class="wiz-dot" data-step="6" onclick="goToStep(6)" title="Installation"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg></div>
</div>
</div>
<button type="button" class="wiz-arrow" id="wizArrowNext" onclick="nextStep()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</button>
</div>
<div style="text-align:center;">
<div class="wiz-title" id="wizTitle">Authentification</div>
<div class="wiz-subtitle" id="wizSubtitle">Entrez votre clé d'accès pour commencer</div>
<div class="wiz-progress"><div class="wiz-progress-fill" id="wizProgress" style="width:14.28%"></div></div>
</div>
<div class="wizard-step active" data-wizard-step="0">
<div class="card anim" id="sec-api" style="animation-delay:0.1s">
<div class="card-header" onclick="toggleCard(this)">
<div class="card-icon" style="background:rgba(239,68,68,0.1);color:#f87171;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
</div>
<h2 class="card-title" style="color:#f87171;">Clé API StreamFusion</h2>
<svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
{% if allow_public_key_registration %}
<p class="card-desc">Obtenez une clé <a href="/register" target="_blank" style="color:var(--accent-light);font-weight:600;text-decoration:none;">ici</a>, puis entrez-la ci-dessous. Cette clé vous permettra d'accéder à cette instance de StreamFusion.</p>
{% else %}
<p class="card-desc">Entrez votre clé d'accès ci-dessous. Cette clé vous permettra d'accéder à cette instance de StreamFusion. Contactez l'administrateur pour en obtenir une.</p>
{% endif %}
<div style="margin-left:54px;">
<div class="fi-group">
<label for="ApiKey">Clé API</label>
<div class="api-key-wrap">
<input type="text" name="ApiKey" id="ApiKey" class="fi mono" placeholder="Entrez votre clé API…" oninput="validateKeyLive(this.value)">
<div class="api-key-status" id="apiKeyStatus">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</div>
</div>
<div class="api-key-msg" id="apiKeyMsg">
<svg id="apiKeyMsgIcon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>
<span id="apiKeyMsgText"></span>
</div>
</div>
<div id="apiKeyError" class="hidden"></div>
</div>
</div>
</div>
<div class="wizard-step" data-wizard-step="1">
<div class="card anim" id="sec-debrid" style="animation-delay:0.15s">
<div class="card-header" onclick="toggleCard(this)">
<div class="card-icon" style="background:rgba(249,115,22,0.1);color:var(--orange-light);">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></svg>
</div>
<h2 class="card-title">Service de Débridage</h2>
<svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<p class="card-desc">Choisissez et configurez votre service de débridage préféré.</p>
<div class="space-y-2">
<div class="tog-row">
<label class="tog"><input id="debrid_rd" name="debrid_rd" type="checkbox" data-unique-account="{{ rd_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1">
<div class="tog-name"><img src="https://i.ibb.co/LjWQpKn/real-debrid.png" alt="">Utiliser Real-Debrid</div>
<div id="rd_token_info_div" class="mt-3 space-y-3" style="display:none;">
<p style="font-size:0.8rem;color:var(--text-muted);">Real-Debrid nécessite une authentification OAuth.</p>
<button type="button" id="rd-auth-button" onclick="startRealDebridAuth()" class="btn-oauth btn-oauth-indigo">S'authentifier avec Real-Debrid</button>
<div id="auth-instructions" style="display:none;" class="auth-box">
<p>Veuillez visiter <a id="verification-url" href="#" target="_blank">l'URL de vérification</a> et entrer le code : <strong id="user-code"></strong></p>
</div>
<input type="hidden" id="rd_token_info" name="rd_token_info">
<div class="sep" style="margin:12px 0;"></div>
<div class="slider-control">
<label>Seuil avant skip</label>
<div class="slider-row">
<div class="slider-track-wrap">
<div class="slider-fill" id="fill_rdMinCachedBeforeCheck"></div>
<input type="range" class="slider-range" id="range_rdMinCachedBeforeCheck" min="0" max="10" step="1" value="3">
</div>
<div class="slider-val"><input type="number" name="rdMinCachedBeforeCheck" id="rdMinCachedBeforeCheck" min="0" max="10" value="3"></div>
</div>
<p class="fi-hint">Sauter RD si déjà N résultats cachés par d'autres services. Recommandé : 13. (0 = toujours vérifier)</p>
</div>
</div>
</div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="debrid_ad" name="debrid_ad" type="checkbox" data-unique-account="{{ ad_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1">
<div class="tog-name"><img src="https://i.ibb.co/1tJSWRGt/alldebrid.png" alt="">Utiliser AllDebrid</div>
<div id="ad_token_info_div" class="mt-3 space-y-3" style="display:none;">
<p style="font-size:0.8rem;color:var(--text-muted);">AllDebrid nécessite une authentification OAuth.</p>
<button type="button" id="ad-auth-button" onclick="startADAuth()" class="btn-oauth btn-oauth-orange">S'authentifier avec AllDebrid</button>
<div id="ad-auth-instructions" style="display:none;" class="auth-box">
<p>Veuillez visiter <a id="ad-verification-url" href="#" target="_blank">l'URL de vérification</a> et entrer le code : <strong id="ad-user-code"></strong></p>
</div>
<input type="hidden" id="ad_token_info" name="ad_token_info">
</div>
</div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="debrid_pm" name="debrid_pm" type="checkbox" data-unique-account="{{ pm_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1">
<div class="tog-name"><img src="https://i.ibb.co/h1YpXBn7/premiumize.png" alt="">Utiliser Premiumize</div>
<div id="pm_token_info_div" class="mt-3" style="display:none;">
<div class="fi-group">
<label for="pm_token_info">Clé API Premiumize</label>
<input type="text" name="pm_token_info" id="pm_token_info" placeholder="Votre clé API Premiumize" class="fi mono">
<p class="fi-hint">Trouvez votre clé sur <a href="https://www.premiumize.me/account" target="_blank">premiumize.me/account</a></p>
</div>
</div>
</div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="debrid_tb" name="debrid_tb" type="checkbox" data-unique-account="{{ tb_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1">
<div class="tog-name"><img src="https://i.ibb.co/LhntJ4Lf/torbox.jpg" alt="">Utiliser TorBox</div>
<div id="tb_token_info_div" class="mt-3" style="display:none;">
<div class="fi-group">
<label for="tb_token_info">Clé API TorBox</label>
<input type="text" name="tb_token_info" id="tb_token_info" placeholder="Votre clé API TorBox" class="fi mono">
<p class="fi-hint">Trouvez votre clé sur <a href="https://torbox.app/settings" target="_blank">torbox.app/settings</a></p>
</div>
</div>
<div id="tb_debrid-fields" style="display:none;margin-top:12px;">
<div class="sep" style="margin:10px 0;"></div>
<div class="sec-label" style="margin-bottom:8px;">Options TorBox</div>
<div class="space-y-2">
<div class="tog-row" style="padding:8px 0;">
<label class="tog"><input id="tb_usenet" name="tb_usenet" type="checkbox"><span class="tog-track"></span></label>
<div><div class="tog-name">Utiliser Usenets</div><div class="tog-sub">Activer la recherche et le téléchargement via Usenet.</div></div>
</div>
<div class="tog-row" style="padding:8px 0;">
<label class="tog"><input id="tb_search" name="tb_search" type="checkbox"><span class="tog-track"></span></label>
<div><div class="tog-name">Moteur de recherche TorBox</div><div class="tog-sub">Activer la recherche publique de torrents.</div></div>
</div>
</div>
</div>
</div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="debrid_dl" name="debrid_dl" type="checkbox" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div class="tog-name"><img src="https://i.ibb.co/tMqpndZh/debrid-link.png" alt="">Utiliser Debrid-Link</div>
</div>
<div id="debridlink_api_key_div" class="hidden" style="margin-left:60px;">
<div class="fi-group"><label for="debridlink_api_key">Clé API Debrid-Link</label><input type="text" name="debridlink_api_key" id="debridlink_api_key" class="fi mono" placeholder="Entrez votre clé API"><p class="fi-hint">Générez votre clé sur <a href="https://debrid-link.com/webapp/apikey" target="_blank">debrid-link.com/webapp/apikey</a></p></div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="debrid_ed" name="debrid_ed" type="checkbox" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div class="tog-name"><img src="https://i.ibb.co/pjnd7Wsr/easydebrid.png" alt="">Utiliser EasyDebrid</div>
</div>
<div id="easydebrid_api_key_div" class="hidden" style="margin-left:60px;">
<div class="fi-group"><label for="easydebrid_api_key">Clé API EasyDebrid</label><input type="text" name="easydebrid_api_key" id="easydebrid_api_key" class="fi mono" placeholder="Entrez votre clé API"><p class="fi-hint">Trouvez votre clé sur <a href="https://easydebrid.com/settings" target="_blank">easydebrid.com/settings</a></p></div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="debrid_oc" name="debrid_oc" type="checkbox" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div class="tog-name"><img src="https://i.ibb.co/MkRRDKPB/offcloud.png" alt="">Utiliser Offcloud</div>
</div>
<div id="offcloud_credentials_div" class="hidden" style="margin-left:60px;">
<input type="hidden" name="offcloud_credentials" id="offcloud_credentials">
<div class="cred-pair-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
Identifiants Offcloud
</div>
<div class="cred-pair">
<div class="fi-group email-field">
<label for="offcloud_email">Adresse e-mail</label>
<input type="email" id="offcloud_email" class="fi" placeholder="email@exemple.com" oninput="syncCred('offcloud')">
</div>
<div class="fi-group">
<label for="offcloud_pass">Mot de passe</label>
<div class="pw-wrap">
<input type="password" id="offcloud_pass" class="fi" placeholder="••••••••" oninput="syncCred('offcloud')">
<button type="button" class="pw-eye" onclick="togglePw(this)" aria-label="Afficher le mot de passe">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
</button>
</div>
</div>
</div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="debrid_pk" name="debrid_pk" type="checkbox" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div class="tog-name"><img src="https://i.ibb.co/m1vSbgt/pikpak.png" alt="">Utiliser PikPak</div>
</div>
<div id="pikpak_credentials_div" class="hidden" style="margin-left:60px;">
<input type="hidden" name="pikpak_credentials" id="pikpak_credentials">
<div class="cred-pair-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
Identifiants PikPak
</div>
<div class="cred-pair">
<div class="fi-group email-field">
<label for="pikpak_email">Adresse e-mail</label>
<input type="email" id="pikpak_email" class="fi" placeholder="email@exemple.com" oninput="syncCred('pikpak')">
</div>
<div class="fi-group">
<label for="pikpak_pass">Mot de passe</label>
<div class="pw-wrap">
<input type="password" id="pikpak_pass" class="fi" placeholder="••••••••" oninput="syncCred('pikpak')">
<button type="button" class="pw-eye" onclick="togglePw(this)" aria-label="Afficher le mot de passe">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card anim" id="sec-stremthru" style="animation-delay:0.35s">
<div class="card-header" onclick="toggleCard(this)">
<div class="card-icon" style="background:rgba(6,182,212,0.1);color:#22d3ee;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h2 class="card-title">StremThru (Proxy)</h2>
<svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<p class="card-desc">Activez StremThru pour proxifier vos requêtes de débridage via un serveur intermédiaire.</p>
<div class="tog-row">
<label class="tog"><input id="stremthru_enabled" name="stremthru_enabled" type="checkbox" checked onchange="toggleStremThruFields(); if(typeof updateProviderFields==='function') updateProviderFields();"><span class="tog-track"></span></label>
<div style="flex:1">
<div class="tog-name">Activer StremThru</div>
<div class="tog-sub">Route vos requêtes via un proxy StremThru pour un accès plus fiable.</div>
</div>
</div>
<div id="stremthru_url_div" style="padding:0 14px;margin-top:14px;display:none;">
<div class="fi-group">
<label for="stremthru_url">URL du serveur StremThru</label>
<input type="text" name="stremthru_url" id="stremthru_url" class="fi mono" placeholder="https://stremthru.13377001.xyz/">
<p class="fi-hint">L'adresse de votre instance StremThru.</p>
</div>
</div>
<div id="stremthru_auth_div" style="padding:0 14px;margin-top:10px;display:none;">
<div class="fi-group">
<label for="stremthru_store_auth">Clé d'authentification (optionnel)</label>
<input type="text" name="stremthru_store_auth" id="stremthru_store_auth" class="fi mono" placeholder="Clé d'auth globale">
<p class="fi-hint">Laissez vide si votre instance ne requiert pas d'authentification.</p>
</div>
</div>
</div>
</div>
<!-- ÉTAPE 2: SOURCES -->
<div class="wizard-step" data-wizard-step="2">
<!-- FOURNISSEURS DE TORRENTS -->
<div class="card anim" id="sec-torrent" style="animation-delay:0.2s">
<div class="card-header" onclick="toggleCard(this)">
<div class="card-icon" style="background:rgba(99,102,241,0.1);color:var(--accent-light);">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
</div>
<h2 class="card-title">Fournisseurs de Torrents</h2>
<svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<p class="card-desc">Configurez les sources de recherche de torrents.</p>
<div class="space-y-2">
<div style="display:none;">
<input id="cache" name="cache" type="checkbox" checked onchange="updateProviderFields()">
</div>
<div class="ygg-locked">
<label class="tog" style="margin-top:2px;">
<input id="yggflix" name="yggflix" type="checkbox" checked disabled onchange="updateProviderFields()">
<span class="tog-track"></span>
</label>
<div style="flex:1;">
<div class="tog-name" style="gap:10px;flex-wrap:wrap;">
<img src="https://i.ibb.co/xqLv40hB/ygglogobig.png" alt="YGG" style="width:36px;height:18px;object-fit:contain;">
YGG Relay
<div class="ygg-tw">
<span class="ygg-badge">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
Source par défaut
</span>
<div class="ygg-tip">
<h4>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
Le roi est mort
</h4>
<p>Depuis la fermeture définitive de <strong>Yggtorrent </strong> suite à son piratage, l'entièreté de son catalogue est disponible au grand public.<br><br>Utilise désormais <strong>YGG.GRATIS</strong> comme source par défaut.</p>
</div>
</div>
</div>
<div class="tog-sub" style="margin-top:6px;">Relais public YGG Torznab — source principale de recherche francophone.</div>
</div>
</div>
<div class="tog-row" style="margin-top:8px;padding-left:54px;">
<label class="tog"><input id="yggflixPriority" name="yggflixPriority" type="checkbox" checked><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="gap:10px;">
Recherche prioritaire
<span class="status-flair active info-tip-wrap" id="yggPriorityFlair"><span class="status-dot"></span><span class="flair-label">Actif</span><div class="info-tip-bubble"><strong>Recherche prioritaire activée</strong><br>YGG Relay est interrogé en <strong>Phase 1</strong>, en même temps que les indexeurs prioritaires.</div></span>
</div>
</div>
</div>
<div class="sep"></div>
<!-- ZILEAN (hidden from UI, enabled by default) -->
<div style="display:none;">
<input id="zilean" name="zilean" type="checkbox" checked>
</div>
{% if jackett_enable %}
<!-- JACKETT -->
<div class="tog-row">
<label class="tog"><input id="jackett" name="jackett" type="checkbox"><span class="tog-track"></span></label>
<div>
<div class="tog-name">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
Jackett
</div>
<div class="tog-sub">Indexeur multi-sources — agrège les résultats de nombreux trackers.</div>
</div>
</div>
<div class="sep"></div>
{% endif %}
<!-- C411 -->
<div class="tog-row">
<label class="tog"><input id="c411" name="c411" type="checkbox" checked data-unique-account="{{ c411_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="flex-wrap:wrap;">
<img src="https://i.ibb.co/W4DygFGm/c411.png" alt="" style="width:34px;height:18px;">
Utiliser C411 API
</div>
<div class="tog-sub">Utilisez l'API C411 Torznab pour trouver plus de résultats.</div>
<div id="c411-category-row" class="indexer-category-row" style="display:none;">
<div class="priority-select-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>Phase de recherche</div>
<div class="priority-select-wrap" data-level="priority">
<select id="c411Category" class="fi" onchange="updatePriorityLevel(this)">
<option value="priority_private" selected>&#9650; Prioritaire — toujours interrogé</option>
<option value="intermediary_private">&#9644; Intermédiaire — si résultats insuffisants</option>
<option value="fallback_private">&#9660; Fallback — dernier recours</option>
</select>
</div>
</div>
</div>
<div class="api-key-indicator">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="api-key-tooltip">Cette option nécessite une clé API.</span>
</div>
</div>
{% if not c411_unique_account %}
<div id="c411-fields" style="display:none;">
<div style="margin-left:60px;" class="fi-group"><label for="c411ApiKey">Clé API C411</label><input type="text" name="c411ApiKey" id="c411ApiKey" class="fi mono" placeholder="Entrez votre clé API..."><p class="fi-hint"><a href="https://c411.org/user/integrations" target="_blank">Obtenez une clé ici</a></p></div>
<div style="margin-left:60px;" class="fi-group"><label for="c411Passkey">Passkey C411</label><input type="text" name="c411Passkey" id="c411Passkey" class="fi mono" placeholder="Passkey pour l'URL d'annonce du tracker (optionnel)"></div>
</div>
{% endif %}
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="torr9" name="torr9" type="checkbox" checked data-unique-account="{{ torr9_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="flex-wrap:wrap;">
<img src="https://i.ibb.co/7Nxg9xz7/torr9logo.png" alt="" style="width:26px;height:26px;">
Utiliser Torr9 API
</div>
<div class="tog-sub">Utilisez l'API Torr9 Torznab pour trouver plus de résultats.</div>
<div id="torr9-category-row" class="indexer-category-row" style="display:none;">
<div class="priority-select-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>Phase de recherche</div>
<div class="priority-select-wrap" data-level="priority">
<select id="torr9Category" class="fi" onchange="updatePriorityLevel(this)">
<option value="priority_private" selected>&#9650; Prioritaire — toujours interrogé</option>
<option value="intermediary_private">&#9644; Intermédiaire — si résultats insuffisants</option>
<option value="fallback_private">&#9660; Fallback — dernier recours</option>
</select>
</div>
</div>
</div>
<div class="api-key-indicator">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="api-key-tooltip">Cette option nécessite une clé API.</span>
</div>
</div>
{% if not torr9_unique_account %}
<div id="torr9-fields" style="display:none;">
<div style="margin-left:60px;" class="fi-group"><label for="torr9ApiKey">Clé API Torr9</label><input type="text" name="torr9ApiKey" id="torr9ApiKey" class="fi mono" placeholder="Entrez votre clé API..."><p class="fi-hint"><a href="https://torr9.net/profile" target="_blank">Obtenez une clé ici</a></p></div>
</div>
{% endif %}
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="lacale" name="lacale" type="checkbox" data-unique-account="{{ lacale_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="flex-wrap:wrap;">
<img src="https://i.ibb.co/ksw8TZw6/lacale.png" alt="" style="width:30px;height:30px;">
Utiliser La-Cale API
</div>
<div class="tog-sub">Utilisez l'API LaCale Torznab pour trouver plus de résultats.</div>
<div id="lacale-category-row" class="indexer-category-row" style="display:none;">
<div class="priority-select-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>Phase de recherche</div>
<div class="priority-select-wrap" data-level="intermediary">
<select id="lacaleCategory" class="fi" onchange="updatePriorityLevel(this)">
<option value="priority_private">&#9650; Prioritaire — toujours interrogé</option>
<option value="intermediary_private" selected>&#9644; Intermédiaire — si résultats insuffisants</option>
<option value="fallback_private">&#9660; Fallback — dernier recours</option>
</select>
</div>
</div>
</div>
<div class="api-key-indicator">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="api-key-tooltip">Cette option nécessite une clé API.</span>
</div>
</div>
{% if not lacale_unique_account %}
<div id="lacale-fields" style="display:none;">
<div style="margin-left:60px;" class="fi-group"><label for="lacaleApiKey">Clé API La-Cale</label><input type="text" name="lacaleApiKey" id="lacaleApiKey" class="fi mono" placeholder="Entrez votre clé API..."><p class="fi-hint"><a href="https://la-cale.space/" target="_blank">Obtenez une clé ici</a></p></div>
</div>
{% endif %}
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="generationfree" name="generationfree" type="checkbox" data-unique-account="{{ generationfree_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="flex-wrap:wrap;">
<img src="https://i.ibb.co/7tTSCgPc/generationfree.png" alt="" style="width:30px;height:30px;">
Utiliser Generation Free API
</div>
<div class="tog-sub">Utilisez l'API Generation Free UNIT3D pour trouver plus de résultats.</div>
<div id="generationfree-category-row" class="indexer-category-row" style="display:none;">
<div class="priority-select-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>Phase de recherche</div>
<div class="priority-select-wrap" data-level="intermediary">
<select id="generationfreeCategory" class="fi" onchange="updatePriorityLevel(this)">
<option value="priority_private">&#9650; Prioritaire — toujours interrogé</option>
<option value="intermediary_private" selected>&#9644; Intermédiaire — si résultats insuffisants</option>
<option value="fallback_private">&#9660; Fallback — dernier recours</option>
</select>
</div>
</div>
</div>
<div class="api-key-indicator">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="api-key-tooltip">Cette option nécessite une clé API.</span>
</div>
</div>
{% if not generationfree_unique_account %}
<div id="generationfree-fields" style="display:none;">
<div style="margin-left:60px;" class="fi-group"><label for="generationfreeApiKey">Clé API Generation Free</label><input type="text" name="generationfreeApiKey" id="generationfreeApiKey" class="fi mono" placeholder="Entrez votre clé API..."><p class="fi-hint"><a href="https://generation-free.org/login" target="_blank">Obtenez une clé ici</a></p></div>
<div style="margin-left:60px;" class="fi-group"><label for="generationfreePasskey">Passkey Generation Free</label><input type="text" name="generationfreePasskey" id="generationfreePasskey" class="fi mono" placeholder="Passkey pour l'URL d'annonce du tracker (optionnel)"></div>
</div>
{% endif %}
<div class="sep"></div>
{% if abn_enable %}
<!-- ABN -->
<div class="tog-row">
<label class="tog"><input id="abn" name="abn" type="checkbox" data-unique-account="{{ abn_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="flex-wrap:wrap;">
<img src="https://i.ibb.co/Cs6yNPBW/abn.png" alt="" style="width:26px;height:26px;">
Utiliser ABN API
</div>
<div class="tog-sub">Utilisez l'API ABN (Abnormal) pour trouver plus de résultats.</div>
<div id="abn-category-row" class="indexer-category-row" style="display:none;">
<div class="priority-select-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>Phase de recherche</div>
<div class="priority-select-wrap" data-level="fallback">
<select id="abnCategory" class="fi" onchange="updatePriorityLevel(this)">
<option value="priority_private">&#9650; Prioritaire — toujours interrogé</option>
<option value="intermediary_private">&#9644; Intermédiaire — si résultats insuffisants</option>
<option value="fallback_private" selected>&#9660; Fallback — dernier recours</option>
</select>
</div>
</div>
</div>
<div class="api-key-indicator">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="api-key-tooltip">Cette option nécessite une clé API.</span>
</div>
</div>
{% if not abn_unique_account %}
<div id="abn-fields" style="display:none;">
<div style="margin-left:60px;" class="fi-group"><label for="abnApiKey">Clé API ABN</label><input type="text" name="abnApiKey" id="abnApiKey" class="fi mono" placeholder="Entrez votre clé API..."><p class="fi-hint"><a href="https://abn.lol" target="_blank">Obtenez une clé ici</a></p></div>
<div style="margin-left:60px;" class="fi-group"><label for="abnPasskey">Passkey ABN</label><input type="text" name="abnPasskey" id="abnPasskey" class="fi mono" placeholder="Passkey pour l'URL d'annonce du tracker (optionnel)"></div>
</div>
{% endif %}
<div class="sep"></div>
{% endif %}
{% if g3mini_enable %}
<!-- G3MINI -->
<div class="tog-row">
<label class="tog"><input id="g3mini" name="g3mini" type="checkbox" data-unique-account="{{ g3mini_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="flex-wrap:wrap;">
<img src="https://i.ibb.co/CLKWKbG/g3mini.png" alt="" style="width:26px;height:26px;">
Utiliser G3MINI API
</div>
<div class="tog-sub">Utilisez l'API Gemini Tracker (UNIT3D) pour trouver plus de résultats.</div>
<div id="g3mini-category-row" class="indexer-category-row" style="display:none;">
<div class="priority-select-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>Phase de recherche</div>
<div class="priority-select-wrap" data-level="intermediary">
<select id="g3miniCategory" class="fi" onchange="updatePriorityLevel(this)">
<option value="priority_private">&#9650; Prioritaire — toujours interrogé</option>
<option value="intermediary_private" selected>&#9644; Intermédiaire — si résultats insuffisants</option>
<option value="fallback_private">&#9660; Fallback — dernier recours</option>
</select>
</div>
</div>
</div>
<div class="api-key-indicator">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="api-key-tooltip">Cette option nécessite une clé API.</span>
</div>
</div>
{% if not g3mini_unique_account %}
<div id="g3mini-fields" style="display:none;">
<div style="margin-left:60px;" class="fi-group"><label for="g3miniApiKey">Clé API G3MINI</label><input type="text" name="g3miniApiKey" id="g3miniApiKey" class="fi mono" placeholder="Entrez votre clé API..."><p class="fi-hint"><a href="https://gemini-tracker.org" target="_blank">Obtenez une clé ici</a></p></div>
<div style="margin-left:60px;" class="fi-group"><label for="g3miniPasskey">Passkey G3MINI</label><input type="text" name="g3miniPasskey" id="g3miniPasskey" class="fi mono" placeholder="Passkey pour l'URL d'annonce du tracker (optionnel)"></div>
</div>
{% endif %}
<div class="sep"></div>
{% endif %}
{% if theoldschool_enable %}
<!-- THEOLDSCHOOL -->
<div class="tog-row">
<label class="tog"><input id="theoldschool" name="theoldschool" type="checkbox" data-unique-account="{{ theoldschool_unique_account|lower }}" onchange="updateProviderFields()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name" style="flex-wrap:wrap;">
<img src="https://i.ibb.co/s9H1BfNh/tos.png" alt="" style="width:26px;height:26px;">
Utiliser TheOldSchool API
</div>
<div class="tog-sub">Utilisez l'API TheOldSchool (UNIT3D) pour trouver plus de résultats.</div>
<div id="theoldschool-category-row" class="indexer-category-row" style="display:none;">
<div class="priority-select-label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>Phase de recherche</div>
<div class="priority-select-wrap" data-level="intermediary">
<select id="theoldschoolCategory" class="fi" onchange="updatePriorityLevel(this)">
<option value="priority_private">&#9650; Prioritaire — toujours interrogé</option>
<option value="intermediary_private" selected>&#9644; Intermédiaire — si résultats insuffisants</option>
<option value="fallback_private">&#9660; Fallback — dernier recours</option>
</select>
</div>
</div>
</div>
<div class="api-key-indicator">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="api-key-tooltip">Cette option nécessite une clé API.</span>
</div>
</div>
{% if not theoldschool_unique_account %}
<div id="theoldschool-fields" style="display:none;">
<div style="margin-left:60px;" class="fi-group"><label for="theoldschoolApiKey">Clé API TheOldSchool</label><input type="text" name="theoldschoolApiKey" id="theoldschoolApiKey" class="fi mono" placeholder="Entrez votre clé API..."><p class="fi-hint"><a href="https://theoldschool.cc" target="_blank">Obtenez une clé ici</a></p></div>
<div style="margin-left:60px;" class="fi-group"><label for="theoldschoolPasskey">Passkey TheOldSchool</label><input type="text" name="theoldschoolPasskey" id="theoldschoolPasskey" class="fi mono" placeholder="Passkey pour l'URL d'annonce du tracker (optionnel)"></div>
</div>
{% endif %}
{% endif %}
</div>
</div>
</div>
<!-- ÉTAPE 3: SERVICES & CONTENU -->
<div class="wizard-step" data-wizard-step="3">
<div class="card anim" id="sec-config" style="animation-delay:0.25s">
<div class="card-header" onclick="toggleCard(this)">
<div class="card-icon" style="background:rgba(168,85,247,0.1);color:#c084fc;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>
</div>
<h2 class="card-title">Configuration personnalisée</h2>
<svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<p class="card-desc">Personnalisez l'ordre et le téléchargeur de vos services.</p>
<div class="space-y-4">
<div class="tog-row">
<label class="tog"><input id="debrid_order" name="debrid_order" type="checkbox" onchange="toggleDebridOrderList()"><span class="tog-track"></span></label>
<div style="flex:1;">
<div class="tog-name">Personnaliser l'ordre des services</div>
<div class="tog-sub">Le cache de chaque service sera vérifié dans cet ordre.</div>
<ul id="debridOrderList" class="mt-3 space-y-2 hidden"></ul>
</div>
</div>
<div class="sep"></div>
<div style="padding:12px 14px;">
<div class="tog-name" style="margin-bottom:4px;">Téléchargement</div>
<div class="tog-sub" style="margin-bottom:12px;">Sélectionnez le service à utiliser pour télécharger les torrents.</div>
<div id="debridDownloaderOptions" class="rad-group"></div>
</div>
</div>
</div>
<!-- CONFIGS CONDITIONNELLES -->
{% if not rd_unique_account %}
<div id="rd_debrid-fields" style="display:none;">
<div class="card">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(59,130,246,0.1);color:#60a5fa;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg></div><h2 class="card-title">Configuration Real-Debrid</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<div style="margin-left:54px;margin-top:12px;display:flex;flex-wrap:wrap;gap:16px;">
<button type="button" id="rd-auth-button" onclick="startRealDebridAuth()" class="btn-oauth btn-oauth-indigo">S'authentifier avec Real-Debrid</button>
<div id="auth-instructions" class="auth-box" style="display:none;flex:1;min-width:200px;">Veuillez vous rendre sur <a id="verification-url" href="#" target="_blank">le lien</a> — Code : <span id="user-code" style="font-weight:700;color:var(--text);"></span></div>
<div id="auth-status" style="display:none;font-size:0.85rem;color:#4ade80;">✓ Authentification réussie !</div>
<textarea id="rd_token_info" rows="3" class="fi mono" style="width:100%;" readonly></textarea>
</div>
</div>
</div>
{% endif %}
{% if not ad_unique_account %}
<div id="ad_debrid-fields" style="display:none;">
<div class="card">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(249,115,22,0.1);color:var(--orange-light);"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg></div><h2 class="card-title">Configuration AllDebrid</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<div style="margin-left:54px;margin-top:12px;display:flex;flex-wrap:wrap;gap:16px;">
<button type="button" id="ad-auth-button" onclick="startADAuth()" class="btn-oauth btn-oauth-orange">S'authentifier avec AllDebrid</button>
<div id="ad-auth-instructions" class="auth-box" style="display:none;flex:1;min-width:200px;">Code PIN : <span id="ad-user-code" style="font-weight:700;color:var(--text);"></span><br>Visitez <a id="ad-verification-url" href="#" target="_blank">le lien</a></div>
<div id="ad-auth-status" style="display:none;font-size:0.85rem;color:#4ade80;">✓ Authentification réussie !</div>
<textarea id="ad_token_info" rows="2" class="fi mono" style="width:100%;" readonly></textarea>
</div>
</div>
</div>
{% endif %}
{% if not pm_unique_account %}
<div id="pm_debrid-fields" style="display:none;">
<div class="card">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(34,197,94,0.1);color:#4ade80;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78Zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg></div><h2 class="card-title">Configuration Premiumize</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<div style="margin-left:54px;margin-top:12px;">
<div class="fi-group"><label for="pm_token_info">Jeton Premiumize</label><input type="text" name="pm_token_info" id="pm_token_info" class="fi mono"></div>
</div>
</div>
</div>
{% endif %}
<!-- CATALOGUES -->
<div class="card anim" id="sec-cat" style="animation-delay:0.28s">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(234,179,8,0.1);color:#facc15;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/></svg></div><h2 class="card-title">Catalogues</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<p class="card-desc">Activez les catalogues pour découvrir du contenu directement dans Stremio.</p>
<div class="space-y-2" style="padding:0 8px;">
<div class="tog-row">
<label class="tog"><input id="ctg_yggflix" name="ctg_yggflix" type="checkbox"><span class="tog-track"></span></label>
<div>
<div class="tog-name">Catalogue Yggflix</div>
<div class="tog-sub">Activez le catalogue Yggflix pour découvrir du contenu.</div>
</div>
</div>
<div class="sep"></div>
<div class="tog-row">
<label class="tog"><input id="ctg_yggtorrent" name="ctg_yggtorrent" type="checkbox"><span class="tog-track"></span></label>
<div>
<div class="tog-name">Catalogue Yggtorrent</div>
<div class="tog-sub">Activez le catalogue Yggtorrent pour découvrir du contenu.</div>
</div>
</div>
</div>
</div>
<div style="display:none;">
<div id="cache-fields"><input type="text" name="cacheUrl" id="cacheUrl" value="https://stremio-jackett-cacher.elfhosted.com/"></div>
</div>
<div class="card anim" id="sec-meta" style="animation-delay:0.3s">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(14,165,233,0.1);color:#38bdf8;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg></div><h2 class="card-title">Fournisseur de métadonnées</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<p class="card-desc">Choisissez la source des informations sur les films et séries.</p>
<div class="rad-group" style="padding:0 14px;">
<label class="rad-card"><input id="tmdb" name="metadata_provider" type="radio" value="tmdb" checked><div class="rad-dot"><div></div></div><div><div class="rad-text">TMDB</div><div class="tog-sub" style="margin-top:2px;">Métadonnées précises dans différentes langues.</div></div></label>
<label class="rad-card"><input id="cinemeta" name="metadata_provider" type="radio" value="cinemeta"><div class="rad-dot"><div></div></div><div><div class="rad-text">Cinemeta</div><div class="tog-sub" style="margin-top:2px;">Métadonnées simples et rapides.</div></div></label>
</div>
</div>
</div>
<!-- ÉTAPE 4: TRI & FILTRES -->
<div class="wizard-step" data-wizard-step="4">
<!-- TRI -->
<div class="card anim" id="sec-tri" style="animation-delay:0.35s">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(236,72,153,0.1);color:#f472b6;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg></div><h2 class="card-title">Options de tri</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<p class="card-desc">Choisissez l'ordre de classement des résultats.</p>
<div class="rad-group" style="padding:0 14px;">
<label class="rad-card"><input id="quality" name="sorting" type="radio" checked><div class="rad-dot"><div></div></div><span class="rad-text">Meilleure qualité en priorité</span></label>
<label class="rad-card"><input id="sizedesc" name="sorting" type="radio"><div class="rad-dot"><div></div></div><span class="rad-text">Taille décroissante</span></label>
<label class="rad-card"><input id="sizeasc" name="sorting" type="radio"><div class="rad-dot"><div></div></div><span class="rad-text">Taille croissante</span></label>
<label class="rad-card"><input id="qualitythensize" name="sorting" type="radio"><div class="rad-dot"><div></div></div><span class="rad-text">Qualité puis taille décroissante</span></label>
</div>
</div>
<!-- EXCLUSIONS -->
<div class="card anim" id="sec-exclus" style="animation-delay:0.4s">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(239,68,68,0.1);color:#f87171;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m4.93 4.93 14.14 14.14"/></svg></div><h2 class="card-title">Exclusions</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<p class="card-desc">Filtrez les qualités, résolutions et mots-clés indésirables.</p>
<div class="space-y-6" style="padding:0 8px;">
<div>
<div class="sec-label">Qualité</div>
<div class="space-y-1">
<label class="chk-row"><input id="cam" name="cam" type="checkbox" checked><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure CAM</span></label>
<label class="chk-row"><input id="hevc" name="hevc" type="checkbox"><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure HEVC (x265, H265)</span></label>
<label class="chk-row"><input id="rips" name="rips" type="checkbox"><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure RIP (HDRip, WEBRip, etc.)</span></label>
</div>
</div>
<div class="sep"></div>
<div>
<div class="sec-label">Résolution</div>
<div class="space-y-1">
<label class="chk-row"><input id="2160p" name="2160p" type="checkbox"><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure 2160p</span></label>
<label class="chk-row"><input id="1080p" name="1080p" type="checkbox"><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure 1080p</span></label>
<label class="chk-row"><input id="720p" name="720p" type="checkbox"><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure 720p</span></label>
<label class="chk-row"><input id="480p" name="480p" type="checkbox" checked><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure 480p</span></label>
<label class="chk-row"><input id="unknown" name="unknown" type="checkbox" checked><div class="chk-box"><svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></div><span class="chk-text">Exclure résolution inconnue</span></label>
</div>
</div>
<div class="sep"></div>
<div>
<div class="sec-label">Mots-clés à exclure</div>
<div class="tog-sub" style="margin-bottom:10px;">Tapez un mot-clé puis appuyez sur virgule ou Entrée pour l'ajouter.</div>
<input type="hidden" name="exclusion-keywords" id="exclusion-keywords">
<div class="tag-input-wrap" id="tagWrap" onclick="document.getElementById('tagInput').focus()">
<input type="text" class="tag-ghost-input" id="tagInput" placeholder="Ajouter un mot-clé…" autocomplete="off">
</div>
<div class="tag-hint">
<kbd>,</kbd> ou <kbd>Entrée</kbd> pour ajouter — <kbd>Retour</kbd> pour supprimer le dernier
</div>
</div>
</div>
</div>
</div>
<!-- ÉTAPE 5: LANGUES & LIMITES -->
<div class="wizard-step" data-wizard-step="5">
<!-- LANGUES -->
<div class="card anim" id="sec-lang" style="animation-delay:0.45s">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(34,197,94,0.1);color:#4ade80;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg></div><h2 class="card-title">Langues</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<p class="card-desc">Choisissez les langues à inclure dans vos résultats.</p>
<div id="languageCheckBoxes" class="pill-group" style="padding:0 14px;">
<label class="pill"><input id="en" type="checkbox" name="language" value="en"><span class="pd"></span>🇬🇧 Anglais</label>
<label class="pill"><input id="fr" type="checkbox" name="language" value="fr" checked><span class="pd"></span>🇫🇷 Français</label>
<label class="pill"><input id="multi" type="checkbox" name="language" value="multi" checked><span class="pd"></span>🌍 MULTi</label>
<label class="pill"><input id="vfq" type="checkbox" name="language" value="vfq"><span class="pd"></span>🍁 VFQ <span class="pill-hint">(Québécois en priorité)</span></label>
</div>
</div>
<!-- LIMITES -->
<div class="card anim" id="sec-limites" style="animation-delay:0.55s">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(6,182,212,0.1);color:#22d3ee;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="m19 9-5 5-4-4-3 3"/></svg></div><h2 class="card-title">Limites de résultats</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<p class="card-desc">Définissez la taille maximale et le nombre de résultats.</p>
<div style="padding:0 14px;">
<div class="slider-grid">
<div class="slider-control">
<label>Taille max. (Go)</label>
<div class="slider-row">
<div class="slider-track-wrap">
<div class="slider-fill" id="fill_maxSize"></div>
<input type="range" class="slider-range" id="range_maxSize" min="0" max="500" step="1" value="200">
</div>
<div class="slider-val"><input type="number" name="maxSize" id="maxSize" min="0" step="0.1" value="200"></div>
</div>
</div>
<div class="slider-control">
<label>Résultats max. / résolution</label>
<div class="slider-row">
<div class="slider-track-wrap">
<div class="slider-fill" id="fill_resultsPerQuality"></div>
<input type="range" class="slider-range" id="range_resultsPerQuality" min="1" max="50" step="1" value="10">
</div>
<div class="slider-val"><input type="number" name="resultsPerQuality" id="resultsPerQuality" min="1" value="10"></div>
</div>
</div>
<div class="slider-control">
<label>Résultats totaux max.</label>
<div class="slider-row">
<div class="slider-track-wrap">
<div class="slider-fill" id="fill_maxResults"></div>
<input type="range" class="slider-range" id="range_maxResults" min="1" max="100" step="1" value="30">
</div>
<div class="slider-val"><input type="number" name="maxResults" id="maxResults" min="1" value="30"></div>
</div>
</div>
</div>
</div>
</div>
<!-- CACHE LOCAL -->
<div class="card anim" id="sec-cache-local" style="animation-delay:0.6s">
<div class="card-header" onclick="toggleCard(this)"><div class="card-icon" style="background:rgba(16,185,129,0.1);color:#34d399;"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg></div><h2 class="card-title">Cache</h2><svg class="card-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
<p class="card-desc">Paramètres de cache débrideur et cache local Postgres.</p>
<div style="padding:0 14px;">
<div class="slider-grid">
<div class="slider-control">
<label class="slider-label-row">Min. résultats en cache <button type="button" class="hint-flair" data-hint-title="Résultats minimum en cache" data-hint-text="Représente les résultats obtenus d'une dernière recherche identique (même titre, même langue). Si ce cache contient au moins le nombre de résultats souhaité, les résultats sont retournés presque instantanément sans nouvelle requête. Ce cache REDIS persiste 7 jours et aide à soulager les requêtes API."><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>En savoir plus</button></label>
<div class="slider-row">
<div class="slider-track-wrap">
<div class="slider-fill" id="fill_minCachedResults"></div>
<input type="range" class="slider-range" id="range_minCachedResults" min="0" max="50" step="1" value="10">
</div>
<div class="slider-val"><input type="number" name="minCachedResults" id="minCachedResults" min="0" value="10"></div>
</div>
</div>
<div class="sep"></div>
<div class="sec-label">Cache local (Postgres)</div>
<div class="slider-control">
<label class="slider-label-row">Min. résultats cache local <button type="button" class="hint-flair" data-hint-title="Résultats minimum en cache local" data-hint-text="Nombre minimum de résultats confirmés en cache local (Postgres) pour éviter entièrement la recherche en direct sur les indexeurs. Si le cache contient au moins N résultats valides et récents, les indexeurs ne sont pas interrogés — réponse quasi-instantanée. (0 = désactivé, toujours interroger les indexeurs)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>En savoir plus</button></label>
<div class="slider-row">
<div class="slider-track-wrap">
<div class="slider-fill" id="fill_minPostgresResults"></div>
<input type="range" class="slider-range" id="range_minPostgresResults" min="0" max="20" step="1" value="5">
</div>
<div class="slider-val"><input type="number" name="minPostgresResults" id="minPostgresResults" min="0" max="20" value="5"></div>
</div>
</div>
<div class="slider-control">
<label class="slider-label-row">Durée de validité du cache (jours) <button type="button" class="hint-flair" data-hint-title="Durée de validité du cache" data-hint-text="Durée maximale (TTL) en jours pendant laquelle le cache local est considéré frais. Après N jours sans nouvelle recherche live, les indexeurs sont ré-interrogés pour récupérer les nouveaux torrents parus depuis. Le TTL est remis à zéro automatiquement après chaque recherche live. (0 = désactivé, cache toujours considéré frais)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>En savoir plus</button></label>
<div class="slider-row">
<div class="slider-track-wrap">
<div class="slider-fill" id="fill_postgresMaxAgeDays"></div>
<input type="range" class="slider-range" id="range_postgresMaxAgeDays" min="0" max="30" step="1" value="7">
</div>
<div class="slider-val"><input type="number" name="postgresMaxAgeDays" id="postgresMaxAgeDays" min="0" max="30" value="7"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ÉTAPE 6: INSTALLATION -->
<div class="wizard-step" data-wizard-step="6">
<!-- MANIFEST GENERATOR -->
<div class="manifest-box">
<button type="button" class="btn-generate" id="generateBtn" onclick="generateManifest()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>
Générer le manifest
</button>
<div class="manifest-result" id="manifestResult">
<div class="manifest-result-inner">
<div class="manifest-result-check">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
</div>
<div class="manifest-result-label">Manifest généré avec succès</div>
<div class="manifest-url-wrap">
<input type="text" class="manifest-url-input" id="manifestUrl" readonly onclick="this.select()">
<button type="button" class="manifest-url-copy" onclick="copyManifestUrl()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
Copier
</button>
</div>
<a id="install" style="display:none;"></a>
<a id="copy" style="display:none;"></a>
<button type="button" class="btn-stremio" id="stremioBtn" onclick="installToStremio()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
Installer sur Stremio
</button>
</div>
</div>
</div>
</div>
<div class="wiz-nav" id="wizNav">
<div style="flex:1;display:flex;justify-content:flex-start;">
<button type="button" class="wiz-btn wiz-btn-prev" id="wizPrev" onclick="prevStep()" style="visibility:hidden">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
Retour
</button>
</div>
<span class="wiz-counter" id="wizCounter">1 / 7</span>
<div style="flex:1;display:flex;justify-content:flex-end;">
<button type="button" class="wiz-btn wiz-btn-next" id="wizNext" onclick="nextStep()">
Suivant
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</button>
</div>
</div>
</form>
</div>
<!-- MODAL RD -->
<div class="rd-modal-overlay" id="rd-modal">
<div class="rd-modal-box">
<div class="rd-modal-accent"></div>
<div class="rd-modal-body">
<div class="rd-modal-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
</div>
<div class="rd-modal-title">Attention utilisateurs de Real-Debrid</div>
<p class="rd-modal-text">Nous cessons le support de <strong>Real-Debrid</strong>. Ce service est désormais très restreint et a <strong>supprimé la majorité de son cache francophone</strong> pour raison légale. Nous vous recommandons fortement de migrer vers de meilleures alternatives comme <strong>AllDebrid</strong> ou <strong>TorBox</strong>. Vous pouvez continer de l'utiliser, mais il risque de se comporter de manière inattendue.</p>
<div class="rd-modal-footer"><button type="button" class="rd-modal-btn" id="rd-modal-close">J'ai compris</button></div>
</div>
</div>
</div>
<!-- J'AIME LES TOASTS -->
<div class="toast" id="toast">
<span id="toastIcon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
</span>
<span id="toastMsg">Copié !</span>
</div>
<!-- MODAL INFO HINT -->
<div class="hint-modal-overlay" id="hint-modal">
<div class="hint-modal-box">
<div class="hint-modal-accent"></div>
<div class="hint-modal-body">
<div class="hint-modal-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
</div>
<div class="hint-modal-title" id="hint-modal-title"></div>
<p class="hint-modal-text" id="hint-modal-text"></p>
<div class="hint-modal-footer"><button type="button" class="hint-modal-btn" id="hint-modal-close">Compris</button></div>
</div>
</div>
</div>
<!-- JAVASCRIPT -->
<script src="/static/config.js?v=5"></script>
<script src="/static/app.js?v=5"></script>
</body>
</html>