diff --git a/frontend/textbooks/geometry_9_ch1.html b/frontend/textbooks/geometry_9_ch1.html index 0ad32f5..9c4ffc9 100644 --- a/frontend/textbooks/geometry_9_ch1.html +++ b/frontend/textbooks/geometry_9_ch1.html @@ -184,6 +184,38 @@ a{color:inherit;text-decoration:none} .search-empty{padding:20px;text-align:center;color:var(--muted);font-size:.88rem} .search-foot{padding:8px 14px;border-top:1px solid var(--border);font-size:.74rem;color:var(--muted);display:flex;gap:14px} .search-foot kbd{padding:2px 6px;background:var(--card);border:1px solid var(--border);border-radius:4px;font-family:'JetBrains Mono',monospace;font-size:.72rem} + +/* === GEOM9 POLISH (visual + micro-interactions) === */ +@keyframes wgFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}} +.sec.active .wg{animation:wgFadeIn .35s cubic-bezier(.16,1,.3,1) backwards} +.sec.active .wg:nth-of-type(1){animation-delay:.02s} +.sec.active .wg:nth-of-type(2){animation-delay:.08s} +.sec.active .wg:nth-of-type(3){animation-delay:.14s} +.sec.active .wg:nth-of-type(4){animation-delay:.20s} +.sec.active .wg:nth-of-type(5){animation-delay:.26s} +.sec.active .wg:nth-of-type(6){animation-delay:.32s} +.wg svg{transition:filter .25s ease} +.wg:hover svg{filter:drop-shadow(0 4px 16px rgba(0,0,0,.10))} +input[type=range]:active{box-shadow:0 0 0 4px var(--pri-soft);border-radius:8px} +.wg input[type=range]{cursor:ew-resize} +.score-display b{transition:transform .22s cubic-bezier(.16,1,.3,1),color .22s;display:inline-block;transform-origin:center} +.score-display b.bump{transform:scale(1.28);color:var(--pri)} +.katex{transition:color .2s} +.wg-help .katex:hover,.card-body .katex:hover{color:var(--pri2,var(--pri));cursor:help} +.hp-fill,.psel-prog-fill,.xp-fill,[id$="-overall-fill"]{transition:width .6s cubic-bezier(.16,1,.3,1)!important} +.boss-card,.btn.primary,.btn-primary{position:relative;overflow:hidden} +.btn.primary::after,.btn-primary::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at center,rgba(255,255,255,.42) 0%,transparent 60%);opacity:0;transition:opacity .25s;pointer-events:none} +.btn.primary:hover::after,.btn-primary:hover::after{opacity:1} +.psel-card{position:relative} +.psel-card .psel-done{position:absolute;top:6px;right:6px;width:18px;height:18px;border-radius:50%;background:#10b981;display:none;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(16,185,129,.45);z-index:2} +.psel-card .psel-done svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round} +.psel-card.done .psel-done{display:flex} +.boss-card{transition:border-color .35s,box-shadow .6s,background .3s,transform .2s} +.boss-card.glow{box-shadow:0 0 24px rgba(16,185,129,.6),0 0 0 2px rgba(16,185,129,.45)!important} +@keyframes bossPulse{0%{box-shadow:0 0 0 0 rgba(16,185,129,.55)}70%{box-shadow:0 0 0 14px rgba(16,185,129,0)}100%{box-shadow:0 0 0 0 rgba(16,185,129,0)}} +.boss-card.pulse{animation:bossPulse .8s ease-out} +.psel-card{transition:transform .2s,box-shadow .2s,border-color .2s,background .25s} +.sec{transition:opacity .25s} @@ -2679,6 +2711,132 @@ function init(){ } } document.addEventListener('DOMContentLoaded', init); + +/* === GEOM9 POLISH JS === */ +(function(){ + function bumpScore(el){ + if(!el) return; + el.classList.remove('bump'); + void el.offsetWidth; + el.classList.add('bump'); + setTimeout(function(){ try{ el.classList.remove('bump'); }catch(e){} }, 270); + } + window.__geom9BumpScore = bumpScore; + + /* Observe .score-display b text changes — auto bump */ + function observeScores(root){ + root = root || document; + var nodes = root.querySelectorAll('.score-display b'); + nodes.forEach(function(b){ + if(b.__scoreObs) return; + b.__scoreObs = true; + var last = b.textContent; + try{ + var mo = new MutationObserver(function(){ + var nv = b.textContent; + if(nv !== last){ last = nv; bumpScore(b); } + }); + mo.observe(b, {childList:true, characterData:true, subtree:true}); + }catch(e){} + }); + } + function rescanScores(){ try{ observeScores(document); }catch(e){} } + if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', rescanScores); + else rescanScores(); + + /* Re-scan on DOM additions (lazy-built sections) */ + try{ + var rootObs = new MutationObserver(function(muts){ + var need = false; + for(var i=0;i= 50 */ + function refreshDoneMarks(){ + try{ + if(typeof STATE === 'undefined' || !STATE.progress) return; + document.querySelectorAll('.psel-card').forEach(function(c){ + var id = c.dataset.id || c.dataset.progCard; + if(!id) return; + var pct = +STATE.progress[id] || 0; + if(!c.querySelector('.psel-done')){ + var s = document.createElement('span'); + s.className = 'psel-done'; + s.setAttribute('title','Прочитано'); + s.innerHTML = ''; + c.appendChild(s); + } + c.classList.toggle('done', pct >= 50); + }); + }catch(e){} + } + /* Wrap refreshProgressUI if present */ + try{ + if(typeof window.refreshProgressUI === 'function'){ + var _origRP = window.refreshProgressUI; + window.refreshProgressUI = function(){ var r = _origRP.apply(this, arguments); setTimeout(refreshDoneMarks, 0); return r; }; + } + }catch(e){} + setTimeout(refreshDoneMarks, 600); + setTimeout(refreshDoneMarks, 1800); + window.addEventListener('focus', function(){ setTimeout(refreshDoneMarks, 200); }); + + /* Smooth-scroll on psel-card click */ + document.addEventListener('click', function(e){ + var card = e.target.closest && e.target.closest('.psel-card'); + if(!card) return; + var id = card.dataset.id; + if(!id) return; + setTimeout(function(){ + var sec = document.getElementById('sec-' + id); + if(sec) try{ sec.scrollIntoView({behavior:'smooth', block:'start'}); }catch(e){} + }, 60); + }); + + /* Boss-card glow when defeated */ + function observeBossGlow(){ + var cards = document.querySelectorAll('.boss-card'); + cards.forEach(function(card){ + if(card.__bossObs) return; + card.__bossObs = true; + try{ + var mo = new MutationObserver(function(){ + if(card.__glowed) return; + var go = card.querySelector('button[id*="-go"]'); + var fb = card.querySelector('.feedback.ok, .boss-fb.ok'); + var defeatedByBtn = go && go.disabled; + var defeatedByFb = fb && fb.textContent && /Побед|повержен/i.test(fb.textContent); + if(defeatedByBtn || defeatedByFb){ + card.__glowed = true; + card.classList.add('glow','pulse'); + setTimeout(function(){ try{ card.classList.remove('pulse'); }catch(e){} }, 900); + setTimeout(function(){ try{ card.classList.remove('glow'); }catch(e){} }, 1400); + } + }); + mo.observe(card, {childList:true, subtree:true, attributes:true, attributeFilter:['class','style','disabled']}); + /* Initial: if already defeated (loaded from state) — skip glow (no animation on page load) */ + var goNow = card.querySelector('button[id*="-go"]'); + if(goNow && goNow.disabled) card.__glowed = true; + }catch(e){} + }); + } + var bossRescan = function(){ try{ observeBossGlow(); }catch(e){} }; + setTimeout(bossRescan, 800); + var bossPoll = setInterval(bossRescan, 2500); + setTimeout(function(){ try{ clearInterval(bossPoll); }catch(e){} }, 90000); +})(); diff --git a/frontend/textbooks/geometry_9_ch2.html b/frontend/textbooks/geometry_9_ch2.html index 3ceea07..7788d5e 100644 --- a/frontend/textbooks/geometry_9_ch2.html +++ b/frontend/textbooks/geometry_9_ch2.html @@ -165,6 +165,38 @@ a{color:inherit;text-decoration:none} .search-empty{padding:20px;text-align:center;color:var(--muted);font-size:.88rem} .search-foot{padding:8px 14px;border-top:1px solid var(--border);font-size:.74rem;color:var(--muted);display:flex;gap:14px} .search-foot kbd{padding:2px 6px;background:var(--card);border:1px solid var(--border);border-radius:4px;font-family:'JetBrains Mono',monospace;font-size:.72rem} + +/* === GEOM9 POLISH (visual + micro-interactions) === */ +@keyframes wgFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}} +.sec.active .wg{animation:wgFadeIn .35s cubic-bezier(.16,1,.3,1) backwards} +.sec.active .wg:nth-of-type(1){animation-delay:.02s} +.sec.active .wg:nth-of-type(2){animation-delay:.08s} +.sec.active .wg:nth-of-type(3){animation-delay:.14s} +.sec.active .wg:nth-of-type(4){animation-delay:.20s} +.sec.active .wg:nth-of-type(5){animation-delay:.26s} +.sec.active .wg:nth-of-type(6){animation-delay:.32s} +.wg svg{transition:filter .25s ease} +.wg:hover svg{filter:drop-shadow(0 4px 16px rgba(0,0,0,.10))} +input[type=range]:active{box-shadow:0 0 0 4px var(--pri-soft);border-radius:8px} +.wg input[type=range]{cursor:ew-resize} +.score-display b{transition:transform .22s cubic-bezier(.16,1,.3,1),color .22s;display:inline-block;transform-origin:center} +.score-display b.bump{transform:scale(1.28);color:var(--pri)} +.katex{transition:color .2s} +.wg-help .katex:hover,.card-body .katex:hover{color:var(--pri2,var(--pri));cursor:help} +.hp-fill,.psel-prog-fill,.xp-fill,[id$="-overall-fill"]{transition:width .6s cubic-bezier(.16,1,.3,1)!important} +.boss-card,.btn.primary,.btn-primary{position:relative;overflow:hidden} +.btn.primary::after,.btn-primary::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at center,rgba(255,255,255,.42) 0%,transparent 60%);opacity:0;transition:opacity .25s;pointer-events:none} +.btn.primary:hover::after,.btn-primary:hover::after{opacity:1} +.psel-card{position:relative} +.psel-card .psel-done{position:absolute;top:6px;right:6px;width:18px;height:18px;border-radius:50%;background:#10b981;display:none;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(16,185,129,.45);z-index:2} +.psel-card .psel-done svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round} +.psel-card.done .psel-done{display:flex} +.boss-card{transition:border-color .35s,box-shadow .6s,background .3s,transform .2s} +.boss-card.glow{box-shadow:0 0 24px rgba(16,185,129,.6),0 0 0 2px rgba(16,185,129,.45)!important} +@keyframes bossPulse{0%{box-shadow:0 0 0 0 rgba(16,185,129,.55)}70%{box-shadow:0 0 0 14px rgba(16,185,129,0)}100%{box-shadow:0 0 0 0 rgba(16,185,129,0)}} +.boss-card.pulse{animation:bossPulse .8s ease-out} +.psel-card{transition:transform .2s,box-shadow .2s,border-color .2s,background .25s} +.sec{transition:opacity .25s} @@ -1615,6 +1647,125 @@ function init(){ } } document.addEventListener('DOMContentLoaded', init); + +/* === GEOM9 POLISH JS === */ +(function(){ + function bumpScore(el){ + if(!el) return; + el.classList.remove('bump'); + void el.offsetWidth; + el.classList.add('bump'); + setTimeout(function(){ try{ el.classList.remove('bump'); }catch(e){} }, 270); + } + window.__geom9BumpScore = bumpScore; + + function observeScores(root){ + root = root || document; + var nodes = root.querySelectorAll('.score-display b'); + nodes.forEach(function(b){ + if(b.__scoreObs) return; + b.__scoreObs = true; + var last = b.textContent; + try{ + var mo = new MutationObserver(function(){ + var nv = b.textContent; + if(nv !== last){ last = nv; bumpScore(b); } + }); + mo.observe(b, {childList:true, characterData:true, subtree:true}); + }catch(e){} + }); + } + function rescanScores(){ try{ observeScores(document); }catch(e){} } + if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', rescanScores); + else rescanScores(); + + try{ + var rootObs = new MutationObserver(function(muts){ + var need = false; + for(var i=0;i= 50); + }); + }catch(e){} + } + try{ + if(typeof window.refreshProgressUI === 'function'){ + var _origRP = window.refreshProgressUI; + window.refreshProgressUI = function(){ var r = _origRP.apply(this, arguments); setTimeout(refreshDoneMarks, 0); return r; }; + } + }catch(e){} + setTimeout(refreshDoneMarks, 600); + setTimeout(refreshDoneMarks, 1800); + window.addEventListener('focus', function(){ setTimeout(refreshDoneMarks, 200); }); + + document.addEventListener('click', function(e){ + var card = e.target.closest && e.target.closest('.psel-card'); + if(!card) return; + var id = card.dataset.id; + if(!id) return; + setTimeout(function(){ + var sec = document.getElementById('sec-' + id); + if(sec) try{ sec.scrollIntoView({behavior:'smooth', block:'start'}); }catch(e){} + }, 60); + }); + + function observeBossGlow(){ + var cards = document.querySelectorAll('.boss-card'); + cards.forEach(function(card){ + if(card.__bossObs) return; + card.__bossObs = true; + try{ + var mo = new MutationObserver(function(){ + if(card.__glowed) return; + var go = card.querySelector('button[id*="-go"]'); + var fb = card.querySelector('.feedback.ok, .boss-fb.ok'); + var defeatedByBtn = go && go.disabled; + var defeatedByFb = fb && fb.textContent && /Побед|повержен/i.test(fb.textContent); + if(defeatedByBtn || defeatedByFb){ + card.__glowed = true; + card.classList.add('glow','pulse'); + setTimeout(function(){ try{ card.classList.remove('pulse'); }catch(e){} }, 900); + setTimeout(function(){ try{ card.classList.remove('glow'); }catch(e){} }, 1400); + } + }); + mo.observe(card, {childList:true, subtree:true, attributes:true, attributeFilter:['class','style','disabled']}); + var goNow = card.querySelector('button[id*="-go"]'); + if(goNow && goNow.disabled) card.__glowed = true; + }catch(e){} + }); + } + var bossRescan = function(){ try{ observeBossGlow(); }catch(e){} }; + setTimeout(bossRescan, 800); + var bossPoll = setInterval(bossRescan, 2500); + setTimeout(function(){ try{ clearInterval(bossPoll); }catch(e){} }, 90000); +})(); diff --git a/frontend/textbooks/geometry_9_ch3.html b/frontend/textbooks/geometry_9_ch3.html index 54b2eb5..9087060 100644 --- a/frontend/textbooks/geometry_9_ch3.html +++ b/frontend/textbooks/geometry_9_ch3.html @@ -165,6 +165,38 @@ a{color:inherit;text-decoration:none} .search-empty{padding:20px;text-align:center;color:var(--muted);font-size:.88rem} .search-foot{padding:8px 14px;border-top:1px solid var(--border);font-size:.74rem;color:var(--muted);display:flex;gap:14px} .search-foot kbd{padding:2px 6px;background:var(--card);border:1px solid var(--border);border-radius:4px;font-family:'JetBrains Mono',monospace;font-size:.72rem} + +/* === GEOM9 POLISH (visual + micro-interactions) === */ +@keyframes wgFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}} +.sec.active .wg{animation:wgFadeIn .35s cubic-bezier(.16,1,.3,1) backwards} +.sec.active .wg:nth-of-type(1){animation-delay:.02s} +.sec.active .wg:nth-of-type(2){animation-delay:.08s} +.sec.active .wg:nth-of-type(3){animation-delay:.14s} +.sec.active .wg:nth-of-type(4){animation-delay:.20s} +.sec.active .wg:nth-of-type(5){animation-delay:.26s} +.sec.active .wg:nth-of-type(6){animation-delay:.32s} +.wg svg{transition:filter .25s ease} +.wg:hover svg{filter:drop-shadow(0 4px 16px rgba(0,0,0,.10))} +input[type=range]:active{box-shadow:0 0 0 4px var(--pri-soft);border-radius:8px} +.wg input[type=range]{cursor:ew-resize} +.score-display b{transition:transform .22s cubic-bezier(.16,1,.3,1),color .22s;display:inline-block;transform-origin:center} +.score-display b.bump{transform:scale(1.28);color:var(--pri)} +.katex{transition:color .2s} +.wg-help .katex:hover,.card-body .katex:hover{color:var(--pri2,var(--pri));cursor:help} +.hp-fill,.psel-prog-fill,.xp-fill,[id$="-overall-fill"]{transition:width .6s cubic-bezier(.16,1,.3,1)!important} +.boss-card,.btn.primary,.btn-primary{position:relative;overflow:hidden} +.btn.primary::after,.btn-primary::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at center,rgba(255,255,255,.42) 0%,transparent 60%);opacity:0;transition:opacity .25s;pointer-events:none} +.btn.primary:hover::after,.btn-primary:hover::after{opacity:1} +.psel-card{position:relative} +.psel-card .psel-done{position:absolute;top:6px;right:6px;width:18px;height:18px;border-radius:50%;background:#10b981;display:none;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(16,185,129,.45);z-index:2} +.psel-card .psel-done svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round} +.psel-card.done .psel-done{display:flex} +.boss-card{transition:border-color .35s,box-shadow .6s,background .3s,transform .2s} +.boss-card.glow{box-shadow:0 0 24px rgba(16,185,129,.6),0 0 0 2px rgba(16,185,129,.45)!important} +@keyframes bossPulse{0%{box-shadow:0 0 0 0 rgba(16,185,129,.55)}70%{box-shadow:0 0 0 14px rgba(16,185,129,0)}100%{box-shadow:0 0 0 0 rgba(16,185,129,0)}} +.boss-card.pulse{animation:bossPulse .8s ease-out} +.psel-card{transition:transform .2s,box-shadow .2s,border-color .2s,background .25s} +.sec{transition:opacity .25s} @@ -1612,6 +1644,125 @@ function init(){ } } document.addEventListener('DOMContentLoaded', init); + +/* === GEOM9 POLISH JS === */ +(function(){ + function bumpScore(el){ + if(!el) return; + el.classList.remove('bump'); + void el.offsetWidth; + el.classList.add('bump'); + setTimeout(function(){ try{ el.classList.remove('bump'); }catch(e){} }, 270); + } + window.__geom9BumpScore = bumpScore; + + function observeScores(root){ + root = root || document; + var nodes = root.querySelectorAll('.score-display b'); + nodes.forEach(function(b){ + if(b.__scoreObs) return; + b.__scoreObs = true; + var last = b.textContent; + try{ + var mo = new MutationObserver(function(){ + var nv = b.textContent; + if(nv !== last){ last = nv; bumpScore(b); } + }); + mo.observe(b, {childList:true, characterData:true, subtree:true}); + }catch(e){} + }); + } + function rescanScores(){ try{ observeScores(document); }catch(e){} } + if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', rescanScores); + else rescanScores(); + + try{ + var rootObs = new MutationObserver(function(muts){ + var need = false; + for(var i=0;i= 50); + }); + }catch(e){} + } + try{ + if(typeof window.refreshProgressUI === 'function'){ + var _origRP = window.refreshProgressUI; + window.refreshProgressUI = function(){ var r = _origRP.apply(this, arguments); setTimeout(refreshDoneMarks, 0); return r; }; + } + }catch(e){} + setTimeout(refreshDoneMarks, 600); + setTimeout(refreshDoneMarks, 1800); + window.addEventListener('focus', function(){ setTimeout(refreshDoneMarks, 200); }); + + document.addEventListener('click', function(e){ + var card = e.target.closest && e.target.closest('.psel-card'); + if(!card) return; + var id = card.dataset.id; + if(!id) return; + setTimeout(function(){ + var sec = document.getElementById('sec-' + id); + if(sec) try{ sec.scrollIntoView({behavior:'smooth', block:'start'}); }catch(e){} + }, 60); + }); + + function observeBossGlow(){ + var cards = document.querySelectorAll('.boss-card'); + cards.forEach(function(card){ + if(card.__bossObs) return; + card.__bossObs = true; + try{ + var mo = new MutationObserver(function(){ + if(card.__glowed) return; + var go = card.querySelector('button[id*="-go"]'); + var fb = card.querySelector('.feedback.ok, .boss-fb.ok'); + var defeatedByBtn = go && go.disabled; + var defeatedByFb = fb && fb.textContent && /Побед|повержен/i.test(fb.textContent); + if(defeatedByBtn || defeatedByFb){ + card.__glowed = true; + card.classList.add('glow','pulse'); + setTimeout(function(){ try{ card.classList.remove('pulse'); }catch(e){} }, 900); + setTimeout(function(){ try{ card.classList.remove('glow'); }catch(e){} }, 1400); + } + }); + mo.observe(card, {childList:true, subtree:true, attributes:true, attributeFilter:['class','style','disabled']}); + var goNow = card.querySelector('button[id*="-go"]'); + if(goNow && goNow.disabled) card.__glowed = true; + }catch(e){} + }); + } + var bossRescan = function(){ try{ observeBossGlow(); }catch(e){} }; + setTimeout(bossRescan, 800); + var bossPoll = setInterval(bossRescan, 2500); + setTimeout(function(){ try{ clearInterval(bossPoll); }catch(e){} }, 90000); +})(); diff --git a/frontend/textbooks/geometry_9_ch4.html b/frontend/textbooks/geometry_9_ch4.html index b809491..616a4bc 100644 --- a/frontend/textbooks/geometry_9_ch4.html +++ b/frontend/textbooks/geometry_9_ch4.html @@ -180,6 +180,38 @@ a{color:inherit;text-decoration:none} .drop-box:hover{border-color:var(--pri);background:var(--pri-soft)} .drop-box h5{font-family:'Unbounded',sans-serif;font-size:.78rem;color:var(--pri2);margin-bottom:8px;text-transform:uppercase;letter-spacing:.05em} .drop-box.over{border-color:var(--pri);background:var(--pri-soft);border-style:solid;transform:scale(1.015)} + +/* === GEOM9 POLISH (visual + micro-interactions) === */ +@keyframes wgFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}} +.sec.active .wg{animation:wgFadeIn .35s cubic-bezier(.16,1,.3,1) backwards} +.sec.active .wg:nth-of-type(1){animation-delay:.02s} +.sec.active .wg:nth-of-type(2){animation-delay:.08s} +.sec.active .wg:nth-of-type(3){animation-delay:.14s} +.sec.active .wg:nth-of-type(4){animation-delay:.20s} +.sec.active .wg:nth-of-type(5){animation-delay:.26s} +.sec.active .wg:nth-of-type(6){animation-delay:.32s} +.wg svg{transition:filter .25s ease} +.wg:hover svg{filter:drop-shadow(0 4px 16px rgba(0,0,0,.10))} +input[type=range]:active{box-shadow:0 0 0 4px var(--pri-soft);border-radius:8px} +.wg input[type=range]{cursor:ew-resize} +.score-display b{transition:transform .22s cubic-bezier(.16,1,.3,1),color .22s;display:inline-block;transform-origin:center} +.score-display b.bump{transform:scale(1.28);color:var(--pri)} +.katex{transition:color .2s} +.wg-help .katex:hover,.card-body .katex:hover{color:var(--pri2,var(--pri));cursor:help} +.hp-fill,.psel-prog-fill,.xp-fill,[id$="-overall-fill"]{transition:width .6s cubic-bezier(.16,1,.3,1)!important} +.boss-card,.btn.primary,.btn-primary{position:relative;overflow:hidden} +.btn.primary::after,.btn-primary::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at center,rgba(255,255,255,.42) 0%,transparent 60%);opacity:0;transition:opacity .25s;pointer-events:none} +.btn.primary:hover::after,.btn-primary:hover::after{opacity:1} +.psel-card{position:relative} +.psel-card .psel-done{position:absolute;top:6px;right:6px;width:18px;height:18px;border-radius:50%;background:#10b981;display:none;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(16,185,129,.45);z-index:2} +.psel-card .psel-done svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round} +.psel-card.done .psel-done{display:flex} +.boss-card{transition:border-color .35s,box-shadow .6s,background .3s,transform .2s} +.boss-card.glow{box-shadow:0 0 24px rgba(16,185,129,.6),0 0 0 2px rgba(16,185,129,.45)!important} +@keyframes bossPulse{0%{box-shadow:0 0 0 0 rgba(16,185,129,.55)}70%{box-shadow:0 0 0 14px rgba(16,185,129,0)}100%{box-shadow:0 0 0 0 rgba(16,185,129,0)}} +.boss-card.pulse{animation:bossPulse .8s ease-out} +.psel-card{transition:transform .2s,box-shadow .2s,border-color .2s,background .25s} +.sec{transition:opacity .25s} @@ -1925,6 +1957,125 @@ function init(){ } } document.addEventListener('DOMContentLoaded', init); + +/* === GEOM9 POLISH JS === */ +(function(){ + function bumpScore(el){ + if(!el) return; + el.classList.remove('bump'); + void el.offsetWidth; + el.classList.add('bump'); + setTimeout(function(){ try{ el.classList.remove('bump'); }catch(e){} }, 270); + } + window.__geom9BumpScore = bumpScore; + + function observeScores(root){ + root = root || document; + var nodes = root.querySelectorAll('.score-display b'); + nodes.forEach(function(b){ + if(b.__scoreObs) return; + b.__scoreObs = true; + var last = b.textContent; + try{ + var mo = new MutationObserver(function(){ + var nv = b.textContent; + if(nv !== last){ last = nv; bumpScore(b); } + }); + mo.observe(b, {childList:true, characterData:true, subtree:true}); + }catch(e){} + }); + } + function rescanScores(){ try{ observeScores(document); }catch(e){} } + if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', rescanScores); + else rescanScores(); + + try{ + var rootObs = new MutationObserver(function(muts){ + var need = false; + for(var i=0;i= 50); + }); + }catch(e){} + } + try{ + if(typeof window.refreshProgressUI === 'function'){ + var _origRP = window.refreshProgressUI; + window.refreshProgressUI = function(){ var r = _origRP.apply(this, arguments); setTimeout(refreshDoneMarks, 0); return r; }; + } + }catch(e){} + setTimeout(refreshDoneMarks, 600); + setTimeout(refreshDoneMarks, 1800); + window.addEventListener('focus', function(){ setTimeout(refreshDoneMarks, 200); }); + + document.addEventListener('click', function(e){ + var card = e.target.closest && e.target.closest('.psel-card'); + if(!card) return; + var id = card.dataset.id; + if(!id) return; + setTimeout(function(){ + var sec = document.getElementById('sec-' + id); + if(sec) try{ sec.scrollIntoView({behavior:'smooth', block:'start'}); }catch(e){} + }, 60); + }); + + function observeBossGlow(){ + var cards = document.querySelectorAll('.boss-card'); + cards.forEach(function(card){ + if(card.__bossObs) return; + card.__bossObs = true; + try{ + var mo = new MutationObserver(function(){ + if(card.__glowed) return; + var go = card.querySelector('button[id*="-go"]'); + var fb = card.querySelector('.feedback.ok, .boss-fb.ok'); + var defeatedByBtn = go && go.disabled; + var defeatedByFb = fb && fb.textContent && /Побед|повержен/i.test(fb.textContent); + if(defeatedByBtn || defeatedByFb){ + card.__glowed = true; + card.classList.add('glow','pulse'); + setTimeout(function(){ try{ card.classList.remove('pulse'); }catch(e){} }, 900); + setTimeout(function(){ try{ card.classList.remove('glow'); }catch(e){} }, 1400); + } + }); + mo.observe(card, {childList:true, subtree:true, attributes:true, attributeFilter:['class','style','disabled']}); + var goNow = card.querySelector('button[id*="-go"]'); + if(goNow && goNow.disabled) card.__glowed = true; + }catch(e){} + }); + } + var bossRescan = function(){ try{ observeBossGlow(); }catch(e){} }; + setTimeout(bossRescan, 800); + var bossPoll = setInterval(bossRescan, 2500); + setTimeout(function(){ try{ clearInterval(bossPoll); }catch(e){} }, 90000); +})(); diff --git a/frontend/textbooks/geometry_9_hub.html b/frontend/textbooks/geometry_9_hub.html index 9a87adf..80579ba 100644 --- a/frontend/textbooks/geometry_9_hub.html +++ b/frontend/textbooks/geometry_9_hub.html @@ -199,6 +199,34 @@ html.dark .final-cta-sub{color:#fcd34d} .final-cta-btn{padding:10px 18px;border-radius:10px;background:linear-gradient(135deg,var(--pri),#fb7185);color:#fff;text-decoration:none;font-weight:800;font-size:.9rem;display:inline-flex;align-items:center;gap:7px;transition:filter .15s} .final-cta-btn:hover{filter:brightness(1.1)} .final-cta-btn svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round} + +/* === GEOM9 POLISH (hub) === */ +@keyframes chCardIn{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}} +.ch-card{animation:chCardIn .4s cubic-bezier(.16,1,.3,1) backwards} +.ch-card:nth-child(1){animation-delay:.04s} +.ch-card:nth-child(2){animation-delay:.10s} +.ch-card:nth-child(3){animation-delay:.16s} +.ch-card:nth-child(4){animation-delay:.22s} +@keyframes bossCardIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}} +.final-wrap.open #fin-bosses-container .boss-card{animation:bossCardIn .35s cubic-bezier(.16,1,.3,1) backwards} +.final-wrap.open #fin-bosses-container .boss-card:nth-child(1){animation-delay:.06s} +.final-wrap.open #fin-bosses-container .boss-card:nth-child(2){animation-delay:.12s} +.final-wrap.open #fin-bosses-container .boss-card:nth-child(3){animation-delay:.18s} +.final-wrap.open #fin-bosses-container .boss-card:nth-child(4){animation-delay:.24s} +.final-wrap.open #fin-bosses-container .boss-card:nth-child(5){animation-delay:.30s} +.final-wrap.open #fin-bosses-container .boss-card:nth-child(6){animation-delay:.36s} +.final-wrap.open #fin-bosses-container .boss-card:nth-child(7){animation-delay:.42s} +.po-fill,.ch-prog-fill,.boss-overall-bar .fill{transition:width .6s cubic-bezier(.16,1,.3,1)!important} +.boss-btn,.ch-action,.final-cta-btn{position:relative;overflow:hidden} +.boss-btn::after,.ch-action::after,.final-cta-btn::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at center,rgba(255,255,255,.45) 0%,transparent 60%);opacity:0;transition:opacity .25s;pointer-events:none} +.boss-btn:hover::after,.ch-action:hover::after,.final-cta-btn:hover::after{opacity:1} +.cheat-list li .katex{transition:color .2s} +.cheat-list li .katex:hover{color:var(--pri-d);cursor:help} +.boss-card.glow-once{box-shadow:0 0 24px rgba(16,185,129,.6),0 0 0 2px rgba(16,185,129,.45)!important} +@keyframes bossPulseH{0%{box-shadow:0 0 0 0 rgba(16,185,129,.55)}70%{box-shadow:0 0 0 14px rgba(16,185,129,0)}100%{box-shadow:0 0 0 0 rgba(16,185,129,0)}} +.boss-card.pulse-once{animation:bossPulseH .85s ease-out} +.fin-boss-bar-bump b{transition:transform .2s,color .2s;display:inline-block} +.fin-boss-bar-bump b.bump{transform:scale(1.18);color:#10b981} @@ -836,6 +864,84 @@ if (document.readyState === 'loading') { loadProgress(); } window.addEventListener('focus', loadProgress); + +/* === GEOM9 HUB POLISH JS === */ +(function(){ + /* Smooth scroll into view when final opens */ + try{ + var finalHead = document.getElementById('final-head'); + var finalWrap = document.getElementById('course-final'); + if(finalHead && finalWrap){ + finalHead.addEventListener('click', function(){ + setTimeout(function(){ + if(finalWrap.classList.contains('open')){ + try{ finalWrap.scrollIntoView({behavior:'smooth', block:'start'}); }catch(e){} + } + }, 80); + }); + } + }catch(e){} + + /* Boss-card glow on defeat (one-shot, only on user action, not page-load state) */ + function observeFinBosses(){ + var cards = document.querySelectorAll('#fin-bosses-container .boss-card'); + cards.forEach(function(card){ + if(card.__finObs) return; + card.__finObs = true; + try{ + var go = card.querySelector('button[id*="-go"]'); + /* If already defeated at observation start — suppress glow */ + if(go && go.disabled) card.__glowed = true; + var mo = new MutationObserver(function(){ + if(card.__glowed) return; + var g = card.querySelector('button[id*="-go"]'); + if(g && g.disabled){ + card.__glowed = true; + card.classList.add('glow-once','pulse-once'); + setTimeout(function(){ try{ card.classList.remove('pulse-once'); }catch(e){} }, 900); + setTimeout(function(){ try{ card.classList.remove('glow-once'); }catch(e){} }, 1500); + } + }); + mo.observe(card, {childList:true, subtree:true, attributes:true, attributeFilter:['class','disabled']}); + }catch(e){} + }); + } + + /* Bump for boss overall counter */ + var lastLab = ''; + function bumpLab(){ + try{ + var lab = document.getElementById('fin-boss-lab'); + if(!lab) return; + var nv = lab.textContent; + if(nv === lastLab){ return; } + lastLab = nv; + if(!lab.parentElement.classList.contains('fin-boss-bar-bump')){ + lab.parentElement.classList.add('fin-boss-bar-bump'); + } + /* wrap digits in a if not already — simplest: bump the whole label briefly */ + lab.style.transition = 'transform .25s ease, color .25s'; + lab.style.transform = 'scale(1.04)'; + lab.style.color = '#10b981'; + setTimeout(function(){ + try{ lab.style.transform=''; lab.style.color=''; }catch(e){} + }, 320); + }catch(e){} + } + try{ + var labEl = document.getElementById('fin-boss-lab'); + if(labEl){ + lastLab = labEl.textContent; + var labObs = new MutationObserver(bumpLab); + labObs.observe(labEl, {childList:true, characterData:true, subtree:true}); + } + }catch(e){} + + /* Rescan periodically (final-body uses lazy render) */ + setTimeout(observeFinBosses, 600); + var pollT = setInterval(observeFinBosses, 1500); + setTimeout(function(){ try{ clearInterval(pollT); }catch(e){} }, 90000); +})();