Build and deploy / test-python (push) Failing after 1m5s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / lint-python (push) Failing after 1m2s
Build and deploy / lint-js (push) Failing after 1m4s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m0s
Le quiz affichait jusqu'ici la meme carte resume en edition comme en Apercu. Ajoute un vrai questionnaire jouable, visible UNIQUEMENT en Mode Apercu (masque en edition via CSS, jamais les deux a la fois) : options de reponse cliquables, marquage correct/incorrect immediat, score qui accumule les points de chaque question repondue correctement, progression "Question suivante", et un ecran de resultat final (score obtenu / total des points possibles) avec "Recommencer le quiz" - structure et identite visuelle calquees sur docs/plan/maquettes/document-formation-web.html (cartes en degrade, options A/B/C/D, feedback vert/orange), adaptees aux tokens --doc-* deja en place (theme clair/sombre inclus, nouvelles variables --doc-quiz-success-*/--doc-quiz-danger-*). Cote rendu (document_engine/rendering/render_document_element.py), _render_quiz ajoute desormais le questionnaire (fonction privee _render_quiz_player) des qu'au moins une question existe : les questions sont embarquees en JSON dans un attribut data-quiz-config (jamais un <script> par element), echappees pour l'HTML - aucun aller-retour serveur pendant qu'on joue, tout le deroulé (reponse/ score/suivant/resultat) est gere par static/document/js/document-editor.js. pointer-events, desactive sur tout element en Apercu pour empecher la selection/le glisser-deposer pendant le test, est reactive specifiquement dans le questionnaire pour qu'il reste reellement cliquable. Tests : 3 nouveaux tests de rendu purs (sans Flask, dont un qui verifie l'echappement HTML du texte d'une question contre une injection). Verifie en live via une simulation DOM complete (basculer Apercu, repondre correctement puis incorrectement, verifier score/feedback/etat des options, passer a la question suivante, voir l'ecran de resultat) - le script de diagnostic n'a pas ete conserve dans le depot. SKIP=djlint : backlog H021 pre-existant, aucun template touche ici. ruff/mypy --strict/vulture/bandit/import-linter/eslint/stylelint tous verts ; 48 tests cibles (document + onboarding) verifies frais. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1123 lines
23 KiB
CSS
1123 lines
23 KiB
CSS
/* 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 <head> (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 : questionnaire interactif en Mode Aperçu (voir docs/plan/
|
|
maquettes/document-formation-web.html — référence visuelle). Masqué en
|
|
édition (seul .docMinigameBadge y est visible, voir plus haut) ; les
|
|
deux jamais visibles en même temps. ---- */
|
|
.docQuizPlayer {
|
|
display: none;
|
|
}
|
|
|
|
.docEditor3.docEditor3--preview [data-kind="quiz"] .docMinigameBadge {
|
|
display: none;
|
|
}
|
|
|
|
.docEditor3.docEditor3--preview [data-kind="quiz"] .docQuizPlayer {
|
|
display: block;
|
|
}
|
|
|
|
.docEditor3.docEditor3--preview [data-kind="quiz"] {
|
|
border: none;
|
|
background: transparent;
|
|
}
|
|
|
|
.docEditor3.docEditor3--preview .docQuizPlayer,
|
|
.docEditor3.docEditor3--preview .docQuizPlayer * {
|
|
/* .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 le quiz reste
|
|
RÉELLEMENT cliquable (répondre, question suivante, recommencer). */
|
|
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;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
|
|
/* ===== 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;
|
|
}
|
|
}
|