{"id":727,"date":"2026-08-05T17:08:31","date_gmt":"2026-08-05T15:08:31","guid":{"rendered":"https:\/\/lesracailles2shanghai.fr\/?page_id=727"},"modified":"2026-08-05T17:12:13","modified_gmt":"2026-08-05T15:12:13","slug":"elementor-727","status":"publish","type":"page","link":"https:\/\/lesracailles2shanghai.fr\/index.php\/elementor-727\/","title":{"rendered":"Elementor #727"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"727\" class=\"elementor elementor-727\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-810962d e-flex e-con-boxed e-con e-parent\" data-id=\"810962d\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-523fb26 elementor-widget elementor-widget-html\" data-id=\"523fb26\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1\">\n<title>\u00c9tincelles \u2014 carnet de sketchs<\/title>\n<style>\n  @import url('https:\/\/fonts.googleapis.com\/css2?family=Anton&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');\n\n  :root{\n    --black: #0b0a0a;\n    --charcoal: #17151400;\n    --panel: #1c1918;\n    --panel-2: #221e1c;\n    --line: #332e2b;\n    --text: #f2ece4;\n    --muted: #9a9088;\n    --spot: #ffb84d;\n    --spot-hot: #ff9d2e;\n    --ember: #e8590c;\n    --personal: #d98a9c;\n  }\n\n  *{ box-sizing: border-box; }\n  html,body{ margin:0; padding:0; }\n  body{\n    background: radial-gradient(ellipse 120% 60% at 50% -10%, #221c17 0%, var(--black) 55%), var(--black);\n    color: var(--text);\n    font-family: 'Inter', sans-serif;\n    min-height: 100vh;\n    padding: 0 0 60px 0;\n    -webkit-tap-highlight-color: transparent;\n  }\n\n  \/* subtle floor grain *\/\n  body::before{\n    content:\"\";\n    position: fixed; inset:0;\n    background-image: radial-gradient(rgba(255,255,255,0.025) 1px, transparent 1px);\n    background-size: 3px 3px;\n    pointer-events: none;\n    z-index: 0;\n  }\n\n  header{\n    padding: 34px 20px 18px;\n    position: relative;\n    z-index: 1;\n    text-align: center;\n  }\n  header .eyebrow{\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11px;\n    letter-spacing: 0.18em;\n    color: var(--muted);\n    text-transform: uppercase;\n  }\n  header h1{\n    font-family: 'Anton', sans-serif;\n    font-weight: 400;\n    font-size: 34px;\n    letter-spacing: 0.01em;\n    margin: 6px 0 0;\n    background: linear-gradient(180deg, #fff5e6, var(--spot) 80%);\n    -webkit-background-clip: text;\n    background-clip: text;\n    color: transparent;\n    text-shadow: 0 0 60px rgba(255,184,77,0.25);\n  }\n  header p{\n    color: var(--muted);\n    font-size: 13.5px;\n    margin: 8px auto 0;\n    max-width: 320px;\n    line-height: 1.5;\n  }\n\n  .app-userlvl{\n    max-width: 300px; margin: 16px auto 0;\n  }\n  .app-userlvl-top{\n    display:flex; justify-content:space-between; align-items:baseline;\n    font-family:'JetBrains Mono', monospace; font-size: 10.5px; color: var(--muted);\n    margin-bottom: 5px;\n  }\n  .app-userlvl-top .lvltitle{ color: var(--spot); font-weight:600; }\n  .app-userlvl-bar{\n    height: 6px; border-radius: 3px; background: var(--panel-2); overflow: hidden;\n    border: 1px solid var(--line);\n  }\n  .app-userlvl-fill{\n    height: 100%; border-radius: 3px;\n    background: linear-gradient(90deg, var(--spot), var(--ember));\n    transition: width .4s ease;\n  }\n\n  .xp-chip{\n    font-family:'JetBrains Mono', monospace; font-size: 10.5px;\n    color: #241606; background: linear-gradient(180deg, var(--spot), var(--spot-hot));\n    padding: 3px 8px; border-radius: 999px; font-weight: 700;\n  }\n\n  .status-pill{\n    display:inline-flex; align-items:center; gap:5px;\n    font-family:'JetBrains Mono', monospace; font-size: 10.5px;\n    padding: 4px 10px; border-radius: 999px; margin-top: 9px; font-weight:600;\n  }\n  .status-pill .dot{ width:6px; height:6px; border-radius:50%; background:currentColor; flex-shrink:0; }\n  .status-pill.ready{ background: rgba(123,196,127,0.1); border:1px solid rgba(123,196,127,0.4); color:#7bc47f; }\n  .status-pill.needs{ background: rgba(226,87,76,0.1); border:1px solid rgba(226,87,76,0.4); color:#ff8a7a; }\n\n  .status-toggle{ display:flex; gap:8px; }\n  .status-btn{\n    flex:1; font-family:'JetBrains Mono', monospace; font-size: 11.5px;\n    padding: 10px 8px; border-radius: 10px; border: 1px solid var(--line);\n    background: var(--panel-2); color: var(--muted); cursor:pointer; text-align:center;\n    transition: all .15s ease;\n  }\n  .status-btn.needs.active{ background: rgba(226,87,76,0.15); border-color:#e2574c; color:#ff8a7a; font-weight:700; }\n  .status-btn.ready.active{ background: rgba(123,196,127,0.15); border-color:#7bc47f; color:#7bc47f; font-weight:700; }\n\n  .wrap{ max-width: 560px; margin: 0 auto; padding: 0 16px; position: relative; z-index: 1; }\n\n  \/* capture card *\/\n  .capture{\n    background: var(--panel);\n    border: 1px solid var(--line);\n    border-radius: 18px;\n    padding: 18px 16px 16px;\n    margin-top: 10px;\n    position: relative;\n    overflow: hidden;\n  }\n  .capture::before{\n    content:\"\";\n    position:absolute; top:-120px; left:50%; transform: translateX(-50%);\n    width: 340px; height: 260px;\n    background: radial-gradient(ellipse at center, rgba(255,184,77,0.16), transparent 65%);\n    pointer-events:none;\n    opacity: 0;\n    transition: opacity .4s ease;\n  }\n  .capture.lit::before{ opacity: 1; }\n\n  label.field-label{\n    display:block;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10.5px;\n    letter-spacing: 0.12em;\n    text-transform: uppercase;\n    color: var(--spot);\n    margin: 14px 0 7px;\n  }\n  label.field-label:first-child{ margin-top: 0; }\n  label.field-label .opt{ color: var(--muted); text-transform: none; letter-spacing: 0; font-size: 10px; }\n\n  input[type=text], textarea{\n    width: 100%;\n    background: var(--panel-2);\n    border: 1px solid var(--line);\n    border-radius: 12px;\n    color: var(--text);\n    font-family: 'Inter', sans-serif;\n    font-size: 15.5px;\n    padding: 12px 13px;\n    resize: none;\n    transition: border-color .2s ease, box-shadow .2s ease;\n  }\n  input[type=text]::placeholder, textarea::placeholder{ color: #5c5550; }\n  input[type=text]:focus, textarea:focus{\n    outline: none;\n    border-color: var(--spot);\n    box-shadow: 0 0 0 3px rgba(255,184,77,0.12);\n  }\n  textarea{ min-height: 92px; line-height: 1.5; font-family: inherit; }\n  #scene{ min-height: 108px; }\n\n  .chips{ display:flex; flex-wrap: wrap; gap: 8px; }\n  .chip{\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12.5px;\n    padding: 7px 12px;\n    border-radius: 999px;\n    border: 1px solid var(--line);\n    background: var(--panel-2);\n    color: var(--muted);\n    cursor: pointer;\n    user-select: none;\n    transition: all .15s ease;\n  }\n  .chip.on{\n    background: linear-gradient(180deg, var(--spot), var(--spot-hot));\n    color: #241606;\n    border-color: var(--spot);\n    font-weight: 600;\n    box-shadow: 0 0 16px rgba(255,157,46,0.35);\n  }\n\n  .field-label.small{ color: var(--muted); font-size: 10px; }\n\n  .keyframe{\n    border: 1px solid rgba(255,157,46,0.3);\n    background: linear-gradient(180deg, rgba(255,184,77,0.07), rgba(255,157,46,0.02));\n    border-radius: 13px;\n    padding: 12px 13px 13px;\n    margin-top: 14px;\n  }\n  .keyframe .field-label{\n    color: var(--spot-hot);\n    display: flex;\n    align-items: center;\n    gap: 6px;\n    margin: 0 0 8px;\n  }\n  .keyframe .field-label::before{\n    content: \"\";\n    width: 6px; height: 6px; border-radius: 50%;\n    background: var(--spot-hot);\n    box-shadow: 0 0 8px var(--spot-hot);\n    flex-shrink: 0;\n  }\n  .keyframe input[type=text]{\n    background: rgba(0,0,0,0.25);\n    border-color: rgba(255,157,46,0.25);\n    font-weight: 600;\n  }\n  .keyframe + .keyframe{ margin-top: 10px; }\n\n  .duration-row{ display:flex; flex-wrap: wrap; gap: 8px; }\n  .dchip{\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 12px;\n    padding: 7px 12px;\n    border-radius: 9px;\n    border: 1px solid var(--line);\n    background: var(--panel-2);\n    color: var(--muted);\n    cursor: pointer;\n  }\n  .dchip.on{\n    background: var(--panel);\n    border-color: var(--spot);\n    color: var(--spot);\n    font-weight: 600;\n  }\n\n  .personal-note{\n    border: 1px solid rgba(217,138,156,0.28);\n    background: linear-gradient(180deg, rgba(217,138,156,0.07), transparent);\n    border-radius: 13px;\n    padding: 12px 13px 13px;\n    margin-top: 14px;\n  }\n  .personal-note .field-label{\n    color: var(--personal);\n    margin: 0 0 8px;\n  }\n  .personal-note textarea{\n    font-style: italic;\n    min-height: 52px;\n    background: rgba(0,0,0,0.2);\n    border-color: rgba(217,138,156,0.22);\n  }\n\n  .card-jeu{\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11.5px;\n    color: var(--spot);\n    margin-top: 8px;\n  }\n  .card-perso{\n    font-size: 13px;\n    font-style: italic;\n    color: var(--personal);\n    margin-top: 6px;\n    line-height: 1.5;\n  }\n\n  .score-badge{\n    flex-shrink: 0;\n    width: 34px; height: 34px;\n    border-radius: 50%;\n    display:flex; align-items:center; justify-content:center;\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 13px; font-weight: 700;\n    border: 1.5px solid var(--line);\n    color: var(--muted);\n    background: var(--panel-2);\n    cursor: pointer;\n  }\n  .score-badge.good{ border-color: #7bc47f; color: #7bc47f; background: rgba(123,196,127,0.08); }\n  .score-badge.bad{ border-color: #e2574c; color: #e2574c; background: rgba(226,87,76,0.08); }\n  .score-badge.pending{ font-size: 10px; color: var(--muted); }\n  .score-reason{\n    font-size: 11.5px; color: var(--muted); margin-top: 8px; line-height: 1.4;\n  }\n\n  .level-row{ display:flex; align-items:center; gap: 8px; margin-top: 10px; }\n  .level-label{\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 10px; letter-spacing: .06em; text-transform: uppercase;\n    color: var(--muted); white-space: nowrap;\n  }\n  .level-bar{\n    flex: 1; height: 5px; border-radius: 3px;\n    background: var(--panel-2); overflow: hidden;\n  }\n  .level-fill{\n    height: 100%; border-radius: 3px;\n    background: linear-gradient(90deg, var(--spot), var(--ember));\n  }\n\n  .card-punch{\n    margin-top: 8px;\n    font-size: 14px;\n    color: #ffcf8a;\n    font-weight: 600;\n    line-height: 1.4;\n  }\n  .card-punch .lbl{ color: var(--spot-hot); font-family:'JetBrains Mono', monospace; font-size: 10px; letter-spacing:.08em; text-transform: uppercase; margin-right: 6px; font-weight: 500; }\n  .card-place{\n    font-family: 'JetBrains Mono', monospace;\n    font-size: 11.5px;\n    color: var(--muted);\n    margin-top: 6px;\n  }\n\n  .save-row{ display:flex; gap: 10px; margin-top: 18px; }\n  button{ font-family: inherit; border: none; cursor: pointer; }\n  .btn-save{\n    flex: 1;\n    background: linear-gradient(180deg, var(--spot), var(--ember));\n    color: #241606;\n    font-weight: 700;\n    font-size: 15px;\n    padding: 13px;\n    border-radius: 12px;\n    box-shadow: 0 6px 20px rgba(232,89,12,0.28);\n    transition: transform .1s ease;\n  }\n  .btn-save:active{ transform: scale(0.97); }\n  .btn-more{\n    background: var(--panel-2);\n    border: 1px solid var(--line);\n    color: var(--muted);\n    font-size: 13px;\n    padding: 13px 14px;\n    border-radius: 12px;\n  }\n\n  .more-fields{ display: none; }\n  .more-fields.show{ display: block; }\n\n  \/* list *\/\n  .list-head{\n    display:flex; align-items:baseline; justify-content: space-between;\n    margin: 30px 2px 12px;\n  }\n  .list-head h2{\n    font-family: 'Anton', sans-serif; font-weight: 400;\n    font-size: 17px; letter-spacing: 0.02em; margin: 0; color: var(--text);\n  }\n  .list-head span{ font-family:'JetBrains Mono', monospace; font-size: 11.5px; color: var(--muted); }\n\n  .empty{\n    text-align:center; color: var(--muted); font-size: 13.5px;\n    padding: 36px 20px; border: 1px dashed var(--line); border-radius: 14px;\n    line-height: 1.6;\n  }\n\n  .card{\n    background: var(--panel);\n    border: 1px solid var(--line);\n    border-radius: 14px;\n    padding: 14px 15px;\n    margin-bottom: 10px;\n    cursor: pointer;\n    transition: border-color .15s ease;\n  }\n  .card:active{ border-color: var(--spot); }\n  .card-top{ display:flex; justify-content:space-between; align-items:flex-start; gap: 10px; }\n  .card-title{ font-size: 15.5px; font-weight: 600; line-height: 1.35; }\n  .card-date{ font-family:'JetBrains Mono', monospace; font-size: 10.5px; color: var(--muted); white-space: nowrap; margin-top: 2px; }\n  .card-tags{ display:flex; flex-wrap:wrap; gap:6px; margin-top: 9px; }\n  .tag{\n    font-family:'JetBrains Mono', monospace; font-size: 10.5px;\n    color: var(--spot); background: rgba(255,184,77,0.08);\n    border: 1px solid rgba(255,184,77,0.25);\n    padding: 3px 8px; border-radius: 999px;\n  }\n  .card-body{ display:none; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }\n  .card.open .card-body{ display:block; }\n  .card-body .row{ margin-bottom: 10px; }\n  .card-body .row:last-child{ margin-bottom: 0; }\n  .card-body .k{ font-family:'JetBrains Mono', monospace; font-size: 10px; letter-spacing:.1em; text-transform:uppercase; color: var(--muted); margin-bottom: 4px; }\n  .card-body .v{ font-size: 14.5px; line-height: 1.55; white-space: pre-wrap; color: #e9e2d8; }\n  .card-actions{ display:flex; gap:8px; margin-top: 14px; }\n  .card-actions button{\n    font-family:'JetBrains Mono', monospace; font-size: 11.5px;\n    background: var(--panel-2); border: 1px solid var(--line); color: var(--muted);\n    padding: 8px 12px; border-radius: 9px;\n  }\n  .card-actions .del{ color: #ff8a7a; border-color: #4a2c26; }\n\n  .toast{\n    position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%) translateY(20px);\n    background: var(--panel); border: 1px solid var(--spot); color: var(--text);\n    font-size: 13.5px; padding: 11px 18px; border-radius: 999px;\n    opacity: 0; transition: all .25s ease; pointer-events:none; z-index: 50;\n    box-shadow: 0 8px 24px rgba(0,0,0,0.4);\n    white-space: nowrap;\n  }\n  .toast.show{ opacity:1; transform: translateX(-50%) translateY(0); }\n\n  \/* ---------- TITLE SCREEN ---------- *\/\n  #titleScreen{\n    position: fixed; inset: 0; z-index: 100;\n    background:\n      radial-gradient(ellipse 70% 45% at 50% 62%, rgba(255,157,46,0.14), transparent 70%),\n      radial-gradient(ellipse 140% 70% at 50% -10%, #241d18 0%, var(--black) 60%),\n      var(--black);\n    display: flex; flex-direction: column; align-items: center; justify-content: space-between;\n    padding: 8vh 20px 6vh;\n    overflow: hidden;\n  }\n  #titleScreen::before, #titleScreen::after{\n    content: \"\";\n    position: absolute; top:0; bottom:0; width: 14vw; min-width: 60px; max-width: 140px;\n    background: linear-gradient(90deg, rgba(120,20,20,0.55), transparent);\n    z-index: 0;\n  }\n  #titleScreen::before{ left:0; }\n  #titleScreen::after{ right:0; transform: scaleX(-1); }\n\n  .ts-top{ text-align:center; position:relative; z-index:2; }\n  .ts-eyebrow{\n    font-family:'JetBrains Mono', monospace; font-size: 11px; letter-spacing:.22em;\n    color: var(--muted); text-transform: uppercase;\n  }\n  .ts-title{\n    font-family:'Anton', sans-serif; font-weight:400; font-size: 54px; letter-spacing:.01em;\n    margin: 8px 0 0;\n    background: linear-gradient(180deg, #fff5e6, var(--spot) 75%);\n    -webkit-background-clip:text; background-clip:text; color:transparent;\n    text-shadow: 0 0 70px rgba(255,184,77,0.3);\n  }\n\n  .ts-stage{\n    position: relative; z-index: 2;\n    width: 100%; max-width: 260px;\n    display:flex; flex-direction:column; align-items:center;\n    margin: 4vh 0;\n  }\n  .ts-spot{\n    position:absolute; top:-70px; left:50%; transform:translateX(-50%);\n    width: 240px; height: 240px;\n    background: radial-gradient(ellipse at center, rgba(255,213,153,0.22), rgba(255,184,77,0.05) 55%, transparent 72%);\n    animation: flicker 4.5s ease-in-out infinite;\n  }\n  @keyframes flicker{ 0%,100%{ opacity:1; } 48%{ opacity:1; } 50%{ opacity:.85; } 52%{ opacity:1; } }\n\n  .ts-avatar{ position: relative; z-index: 3; animation: bob 2.6s ease-in-out infinite; }\n  @keyframes bob{\n    0%,100%{ transform: translateY(0) rotate(0deg); }\n    50%{ transform: translateY(-7px) rotate(-1deg); }\n  }\n  .ts-avatar .arm{ transform-origin: 60px 108px; animation: swing 2.6s ease-in-out infinite; }\n  @keyframes swing{\n    0%,100%{ transform: rotate(0deg); }\n    50%{ transform: rotate(8deg); }\n  }\n\n  .ts-floor{\n    width: 150px; height: 16px; margin-top: -6px;\n    background: radial-gradient(ellipse at center, rgba(255,157,46,0.25), transparent 75%);\n    border-radius: 50%;\n    position: relative; z-index: 2;\n  }\n\n  .ts-pseudo{\n    font-family:'JetBrains Mono', monospace; font-size: 12.5px; color: var(--spot);\n    margin-top: 10px; letter-spacing: .05em; min-height: 16px;\n  }\n  .ts-userlvl{\n    width: 100%; max-width: 240px; margin-top: 8px;\n    display: none;\n  }\n  .ts-userlvl.show{ display: block; }\n  .ts-userlvl-top{\n    display:flex; justify-content:space-between; align-items:baseline;\n    font-family:'JetBrains Mono', monospace; font-size: 10.5px; color: var(--muted);\n    margin-bottom: 5px;\n  }\n  .ts-userlvl-top .lvltitle{ color: var(--spot); font-weight: 600; }\n\n  .ts-menu{ position:relative; z-index:2; width:100%; max-width: 280px; display:flex; flex-direction:column; gap:12px; }\n  .ts-btn{\n    font-family:'Anton', sans-serif; font-weight:400; letter-spacing:.03em;\n    font-size: 17px; text-transform: uppercase;\n    padding: 14px 18px; border-radius: 12px; text-align:center;\n    border: 1px solid var(--line); background: var(--panel);\n    color: var(--text); cursor:pointer; position:relative;\n    transition: all .15s ease;\n  }\n  .ts-btn .arrow{ position:absolute; left:16px; top:50%; transform:translateY(-50%); opacity:0; color:var(--spot); transition: opacity .15s ease; }\n  .ts-btn:not(.disabled):active{ transform: scale(0.97); }\n  .ts-btn:not(.disabled):hover .arrow{ opacity:1; }\n  .ts-btn.primary{\n    background: linear-gradient(180deg, var(--spot), var(--ember));\n    color:#241606; border-color: transparent;\n    box-shadow: 0 8px 24px rgba(232,89,12,0.3);\n  }\n  .ts-btn.disabled{ opacity:.4; cursor:not-allowed; }\n  .ts-hint{ text-align:center; font-size:11px; color:var(--muted); margin-top:2px; font-family:'JetBrains Mono', monospace; }\n\n  \/* modal *\/\n  .ts-modal-backdrop{\n    position: fixed; inset:0; z-index: 200; background: rgba(0,0,0,0.65);\n    display:flex; align-items:center; justify-content:center; padding: 20px;\n    opacity:0; pointer-events:none; transition: opacity .2s ease;\n  }\n  .ts-modal-backdrop.show{ opacity:1; pointer-events:auto; }\n  .ts-modal{\n    background: var(--panel); border: 1px solid var(--line); border-radius: 18px;\n    padding: 22px 20px; width: 100%; max-width: 340px;\n  }\n  .ts-modal h3{\n    font-family:'Anton', sans-serif; font-weight:400; font-size:20px; margin:0 0 4px; color: var(--spot);\n  }\n  .ts-modal p{ font-size:12.5px; color:var(--muted); margin: 0 0 16px; line-height:1.5; }\n  .ts-modal input[type=text]{\n    width:100%; background: var(--panel-2); border:1px solid var(--line); border-radius:10px;\n    color:var(--text); font-size:15px; padding:11px 12px; font-family:'Inter',sans-serif;\n  }\n  .ts-colors{ display:flex; gap:10px; margin: 14px 0 4px; }\n  .ts-color{\n    width:34px; height:34px; border-radius:50%; cursor:pointer; border:2px solid transparent;\n  }\n  .ts-color.on{ border-color: var(--text); }\n  .ts-modal-actions{ display:flex; gap:10px; margin-top:18px; }\n  .ts-modal-actions .cancel{\n    flex:1; background:var(--panel-2); border:1px solid var(--line); color:var(--muted);\n    padding:12px; border-radius:10px; font-size:13.5px;\n  }\n  .ts-modal-actions .confirm{\n    flex:1.4; background: linear-gradient(180deg, var(--spot), var(--ember)); color:#241606;\n    font-weight:700; padding:12px; border-radius:10px; font-size:13.5px;\n  }\n\n  #gameApp{ display:none; opacity:0; transition: opacity .35s ease; }\n  #gameApp.show{ opacity:1; }\n<\/style>\n<\/head>\n<body>\n\n<div id=\"titleScreen\">\n  <div class=\"ts-top\">\n    <div class=\"ts-eyebrow\">carnet d'\u00e9tincelles<\/div>\n    <div class=\"ts-title\">SPARK<\/div>\n  <\/div>\n\n  <div class=\"ts-stage\">\n    <div class=\"ts-spot\"><\/div>\n    <svg class=\"ts-avatar\" id=\"avatarSvg\" width=\"120\" height=\"120\" viewBox=\"0 0 120 120\">\n      <ellipse cx=\"60\" cy=\"112\" rx=\"26\" ry=\"5\" fill=\"rgba(0,0,0,0.4)\"\/>\n      <g class=\"arm\">\n        <rect x=\"52\" y=\"66\" width=\"8\" height=\"34\" rx=\"4\" fill=\"#2a2422\"\/>\n        <circle cx=\"56\" cy=\"102\" r=\"5\" fill=\"#12100f\"\/>\n      <\/g>\n      <rect x=\"42\" y=\"58\" width=\"36\" height=\"46\" rx=\"14\" id=\"avatarBody\" fill=\"#e8590c\"\/>\n      <circle cx=\"60\" cy=\"40\" r=\"20\" fill=\"#e8b88f\"\/>\n      <path d=\"M40 34 Q60 12 80 34 Q80 20 60 16 Q40 20 40 34 Z\" fill=\"#2a2422\"\/>\n      <circle cx=\"52\" cy=\"42\" r=\"2.4\" fill=\"#1a1512\"\/>\n      <circle cx=\"68\" cy=\"42\" r=\"2.4\" fill=\"#1a1512\"\/>\n      <path d=\"M52 50 Q60 55 68 50\" stroke=\"#1a1512\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n    <\/svg>\n    <div class=\"ts-floor\"><\/div>\n    <div class=\"ts-pseudo\" id=\"tsPseudo\"><\/div>\n    <div class=\"ts-userlvl\" id=\"tsUserLvl\">\n      <div class=\"ts-userlvl-top\"><span class=\"lvltitle\" id=\"tsLvlTitle\">\u2014<\/span><span id=\"tsLvlXp\">0 xp<\/span><\/div>\n      <div class=\"level-bar\"><div class=\"level-fill\" id=\"tsLvlFill\" style=\"width:0%\"><\/div><\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"ts-menu\">\n    <div class=\"ts-btn primary\" id=\"btnNewGame\"><span class=\"arrow\">\u25b8<\/span>Nouvelle sc\u00e8ne<\/div>\n    <div class=\"ts-btn disabled\" id=\"btnContinue\"><span class=\"arrow\">\u25b8<\/span>Continuer<\/div>\n    <div class=\"ts-hint\" id=\"tsHint\">aucune partie sauvegard\u00e9e<\/div>\n  <\/div>\n<\/div>\n\n<div class=\"ts-modal-backdrop\" id=\"modalBackdrop\">\n  <div class=\"ts-modal\">\n    <h3>Entrer en sc\u00e8ne<\/h3>\n    <p>Choisis ton nom de sc\u00e8ne et la couleur de ton avatar. C'est juste pour toi.<\/p>\n    <input type=\"text\" id=\"pseudoInput\" placeholder=\"ton nom de sc\u00e8ne\" maxlength=\"24\">\n    <div class=\"ts-colors\" id=\"colorPicker\">\n      <div class=\"ts-color on\" data-color=\"#e8590c\" style=\"background:#e8590c\"><\/div>\n      <div class=\"ts-color\" data-color=\"#d98a9c\" style=\"background:#d98a9c\"><\/div>\n      <div class=\"ts-color\" data-color=\"#3fa9a0\" style=\"background:#3fa9a0\"><\/div>\n      <div class=\"ts-color\" data-color=\"#7b8ce8\" style=\"background:#7b8ce8\"><\/div>\n    <\/div>\n    <div class=\"ts-modal-actions\">\n      <button class=\"cancel\" id=\"modalCancel\">Annuler<\/button>\n      <button class=\"confirm\" id=\"modalConfirm\">Entrer en sc\u00e8ne<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div id=\"gameApp\">\n\n<header>\n  <div class=\"eyebrow\" id=\"mainEyebrow\">carnet d'\u00e9tincelles<\/div>\n  <h1>SPARK<\/h1>\n  <p>Capture la sc\u00e8ne, pas le texte. Trois secondes suffisent pour ne pas la perdre.<\/p>\n  <div class=\"app-userlvl\">\n    <div class=\"app-userlvl-top\"><span class=\"lvltitle\" id=\"appLvlTitle\">\u2014<\/span><span id=\"appLvlXp\">0 xp<\/span><\/div>\n    <div class=\"app-userlvl-bar\"><div class=\"app-userlvl-fill\" id=\"appLvlFill\" style=\"width:0%\"><\/div><\/div>\n  <\/div>\n<\/header>\n\n<div class=\"wrap\">\n\n  <div class=\"capture\" id=\"captureCard\">\n    <label class=\"field-label\">L'accroche <span class=\"opt\">\u2014 le mot qui te rappelle tout<\/span><\/label>\n    <input type=\"text\" id=\"title\" placeholder=\"ex : le radar qui me juge\" maxlength=\"80\">\n\n    <label class=\"field-label\">Lieu \/ moment<\/label>\n    <input type=\"text\" id=\"place\" placeholder=\"ex : auto-\u00e9cole, lundi matin, \u00e9l\u00e8ve en panique\" maxlength=\"80\">\n\n    <label class=\"field-label\">Mots-cl\u00e9s <span class=\"opt small\">\u2014 des bouts, pas des phrases<\/span><\/label>\n    <textarea id=\"scene\" placeholder=\"klaxon \u00b7 silence g\u00eanant \u00b7 sa main qui tremble\" style=\"min-height:60px;\"><\/textarea>\n\n    <label class=\"field-label\">\u00c9motion sur sc\u00e8ne<\/label>\n    <div class=\"chips\" id=\"emotionChips\"><\/div>\n\n    <label class=\"field-label\">\ud83c\udfad Comment tu le joues <span class=\"opt\">\u2014 ton, rythme, geste<\/span><\/label>\n    <input type=\"text\" id=\"jeu\" placeholder=\"voix aigu\u00eb \u00b7 mime le volant \u00b7 silence 2 sec\">\n\n    <div class=\"personal-note\">\n      <label class=\"field-label\">\u275d Pourquoi \u00e7a TE fait rire<\/label>\n      <textarea id=\"perso\" placeholder=\"la vraie raison, m\u00eame b\u00eate \u2014 c'est souvent \u00e7a qui te fait remonter toute la sc\u00e8ne\"><\/textarea>\n    <\/div>\n\n    <div class=\"keyframe\">\n      <label class=\"field-label\">Punchlines <span class=\"opt\">\u2014 jusqu'\u00e0 3<\/span><\/label>\n      <input type=\"text\" id=\"punchline1\" placeholder=\"punchline 1 \u2014 la principale\" style=\"margin-bottom:8px;\">\n      <input type=\"text\" id=\"punchline2\" placeholder=\"punchline 2 (optionnel)\" style=\"margin-bottom:8px;\">\n      <input type=\"text\" id=\"punchline3\" placeholder=\"punchline 3 (optionnel)\">\n    <\/div>\n\n    <div class=\"keyframe\">\n      <label class=\"field-label\">Chute<\/label>\n      <input type=\"text\" id=\"chute\" placeholder=\"comment \u00e7a retombe\">\n    <\/div>\n\n    <label class=\"field-label\">Dur\u00e9e du sketch <span class=\"opt\">(optionnel)<\/span><\/label>\n    <div class=\"duration-row\" id=\"durationChips\"><\/div>\n\n    <div class=\"save-row\">\n      <button class=\"btn-save\" id=\"saveBtn\">Garder l'\u00e9tincelle<\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"list-head\">\n    <h2>Tes \u00e9tincelles<\/h2>\n    <span id=\"countLabel\">0<\/span>\n  <\/div>\n\n  <div id=\"listZone\">\n    <div class=\"empty\">Rien pour l'instant. Ta premi\u00e8re id\u00e9e peut \u00eatre aussi b\u00eate qu'une phrase \u2014 c'est suffisant pour rouvrir toute la sc\u00e8ne plus tard.<\/div>\n  <\/div>\n\n<\/div>\n\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<\/div>\n\n<script>\nconst EMOTIONS = [\"Absurde\",\"Malaise\",\"Col\u00e8re\",\"Honte\",\"Panique\",\"Fiert\u00e9\",\"Tendresse\",\"Injustice\"];\nconst DURATIONS = [\"30 sec\",\"1 min\",\"2-3 min\",\"5 min+\"];\nconst STORAGE_KEY = \"sparks-v2\";\nlet sparks = [];\nlet selectedEmotions = new Set();\nlet selectedDuration = null;\nlet openCardId = null;\n\nconst el = id => document.getElementById(id);\nconst emotionChips = el('emotionChips');\nconst durationChips = el('durationChips');\nconst listZone = el('listZone');\nconst countLabel = el('countLabel');\nconst toast = el('toast');\n\nEMOTIONS.forEach(e=>{\n  const c = document.createElement('div');\n  c.className = 'chip';\n  c.textContent = e;\n  c.onclick = ()=>{\n    if(selectedEmotions.has(e)){ selectedEmotions.delete(e); c.classList.remove('on'); }\n    else { selectedEmotions.add(e); c.classList.add('on'); }\n  };\n  emotionChips.appendChild(c);\n});\n\nDURATIONS.forEach(d=>{\n  const c = document.createElement('div');\n  c.className = 'dchip';\n  c.textContent = d;\n  c.onclick = ()=>{\n    if(selectedDuration === d){\n      selectedDuration = null;\n      c.classList.remove('on');\n    } else {\n      selectedDuration = d;\n      document.querySelectorAll('.dchip').forEach(x=>x.classList.remove('on'));\n      c.classList.add('on');\n    }\n  };\n  durationChips.appendChild(c);\n});\n\n['title','scene'].forEach(id=>{\n  el(id).addEventListener('focus', ()=> el('captureCard').classList.add('lit'));\n  el(id).addEventListener('blur', ()=> el('captureCard').classList.remove('lit'));\n});\n\nconst USER_LEVELS = [\n  { title: \"D\u00e9butant de sc\u00e8ne\", min: 0 },\n  { title: \"Jeune talent\", min: 20 },\n  { title: \"Apprenti comique\", min: 45 },\n  { title: \"Rookie du stand up\", min: 90 },\n  { title: \"Comique amateur\", min: 160 },\n  { title: \"Humoriste des r\u00e9seaux sociaux\", min: 280 },\n  { title: \"Humoriste\", min: 450 }\n];\n\nfunction getPunchlines(s){\n  if(s.punchlines && s.punchlines.length) return s.punchlines;\n  if(s.punchline) return [s.punchline];\n  return [];\n}\n\nfunction sparkXP(s){\n  let pts = 0;\n  if(s.title && s.title !== \"(sans titre)\") pts += 1;\n  if(s.place) pts += 1;\n  if(s.scene) pts += (s.scene.length > 15 ? 2 : 1);\n  if(s.jeu) pts += 2;\n  if(s.perso) pts += 2;\n  const pl = getPunchlines(s);\n  if(pl.length) pts += 3 + Math.min(pl.length - 1, 2);\n  if(s.chute) pts += 3;\n  pts += Math.min((s.emotions || []).length, 2);\n  if(s.duration) pts += 1;\n  return pts;\n}\n\nfunction userLevelInfo(totalXp){\n  let current = USER_LEVELS[0];\n  let idx = 0;\n  USER_LEVELS.forEach((l,i)=>{ if(totalXp >= l.min){ current = l; idx = i; } });\n  const next = USER_LEVELS[idx+1];\n  const span = next ? (next.min - current.min) : 1;\n  const into = next ? (totalXp - current.min) : span;\n  const pct = next ? Math.min(100, Math.round(into\/span*100)) : 100;\n  return {\n    title: current.title,\n    index: idx+1,\n    total: USER_LEVELS.length,\n    xp: totalXp,\n    nextMin: next ? next.min : null,\n    pct\n  };\n}\n\nfunction renderUserLevel(){\n  const total = sparks.reduce((sum,s)=> sum + sparkXP(s), 0);\n  const info = userLevelInfo(total);\n  const xpLabel = info.nextMin != null ? `${info.xp} \/ ${info.nextMin} xp` : `${info.xp} xp \u00b7 max`;\n\n  if(el('tsLvlTitle')){\n    el('tsLvlTitle').textContent = `Niv.${info.index} \u00b7 ${info.title}`;\n    el('tsLvlXp').textContent = xpLabel;\n    el('tsLvlFill').style.width = info.pct + '%';\n    el('tsUserLvl').classList.toggle('show', sparks.length > 0);\n  }\n  if(el('appLvlTitle')){\n    el('appLvlTitle').textContent = `Niv.${info.index} \u00b7 ${info.title}`;\n    el('appLvlXp').textContent = xpLabel;\n    el('appLvlFill').style.width = info.pct + '%';\n  }\n}\n\nasync function scoreSpark(spark){\n  spark.scoring = true;\n  render();\n  const pl = getPunchlines(spark);\n  const plText = pl.length ? pl.map((p,i)=>`  ${i+1}. ${p}`).join('\\n') : '\u2014';\n  const prompt = `Tu es un coach de stand-up exigeant mais bienveillant. Voici les fragments bruts d'une id\u00e9e de sketch (pas r\u00e9dig\u00e9e, juste des bouts de mots) :\nLieu\/moment : ${spark.place || \"\u2014\"}\nMots-cl\u00e9s : ${spark.scene || \"\u2014\"}\nJeu (ton\/rythme\/geste) : ${spark.jeu || \"\u2014\"}\nPourquoi \u00e7a le fait rire : ${spark.perso || \"\u2014\"}\nPunchlines :\n${plText}\nChute : ${spark.chute || \"\u2014\"}\n\n\u00c9value le potentiel comique et la solidit\u00e9 de structure (accroche \u2192 punchlines \u2192 chute), m\u00eame \u00e0 l'\u00e9tat de fragments. Note de 1 \u00e0 10. R\u00e9ponds UNIQUEMENT avec un JSON strict, sans backticks ni texte autour : {\"score\": <entier 1-10>, \"raison\": \"<une phrase courte en fran\u00e7ais, directe>\"}`;\n\n  try{\n    const response = await fetch(\"https:\/\/api.anthropic.com\/v1\/messages\", {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application\/json\" },\n      body: JSON.stringify({\n        model: \"claude-sonnet-4-6\",\n        max_tokens: 200,\n        messages: [{ role: \"user\", content: prompt }]\n      })\n    });\n    const data = await response.json();\n    const text = (data.content || []).map(b => b.text || \"\").join(\"\").replace(\/```json|```\/g,\"\").trim();\n    const parsed = JSON.parse(text);\n    spark.score = Math.max(1, Math.min(10, parseInt(parsed.score,10)));\n    spark.scoreReason = parsed.raison || \"\";\n  }catch(e){\n    spark.score = null;\n    spark.scoreReason = \"\";\n  }\n  spark.scoring = false;\n  await persist();\n  render();\n}\n\nfunction showToast(msg){\n  toast.textContent = msg;\n  toast.classList.add('show');\n  setTimeout(()=> toast.classList.remove('show'), 1600);\n}\n\nfunction fmtDate(iso){\n  const d = new Date(iso);\n  return d.toLocaleDateString('fr-FR', {day:'2-digit', month:'short'}) + ' \u00b7 ' + d.toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'});\n}\n\nasync function loadSparks(){\n  try{\n    const res = await window.storage.get(STORAGE_KEY, false);\n    sparks = res ? JSON.parse(res.value) : [];\n  }catch(e){\n    sparks = [];\n  }\n  render();\n}\n\nasync function persist(){\n  try{\n    await window.storage.set(STORAGE_KEY, JSON.stringify(sparks), false);\n  }catch(e){\n    showToast(\"Erreur de sauvegarde, r\u00e9essaie\");\n  }\n}\n\nfunction resetForm(){\n  el('title').value = '';\n  el('place').value = '';\n  el('scene').value = '';\n  el('jeu').value = '';\n  el('perso').value = '';\n  el('punchline1').value = '';\n  el('punchline2').value = '';\n  el('punchline3').value = '';\n  el('chute').value = '';\n  selectedEmotions.clear();\n  selectedDuration = null;\n  document.querySelectorAll('.chip.on').forEach(c=>c.classList.remove('on'));\n  document.querySelectorAll('.dchip.on').forEach(c=>c.classList.remove('on'));\n}\n\nel('saveBtn').onclick = async ()=>{\n  const title = el('title').value.trim();\n  const scene = el('scene').value.trim();\n  const punchlines = [el('punchline1').value.trim(), el('punchline2').value.trim(), el('punchline3').value.trim()].filter(Boolean);\n  if(!title && !scene && !punchlines.length){\n    showToast(\"\u00c9cris au moins l'accroche, un mot-cl\u00e9 ou une punchline\");\n    return;\n  }\n  const spark = {\n    id: Date.now().toString(36) + Math.random().toString(36).slice(2,6),\n    title: title || \"(sans titre)\",\n    place: el('place').value.trim(),\n    emotions: Array.from(selectedEmotions),\n    scene,\n    jeu: el('jeu').value.trim(),\n    perso: el('perso').value.trim(),\n    punchlines,\n    chute: el('chute').value.trim(),\n    duration: selectedDuration,\n    date: new Date().toISOString()\n  };\n  sparks.unshift(spark);\n  await persist();\n  resetForm();\n  render();\n  showToast(\"\u00c9tincelle gard\u00e9e \u2726\");\n  scoreSpark(spark);\n};\n\nfunction render(){\n  countLabel.textContent = sparks.length;\n  renderUserLevel();\n  if(sparks.length === 0){\n    listZone.innerHTML = '<div class=\"empty\">Rien pour l\\'instant. Ta premi\u00e8re id\u00e9e peut \u00eatre aussi b\u00eate qu\\'une phrase \u2014 c\\'est suffisant pour rouvrir toute la sc\u00e8ne plus tard.<\/div>';\n    return;\n  }\n  listZone.innerHTML = '';\n  sparks.forEach(s=>{\n    const card = document.createElement('div');\n    card.className = 'card';\n    const tagsHtml = s.emotions.map(e=>`<span class=\"tag\">${e}<\/span>`).join('') + (s.duration ? `<span class=\"tag\">${s.duration}<\/span>` : '') + `<span class=\"xp-chip\">+${sparkXP(s)} xp<\/span>`;\n\n    let scoreHtml;\n    if(s.scoring){ scoreHtml = `<div class=\"score-badge pending\">\u00b7\u00b7\u00b7<\/div>`; }\n    else if(s.score != null){ scoreHtml = `<div class=\"score-badge ${s.score >= 6 ? 'good' : 'bad'}\" data-rescore=\"${s.id}\">${s.score}<\/div>`; }\n    else { scoreHtml = `<div class=\"score-badge\" data-rescore=\"${s.id}\" title=\"Noter avec l'IA\">?<\/div>`; }\n\n    card.innerHTML = `\n      <div class=\"card-top\">\n        <div class=\"card-title\">${escapeHtml(s.title)}<\/div>\n        <div style=\"display:flex; align-items:center; gap:8px;\">\n          <div class=\"card-date\">${fmtDate(s.date)}<\/div>\n          ${scoreHtml}\n        <\/div>\n      <\/div>\n      ${s.place ? `<div class=\"card-place\">\ud83d\udccd ${escapeHtml(s.place)}<\/div>` : ''}\n      ${s.jeu ? `<div class=\"card-jeu\">\ud83c\udfad ${escapeHtml(s.jeu)}<\/div>` : ''}\n      ${(()=>{ const pl = getPunchlines(s); return pl.length ? `<div class=\"card-punch\"><span class=\"lbl\">${pl.length>1?'Punchlines':'Punchline'}<\/span>${pl.map(escapeHtml).join(' \u00b7 ')}<\/div>` : ''; })()}\n      ${s.perso ? `<div class=\"card-perso\">\u275d ${escapeHtml(s.perso)}<\/div>` : ''}\n      ${tagsHtml ? `<div class=\"card-tags\">${tagsHtml}<\/div>` : ''}\n      ${s.status ? `<div class=\"status-pill ${s.status}\"><span class=\"dot\"><\/span>${s.status === 'ready' ? 'Pr\u00eat \u00e0 jouer' : '\u00c0 am\u00e9liorer'}<\/div>` : ''}\n      <div class=\"card-body\">\n        ${s.scene ? `<div class=\"row\"><div class=\"k\">Mots-cl\u00e9s<\/div><div class=\"v\">${escapeHtml(s.scene)}<\/div><\/div>` : ''}\n        ${s.chute ? `<div class=\"row\"><div class=\"k\">Chute<\/div><div class=\"v\">${escapeHtml(s.chute)}<\/div><\/div>` : ''}\n        ${s.scoreReason ? `<div class=\"score-reason\">\u2726 ${escapeHtml(s.scoreReason)}<\/div>` : ''}\n        <div class=\"row\">\n          <div class=\"k\">Statut<\/div>\n          <div class=\"status-toggle\">\n            <button class=\"status-btn needs ${s.status==='needs_work'?'active':''}\" data-status=\"needs_work\" data-id=\"${s.id}\">\ud83d\udd34 \u00c0 am\u00e9liorer<\/button>\n            <button class=\"status-btn ready ${s.status==='ready'?'active':''}\" data-status=\"ready\" data-id=\"${s.id}\">\ud83d\udfe2 Pr\u00eat \u00e0 jouer<\/button>\n          <\/div>\n        <\/div>\n        <div class=\"card-actions\">\n          <button class=\"del\" data-id=\"${s.id}\">Supprimer<\/button>\n        <\/div>\n      <\/div>\n    `;\n    if(s.id === openCardId) card.classList.add('open');\n    card.addEventListener('click', (ev)=>{\n      if(ev.target.closest('.del')) return;\n      if(ev.target.closest('.status-btn')){\n        ev.stopPropagation();\n        const btn = ev.target.closest('.status-btn');\n        const newStatus = btn.dataset.status;\n        s.status = (s.status === newStatus) ? null : newStatus;\n        persist();\n        render();\n        return;\n      }\n      if(ev.target.closest('[data-rescore]')){\n        ev.stopPropagation();\n        if(!s.scoring) scoreSpark(s);\n        return;\n      }\n      card.classList.toggle('open');\n      openCardId = card.classList.contains('open') ? s.id : null;\n    });\n    card.querySelector('.del').addEventListener('click', async (ev)=>{\n      ev.stopPropagation();\n      sparks = sparks.filter(x=>x.id !== s.id);\n      await persist();\n      render();\n      showToast(\"Supprim\u00e9e\");\n    });\n    listZone.appendChild(card);\n  });\n}\n\nfunction escapeHtml(str){\n  const d = document.createElement('div');\n  d.textContent = str;\n  return d.innerHTML;\n}\n\n\/* ---------- TITLE SCREEN \/ PROFILE ---------- *\/\nconst PROFILE_KEY = \"profile-v1\";\nlet profile = null;\nlet selectedColor = \"#e8590c\";\n\nasync function loadProfile(){\n  try{\n    const res = await window.storage.get(PROFILE_KEY, false);\n    profile = res ? JSON.parse(res.value) : null;\n  }catch(e){\n    profile = null;\n  }\n  if(profile){\n    el('btnContinue').classList.remove('disabled');\n    el('tsHint').textContent = \"reprendre : \" + profile.pseudo;\n    el('tsPseudo').textContent = profile.pseudo;\n    el('avatarBody').setAttribute('fill', profile.color || \"#e8590c\");\n  } else {\n    el('btnContinue').classList.add('disabled');\n    el('tsHint').textContent = \"aucune partie sauvegard\u00e9e\";\n  }\n}\n\nfunction enterApp(){\n  el('titleScreen').style.display = 'none';\n  const app = el('gameApp');\n  app.style.display = 'block';\n  requestAnimationFrame(()=> app.classList.add('show'));\n  if(profile){\n    el('mainEyebrow').textContent = \"carnet d'\u00e9tincelles \u2014 \" + profile.pseudo;\n  }\n}\n\nel('btnContinue').addEventListener('click', ()=>{\n  if(!profile) return;\n  enterApp();\n});\n\nel('btnNewGame').addEventListener('click', ()=>{\n  el('pseudoInput').value = profile ? profile.pseudo : '';\n  el('modalBackdrop').classList.add('show');\n  el('pseudoInput').focus();\n});\n\nel('modalCancel').addEventListener('click', ()=>{\n  el('modalBackdrop').classList.remove('show');\n});\n\ndocument.querySelectorAll('.ts-color').forEach(c=>{\n  c.addEventListener('click', ()=>{\n    document.querySelectorAll('.ts-color').forEach(x=>x.classList.remove('on'));\n    c.classList.add('on');\n    selectedColor = c.dataset.color;\n    el('avatarBody').setAttribute('fill', selectedColor);\n  });\n});\n\nel('modalConfirm').addEventListener('click', async ()=>{\n  const pseudo = el('pseudoInput').value.trim() || \"Sans nom\";\n  profile = { pseudo, color: selectedColor, createdAt: (profile && profile.createdAt) || new Date().toISOString() };\n  try{\n    await window.storage.set(PROFILE_KEY, JSON.stringify(profile), false);\n  }catch(e){\n    showToast(\"Erreur de sauvegarde du profil\");\n  }\n  el('modalBackdrop').classList.remove('show');\n  enterApp();\n});\n\nloadProfile();\nloadSparks();\n<\/script>\n\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>\u00c9tincelles \u2014 carnet de sketchs carnet d&rsquo;\u00e9tincelles SPARK \u20140 xp \u25b8Nouvelle sc\u00e8ne \u25b8Continuer aucune partie sauvegard\u00e9e Entrer en sc\u00e8ne Choisis ton nom de sc\u00e8ne et la couleur de ton avatar. C&rsquo;est juste pour toi. Annuler Entrer en sc\u00e8ne carnet d&rsquo;\u00e9tincelles SPARK Capture la sc\u00e8ne, pas le texte. Trois secondes suffisent pour ne pas la perdre. [&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-727","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/pages\/727","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/comments?post=727"}],"version-history":[{"count":5,"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/pages\/727\/revisions"}],"predecessor-version":[{"id":732,"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/pages\/727\/revisions\/732"}],"wp:attachment":[{"href":"https:\/\/lesracailles2shanghai.fr\/index.php\/wp-json\/wp\/v2\/media?parent=727"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}