/* document-editor.css — éditeur de support de formation (voir docs/plan/PLAN.md). Tout est scopé sous .docEditor3 : aucune règle ici ne touche jamais html[data-theme] (figé "dark" pour le reste du site, voir templates/base.html) — le thème clair/sombre de CET éditeur est un attribut data-theme posé sur .docEditor3 lui-même (voir static/document/js/document-editor.js), avec ses propres tokens --doc-* ci-dessous plutôt que les --forge-* globaux. */ /* Demande explicite : l'éditeur occupe TOUTE la largeur de la fenêtre, bord à bord — .content limite normalement à 760px (voir static/style.css) et .content-wide à 1600px, tous deux avec un padding fixe. Neutralisé ici pour cette page précise seulement (ce fichier n'est chargé QUE par templates/document/document_edit.html) : même sélecteur que la règle du site (`body.objectEditBody > main.content`, spécificité identique), mais chargé après static/style.css dans (voir son {% block extra_head %}) donc prioritaire à spécificité égale. */ body.objectEditBody > main.content { max-width: none; width: 100%; padding: 0; margin: 0; } .docEditor3 { --doc-bg: var(--forge-bg); --doc-bg-2: var(--forge-bg-secondary); --doc-card: var(--forge-card); --doc-border: var(--forge-border); --doc-text: var(--forge-text); --doc-muted: var(--forge-text-muted); --doc-accent: var(--accent); --doc-accent-2: var(--accent-2); --doc-glow: 0 0 0 1px rgb(255 95 46 / 25%), 0 8px 24px -6px rgb(255 95 46 / 25%); --doc-quiz-success-bg: rgb(59 165 93 / 12%); --doc-quiz-success-border: #3ba55d; --doc-quiz-success-text: #8fe3ab; --doc-quiz-danger-bg: rgb(255 95 46 / 12%); --doc-quiz-danger-border: #ff5f2e; --doc-quiz-danger-text: #ffb3a0; /* Remplit main.content (voir body.objectEditBody dans static/style.css : `main.content` y est déjà `flex:1 1 auto; min-height:0; overflow:hidden; display:flex; flex-direction:column;`) — jamais `position:fixed` : cet ancêtre a `overflow:hidden`, qui ROGNE VISUELLEMENT tout descendant `position:fixed` à sa propre boîte (laquelle commence sous la barre de navigation du site, pas au vrai sommet du viewport) — bug réel trouvé le 20/09/2026 : le bandeau d'outils (56px) tombait alors entièrement dans la zone rognée, invisible, alors que le reste de l'éditeur semblait décalé vers le haut à sa place. */ flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; background: var(--doc-bg); color: var(--doc-text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } .docEditor3[data-theme="light"] { --doc-bg: #f6f5f2; --doc-bg-2: #fff; --doc-card: #fff; --doc-border: #e3e1db; --doc-text: #14161c; --doc-muted: #6b7280; --doc-glow: 0 0 0 1px rgb(255 95 46 / 30%), 0 8px 24px -6px rgb(255 95 46 / 30%); --doc-quiz-success-bg: #e4f5ea; --doc-quiz-success-border: #2e7d46; --doc-quiz-success-text: #1d4c2c; --doc-quiz-danger-bg: #fdede8; --doc-quiz-danger-border: #c1451f; --doc-quiz-danger-text: #7a1418; } .docEditor3 * { box-sizing: border-box; } .docEditor3 button { font-family: inherit; } /* ===== TOPBAR ===== */ .docTopbar { height: 56px; flex-shrink: 0; background: var(--doc-bg-2); border-bottom: 1px solid var(--doc-border); display: flex; align-items: center; justify-content: space-between; padding: 0 20px; gap: 12px; } .docCrumb { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; min-width: 0; overflow: hidden; } .docCrumbDim { color: var(--doc-muted); font-weight: 400; white-space: nowrap; text-decoration: none; } .docCrumbCur { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--doc-text); } .docTopbarActions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; } .docIconBtn { width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--doc-border); background: transparent; color: var(--doc-text); display: flex; align-items: center; justify-content: center; cursor: pointer; } .docIconBtn:hover:not(:disabled) { border-color: var(--doc-muted); } .docIconBtn:disabled { opacity: 0.35; cursor: default; } .docDividerV { width: 1px; height: 22px; background: var(--doc-border); margin: 0 4px; } .docBtnSecondary { height: 34px; padding: 0 14px; border-radius: 10px; border: 1px solid var(--doc-border); background: transparent; color: var(--doc-text); font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 7px; cursor: pointer; } .docBtnSecondary:hover { border-color: var(--doc-muted); } .docBtnPrimary { border-color: var(--doc-accent); color: var(--doc-accent); } .docBtnPrimary:hover { background: rgb(255 95 46 / 8%); } .docWidthPicker { display: flex; gap: 4px; background: var(--doc-card); border: 1px solid var(--doc-border); border-radius: 10px; padding: 3px; } .docWidthBtn { border: none; background: transparent; color: var(--doc-muted); font-size: 12.5px; font-weight: 600; padding: 5px 10px; border-radius: 7px; cursor: pointer; } .docWidthBtn.is-active { background: rgb(255 95 46 / 12%); color: var(--doc-accent); } /* ===== BODY LAYOUT ===== */ .docBodyWrap { flex: 1; display: flex; min-height: 0; position: relative; } .docSidebar { flex-shrink: 0; background: var(--doc-bg-2); padding: 20px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 22px; } .docSidebarLeft { width: 248px; border-right: 1px solid var(--doc-border); } .docSidebarRight { width: 300px; border-left: 1px solid var(--doc-border); } .docSectionLabel { font-size: 12px; font-weight: 700; letter-spacing: 0.04em; color: var(--doc-muted); margin-bottom: 10px; } .docShapesGrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; } .docLibItem { border: 1px solid var(--doc-border); border-radius: 10px; cursor: grab; background: var(--doc-card); transition: border-color 0.15s ease, box-shadow 0.15s ease; } .docLibItem:hover { border-color: var(--doc-accent); box-shadow: var(--doc-glow); } .docLibItem--shape { padding: 10px 8px; display: flex; flex-direction: column; align-items: center; gap: 6px; } .docLibItem--row { padding: 9px 10px; display: flex; align-items: center; gap: 10px; } .docLibItem span:last-child { font-size: 12.5px; font-weight: 600; } .docLibList { display: flex; flex-direction: column; gap: 6px; } .docLibIcon { width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; font-size: 14px; flex-shrink: 0; } .docLibIcon--rectangle::before { content: "▭"; } .docLibIcon--cercle::before { content: "○"; } .docLibIcon--triangle::before { content: "△"; } .docLibIcon--trait::before { content: "―"; } .docLibIcon--paragraphe::before { content: "¶"; } .docLibIcon--image::before { content: "🖼"; } .docLibIcon--bouton::before { content: "⬚"; } .docLibIcon--titre::before { content: "T"; font-weight: 800; } .docLibIcon--quiz::before { content: "?"; color: var(--doc-accent); font-weight: 800; } .docLibIcon--association::before { content: "⇄"; color: var(--doc-accent); } .docLibIcon--memory::before { content: "▤"; color: var(--doc-accent); } .docLibIcon--mots::before { content: "▦"; color: var(--doc-accent); } .docLibIcon--scenario::before { content: "◈"; color: var(--doc-accent); } .docLibIcon--zones::before { content: "⚠"; color: var(--doc-accent); } /* ---- CANVAS ---- */ .docCanvasArea { flex: 1; background: var(--doc-bg); padding: 36px 40px; overflow: auto; display: flex; justify-content: center; position: relative; } .docPage { width: 760px; max-width: 100%; height: fit-content; background: var(--doc-card); border: 1px solid var(--doc-border); border-radius: 16px; box-shadow: 0 1px 3px rgb(0 0 0 / 30%); padding: 48px 52px; position: relative; transform-origin: top center; transition: width 0.2s ease; } /* Enfant qui reçoit le HTML rendu (voir #docPage vs #docPageContent dans document-editor.js — le rafraîchissement du canevas ne remplace QUE ce contenu, jamais .docPage elle-même, pour que .docSnapGridOverlay, sa voisine, survive à chaque rafraîchissement). */ .docPageContent { display: flex; flex-direction: column; gap: 18px; } .docPage.docPage--fixedWidth { width: var(--doc-preview-width, 760px); padding: 28px 20px; } .docRow { position: relative; } .docRow > [data-element-id] { flex: 1 1 220px; min-width: 0; } [data-element-id] { position: relative; border-radius: 8px; padding: 6px; margin: -6px; cursor: pointer; transition: background 0.1s ease; } [data-kind="row"] > [data-element-id] { margin: 0; } [data-element-id]:hover { background: rgb(255 95 46 / 6%); } [data-element-id].docSelected { background: rgb(255 95 46 / 10%); outline: 1px dashed var(--doc-accent); } [data-element-id].docDropTarget--before { box-shadow: inset 0 3px 0 0 var(--doc-accent); } [data-element-id].docDropTarget--after { box-shadow: inset 0 -3px 0 0 var(--doc-accent); } [data-element-id].docDropTarget--mergeLeft { box-shadow: inset 3px 0 0 0 var(--doc-accent); } [data-element-id].docDropTarget--mergeRight { box-shadow: inset -3px 0 0 0 var(--doc-accent); } .docShape[data-element-id] { padding: 0; margin: 0; border-radius: 0; } .docShape[data-element-id].docSelected { outline: 2px solid var(--doc-accent); background: transparent; } .docText { outline: none; } .docImage.docImagePlaceholder { width: 100%; height: 190px; border-radius: 10px; background: var(--doc-bg-2); border: 1px dashed var(--doc-border); display: flex; align-items: center; justify-content: center; gap: 8px; color: var(--doc-muted); font-size: 13px; font-weight: 600; } img.docImage { max-width: 100%; border-radius: 10px; display: block; } .docButton { border: none; border-radius: 999px; padding: 10px 22px; font-weight: 700; font-size: 14px; background: var(--doc-accent); color: #14100c; cursor: pointer; } .docMinigame { border: 1px solid var(--doc-accent); border-radius: 12px; background: rgb(255 95 46 / 8%); } .docMinigameBadge { padding: 18px 20px; display: flex; align-items: center; justify-content: space-between; gap: 12px; } .docMinigameLabel { font-size: 15px; font-weight: 700; } .docMinigamePlaceholder { font-size: 12.5px; color: var(--doc-muted); } /* ---- Quiz/Association/Memory/Mots mêlés/Scénario : mini-jeux interactifs en Mode Aperçu (voir docs/plan/maquettes/ document-formation-web.html — référence visuelle du Quiz). Masqués en édition (seul .docMinigameBadge y est visible, voir plus haut) ; jamais les deux visibles en même temps. ---- */ .docQuizPlayer, .docAssocPlayer, .docMemoryPlayer, .docMotsPlayer, .docScenarioPlayer { display: none; } .docEditor3.docEditor3--preview [data-kind="quiz"] .docMinigameBadge, .docEditor3.docEditor3--preview [data-kind="association"] .docMinigameBadge, .docEditor3.docEditor3--preview [data-kind="memory"] .docMinigameBadge, .docEditor3.docEditor3--preview [data-kind="mots"] .docMinigameBadge, .docEditor3.docEditor3--preview [data-kind="scenario"] .docMinigameBadge { display: none; } .docEditor3.docEditor3--preview [data-kind="quiz"] .docQuizPlayer, .docEditor3.docEditor3--preview [data-kind="association"] .docAssocPlayer, .docEditor3.docEditor3--preview [data-kind="memory"] .docMemoryPlayer, .docEditor3.docEditor3--preview [data-kind="mots"] .docMotsPlayer, .docEditor3.docEditor3--preview [data-kind="scenario"] .docScenarioPlayer { display: block; } .docEditor3.docEditor3--preview [data-kind="quiz"], .docEditor3.docEditor3--preview [data-kind="association"], .docEditor3.docEditor3--preview [data-kind="memory"], .docEditor3.docEditor3--preview [data-kind="mots"], .docEditor3.docEditor3--preview [data-kind="scenario"] { border: none; background: transparent; } .docEditor3.docEditor3--preview .docQuizPlayer, .docEditor3.docEditor3--preview .docQuizPlayer *, .docEditor3.docEditor3--preview .docAssocPlayer, .docEditor3.docEditor3--preview .docAssocPlayer *, .docEditor3.docEditor3--preview .docMemoryPlayer, .docEditor3.docEditor3--preview .docMemoryPlayer *, .docEditor3.docEditor3--preview .docMotsPlayer, .docEditor3.docEditor3--preview .docMotsPlayer *, .docEditor3.docEditor3--preview .docScenarioPlayer, .docEditor3.docEditor3--preview .docScenarioPlayer * { /* .docEditor3--preview désactive pointer-events sur tout [data-element-id] (voir plus bas) pour empêcher la sélection/le déplacement pendant l'Aperçu — réactivé ici spécifiquement pour que ces mini-jeux restent RÉELLEMENT cliquables/glissables. */ pointer-events: auto; } .docQuizCard, .docQuizResultCard { background: linear-gradient(180deg, var(--doc-card), var(--doc-bg-2)); border: 1px solid var(--doc-border); border-radius: 16px; padding: 1.8rem; } .docQuizResultCard { text-align: center; } .docQuizKicker { font-size: 12px; font-weight: 700; letter-spacing: 0.04em; color: var(--doc-accent); margin-bottom: 6px; } .docQuizPlayerTitle { font-size: 1.15rem; font-weight: 700; margin: 0 0 20px; } .docQuizProgressTrack { height: 4px; background: var(--doc-border); border-radius: 2px; overflow: hidden; margin-bottom: 10px; } .docQuizProgressFill { height: 100%; width: 0%; background: linear-gradient(120deg, var(--doc-accent), var(--doc-accent-2)); transition: width 0.2s ease; } .docQuizMeta { display: flex; justify-content: space-between; font-size: 13px; color: var(--doc-muted); font-weight: 600; margin-bottom: 20px; } .docQuizQuestionText { font-size: 17px; font-weight: 700; line-height: 1.3; margin: 0 0 18px; } .docQuizOptions { display: flex; flex-direction: column; gap: 10px; } .docQuizOption { text-align: left; padding: 13px 15px; border: 1px solid var(--doc-border); background: var(--doc-bg-2); color: var(--doc-text); border-radius: 10px; font-size: 15px; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 12px; transition: border-color 0.15s ease; } .docQuizOption:hover:not(:disabled) { border-color: var(--doc-accent); } .docQuizOptionLetter { flex-shrink: 0; width: 24px; height: 24px; border-radius: 50%; border: 1px solid var(--doc-border); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12.5px; color: var(--doc-muted); } .docQuizOption.is-correct { border-color: var(--doc-quiz-success-border); background: var(--doc-quiz-success-bg); } .docQuizOption.is-correct .docQuizOptionLetter { border-color: var(--doc-quiz-success-border); background: var(--doc-quiz-success-border); color: #0b0e14; } .docQuizOption.is-wrong { border-color: var(--doc-quiz-danger-border); background: var(--doc-quiz-danger-bg); } .docQuizOption.is-wrong .docQuizOptionLetter { border-color: var(--doc-accent); background: var(--doc-accent); color: #0b0e14; } .docQuizOption:disabled:not(.is-correct, .is-wrong) { opacity: 0.45; } .docQuizFeedback { display: none; margin-top: 16px; padding: 13px 15px; border-radius: 10px; font-size: 14px; line-height: 1.5; } .docQuizFeedback.is-visible { display: block; } .docQuizFeedback.is-ok { background: var(--doc-quiz-success-bg); color: var(--doc-quiz-success-text); border: 1px solid var(--doc-quiz-success-border); } .docQuizFeedback.is-ko { background: var(--doc-quiz-danger-bg); color: var(--doc-quiz-danger-text); border: 1px solid var(--doc-quiz-danger-border); } .docQuizNextBar { margin-top: 20px; display: flex; justify-content: flex-end; } .docQuizNextBtn { padding: 0.75rem 1.6rem; border-radius: 10px; border: none; background: linear-gradient(120deg, var(--doc-accent), var(--doc-accent-2)); color: #14100c; font-weight: 700; font-size: 14px; cursor: pointer; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; } .docQuizNextBtn.is-visible { opacity: 1; pointer-events: auto; } .docQuizResultBig { font-weight: 800; font-size: 44px; background: linear-gradient(120deg, var(--doc-accent), var(--doc-accent-2)); background-clip: text; color: transparent; line-height: 1; } .docQuizResultSub { margin-top: 6px; margin-bottom: 18px; font-size: 13px; color: var(--doc-muted); font-weight: 600; } .docQuizRestartBtn { padding: 0.7rem 1.5rem; border-radius: 10px; background: transparent; border: 1px solid var(--doc-border); color: var(--doc-text); font-weight: 600; font-size: 14px; cursor: pointer; } /* ---- Association : plateau de glisser-déposer (voir docs/plan/PLAN.md, "relier visuellement deux éléments qui vont ensemble"). Réutilise .docQuizFeedback/.docQuizKicker (même rôle visuel) plutôt que de dupliquer ces règles. ---- */ .docAssocCard { background: linear-gradient(180deg, var(--doc-card), var(--doc-bg-2)); border: 1px solid var(--doc-border); border-radius: 16px; padding: 1.8rem; } .docAssocTitle { font-size: 1.15rem; font-weight: 700; margin: 0 0 14px; } .docAssocMeta { font-size: 13px; color: var(--doc-muted); font-weight: 600; margin-bottom: 16px; } .docAssocBoard { display: flex; gap: 24px; } .docAssocColumn { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; } .docAssocItem, .docAssocSlot { padding: 13px 15px; border: 1px solid var(--doc-border); background: var(--doc-bg-2); color: var(--doc-text); border-radius: 10px; font-size: 14px; font-weight: 500; transition: border-color 0.15s ease, opacity 0.15s ease; } .docAssocItem { cursor: grab; } .docAssocItem:hover, .docAssocSlot:hover { border-color: var(--doc-accent); } .docAssocItem.is-selected { border-color: var(--doc-accent); box-shadow: var(--doc-glow); } .docAssocItem.is-matched, .docAssocSlot.is-matched { border-color: var(--doc-quiz-success-border); background: var(--doc-quiz-success-bg); color: var(--doc-quiz-success-text); cursor: default; opacity: 0.85; } .docAssocItem.is-wrong, .docAssocSlot.is-wrong { border-color: var(--doc-quiz-danger-border); background: var(--doc-quiz-danger-bg); } /* ---- Barre de bouton "Recommencer" partagée par tous les mini-jeux SAUF le Quiz (qui garde son propre écran de résultat séparé) : le plateau de jeu reste affiché en permanence une fois terminé, seul ce bouton apparaît/disparaît (voir retour utilisateur du 20/09/2026). ---- */ .docMinigameRestartBar { display: none; margin-top: 20px; text-align: center; } .docMinigameRestartBar.is-visible { display: block; } .docMinigameRestartBar button { padding: 0.7rem 1.5rem; border-radius: 10px; background: transparent; border: 1px solid var(--doc-border); color: var(--doc-text); font-weight: 600; font-size: 14px; cursor: pointer; } /* ---- Association : panneau Propriétés — paires reliées visuellement par un glyphe entre les deux champs (voir forgeDocRenderAssociationPairHtml, static/document/js/document-editor.js). Empilement VERTICAL (pas côte à côte) : la colonne du panneau Propriétés est trop étroite pour deux champs de texte libre côte à côte, voir retour utilisateur du 20/09/2026. ---- */ .docAssocPairRow { display: flex; flex-direction: column; gap: 8px; border: 1px solid var(--doc-border); border-radius: 10px; padding: 12px; margin-bottom: 10px; background: var(--doc-card); } .docAssocPairInput { width: 100%; resize: vertical; border: 1px solid var(--doc-border); border-radius: 8px; padding: 8px 10px; font-size: 13px; font-family: inherit; color: var(--doc-text); background: var(--doc-bg-2); } .docAssocPairLink { align-self: center; color: var(--doc-accent); font-weight: 700; font-size: 15px; } /* ---- Memory : panneau Propriétés — étiquette au-dessus de chaque champ recto/verso (voir forgeDocRenderMemoryCardHtml). Réutilise .docAssocPairRow/.docAssocPairInput (même carte, mêmes champs) plutôt que de dupliquer leurs règles. ---- */ .docMemoryFaceLabel { font-size: 11.5px; font-weight: 700; letter-spacing: 0.03em; color: var(--doc-muted); text-transform: uppercase; margin-top: 4px; } /* ---- Memory : plateau de jeu (voir docs/plan/PLAN.md, "retourner des cartes pour constituer des paires d'images identiques"). Réutilise .docAssocTitle/.docAssocMeta/.docMinigameRestartBar (mêmes rôles visuels, voir forgeDocRenderMemoryProps ci-dessus). ---- */ .docMemoryCardWrap { background: linear-gradient(180deg, var(--doc-card), var(--doc-bg-2)); border: 1px solid var(--doc-border); border-radius: 16px; padding: 1.8rem; } .docMemoryGrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: 12px; } .docMemoryCard { aspect-ratio: 3 / 4; perspective: 700px; cursor: pointer; } .docMemoryCardInner { position: relative; width: 100%; height: 100%; transition: transform 0.4s ease; transform-style: preserve-3d; } .docMemoryCard.is-flipped .docMemoryCardInner { transform: rotateY(180deg); } .docMemoryCard.is-matched { /* Une paire trouvée reste face retournée en PERMANENCE (voir forgeDocMemoryFlip, static/document/js/document-editor.js — la classe is-flipped n'est jamais retirée pour une carte appariée). Pas d'opacité réduite ici : une carte à 55% d'opacité, à côté de cartes face cachée pleinement opaques, se lisait comme "repartie face cachée" (retour utilisateur du 20/09/2026) alors qu'elle restait techniquement retournée — la bordure verte ci-dessous suffit à signaler l'état "trouvée", sans jamais assombrir le contenu révélé. */ cursor: default; } .docMemoryCardFace { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 6px; border-radius: 10px; border: 1px solid var(--doc-border); background: var(--doc-bg-2); backface-visibility: hidden; overflow: hidden; text-align: center; font-size: 12px; color: var(--doc-text); } .docMemoryCardFace img { max-width: 100%; max-height: 60%; object-fit: contain; } .docMemoryCardFront { background: linear-gradient(135deg, var(--doc-accent), var(--doc-accent-2)); color: #14100c; } .docMemoryCardBackGlyph { font-size: 26px; font-weight: 800; } .docMemoryCardBack { transform: rotateY(180deg); border-color: var(--doc-accent); } .docMemoryCard.is-matched .docMemoryCardFace.docMemoryCardBack { border-color: var(--doc-quiz-success-border); background: var(--doc-quiz-success-bg); color: var(--doc-quiz-success-text); } /* ---- Mots mêlés : grille interactive (voir docs/plan/PLAN.md, "mots cachés horizontalement/verticalement/en diagonale"). Réutilise .docAssocCard/.docAssocTitle/.docAssocMeta/.docMinigameRestartBar (mêmes rôles visuels que l'Association/Memory ci-dessus). ---- */ .docMotsBoard { display: flex; flex-wrap: wrap; gap: 24px; align-items: flex-start; } .docMotsGrid { display: grid; gap: 3px; width: min(100%, 420px); user-select: none; } .docMotsCell { aspect-ratio: 1; display: flex; align-items: center; justify-content: center; border: 1px solid var(--doc-border); background: var(--doc-bg-2); color: var(--doc-text); font-weight: 700; font-size: 13px; border-radius: 4px; cursor: pointer; } .docMotsCell.is-selecting { border-color: var(--doc-accent); background: rgb(255 95 46 / 18%); } .docMotsCell.is-found { border-color: var(--doc-quiz-success-border); background: var(--doc-quiz-success-bg); color: var(--doc-quiz-success-text); cursor: default; } .docMotsWordList { display: flex; flex-direction: column; gap: 8px; min-width: 140px; } .docMotsWordChip { padding: 8px 12px; border: 1px solid var(--doc-border); border-radius: 8px; font-size: 13px; font-weight: 600; color: var(--doc-text); background: var(--doc-bg-2); } .docMotsWordChip.is-found { border-color: var(--doc-quiz-success-border); background: var(--doc-quiz-success-bg); color: var(--doc-quiz-success-text); text-decoration: line-through; } .docUnknown { font-size: 12.5px; color: var(--doc-muted); border: 1px dashed var(--doc-border); border-radius: 8px; padding: 10px; } /* ---- grille d'accroche (formes libres) — voir docs/plan/PLAN.md, "grille d'accroche réelle" : visible en overlay pendant le déplacement d'une forme (voir .docPage--dragging-shape ci-dessous), jamais décorative. */ .docSnapGridOverlay { position: absolute; inset: 0; pointer-events: none; z-index: 1; opacity: 0; transition: opacity 0.1s ease; background-image: linear-gradient(to right, rgb(255 95 46 / 12%) 1px, transparent 1px), linear-gradient(to bottom, rgb(255 95 46 / 12%) 1px, transparent 1px); background-size: var(--doc-snap-size, 8px) var(--doc-snap-size, 8px); } .docPage.docPage--dragging-shape .docSnapGridOverlay { opacity: 1; } .docZoomPill { position: absolute; bottom: 24px; left: 50%; transform: translateX(-50%); background: var(--doc-card); border: 1px solid var(--doc-border); border-radius: 999px; height: 36px; padding: 0 6px; display: flex; align-items: center; gap: 6px; box-shadow: 0 2px 6px rgb(0 0 0 / 30%); } .docZoomPill button { width: 26px; height: 26px; border-radius: 999px; border: none; background: transparent; color: var(--doc-text); cursor: pointer; font-size: 15px; font-weight: 700; } .docZoomPill button:hover { background: var(--doc-bg-2); } .docZoomPill span { font-size: 12.5px; font-weight: 700; color: var(--doc-muted); width: 40px; text-align: center; } /* ---- RIGHT SIDEBAR : Propriétés ---- */ .docField { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; } .docFieldRow { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .docField label, .docFieldRow .docFieldLabel { font-size: 13px; color: var(--doc-muted); } .docField input, .docField textarea, .docField select { border: 1px solid var(--doc-border); border-radius: 8px; padding: 8px 10px; font-size: 13px; color: var(--doc-text); background: var(--doc-card); font-family: inherit; width: 100%; resize: vertical; } .docSwatches { display: flex; gap: 8px; } .docSwatch { width: 22px; height: 22px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; } .docSwatch.is-active { border-color: var(--doc-text); } .docSegmented { display: flex; flex-wrap: wrap; gap: 6px; } .docSegBtn { padding: 6px 10px; border-radius: 8px; border: 1px solid var(--doc-border); background: var(--doc-card); font-size: 12.5px; font-weight: 600; color: var(--doc-text); cursor: pointer; } .docSegBtn.is-active { background: rgb(255 95 46 / 12%); color: var(--doc-accent); border-color: var(--doc-accent); } .docToolbarRow { display: flex; gap: 6px; margin-bottom: 14px; } .docFmtBtn { width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--doc-border); background: var(--doc-card); display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 14px; font-weight: 800; color: var(--doc-text); } .docFmtBtn.is-active { background: rgb(255 95 46 / 12%); border-color: var(--doc-accent); color: var(--doc-accent); } .docFmtBtn.docFmtBtn--italic { font-style: italic; font-weight: 400; } .docFmtBtn.docFmtBtn--underline { text-decoration: underline; font-weight: 400; } .docDeleteBtn { width: 100%; height: 38px; border-radius: 10px; border: 1px solid var(--status-danger, #f04438); background: transparent; color: var(--status-danger, #f04438); font-weight: 700; cursor: pointer; margin-top: 6px; } .docDeleteBtn:hover { background: rgb(240 68 56 / 10%); } /* ---- Quiz : liste de questions répétable, chacune avec sa propre liste de choix répétable (voir forgeDocRenderQuizProps, static/document/js/ document-editor.js) ---- */ .docQuizQuestionsLabel { margin-top: 10px; } .docQuizQuestion { border: 1px solid var(--doc-border); border-radius: 10px; padding: 12px; margin-bottom: 10px; background: var(--doc-card); } .docQuizQuestionHeader { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; } .docQuizRemoveBtn { border: none; background: transparent; color: var(--doc-muted); cursor: pointer; font-size: 14px; } .docQuizRemoveBtn:hover { color: var(--status-danger, #f04438); } .docQuizChoicesList { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; } .docQuizChoiceRow { display: flex; align-items: center; gap: 8px; } .docQuizChoiceRow input[type="text"] { flex: 1; } /* ---- Scénario : panneau Propriétés — chaque choix garde sa case "bon choix"/son texte (.docQuizChoiceRow, réutilisé tel quel) ET, en plus, sa conséquence en dessous (voir forgeDocRenderScenarioChoiceHtml, static/document/js/document-editor.js) — un bloc de plus que le Quiz, d'où ce conteneur dédié. ---- */ .docScenarioChoiceBlock { display: flex; flex-direction: column; gap: 6px; } .docQuizAddBtn { width: 100%; justify-content: center; margin-top: 4px; } .docEmptyState { font-size: 13px; color: var(--doc-muted); text-align: center; padding: 30px 10px; } /* ===== BOTTOM NAV (mobile) ===== */ .docBottomNav { display: none; position: fixed; bottom: 0; left: 0; right: 0; height: 58px; background: var(--doc-bg-2); border-top: 1px solid var(--doc-border); z-index: 40; align-items: stretch; justify-content: space-around; } .docBottomNav button { flex: 1; background: transparent; border: none; color: var(--doc-muted); cursor: pointer; font-size: 12px; font-weight: 600; } .docBottomNav button.is-active { color: var(--doc-accent); } .docSidebarClose { display: none; } /* ===== MODE APERÇU : masque tout le chrome d'édition ===== */ .docEditor3.docEditor3--preview .docSidebarLeft, .docEditor3.docEditor3--preview .docSidebarRight, .docEditor3.docEditor3--preview .docBottomNav, .docEditor3.docEditor3--preview .docZoomPill { display: none; } .docEditor3.docEditor3--preview [data-element-id] { cursor: default; pointer-events: none; } .docEditor3.docEditor3--preview [data-element-id]:hover, .docEditor3.docEditor3--preview [data-element-id].docSelected { background: transparent; outline: none; } .docEditor3.docEditor3--preview .docCanvasArea { padding: 40px; } /* ---- Modale générique (utilisée aujourd'hui par l'éditeur d'arbre du mini-jeu Scénario, voir forgeDocOpenScenarioTreeModal) — overlay + boîte de dialogue centrée, indépendante de tout framework externe (aucune dépendance partagée avec game_engine, voir CLAUDE.md). ---- */ .docModalBackdrop { display: none; position: fixed; inset: 0; background: rgb(11 14 20 / 65%); z-index: 200; align-items: center; justify-content: center; padding: 24px; } .docModalBackdrop.is-open { display: flex; } .docModalDialog { background: var(--doc-bg-2); border: 1px solid var(--doc-border); border-radius: 16px; width: min(640px, 100%); max-height: min(80vh, 720px); display: flex; flex-direction: column; overflow: hidden; } .docModalHeader { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--doc-border); } .docModalTitle { font-size: 15px; font-weight: 700; color: var(--doc-text); } .docModalCloseBtn { border: none; background: transparent; color: var(--doc-muted); font-size: 16px; cursor: pointer; padding: 4px; } .docModalCloseBtn:hover { color: var(--doc-text); } .docModalBody { padding: 20px; overflow-y: auto; } /* ---- Scénario : panneau Propriétés — une carte par scénario (titre + nombre de nœuds + bouton d'ouverture de la modale), l'édition de l'arbre lui-même se fait entièrement dans la modale (voir forgeDocRenderScenarioTreeModal). ---- */ .docScenarioCard .docBtnSecondary { width: 100%; justify-content: center; } /* ---- Scénario : éditeur d'arbre en GRAPHE VISUEL (retour utilisateur du 21/09/2026 : "passons à un véritable graphe visuel", remplace la première version en liste de nœuds + menus déroulants). Dialogue bien plus grand que la modale générique par défaut : un graphe a besoin de place pour être lisible. ---- */ #docScenarioTreeModal .docModalDialog { width: min(1180px, 95vw); max-height: min(88vh, 820px); } #docScenarioTreeModal .docModalBody { padding: 0; overflow: hidden; display: flex; flex-direction: column; min-height: 0; } .docScenarioGraphTitleRow { padding: 16px 20px; border-bottom: 1px solid var(--doc-border); } .docScenarioGraphTitleRow input { width: 100%; border: 1px solid var(--doc-border); border-radius: 8px; padding: 8px 10px; font-size: 14px; font-weight: 700; color: var(--doc-text); background: var(--doc-bg-2); } .docScenarioGraphToolbar { display: flex; align-items: center; gap: 12px; padding: 10px 20px; border-bottom: 1px solid var(--doc-border); } .docScenarioGraphHint { font-size: 12.5px; color: var(--doc-muted); } .docScenarioGraphHint.is-connecting { color: var(--doc-accent); font-weight: 600; } .docScenarioGraphSplit { flex: 1 1 auto; min-height: 0; display: flex; } .docScenarioGraphCanvas { position: relative; flex: 1 1 auto; min-width: 0; overflow: auto; background: radial-gradient(circle, var(--doc-border) 1px, transparent 1px) 0 0 / 24px 24px, var(--doc-bg-2); cursor: default; } .docScenarioGraphCanvas.is-connecting { cursor: crosshair; } .docScenarioGraphCanvas.is-connecting .docScenarioGraphNode { cursor: crosshair; } .docScenarioGraphInner { position: relative; width: 2200px; height: 1600px; } .docScenarioGraphSvg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; } .docScenarioGraphEdge { fill: none; stroke: var(--doc-muted); stroke-width: 2; } .docScenarioGraphEdgeLabel { position: absolute; transform: translate(-50%, -50%); background: var(--doc-bg-2); border: 1px solid var(--doc-border); border-radius: 6px; padding: 2px 7px; font-size: 11px; font-weight: 600; color: var(--doc-muted); white-space: nowrap; max-width: 140px; overflow: hidden; text-overflow: ellipsis; } .docScenarioGraphNode { position: absolute; width: 180px; border: 1px solid var(--doc-border); border-radius: 10px; background: var(--doc-card); padding: 10px 12px; cursor: grab; user-select: none; box-shadow: 0 2px 6px rgb(0 0 0 / 20%); } .docScenarioGraphNode:active { cursor: grabbing; } .docScenarioGraphNode.is-root { border-color: var(--doc-accent); } .docScenarioGraphNode.is-selected { border-color: var(--doc-accent); box-shadow: 0 0 0 2px var(--doc-accent); } .docScenarioGraphNode.is-connect-target:hover { border-color: var(--doc-quiz-success-border); box-shadow: 0 0 0 2px var(--doc-quiz-success-border); } .docScenarioGraphNodeLabel { font-size: 10.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--doc-accent); margin-bottom: 4px; } .docScenarioGraphNodeText { font-size: 12.5px; line-height: 1.35; color: var(--doc-text); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden; } .docScenarioGraphInspector { flex: 0 0 300px; border-left: 1px solid var(--doc-border); padding: 16px; overflow-y: auto; } .docScenarioGraphInspectorEmpty { font-size: 13px; color: var(--doc-muted); text-align: center; padding: 30px 10px; } .docScenarioChoiceTargetRow { display: flex; align-items: center; gap: 6px; margin-top: 4px; } .docScenarioChoiceTargetLabel { flex: 1; min-width: 0; font-size: 12px; color: var(--doc-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .docScenarioChoiceLinkBtn { border: 1px solid var(--doc-border); background: transparent; color: var(--doc-text); border-radius: 6px; padding: 3px 8px; font-size: 11.5px; cursor: pointer; white-space: nowrap; } .docScenarioChoiceLinkBtn:hover { border-color: var(--doc-accent); } .docScenarioChoiceLinkBtn.is-active { border-color: var(--doc-accent); background: var(--doc-accent); color: #14100c; } /* ===== RESPONSIVE (chrome de l'éditeur lui-même, <900px) ===== */ @media (width <= 900px) { .docCrumbDim { display: none; } .docTopbar { padding: 0 14px; } .docBtnLabel { display: none; } .docBtnSecondary { padding: 0 10px; } .docWidthPicker { display: none; } .docCanvasArea { padding: 18px 14px 84px; } .docPage { padding: 28px 20px; } .docSidebar { /* position:absolute relative à .docBodyWrap (position:relative, voir plus haut) plutôt que position:fixed relative au viewport : ce dernier subirait le même rognage par overflow:hidden que .docEditor3 (voir son commentaire) — inutile de toute façon ici, .docBodyWrap exclut déjà .docTopbar/.docBottomNav (ses frères, jamais ses parents), inset:0 suffit sans aucun calcul de hauteur de bandeau. */ position: absolute; inset: 0; width: 100%; z-index: 30; transition: transform 0.25s ease; } .docSidebarLeft { transform: translateX(-100%); } .docSidebarRight { transform: translateX(100%); } .docSidebar.is-open { transform: translateX(0); } .docSidebarClose { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--doc-muted); margin-bottom: 16px; cursor: pointer; padding: 0 16px; } .docBottomNav { display: flex; } .docAssocBoard { flex-direction: column; } }