obs/obs-mercredi-2.html

1609 lines
52 KiB
HTML
Raw 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">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Grille d'observation - Micro-teaching - Formation IA</title>
<!-- Tabler Icons CSS CDN -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/tabler-icons.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&family=DM+Sans:ital,wght@0,400;0,500;0,700;1,400&display=swap');
:root {
/* Theme core colors (Indigo/Violet) */
--primary-hsl: 247, 80%, 62%;
--primary: hsl(var(--primary-hsl));
--primary-light: hsl(247, 85%, 96%);
--primary-dark: hsl(247, 80%, 35%);
/* Neutral colors - Clean & Premium Cool Grays */
--bg-primary: #f8fafc;
--bg-secondary: #ffffff;
--bg-tertiary: #f1f5f9;
--color-text-primary: #0f172a;
--color-text-secondary: #475569;
--color-text-tertiary: #94a3b8;
--color-border-primary: #f1f5f9;
--color-border-secondary: #e2e8f0;
--color-border-tertiary: #e2e8f0;
--border-radius-sm: 8px;
--border-radius-md: 14px;
--border-radius-lg: 18px;
--shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.05), 0 1px 2px 0 rgba(0, 0, 0, 0.03);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.04), 0 2px 4px -2px rgba(0, 0, 0, 0.04);
--shadow-lg: 0 12px 20px -3px rgba(0, 0, 0, 0.05), 0 4px 8px -4px rgba(0, 0, 0, 0.05);
/* Warning Accent (Amber) */
--color-a-bg: hsl(36, 85%, 96%);
--color-a-border: hsl(36, 80%, 88%);
--color-a-accent: hsl(36, 90%, 45%);
--color-a-dark: hsl(36, 95%, 22%);
}
/* Header Right Container & Timer styles */
.header-right {
display: flex;
align-items: center;
gap: 16px;
flex-shrink: 0;
}
/* Timer Widget */
.timer-pill {
background: var(--primary-light);
border: 1px solid var(--color-a-border);
border-radius: var(--border-radius-md);
padding: 8px 18px;
display: flex;
align-items: center;
gap: 16px;
box-shadow: var(--shadow-md);
transition: all 0.3s ease;
}
.timer-texts {
display: flex;
flex-direction: column;
}
.timer-label {
font-size: 0.65rem;
font-weight: 800;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--primary-dark);
opacity: 0.8;
}
.timer-display {
font-size: 1.35rem;
font-weight: 900;
color: var(--primary-dark);
min-width: 60px;
line-height: 1.1;
text-align: center;
}
.timer-controls {
display: flex;
gap: 6px;
}
.tcbtn {
background: var(--bg-secondary);
border: 1px solid var(--color-border-secondary);
border-radius: 8px;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 0.95rem;
color: var(--color-text-primary);
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: var(--shadow-sm);
}
.tcbtn:hover {
background: var(--primary);
color: white;
border-color: var(--primary);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(117, 95, 236, 0.25);
}
.tcbtn:active {
transform: translateY(0);
}
@keyframes pulse-timer {
0% { box-shadow: 0 0 0 0 hsla(247, 80%, 62%, 0.4); }
70% { box-shadow: 0 0 0 10px hsla(247, 80%, 62%, 0); }
100% { box-shadow: 0 0 0 0 hsla(247, 80%, 62%, 0); }
}
.timer-pill.ticking {
animation: pulse-timer 2s infinite;
border-color: var(--primary);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-primary);
color: var(--color-text-primary);
font-family: 'Nunito', sans-serif;
transition: background-color 0.3s ease, color 0.3s ease;
min-height: 100vh;
display: flex;
flex-direction: column;
background-image:
radial-gradient(at 0% 0%, hsla(247, 80%, 62%, 0.04) 0px, transparent 50%),
radial-gradient(at 100% 0%, hsla(162, 75%, 34%, 0.01) 0px, transparent 50%),
radial-gradient(at 50% 100%, hsla(36, 90%, 45%, 0.02) 0px, transparent 50%);
background-attachment: fixed;
}
.fiche {
max-width: 960px;
width: 100%;
margin: 0 auto;
padding: 2.5rem 24px;
flex-grow: 1;
display: flex;
flex-direction: column;
}
/* Header */
.fiche-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1.5rem;
border-bottom: 1px solid var(--color-border-secondary);
padding-bottom: 1.5rem;
margin-bottom: 2rem;
}
.fiche-kicker {
font-size: 0.75rem;
font-weight: 800;
letter-spacing: .2em;
text-transform: uppercase;
color: var(--primary);
margin-bottom: 8px;
}
.fiche-title {
font-size: 2rem;
font-weight: 900;
color: var(--color-text-primary);
line-height: 1.2;
letter-spacing: -0.02em;
}
/* Identity input cards */
.identity-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 16px;
margin-bottom: 2rem;
}
.id-field {
display: flex;
flex-direction: column;
gap: 6px;
background: var(--bg-secondary);
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-md);
padding: 10px 14px;
box-shadow: var(--shadow-sm);
transition: all 0.25s ease;
}
.id-field:focus-within {
border-color: var(--primary);
box-shadow: 0 0 0 3px hsla(247, 80%, 62%, 0.12), var(--shadow-md);
}
.field-label {
font-size: 0.65rem;
font-weight: 800;
letter-spacing: .1em;
text-transform: uppercase;
color: var(--color-text-secondary);
}
.field-line {
border: none;
background: transparent;
font-family: 'DM Sans', sans-serif;
font-size: 0.9rem;
color: var(--color-text-primary);
padding: 2px 0 0 0;
width: 100%;
outline: none;
}
.field-line::placeholder {
color: var(--color-text-tertiary);
opacity: 0.7;
}
/* Instructions Notice block */
.notice {
background: var(--primary-light);
border-left: 4px solid var(--primary);
border-radius: 0 var(--border-radius-md) var(--border-radius-md) 0;
padding: 14px 20px;
margin-bottom: 2rem;
display: flex;
gap: 12px;
align-items: flex-start;
box-shadow: var(--shadow-sm);
}
.notice i {
color: var(--primary);
font-size: 1.3rem;
flex-shrink: 0;
margin-top: 1px;
}
.notice p {
font-size: 0.9rem;
color: var(--color-text-secondary);
line-height: 1.6;
}
.notice strong {
font-weight: 800;
color: var(--primary-dark);
}
/* Dimensions styling */
.dim-block {
margin-bottom: 2.5rem;
background: var(--bg-secondary);
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-lg);
overflow: hidden;
box-shadow: var(--shadow-sm);
transition: box-shadow 0.25s ease;
}
.dim-block:hover {
box-shadow: var(--shadow-md);
}
.dim-head {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 20px;
border-bottom: 1px solid var(--color-border-secondary);
}
.dim-icon {
width: 40px;
height: 40px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3rem;
flex-shrink: 0;
box-shadow: var(--shadow-sm);
}
/* Theme Contenu (Primary Violet) */
.dim-block.dim-contenu .dim-head {
background: var(--primary-light);
}
.dim-block.dim-contenu .dim-icon {
background: hsl(247, 85%, 90%);
color: var(--primary);
}
.dim-block.dim-contenu .dim-title {
color: var(--primary-dark);
}
/* Theme Methode (Emerald Green) */
.dim-block.dim-methode .dim-head {
background: hsl(162, 85%, 96%);
border-bottom-color: hsl(162, 80%, 90%);
}
.dim-block.dim-methode .dim-icon {
background: hsl(162, 85%, 90%);
color: hsl(162, 75%, 34%);
}
.dim-block.dim-methode .dim-title {
color: hsl(162, 80%, 20%);
}
/* Theme Posture (Amber/Orange) */
.dim-block.dim-posture .dim-head {
background: var(--color-a-bg);
border-bottom-color: var(--color-a-border);
}
.dim-block.dim-posture .dim-icon {
background: hsl(36, 85%, 90%);
color: var(--color-a-accent);
}
.dim-block.dim-posture .dim-title {
color: var(--color-a-dark);
}
.dim-meta {
flex: 1;
display: flex;
flex-direction: column;
}
.dim-num {
font-size: 0.65rem;
font-weight: 800;
letter-spacing: .1em;
text-transform: uppercase;
color: var(--color-text-tertiary);
margin-bottom: 2px;
}
.dim-title {
font-size: 1.15rem;
font-weight: 900;
}
.dim-q {
font-size: 0.85rem;
color: var(--color-text-secondary);
font-style: italic;
opacity: 0.9;
}
/* Criteria Grid inside dimension cards */
.crit-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
}
.crit {
border-right: 1px solid var(--color-border-secondary);
border-bottom: 1px solid var(--color-border-secondary);
padding: 20px;
display: flex;
flex-direction: column;
gap: 8px;
background: var(--bg-secondary);
transition: background-color 0.2s ease;
}
.crit:hover {
background: var(--bg-primary);
}
.crit:nth-child(2n) {
border-right: none;
}
.crit:nth-last-child(-n+2) {
border-bottom: none;
}
.crit-odd-last {
border-bottom: none !important;
}
.cl {
font-size: 0.7rem;
font-weight: 800;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--color-text-tertiary);
margin-bottom: 2px;
}
.cq {
font-size: 0.9rem;
font-weight: 800;
color: var(--color-text-primary);
line-height: 1.5;
margin-bottom: 4px;
}
/* Rating segment controller */
.scale-labels {
display: flex;
justify-content: space-between;
margin-top: 4px;
padding: 0 4px;
}
.sl-label {
font-size: 0.7rem;
font-weight: 700;
color: var(--color-text-tertiary);
text-transform: uppercase;
letter-spacing: .03em;
}
.scale-row {
display: flex;
gap: 8px;
margin-top: 6px;
margin-bottom: 8px;
}
.scale-opt {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
cursor: pointer;
background: var(--bg-primary);
border: 1px solid var(--color-border-secondary);
border-radius: 12px;
padding: 6px 12px;
flex: 1;
transition: all 0.2s ease;
}
.scale-opt:hover {
border-color: var(--primary);
background: var(--primary-light);
}
.scale-num {
font-size: 0.8rem;
font-weight: 800;
color: var(--color-text-primary);
}
.dim-contenu .scale-opt input[type="radio"] {
accent-color: var(--primary);
}
.dim-methode .scale-opt input[type="radio"] {
accent-color: hsl(162, 75%, 34%);
}
.dim-posture .scale-opt input[type="radio"] {
accent-color: var(--color-a-accent);
}
.scale-opt input[type="radio"] {
width: 15px;
height: 15px;
cursor: pointer;
}
/* Observator inputs (textareas) */
.obs-area {
width: 100%;
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-md);
background: var(--bg-primary);
font-family: 'DM Sans', sans-serif;
font-size: 0.875rem;
color: var(--color-text-primary);
padding: 10px 14px;
resize: vertical;
outline: none;
line-height: 1.55;
transition: all 0.25s ease;
}
.obs-area:focus {
border-color: var(--primary);
background: var(--bg-secondary);
box-shadow: 0 0 0 3px hsla(247, 80%, 62%, 0.12);
}
.obs-area::placeholder {
color: var(--color-text-tertiary);
font-style: italic;
opacity: 0.7;
}
.divider {
border: none;
border-top: 1px solid var(--color-border-secondary);
margin: 2.5rem 0 1.5rem 0;
}
/* Synthesis block styles */
.synth-block {
background: var(--bg-secondary);
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-sm);
margin-bottom: 2.5rem;
overflow: hidden;
transition: box-shadow 0.25s ease;
}
.synth-block:hover {
box-shadow: var(--shadow-md);
}
.synth-head {
background: var(--primary-light);
border-bottom: 1px solid var(--color-border-secondary);
padding: 14px 20px;
display: flex;
align-items: center;
gap: 10px;
}
.synth-head i {
color: var(--primary);
font-size: 1.25rem;
}
.synth-lbl {
font-size: 0.8rem;
font-weight: 800;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--primary-dark);
}
.synth-body {
padding: 20px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.sb-col {
display: flex;
flex-direction: column;
gap: 8px;
}
.sb-col-lbl {
font-size: 0.7rem;
font-weight: 800;
letter-spacing: .05em;
text-transform: uppercase;
color: var(--color-text-secondary);
}
/* Score Strip inside synthesis block */
.score-strip {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 12px;
padding: 20px;
background: var(--bg-tertiary);
border-top: 1px solid var(--color-border-secondary);
}
.sc-card {
background: var(--bg-secondary);
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-md);
padding: 12px;
text-align: center;
box-shadow: var(--shadow-sm);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 4px;
}
.sc-lbl {
font-size: 0.7rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: .05em;
color: var(--color-text-secondary);
}
.sc-val {
font-size: 1.5rem;
font-weight: 900;
color: var(--color-text-primary);
}
.sc-val.vc {
color: var(--primary);
}
.sc-val.vt {
color: hsl(162, 75%, 34%);
}
.sc-val.va {
color: var(--color-a-accent);
}
/* Section Headers */
.section-title {
font-size: 0.85rem;
font-weight: 800;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--primary);
margin: 2.5rem 0 1.5rem 0;
display: flex;
align-items: center;
gap: 10px;
}
.section-title i {
font-size: 1.2rem;
}
.section-title::after {
content: "";
flex: 1;
height: 1px;
background: var(--color-border-secondary);
opacity: 0.8;
}
/* Signature Section Styles */
.signature-block {
background: var(--bg-secondary);
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-lg);
padding: 24px;
box-shadow: var(--shadow-sm);
margin-bottom: 2rem;
transition: box-shadow 0.2s ease;
}
.signature-block:hover {
box-shadow: var(--shadow-md);
}
.signature-grid {
display: grid;
grid-template-columns: 1.5fr 1fr;
gap: 24px;
}
.signature-col {
display: flex;
flex-direction: column;
gap: 12px;
}
.signature-label {
font-size: 0.75rem;
font-weight: 800;
letter-spacing: .05em;
text-transform: uppercase;
color: var(--color-text-secondary);
}
.signature-pad-wrapper {
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-md);
background: var(--bg-primary);
padding: 12px;
display: flex;
flex-direction: column;
gap: 12px;
transition: all 0.25s ease;
}
.signature-pad-wrapper:focus-within {
border-color: var(--primary);
box-shadow: 0 0 0 3px hsla(247, 80%, 62%, 0.12);
}
.signature-pad {
width: 100%;
height: 180px;
background: #ffffff;
border-radius: var(--border-radius-sm);
border: 1px dashed var(--color-border-secondary);
cursor: crosshair;
touch-action: none;
}
.signature-pad-controls {
display: flex;
gap: 10px;
justify-content: flex-end;
}
.signature-btn {
font-family: 'Nunito', sans-serif;
font-size: 0.75rem;
font-weight: 700;
letter-spacing: .03em;
text-transform: uppercase;
background: var(--bg-secondary);
border: 1px solid var(--color-border-secondary);
color: var(--color-text-secondary);
border-radius: 8px;
padding: 8px 14px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: var(--shadow-sm);
}
.signature-btn:hover {
background: var(--bg-tertiary);
color: var(--color-text-primary);
transform: translateY(-1px);
}
.signature-btn.clear:hover {
background: #fee2e2;
color: #ef4444;
border-color: #fca5a5;
box-shadow: 0 2px 4px rgba(239, 68, 68, 0.1);
}
.signature-btn.save {
background: var(--primary);
border-color: var(--primary);
color: white;
}
.signature-btn.save:hover {
background: var(--primary-dark);
border-color: var(--primary-dark);
box-shadow: 0 4px 8px rgba(117, 95, 236, 0.25);
}
.date-col {
justify-content: space-between;
}
.signature-info-box {
background: var(--primary-light);
border: 1px solid var(--color-border-secondary);
border-radius: var(--border-radius-md);
padding: 16px;
display: flex;
gap: 12px;
align-items: flex-start;
}
.signature-info-box i {
color: var(--primary);
font-size: 1.25rem;
flex-shrink: 0;
margin-top: 2px;
}
.signature-info-box p {
font-size: 0.8rem;
color: var(--color-text-secondary);
line-height: 1.5;
}
/* Footer */
.footer-strip {
display: flex;
align-items: center;
justify-content: space-between;
border-top: 1px solid var(--color-border-secondary);
padding-top: 1.5rem;
margin-top: 3rem;
gap: 1.5rem;
flex-wrap: wrap;
}
.footer-note {
font-size: 0.85rem;
color: var(--color-text-secondary);
font-style: italic;
line-height: 1.5;
flex: 1;
max-width: 60%;
}
.print-btn {
font-family: 'Nunito', sans-serif;
font-size: 0.75rem;
font-weight: 800;
letter-spacing: .08em;
text-transform: uppercase;
background: var(--primary);
border: 1px solid var(--primary);
color: white;
border-radius: 10px;
padding: 10px 18px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
white-space: nowrap;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: var(--shadow-sm);
}
.print-btn:hover {
background: var(--primary-dark);
border-color: var(--primary-dark);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(117, 95, 236, 0.25);
}
.print-btn:active {
transform: translateY(0);
}
/* Accessibility Utilities */
.sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
/* Responsive CSS Overrides for Signature */
@media (max-width: 860px) {
.signature-grid {
grid-template-columns: 1fr;
gap: 16px;
}
.date-col {
gap: 16px;
}
}
/* Print Styles for Signature */
@media print {
.signature-pad-controls {
display: none !important;
}
.signature-pad {
border: 1px solid #94a3b8 !important;
background: white !important;
}
.signature-block {
page-break-inside: avoid;
border: 1px solid #94a3b8 !important;
background: white !important;
box-shadow: none !important;
}
.signature-info-box {
border: 1px solid #94a3b8 !important;
background: white !important;
}
}
/* Responsive CSS Overrides */
@media (max-width: 860px) {
.fiche {
padding: 1.5rem 16px;
}
.fiche-header {
flex-direction: column;
align-items: stretch;
gap: 1rem;
}
.header-right {
flex-direction: row;
justify-content: space-between;
width: 100%;
gap: 12px;
}
.identity-row {
grid-template-columns: 1fr;
gap: 12px;
}
.crit-grid {
grid-template-columns: 1fr;
}
.crit {
border-right: none;
}
.crit:nth-last-child(-n+2) {
border-bottom: 1px solid var(--color-border-secondary);
}
.crit:last-child {
border-bottom: none;
}
.synth-body {
grid-template-columns: 1fr;
gap: 16px;
}
.score-strip {
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.footer-strip {
flex-direction: column;
align-items: flex-start;
gap: 1rem;
}
.footer-note {
max-width: 100%;
}
.footer-btns {
flex-direction: column;
width: 100%;
gap: 8px;
}
.footer-btns button {
width: 100%;
justify-content: center;
}
}
/* Print Styles Overrides */
@media print {
body {
background: white !important;
color: black !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.print-btn, .timer-pill {
display: none !important;
}
.dim-block, .synth-block {
page-break-inside: avoid;
border: 1px solid #94a3b8 !important;
background: white !important;
box-shadow: none !important;
}
.obs-area {
background: white !important;
border: 1px solid #94a3b8 !important;
resize: none;
}
.crit {
page-break-inside: avoid;
}
.scale-opt {
border: 1px solid #94a3b8 !important;
background: white !important;
}
.id-field {
border: 1px solid #94a3b8 !important;
background: white !important;
box-shadow: none !important;
}
}
</style>
</head>
<body>
<div class="fiche">
<!-- Accessibility Hidden Title -->
<h2 class="sr-only">Grille d'observation complète pour les micro-teachings du Mercredi 2, 3 dimensions Contenu, Méthode, Posture avec critères et zones de saisie, et synthèse de débrief</h2>
<!-- Header -->
<div class="fiche-header">
<div class="header-left">
<div class="fiche-kicker">Mercredi 2 · Micro-teaching UF1 / UF2 · Grille observateur</div>
<div class="fiche-title">Grille d'observation<br />micro-teaching</div>
</div>
<div class="header-right">
<!-- Timer widget -->
<div class="timer-pill" id="timer-widget">
<div class="timer-texts">
<span class="timer-label">Minuteur passage</span>
<span class="timer-display" id="timer-display">10:00</span>
</div>
<div class="timer-controls">
<button class="tcbtn" onclick="startTimer()" aria-label="Démarrer le minuteur">
<i class="ti ti-player-play" aria-hidden="true"></i>
</button>
<button class="tcbtn" onclick="pauseTimer()" aria-label="Pause">
<i class="ti ti-player-pause" aria-hidden="true"></i>
</button>
<button class="tcbtn" onclick="resetTimer()" aria-label="Réinitialiser">
<i class="ti ti-refresh" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Identity card row -->
<div class="identity-row">
<div class="id-field">
<span class="field-label">Formateur observé</span>
<input class="field-line" type="text" placeholder="Prénom Nom" />
</div>
<div class="id-field">
<span class="field-label">Séquence animée</span>
<input class="field-line" type="text" placeholder="Ex. : UF2 Prompt Engineering" />
</div>
<div class="id-field">
<span class="field-label">Observateur</span>
<input class="field-line" type="text" placeholder="Prénom Nom" />
</div>
</div>
<!-- Informative Notice block -->
<div class="notice">
<i class="ti ti-info-circle" aria-hidden="true"></i>
<p>Notez vos observations <strong>pendant</strong> le passage, pas après. Pour chaque critère : cochez le niveau observé (1 = absent ou insuffisant · 4 = excellent) puis notez un exemple concret dans la zone de texte. Le débrief ne dure que 5 min — préparez 1 point fort + 1 axe prioritaire avant de parler.</p>
</div>
<!-- Dimension 1: Contenu -->
<div class="dim-block dim-contenu">
<div class="dim-head">
<div class="dim-icon"><i class="ti ti-file-text" aria-hidden="true"></i></div>
<div class="dim-meta">
<div class="dim-num">Dimension 1</div>
<div class="dim-title">Contenu</div>
</div>
<div class="dim-q">Ce qui est transmis — exactitude, hiérarchisation, complétude</div>
</div>
<div class="crit-grid">
<div class="crit">
<div class="cl">Cr1.1</div>
<div class="cq">Les points clés de la séquence sont couverts sans omission importante</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr1.1">
<label class="scale-opt"><input type="radio" name="c11" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c11" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c11" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c11" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr1.1"></textarea>
</div>
<div class="crit">
<div class="cl">Cr1.2</div>
<div class="cq">Aucune erreur factuelle — les informations sur l'IA et les outils sont exactes</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr1.2">
<label class="scale-opt"><input type="radio" name="c12" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c12" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c12" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c12" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr1.2"></textarea>
</div>
<div class="crit">
<div class="cl">Cr1.3</div>
<div class="cq">La hiérarchisation est claire : l'essentiel est mis en avant, l'accessoire reste secondaire</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr1.3">
<label class="scale-opt"><input type="radio" name="c13" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c13" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c13" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c13" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr1.3"></textarea>
</div>
<div class="crit">
<div class="cl">Cr1.4</div>
<div class="cq">Au moins un exemple concret ancré dans un contexte professionnel réel est utilisé</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr1.4">
<label class="scale-opt"><input type="radio" name="c14" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c14" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c14" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c14" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr1.4"></textarea>
</div>
</div>
</div>
<!-- Dimension 2: Méthode -->
<div class="dim-block dim-methode">
<div class="dim-head">
<div class="dim-icon"><i class="ti ti-tools" aria-hidden="true"></i></div>
<div class="dim-meta">
<div class="dim-num">Dimension 2</div>
<div class="dim-title">Méthode</div>
</div>
<div class="dim-q">Comment c'est animé — choix pédagogique, gestion du temps, clarté des consignes</div>
</div>
<div class="crit-grid">
<div class="crit">
<div class="cl">Cr2.1</div>
<div class="cq">La méthode choisie sert le contenu (démo, échanges, atelier) — elle n'est pas arbitraire</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr2.1">
<label class="scale-opt"><input type="radio" name="c21" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c21" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c21" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c21" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr2.1"></textarea>
</div>
<div class="crit">
<div class="cl">Cr2.2</div>
<div class="cq">Le temps est respecté — le formateur sait accélérer ou couper sans perdre le fil</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr2.2">
<label class="scale-opt"><input type="radio" name="c22" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c22" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c22" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c22" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr2.2"></textarea>
</div>
<div class="crit">
<div class="cl">Cr2.3</div>
<div class="cq">Les consignes sont claires et sans ambiguïté — un apprenant saurait quoi faire sans relancer</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr2.3">
<label class="scale-opt"><input type="radio" name="c23" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c23" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c23" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c23" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr2.3"></textarea>
</div>
<div class="crit">
<div class="cl">Cr2.4</div>
<div class="cq">L'imprévu est géré — question hors sujet, silence, problème technique — sans déstabilisation visible</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr2.4">
<label class="scale-opt"><input type="radio" name="c24" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c24" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c24" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c24" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr2.4"></textarea>
</div>
</div>
</div>
<!-- Dimension 3: Posture -->
<div class="dim-block dim-posture">
<div class="dim-head">
<div class="dim-icon"><i class="ti ti-user-check" aria-hidden="true"></i></div>
<div class="dim-meta">
<div class="dim-num">Dimension 3</div>
<div class="dim-title">Posture</div>
</div>
<div class="dim-q">Comment le formateur est présent — engagement, écoute, crédibilité</div>
</div>
<div class="crit-grid">
<div class="crit">
<div class="cl">Cr3.1</div>
<div class="cq">Le groupe est engagé — le formateur crée de l'interaction, pas un monologue à sens unique</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr3.1">
<label class="scale-opt"><input type="radio" name="c31" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c31" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c31" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c31" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr3.1"></textarea>
</div>
<div class="crit">
<div class="cl">Cr3.2</div>
<div class="cq">La posture est cohérente avec la séquence — expert, facilitateur ou praticien selon ce qui est enseigné</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr3.2">
<label class="scale-opt"><input type="radio" name="c32" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c32" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c32" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c32" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr3.2"></textarea>
</div>
<div class="crit">
<div class="cl">Cr3.3</div>
<div class="cq">Le formateur assume ses zones d'incertitude sans perdre en crédibilité — il ne survend pas</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr3.3">
<label class="scale-opt"><input type="radio" name="c33" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c33" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c33" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c33" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr3.3"></textarea>
</div>
<div class="crit">
<div class="cl">Cr3.4</div>
<div class="cq">L'écoute est active — les réponses du groupe sont reprises et valorisées, pas ignorées</div>
<div class="scale-labels"><span class="sl-label">Absent</span><span class="sl-label">Excellent</span></div>
<div class="scale-row" role="radiogroup" aria-label="Cr3.4">
<label class="scale-opt"><input type="radio" name="c34" value="1" /><span class="scale-num">1</span></label>
<label class="scale-opt"><input type="radio" name="c34" value="2" /><span class="scale-num">2</span></label>
<label class="scale-opt"><input type="radio" name="c34" value="3" /><span class="scale-num">3</span></label>
<label class="scale-opt"><input type="radio" name="c34" value="4" /><span class="scale-num">4</span></label>
</div>
<textarea class="obs-area" rows="2" placeholder="Ce que j'ai observé…" aria-label="Observation Cr3.4"></textarea>
</div>
</div>
</div>
<!-- Synthesis for Debriefing -->
<div class="synth-block">
<div class="synth-head">
<i class="ti ti-message-dots" aria-hidden="true"></i>
<span class="synth-lbl">Synthèse pour le débrief — à préparer avant de parler</span>
</div>
<div class="synth-body">
<div class="sb-col">
<div class="sb-col-lbl">1 point fort (à dire en premier)</div>
<textarea class="obs-area" rows="3" placeholder="Ce que le formateur a vraiment bien fait — soyez précis, pas générique…" aria-label="Point fort pour le débrief"></textarea>
</div>
<div class="sb-col">
<div class="sb-col-lbl">1 axe prioritaire (1 seul)</div>
<textarea class="obs-area" rows="3" placeholder="La chose la plus utile à améliorer — formulée comme une suggestion, pas un reproche…" aria-label="Axe d'amélioration pour le débrief"></textarea>
</div>
<div class="sb-col">
<div class="sb-col-lbl">Moment précis à illustrer</div>
<textarea class="obs-area" rows="3" placeholder="Le moment exact (minute, phrase, geste) qui illustre votre feedback…" aria-label="Moment précis à illustrer"></textarea>
</div>
<div class="sb-col">
<div class="sb-col-lbl">Question à poser au formateur</div>
<textarea class="obs-area" rows="3" placeholder="Ce que vous voulez lui demander sur ses propres ressentis ou choix…" aria-label="Question pour le débrief"></textarea>
</div>
</div>
<!-- Score Strip -->
<div class="score-strip" id="score-strip">
<div class="sc-card">
<div class="sc-lbl">Contenu /16</div>
<div class="sc-val vc" id="sc-c"></div>
</div>
<div class="sc-card">
<div class="sc-lbl">Méthode /16</div>
<div class="sc-val vt" id="sc-m"></div>
</div>
<div class="sc-card">
<div class="sc-lbl">Posture /16</div>
<div class="sc-val va" id="sc-p"></div>
</div>
<div class="sc-card">
<div class="sc-lbl">Total /48</div>
<div class="sc-val" id="sc-t"></div>
</div>
</div>
</div>
<!-- PART 4 -->
<div class="section-title">
<i class="ti ti-edit" aria-hidden="true"></i>Signature de l'observateur
</div>
<div class="signature-block">
<div class="signature-grid">
<div class="signature-col">
<div class="signature-label">Signature de l'observateur</div>
<div class="signature-pad-wrapper">
<canvas class="signature-pad" id="signature-pad"></canvas>
<div class="signature-pad-controls">
<button type="button" class="signature-btn clear" onclick="clearSignature()">
<i class="ti ti-trash" aria-hidden="true"></i> Effacer
</button>
<button type="button" class="signature-btn save" onclick="saveSignature()">
<i class="ti ti-circle-check" aria-hidden="true"></i> Enregistrer
</button>
</div>
</div>
</div>
<div class="signature-col date-col">
<div class="id-field">
<span class="field-label">Date d'observation</span>
<input type="text" class="field-line" placeholder="__/__/____" id="signature-date" />
</div>
<div class="signature-info-box">
<i class="ti ti-info-circle" aria-hidden="true"></i>
<p>Cette signature valide officiellement la grille d'observation et le débriefing du micro-teaching effectué.</p>
</div>
</div>
</div>
</div>
<!-- Footer strip with clear and print button -->
<div class="footer-strip">
<div class="footer-note">À remettre au formateur référent après le débrief. Une grille par observateur par passage.</div>
<div class="footer-btns">
<button class="signature-btn clear" onclick="clearAll()">
<i class="ti ti-eraser" aria-hidden="true"></i> Effacer toutes les saisies
</button>
<button class="print-btn" onclick="window.print()">
<i class="ti ti-printer" aria-hidden="true"></i>Imprimer la grille
</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('signature-pad');
const ctx = canvas.getContext('2d');
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let ratio = Math.max(window.devicePixelRatio || 1, 1);
// Fonction optimisée pour le redimensionnement du canvas
function resizeCanvas() {
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * ratio;
canvas.height = rect.height * ratio;
canvas.style.width = rect.width + 'px';
canvas.style.height = rect.height + 'px';
ctx.scale(ratio, ratio);
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.strokeStyle = '#0f172a';
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// Initialisation du canvas
function initCanvas() {
const resizeObserver = new ResizeObserver(() => {
resizeCanvas();
const savedSignature = localStorage.getItem('signatureData_obs_m2');
if (savedSignature) {
const img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0, canvas.width / ratio, canvas.height / ratio);
};
img.src = savedSignature;
}
});
resizeObserver.observe(canvas);
resizeCanvas();
}
// Fonctions de dessin optimisées
function startDrawing(e) {
isDrawing = true;
const rect = canvas.getBoundingClientRect();
lastX = (e.clientX || e.touches[0].clientX) - rect.left;
lastY = (e.clientY || e.touches[0].clientY) - rect.top;
}
function draw(e) {
if (!isDrawing) return;
const rect = canvas.getBoundingClientRect();
const currentX = (e.clientX || e.touches[0].clientX) - rect.left;
const currentY = (e.clientY || e.touches[0].clientY) - rect.top;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(currentX, currentY);
ctx.stroke();
[lastX, lastY] = [currentX, currentY];
}
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', () => { isDrawing = false; });
canvas.addEventListener('mouseout', () => { isDrawing = false; });
canvas.addEventListener('touchstart', function(e) {
e.preventDefault();
startDrawing(e);
}, { passive: false });
canvas.addEventListener('touchmove', function(e) {
e.preventDefault();
draw(e);
}, { passive: false });
canvas.addEventListener('touchend', () => { isDrawing = false; });
// Fonctions de gestion de la signature
window.clearSignature = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
localStorage.removeItem('signatureData_obs_m2');
};
window.saveSignature = function() {
const signatureData = canvas.toDataURL('image/png');
localStorage.setItem('signatureData_obs_m2', signatureData);
return signatureData;
};
const savedSignature = localStorage.getItem('signatureData_obs_m2');
if (savedSignature) {
const img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0, canvas.width / ratio, canvas.height / ratio);
};
img.src = savedSignature;
}
// Date de signature
const signatureDate = document.getElementById('signature-date');
const savedDate = localStorage.getItem('signatureDate_obs_m2');
if (savedDate) signatureDate.value = savedDate;
signatureDate.addEventListener('input', () => {
localStorage.setItem('signatureDate_obs_m2', signatureDate.value);
});
// Initialiser le canvas & les scores au démarrage
initCanvas();
updateScores();
});
</script>
<!-- Active Auto-save & Scores computation script -->
<script>
// Score calculation logic
const DIMS = {
c: ['c11', 'c12', 'c13', 'c14'],
m: ['c21', 'c22', 'c23', 'c24'],
p: ['c31', 'c32', 'c33', 'c34']
};
function calcScore(keys) {
let t = 0, n = 0;
keys.forEach(k => {
const v = document.querySelector('input[name=' + k + ']:checked');
if (v) {
t += parseInt(v.value);
n++;
}
});
return n === keys.length ? t : null;
}
function updateScores() {
const c = calcScore(DIMS.c), m = calcScore(DIMS.m), p = calcScore(DIMS.p);
document.getElementById('sc-c').textContent = c !== null ? c : '—';
document.getElementById('sc-m').textContent = m !== null ? m : '—';
document.getElementById('sc-p').textContent = p !== null ? p : '—';
document.getElementById('sc-t').textContent = (c !== null && m !== null && p !== null) ? (c + m + p) : '—';
}
// Auto-save & Load for Textareas
const textareas = document.querySelectorAll('textarea');
textareas.forEach((t, index) => {
const savedVal = localStorage.getItem(`textarea_obs_m2_${index}`);
if (savedVal) t.value = savedVal;
t.addEventListener('input', () => {
localStorage.setItem(`textarea_obs_m2_${index}`, t.value);
});
});
// Auto-save & Load for Text Inputs
const textInputs = document.querySelectorAll('input[type="text"]');
textInputs.forEach((input, index) => {
if (input.id === 'signature-date') return;
const savedVal = localStorage.getItem(`input_obs_m2_${index}`);
if (savedVal) input.value = savedVal;
input.addEventListener('input', () => {
localStorage.setItem(`input_obs_m2_${index}`, input.value);
});
});
// Auto-save & Load for Radio Ratings
const radios = document.querySelectorAll('input[type="radio"]');
radios.forEach((radio) => {
const savedVal = localStorage.getItem(`radio_obs_m2_${radio.name}`);
if (savedVal && radio.value === savedVal) {
radio.checked = true;
}
radio.addEventListener('change', () => {
localStorage.setItem(`radio_obs_m2_${radio.name}`, radio.value);
updateScores();
});
});
// Clear All Function
window.clearAll = function() {
if (!confirm('Effacer toutes les saisies de cette grille d\'observation ?')) return;
document.querySelectorAll('textarea').forEach(t => t.value = '');
document.querySelectorAll('input[type=radio]').forEach(r => r.checked = false);
document.querySelectorAll('.field-line').forEach(i => i.value = '');
if (typeof clearSignature === 'function') {
clearSignature();
}
const sigDateEl = document.getElementById('signature-date');
if (sigDateEl) sigDateEl.value = '';
updateScores();
// Remove from localStorage
const keysToRemove = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key && (key.startsWith('textarea_obs_m2_') || key.startsWith('input_obs_m2_') || key.startsWith('radio_obs_m2_') || key === 'signatureData_obs_m2' || key === 'signatureDate_obs_m2')) {
keysToRemove.push(key);
}
}
keysToRemove.forEach(k => localStorage.removeItem(k));
};
// Timer Logic (10 minutes passage)
let secs = 600, interval = null;
function fmt(s) {
const m = Math.floor(s / 60), ss = s % 60;
return String(m).padStart(2, '0') + ':' + String(ss).padStart(2, '0');
}
function renderTimer() {
document.getElementById('timer-display').textContent = fmt(secs);
}
function startTimer() {
if (interval) return;
document.getElementById('timer-widget').classList.add('ticking');
interval = setInterval(() => {
if (secs <= 0) {
clearInterval(interval);
interval = null;
document.getElementById('timer-widget').classList.remove('ticking');
document.getElementById('timer-display').textContent = 'Temps !';
return;
}
secs--;
renderTimer();
}, 1000);
}
function pauseTimer() {
clearInterval(interval);
interval = null;
document.getElementById('timer-widget').classList.remove('ticking');
}
function resetTimer() {
clearInterval(interval);
interval = null;
secs = 600;
document.getElementById('timer-widget').classList.remove('ticking');
renderTimer();
}
</script>
</body>
</html>