{"id":173,"date":"2026-05-01T18:06:09","date_gmt":"2026-05-01T18:06:09","guid":{"rendered":"http:\/\/premierssurplace.be\/?page_id=173"},"modified":"2026-05-01T18:06:09","modified_gmt":"2026-05-01T18:06:09","slug":"jeu-2","status":"publish","type":"page","link":"http:\/\/premierssurplace.be\/?page_id=173","title":{"rendered":"Jeu"},"content":{"rendered":"\n<style>\n  \/* \u2500\u2500 Design Tokens \u2500\u2500 *\/\n  :root {\n    --font-body: 'Satoshi', 'Helvetica Neue', sans-serif;\n    --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);\n    --text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);\n    --text-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);\n    --text-lg: clamp(1.125rem, 1rem + 0.75vw, 1.5rem);\n    --text-xl: clamp(1.5rem, 1.2rem + 1.25vw, 2.25rem);\n    --text-2xl: clamp(2rem, 1.2rem + 2.5vw, 3.5rem);\n    --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem;\n    --space-5: 1.25rem; --space-6: 1.5rem; --space-8: 2rem; --space-10: 2.5rem;\n    --space-12: 3rem; --space-16: 4rem;\n    --radius-sm: 0.375rem; --radius-md: 0.5rem; --radius-lg: 0.75rem;\n    --radius-xl: 1rem; --radius-full: 9999px;\n    --transition-interactive: 180ms cubic-bezier(0.16, 1, 0.3, 1);\n\n    \/* Couleurs \u2013 th\u00e8me m\u00e9dical rouge\/blanc avec accent vert *\/\n    --color-bg: #f7f6f2;\n    --color-surface: #ffffff;\n    --color-surface-2: #f9f8f5;\n    --color-border: oklch(0.2 0.01 80 \/ 0.12);\n    --color-text: #1a1a1a;\n    --color-text-muted: #6b6b6b;\n    --color-text-faint: #a0a0a0;\n    --color-primary: #c0392b;\n    --color-primary-hover: #96281b;\n    --color-primary-light: #fdecea;\n    --color-success: #27ae60;\n    --color-success-hover: #1e8449;\n    --color-success-light: #eafaf1;\n    --color-warning: #e67e22;\n    --color-warning-light: #fef5ec;\n    --color-beat: #c0392b;\n    --shadow-sm: 0 1px 3px oklch(0.2 0.01 80 \/ 0.08);\n    --shadow-md: 0 4px 16px oklch(0.2 0.01 80 \/ 0.1);\n    --shadow-lg: 0 12px 40px oklch(0.2 0.01 80 \/ 0.14);\n  }\n\n  \/* \u2500\u2500 Base \u2500\u2500 *\/\n  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n  html { -webkit-font-smoothing: antialiased; }\n  body {\n    font-family: var(--font-body);\n    font-size: var(--text-base);\n    color: var(--color-text);\n    background: var(--color-bg);\n    min-height: 100vh;\n    padding: var(--space-6) var(--space-4);\n  }\n  button { cursor: pointer; border: none; background: none; font: inherit; }\n\n.page-header {\ndisplay: none;\n}\n\n.page-content {\ndisplay: flex;\nflex-direction: column;\nalign-items: center;\n}\n\n.wp-block-button__link {\ncolor: white;\nmargin-top: 20px;\n}\n  \/* \u2500\u2500 Layout \u2500\u2500 *\/\n  .game-wrapper {\n    width: 100%;\n    max-width: 560px;\n    display: flex;\n    flex-direction: column;\n    gap: var(--space-6);\n  }\n\n  \/* \u2500\u2500 Header \u2500\u2500 *\/\n  .game-header { text-align: center; }\n  .game-logo {\n    display: inline-flex;\n    align-items: center;\n    gap: var(--space-2);\n    margin-bottom: var(--space-4);\n  }\n  .game-logo svg { color: var(--color-primary); }\n  .game-title {\n    font-size: var(--text-xl);\n    font-weight: 700;\n    color: var(--color-text);\n    line-height: 1.15;\n  }\n  .game-subtitle {\n    font-size: var(--text-sm);\n    color: var(--color-text-muted);\n    margin-top: var(--space-2);\n    max-width: 42ch;\n    margin-inline: auto;\n  }\n\n  \/* \u2500\u2500 Card \u2500\u2500 *\/\n  .card {\n    background: var(--color-surface);\n    border-radius: var(--radius-xl);\n    box-shadow: var(--shadow-md);\n    padding: var(--space-8);\n    border: 1px solid var(--color-border);\n  }\n\n  \/* \u2500\u2500 Minuteur \u2500\u2500 *\/\n  .timer-ring-wrap {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    gap: var(--space-4);\n    margin-bottom: var(--space-6);\n  }\n  .timer-ring {\n    position: relative;\n    width: 120px;\n    height: 120px;\n  }\n  .timer-ring svg { transform: rotate(-90deg); }\n  .timer-ring circle.track {\n    fill: none;\n    stroke: var(--color-primary-light);\n    stroke-width: 8;\n  }\n  .timer-ring circle.progress {\n    fill: none;\n    stroke: var(--color-primary);\n    stroke-width: 8;\n    stroke-linecap: round;\n    stroke-dasharray: 314;\n    stroke-dashoffset: 0;\n    transition: stroke-dashoffset 0.25s linear;\n  }\n  .timer-value {\n    position: absolute;\n    inset: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: var(--text-xl);\n    font-weight: 700;\n    color: var(--color-primary);\n    line-height: 1;\n  }\n  .timer-label {\n    font-size: var(--text-xs);\n    color: var(--color-text-muted);\n    text-transform: uppercase;\n    letter-spacing: 0.08em;\n    font-weight: 500;\n  }\n\n  \/* \u2500\u2500 Zone de clic \u2500\u2500 *\/\n  .click-zone-wrap {\n    position: relative;\n    border-radius: var(--radius-lg);\n    overflow: hidden;\n    cursor: pointer;\n    user-select: none;\n    -webkit-tap-highlight-color: transparent;\n  }\n  .click-zone-img {\n    width: 100%;\n    aspect-ratio: 3\/2;\n    object-fit: cover;\n    display: block;\n    border-radius: var(--radius-lg);\n    pointer-events: none;\n  }\n  .click-zone-overlay {\n    position: absolute;\n    inset: 0;\n    border-radius: var(--radius-lg);\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    gap: var(--space-3);\n    background: oklch(0.08 0 0 \/ 0.42);\n    backdrop-filter: blur(2px);\n    transition: background var(--transition-interactive);\n  }\n  .click-zone-wrap.active .click-zone-overlay {\n    background: oklch(0.08 0 0 \/ 0.18);\n  }\n  .click-zone-overlay-text {\n    color: #fff;\n    font-weight: 700;\n    font-size: var(--text-lg);\n    text-align: center;\n    text-shadow: 0 2px 8px oklch(0 0 0 \/ 0.5);\n    padding: var(--space-2) var(--space-4);\n  }\n  .click-zone-overlay-sub {\n    color: oklch(1 0 0 \/ 0.75);\n    font-size: var(--text-sm);\n    text-align: center;\n    text-shadow: 0 1px 4px oklch(0 0 0 \/ 0.4);\n  }\n\n  \/* Ripple au clic *\/\n  .ripple {\n    position: absolute;\n    border-radius: 50%;\n    width: 60px;\n    height: 60px;\n    background: oklch(1 0 0 \/ 0.45);\n    transform: translate(-50%, -50%) scale(0);\n    animation: ripple-anim 0.45s ease-out forwards;\n    pointer-events: none;\n  }\n  @keyframes ripple-anim {\n    to { transform: translate(-50%, -50%) scale(3.5); opacity: 0; }\n  }\n\n  \/* Pulsation c\u0153ur pendant la session *\/\n  @keyframes heartbeat {\n    0%,100% { transform: scale(1); }\n    15% { transform: scale(1.18); }\n    30% { transform: scale(1); }\n    45% { transform: scale(1.1); }\n    60% { transform: scale(1); }\n  }\n  .click-zone-wrap.active .click-zone-overlay-text {\n    animation: heartbeat 0.6s ease-in-out;\n  }\n\n  \/* \u2500\u2500 Stats bar \u2500\u2500 *\/\n  .stats-row {\n    display: grid;\n    grid-template-columns: 1fr 1fr 1fr;\n    gap: var(--space-3);\n    margin-top: var(--space-5);\n  }\n  .stat-item {\n    background: var(--color-surface-2);\n    border-radius: var(--radius-md);\n    padding: var(--space-3) var(--space-2);\n    text-align: center;\n    border: 1px solid var(--color-border);\n  }\n  .stat-value {\n    font-size: var(--text-lg);\n    font-weight: 700;\n    color: var(--color-text);\n    font-variant-numeric: tabular-nums;\n    line-height: 1.2;\n  }\n  .stat-label {\n    font-size: var(--text-xs);\n    color: var(--color-text-muted);\n    margin-top: var(--space-1);\n    text-transform: uppercase;\n    letter-spacing: 0.06em;\n  }\n\n  \/* \u2500\u2500 Rythme visuel (m\u00e9tronome) \u2500\u2500 *\/\n  .beat-bar-wrap {\n    display: flex;\n    align-items: flex-end;\n    justify-content: center;\n    gap: 3px;\n    height: 28px;\n    margin-top: var(--space-4);\n  }\n  .beat-bar {\n    width: 6px;\n    background: oklch(from var(--color-primary) l c h \/ 0.18);\n    border-radius: 3px;\n    transition: height 0.12s ease, background 0.12s ease;\n    height: 4px;\n  }\n  .beat-bar.lit {\n    background: var(--color-primary);\n    height: 28px;\n  }\n\n  \/* \u2500\u2500 Guide rythme \u2500\u2500 *\/\n  .rhythm-guide {\n    display: flex;\n    align-items: center;\n    gap: var(--space-3);\n    padding: var(--space-3) var(--space-4);\n    background: oklch(from var(--color-primary) 0.96 0.01 30 \/ 1);\n    border-radius: var(--radius-md);\n    border: 1px solid oklch(from var(--color-primary) 0.88 0.04 30 \/ 1);\n    margin-top: var(--space-4);\n  }\n  .rhythm-dot {\n    width: 10px;\n    height: 10px;\n    border-radius: var(--radius-full);\n    background: var(--color-primary);\n    flex-shrink: 0;\n    transition: transform 0.1s ease, box-shadow 0.1s ease;\n  }\n  .rhythm-dot.pulse {\n    transform: scale(1.6);\n    box-shadow: 0 0 0 4px oklch(from var(--color-primary) l c h \/ 0.25);\n  }\n  .rhythm-text {\n    font-size: var(--text-xs);\n    color: var(--color-text-muted);\n    line-height: 1.4;\n  }\n  .rhythm-text strong { color: var(--color-text); font-weight: 600; }\n\n  \/* \u2500\u2500 Bouton start \u2500\u2500 *\/\n  .btn-start {\n    width: 100%;\n    padding: var(--space-4) var(--space-6);\n    background: var(--color-primary);\n    color: #fff;\n    font-size: var(--text-base);\n    font-weight: 700;\n    border-radius: var(--radius-lg);\n    box-shadow: var(--shadow-sm);\n    letter-spacing: 0.02em;\n    transition: background var(--transition-interactive), transform 0.1s ease, box-shadow var(--transition-interactive);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: var(--space-2);\n    margin-top: var(--space-6);\n  }\n  .btn-start:hover { background: var(--color-primary-hover); box-shadow: var(--shadow-md); }\n  .btn-start:active { transform: scale(0.98); }\n  .btn-start:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }\n\n  \/* \u2500\u2500 R\u00e9sultat \u2500\u2500 *\/\n  .result-panel {\n    border-radius: var(--radius-xl);\n    padding: var(--space-8);\n    border: 2px solid transparent;\n    box-shadow: var(--shadow-lg);\n    text-align: center;\n    display: none;\n    flex-direction: column;\n    align-items: center;\n    gap: var(--space-4);\n  }\n  .result-panel.show { display: flex; animation: fadeSlideUp 0.45s cubic-bezier(0.16,1,0.3,1); }\n  @keyframes fadeSlideUp {\n    from { opacity: 0; transform: translateY(16px); }\n    to   { opacity: 1; transform: translateY(0); }\n  }\n  .result-panel.good {\n    background: var(--color-success-light);\n    border-color: var(--color-success);\n  }\n  .result-panel.bad {\n    background: var(--color-primary-light);\n    border-color: var(--color-primary);\n  }\n  .result-panel.ok {\n    background: var(--color-warning-light);\n    border-color: var(--color-warning);\n  }\n  .result-icon { font-size: 3rem; line-height: 1; }\n  .result-title {\n    font-size: var(--text-xl);\n    font-weight: 700;\n    color: var(--color-text);\n  }\n  .result-body {\n    font-size: var(--text-base);\n    color: var(--color-text-muted);\n    max-width: 38ch;\n  }\n  .result-score {\n    font-size: var(--text-2xl);\n    font-weight: 700;\n    color: var(--color-text);\n    font-variant-numeric: tabular-nums;\n  }\n  .result-score span {\n    font-size: var(--text-sm);\n    font-weight: 500;\n    color: var(--color-text-muted);\n  }\n  .btn-retry {\n    padding: var(--space-3) var(--space-8);\n    background: var(--color-text);\n    color: #fff;\n    font-weight: 700;\n    font-size: var(--text-sm);\n    border-radius: var(--radius-full);\n    transition: background var(--transition-interactive);\n    margin-top: var(--space-2);\n  }\n  .btn-retry:hover { background: oklch(0.3 0 0); }\n\n  \/* \u2500\u2500 Info card \u2500\u2500 *\/\n  .info-card {\n    display: flex;\n    gap: var(--space-3);\n    align-items: flex-start;\n    padding: var(--space-4);\n    background: var(--color-surface);\n    border-radius: var(--radius-lg);\n    border: 1px solid var(--color-border);\n    box-shadow: var(--shadow-sm);\n  }\n  .info-card svg { color: var(--color-primary); flex-shrink: 0; margin-top: 2px; }\n  .info-card-text { font-size: var(--text-sm); color: var(--color-text-muted); line-height: 1.55; }\n  .info-card-text strong { color: var(--color-text); }\n\n  @media (max-width: 400px) {\n    .card { padding: var(--space-5); }\n    .stats-row { grid-template-columns: 1fr 1fr; }\n  }\n<\/style>\n<\/head>\n<body>\n\n<div class=\"game-wrapper\">\n\n  <!-- Header -->\n  <header class=\"game-header\">\n    <div class=\"game-logo\">\n      <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n        <path d=\"M12 21.593c-5.63-5.539-11-10.297-11-14.402C1 3.498 3.498 1 6.404 1c1.99 0 3.784 1.133 4.97 2.742C12.59 2.116 14.36 1 16.596 1 19.502 1 22 3.498 22 7.191c0 4.105-5.371 8.863-10 14.402z\"\/>\n      <\/svg>\n      <span style=\"font-weight:700;font-size:var(--text-lg);letter-spacing:-0.01em;\">Premiers sur Place<\/span>\n    <\/div>\n    <h1 class=\"game-title\">Testez votre rythme de RCP<\/h1>\n    <p class=\"game-subtitle\">Simulez les compressions thoraciques d&rsquo;un massage cardiaque&nbsp;: 100 clics par minute pendant 20 secondes.<\/p>\n  <\/header>\n\n  <!-- Jeu -->\n  <div class=\"card\" id=\"game-card\">\n\n    <!-- Timer ring -->\n    <div class=\"timer-ring-wrap\">\n      <div class=\"timer-ring\" aria-label=\"Temps restant\">\n        <svg width=\"120\" height=\"120\" viewBox=\"0 0 120 120\">\n          <circle class=\"track\" cx=\"60\" cy=\"60\" r=\"50\"\/>\n          <circle class=\"progress\" id=\"timer-arc\" cx=\"60\" cy=\"60\" r=\"50\"\/>\n        <\/svg>\n        <div class=\"timer-value\" id=\"timer-display\">20<\/div>\n      <\/div>\n      <div class=\"timer-label\">secondes restantes<\/div>\n    <\/div>\n\n    <!-- Zone de clic -->\n    <div class=\"click-zone-wrap\" id=\"click-zone\" role=\"button\" tabindex=\"0\"\n         aria-label=\"Zone de compression \u2013 cliquez ici au rythme d'un massage cardiaque\">\n      <!-- Illustration SVG inline d'un torse humain vue de face -->\n      <svg class=\"click-zone-img\" viewBox=\"0 0 560 373\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\">\n        <!-- Fond m\u00e9dical -->\n        <rect width=\"560\" height=\"373\" fill=\"#1a2744\"\/>\n        <!-- Grille subtile -->\n        <defs>\n          <pattern id=\"grid\" width=\"28\" height=\"28\" patternUnits=\"userSpaceOnUse\">\n            <path d=\"M 28 0 L 0 0 0 28\" fill=\"none\" stroke=\"rgba(255,255,255,0.04)\" stroke-width=\"1\"\/>\n          <\/pattern>\n        <\/defs>\n        <rect width=\"560\" height=\"373\" fill=\"url(#grid)\"\/>\n        <!-- Silhouette corps -->\n        <ellipse cx=\"280\" cy=\"100\" rx=\"52\" ry=\"60\" fill=\"#2d3f6b\" stroke=\"#4a6fa5\" stroke-width=\"1.5\"\/>\n        <!-- T\u00eate -->\n        <ellipse cx=\"280\" cy=\"52\" rx=\"34\" ry=\"38\" fill=\"#2d3f6b\" stroke=\"#4a6fa5\" stroke-width=\"1.5\"\/>\n        <!-- Torse principal -->\n        <path d=\"M228 148 C228 140 240 132 280 132 C320 132 332 140 332 148 L340 310 C340 316 336 320 330 320 L230 320 C224 320 220 316 220 310 Z\" fill=\"#2d3f6b\" stroke=\"#4a6fa5\" stroke-width=\"1.5\"\/>\n        <!-- C\u00f4tes gauches -->\n        <path d=\"M255 165 Q238 170 235 180\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <path d=\"M255 178 Q236 185 233 197\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <path d=\"M256 191 Q237 200 235 213\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <path d=\"M257 204 Q239 215 238 228\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <!-- C\u00f4tes droites -->\n        <path d=\"M305 165 Q322 170 325 180\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <path d=\"M305 178 Q324 185 327 197\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <path d=\"M304 191 Q323 200 325 213\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <path d=\"M303 204 Q321 215 322 228\" stroke=\"#4a6fa5\" stroke-width=\"1.2\" fill=\"none\" opacity=\"0.7\"\/>\n        <!-- Sternum -->\n        <line x1=\"280\" y1=\"155\" x2=\"280\" y2=\"235\" stroke=\"#4a6fa5\" stroke-width=\"2\" opacity=\"0.6\"\/>\n        <!-- Bras gauche -->\n        <path d=\"M228 148 L200 160 L190 240 L205 242 L215 175 L232 165 Z\" fill=\"#2d3f6b\" stroke=\"#4a6fa5\" stroke-width=\"1.5\"\/>\n        <!-- Bras droit -->\n        <path d=\"M332 148 L360 160 L370 240 L355 242 L345 175 L328 165 Z\" fill=\"#2d3f6b\" stroke=\"#4a6fa5\" stroke-width=\"1.5\"\/>\n\n        <!-- Zone cible rouge pulsante -->\n        <circle cx=\"280\" cy=\"200\" r=\"38\" fill=\"rgba(192,57,43,0.15)\" stroke=\"#c0392b\" stroke-width=\"2\" stroke-dasharray=\"6 3\"\/>\n        <circle cx=\"280\" cy=\"200\" r=\"22\" fill=\"rgba(192,57,43,0.25)\" stroke=\"#c0392b\" stroke-width=\"1.5\"\/>\n\n        <!-- Croix m\u00e9dicale sur la zone cible -->\n        <rect x=\"272\" y=\"192\" width=\"16\" height=\"5\" rx=\"2.5\" fill=\"#e74c3c\"\/>\n        <rect x=\"277.5\" y=\"187\" width=\"5\" height=\"16\" rx=\"2.5\" fill=\"#e74c3c\"\/>\n\n        <!-- ECG line en bas -->\n        <polyline points=\"0,350 60,350 80,330 95,365 110,315 125,370 140,350 560,350\"\n          fill=\"none\" stroke=\"#27ae60\" stroke-width=\"2\" opacity=\"0.6\"\/>\n\n        <!-- Label indicateur -->\n        <text x=\"280\" y=\"258\" text-anchor=\"middle\" fill=\"#c0392b\" font-size=\"11\" font-family=\"Satoshi,sans-serif\" font-weight=\"700\" letter-spacing=\"1\">ZONE DE COMPRESSION<\/text>\n      <\/svg>\n\n      <div class=\"click-zone-overlay\" id=\"overlay\">\n        <div class=\"click-zone-overlay-text\" id=\"overlay-text\">\u25b6 Cliquez pour commencer<\/div>\n        <div class=\"click-zone-overlay-sub\" id=\"overlay-sub\">Appuyez sur la zone marqu\u00e9e<\/div>\n      <\/div>\n    <\/div>\n\n    <!-- Rythme visuel barres -->\n    <div class=\"beat-bar-wrap\" id=\"beat-bars\"><\/div>\n\n    <!-- Guide rythme -->\n    <div class=\"rhythm-guide\">\n      <div class=\"rhythm-dot\" id=\"rhythm-dot\"><\/div>\n      <div class=\"rhythm-text\">\n        <strong>Rythme cible&nbsp;:<\/strong> 100 compressions\/min\n        \u2014 soit <strong>1 clic toutes les 0,6 s<\/strong> (\u2669 = 100 bpm).\n        Suivez le point rouge.\n      <\/div>\n    <\/div>\n\n    <!-- Stats -->\n    <div class=\"stats-row\">\n      <div class=\"stat-item\">\n        <div class=\"stat-value\" id=\"stat-clicks\">0<\/div>\n        <div class=\"stat-label\">Clics<\/div>\n      <\/div>\n      <div class=\"stat-item\">\n        <div class=\"stat-value\" id=\"stat-bpm\">\u2014<\/div>\n        <div class=\"stat-label\">BPM actuel<\/div>\n      <\/div>\n      <div class=\"stat-item\">\n        <div class=\"stat-value\" id=\"stat-target\" style=\"color:var(--color-primary);\">100<\/div>\n        <div class=\"stat-label\">BPM cible<\/div>\n      <\/div>\n    <\/div>\n\n    <!-- Bouton reset (cach\u00e9 au d\u00e9part) -->\n    <button class=\"btn-start\" id=\"btn-start\">\n      <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" aria-hidden=\"true\">\n        <polygon points=\"5 3 19 12 5 21 5 3\"\/>\n      <\/svg>\n      D\u00e9marrer le test\n    <\/button>\n  <\/div>\n\n  <!-- R\u00e9sultat -->\n  <div class=\"result-panel\" id=\"result-panel\" role=\"alert\" aria-live=\"polite\">\n    <div class=\"result-icon\" id=\"result-icon\">\u2705<\/div>\n    <div class=\"result-title\" id=\"result-title\">Excellent !<\/div>\n    <div class=\"result-score\" id=\"result-score\">33 <span>clics en 20 s<\/span><\/div>\n    <div class=\"result-body\" id=\"result-body\">Votre rythme correspond \u00e0 un massage cardiaque efficace.<\/div>\n    <button class=\"btn-retry\" id=\"btn-retry\">Recommencer<\/button>\n  <\/div>\n\n  <!-- Info bas de page -->\n  <div class=\"info-card\">\n    <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n      <circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/>\n    <\/svg>\n    <p class=\"info-card-text\">\n      <strong>Le saviez-vous&nbsp;?<\/strong> En cas d&rsquo;arr\u00eat cardiaque, les compressions thoraciques doivent \u00eatre\n      r\u00e9alis\u00e9es \u00e0 un rythme de <strong>100 \u00e0 120 compressions par minute<\/strong>, avec une profondeur d&rsquo;environ\n      5 \u00e0 6 cm. Ce test simule uniquement le rythme, pas la force. Appelez le <strong>112<\/strong> en premier.\n    <\/p>\n  <\/div>\n\n<\/div><!-- \/.game-wrapper -->\n\n<script>\n(function(){\n  \/* \u2500\u2500 Config \u2500\u2500 *\/\n  const DURATION   = 20;       \/\/ secondes\n  const TARGET_BPM = 100;      \/\/ clics\/min\n  const TARGET_CLICKS = Math.round(TARGET_BPM * DURATION \/ 60); \/\/ 33\n  const TOLERANCE  = 0.15;     \/\/ \u00b115 %\n  const METRO_INTERVAL = 60000 \/ TARGET_BPM; \/\/ 600 ms\n\n  \/* \u2500\u2500 State \u2500\u2500 *\/\n  let state = 'idle';   \/\/ idle | running | done\n  let startTime = null;\n  let clicks = 0;\n  let timerInterval = null;\n  let metroInterval = null;\n  let clickTimestamps = [];\n  let beatBars = [];\n  let beatIndex = 0;\n\n  \/* \u2500\u2500 DOM refs \u2500\u2500 *\/\n  const zone        = document.getElementById('click-zone');\n  const overlay     = document.getElementById('overlay');\n  const overlayText = document.getElementById('overlay-text');\n  const overlaySub  = document.getElementById('overlay-sub');\n  const timerDisp   = document.getElementById('timer-display');\n  const timerArc    = document.getElementById('timer-arc');\n  const statClicks  = document.getElementById('stat-clicks');\n  const statBpm     = document.getElementById('stat-bpm');\n  const beatBarsWrap= document.getElementById('beat-bars');\n  const rhythmDot   = document.getElementById('rhythm-dot');\n  const btnStart    = document.getElementById('btn-start');\n  const resultPanel = document.getElementById('result-panel');\n  const resultIcon  = document.getElementById('result-icon');\n  const resultTitle = document.getElementById('result-title');\n  const resultScore = document.getElementById('result-score');\n  const resultBody  = document.getElementById('result-body');\n  const btnRetry    = document.getElementById('btn-retry');\n\n  \/* \u2500\u2500 Beat bars init \u2500\u2500 *\/\n  const BAR_COUNT = 24;\n  for(let i=0; i<BAR_COUNT; i++){\n    const b = document.createElement('div');\n    b.className = 'beat-bar';\n    beatBarsWrap.appendChild(b);\n    beatBars.push(b);\n  }\n\n  \/* \u2500\u2500 Arc timer helper \u2500\u2500 *\/\n  const CIRCUMFERENCE = 2 * Math.PI * 50; \/\/ r=50 \u2192 ~314\n  function setArc(fraction){ \/\/ 1=full, 0=empty\n    timerArc.style.strokeDashoffset = CIRCUMFERENCE * (1 - fraction);\n  }\n  setArc(1);\n\n  \/* \u2500\u2500 M\u00e9tronome guide \u2500\u2500 *\/\n  function startMetronome(){\n    let on = true;\n    rhythmDot.classList.add('pulse');\n    metroInterval = setInterval(()=>{\n      on = !on;\n      if(on) rhythmDot.classList.add('pulse');\n      else   rhythmDot.classList.remove('pulse');\n    }, METRO_INTERVAL \/ 2);\n  }\n  function stopMetronome(){\n    clearInterval(metroInterval);\n    rhythmDot.classList.remove('pulse');\n  }\n\n  \/* \u2500\u2500 Light a beat bar \u2500\u2500 *\/\n  function lightBar(){\n    beatBars[beatIndex % BAR_COUNT].classList.add('lit');\n    if(beatIndex > 0){\n      beatBars[(beatIndex - 1) % BAR_COUNT].classList.remove('lit');\n    }\n    beatIndex++;\n  }\n\n  \/* \u2500\u2500 Ripple effect \u2500\u2500 *\/\n  function addRipple(e){\n    const rect = zone.getBoundingClientRect();\n    const x = (e.clientX ?? rect.left + rect.width\/2) - rect.left;\n    const y = (e.clientY ?? rect.top  + rect.height\/2)- rect.top;\n    const ripple = document.createElement('div');\n    ripple.className = 'ripple';\n    ripple.style.left = x + 'px';\n    ripple.style.top  = y + 'px';\n    zone.appendChild(ripple);\n    ripple.addEventListener('animationend', ()=> ripple.remove());\n  }\n\n  \/* \u2500\u2500 Start \u2500\u2500 *\/\n  function startGame(){\n    state = 'running';\n    clicks = 0;\n    clickTimestamps = [];\n    beatIndex = 0;\n    beatBars.forEach(b => b.classList.remove('lit'));\n    startTime = performance.now();\n\n    statClicks.textContent = '0';\n    statBpm.textContent    = '\u2014';\n\n    zone.classList.add('active');\n    overlay.style.display = 'none';\n    resultPanel.classList.remove('show','good','bad','ok');\n\n    btnStart.disabled = true;\n    btnStart.innerHTML = `<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><rect x=\"6\" y=\"4\" width=\"4\" height=\"16\"\/><rect x=\"14\" y=\"4\" width=\"4\" height=\"16\"\/><\/svg> En cours\u2026`;\n\n    startMetronome();\n\n    \/\/ Countdown\n    let remaining = DURATION;\n    timerDisp.textContent = remaining;\n    setArc(1);\n\n    timerInterval = setInterval(()=>{\n      const elapsed = (performance.now() - startTime) \/ 1000;\n      remaining = Math.max(0, DURATION - elapsed);\n      timerDisp.textContent = Math.ceil(remaining);\n      setArc(remaining \/ DURATION);\n      if(remaining <= 0){ endGame(); }\n    }, 80);\n  }\n\n  \/* \u2500\u2500 End \u2500\u2500 *\/\n  function endGame(){\n    if(state !== 'running') return;\n    state = 'done';\n    clearInterval(timerInterval);\n    stopMetronome();\n\n    zone.classList.remove('active');\n    timerDisp.textContent = '0';\n    setArc(0);\n\n    \/\/ BPM final = clics * 3 (car 20s = 1\/3 min)\n    const bpmFinal = Math.round(clicks * (60 \/ DURATION));\n    statBpm.textContent = bpmFinal;\n\n    \/\/ Eval\n    const low  = TARGET_BPM * (1 - TOLERANCE);  \/\/ 85\n    const high = TARGET_BPM * (1 + TOLERANCE);  \/\/ 115\n    const perfectLow  = TARGET_BPM * 0.97;\n    const perfectHigh = TARGET_BPM * 1.03;\n\n    let cls, icon, title, body;\n    if(bpmFinal >= perfectLow && bpmFinal <= perfectHigh){\n      cls   = 'good';\n      icon  = '\ud83c\udfaf';\n      title = 'Parfait !';\n      body  = `Votre rythme de <strong>${bpmFinal} BPM<\/strong> est id\u00e9al pour un massage cardiaque efficace. Bravo !`;\n    } else if(bpmFinal >= low && bpmFinal <= high){\n      cls   = 'good';\n      icon  = '\u2705';\n      title = 'Bon rythme !';\n      body  = `Avec <strong>${bpmFinal} BPM<\/strong>, vous \u00eates dans la plage recommand\u00e9e (100\u2013120\/min). Un peu d'entra\u00eenement et ce sera parfait.`;\n    } else if(bpmFinal < low){\n      cls   = bpmFinal < 70 ? 'bad' : 'ok';\n      icon  = bpmFinal < 70 ? '\ud83d\udc22' : '\u26a0\ufe0f';\n      title = bpmFinal < 70 ? 'Trop lent !' : 'Un peu lent\u2026';\n      body  = `<strong>${bpmFinal} BPM<\/strong> \u2014 le rythme cible est 100\/min. Essayez de comprimer plus vite, pensez au refrain de <em>Stayin' Alive<\/em> des Bee Gees.`;\n    } else {\n      cls   = bpmFinal > 140 ? 'bad' : 'ok';\n      icon  = bpmFinal > 140 ? '\ud83d\ude80' : '\u26a0\ufe0f';\n      title = bpmFinal > 140 ? 'Trop rapide !' : 'Un peu rapide\u2026';\n      body  = `<strong>${bpmFinal} BPM<\/strong> \u2014 vous d\u00e9passez les 120\/min recommand\u00e9s. Prenez le temps de bien appuyer \u00e0 chaque compression.`;\n    }\n\n    resultIcon.textContent  = icon;\n    resultTitle.textContent = title;\n    resultScore.innerHTML   = `${clicks} <span>clics en 20 s (${bpmFinal} BPM)<\/span>`;\n    resultBody.innerHTML    = body;\n    resultPanel.className   = `result-panel ${cls} show`;\n\n    btnStart.disabled = false;\n    btnStart.innerHTML = `<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polygon points=\"5 3 19 12 5 21 5 3\"\/><\/svg> Recommencer`;\n    btnStart.onclick = startGame;\n\n    overlayText.textContent = '\u25b6 Cliquez pour recommencer';\n    overlaySub.textContent  = '';\n    overlay.style.display   = '';\n  }\n\n  \/* \u2500\u2500 Click handler \u2500\u2500 *\/\n  function handleClick(e){\n    if(state === 'idle'){\n      startGame();\n      return;\n    }\n    if(state !== 'running') return;\n\n    clicks++;\n    const now = performance.now();\n    clickTimestamps.push(now);\n    statClicks.textContent = clicks;\n    lightBar();\n    addRipple(e);\n\n    \/\/ BPM glissant sur les 5 derniers clics\n    if(clickTimestamps.length >= 3){\n      const last = clickTimestamps.slice(-5);\n      const intervals = [];\n      for(let i=1; i<last.length; i++) intervals.push(last[i]-last[i-1]);\n      const avgInterval = intervals.reduce((a,b)=>a+b,0)\/intervals.length;\n      const bpm = Math.round(60000 \/ avgInterval);\n      statBpm.textContent = bpm;\n    }\n  }\n\n  \/* \u2500\u2500 Keyboard support \u2500\u2500 *\/\n  zone.addEventListener('keydown', e=>{\n    if(e.key === 'Enter' || e.key === ' '){ e.preventDefault(); handleClick(e); }\n  });\n  zone.addEventListener('click', handleClick);\n  zone.addEventListener('touchstart', e=>{ e.preventDefault(); handleClick(e.touches[0]); }, { passive: false });\n\n  btnStart.addEventListener('click', ()=>{ if(state === 'idle') startGame(); });\n  btnRetry.addEventListener('click', ()=>{\n    resultPanel.classList.remove('show');\n    state = 'idle';\n    timerDisp.textContent = DURATION;\n    setArc(1);\n    statClicks.textContent = '0';\n    statBpm.textContent    = '\u2014';\n    overlayText.textContent = '\u25b6 Cliquez pour commencer';\n    overlaySub.textContent  = 'Appuyez sur la zone marqu\u00e9e';\n    overlay.style.display   = '';\n    beatBars.forEach(b => b.classList.remove('lit'));\n    btnStart.disabled = false;\n    btnStart.innerHTML = `<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polygon points=\"5 3 19 12 5 21 5 3\"\/><\/svg> D\u00e9marrer le test`;\n    btnStart.onclick = startGame;\n  });\n\n  btnStart.onclick = startGame;\n\n})();\n<\/script>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"http:\/\/premierssurplace.be\/?page_id=17&amp;preview_id=6&amp;preview_nonce=f9a7642638\">Retour au site<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Premiers sur Place Testez votre rythme de RCP Simulez les compressions thoraciques d&rsquo;un massage cardiaque&nbsp;: 100 clics par minute pendant 20 secondes. 20 secondes restantes ZONE DE COMPRESSION \u25b6 Cliquez pour commencer Appuyez sur la zone marqu\u00e9e Rythme cible&nbsp;: 100 compressions\/min \u2014 soit 1 clic toutes les 0,6 s (\u2669 = 100 bpm). Suivez le [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-173","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/premierssurplace.be\/index.php?rest_route=\/wp\/v2\/pages\/173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/premierssurplace.be\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/premierssurplace.be\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/premierssurplace.be\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/premierssurplace.be\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=173"}],"version-history":[{"count":8,"href":"http:\/\/premierssurplace.be\/index.php?rest_route=\/wp\/v2\/pages\/173\/revisions"}],"predecessor-version":[{"id":187,"href":"http:\/\/premierssurplace.be\/index.php?rest_route=\/wp\/v2\/pages\/173\/revisions\/187"}],"wp:attachment":[{"href":"http:\/\/premierssurplace.be\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}