diff --git a/www/html/Game/data/quiz-settings.json b/www/html/Game/data/quiz-settings.json index 70089df..4a228d9 100644 --- a/www/html/Game/data/quiz-settings.json +++ b/www/html/Game/data/quiz-settings.json @@ -1,5 +1,5 @@ { - "readMs": 5000, + "readMs": 15000, "answerMs": 5000, "betweenMs": 3000, "carryReadMs": 3000, diff --git a/www/html/Game/public/img/QUESTION/README.txt b/www/html/Game/public/img/QUESTION/README.txt index ffff77a..4cc6b86 100644 --- a/www/html/Game/public/img/QUESTION/README.txt +++ b/www/html/Game/public/img/QUESTION/README.txt @@ -6,7 +6,7 @@ QUESTION — รูปสำหรับฉาก / อัปโหลด - **popup-Howto.png** — พื้นหลังหน้า HOWTO / คำแนะนำก่อนเริ่ม - **popup-result.png** — พื้นหลังแผงสรุปคะแนนท้ายเกม - - **time.png** — แผ่นตกแต่งกล่อง **TIME** กลางจอ Cyber HUD ระหว่างเล่น (แมป mng8a80o) + - **time.png** — กราฟิกคำว่า **TIME :** แสดงเป็น `` ซ้ายของตัวเลขนับถอยหลัง (ไม่ใช่พื้นหลังของบล็อก) — Cyber HUD แมป mng8a80o ระหว่างเล่น - **score-bar.png** — แผ่นตกแต่งแถบ **SCORE** ด้านซ้าย Cyber HUD (แมป mng8a80o) - **hud-time-plaque.png** — (เก่า / ทางเลือก) ถ้าไม่มี **time.png** โค้ดจะไม่ใช้ไฟล์นี้อีกต่อไปสำหรับ HUD หลัก — ใช้ **time.png** แทน - **hud-question-plaque.png** — (ไม่บังคับ / ไม่โหลดอัตโนมัติในเกม) ถ้าต้องการใช้รูป plaque ให้อัปโหลดไฟล์นี้แล้วผูกเองใน CSS หรือขยายโค้ด — ค่าเริ่มต้นใช้กรอบจากคลาส `quiz-map-question-panel--question-mission-live` แทน @@ -17,7 +17,7 @@ QUESTION — รูปสำหรับฉาก / อัปโหลด ถ้าไฟล์หาย ระบบ fallback ไป `/Game/img/gauntlet-assets/` ชื่อเดียวกัน (เฉพาะ popup-*) · แผ่น HUD ถ้าไม่มีไฟล์จะใช้ข้อความล้วน -English: Map **mng8a80o** uses mission UI; place **popup-Howto.png** and **popup-result.png** here. Cyber HUD plates: **time.png** (center timer), **score-bar.png** (left scoreboard). **hud-question-plaque.png** is not fetched by the client anymore (avoids 404); default question frame uses CSS class `quiz-map-question-panel--question-mission-live` unless you wire a custom image yourself. For correct-answer FX: **score+.png** (+10 popup over the correct zone). For mission summary wrong-answer stamp on avatars: **result-Lose_stamp.png** (falls back to gauntlet-assets if missing). Admin True/False tab icon: **admin-tab-minigame-1.png**. +English: Map **mng8a80o** uses mission UI; place **popup-Howto.png** and **popup-result.png** here. Cyber HUD: **time.png** is an inline **“TIME :”** graphic to the **left** of the countdown digit (not a full-block background); **score-bar.png** (left scoreboard). **hud-question-plaque.png** is not fetched by the client anymore (avoids 404); default question frame uses CSS class `quiz-map-question-panel--question-mission-live` unless you wire a custom image yourself. For correct-answer FX: **score+.png** (+10 popup over the correct zone). For mission summary wrong-answer stamp on avatars: **result-Lose_stamp.png** (falls back to gauntlet-assets if missing). Admin True/False tab icon: **admin-tab-minigame-1.png**. โฟลเดอร์นี้ถูกสร้างจาก repo + สคริปต์ deploy เพื่อหลีกเลี่ยงข้อผิดพลาด FTP: diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index f9336d5..2bbde9d 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -604,6 +604,9 @@ } const keys = {}; const characterImages = {}; + /** data URL จาก canvas compose สี — กันยิง toDataURL ทุกเฟรมตอน sync HUD */ + const cyberHudScoreAvatarUrlCache = new Map(); + const CYBER_HUD_AV_URL_CACHE_CAP = 56; function createDefaultAvatarImg() { const c = document.createElement('canvas'); c.width = 64; c.height = 64; @@ -5966,7 +5969,9 @@ if (fallbackUrl) imgEl.src = fallbackUrl; return; } - const tint = playTintFromPeerId(peerId != null ? String(peerId) : String(characterId)); + const tint = (peerId != null && myId != null && String(peerId) === String(myId)) + ? (me.playTint || playTintFromPeerId(String(peerId))) + : playTintFromPeerId(peerId != null ? String(peerId) : String(characterId)); const out = getPlayTintedAvatarSource(rawImg, characterId, 'down', nowT, false, tint); if (out && out.tagName === 'CANVAS' && out.width > 0) { try { @@ -8432,8 +8437,11 @@ img.alt = ''; const cid = r.characterId ? String(r.characterId) : ''; if (cid) { - const im = getCharacterImg(cid, 'down'); - if (im && im.src) img.src = im.src; + setCyberHudScoreAvatarImg(img, { + id: r.id, + characterId: cid, + isMe: myId != null && r.id != null && String(r.id) === String(myId), + }); } else { img.src = defaultAvatarImg.src; } @@ -13325,29 +13333,19 @@ delete qPlaque.dataset.qmQsrc; } } - if (tb) { - const tUrl = questionMissionHudAssetUrl('time.png'); - if (on) { - if (tb.dataset.qmTimeSrc !== tUrl) { - tb.dataset.qmTimeSrc = tUrl; - const im = new Image(); - im.onload = function () { - tb.style.backgroundImage = 'url(' + tUrl + ')'; - tb.style.backgroundSize = '100% auto'; - tb.style.backgroundPosition = '50% 0'; - tb.style.backgroundRepeat = 'no-repeat'; - tb.style.paddingTop = 'clamp(22px, 6.5vmin, 44px)'; - tb.style.minWidth = 'min(280px, 78vw)'; - }; - im.onerror = function () { - tb.style.backgroundImage = ''; - tb.style.paddingTop = ''; - tb.style.minWidth = ''; - delete tb.dataset.qmTimeSrc; - }; - im.src = tUrl; - } - } else { + const plaqueImg = root ? document.getElementById('play-cyber-time-plaque-img') : null; + const head = tb && tb.querySelector ? tb.querySelector('.play-cyber-time-head') : null; + const clearQmTimePlaque = () => { + if (plaqueImg) { + plaqueImg.onload = null; + plaqueImg.onerror = null; + plaqueImg.removeAttribute('src'); + plaqueImg.classList.add('is-hidden'); + plaqueImg.setAttribute('aria-hidden', 'true'); + delete plaqueImg.dataset.qmTimeSrc; + } + if (head) head.classList.remove('play-cyber-time-head--qm-plaque'); + if (tb) { tb.style.backgroundImage = ''; tb.style.backgroundSize = ''; tb.style.backgroundPosition = ''; @@ -13356,6 +13354,92 @@ tb.style.minWidth = ''; delete tb.dataset.qmTimeSrc; } + }; + if (tb && plaqueImg && head) { + const tUrl = questionMissionHudAssetUrl('time.png'); + if (on) { + tb.style.backgroundImage = ''; + tb.style.backgroundSize = ''; + tb.style.backgroundPosition = ''; + tb.style.backgroundRepeat = ''; + tb.style.paddingTop = ''; + tb.style.minWidth = ''; + const applyPlaque = () => { + head.classList.add('play-cyber-time-head--qm-plaque'); + plaqueImg.classList.remove('is-hidden'); + plaqueImg.setAttribute('aria-hidden', 'false'); + }; + if (plaqueImg.dataset.qmTimeSrc === tUrl && plaqueImg.getAttribute('src') === tUrl + && plaqueImg.complete && (plaqueImg.naturalWidth || 0) > 0) { + applyPlaque(); + } else if (plaqueImg.dataset.qmTimeSrc !== tUrl || plaqueImg.getAttribute('src') !== tUrl) { + plaqueImg.dataset.qmTimeSrc = tUrl; + plaqueImg.onload = function () { + if ((plaqueImg.naturalWidth || 0) > 0) applyPlaque(); + else clearQmTimePlaque(); + }; + plaqueImg.onerror = function () { + clearQmTimePlaque(); + }; + plaqueImg.setAttribute('src', tUrl); + } + } else { + clearQmTimePlaque(); + } + } + } + + /** แถบ Cyber SCORE — ใช้ tint เดียวกับในเกม (ไม่ใช้ PNG รวมซิลูเอตขาวจาก getCharacterImg อย่างเดียว) */ + function setCyberHudScoreAvatarImg(avImg, row) { + const cid = row.characterId ? String(row.characterId) : ''; + if (!cid) { + avImg.src = defaultAvatarImg.src; + return; + } + const dir = 'down'; + const nowT = Date.now(); + const walk = false; + const rawImg = getAvatarImg(cid, dir, nowT, walk); + const peerId = row.id; + const tint = row.isMe + ? (me.playTint || playTintFromPeerId(String(myId != null ? myId : 'me'))) + : (() => { + const ox = others.get(peerId); + return ox ? (ox.playTint || playTintFromPeerId(String(peerId))) : playTintFromPeerId(String(peerId)); + })(); + const cacheKey = [row.isMe ? 'me' : String(peerId), cid, tint.head, tint.hair, tint.body].join('|'); + const comp = rawImg && cid && tint + ? getPlayTintedAvatarSource(rawImg, cid, dir, nowT, walk, tint) + : rawImg; + if (comp && comp.tagName === 'CANVAS' && comp.width > 0) { + let dataUrl = cyberHudScoreAvatarUrlCache.get(cacheKey); + if (!dataUrl) { + try { + dataUrl = comp.toDataURL('image/png'); + } catch (e) { + dataUrl = ''; + } + if (dataUrl) { + if (cyberHudScoreAvatarUrlCache.size >= CYBER_HUD_AV_URL_CACHE_CAP) { + const first = cyberHudScoreAvatarUrlCache.keys().next(); + if (!first.done) cyberHudScoreAvatarUrlCache.delete(first.value); + } + cyberHudScoreAvatarUrlCache.set(cacheKey, dataUrl); + } + } + if (dataUrl) { + avImg.src = dataUrl; + return; + } + const im = getCharacterImg(cid, dir); + avImg.src = im && im.src ? im.src : defaultAvatarImg.src; + return; + } + if (comp && comp.src) { + avImg.src = comp.src; + } else { + const im = getCharacterImg(cid, dir); + avImg.src = im && im.src ? im.src : defaultAvatarImg.src; } } @@ -13526,39 +13610,41 @@ } if (hintEl) { if (isQuizQuestionMissionHudActivePlay()) { - hintEl.textContent = playQuizPhaseLocal === 'answer' - ? 'เดินไปโซน จริง / เท็จ ตามคำถามด้านบน · หมดเวลาแล้วไปข้อถัดไป' - : 'อ่านคำถามกลางจอ — เมื่อเข้ารอบตอบให้เดินไปโซนสีฟ้า (จริง) หรือชมพู (เท็จ)'; - } else if (isStackTowerMissionHudActivePlay()) { - hintEl.textContent = 'กด SPACE / ENTER หรือคลิกที่จอ = DROP · วางต่อเนื่องแม่น = โบนัส · ถอดรหัสให้ครบ 100% ภายในเวลา'; - } else if (isQuizCarry()) { - hintEl.textContent = quizCarrySessionEnded - ? 'ชุดคำถามจบแล้ว · Session ended — ดูคะแนนด้าน SCORE' - : ('ยืนโซนตัวเลือกแล้วกด F/Grab หยิบ · ถือป้ายถูกแล้วไปฮับส่ง — ถูก +' + QUIZ_CARRY_POINTS_PER_CORRECT + ' แต้ม (correct +' + QUIZ_CARRY_POINTS_PER_CORRECT + ' on hub)'); - } else if (isJumpSurvive()) { - if (isJumpSurviveMissionUiMapPlay()) { - hintEl.textContent = jumpSurviveEliminated - ? 'คุณตกน้ำแล้ว — ดูเพื่อนต่อ — รอจบเพื่อรับคะแนน (ผู้รอดได้ 100 คะแนน)' - : 'กระโดดตามแท่น — หลีกหนาม/กับดักด้านล่าง · หมดเวลาแล้วสรุปคะแนน (ผู้รอด 100) · Space / W / ↑ กระโดด · A D / ← → เดิน'; - } else { - hintEl.textContent = jumpSurviveEliminated - ? 'Spectate remaining nodes · Exit room to reset session' - : 'Space / W / ↑ jump · A D / arrows move · Hit ceiling/floor = out (watch others)'; - } - } else if (isSpaceShooter()) { - hintEl.textContent = spaceShooterGameEnded - ? 'จบแล้ว · Session ended — ดูอันดับบน overlay / see rankings on overlay' - : 'A D / ← → = move · W S / ↑ ↓ = up/down (lower half of map only) · Space = fire · +5 per hit'; - } else if (isBalloonBoss()) { - hintEl.textContent = balloonBossGameEnded - ? 'จบแล้ว · Session ended — see overlay' - : (me.balloonBossEliminated - ? 'คุณตกรอบแล้ว — ดูเพื่อนเล่น · You are out — spectate' - : 'ยานมีแรงเฉื่อย — A D / arrows / W S เร่งทิศทาง · ปล่อยปุ่มแล้วยังไหล (แรงหน่วง) · Space = ยิง (ดีเลย์) · ลูกโป้งหมด = ตกรอบ'); - } else if (isGauntletCrownHeistMapPlay()) { - hintEl.textContent = 'Space / W / ↑ jump · Start 100 pts · Hit -10 · Fall off left edge = out · Rank bonus at end'; + hintEl.textContent = ''; + hintEl.setAttribute('aria-hidden', 'true'); } else { - hintEl.textContent = 'Space / W / ↑ jump · Lanes + lasers · Clear = right + score'; + hintEl.removeAttribute('aria-hidden'); + if (isStackTowerMissionHudActivePlay()) { + hintEl.textContent = 'กด SPACE / ENTER หรือคลิกที่จอ = DROP · วางต่อเนื่องแม่น = โบนัส · ถอดรหัสให้ครบ 100% ภายในเวลา'; + } else if (isQuizCarry()) { + hintEl.textContent = quizCarrySessionEnded + ? 'ชุดคำถามจบแล้ว · Session ended — ดูคะแนนด้าน SCORE' + : ('ยืนโซนตัวเลือกแล้วกด F/Grab หยิบ · ถือป้ายถูกแล้วไปฮับส่ง — ถูก +' + QUIZ_CARRY_POINTS_PER_CORRECT + ' แต้ม (correct +' + QUIZ_CARRY_POINTS_PER_CORRECT + ' on hub)'); + } else if (isJumpSurvive()) { + if (isJumpSurviveMissionUiMapPlay()) { + hintEl.textContent = jumpSurviveEliminated + ? 'คุณตกน้ำแล้ว — ดูเพื่อนต่อ — รอจบเพื่อรับคะแนน (ผู้รอดได้ 100 คะแนน)' + : 'กระโดดตามแท่น — หลีกหนาม/กับดักด้านล่าง · หมดเวลาแล้วสรุปคะแนน (ผู้รอด 100) · Space / W / ↑ กระโดด · A D / ← → เดิน'; + } else { + hintEl.textContent = jumpSurviveEliminated + ? 'Spectate remaining nodes · Exit room to reset session' + : 'Space / W / ↑ jump · A D / arrows move · Hit ceiling/floor = out (watch others)'; + } + } else if (isSpaceShooter()) { + hintEl.textContent = spaceShooterGameEnded + ? 'จบแล้ว · Session ended — ดูอันดับบน overlay / see rankings on overlay' + : 'A D / ← → = move · W S / ↑ ↓ = up/down (lower half of map only) · Space = fire · +5 per hit'; + } else if (isBalloonBoss()) { + hintEl.textContent = balloonBossGameEnded + ? 'จบแล้ว · Session ended — see overlay' + : (me.balloonBossEliminated + ? 'คุณตกรอบแล้ว — ดูเพื่อนเล่น · You are out — spectate' + : 'ยานมีแรงเฉื่อย — A D / arrows / W S เร่งทิศทาง · ปล่อยปุ่มแล้วยังไหล (แรงหน่วง) · Space = ยิง (ดีเลย์) · ลูกโป้งหมด = ตกรอบ'); + } else if (isGauntletCrownHeistMapPlay()) { + hintEl.textContent = 'Space / W / ↑ jump · Start 100 pts · Hit -10 · Fall off left edge = out · Rank bonus at end'; + } else { + hintEl.textContent = 'Space / W / ↑ jump · Lanes + lasers · Clear = right + score'; + } } } if (previewEl) { @@ -13652,19 +13738,13 @@ const row = rows[r]; const li = document.createElement('li'); li.className = 'play-cyber-score-row' + (row.isMe ? ' is-me' : '') + (row.eliminated ? ' is-out' : '') - + (quizMissionHud ? ' play-cyber-score-row--scores-only' : ''); + + (quizMissionHud ? ' play-cyber-score-row--qm-mock' : ''); const av = document.createElement('img'); - av.className = 'play-cyber-score-av'; + av.className = 'play-cyber-score-av' + (quizMissionHud ? ' play-cyber-score-av--qm' : ''); av.alt = ''; - const cid = row.characterId ? String(row.characterId) : ''; - if (!cid) { - av.src = defaultAvatarImg.src; - } else { - const im = getCharacterImg(cid, 'down'); - if (im && im.src) av.src = im.src; - } + setCyberHudScoreAvatarImg(av, row); const sc = document.createElement('span'); - sc.className = 'play-cyber-score-val'; + sc.className = 'play-cyber-score-val' + (quizMissionHud ? ' play-cyber-qm-score' : ''); if (isGauntlet() || isSpaceShooter() || isBalloonBoss() || isQuizCarry() || jumpMissionHud || quizMissionHud || stackMissionHud) { sc.textContent = String(row.score); } else { @@ -13678,7 +13758,17 @@ crown.title = 'Leader'; sc.insertBefore(crown, sc.firstChild); } - li.appendChild(av); + const qmLeft = document.createElement('div'); + qmLeft.className = 'play-cyber-qm-left'; + const avWrap = document.createElement('span'); + avWrap.className = 'play-cyber-qm-av-wrap'; + avWrap.appendChild(av); + const qmName = document.createElement('span'); + qmName.className = 'play-cyber-qm-name'; + qmName.textContent = String(row.nickname || '').trim().slice(0, 28); + qmLeft.appendChild(avWrap); + qmLeft.appendChild(qmName); + li.appendChild(qmLeft); li.appendChild(sc); } else { const mid = document.createElement('div'); diff --git a/www/html/Game/public/js/version.js b/www/html/Game/public/js/version.js index 16ac369..ca041ac 100644 --- a/www/html/Game/public/js/version.js +++ b/www/html/Game/public/js/version.js @@ -1,6 +1,6 @@ // ทุกครั้งที่มีการเพิ่มหรือเปลี่ยน ให้เพิ่ม v +0.0001 // หลังแก้ค่าแล้วต้อง copy ไป path ที่ Nginx ชี้ (หรือรัน copy-frogger-files-only.sh) ถึงจะเห็นบนเว็บ -window.APP_VERSION = '0.0203'; +window.APP_VERSION = '0.0216'; document.addEventListener('DOMContentLoaded', function () { var t = document.querySelector('.version-tag'); if (t) t.textContent = 'v ' + window.APP_VERSION; diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index 1cc7134..5b89fab 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -763,11 +763,13 @@ .qc-mission-rank-avatar { position: absolute; left: 50%; - top: 50%; - transform: translate(-50%, -50%); - width: 72%; - height: 72%; - object-fit: contain; + top: 40%; + transform: translate(-50%, -50%) scale(1.28); + transform-origin: 50% 30%; + width: 88%; + height: 88%; + object-fit: cover; + object-position: center 18%; image-rendering: pixelated; display: block; pointer-events: none; @@ -1245,7 +1247,10 @@ .gcm-frame img.gcm-av { width: 100%; height: 100%; - object-fit: contain; + object-fit: cover; + object-position: center 22%; + transform: scale(1.32); + transform-origin: 50% 26%; image-rendering: pixelated; } .gcm-frame img.gcm-stamp { @@ -1416,41 +1421,142 @@ font-family: 'Share Tech Mono', ui-monospace, monospace; } .play-cyber-hud.is-hidden { display: none !important; } - /* mng8a80o ช่วงเล่น — แผง SCORE / TIME ใช้รูปจาก /Game/img/QUESTION (อัปโหลด score-bar.png · time.png) */ + /* mng8a80o — แผง SCORE: มุมคม, หัว SCORE ใหญ่, แถวแนวนอน = [อวาตาร์เล็ก + ชื่อไทย] ซ้าย | คะแนนใหญ่ขวา */ #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-scoreboard { - width: min(118px, 35vw); - background: url(/Game/img/QUESTION/score-bar.png) left center / auto min(96%, 360px) no-repeat; - border: none; - box-shadow: none; - padding: clamp(1.85rem, 6.5vmin, 3.05rem) clamp(6px, 1.5vw, 11px) clamp(8px, 1.6vw, 12px) clamp(4px, 1vw, 8px); - min-height: min(46vh, 320px); + width: min(252px, 64vw); + max-width: min(252px, 64vw); + box-sizing: border-box; + padding: 0.48rem 0.62rem 0.52rem; + background: linear-gradient( + 165deg, + rgba(10, 26, 48, 0.92) 0%, + rgba(5, 14, 32, 0.94) 42%, + rgba(8, 20, 40, 0.9) 100% + ); + border: 1px solid rgba(0, 255, 240, 0.38); + border-radius: 2px; + box-shadow: + 0 0 0 1px rgba(0, 0, 0, 0.45), + 0 0 24px rgba(0, 200, 255, 0.16), + inset 0 1px 0 rgba(255, 255, 255, 0.08); + overflow: visible; + min-height: unset; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-list { + box-sizing: border-box; + width: 100%; + max-width: 100%; + max-height: 48vh; } #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-panel-title { - border-bottom: none; - margin-bottom: 0.15rem; - padding-bottom: 0; - color: #b8f6ff; - text-shadow: 0 0 10px rgba(0, 0, 0, 0.95), 0 0 18px rgba(0, 200, 255, 0.35); - display: none; + display: block; + font-family: 'Orbitron', sans-serif; + font-weight: 800; + font-size: clamp(0.82rem, 2.4vmin, 0.95rem); + letter-spacing: 0.22em; + text-transform: uppercase; + color: #8afeff; + text-shadow: + 0 0 16px rgba(0, 240, 255, 0.62), + 0 0 32px rgba(0, 160, 255, 0.32); + margin: 0 0 0.34rem; + padding: 0 0 0.38rem; + border-bottom: 1px solid rgba(0, 255, 240, 0.48); + text-align: left; + line-height: 1.15; } #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row { - border-bottom-color: rgba(0, 255, 240, 0.1); + border-bottom: none; } - /* คะแนนชิดรูป — ห้ามใช้ 1fr + justify-end (ดันตัวเลขไปขวาสุดของแผง) */ - #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--scores-only { + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--qm-mock { display: flex; flex-direction: row; align-items: center; - justify-content: flex-start; - gap: 0.32rem; - width: auto; - max-width: 100%; + justify-content: space-between; + gap: 0.42rem; + width: 100%; + min-width: 0; + box-sizing: border-box; + padding: 0.3rem 0; + border-bottom: 1px solid rgba(0, 255, 240, 0.32); + grid-template-columns: unset; + grid-template: none; } - #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--scores-only .play-cyber-score-val { - justify-self: unset; - text-align: left; - min-width: unset; + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--qm-mock:last-child { + border-bottom: none; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-qm-left { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + justify-content: flex-start; + gap: 0.4rem; + flex: 1 1 auto; + min-width: 0; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-qm-name { + font-family: 'Share Tech Mono', ui-monospace, monospace; + font-size: 0.58rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: none; + color: rgba(248, 252, 255, 0.95); + text-shadow: 0 1px 5px rgba(0, 0, 0, 0.92); + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--qm-mock.is-me .play-cyber-qm-name { + color: #e8fcff; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-qm-score { flex: 0 0 auto; + align-self: center; + font-family: 'Orbitron', sans-serif; + font-size: clamp(1.02rem, 3.5vmin, 1.38rem); + font-weight: 800; + color: #7af8ff; + text-align: right; + line-height: 1; + text-shadow: + 0 0 14px rgba(0, 255, 240, 0.48), + 0 0 26px rgba(0, 160, 255, 0.22); + min-width: 2.1rem; + justify-self: unset; + white-space: nowrap; + } + /* อวาตาร์แถบ SCORE: คอขึ้นไป (crop) — wrap ตัดขอบหลัง scale */ + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-qm-av-wrap { + display: block; + width: 34px; + height: 34px; + flex-shrink: 0; + overflow: hidden; + border-radius: 2px; + border: 1px solid rgba(0, 255, 240, 0.4); + background: rgba(0, 16, 28, 0.95); + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-score-row--qm-mock .play-cyber-score-av--qm { + display: block; + width: 34px; + height: 34px; + border: none; + object-fit: cover; + object-position: center 4%; + transform: scale(1.38); + transform-origin: center 8%; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-self-frame { + overflow: hidden; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-self-frame img { + object-fit: cover; + object-position: center 6%; + transform: scale(1.36); + transform-origin: center 10%; } #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-sub { margin-top: 0.32rem; @@ -1458,6 +1564,10 @@ font-size: 0.52rem; max-width: min(88vw, 420px); } + /* โหมดคำถาม: ไม่แสดงกล่องคำแนะ (ให้พื้นที่ซ้ายกับแถบ SCORE) */ + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-hint { + display: none !important; + } #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-head { display: flex; flex-direction: row; @@ -1467,6 +1577,25 @@ column-gap: 0.08rem; row-gap: 0.12rem; } + /* time.png = กราฟิกคำว่า TIME : ด้านซ้ายของตัวเลข */ + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-head--qm-plaque .play-cyber-time-plaque-img { + display: block; + height: clamp(1rem, 3.4vmin, 1.55rem); + width: auto; + max-width: min(48vw, 200px); + object-fit: contain; + object-position: left center; + flex-shrink: 0; + margin-right: 0.12rem; + align-self: center; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-head--qm-plaque { + align-items: center; + } + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-head--qm-plaque .play-cyber-time-label, + #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-head--qm-plaque .play-cyber-time-colon { + display: none !important; + } #play-cyber-hud.play-cyber-hud--question-mission .play-cyber-time-colon { display: inline; font-family: 'Orbitron', sans-serif; @@ -1630,6 +1759,9 @@ flex-direction: column; align-items: center; } + .play-cyber-time-plaque-img { + display: none; + } .play-cyber-time-colon { display: none; line-height: 1; @@ -1990,6 +2122,7 @@
+
TIME
0
@@ -2119,8 +2252,8 @@
- - + +
v —