المسابقات والعروض التفاعلية | www.flsafa.com :root{--bg:#f4f8ff;--cd:#fff;--tx:#1b2a4a;--bd:#d5e2fa;--in:#fff;box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)} @media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#0f172a;--cd:#1e293b;--tx:#e8eefc;--bd:#334155;--in:#0f172a}} :root[data-theme="dark"]{--bg:#0f172a;--cd:#1e293b;--tx:#e8eefc;--bd:#334155;--in:#0f172a} html{scroll-padding-top:env(safe-area-inset-top,0px)} *{box-sizing:border-box} body{margin:0;background:var(--bg);color:var(--tx);font:16px/1.8 Tajawal,Tahoma,sans-serif;background-color:var(--bg)} #app{max-width:760px;margin:0 auto;padding:12px} .hd{background:linear-gradient(135deg,#0a3d91,#035dcd 55%,#0b8f6a);color:#fff;border-radius:22px;padding:22px 16px;text-align:center} .hd img{max-height:70px;max-width:100%;margin-bottom:6px} .hd h1{margin:0;font-size:26px;font-weight:800;line-height:1.5} .hd p{margin:0;color:#e8f1ff} .bg{display:inline-block;margin-top:8px;background:#ffd166;color:#5a3d00;font-weight:800;border-radius:99px;padding:2px 16px;font-size:14px} .tabs{display:flex;gap:6px;margin:12px 0;overflow-x:auto} .tabs button{flex:1;white-space:nowrap;border:1px solid var(--bd);background:var(--cd);color:var(--tx);font:inherit;font-weight:700;border-radius:12px;padding:6px 12px;cursor:pointer} .tabs button.on{background:#035dcd;color:#fff;border-color:#035dcd} .cd{background:var(--cd);border-radius:18px;padding:16px;margin-bottom:12px;box-shadow:0 4px 14px rgba(20,33,61,.08)} .cd h2,.cd h3{margin:0 0 8px;color:#0a3d91} @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .cd h2,:root:not([data-theme="light"]) .cd h3{color:#9cc3ff}} :root[data-theme="dark"] .cd h2,:root[data-theme="dark"] .cd h3{color:#9cc3ff} .b{border:0;background:linear-gradient(135deg,#0b8f6a,#1f9d63);color:#fff;font:inherit;font-weight:800;border-radius:12px;padding:6px 18px;cursor:pointer;margin:4px 0} .sm{border:1px solid var(--bd);background:var(--in);color:var(--tx);font:inherit;font-size:14px;border-radius:10px;padding:0 10px;cursor:pointer;margin-inline-start:4px} .op{display:block;width:100%;text-align:start;border:2px solid var(--bd);background:var(--in);color:var(--tx);font:inherit;border-radius:12px;padding:6px 14px;margin:6px 0;cursor:pointer} .op.ok{border-color:#0b8f6a;background:#0b8f6a;color:#fff} .op.no{border-color:#c0392b;background:#c0392b;color:#fff} input,select,textarea{width:100%;font:inherit;color:var(--tx);background:var(--in);border:1px solid var(--bd);border-radius:10px;padding:4px 10px;margin:4px 0} label{font-weight:700;font-size:14px} .it{display:flex;justify-content:space-between;align-items:center;gap:8px;border-top:1px solid var(--bd);padding:6px 0} .it.col{display:block} .tl{display:flex;gap:8px;justify-content:center;margin-bottom:8px} .tl i{width:14px;height:14px;border-radius:50%;background:var(--bd);cursor:pointer} .tl i.on{background:#ffb100} .big{font-size:22px;font-weight:800} .cert{background:#fff;color:#1b2a4a;text-align:center;border:8px double #ffb100;border-radius:12px;padding:28px 14px;margin-bottom:12px} .cert img{max-height:70px} .cert h1{color:#0a3d91;margin:6px 0} .cert h2{color:#b36b00;margin:0} .ft{text-align:center;margin:14px 0} .ft a{color:#035dcd;font-weight:800;text-decoration:none} @media print{.nop,.ft{display:none!important}body{background:#fff}.cert{border-width:8px}} 🏠 www.flsafa.com var $=function(s){return document.querySelector(s)}; var E=function(s){return String(s).replace(/[&<>"]/g,function(c){return{'&':'&','<':'<','>':'>','"':'"'}[c]})}; var L={ar:{quiz:'المسابقة',show:'العرض',res:'النتائج',set:'الإعدادات',inst:'اسم المؤسسة',season:'الموسم الدراسي',date:'تاريخ الاحتفال',logo:'الشعار',lang:'اللغة',lv:'المستوى',lvs:['بسيط','متوسط','مركب'],all:'كل المستويات',name:'اسم المتعلم',start:'ابدأ المسابقة',next:'التالي',prev:'السابق',fin:'انتهت المسابقة',score:'النتيجة',q:'نص السؤال',o:'الخيار',ok:'الجواب الصحيح',save:'حفظ السؤال',del:'حذف',edit:'تعديل',add:'مشهد جديد',ttl:'العنوان',txt:'النص',cert:'شهادة',print:'طباعة',back:'رجوع',days:'يوم على الاحتفال',today:'اليوم يوم الاحتفال 🎉',none:'لا توجد نتائج بعد',noq:'لا توجد أسئلة في هذا المستوى',ct:'شهادة تقدير',cb:'تشهد المؤسسة بأن',cs:'حصل على النتيجة',mq:'إدارة الأسئلة',ms:'مشاهد العرض'}, fr:{quiz:'Concours',show:'Présentation',res:'Résultats',set:'Réglages',inst:"Nom de l'établissement",season:'Année scolaire',date:'Date de la fête',logo:'Logo',lang:'Langue',lv:'Niveau',lvs:['Simple','Moyen','Complexe'],all:'Tous les niveaux',name:"Nom de l'élève",start:'Commencer',next:'Suivant',prev:'Précédent',fin:'Concours terminé',score:'Score',q:'Question',o:'Choix',ok:'Bonne réponse',save:'Enregistrer',del:'Supprimer',edit:'Modifier',add:'Nouvelle scène',ttl:'Titre',txt:'Texte',cert:'Certificat',print:'Imprimer',back:'Retour',days:'jours avant la fête',today:"C'est le jour de la fête 🎉",none:'Aucun résultat',noq:'Aucune question à ce niveau',ct:'Certificat de mérite',cb:'Atteste que',cs:'a obtenu le score de',mq:'Gérer les questions',ms:'Scènes'}}; var D={cfg:{inst:'www.flsafa.com',season:'2026-2027',date:'2026-10-31',logo:'',lang:'ar'}, qs:[{q:'ما هي عاصمة المغرب؟',a:['الرباط','الدار البيضاء','فاس','طنجة'],c:0,l:0},{q:'كم عدد جهات المملكة المغربية؟',a:['10','12','14','16'],c:1,l:1},{q:'أي سلسلة جبال تمتد في وسط المغرب؟',a:['الأطلس','الألب','الأنديز','القوقاز'],c:0,l:2}], sc:[{t:'التمهيد',x:'كلمة افتتاحية حول مناسبة الاحتفال.'},{t:'الخط الزمني',x:'أهم المحطات التي نذكرها في هذه المناسبة.'},{t:'الختام',x:'خلاصة العرض وتوزيع الشهادات.'}],rs:[]}; try{var raw=localStorage.getItem('flsafa-tool');if(raw)D=Object.assign(D,JSON.parse(raw))}catch(e){} function sv(){try{localStorage.setItem('flsafa-tool',JSON.stringify(D))}catch(e){}} var T='quiz',P=null,ed=-1,vi=0,CT=null; function t(){return L[D.cfg.lang]} function lb(l){return l<0?t().all:t().lvs[l]} function vQuiz(s){ if(P){ if(P.done)return '<div class="cd"><h2>'+s.fin+'</h2><p class="big">'+s.score+': '+P.sc+' / '+P.l.length+'</p><button class="b" onclick="P=null;render()">'+s.back+'</button></div>'; var q=P.l[P.i]; return '<div class="cd"><p>'+(P.i+1)+' / '+P.l.length+' · '+lb(q.l)+'</p><h2>'+E(q.q)+'</h2>'+q.a.map(function(o,k){var cl=P.sel==null?'':k==q.c?' ok':k==P.sel?' no':'';return '<button class="op'+cl+'" onclick="ans('+k+')">'+E(o)+'</button>'}).join('')+(P.sel!=null?'<button class="b" onclick="nxt()">'+s.next+'</button>':'')+'</div>'} var f=ed>=0?D.qs[ed]:{q:'',a:['','','',''],c:0,l:0}; var opts=function(arr,sel){return arr.map(function(x,i){return '<option value="'+i+'"'+(i==sel?' selected':'')+'>'+x+'</option>'}).join('')}; return '<div class="cd"><label>'+s.name+'</label><input id="nm"><label>'+s.lv+'</label><select id="lv"><option value="-1">'+s.all+'</option>'+opts(s.lvs,-2)+'</select><button class="b" onclick="go()">'+s.start+'</button><p id="msg"></p></div>' +'<div class="cd"><h3>'+s.mq+'</h3><label>'+s.q+'</label><input id="qq" value="'+E(f.q)+'">'+[0,1,2,3].map(function(i){return '<input id="o'+i+'" placeholder="'+s.o+' '+(i+1)+'" value="'+E(f.a[i])+'">'}).join('') +'<label>'+s.ok+'</label><select id="oc">'+opts(['1','2','3','4'],f.c)+'</select><label>'+s.lv+'</label><select id="ol">'+opts(s.lvs,f.l)+'</select><button class="b" onclick="sq()">'+s.save+'</button>' +D.qs.map(function(x,i){return '<div class="it"><span>'+lb(x.l)+' · '+E(x.q)+'</span><span><button class="sm" onclick="ed='+i+';render()">'+s.edit+'</button><button class="sm" onclick="D.qs.splice('+i+',1);ed=-1;sv();render()">'+s.del+'</button></span></div>'}).join('')+'</div>'} function go(){var lv=+$('#lv').value,l=D.qs.filter(function(x){return lv<0||x.l==lv});if(!l.length){$('#msg').textContent=t().noq;return}P={n:$('#nm').value.trim()||'—',lv:lv,l:l,i:0,sc:0,sel:null};render()} function ans(k){if(P.sel!=null)return;P.sel=k;if(k==P.l[P.i].c)P.sc++;render()} function nxt(){P.i++;P.sel=null;if(P.i>=P.l.length){P.done=1;D.rs.push({n:P.n,s:P.sc,t:P.l.length,l:P.lv,d:new Date().toISOString().slice(0,10)});sv()}render()} function sq(){var a=[0,1,2,3].map(function(i){return $('#o'+i).value.trim()}),q=$('#qq').value.trim();if(!q||a.some(function(x){return !x}))return;var o={q:q,a:a,c:+$('#oc').value,l:+$('#ol').value};if(ed>=0)D.qs[ed]=o;else D.qs.push(o);ed=-1;sv();render()} function vShow(s){ var n=D.sc.length;if(vi>=n)vi=Math.max(0,n-1);var c=D.sc[vi]||{t:'',x:''}; return '<div class="cd"><div class="tl">'+D.sc.map(function(_,i){return '<i class="'+(i==vi?'on':'')+'" onclick="vi='+i+';render()"></i>'}).join('')+'</div><h2>'+E(c.t)+'</h2><p>'+E(c.x)+'</p><button class="b" onclick="vi=Math.max(0,vi-1);render()">'+s.prev+'</button> <button class="b" onclick="vi=Math.min('+Math.max(0,n-1)+',vi+1);render()">'+s.next+'</button></div>' +'<div class="cd"><h3>'+s.ms+'</h3>'+D.sc.map(function(x,i){return '<div class="it col"><input value="'+E(x.t)+'" oninput="D.sc['+i+'].t=this.value;sv()"><textarea rows="2" oninput="D.sc['+i+'].x=this.value;sv()">'+E(x.x)+'</textarea><button class="sm" onclick="D.sc.splice('+i+',1);sv();render()">'+s.del+'</button></div>'}).join('')+'<button class="b" onclick="D.sc.push({t:\'\',x:\'\'});vi=D.sc.length-1;sv();render()">+ '+s.add+'</button></div>'} function vRes(s){ return '<div class="cd">'+(D.rs.length?D.rs.map(function(r,i){return '<div class="it"><span>'+E(r.n)+' · '+r.s+'/'+r.t+' · '+lb(r.l)+' · '+r.d+'</span><button class="sm" onclick="CT='+i+';render()">'+s.cert+'</button></div>'}).join(''):'<p>'+s.none+'</p>')+'</div>'} function vSet(s){ return '<div class="cd"><label>'+s.inst+'</label><input value="'+E(D.cfg.inst)+'" onchange="D.cfg.inst=this.value;sv();render()"><label>'+s.season+'</label><input value="'+E(D.cfg.season)+'" onchange="D.cfg.season=this.value;sv();render()"><label>'+s.date+'</label><input type="date" value="'+D.cfg.date+'" onchange="D.cfg.date=this.value;sv();render()"><label>'+s.logo+'</label><input type="file" accept="image/*" onchange="lg(this)"><label>'+s.lang+'</label><select onchange="D.cfg.lang=this.value;sv();render()"><option value="ar"'+(D.cfg.lang=='ar'?' selected':'')+'>العربية</option><option value="fr"'+(D.cfg.lang=='fr'?' selected':'')+'>Français</option></select></div>'} function lg(el){var f=el.files[0];if(!f)return;var r=new FileReader();r.onload=function(){D.cfg.logo=r.result;sv();render()};r.readAsDataURL(f)} function render(){ var s=t(),c=D.cfg; document.documentElement.lang=c.lang;document.documentElement.dir=c.lang=='ar'?'rtl':'ltr'; var dl=c.date?Math.ceil((new Date(c.date)-new Date().setHours(0,0,0,0))/864e5):-1; var h='<div class="hd nop">'+(c.logo?'<img src="'+c.logo+'" alt="">':'')+'<h1>'+E(c.inst)+'</h1><p>'+E(c.season)+'</p>'+(dl>0?'<span class="bg">'+dl+' '+s.days+'</span>':dl==0?'<span class="bg">'+s.today+'</span>':'')+'</div>'; if(CT!=null&&D.rs[CT]){var r=D.rs[CT]; h+='<div class="cd cert" style="margin-top:12px">'+(c.logo?'<img src="'+c.logo+'" alt="">':'')+'<h2>'+s.ct+'</h2><p>'+s.cb+'</p><h1>'+E(r.n)+'</h1><p>'+s.cs+' '+r.s+' / '+r.t+'</p><p>'+E(c.inst)+' · '+E(c.season)+' · '+r.d+'</p><small>www.flsafa.com</small></div><div class="nop"><button class="b" onclick="window.print()">'+s.print+'</button> <button class="b" onclick="CT=null;render()">'+s.back+'</button></div>'; $('#app').innerHTML=h;return} h+='<div class="tabs nop">'+[['quiz',s.quiz],['show',s.show],['res',s.res],['set',s.set]].map(function(x){return '<button class="'+(T==x[0]?'on':'')+'" onclick="T=\''+x[0]+'\';P=null;render()">'+x[1]+'</button>'}).join('')+'</div><div class="nop">'+(T=='quiz'?vQuiz(s):T=='show'?vShow(s):T=='res'?vRes(s):vSet(s))+'</div>'; $('#app').innerHTML=h} render();