From c73b27e89f577372a68fdcedfaed6ecc02d8f0d7 Mon Sep 17 00:00:00 2001 From: giteaadmin Date: Mon, 3 Aug 2026 03:25:36 +0000 Subject: [PATCH] update mg quest and mobile some path --- www/html/Game/public/css/room-lobby.css | 4091 ++++++++++++----------- www/html/Game/public/css/style.css | 3987 +++++++++++----------- www/html/Game/public/js/play.js | 374 ++- www/html/Game/public/js/room-lobby.js | 207 +- www/html/Game/public/play.html | 188 +- www/html/Game/public/room-lobby.html | 3485 +++++++++---------- www/html/Game/server.js | 136 +- 7 files changed, 6681 insertions(+), 5787 deletions(-) diff --git a/www/html/Game/public/css/room-lobby.css b/www/html/Game/public/css/room-lobby.css index f4a12b8..568ce02 100644 --- a/www/html/Game/public/css/room-lobby.css +++ b/www/html/Game/public/css/room-lobby.css @@ -1,2042 +1,2049 @@ -* { box-sizing: border-box; } -@font-face { - font-family: 'NotoSansThai'; - src: - url('/Create%20Room/FONTS/NotoSansThai-Medium.ttf') format('truetype'); - font-weight: 500; - font-style: normal; - font-display: swap; -} -body { font-family: sans-serif; margin: 0; background: #1a1b26; color: #c0caf5; } -body.room-lobby-page, -body.room-lobby-page * { - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; -} -.container { max-width: 720px; margin: 1rem auto; padding: 1rem; } - -/* โครง Editor — แยกแถบเครื่องมือ / พื้นที่วาด */ -.editor-page { - display: block; -} - -/* Editor ฝังใน Admin (?embed=1) — เต็มความสูง iframe, พื้นที่แคนวาสใหญ่ + เลื่อนแยก */ -html.editor-embed-admin { - height: 100%; -} -html.editor-embed-admin body { - height: 100%; - margin: 0; - overflow: hidden; -} -body.editor-embed-admin .version-tag { - display: none !important; -} -body.editor-embed-admin .container.editor-page { - max-width: none !important; - width: 100%; - height: 100%; - margin: 0 !important; - padding: 0.35rem 0.5rem 0.45rem; - display: flex; - flex-direction: column; - min-height: 0; - box-sizing: border-box; -} -body.editor-embed-admin .container.editor-page > h1 { - display: none; -} -body.editor-embed-admin .editor-toolbar-wrap { - flex: 0 1 auto; - max-height: min(36vh, 360px); - overflow-x: hidden; - overflow-y: auto; - padding: 0.15rem 0.25rem 0.45rem 0; - margin: 0 0 0.3rem; - border-bottom: 1px solid rgba(65, 72, 104, 0.9); - scrollbar-width: thin; -} -body.editor-embed-admin .editor-workspace { - flex: 1 1 auto; - min-height: 0; - display: flex; - flex-direction: column; - overflow: hidden; -} -body.editor-embed-admin .canvas-wrap { - flex: 1 1 auto; - min-height: 140px; - overflow: auto; - margin: 0 !important; - border-radius: 10px; - border: 1px solid #414868; - background: #0f1018; - -webkit-overflow-scrolling: touch; -} -body.editor-embed-admin #editor-status { - flex: 0 0 auto; - margin: 0.3rem 0 0; - font-size: 0.8rem; - line-height: 1.35; -} -body.editor-embed-admin .editor-legend-short { - margin: 0.25rem 0 0; - font-size: 0.76rem; - line-height: 1.4; - color: #a8b0d0; -} -body.editor-embed-admin .editor-toolbar { - margin-top: 0.25rem; - margin-bottom: 0.35rem; -} -body.editor-embed-admin .frogger-lanes { - margin: 0.35rem 0; -} -body.editor-embed-admin .editor-bg-section { - margin: 0.35rem 0 0.15rem; -} -h1 { color: #7aa2f7; } -a { color: #9ece6a; } -label { display: inline-block; margin: 0.25rem 0.5rem 0.25rem 0; } -input, button { padding: 0.4rem 0.6rem; margin: 0 0.25rem 0 0; border-radius: 6px; border: 1px solid #414868; } -input { background: #24283b; color: #c0caf5; } -button { background: #7aa2f7; color: #1a1b26; cursor: pointer; border: none; } -.legend { font-size: 0.9rem; color: #a9b1d6; margin: 0.5rem 0; } -.frogger-lanes { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; position: relative; z-index: 2; min-height: 80px; } -.frogger-lanes h3 { margin: 0 0 0.5rem 0; color: #7aa2f7; font-size: 1rem; } -.frogger-lanes table { width: 100%; border-collapse: collapse; font-size: 0.85rem; } -.frogger-lanes th, .frogger-lanes td { padding: 0.25rem 0.5rem; text-align: left; border: 1px solid #414868; } -.frogger-lanes select, .frogger-lanes input[type="number"] { padding: 0.35rem 0.5rem; min-width: 4rem; background: #1a1b26; color: #c0caf5; border: 1px solid #414868; border-radius: 4px; cursor: pointer; font-size: 0.9rem; } -.frogger-lanes select { min-width: 6rem; } -.frogger-lanes .lane-speed { width: 4rem; } -.frogger-lanes .lane-spacing { width: 4rem; } -.frogger-lanes td { vertical-align: middle; } -.frogger-lanes select:disabled, .frogger-lanes input:disabled { opacity: 0.6; cursor: not-allowed; } -.game-type-hint { font-size: 0.85rem; color: #a9b1d6; margin-left: 0.5rem; } -.editor-toolbar { margin: 1rem 0; flex-wrap: wrap; display: flex; align-items: center; gap: 0.5rem 1rem; } -.editor-toolbar label, .editor-toolbar .game-type-hint { margin: 0; } -.editor-bg-section { margin: 0.75rem 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; } -.editor-bg-section label { margin: 0; } -.canvas-wrap { margin: 1rem 0; } -.container { padding-left: 1rem; padding-right: 1rem; } -#editor-canvas { background: #1a1b26; display: block; } -.game-wrap { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 0; } -.game-header { flex-shrink: 0; background: #24283b; padding: 0.5rem 1rem; display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; } -.game-header span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.game-header button { flex-shrink: 0; } -#game-canvas { - flex: 1 1 auto; - display: block; - width: 100%; - min-height: 0; - min-width: 0; - touch-action: none; -} -.game-wrap .chat-panel { flex-shrink: 0; } -.chat-panel { height: 160px; border-top: 1px solid #414868; display: flex; flex-direction: column; } -#chat-messages { flex: 1; overflow-y: auto; padding: 0.5rem; font-size: 0.9rem; } -#chat-form { display: flex; padding: 0.5rem; gap: 0.5rem; } -#chat-input { flex: 1; } - -.lobby-section { margin: 1.25rem 0; padding: 1rem; background: #24283b; border-radius: 8px; } -.lobby-section h2 { margin: 0 0 0.75rem 0; font-size: 1rem; color: #7aa2f7; } -#room-list { list-style: none; margin: 0; padding: 0; } -#room-list .room-item { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid #414868; } -#room-list .room-item:last-child { border-bottom: none; } -#room-list .room-name { font-weight: 600; color: #c0caf5; min-width: 0; } -#room-list .room-meta { font-size: 0.85rem; color: #a9b1d6; } -#room-list .room-meta-inline { font-size: 0.8rem; color: #565f89; font-weight: normal; } -#room-list-status { margin: 0; color: #a9b1d6; font-size: 0.9rem; } - -.room-lobby-peers { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; } -.room-lobby-peer { padding: 0.35rem 0; color: #c0caf5; } -.room-lobby-peer:not(:last-child) { border-bottom: 1px solid #414868; } -#lobby-map-wrap { position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; min-width: 100vw; min-height: 100vh; z-index: 0; } -body.room-lobby-page { - background: - radial-gradient(120% 120% at 50% -12%, rgba(86, 122, 255, 0.26) 0%, rgba(30, 37, 83, 0.16) 40%, rgba(7, 10, 25, 0) 75%), - linear-gradient(180deg, #1a1d46 0%, #111530 42%, #090d22 100%); - color: #ebf6ff; -} -#lobby-map-wrap::before { - content: ''; - position: absolute; - inset: 0; - z-index: 1; - pointer-events: none; - background: - radial-gradient(80% 65% at 50% 18%, rgba(106, 194, 255, 0.2), rgba(106, 194, 255, 0) 72%), - linear-gradient(180deg, rgba(10, 16, 46, 0.25) 0%, rgba(6, 12, 31, 0.05) 30%, rgba(5, 9, 24, 0.5) 100%); -} -#lobby-map-wrap::after { - content: ''; - position: absolute; - inset: 0; - z-index: 2; - pointer-events: none; - box-shadow: inset 0 0 160px rgba(8, 12, 30, 0.85); -} -#lobby-map-canvas { - display: block; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - width: 100%; - height: 100%; - min-width: 100%; - min-height: 100%; - margin: 0; - padding: 0; - background: - radial-gradient(circle at 50% 20%, rgba(124, 197, 255, 0.25) 0%, rgba(124, 197, 255, 0) 45%), - linear-gradient(180deg, #252c66 0%, #1a2150 45%, #121a3b 100%); - box-sizing: border-box; -} -#lobby-map-canvas:focus { - outline: none; -} -#lobby-map-canvas:focus-visible { - outline: 2px solid rgba(122, 162, 247, 0.45); - outline-offset: -2px; -} -/* LobbyB (mn8nx46h) — ไม่แสดงปุ่มพร้อม */ -body.room-lobby--lobby-b .room-lobby-ready-fixed { - display: none !important; -} -.lobby-interact-hint { - position: absolute; - bottom: max(10px, env(safe-area-inset-bottom)); - left: 50%; - transform: translateX(-50%); - z-index: 2; - margin: 0; - padding: 0.2rem 0.55rem; - font-size: clamp(0.72rem, 1.8vw, 0.85rem); - color: rgba(203, 213, 245, 0.9); - text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55); - pointer-events: none; - font-family: system-ui, 'Kanit', sans-serif; - white-space: nowrap; -} -.lobby-interact-hint kbd { - display: inline-block; - padding: 0.06em 0.32em; - border-radius: 4px; - background: rgba(26, 27, 38, 0.88); - border: 1px solid rgba(122, 162, 247, 0.45); - font-size: 0.88em; - font-family: inherit; -} -.lobby-zoom-pct { - position: absolute; - top: 12px; - left: 50%; - transform: translateX(-50%); - z-index: 2; - padding: 6px 12px; - border-radius: 8px; - background: rgba(26, 27, 38, 0.85); - color: #c0caf5; - font-size: 1rem; - font-weight: 600; - pointer-events: none; - opacity: 0; - transition: opacity 0.2s ease; -} -.lobby-zoom-pct.lobby-zoom-pct-visible { opacity: 1; } -/* ซ่อนแผง overlay รายชื่อ / host / แชท — โถงโฟกัสแผนที่ + ปุ่ม READY/ไมค์ ด้านนอก */ -.room-lobby-overlay { display: none !important; } -.room-lobby-top-left-cluster { - position: fixed; - top: max(12px, env(safe-area-inset-top)); - left: max(0px, env(safe-area-inset-left)); - z-index: 55; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.4rem; - pointer-events: none; -} -.room-lobby-top-left-cluster .room-lobby-exit-fixed { - pointer-events: auto; -} -.room-lobby-room-id-pill { - pointer-events: auto; - display: inline-flex; - align-items: center; - gap: 0.4rem; - min-height: 44px; - padding: 0.5rem 0.9rem; - border-radius: 12px; - border: 1px solid rgba(106, 232, 255, 0.58); - background: linear-gradient(180deg, rgba(43, 67, 128, 0.86), rgba(22, 34, 74, 0.9)); - box-shadow: - inset 0 0 0 1px rgba(188, 247, 255, 0.2), - 0 0 18px rgba(80, 213, 255, 0.32); - color: #dff6ff; - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif; - letter-spacing: 0.03em; -} -.room-lobby-room-id-label { - font-weight: 600; - font-size: clamp(0.78rem, 1.7vw, 0.9rem); - opacity: 0.92; -} -#room-id-value { - font-weight: 800; - font-size: clamp(0.85rem, 1.9vw, 1rem); - color: #f4fdff; -} -.room-lobby-room-id-lock { - font-size: 0.85rem; - filter: drop-shadow(0 0 6px rgba(105, 227, 255, 0.6)); -} - -/* มุมขวาบน — โปรไฟล์ตัวละคร */ -.room-lobby-top-right-cluster { - position: fixed; - top: max(12px, env(safe-area-inset-top)); - right: max(12px, env(safe-area-inset-right)); - z-index: 56; - display: flex; - flex-direction: row; - align-items: flex-start; - gap: 0.4rem; - pointer-events: none; -} -.room-lobby-top-right-cluster > * { - pointer-events: auto; -} -.room-lobby-top-right-actions { - display: none !important; -} -.room-lobby-top-right-action-btn { - position: relative; - flex: 0 0 auto; - width: clamp(100px, 11vw, 161px); - height: auto; - min-width: 0; - min-height: 0; - max-width: 161px; - aspect-ratio: 161 / 176; - padding: 0; - margin: 0; - border: none; - border-radius: 0; - background: transparent; - box-shadow: none; - cursor: pointer; - overflow: visible; - isolation: isolate; -} -.room-lobby-top-right-action-btn img { - width: 100%; - height: auto; - max-width: 161px; - aspect-ratio: 161 / 176; - object-fit: contain; - display: block; - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} -.room-lobby-profile-wrap { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.2rem; -} -.room-lobby-profile-frame { - position: relative; - width: 159px; - height: 157px; - min-width: 159px; - min-height: 157px; - max-width: 159px; - max-height: 157px; - aspect-ratio: 159 / 157; - border-radius: 0; - border: none; - overflow: hidden; - background: url(../img/btn-profile-bg.png) center/100% 100% no-repeat; - box-shadow: none; -} -.room-lobby-profile-avatar-viewport { - position: absolute; - left: 12px; - top: 10px; - width: 124px; - height: 118px; - overflow: hidden; - border-radius: 12px; -} -.room-lobby-profile-frame #room-lobby-profile-avatar { - position: absolute; - left: 50%; - top: 5px; - display: block; - width: 120%; - height: auto; - max-width: none; - object-fit: contain; - object-position: center top; - transform: translateX(-50%); - transform-origin: center center; - image-rendering: pixelated; - image-rendering: crisp-edges; -} -.room-lobby-profile-set-btn { - position: absolute; - right: 0; - bottom: 0; - width: 71px; - height: 71px; - min-width: 71px; - min-height: 71px; - max-width: 71px; - max-height: 71px; - aspect-ratio: 71 / 71; - padding: 0; - margin: 0; - border: none; - border-radius: 0; - background: transparent; - cursor: pointer; - z-index: 2; -} -.room-lobby-profile-set-btn img { - display: block; - width: 71px; - height: 71px; - min-width: 71px; - min-height: 71px; - max-width: 71px; - max-height: 71px; - aspect-ratio: 71 / 71; - object-fit: contain; -} - -/* Profile overlay — see profile-popup.css (linked from room-lobby.html) */ - - -/* Host Console popup */ -.room-lobby-host-console-overlay { - position: fixed; - inset: 0; - z-index: 10070; - display: flex; - align-items: center; - justify-content: center; - padding: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left)); -} -.room-lobby-host-console-overlay.is-hidden { - display: none !important; -} -.room-lobby-host-console-backdrop { - position: absolute; - inset: 0; - background: rgba(0, 0, 0, 0.8); -} -.room-lobby-host-console-dialog { - position: relative; - z-index: 1; - width: min(990px, calc(100vw - 24px), calc((100dvh - 24px) * (990 / 881))); - aspect-ratio: 990 / 881; - max-height: calc(100dvh - 24px); - --hc-scale: 1; - --hc-close-hit-size: calc(82px * var(--hc-scale)); - --hc-close-hit-top: 9%; - --hc-close-hit-right: 6.5%; - background: url(../img/03-4-Host-Console/host-console-bg.png) center/100% 100% no-repeat; - box-sizing: border-box; -} -.room-lobby-host-console-body { - position: absolute; - top: 13.6%; - right: 7.9%; - bottom: 6%; - left: 8.2%; - display: flex; - flex-direction: column; - align-items: center; - min-height: 0; - padding-top: calc(50px * var(--hc-scale)); - padding-bottom: calc(62px * var(--hc-scale)); - box-sizing: border-box; -} -.room-lobby-host-console-close { - position: absolute; - top: var(--hc-close-hit-top); - right: var(--hc-close-hit-right); - width: var(--hc-close-hit-size); - height: var(--hc-close-hit-size); - border: none; - border-radius: 0; - background: transparent; - color: transparent; - font-size: 0; - line-height: 1; - cursor: pointer; - text-shadow: none; - z-index: 3; - -webkit-tap-highlight-color: transparent; -} -.room-lobby-host-console-txt-img { - width: auto; - object-fit: contain; - display: block; -} -.room-lobby-host-console-txt-max { - height: calc(66px * var(--hc-scale)); - margin-bottom: calc(10px * var(--hc-scale)); -} -.room-lobby-host-console-max-wrap { - position: relative; - width: min(82%, calc(657px * var(--hc-scale))); - aspect-ratio: 657 / 141; - margin-bottom: calc(-10px * var(--hc-scale)); - margin-top: calc(-30px * var(--hc-scale)); -} -.room-lobby-host-console-textfield-bg { - width: 100%; - height: 100%; - object-fit: contain; - display: block; -} -.room-lobby-host-console-arrow-btn { - position: absolute; - top: 50%; - width: calc(51px * var(--hc-scale)); - height: calc(54px * var(--hc-scale)); - padding: 0; - margin: 0; - border: none; - border-radius: 0; - background: transparent; - cursor: pointer; - transform: translateY(-50%); -} -.room-lobby-host-console-arrow-left { left: 4.9%; } -.room-lobby-host-console-arrow-right { right: 4.9%; } -.room-lobby-host-console-arrow-btn img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; -} -.room-lobby-host-console-max-value { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - min-width: 2ch; - text-align: center; - font-size: calc(40px * var(--hc-scale)); - font-weight: 700; - color: #eaf9ff; - text-shadow: 0 0 10px rgba(0, 255, 255, 0.35); -} -.room-lobby-host-console-summary { - margin: 0 0 calc(12px * var(--hc-scale)); - font-size: calc(24px * var(--hc-scale)); - color: #d9f3ff; - margin-bottom: 4%; -} -.room-lobby-host-console-line { - width: min(94%, calc(744px * var(--hc-scale))); - height: auto; - margin-bottom: calc(10px * var(--hc-scale)); - object-fit: contain; -} -.room-lobby-host-console-txt-members { - height: calc(61px * var(--hc-scale)); - margin-bottom: calc(8px * var(--hc-scale)); -} -.room-lobby-host-console-members { - width: min(84%, calc(694px * var(--hc-scale))); - flex: 1 1 auto; - min-height: 0; - overflow-x: hidden; - overflow-y: scroll; - padding-right: calc(40px * var(--hc-scale)); - padding-left: calc(35px * var(--hc-scale)); - scrollbar-width: auto; - scrollbar-color: rgba(255, 104, 228, 0.98) rgba(20, 40, 70, 0.55); - scrollbar-gutter: stable both-edges; -} -.room-lobby-host-console-members::-webkit-scrollbar { - width: clamp(24px, calc(36px * var(--hc-scale)), 42px); -} -.room-lobby-host-console-members::-webkit-scrollbar-track { - background: rgba(20, 40, 70, 0.55); - border-radius: 999px; - border: 1px solid rgba(90, 220, 255, 0.35); -} -.room-lobby-host-console-members::-webkit-scrollbar-thumb { - background: linear-gradient(180deg, rgba(255, 125, 236, 1) 0%, rgba(241, 74, 215, 1) 100%); - border-radius: 999px; - border: 3px solid rgba(16, 32, 56, 0.65); - background-clip: padding-box; - box-shadow: 0 0 10px rgba(255, 84, 226, 0.45); -} -.room-lobby-host-console-members-list { - list-style: none; - margin: 0; - padding: 0; - display: flex; - flex-direction: column; - gap: calc(18px * var(--hc-scale)); -} -.room-lobby-host-console-member-item { - position: relative; - min-height: calc(44px * var(--hc-scale)); - padding: calc(2px * var(--hc-scale)) calc(104px * var(--hc-scale)) calc(2px * var(--hc-scale)) calc(12px * var(--hc-scale)); - display: flex; - align-items: center; - justify-content: flex-start; - gap: 0.6rem; - color: #e9f8ff; - font-size: calc(28px * var(--hc-scale)); - background: url(../img/03-4-Host-Console/host-console-line-2.png) left bottom/100% 3px no-repeat; -} -.room-lobby-host-console-member-item.is-host { - min-height: calc(80px * var(--hc-scale)); - padding-right: calc(12px * var(--hc-scale)); - background: url(../img/03-4-Host-Console/host-console-hostname.png) center/100% 100% no-repeat; - font-weight: 700; -} -.room-lobby-host-console-member-name { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - color: inherit; - padding-left: 4%; - margin-top: -4%; -} -.room-lobby-host-console-member-item.is-host .room-lobby-host-console-member-name { - margin-top: 0%; /* เพิ่มค่านี้ = ขยับลง */ -} -.room-lobby-host-console-delete-btn { - position: absolute; - right: calc(10px * var(--hc-scale)); - top: 50%; - transform: translateY(-50%); - width: calc(84px * var(--hc-scale)); - height: calc(84px * var(--hc-scale)); - min-width: calc(84px * var(--hc-scale)); - padding: 0; - border: none; - border-radius: 0; - background: transparent; - cursor: pointer; - margin-top: -2%; - margin-right: -1%; -} -.room-lobby-host-console-delete-btn img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; -} -.room-lobby-host-console-delete-btn:disabled { - opacity: 0.35; - cursor: default; -} -.room-lobby-host-console-confirm { - position: absolute; - left: 50%; - bottom: calc(-60px * var(--hc-scale)); - transform: translateX(-50%); - width: min(43%, calc(350px * var(--hc-scale))); - aspect-ratio: 350 / 129; - border: none; - border-radius: 0; - padding: 0; - background: transparent; - cursor: pointer; -} -.room-lobby-host-console-confirm img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; -} -/* Profile popup: tightened scaling for reduced viewports */ -@media (max-width: 1100px), (max-height: 700px) { - .room-lobby-profile-content { - top: 13%; - right: 4%; - bottom: 8%; - left: 4%; - gap: clamp(8px, 1vw, 14px); - grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.12fr); - } - .room-lobby-profile-left-pane { - grid-template-rows: minmax(0, 1fr) auto; - row-gap: clamp(3px, 0.5vw, 6px); - } - .room-lobby-profile-logout { - width: min(58%, 100%); - } - .room-lobby-profile-char-card #room-lobby-profile-overlay-avatar { - width: 74%; - max-width: 74%; - max-height: 60%; - } -} -@media (max-width: 900px), (max-height: 560px) { - .room-lobby-profile-content { - top: 11%; - right: 3%; - bottom: 7%; - left: 3%; - gap: 8px; - grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.08fr); - } - .room-lobby-profile-logout { - width: min(62%, 100%); - } - .room-lobby-profile-char-card #room-lobby-profile-overlay-avatar { - width: 64%; - max-width: 64%; - max-height: 56%; - } -} -.room-lobby-actions { margin-top: 1rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; } -.room-lobby-actions .room-lobby-btn-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; opacity: 0; pointer-events: none; } -.room-lobby-actions label { margin: 0; } -.room-lobby-actions #btn-start { background: #9ece6a; color: #1a1b26; } -#host-only { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; } -#host-only select { padding: 0.4rem 0.6rem; border-radius: 6px; border: 1px solid #414868; background: #24283b; color: #c0caf5; } -.host-start-area-hint { - flex-basis: 100%; - margin: 0; - font-size: 0.88rem; - color: #e0af68; - line-height: 1.35; - max-width: 100%; -} -#host-only #btn-start:disabled { - opacity: 0.5; - cursor: not-allowed; - filter: grayscale(0.25); -} -.room-lobby-chat { margin-top: 1rem; } -.room-lobby-chat.chat-panel { - border-radius: 12px; - overflow: hidden; - box-shadow: none; -} -.room-lobby-chat-peers.chat-panel { - position: fixed; - right: 0.25rem; - bottom: 10rem; - width: 576px; - height: 525px; - max-width: calc(100vw - 2.5rem); - z-index: 52; - margin-top: 0; - display: flex; - flex-flow: column; - padding: 2rem; - box-sizing: border-box; - border-top: 0px solid #414868; - background: url(../img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; - background-color: transparent; -} -.room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img img { width: 90px; height: 77px; } -.room-lobby-chat-peers.chat-panel .chat-close-btn { width: 48px; height: 48px; } -.room-lobby-chat-peers.chat-panel .chat-close-btn img { width: 50px; height: 50px; } -.room-lobby-chat-peers.chat-panel #chat-messages { padding: 0.75rem; font-size: 1.05rem; gap: 0.5rem; } -.room-lobby-chat-peers.chat-panel .chat-form-bar { padding: 0.6rem 0; gap: 0.5rem; } -.room-lobby-chat-peers.chat-panel #chat-input { padding: 0.6rem 0.85rem; font-size: 1.05rem; } -.room-lobby-chat-peers.chat-panel .chat-send-btn { width: 52px; height: 52px; } -.room-lobby-chat-peers.chat-panel .chat-send-btn img { width: 58px; height: 58px; } -.room-lobby-chat-peers.chat-panel .chat-msg { padding: 0.6rem 1rem; font-size: 1.05rem; } -.room-lobby-chat-peers.chat-panel .chat-header-bar { - margin: 0 -2rem 0 -2rem; - padding-left: 2rem; - padding-right: 2rem; - justify-content: space-between; - align-items: center; - min-height: 72px; - height: 72px; -} -.room-lobby-chat-peers.chat-panel #chat-messages { - flex: 1; - min-height: 0; - height: auto; -} -.room-lobby-chat .chat-header-bar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0; - min-height: 48px; - height: 48px; - background: url(../img/chat-line.png) bottom repeat-x; - background-size: 100% 4px; - background-color: transparent; -} -.room-lobby-chat-peers .chat-header-title.chat-header-title-img { - display: inline-flex; - align-items: center; - line-height: 0; -} -.room-lobby-chat-peers .chat-header-title.chat-header-title-img img { - width: 60px; - height: 51px; - object-fit: contain; - display: block; -} -.room-lobby-chat-ai .chat-header-title.chat-header-title-img { - display: flex; - align-items: flex-end; - gap: 0.5rem; - line-height: 0; - min-width: 0; - overflow: visible; -} -.room-lobby-chat-ai .chat-header-title.chat-header-title-img .ai-chat-title-label { - height: 64px; - width: auto; - max-width: none; - object-fit: contain; - display: block; - flex-shrink: 0; - margin-bottom: -2px; -} -/* รูปหัวแชท AI — ยกขึ้นเหนือเส้น */ -.room-lobby-chat-ai .chat-header-title.chat-header-title-img img { - width: 86px; - height: 92px; - object-fit: cover; - display: block; - flex-shrink: 0; - margin-top: -27px; - margin-left: -6px; - position: relative; - z-index: 1; -} -.room-lobby-chat .chat-header-title { - font-size: 1rem; - font-weight: 600; - color: #a0aec0; -} -.room-lobby-chat .chat-close-btn { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - padding: 0; - border: none; - border-radius: 8px; - background: transparent; - cursor: pointer; - margin-left: auto; -} -.room-lobby-chat-peers .chat-header-bar .chat-close-btn { margin-left: 0; } -.room-lobby-chat .chat-close-btn img { width: 34px; height: 34px; object-fit: contain; } -.room-lobby-chat .chat-close-btn:hover { opacity: 0.9; } -.room-lobby-chat.chat-panel-collapsed #chat-messages, -.room-lobby-chat.chat-panel-collapsed .chat-form-bar { display: none !important; } -.room-lobby-chat-peers.chat-panel-collapsed .chat-header-title { display: none !important; } -.room-lobby-chat-peers.chat-panel-collapsed .chat-header-bar { - justify-content: center; - padding: 0; - background: none !important; - border: none; -} -.room-lobby-chat-peers.chat-panel-collapsed.chat-panel { - width: 80px; - height: 80px; - min-height: 0; - padding: 0; - right: 1.25rem; - bottom: 6.25rem; - display: flex; - align-items: center; - justify-content: center; - background: none !important; - background-color: transparent !important; - border: none; - box-shadow: none; -} -.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn { - width: 80px; - height: 80px; - overflow: visible; -} -.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn img { - width: 100%; - height: 100%; - object-fit: contain; - object-position: center; - display: block; -} -.room-lobby-chat #chat-messages, -.room-lobby-chat #ai-chat-messages { - height: 100px; - overflow-y: auto; - padding: 0.5rem; - font-size: 0.85rem; - border: none; - margin: 0; - display: flex; - flex-direction: column; - gap: 0.35rem; - background: none; - background-color: transparent; - box-shadow: none; -} -.room-lobby-chat .chat-messages-bg { border-radius: 0; } -.room-lobby-chat #chat-form.chat-form-bar, -.room-lobby-chat #ai-chat-form.chat-form-bar { - display: flex; - gap: 0.4rem; - align-items: center; - padding: 0.4rem 0; - background: none; - background-color: transparent; - border-top: none; - flex-shrink: 0; -} -.room-lobby-chat-peers .chat-form-bar { - padding-left: 0; - padding-right: 0; -} -.room-lobby-chat #chat-input, -.room-lobby-chat #ai-chat-input { - flex: 1; - min-width: 0; - padding: 0.45rem 0.6rem; - border-radius: 10px; - border: 1px solid rgba(0, 212, 255, 0.25); - background: rgba(30, 35, 50, 0.8); - color: #c0caf5; - font-size: 0.9rem; - box-sizing: border-box; - margin-left: 9px; -} -.room-lobby-chat .chat-send-btn { - display: flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - flex-shrink: 0; - padding: 0; - border: none; - border-radius: 10px; - background: transparent; - cursor: pointer; -} -.room-lobby-chat .chat-send-btn img { width: 45px; height: 45px; object-fit: contain; } -.room-lobby-chat .chat-send-btn:hover { opacity: 0.9; } -.room-lobby-chat .chat-msg { - padding: 0.4rem 0.75rem; - border-radius: 12px; - max-width: 85%; - background-size: 100% 100%; - background-repeat: no-repeat; - background-position: center; -} -.room-lobby-chat .chat-msg-mine { - align-self: flex-end; - text-align: right; - background-image: url(../img/chat-bubble-me.png); - background-color: rgba(122, 162, 247, 0.9); - color: #1a1b26; -} -.room-lobby-chat .chat-msg-other { - align-self: flex-start; - text-align: left; - background-image: url(../img/chat-bubble-friend.png); - background-color: rgba(65, 72, 104, 0.9); - color: #c0caf5; -} -.room-lobby-chat .chat-msg-ai { - align-self: flex-start; - text-align: left; - background-image: url(../img/chat-bubble-friend.png); - background-color: rgba(158, 206, 106, 0.9); - color: #1a1b26; -} -.room-lobby-chat .chat-msg-system { - align-self: center; - text-align: center; - max-width: 95%; - background-image: none; - background-color: rgba(26, 27, 38, 0.72); - color: #9aa5ce; - font-size: 0.88rem; - font-style: italic; - padding: 0.35rem 0.6rem; -} - -/* AI chat — loading แบบ Messenger (จุดกระโดด 3 จุด), อยู่ติดข้อความล่าสุดในลิสต์ */ -.room-lobby-chat .ai-chat-typing { - display: flex; - align-items: center; - gap: 4px; - padding: 12px 14px; - min-height: 24px; - flex-shrink: 0; - background-image: url(../img/chat-bubble-friend.png); - background-color: rgba(158, 206, 106, 0.9); - background-size: 100% 100%; - background-repeat: no-repeat; - background-position: center; -} -.room-lobby-chat .ai-typing-dot { - width: 6px; - height: 6px; - border-radius: 50%; - background: #1a1b26; - animation: ai-typing-bounce 1.4s ease-in-out infinite both; -} -.room-lobby-chat .ai-typing-dot:nth-child(1) { animation-delay: 0s; } -.room-lobby-chat .ai-typing-dot:nth-child(2) { animation-delay: 0.2s; } -.room-lobby-chat .ai-typing-dot:nth-child(3) { animation-delay: 0.4s; } -@keyframes ai-typing-bounce { - 0%, 60%, 100% { transform: translateY(0); } - 30% { transform: translateY(-6px); } -} - -/* AI chat panel — match Main-Lobby lobby-ai-chat-panel */ -.room-lobby-chat-ai.chat-panel { - position: fixed; - left: 8px; - right: auto; - bottom: clamp(0.5rem, 2vw, 1rem); - width: 454px; - height: 526px; - max-width: calc(100vw - 2.5rem); - z-index: 51; - margin: 0; - display: flex; - flex-flow: column; - box-sizing: border-box; - padding: 2.6rem; - overflow: visible; - background: url(../img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; - background-color: transparent; - border: none; - box-shadow: none; - border-radius: 12px; - pointer-events: none; -} -.room-lobby-chat-ai.chat-panel .chat-header-bar, -.room-lobby-chat-ai.chat-panel #ai-chat-messages, -.room-lobby-chat-ai.chat-panel #ai-chat-form, -.room-lobby-chat-ai.chat-panel .ai-chat-admin-link { - pointer-events: auto; -} -.room-lobby-chat-ai.chat-panel .chat-header-bar { - margin: 0 -2rem 0 -2rem; - padding: 0 1rem; - justify-content: space-between; - align-items: center; - min-height: 50px; - height: 50px; - overflow: visible; - background: url(../img/AI-chat-line.png) bottom repeat-x; - background-size: 100% 3px; - background-color: transparent; -} -.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img img { - width: 100px; - height: 116px; - margin-top: -39px; - margin-left: 16px; - object-fit: cover; - position: relative; - z-index: 1; -} -.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img .ai-chat-title-label { - height: 80px; - width: auto; - max-width: none; - margin-bottom: -4px; - margin-left: -5px; - transform: translateX(-6px); -} -.room-lobby-chat-ai.chat-panel .chat-close-btn { - display: flex; - align-items: center; - justify-content: center; - width: 60px; - height: 60px; - padding: 0; - border: none; - border-radius: 8px; - background: transparent; - cursor: pointer; - margin-left: auto; -} -.room-lobby-chat-ai.chat-panel .chat-close-btn img { - width: 60px; - height: 60px; - object-fit: contain; -} -.room-lobby-chat-ai.chat-panel .chat-close-btn:hover { - opacity: 0.9; -} -.room-lobby-chat-ai.chat-panel #ai-chat-messages { - flex: 1; - min-height: 0; - height: auto; - overflow-y: auto; - padding: 0.2rem 0.35rem 0.25rem 0; - font-size: 1.05rem; - gap: 0.5rem; - background: none; - border: none; - scrollbar-width: thin; - scrollbar-color: rgba(244, 252, 255, 0.98) rgba(53, 110, 167, 0.28); -} -.room-lobby-chat-ai.chat-panel #ai-chat-messages::-webkit-scrollbar { - width: 1rem; - scrollbar-width: auto; -} -.room-lobby-chat-ai.chat-panel #ai-chat-messages::-webkit-scrollbar-track { - border-radius: 999px; - background: linear-gradient(180deg, rgba(38, 77, 125, 0.45) 0%, rgba(32, 66, 106, 0.38) 100%); - box-shadow: inset 0 0 0 1px rgba(107, 193, 255, 0.25); -} -.room-lobby-chat-ai.chat-panel #ai-chat-messages::-webkit-scrollbar-thumb { - border-radius: 999px; - background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, rgba(221, 244, 255, 0.96) 100%); - box-shadow: - 0 0 10px rgba(169, 239, 255, 0.55), - inset 0 0 0 1px rgba(180, 235, 255, 0.9); -} -.room-lobby-chat-ai.chat-panel .chat-form-bar { - display: flex; - gap: 0; - align-items: center; - padding: 0.6rem 0; - flex-shrink: 0; - background: none; - border: none; - width: calc(100% + 3rem); - margin-left: 0; - margin-right: 0; -} -.room-lobby-chat-ai.chat-panel #ai-chat-input { - flex: 0.85; - min-width: 0; - min-height: 50px; - padding: 0.6rem 0.85rem; - border-radius: 8px; - border: 1px solid rgba(0, 212, 255, 0.32); - background: rgba(30, 35, 50, 0.55); - color: #c0caf5; - font-size: 1.05rem; - margin: 0; -} -.room-lobby-chat-ai.chat-panel .chat-send-btn { - width: 73px; - height: 73px; - margin-left: 0; - margin-right: -0.7rem; -} -.room-lobby-chat-ai.chat-panel .chat-send-btn img { - width: 102px; - height: 98px; - object-fit: contain; -} -.room-lobby-chat-ai.chat-panel .chat-send-btn:focus, -.room-lobby-chat-ai.chat-panel .chat-send-btn:focus-visible { - outline: none !important; - box-shadow: none !important; - border-color: transparent !important; -} -.room-lobby-chat-ai.chat-panel .chat-msg { - padding: 0.58rem 0.92rem; - font-size: 1.05rem; - line-height: 1.33; - border: none; - box-shadow: none; -} -.room-lobby-chat-ai.chat-panel .chat-msg-mine { - background-color: rgba(122, 162, 247, 0.2); - color: #f787e4; -} -.room-lobby-chat-ai.chat-panel .chat-msg-ai { - background-color: rgba(158, 206, 106, 0.2); - color: #f2f8ff; -} -.room-lobby-chat-ai.chat-panel .ai-chat-typing { - padding: 14px 18px; - min-height: 28px; - background-color: rgba(158, 206, 106, 0.32); -} -.room-lobby-chat-ai.chat-panel .ai-typing-dot { - width: 8px; - height: 8px; - background: #f2f8ff; -} -.room-lobby-chat-ai.chat-panel .ai-chat-admin-link { - margin: 0.35rem 0 0 0; - font-size: 0.75rem; - flex-shrink: 0; -} -.room-lobby-chat-ai.chat-panel, -.room-lobby-chat-ai.chat-panel #ai-chat-messages, -.room-lobby-chat-ai.chat-panel #ai-chat-input, -.room-lobby-chat-ai.chat-panel .chat-msg, -.room-lobby-chat-ai.chat-panel .ai-chat-typing, -.room-lobby-chat-ai.chat-panel .chat-send-btn, -.room-lobby-chat-ai.chat-panel .ai-chat-admin-link, -.room-lobby-chat-ai.chat-panel .ai-chat-admin-link a { - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; -} -.room-lobby-chat-ai.chat-panel #ai-chat-messages, -.room-lobby-chat-ai.chat-panel #ai-chat-messages * { - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; -} -.room-lobby-chat-ai.chat-panel #ai-chat-input::placeholder { - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; -} - -/* Host console: force NotoSansThai for highlighted text areas */ -.room-lobby-host-console-summary, -.room-lobby-host-console-member-item, -.room-lobby-host-console-member-name, -.room-lobby-host-console-max-value { - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; -} - -/* AI chat collapsed — match Main-Lobby lobby-btn-ai-chat style */ -.room-lobby-chat-ai.chat-panel-collapsed #ai-chat-messages, -.room-lobby-chat-ai.chat-panel-collapsed .chat-form-bar, -.room-lobby-chat-ai.chat-panel-collapsed .ai-chat-admin-link { display: none !important; } -.room-lobby-chat-ai.chat-panel-collapsed .chat-header-title { display: none !important; } -.room-lobby-chat-ai.chat-panel-collapsed .chat-header-bar { - justify-content: center; - padding: 0; - background: none !important; - border: none; - min-height: 0; - height: auto; -} -.room-lobby-chat-ai.chat-panel-collapsed.chat-panel { - width: 213px; - max-width: 213px; - height: 201px; - min-height: 201px; - padding: 0; - left: max(1.25rem, env(safe-area-inset-left)); - bottom: clamp(0.5rem, 2vw, 1rem); - display: flex; - align-items: center; - justify-content: center; - background: none !important; - background-color: transparent !important; - border: none; - box-shadow: none; -} -.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn { - width: 213px; - height: 201px; - min-width: 213px; - min-height: 201px; - max-width: 213px; - max-height: 201px; - aspect-ratio: 213 / 201; - overflow: visible; - border-radius: 0; - margin-left: 0; -} -.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { - width: 213px; - height: 201px; - min-width: 213px; - min-height: 201px; - max-width: 213px; - max-height: 201px; - aspect-ratio: 213 / 201; - object-fit: contain; - object-position: center; - display: block; -} - -.room-lobby-exit-fixed { - position: static; - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-items: center; - justify-content: flex-start; - gap: 10px; - width: max-content; - max-width: calc(100vw - 24px); - box-sizing: border-box; -} -.room-lobby-exit-fixed .btn-exit-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 auto; - margin: 0; - width: clamp(58px, 9vw, 72px); - height: clamp(58px, 9vw, 72px); - min-width: clamp(58px, 9vw, 72px); - padding: 0; - border: none; - border-radius: 0; - background: transparent; - box-shadow: none; - cursor: pointer; -} -.room-lobby-exit-fixed .btn-exit-icon:hover { - transform: translateY(-1px); - filter: brightness(1.08); -} -.room-lobby-exit-fixed .btn-exit-icon img { - width: 100%; - height: auto; - object-fit: contain; - display: block; -} - -.room-lobby-ready-fixed { - position: fixed; - bottom: max(2rem, env(safe-area-inset-bottom)); - left: 50%; - transform: translateX(-50%); - z-index: 120; - pointer-events: none; -} -.room-lobby-ready-fixed .ready-label, -.room-lobby-ready-fixed .ready-check-input { - pointer-events: auto; -} -.room-lobby-ready-fixed .ready-label { - position: relative; - display: inline-block; - padding: 0; - margin: 0; - border: none; - border-radius: 0; - background: transparent; - box-shadow: none; - cursor: pointer; - transition: transform 0.15s ease, filter 0.15s ease; - line-height: 0; - filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.42)); -} -.room-lobby-ready-fixed .ready-label:hover { - transform: scale(1.04); - filter: brightness(1.08); -} -.room-lobby-ready-fixed .ready-label:active { - transform: scale(0.98); -} -.room-lobby-ready-fixed .ready-check-input { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - margin: 0; - opacity: 0; - cursor: pointer; - z-index: 2; -} -.room-lobby-ready-fixed .ready-label-img { - display: block; - height: clamp(44px, 8vh, 72px); - width: auto; - max-width: min(240px, 78vw); - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} -.room-lobby-ready-fixed .ready-label--active .ready-label-img { - filter: drop-shadow(0 0 10px rgba(158, 206, 106, 0.45)); -} -body.room-lobby-page #room-players-hud { - top: max(10px, env(safe-area-inset-top)) !important; - min-width: 0; - border-radius: 0; - border: none; - background: transparent; - box-shadow: none; - backdrop-filter: none; - color: #e3f6ff !important; - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; - text-transform: none; - letter-spacing: 0.08em; - text-shadow: - 0 2px 0 rgba(0, 0, 0, 0.8), - 0 0 12px rgba(0, 0, 0, 0.55); - text-align: center; -} - -/* มุมขวาล่าง — ไมค์ทุกห้อง + ปุ่ม LobbyB (แว่น/ถ้วย) */ -.room-lobby-br-fixed { - --lobby-br-btn: 80px; - position: fixed; - bottom: max(0.95rem, env(safe-area-inset-bottom)); - right: max(1.25rem, env(safe-area-inset-right)); - z-index: 400; - display: flex; - flex-direction: row; - align-items: flex-end; - gap: 10px; - pointer-events: none; -} -.room-lobby-br-fixed .lobby-b-extra-row, -.room-lobby-br-fixed .btn-voice-icon { - pointer-events: auto; -} -.lobby-b-extra-row { - display: flex; - flex-direction: row; - align-items: flex-end; - gap: 10px; -} -.lobby-b-extra-row.is-hidden { - display: none !important; -} -/* โหมดเกม (ควิซ) ใน room-lobby — ไม่โชว์แว่น/ถ้วย LobbyB */ -body.room-lobby--quiz-active .lobby-b-extra-row { - display: none !important; - visibility: hidden !important; - pointer-events: none !important; -} -/* ปุ่มมุมขวาล่าง — ขนาดเดียวกัน (กัน UA border / box model ต่างกัน) */ -.room-lobby-br-fixed .lobby-b-sq-btn, -.room-lobby-br-fixed .btn-voice-icon { - box-sizing: border-box; - width: var(--lobby-br-btn); - height: var(--lobby-br-btn); - min-width: var(--lobby-br-btn); - min-height: var(--lobby-br-btn); - max-width: var(--lobby-br-btn); - max-height: var(--lobby-br-btn); - margin: 0; - padding: 0; - border: none; - border-radius: 0; - appearance: none; - -webkit-appearance: none; - flex-shrink: 0; - cursor: pointer; - background: transparent; - box-shadow: none; -} -/* สไตล์เดียวกับปุ่มไมค์ — ไม่มีกรอบ cyan / bg-item */ -.lobby-b-sq-btn { - display: flex; - align-items: center; - justify-content: center; - transition: transform 0.15s ease, filter 0.15s ease; -} -.lobby-b-sq-btn:hover { - transform: scale(1.04); - filter: brightness(1.08); -} -.lobby-b-sq-btn:active { transform: scale(0.98); } -.room-lobby-br-fixed .lobby-b-sq-btn img, -.room-lobby-br-fixed .btn-voice-icon img { - width: 100%; - height: 100%; - max-width: 100%; - max-height: 100%; - object-fit: contain; - object-position: center; - display: block; - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} -.room-lobby-br-fixed .btn-voice-icon { - display: flex; - align-items: center; - justify-content: center; - background: transparent; -} - -/* Desktop tuning: keep controls visibly large and readable */ -@media (min-width: 1024px) { - .room-lobby-chat-peers.chat-panel { - right: 0.9rem; - bottom: 11rem; - width: 454px; - height: 414px; - padding: 1.7rem 1.45rem 1.15rem; - border-radius: 0; - background: url(../img/chat-bg.png) center/100% 100% no-repeat; - border: none; - box-shadow: none; - backdrop-filter: none; - } - .room-lobby-chat-peers.chat-panel .chat-header-bar { - margin: 0; - padding: 0 0.15rem; - min-height: 58px; - height: 58px; - background: url(../img/chat-line.png) left bottom / 375px 4px no-repeat; - box-shadow: none; - } - .room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img img { - display: block; - width: 90px; - height: 77px; - object-fit: contain; - } - .room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img::before { - content: none; - display: none; - } - .room-lobby-chat-peers.chat-panel .chat-close-btn { - width: 58px; - height: 58px; - min-width: 58px; - min-height: 58px; - max-width: 58px; - max-height: 58px; - margin-left: auto; - } - .room-lobby-chat-peers.chat-panel .chat-close-btn img { - width: 58px; - height: 58px; - object-fit: contain; - } - .room-lobby-chat-peers.chat-panel #chat-messages { - width: calc(100% - 16px); - margin-right: 16px; - padding: 0.35rem 0.7rem 0.25rem 0.15rem; - font-size: 1rem; - line-height: 1.42; - gap: 0.42rem; - margin-top: 0.15rem; - margin-bottom: 0.2rem; - scrollbar-width: auto; - scrollbar-color: rgba(250, 253, 255, 0.98) rgba(12, 26, 47, 0.45); - box-sizing: border-box; - } - .room-lobby-chat-peers.chat-panel #chat-messages::-webkit-scrollbar { - width: 15px; - } - .room-lobby-chat-peers.chat-panel #chat-messages::-webkit-scrollbar-track { - border-radius: 999px; - background: rgba(20, 44, 72, 0.45); - border: 1px solid rgba(124, 221, 255, 0.3); - } - .room-lobby-chat-peers.chat-panel #chat-messages::-webkit-scrollbar-thumb { - border-radius: 999px; - background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(241, 249, 255, 0.98) 100%); - box-shadow: 0 0 8px rgba(182, 239, 255, 0.45); - } - .room-lobby-chat-peers.chat-panel .chat-msg { - max-width: 93%; - padding: 0.22rem 0.35rem; - font-size: 0.98rem; - border-radius: 10px; - background-image: none; - background-color: transparent; - box-shadow: none; - } - .room-lobby-chat-peers.chat-panel .chat-msg-other { - color: #d5bb63; - font-weight: 500; - } - .room-lobby-chat-peers.chat-panel .chat-msg-mine { - color: #cf74d1; - background-color: rgba(39, 67, 112, 0.82); - border: 1px solid rgba(116, 206, 255, 0.2); - align-self: flex-end; - text-align: left; - padding: 0.32rem 0.62rem; - } - .room-lobby-chat-peers.chat-panel .chat-form-bar { - padding: 0.24rem 0 0; - gap: 0; - align-items: center; - justify-content: space-between; - } - .room-lobby-chat-peers.chat-panel #chat-input { - margin-left: 17px; - width: 308px; - min-width: 308px; - max-width: 308px; - height: 61px; - min-height: 61px; - max-height: 61px; - padding: 0 0.95rem; - font-size: 0.95rem; - border-radius: 0; - border: none; - background: url(../img/chatbox.png) center/100% 100% no-repeat; - color: #e8f7ff; - } - .room-lobby-chat-peers.chat-panel #chat-input::placeholder { - color: rgba(195, 211, 236, 0.66); - } - .room-lobby-chat-peers.chat-panel .chat-send-btn { - width: 102px; - height: 98px; - min-width: 102px; - min-height: 98px; - max-width: 102px; - max-height: 98px; - margin-left: -26px; - margin-right: 2px; - } - .room-lobby-chat-peers.chat-panel .chat-send-btn img { - width: 102px; - height: 98px; - } - .room-lobby-top-left-cluster { - top: max(18px, env(safe-area-inset-top)); - left: max(0px, env(safe-area-inset-left)); - gap: 0; - } - .room-lobby-exit-fixed { - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; - gap: 0.45rem; - margin-top: -1.4rem; - width: auto; - max-width: none; - } - .room-lobby-top-right-cluster { - top: max(16px, env(safe-area-inset-top)); - right: max(16px, env(safe-area-inset-right)); - } - .room-lobby-room-id-pill { - width: fit-content; - min-width: 0; - height: 180px; - min-height: 180px; - max-height: 180px; - max-width: none; - padding: 0 15px; - border-style: solid; - border-width: 0 60px; - border-radius: 0; - background: transparent; - border-image-source: url("../img/Room-id-BG.png"); - border-image-slice: 0 60 0 60 fill; - border-image-repeat: stretch; - box-shadow: none; - gap: 0.7rem; - align-items: center; - white-space: nowrap; - } - .room-lobby-room-id-label { - font-size: 2.05rem; - font-weight: 600; - line-height: 1; - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif; - text-transform: none; - color: #e8f7ff; - text-shadow: - 0 0 6px rgba(110, 226, 255, 0.8), - 0 0 14px rgba(44, 198, 255, 0.5); - } - #room-id-value { - font-size: 2.35rem; - line-height: 1; - font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif; - text-transform: none; - font-weight: 600; - color: #ecfbff; - text-shadow: - 0 0 7px rgba(118, 230, 255, 0.9), - 0 0 16px rgba(52, 203, 255, 0.55); - } - .room-lobby-room-id-lock { - width: 60px; - height: 65px; - min-width: 60px; - min-height: 65px; - max-width: 60px; - max-height: 65px; - aspect-ratio: 60 / 65; - font-size: 0; - color: transparent; - background: url("../img/Room-id-private.png") center / 100% 100% no-repeat; - filter: none; - } - .room-lobby-profile-frame { - width: 159px; - height: 157px; - min-width: 159px; - min-height: 157px; - max-width: 159px; - max-height: 157px; - aspect-ratio: 159 / 157; - } - .room-lobby-exit-fixed .btn-exit-icon { - width: 121px; - height: 119px; - min-width: 121px; - min-height: 119px; - max-width: 121px; - max-height: 119px; - aspect-ratio: 121 / 119; - margin-left: 13px; - margin-top: -15px; - margin-bottom: -15px; - } - body.room-lobby-page #room-players-hud { - min-width: 0; - font-size: clamp(1.35rem, 1.95vw, 1.9rem); - padding: 0.1rem 0.4rem; - } - .room-lobby-ready-fixed .ready-label-img { - width: 320px; - height: 126px; - min-width: 320px; - min-height: 126px; - max-width: 320px; - max-height: 126px; - aspect-ratio: 320 / 126; - } - .room-lobby-br-fixed { - --lobby-br-btn: 137px; - bottom: max(0.65rem, env(safe-area-inset-bottom)); - right: max(0.85rem, env(safe-area-inset-right)); - display: flex; - flex-direction: row; - align-items: center; - justify-content: flex-end; - gap: 0.75rem; - } - /* แถวเดียว: หลักฐาน | อันดับ | ไมค์ (ตรง production) */ - .room-lobby-br-fixed .lobby-b-extra-row:not(.is-hidden) { - display: contents; - } - .room-lobby-br-fixed .lobby-b-extra-row { - position: static !important; - margin: 0 !important; - transform: none !important; - z-index: auto; - } - .room-lobby-br-fixed .btn-voice-icon { - position: static !important; - margin: 0 !important; - transform: none !important; - } - .room-lobby-br-fixed .lobby-b-sq-btn, - .room-lobby-br-fixed .btn-voice-icon { - width: var(--lobby-br-btn); - height: var(--lobby-br-btn); - min-width: var(--lobby-br-btn); - min-height: var(--lobby-br-btn); - max-width: var(--lobby-br-btn); - max-height: var(--lobby-br-btn); - } - .room-lobby-chat-peers.chat-panel-collapsed.chat-panel { - width: 122px; - height: 120px; - bottom: 12rem; - right: max(0.85rem, env(safe-area-inset-right)); - } - .room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn { - width: 122px; - height: 120px; - min-width: 122px; - min-height: 120px; - max-width: 122px; - max-height: 120px; - aspect-ratio: 122 / 120; - margin-right: -20px; - } - .room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn img { - width: 122px; - height: 120px; - aspect-ratio: 122 / 120; - } -} - -/* แฟ้มหลักฐาน LobbyB — ดู css/evidence-view-overlay.css (layout ev-*) */ - -/* กระดานอันดับ LobbyB — ดู css/leaderboard-popup.css */ - -.version-tag { - position: fixed; - right: 8px; - bottom: 4px; - left: auto; - font-size: 10px; - color: #a9b1d6; - opacity: 0.7; - pointer-events: none; -} - -/* Editor — เกมตอบคำถาม */ -.quiz-editor-wrap { - margin: 1rem 0; - padding: 1rem; - background: #24283b; - border-radius: 8px; - border: 1px solid #414868; -} -.quiz-editor-wrap h3 { - margin: 0 0 0.5rem; - font-size: 1rem; - color: #7aa2f7; -} -.quiz-questions-list { - display: flex; - flex-direction: column; - gap: 0.6rem; - margin: 0.75rem 0; -} -.quiz-q-row { - display: grid; - grid-template-columns: 1fr auto auto; - gap: 0.5rem; - align-items: center; -} -@media (max-width: 600px) { - .quiz-q-row { - grid-template-columns: 1fr; - } -} -.quiz-q-row input[type="text"] { - min-width: 0; - padding: 0.4rem 0.5rem; - border-radius: 6px; - border: 1px solid #565f89; - background: #1a1b26; - color: #c0caf5; -} -.quiz-q-row select { - padding: 0.35rem; - border-radius: 6px; - border: 1px solid #565f89; - background: #1a1b26; - color: #c0caf5; -} -.btn-quiz-add, -.quiz-q-remove { - padding: 0.35rem 0.65rem; - border-radius: 6px; - cursor: pointer; - border: 1px solid #565f89; - background: #414868; - color: #c0caf5; - font: inherit; -} -.quiz-q-remove { - font-size: 0.8rem; -} - -/* design 2026-05: แสดงปุ่มตั้งค่าโฮสต์ + ปรับแต่ง มุมขวาบน (ตาม TryChangeCSS/CSS ใหม่ — ไม่ใช้ JS เก่า) */ -body.room-lobby-page .room-lobby-top-right-actions { - display: none !important; -} - -/* ---- Player Pick Vote overlay (Card Ban / Silence) — โหวตเลือกผู้เล่น ---- - สร้างด้วย JS ใน room-lobby.js (#pick-vote-overlay) แต่เดิมไม่มี CSS เลย → div จมหลัง UI lobby มองไม่เห็น */ -#pick-vote-overlay { - position: fixed; - inset: 0; - z-index: 12000; - display: flex; - align-items: center; - justify-content: center; - padding: 4vh 4vw; - background: rgba(4, 8, 16, 0.74); - backdrop-filter: blur(4px); - -webkit-backdrop-filter: blur(4px); - opacity: 0; - visibility: hidden; - pointer-events: none; - transition: opacity 0.22s ease, visibility 0.22s ease; - font-family: 'Kanit', sans-serif; -} -#pick-vote-overlay.is-open { - opacity: 1; - visibility: visible; - pointer-events: auto; -} -#pick-vote-overlay .pv-shell { - width: min(460px, 92vw); - max-height: 88vh; - overflow-y: auto; - box-sizing: border-box; - padding: 1.4rem 1.5rem 1.6rem; - border-radius: 18px; - text-align: center; - color: #e8f6ff; - background: linear-gradient(165deg, rgba(16, 30, 50, 0.97), rgba(8, 16, 30, 0.97)); - border: 1px solid rgba(83, 224, 255, 0.55); - box-shadow: 0 0 28px rgba(83, 224, 255, 0.35), inset 0 0 24px rgba(80, 180, 240, 0.14); - transform: translateY(12px) scale(0.97); - transition: transform 0.26s cubic-bezier(0.2, 0.9, 0.3, 1.2); -} -#pick-vote-overlay.is-open .pv-shell { - transform: translateY(0) scale(1); -} -#pick-vote-overlay .pv-badge { - display: inline-block; - padding: 0.2rem 0.85rem; - border-radius: 999px; - font-size: 0.74rem; - font-weight: 700; - letter-spacing: 0.08em; - color: #04121e; - background: linear-gradient(90deg, #53e0ff, #8ad8ff); - box-shadow: 0 0 14px rgba(83, 224, 255, 0.55); -} -#pick-vote-overlay .pv-title { - margin: 0.7rem 0 0.3rem; - font-size: 1.32rem; - font-weight: 700; - text-shadow: 0 0 12px rgba(83, 224, 255, 0.45); -} -#pick-vote-overlay .pv-sub { - margin: 0 0 0.7rem; - font-size: 0.86rem; - line-height: 1.35; - color: #a9c7da; -} -#pick-vote-overlay .pv-timer { - font-size: 1.5rem; - font-weight: 700; - color: #53e0ff; - margin-bottom: 0.6rem; - min-height: 1.4em; -} -#pick-vote-overlay .pv-timer.low { - color: #ff7a7a; - animation: pvPulse 0.7s ease-in-out infinite; -} -@keyframes pvPulse { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.12); } -} -#pick-vote-overlay .pv-list { - display: flex; - flex-direction: column; - gap: 0.5rem; - margin-bottom: 0.6rem; -} -#pick-vote-overlay .pv-cand { - position: relative; - display: flex; - align-items: center; - justify-content: center; - gap: 0.5rem; - width: 100%; - padding: 0.7rem 1rem; - border-radius: 12px; - font: 600 1rem 'Kanit', sans-serif; - color: #e8f6ff; - cursor: pointer; - background: rgba(28, 48, 74, 0.85); - border: 1px solid rgba(83, 224, 255, 0.3); - transition: transform 0.12s ease, border-color 0.15s ease, background 0.15s ease; -} -#pick-vote-overlay .pv-cand:hover { - transform: translateY(-1px); - border-color: rgba(83, 224, 255, 0.7); - background: rgba(36, 62, 94, 0.95); -} -#pick-vote-overlay .pv-cand.is-picked { - border-color: #53e0ff; - background: linear-gradient(90deg, rgba(83, 224, 255, 0.28), rgba(83, 224, 255, 0.14)); - box-shadow: 0 0 14px rgba(83, 224, 255, 0.5); -} -#pick-vote-overlay .pv-me { - font-size: 0.78rem; - color: #8ad8ff; -} -#pick-vote-overlay .pv-bot { - font-size: 0.72rem; - color: #04121e; - background: #7fd4a8; - padding: 0.05rem 0.45rem; - border-radius: 999px; -} -#pick-vote-overlay .pv-count { - position: absolute; - right: 0.7rem; - min-width: 1.5em; - height: 1.5em; - line-height: 1.5em; - border-radius: 999px; - font-size: 0.82rem; - font-weight: 700; - color: #04121e; - background: #53e0ff; - opacity: 0; - transform: scale(0.6); - transition: opacity 0.15s ease, transform 0.15s ease; -} -#pick-vote-overlay .pv-count.show { - opacity: 1; - transform: scale(1); -} -#pick-vote-overlay .pv-result { - margin: 0.4rem 0; - padding: 0.7rem; - border-radius: 12px; - font-size: 1.05rem; - font-weight: 700; - color: #fff; - background: rgba(83, 224, 255, 0.16); - border: 1px solid rgba(83, 224, 255, 0.5); -} -#pick-vote-overlay .pv-foot { - font-size: 0.82rem; - color: #a9c7da; - min-height: 1.2em; -} - -/* ===== มือถือ: ย่อปุ่ม AI chat ที่ใหญ่เกิน (213x201) + ปุ่ม interact (F) ให้พอดีจอ ===== */ -@media (max-width: 600px) { - .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn, - .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { - width: 92px !important; - height: 87px !important; - min-width: 92px !important; - min-height: 87px !important; - max-width: 92px !important; - max-height: 87px !important; - } - .room-lobby-chat-ai.chat-panel .chat-close-btn, - .room-lobby-chat-ai.chat-panel .chat-close-btn img { - width: 42px !important; - height: 42px !important; - } -} - -/* ===== มือถือแนวนอน (จอเตี้ย) — ย่อ/จัด UI ห้องเกม (LobbyA) ให้พอดีไม่ล้น · อิงแนวทาง Main-Lobby · ไม่แตะ PC ===== */ -@media (orientation: landscape) and (max-height: 540px) { - /* ปุ่มมุมขวาล่าง (ไมค์ + แว่น/ถ้วย) — ย่อตามความสูงจอ */ - .room-lobby-br-fixed { --lobby-br-btn: clamp(46px, 11vh, 64px); gap: 7px; } - /* แผงแชท — เดิม 576x525 ล้นจอแนวนอน → ย่อให้พอดีความสูงจอ */ - .room-lobby-chat-peers.chat-panel { - width: min(360px, 52vw); - height: min(248px, calc(100dvh - 80px)); - bottom: max(0.5rem, env(safe-area-inset-bottom)); - padding: 0.9rem 1rem; - } - /* ปุ่มแชท AI (collapsed) — ย่อลงอีกบนแนวนอน */ - .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn, - .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { - width: 62px !important; height: 58px !important; - min-width: 62px !important; min-height: 58px !important; - max-width: 62px !important; max-height: 58px !important; - } - /* ปุ่ม ready — เตี้ยลงเล็กน้อย ไม่ชนปุ่มอื่น */ - .room-lobby-ready-fixed .ready-label-img { height: clamp(38px, 9.5vh, 58px); } - /* ปุ่ม exit/howto มุมซ้ายบน — อิงความสูงจอ */ - .room-lobby-exit-fixed .btn-exit-icon { - width: clamp(46px, 10vh, 62px); - height: clamp(46px, 10vh, 62px); - min-width: clamp(46px, 10vh, 62px); - } -} +* { box-sizing: border-box; } +@font-face { + font-family: 'NotoSansThai'; + src: + url('/Create%20Room/FONTS/NotoSansThai-Medium.ttf') format('truetype'); + font-weight: 500; + font-style: normal; + font-display: swap; +} +body { font-family: sans-serif; margin: 0; background: #1a1b26; color: #c0caf5; } +body.room-lobby-page, +body.room-lobby-page * { + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; +} +.container { max-width: 720px; margin: 1rem auto; padding: 1rem; } + +/* โครง Editor — แยกแถบเครื่องมือ / พื้นที่วาด */ +.editor-page { + display: block; +} + +/* Editor ฝังใน Admin (?embed=1) — เต็มความสูง iframe, พื้นที่แคนวาสใหญ่ + เลื่อนแยก */ +html.editor-embed-admin { + height: 100%; +} +html.editor-embed-admin body { + height: 100%; + margin: 0; + overflow: hidden; +} +body.editor-embed-admin .version-tag { + display: none !important; +} +body.editor-embed-admin .container.editor-page { + max-width: none !important; + width: 100%; + height: 100%; + margin: 0 !important; + padding: 0.35rem 0.5rem 0.45rem; + display: flex; + flex-direction: column; + min-height: 0; + box-sizing: border-box; +} +body.editor-embed-admin .container.editor-page > h1 { + display: none; +} +body.editor-embed-admin .editor-toolbar-wrap { + flex: 0 1 auto; + max-height: min(36vh, 360px); + overflow-x: hidden; + overflow-y: auto; + padding: 0.15rem 0.25rem 0.45rem 0; + margin: 0 0 0.3rem; + border-bottom: 1px solid rgba(65, 72, 104, 0.9); + scrollbar-width: thin; +} +body.editor-embed-admin .editor-workspace { + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; + overflow: hidden; +} +body.editor-embed-admin .canvas-wrap { + flex: 1 1 auto; + min-height: 140px; + overflow: auto; + margin: 0 !important; + border-radius: 10px; + border: 1px solid #414868; + background: #0f1018; + -webkit-overflow-scrolling: touch; +} +body.editor-embed-admin #editor-status { + flex: 0 0 auto; + margin: 0.3rem 0 0; + font-size: 0.8rem; + line-height: 1.35; +} +body.editor-embed-admin .editor-legend-short { + margin: 0.25rem 0 0; + font-size: 0.76rem; + line-height: 1.4; + color: #a8b0d0; +} +body.editor-embed-admin .editor-toolbar { + margin-top: 0.25rem; + margin-bottom: 0.35rem; +} +body.editor-embed-admin .frogger-lanes { + margin: 0.35rem 0; +} +body.editor-embed-admin .editor-bg-section { + margin: 0.35rem 0 0.15rem; +} +h1 { color: #7aa2f7; } +a { color: #9ece6a; } +label { display: inline-block; margin: 0.25rem 0.5rem 0.25rem 0; } +input, button { padding: 0.4rem 0.6rem; margin: 0 0.25rem 0 0; border-radius: 6px; border: 1px solid #414868; } +input { background: #24283b; color: #c0caf5; } +button { background: #7aa2f7; color: #1a1b26; cursor: pointer; border: none; } +.legend { font-size: 0.9rem; color: #a9b1d6; margin: 0.5rem 0; } +.frogger-lanes { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; position: relative; z-index: 2; min-height: 80px; } +.frogger-lanes h3 { margin: 0 0 0.5rem 0; color: #7aa2f7; font-size: 1rem; } +.frogger-lanes table { width: 100%; border-collapse: collapse; font-size: 0.85rem; } +.frogger-lanes th, .frogger-lanes td { padding: 0.25rem 0.5rem; text-align: left; border: 1px solid #414868; } +.frogger-lanes select, .frogger-lanes input[type="number"] { padding: 0.35rem 0.5rem; min-width: 4rem; background: #1a1b26; color: #c0caf5; border: 1px solid #414868; border-radius: 4px; cursor: pointer; font-size: 0.9rem; } +.frogger-lanes select { min-width: 6rem; } +.frogger-lanes .lane-speed { width: 4rem; } +.frogger-lanes .lane-spacing { width: 4rem; } +.frogger-lanes td { vertical-align: middle; } +.frogger-lanes select:disabled, .frogger-lanes input:disabled { opacity: 0.6; cursor: not-allowed; } +.game-type-hint { font-size: 0.85rem; color: #a9b1d6; margin-left: 0.5rem; } +.editor-toolbar { margin: 1rem 0; flex-wrap: wrap; display: flex; align-items: center; gap: 0.5rem 1rem; } +.editor-toolbar label, .editor-toolbar .game-type-hint { margin: 0; } +.editor-bg-section { margin: 0.75rem 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; } +.editor-bg-section label { margin: 0; } +.canvas-wrap { margin: 1rem 0; } +.container { padding-left: 1rem; padding-right: 1rem; } +#editor-canvas { background: #1a1b26; display: block; } +.game-wrap { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 0; } +.game-header { flex-shrink: 0; background: #24283b; padding: 0.5rem 1rem; display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; } +.game-header span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.game-header button { flex-shrink: 0; } +#game-canvas { + flex: 1 1 auto; + display: block; + width: 100%; + min-height: 0; + min-width: 0; + touch-action: none; +} +.game-wrap .chat-panel { flex-shrink: 0; } +.chat-panel { height: 160px; border-top: 1px solid #414868; display: flex; flex-direction: column; } +#chat-messages { flex: 1; overflow-y: auto; padding: 0.5rem; font-size: 0.9rem; } +#chat-form { display: flex; padding: 0.5rem; gap: 0.5rem; } +#chat-input { flex: 1; } + +.lobby-section { margin: 1.25rem 0; padding: 1rem; background: #24283b; border-radius: 8px; } +.lobby-section h2 { margin: 0 0 0.75rem 0; font-size: 1rem; color: #7aa2f7; } +#room-list { list-style: none; margin: 0; padding: 0; } +#room-list .room-item { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid #414868; } +#room-list .room-item:last-child { border-bottom: none; } +#room-list .room-name { font-weight: 600; color: #c0caf5; min-width: 0; } +#room-list .room-meta { font-size: 0.85rem; color: #a9b1d6; } +#room-list .room-meta-inline { font-size: 0.8rem; color: #565f89; font-weight: normal; } +#room-list-status { margin: 0; color: #a9b1d6; font-size: 0.9rem; } + +.room-lobby-peers { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; } +.room-lobby-peer { padding: 0.35rem 0; color: #c0caf5; } +.room-lobby-peer:not(:last-child) { border-bottom: 1px solid #414868; } +#lobby-map-wrap { position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; min-width: 100vw; min-height: 100vh; min-height: 100dvh; z-index: 0; } +body.room-lobby-page { + background: + radial-gradient(120% 120% at 50% -12%, rgba(86, 122, 255, 0.26) 0%, rgba(30, 37, 83, 0.16) 40%, rgba(7, 10, 25, 0) 75%), + linear-gradient(180deg, #1a1d46 0%, #111530 42%, #090d22 100%); + color: #ebf6ff; +} +#lobby-map-wrap::before { + content: ''; + position: absolute; + inset: 0; + z-index: 1; + pointer-events: none; + background: + radial-gradient(80% 65% at 50% 18%, rgba(106, 194, 255, 0.2), rgba(106, 194, 255, 0) 72%), + linear-gradient(180deg, rgba(10, 16, 46, 0.25) 0%, rgba(6, 12, 31, 0.05) 30%, rgba(5, 9, 24, 0.5) 100%); +} +#lobby-map-wrap::after { + content: ''; + position: absolute; + inset: 0; + z-index: 2; + pointer-events: none; + box-shadow: inset 0 0 160px rgba(8, 12, 30, 0.85); +} +#lobby-map-canvas { + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + width: 100%; + height: 100%; + min-width: 100%; + min-height: 100%; + margin: 0; + padding: 0; + background: + radial-gradient(circle at 50% 20%, rgba(124, 197, 255, 0.25) 0%, rgba(124, 197, 255, 0) 45%), + linear-gradient(180deg, #252c66 0%, #1a2150 45%, #121a3b 100%); + box-sizing: border-box; +} +/* [2026-08-02] กันภาพยืดตอนบัฟเฟอร์ยังค้างขนาดเก่า (หมุนจอ / แถบ URL ยุบ-กางบน iOS) + ปกติ canvas.width/height = ขนาด viewport พอดี ⇒ contain ไม่ทำอะไรเลย (วัดแล้วยืด 0.0% ทุกเครื่อง) + แต่ช่วงที่ค่ายังไม่ถูกวัดใหม่ จะเห็นเป็น "ขอบว่าง" แทน "ภาพยืดผิดสัดส่วน" ซึ่งดีกว่ามาก + ห่อด้วย pointer: coarse → PC (pointer: fine) ไม่โดนกฎนี้เลย · สูตรเดียวกับที่ play.html ใช้มาตั้งแต่ 07-31 */ +@media (pointer: coarse) { + #lobby-map-canvas { object-fit: contain; } +} +#lobby-map-canvas:focus { + outline: none; +} +#lobby-map-canvas:focus-visible { + outline: 2px solid rgba(122, 162, 247, 0.45); + outline-offset: -2px; +} +/* LobbyB (mn8nx46h) — ไม่แสดงปุ่มพร้อม */ +body.room-lobby--lobby-b .room-lobby-ready-fixed { + display: none !important; +} +.lobby-interact-hint { + position: absolute; + bottom: max(10px, env(safe-area-inset-bottom)); + left: 50%; + transform: translateX(-50%); + z-index: 2; + margin: 0; + padding: 0.2rem 0.55rem; + font-size: clamp(0.72rem, 1.8vw, 0.85rem); + color: rgba(203, 213, 245, 0.9); + text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55); + pointer-events: none; + font-family: system-ui, 'Kanit', sans-serif; + white-space: nowrap; +} +.lobby-interact-hint kbd { + display: inline-block; + padding: 0.06em 0.32em; + border-radius: 4px; + background: rgba(26, 27, 38, 0.88); + border: 1px solid rgba(122, 162, 247, 0.45); + font-size: 0.88em; + font-family: inherit; +} +.lobby-zoom-pct { + position: absolute; + top: 12px; + left: 50%; + transform: translateX(-50%); + z-index: 2; + padding: 6px 12px; + border-radius: 8px; + background: rgba(26, 27, 38, 0.85); + color: #c0caf5; + font-size: 1rem; + font-weight: 600; + pointer-events: none; + opacity: 0; + transition: opacity 0.2s ease; +} +.lobby-zoom-pct.lobby-zoom-pct-visible { opacity: 1; } +/* ซ่อนแผง overlay รายชื่อ / host / แชท — โถงโฟกัสแผนที่ + ปุ่ม READY/ไมค์ ด้านนอก */ +.room-lobby-overlay { display: none !important; } +.room-lobby-top-left-cluster { + position: fixed; + top: max(12px, env(safe-area-inset-top)); + left: max(0px, env(safe-area-inset-left)); + z-index: 55; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0.4rem; + pointer-events: none; +} +.room-lobby-top-left-cluster .room-lobby-exit-fixed { + pointer-events: auto; +} +.room-lobby-room-id-pill { + pointer-events: auto; + display: inline-flex; + align-items: center; + gap: 0.4rem; + min-height: 44px; + padding: 0.5rem 0.9rem; + border-radius: 12px; + border: 1px solid rgba(106, 232, 255, 0.58); + background: linear-gradient(180deg, rgba(43, 67, 128, 0.86), rgba(22, 34, 74, 0.9)); + box-shadow: + inset 0 0 0 1px rgba(188, 247, 255, 0.2), + 0 0 18px rgba(80, 213, 255, 0.32); + color: #dff6ff; + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif; + letter-spacing: 0.03em; +} +.room-lobby-room-id-label { + font-weight: 600; + font-size: clamp(0.78rem, 1.7vw, 0.9rem); + opacity: 0.92; +} +#room-id-value { + font-weight: 800; + font-size: clamp(0.85rem, 1.9vw, 1rem); + color: #f4fdff; +} +.room-lobby-room-id-lock { + font-size: 0.85rem; + filter: drop-shadow(0 0 6px rgba(105, 227, 255, 0.6)); +} + +/* มุมขวาบน — โปรไฟล์ตัวละคร */ +.room-lobby-top-right-cluster { + position: fixed; + top: max(12px, env(safe-area-inset-top)); + right: max(12px, env(safe-area-inset-right)); + z-index: 56; + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 0.4rem; + pointer-events: none; +} +.room-lobby-top-right-cluster > * { + pointer-events: auto; +} +.room-lobby-top-right-actions { + display: none !important; +} +.room-lobby-top-right-action-btn { + position: relative; + flex: 0 0 auto; + width: clamp(100px, 11vw, 161px); + height: auto; + min-width: 0; + min-height: 0; + max-width: 161px; + aspect-ratio: 161 / 176; + padding: 0; + margin: 0; + border: none; + border-radius: 0; + background: transparent; + box-shadow: none; + cursor: pointer; + overflow: visible; + isolation: isolate; +} +.room-lobby-top-right-action-btn img { + width: 100%; + height: auto; + max-width: 161px; + aspect-ratio: 161 / 176; + object-fit: contain; + display: block; + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} +.room-lobby-profile-wrap { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.2rem; +} +.room-lobby-profile-frame { + position: relative; + width: 159px; + height: 157px; + min-width: 159px; + min-height: 157px; + max-width: 159px; + max-height: 157px; + aspect-ratio: 159 / 157; + border-radius: 0; + border: none; + overflow: hidden; + background: url(../img/btn-profile-bg.png) center/100% 100% no-repeat; + box-shadow: none; +} +.room-lobby-profile-avatar-viewport { + position: absolute; + left: 12px; + top: 10px; + width: 124px; + height: 118px; + overflow: hidden; + border-radius: 12px; +} +.room-lobby-profile-frame #room-lobby-profile-avatar { + position: absolute; + left: 50%; + top: 5px; + display: block; + width: 120%; + height: auto; + max-width: none; + object-fit: contain; + object-position: center top; + transform: translateX(-50%); + transform-origin: center center; + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.room-lobby-profile-set-btn { + position: absolute; + right: 0; + bottom: 0; + width: 71px; + height: 71px; + min-width: 71px; + min-height: 71px; + max-width: 71px; + max-height: 71px; + aspect-ratio: 71 / 71; + padding: 0; + margin: 0; + border: none; + border-radius: 0; + background: transparent; + cursor: pointer; + z-index: 2; +} +.room-lobby-profile-set-btn img { + display: block; + width: 71px; + height: 71px; + min-width: 71px; + min-height: 71px; + max-width: 71px; + max-height: 71px; + aspect-ratio: 71 / 71; + object-fit: contain; +} + +/* Profile overlay — see profile-popup.css (linked from room-lobby.html) */ + + +/* Host Console popup */ +.room-lobby-host-console-overlay { + position: fixed; + inset: 0; + z-index: 10070; + display: flex; + align-items: center; + justify-content: center; + padding: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left)); +} +.room-lobby-host-console-overlay.is-hidden { + display: none !important; +} +.room-lobby-host-console-backdrop { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.8); +} +.room-lobby-host-console-dialog { + position: relative; + z-index: 1; + width: min(990px, calc(100vw - 24px), calc((100dvh - 24px) * (990 / 881))); + aspect-ratio: 990 / 881; + max-height: calc(100dvh - 24px); + --hc-scale: 1; + --hc-close-hit-size: calc(82px * var(--hc-scale)); + --hc-close-hit-top: 9%; + --hc-close-hit-right: 6.5%; + background: url(../img/03-4-Host-Console/host-console-bg.png) center/100% 100% no-repeat; + box-sizing: border-box; +} +.room-lobby-host-console-body { + position: absolute; + top: 13.6%; + right: 7.9%; + bottom: 6%; + left: 8.2%; + display: flex; + flex-direction: column; + align-items: center; + min-height: 0; + padding-top: calc(50px * var(--hc-scale)); + padding-bottom: calc(62px * var(--hc-scale)); + box-sizing: border-box; +} +.room-lobby-host-console-close { + position: absolute; + top: var(--hc-close-hit-top); + right: var(--hc-close-hit-right); + width: var(--hc-close-hit-size); + height: var(--hc-close-hit-size); + border: none; + border-radius: 0; + background: transparent; + color: transparent; + font-size: 0; + line-height: 1; + cursor: pointer; + text-shadow: none; + z-index: 3; + -webkit-tap-highlight-color: transparent; +} +.room-lobby-host-console-txt-img { + width: auto; + object-fit: contain; + display: block; +} +.room-lobby-host-console-txt-max { + height: calc(66px * var(--hc-scale)); + margin-bottom: calc(10px * var(--hc-scale)); +} +.room-lobby-host-console-max-wrap { + position: relative; + width: min(82%, calc(657px * var(--hc-scale))); + aspect-ratio: 657 / 141; + margin-bottom: calc(-10px * var(--hc-scale)); + margin-top: calc(-30px * var(--hc-scale)); +} +.room-lobby-host-console-textfield-bg { + width: 100%; + height: 100%; + object-fit: contain; + display: block; +} +.room-lobby-host-console-arrow-btn { + position: absolute; + top: 50%; + width: calc(51px * var(--hc-scale)); + height: calc(54px * var(--hc-scale)); + padding: 0; + margin: 0; + border: none; + border-radius: 0; + background: transparent; + cursor: pointer; + transform: translateY(-50%); +} +.room-lobby-host-console-arrow-left { left: 4.9%; } +.room-lobby-host-console-arrow-right { right: 4.9%; } +.room-lobby-host-console-arrow-btn img { + width: 100%; + height: 100%; + object-fit: contain; + display: block; +} +.room-lobby-host-console-max-value { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + min-width: 2ch; + text-align: center; + font-size: calc(40px * var(--hc-scale)); + font-weight: 700; + color: #eaf9ff; + text-shadow: 0 0 10px rgba(0, 255, 255, 0.35); +} +.room-lobby-host-console-summary { + margin: 0 0 calc(12px * var(--hc-scale)); + font-size: calc(24px * var(--hc-scale)); + color: #d9f3ff; + margin-bottom: 4%; +} +.room-lobby-host-console-line { + width: min(94%, calc(744px * var(--hc-scale))); + height: auto; + margin-bottom: calc(10px * var(--hc-scale)); + object-fit: contain; +} +.room-lobby-host-console-txt-members { + height: calc(61px * var(--hc-scale)); + margin-bottom: calc(8px * var(--hc-scale)); +} +.room-lobby-host-console-members { + width: min(84%, calc(694px * var(--hc-scale))); + flex: 1 1 auto; + min-height: 0; + overflow-x: hidden; + overflow-y: scroll; + padding-right: calc(40px * var(--hc-scale)); + padding-left: calc(35px * var(--hc-scale)); + scrollbar-width: auto; + scrollbar-color: rgba(255, 104, 228, 0.98) rgba(20, 40, 70, 0.55); + scrollbar-gutter: stable both-edges; +} +.room-lobby-host-console-members::-webkit-scrollbar { + width: clamp(24px, calc(36px * var(--hc-scale)), 42px); +} +.room-lobby-host-console-members::-webkit-scrollbar-track { + background: rgba(20, 40, 70, 0.55); + border-radius: 999px; + border: 1px solid rgba(90, 220, 255, 0.35); +} +.room-lobby-host-console-members::-webkit-scrollbar-thumb { + background: linear-gradient(180deg, rgba(255, 125, 236, 1) 0%, rgba(241, 74, 215, 1) 100%); + border-radius: 999px; + border: 3px solid rgba(16, 32, 56, 0.65); + background-clip: padding-box; + box-shadow: 0 0 10px rgba(255, 84, 226, 0.45); +} +.room-lobby-host-console-members-list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: calc(18px * var(--hc-scale)); +} +.room-lobby-host-console-member-item { + position: relative; + min-height: calc(44px * var(--hc-scale)); + padding: calc(2px * var(--hc-scale)) calc(104px * var(--hc-scale)) calc(2px * var(--hc-scale)) calc(12px * var(--hc-scale)); + display: flex; + align-items: center; + justify-content: flex-start; + gap: 0.6rem; + color: #e9f8ff; + font-size: calc(28px * var(--hc-scale)); + background: url(../img/03-4-Host-Console/host-console-line-2.png) left bottom/100% 3px no-repeat; +} +.room-lobby-host-console-member-item.is-host { + min-height: calc(80px * var(--hc-scale)); + padding-right: calc(12px * var(--hc-scale)); + background: url(../img/03-4-Host-Console/host-console-hostname.png) center/100% 100% no-repeat; + font-weight: 700; +} +.room-lobby-host-console-member-name { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: inherit; + padding-left: 4%; + margin-top: -4%; +} +.room-lobby-host-console-member-item.is-host .room-lobby-host-console-member-name { + margin-top: 0%; /* เพิ่มค่านี้ = ขยับลง */ +} +.room-lobby-host-console-delete-btn { + position: absolute; + right: calc(10px * var(--hc-scale)); + top: 50%; + transform: translateY(-50%); + width: calc(84px * var(--hc-scale)); + height: calc(84px * var(--hc-scale)); + min-width: calc(84px * var(--hc-scale)); + padding: 0; + border: none; + border-radius: 0; + background: transparent; + cursor: pointer; + margin-top: -2%; + margin-right: -1%; +} +.room-lobby-host-console-delete-btn img { + width: 100%; + height: 100%; + object-fit: contain; + display: block; +} +.room-lobby-host-console-delete-btn:disabled { + opacity: 0.35; + cursor: default; +} +.room-lobby-host-console-confirm { + position: absolute; + left: 50%; + bottom: calc(-60px * var(--hc-scale)); + transform: translateX(-50%); + width: min(43%, calc(350px * var(--hc-scale))); + aspect-ratio: 350 / 129; + border: none; + border-radius: 0; + padding: 0; + background: transparent; + cursor: pointer; +} +.room-lobby-host-console-confirm img { + width: 100%; + height: 100%; + object-fit: contain; + display: block; +} +/* Profile popup: tightened scaling for reduced viewports */ +@media (max-width: 1100px), (max-height: 700px) { + .room-lobby-profile-content { + top: 13%; + right: 4%; + bottom: 8%; + left: 4%; + gap: clamp(8px, 1vw, 14px); + grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.12fr); + } + .room-lobby-profile-left-pane { + grid-template-rows: minmax(0, 1fr) auto; + row-gap: clamp(3px, 0.5vw, 6px); + } + .room-lobby-profile-logout { + width: min(58%, 100%); + } + .room-lobby-profile-char-card #room-lobby-profile-overlay-avatar { + width: 74%; + max-width: 74%; + max-height: 60%; + } +} +@media (max-width: 900px), (max-height: 560px) { + .room-lobby-profile-content { + top: 11%; + right: 3%; + bottom: 7%; + left: 3%; + gap: 8px; + grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.08fr); + } + .room-lobby-profile-logout { + width: min(62%, 100%); + } + .room-lobby-profile-char-card #room-lobby-profile-overlay-avatar { + width: 64%; + max-width: 64%; + max-height: 56%; + } +} +.room-lobby-actions { margin-top: 1rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; } +.room-lobby-actions .room-lobby-btn-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; opacity: 0; pointer-events: none; } +.room-lobby-actions label { margin: 0; } +.room-lobby-actions #btn-start { background: #9ece6a; color: #1a1b26; } +#host-only { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; } +#host-only select { padding: 0.4rem 0.6rem; border-radius: 6px; border: 1px solid #414868; background: #24283b; color: #c0caf5; } +.host-start-area-hint { + flex-basis: 100%; + margin: 0; + font-size: 0.88rem; + color: #e0af68; + line-height: 1.35; + max-width: 100%; +} +#host-only #btn-start:disabled { + opacity: 0.5; + cursor: not-allowed; + filter: grayscale(0.25); +} +.room-lobby-chat { margin-top: 1rem; } +.room-lobby-chat.chat-panel { + border-radius: 12px; + overflow: hidden; + box-shadow: none; +} +.room-lobby-chat-peers.chat-panel { + position: fixed; + right: 0.25rem; + bottom: 10rem; + width: 576px; + height: 525px; + max-width: calc(100vw - 2.5rem); + z-index: 52; + margin-top: 0; + display: flex; + flex-flow: column; + padding: 2rem; + box-sizing: border-box; + border-top: 0px solid #414868; + background: url(../img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; + background-color: transparent; +} +.room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img img { width: 90px; height: 77px; } +.room-lobby-chat-peers.chat-panel .chat-close-btn { width: 48px; height: 48px; } +.room-lobby-chat-peers.chat-panel .chat-close-btn img { width: 50px; height: 50px; } +.room-lobby-chat-peers.chat-panel #chat-messages { padding: 0.75rem; font-size: 1.05rem; gap: 0.5rem; } +.room-lobby-chat-peers.chat-panel .chat-form-bar { padding: 0.6rem 0; gap: 0.5rem; } +.room-lobby-chat-peers.chat-panel #chat-input { padding: 0.6rem 0.85rem; font-size: 1.05rem; } +.room-lobby-chat-peers.chat-panel .chat-send-btn { width: 52px; height: 52px; } +.room-lobby-chat-peers.chat-panel .chat-send-btn img { width: 58px; height: 58px; } +.room-lobby-chat-peers.chat-panel .chat-msg { padding: 0.6rem 1rem; font-size: 1.05rem; } +.room-lobby-chat-peers.chat-panel .chat-header-bar { + margin: 0 -2rem 0 -2rem; + padding-left: 2rem; + padding-right: 2rem; + justify-content: space-between; + align-items: center; + min-height: 72px; + height: 72px; +} +.room-lobby-chat-peers.chat-panel #chat-messages { + flex: 1; + min-height: 0; + height: auto; +} +.room-lobby-chat .chat-header-bar { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0; + min-height: 48px; + height: 48px; + background: url(../img/chat-line.png) bottom repeat-x; + background-size: 100% 4px; + background-color: transparent; +} +.room-lobby-chat-peers .chat-header-title.chat-header-title-img { + display: inline-flex; + align-items: center; + line-height: 0; +} +.room-lobby-chat-peers .chat-header-title.chat-header-title-img img { + width: 60px; + height: 51px; + object-fit: contain; + display: block; +} +.room-lobby-chat-ai .chat-header-title.chat-header-title-img { + display: flex; + align-items: flex-end; + gap: 0.5rem; + line-height: 0; + min-width: 0; + overflow: visible; +} +.room-lobby-chat-ai .chat-header-title.chat-header-title-img .ai-chat-title-label { + height: 64px; + width: auto; + max-width: none; + object-fit: contain; + display: block; + flex-shrink: 0; + margin-bottom: -2px; +} +/* รูปหัวแชท AI — ยกขึ้นเหนือเส้น */ +.room-lobby-chat-ai .chat-header-title.chat-header-title-img img { + width: 86px; + height: 92px; + object-fit: cover; + display: block; + flex-shrink: 0; + margin-top: -27px; + margin-left: -6px; + position: relative; + z-index: 1; +} +.room-lobby-chat .chat-header-title { + font-size: 1rem; + font-weight: 600; + color: #a0aec0; +} +.room-lobby-chat .chat-close-btn { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + border: none; + border-radius: 8px; + background: transparent; + cursor: pointer; + margin-left: auto; +} +.room-lobby-chat-peers .chat-header-bar .chat-close-btn { margin-left: 0; } +.room-lobby-chat .chat-close-btn img { width: 34px; height: 34px; object-fit: contain; } +.room-lobby-chat .chat-close-btn:hover { opacity: 0.9; } +.room-lobby-chat.chat-panel-collapsed #chat-messages, +.room-lobby-chat.chat-panel-collapsed .chat-form-bar { display: none !important; } +.room-lobby-chat-peers.chat-panel-collapsed .chat-header-title { display: none !important; } +.room-lobby-chat-peers.chat-panel-collapsed .chat-header-bar { + justify-content: center; + padding: 0; + background: none !important; + border: none; +} +.room-lobby-chat-peers.chat-panel-collapsed.chat-panel { + width: 80px; + height: 80px; + min-height: 0; + padding: 0; + right: 1.25rem; + bottom: 6.25rem; + display: flex; + align-items: center; + justify-content: center; + background: none !important; + background-color: transparent !important; + border: none; + box-shadow: none; +} +.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn { + width: 80px; + height: 80px; + overflow: visible; +} +.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn img { + width: 100%; + height: 100%; + object-fit: contain; + object-position: center; + display: block; +} +.room-lobby-chat #chat-messages, +.room-lobby-chat #ai-chat-messages { + height: 100px; + overflow-y: auto; + padding: 0.5rem; + font-size: 0.85rem; + border: none; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.35rem; + background: none; + background-color: transparent; + box-shadow: none; +} +.room-lobby-chat .chat-messages-bg { border-radius: 0; } +.room-lobby-chat #chat-form.chat-form-bar, +.room-lobby-chat #ai-chat-form.chat-form-bar { + display: flex; + gap: 0.4rem; + align-items: center; + padding: 0.4rem 0; + background: none; + background-color: transparent; + border-top: none; + flex-shrink: 0; +} +.room-lobby-chat-peers .chat-form-bar { + padding-left: 0; + padding-right: 0; +} +.room-lobby-chat #chat-input, +.room-lobby-chat #ai-chat-input { + flex: 1; + min-width: 0; + padding: 0.45rem 0.6rem; + border-radius: 10px; + border: 1px solid rgba(0, 212, 255, 0.25); + background: rgba(30, 35, 50, 0.8); + color: #c0caf5; + font-size: 0.9rem; + box-sizing: border-box; + margin-left: 9px; +} +.room-lobby-chat .chat-send-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + flex-shrink: 0; + padding: 0; + border: none; + border-radius: 10px; + background: transparent; + cursor: pointer; +} +.room-lobby-chat .chat-send-btn img { width: 45px; height: 45px; object-fit: contain; } +.room-lobby-chat .chat-send-btn:hover { opacity: 0.9; } +.room-lobby-chat .chat-msg { + padding: 0.4rem 0.75rem; + border-radius: 12px; + max-width: 85%; + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; +} +.room-lobby-chat .chat-msg-mine { + align-self: flex-end; + text-align: right; + background-image: url(../img/chat-bubble-me.png); + background-color: rgba(122, 162, 247, 0.9); + color: #1a1b26; +} +.room-lobby-chat .chat-msg-other { + align-self: flex-start; + text-align: left; + background-image: url(../img/chat-bubble-friend.png); + background-color: rgba(65, 72, 104, 0.9); + color: #c0caf5; +} +.room-lobby-chat .chat-msg-ai { + align-self: flex-start; + text-align: left; + background-image: url(../img/chat-bubble-friend.png); + background-color: rgba(158, 206, 106, 0.9); + color: #1a1b26; +} +.room-lobby-chat .chat-msg-system { + align-self: center; + text-align: center; + max-width: 95%; + background-image: none; + background-color: rgba(26, 27, 38, 0.72); + color: #9aa5ce; + font-size: 0.88rem; + font-style: italic; + padding: 0.35rem 0.6rem; +} + +/* AI chat — loading แบบ Messenger (จุดกระโดด 3 จุด), อยู่ติดข้อความล่าสุดในลิสต์ */ +.room-lobby-chat .ai-chat-typing { + display: flex; + align-items: center; + gap: 4px; + padding: 12px 14px; + min-height: 24px; + flex-shrink: 0; + background-image: url(../img/chat-bubble-friend.png); + background-color: rgba(158, 206, 106, 0.9); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; +} +.room-lobby-chat .ai-typing-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: #1a1b26; + animation: ai-typing-bounce 1.4s ease-in-out infinite both; +} +.room-lobby-chat .ai-typing-dot:nth-child(1) { animation-delay: 0s; } +.room-lobby-chat .ai-typing-dot:nth-child(2) { animation-delay: 0.2s; } +.room-lobby-chat .ai-typing-dot:nth-child(3) { animation-delay: 0.4s; } +@keyframes ai-typing-bounce { + 0%, 60%, 100% { transform: translateY(0); } + 30% { transform: translateY(-6px); } +} + +/* AI chat panel — match Main-Lobby lobby-ai-chat-panel */ +.room-lobby-chat-ai.chat-panel { + position: fixed; + left: 8px; + right: auto; + bottom: clamp(0.5rem, 2vw, 1rem); + width: 454px; + height: 526px; + max-width: calc(100vw - 2.5rem); + z-index: 51; + margin: 0; + display: flex; + flex-flow: column; + box-sizing: border-box; + padding: 2.6rem; + overflow: visible; + background: url(../img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; + background-color: transparent; + border: none; + box-shadow: none; + border-radius: 12px; + pointer-events: none; +} +.room-lobby-chat-ai.chat-panel .chat-header-bar, +.room-lobby-chat-ai.chat-panel #ai-chat-messages, +.room-lobby-chat-ai.chat-panel #ai-chat-form, +.room-lobby-chat-ai.chat-panel .ai-chat-admin-link { + pointer-events: auto; +} +.room-lobby-chat-ai.chat-panel .chat-header-bar { + margin: 0 -2rem 0 -2rem; + padding: 0 1rem; + justify-content: space-between; + align-items: center; + min-height: 50px; + height: 50px; + overflow: visible; + background: url(../img/AI-chat-line.png) bottom repeat-x; + background-size: 100% 3px; + background-color: transparent; +} +.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img img { + width: 100px; + height: 116px; + margin-top: -39px; + margin-left: 16px; + object-fit: cover; + position: relative; + z-index: 1; +} +.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img .ai-chat-title-label { + height: 80px; + width: auto; + max-width: none; + margin-bottom: -4px; + margin-left: -5px; + transform: translateX(-6px); +} +.room-lobby-chat-ai.chat-panel .chat-close-btn { + display: flex; + align-items: center; + justify-content: center; + width: 60px; + height: 60px; + padding: 0; + border: none; + border-radius: 8px; + background: transparent; + cursor: pointer; + margin-left: auto; +} +.room-lobby-chat-ai.chat-panel .chat-close-btn img { + width: 60px; + height: 60px; + object-fit: contain; +} +.room-lobby-chat-ai.chat-panel .chat-close-btn:hover { + opacity: 0.9; +} +.room-lobby-chat-ai.chat-panel #ai-chat-messages { + flex: 1; + min-height: 0; + height: auto; + overflow-y: auto; + padding: 0.2rem 0.35rem 0.25rem 0; + font-size: 1.05rem; + gap: 0.5rem; + background: none; + border: none; + scrollbar-width: thin; + scrollbar-color: rgba(244, 252, 255, 0.98) rgba(53, 110, 167, 0.28); +} +.room-lobby-chat-ai.chat-panel #ai-chat-messages::-webkit-scrollbar { + width: 1rem; + scrollbar-width: auto; +} +.room-lobby-chat-ai.chat-panel #ai-chat-messages::-webkit-scrollbar-track { + border-radius: 999px; + background: linear-gradient(180deg, rgba(38, 77, 125, 0.45) 0%, rgba(32, 66, 106, 0.38) 100%); + box-shadow: inset 0 0 0 1px rgba(107, 193, 255, 0.25); +} +.room-lobby-chat-ai.chat-panel #ai-chat-messages::-webkit-scrollbar-thumb { + border-radius: 999px; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, rgba(221, 244, 255, 0.96) 100%); + box-shadow: + 0 0 10px rgba(169, 239, 255, 0.55), + inset 0 0 0 1px rgba(180, 235, 255, 0.9); +} +.room-lobby-chat-ai.chat-panel .chat-form-bar { + display: flex; + gap: 0; + align-items: center; + padding: 0.6rem 0; + flex-shrink: 0; + background: none; + border: none; + width: calc(100% + 3rem); + margin-left: 0; + margin-right: 0; +} +.room-lobby-chat-ai.chat-panel #ai-chat-input { + flex: 0.85; + min-width: 0; + min-height: 50px; + padding: 0.6rem 0.85rem; + border-radius: 8px; + border: 1px solid rgba(0, 212, 255, 0.32); + background: rgba(30, 35, 50, 0.55); + color: #c0caf5; + font-size: 1.05rem; + margin: 0; +} +.room-lobby-chat-ai.chat-panel .chat-send-btn { + width: 73px; + height: 73px; + margin-left: 0; + margin-right: -0.7rem; +} +.room-lobby-chat-ai.chat-panel .chat-send-btn img { + width: 102px; + height: 98px; + object-fit: contain; +} +.room-lobby-chat-ai.chat-panel .chat-send-btn:focus, +.room-lobby-chat-ai.chat-panel .chat-send-btn:focus-visible { + outline: none !important; + box-shadow: none !important; + border-color: transparent !important; +} +.room-lobby-chat-ai.chat-panel .chat-msg { + padding: 0.58rem 0.92rem; + font-size: 1.05rem; + line-height: 1.33; + border: none; + box-shadow: none; +} +.room-lobby-chat-ai.chat-panel .chat-msg-mine { + background-color: rgba(122, 162, 247, 0.2); + color: #f787e4; +} +.room-lobby-chat-ai.chat-panel .chat-msg-ai { + background-color: rgba(158, 206, 106, 0.2); + color: #f2f8ff; +} +.room-lobby-chat-ai.chat-panel .ai-chat-typing { + padding: 14px 18px; + min-height: 28px; + background-color: rgba(158, 206, 106, 0.32); +} +.room-lobby-chat-ai.chat-panel .ai-typing-dot { + width: 8px; + height: 8px; + background: #f2f8ff; +} +.room-lobby-chat-ai.chat-panel .ai-chat-admin-link { + margin: 0.35rem 0 0 0; + font-size: 0.75rem; + flex-shrink: 0; +} +.room-lobby-chat-ai.chat-panel, +.room-lobby-chat-ai.chat-panel #ai-chat-messages, +.room-lobby-chat-ai.chat-panel #ai-chat-input, +.room-lobby-chat-ai.chat-panel .chat-msg, +.room-lobby-chat-ai.chat-panel .ai-chat-typing, +.room-lobby-chat-ai.chat-panel .chat-send-btn, +.room-lobby-chat-ai.chat-panel .ai-chat-admin-link, +.room-lobby-chat-ai.chat-panel .ai-chat-admin-link a { + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; +} +.room-lobby-chat-ai.chat-panel #ai-chat-messages, +.room-lobby-chat-ai.chat-panel #ai-chat-messages * { + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; +} +.room-lobby-chat-ai.chat-panel #ai-chat-input::placeholder { + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; +} + +/* Host console: force NotoSansThai for highlighted text areas */ +.room-lobby-host-console-summary, +.room-lobby-host-console-member-item, +.room-lobby-host-console-member-name, +.room-lobby-host-console-max-value { + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; +} + +/* AI chat collapsed — match Main-Lobby lobby-btn-ai-chat style */ +.room-lobby-chat-ai.chat-panel-collapsed #ai-chat-messages, +.room-lobby-chat-ai.chat-panel-collapsed .chat-form-bar, +.room-lobby-chat-ai.chat-panel-collapsed .ai-chat-admin-link { display: none !important; } +.room-lobby-chat-ai.chat-panel-collapsed .chat-header-title { display: none !important; } +.room-lobby-chat-ai.chat-panel-collapsed .chat-header-bar { + justify-content: center; + padding: 0; + background: none !important; + border: none; + min-height: 0; + height: auto; +} +.room-lobby-chat-ai.chat-panel-collapsed.chat-panel { + width: 213px; + max-width: 213px; + height: 201px; + min-height: 201px; + padding: 0; + left: max(1.25rem, env(safe-area-inset-left)); + bottom: clamp(0.5rem, 2vw, 1rem); + display: flex; + align-items: center; + justify-content: center; + background: none !important; + background-color: transparent !important; + border: none; + box-shadow: none; +} +.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn { + width: 213px; + height: 201px; + min-width: 213px; + min-height: 201px; + max-width: 213px; + max-height: 201px; + aspect-ratio: 213 / 201; + overflow: visible; + border-radius: 0; + margin-left: 0; +} +.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { + width: 213px; + height: 201px; + min-width: 213px; + min-height: 201px; + max-width: 213px; + max-height: 201px; + aspect-ratio: 213 / 201; + object-fit: contain; + object-position: center; + display: block; +} + +.room-lobby-exit-fixed { + position: static; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + justify-content: flex-start; + gap: 10px; + width: max-content; + max-width: calc(100vw - 24px); + box-sizing: border-box; +} +.room-lobby-exit-fixed .btn-exit-icon { + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + margin: 0; + width: clamp(58px, 9vw, 72px); + height: clamp(58px, 9vw, 72px); + min-width: clamp(58px, 9vw, 72px); + padding: 0; + border: none; + border-radius: 0; + background: transparent; + box-shadow: none; + cursor: pointer; +} +.room-lobby-exit-fixed .btn-exit-icon:hover { + transform: translateY(-1px); + filter: brightness(1.08); +} +.room-lobby-exit-fixed .btn-exit-icon img { + width: 100%; + height: auto; + object-fit: contain; + display: block; +} + +.room-lobby-ready-fixed { + position: fixed; + bottom: max(2rem, env(safe-area-inset-bottom)); + left: 50%; + transform: translateX(-50%); + z-index: 120; + pointer-events: none; +} +.room-lobby-ready-fixed .ready-label, +.room-lobby-ready-fixed .ready-check-input { + pointer-events: auto; +} +.room-lobby-ready-fixed .ready-label { + position: relative; + display: inline-block; + padding: 0; + margin: 0; + border: none; + border-radius: 0; + background: transparent; + box-shadow: none; + cursor: pointer; + transition: transform 0.15s ease, filter 0.15s ease; + line-height: 0; + filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.42)); +} +.room-lobby-ready-fixed .ready-label:hover { + transform: scale(1.04); + filter: brightness(1.08); +} +.room-lobby-ready-fixed .ready-label:active { + transform: scale(0.98); +} +.room-lobby-ready-fixed .ready-check-input { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + margin: 0; + opacity: 0; + cursor: pointer; + z-index: 2; +} +.room-lobby-ready-fixed .ready-label-img { + display: block; + height: clamp(44px, 8vh, 72px); + width: auto; + max-width: min(240px, 78vw); + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} +.room-lobby-ready-fixed .ready-label--active .ready-label-img { + filter: drop-shadow(0 0 10px rgba(158, 206, 106, 0.45)); +} +body.room-lobby-page #room-players-hud { + top: max(10px, env(safe-area-inset-top)) !important; + min-width: 0; + border-radius: 0; + border: none; + background: transparent; + box-shadow: none; + backdrop-filter: none; + color: #e3f6ff !important; + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif !important; + text-transform: none; + letter-spacing: 0.08em; + text-shadow: + 0 2px 0 rgba(0, 0, 0, 0.8), + 0 0 12px rgba(0, 0, 0, 0.55); + text-align: center; +} + +/* มุมขวาล่าง — ไมค์ทุกห้อง + ปุ่ม LobbyB (แว่น/ถ้วย) */ +.room-lobby-br-fixed { + --lobby-br-btn: 80px; + position: fixed; + bottom: max(0.95rem, env(safe-area-inset-bottom)); + right: max(1.25rem, env(safe-area-inset-right)); + z-index: 400; + display: flex; + flex-direction: row; + align-items: flex-end; + gap: 10px; + pointer-events: none; +} +.room-lobby-br-fixed .lobby-b-extra-row, +.room-lobby-br-fixed .btn-voice-icon { + pointer-events: auto; +} +.lobby-b-extra-row { + display: flex; + flex-direction: row; + align-items: flex-end; + gap: 10px; +} +.lobby-b-extra-row.is-hidden { + display: none !important; +} +/* โหมดเกม (ควิซ) ใน room-lobby — ไม่โชว์แว่น/ถ้วย LobbyB */ +body.room-lobby--quiz-active .lobby-b-extra-row { + display: none !important; + visibility: hidden !important; + pointer-events: none !important; +} +/* ปุ่มมุมขวาล่าง — ขนาดเดียวกัน (กัน UA border / box model ต่างกัน) */ +.room-lobby-br-fixed .lobby-b-sq-btn, +.room-lobby-br-fixed .btn-voice-icon { + box-sizing: border-box; + width: var(--lobby-br-btn); + height: var(--lobby-br-btn); + min-width: var(--lobby-br-btn); + min-height: var(--lobby-br-btn); + max-width: var(--lobby-br-btn); + max-height: var(--lobby-br-btn); + margin: 0; + padding: 0; + border: none; + border-radius: 0; + appearance: none; + -webkit-appearance: none; + flex-shrink: 0; + cursor: pointer; + background: transparent; + box-shadow: none; +} +/* สไตล์เดียวกับปุ่มไมค์ — ไม่มีกรอบ cyan / bg-item */ +.lobby-b-sq-btn { + display: flex; + align-items: center; + justify-content: center; + transition: transform 0.15s ease, filter 0.15s ease; +} +.lobby-b-sq-btn:hover { + transform: scale(1.04); + filter: brightness(1.08); +} +.lobby-b-sq-btn:active { transform: scale(0.98); } +.room-lobby-br-fixed .lobby-b-sq-btn img, +.room-lobby-br-fixed .btn-voice-icon img { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + object-fit: contain; + object-position: center; + display: block; + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} +.room-lobby-br-fixed .btn-voice-icon { + display: flex; + align-items: center; + justify-content: center; + background: transparent; +} + +/* Desktop tuning: keep controls visibly large and readable */ +@media (min-width: 1024px) { + .room-lobby-chat-peers.chat-panel { + right: 0.9rem; + bottom: 11rem; + width: 454px; + height: 414px; + padding: 1.7rem 1.45rem 1.15rem; + border-radius: 0; + background: url(../img/chat-bg.png) center/100% 100% no-repeat; + border: none; + box-shadow: none; + backdrop-filter: none; + } + .room-lobby-chat-peers.chat-panel .chat-header-bar { + margin: 0; + padding: 0 0.15rem; + min-height: 58px; + height: 58px; + background: url(../img/chat-line.png) left bottom / 375px 4px no-repeat; + box-shadow: none; + } + .room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img img { + display: block; + width: 90px; + height: 77px; + object-fit: contain; + } + .room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img::before { + content: none; + display: none; + } + .room-lobby-chat-peers.chat-panel .chat-close-btn { + width: 58px; + height: 58px; + min-width: 58px; + min-height: 58px; + max-width: 58px; + max-height: 58px; + margin-left: auto; + } + .room-lobby-chat-peers.chat-panel .chat-close-btn img { + width: 58px; + height: 58px; + object-fit: contain; + } + .room-lobby-chat-peers.chat-panel #chat-messages { + width: calc(100% - 16px); + margin-right: 16px; + padding: 0.35rem 0.7rem 0.25rem 0.15rem; + font-size: 1rem; + line-height: 1.42; + gap: 0.42rem; + margin-top: 0.15rem; + margin-bottom: 0.2rem; + scrollbar-width: auto; + scrollbar-color: rgba(250, 253, 255, 0.98) rgba(12, 26, 47, 0.45); + box-sizing: border-box; + } + .room-lobby-chat-peers.chat-panel #chat-messages::-webkit-scrollbar { + width: 15px; + } + .room-lobby-chat-peers.chat-panel #chat-messages::-webkit-scrollbar-track { + border-radius: 999px; + background: rgba(20, 44, 72, 0.45); + border: 1px solid rgba(124, 221, 255, 0.3); + } + .room-lobby-chat-peers.chat-panel #chat-messages::-webkit-scrollbar-thumb { + border-radius: 999px; + background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(241, 249, 255, 0.98) 100%); + box-shadow: 0 0 8px rgba(182, 239, 255, 0.45); + } + .room-lobby-chat-peers.chat-panel .chat-msg { + max-width: 93%; + padding: 0.22rem 0.35rem; + font-size: 0.98rem; + border-radius: 10px; + background-image: none; + background-color: transparent; + box-shadow: none; + } + .room-lobby-chat-peers.chat-panel .chat-msg-other { + color: #d5bb63; + font-weight: 500; + } + .room-lobby-chat-peers.chat-panel .chat-msg-mine { + color: #cf74d1; + background-color: rgba(39, 67, 112, 0.82); + border: 1px solid rgba(116, 206, 255, 0.2); + align-self: flex-end; + text-align: left; + padding: 0.32rem 0.62rem; + } + .room-lobby-chat-peers.chat-panel .chat-form-bar { + padding: 0.24rem 0 0; + gap: 0; + align-items: center; + justify-content: space-between; + } + .room-lobby-chat-peers.chat-panel #chat-input { + margin-left: 17px; + width: 308px; + min-width: 308px; + max-width: 308px; + height: 61px; + min-height: 61px; + max-height: 61px; + padding: 0 0.95rem; + font-size: 0.95rem; + border-radius: 0; + border: none; + background: url(../img/chatbox.png) center/100% 100% no-repeat; + color: #e8f7ff; + } + .room-lobby-chat-peers.chat-panel #chat-input::placeholder { + color: rgba(195, 211, 236, 0.66); + } + .room-lobby-chat-peers.chat-panel .chat-send-btn { + width: 102px; + height: 98px; + min-width: 102px; + min-height: 98px; + max-width: 102px; + max-height: 98px; + margin-left: -26px; + margin-right: 2px; + } + .room-lobby-chat-peers.chat-panel .chat-send-btn img { + width: 102px; + height: 98px; + } + .room-lobby-top-left-cluster { + top: max(18px, env(safe-area-inset-top)); + left: max(0px, env(safe-area-inset-left)); + gap: 0; + } + .room-lobby-exit-fixed { + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + gap: 0.45rem; + margin-top: -1.4rem; + width: auto; + max-width: none; + } + .room-lobby-top-right-cluster { + top: max(16px, env(safe-area-inset-top)); + right: max(16px, env(safe-area-inset-right)); + } + .room-lobby-room-id-pill { + width: fit-content; + min-width: 0; + height: 180px; + min-height: 180px; + max-height: 180px; + max-width: none; + padding: 0 15px; + border-style: solid; + border-width: 0 60px; + border-radius: 0; + background: transparent; + border-image-source: url("../img/Room-id-BG.png"); + border-image-slice: 0 60 0 60 fill; + border-image-repeat: stretch; + box-shadow: none; + gap: 0.7rem; + align-items: center; + white-space: nowrap; + } + .room-lobby-room-id-label { + font-size: 2.05rem; + font-weight: 600; + line-height: 1; + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif; + text-transform: none; + color: #e8f7ff; + text-shadow: + 0 0 6px rgba(110, 226, 255, 0.8), + 0 0 14px rgba(44, 198, 255, 0.5); + } + #room-id-value { + font-size: 2.35rem; + line-height: 1; + font-family: 'NotoSansThai', 'Kanit', system-ui, sans-serif; + text-transform: none; + font-weight: 600; + color: #ecfbff; + text-shadow: + 0 0 7px rgba(118, 230, 255, 0.9), + 0 0 16px rgba(52, 203, 255, 0.55); + } + .room-lobby-room-id-lock { + width: 60px; + height: 65px; + min-width: 60px; + min-height: 65px; + max-width: 60px; + max-height: 65px; + aspect-ratio: 60 / 65; + font-size: 0; + color: transparent; + background: url("../img/Room-id-private.png") center / 100% 100% no-repeat; + filter: none; + } + .room-lobby-profile-frame { + width: 159px; + height: 157px; + min-width: 159px; + min-height: 157px; + max-width: 159px; + max-height: 157px; + aspect-ratio: 159 / 157; + } + .room-lobby-exit-fixed .btn-exit-icon { + width: 121px; + height: 119px; + min-width: 121px; + min-height: 119px; + max-width: 121px; + max-height: 119px; + aspect-ratio: 121 / 119; + margin-left: 13px; + margin-top: -15px; + margin-bottom: -15px; + } + body.room-lobby-page #room-players-hud { + min-width: 0; + font-size: clamp(1.35rem, 1.95vw, 1.9rem); + padding: 0.1rem 0.4rem; + } + .room-lobby-ready-fixed .ready-label-img { + width: 320px; + height: 126px; + min-width: 320px; + min-height: 126px; + max-width: 320px; + max-height: 126px; + aspect-ratio: 320 / 126; + } + .room-lobby-br-fixed { + --lobby-br-btn: 137px; + bottom: max(0.65rem, env(safe-area-inset-bottom)); + right: max(0.85rem, env(safe-area-inset-right)); + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-end; + gap: 0.75rem; + } + /* แถวเดียว: หลักฐาน | อันดับ | ไมค์ (ตรง production) */ + .room-lobby-br-fixed .lobby-b-extra-row:not(.is-hidden) { + display: contents; + } + .room-lobby-br-fixed .lobby-b-extra-row { + position: static !important; + margin: 0 !important; + transform: none !important; + z-index: auto; + } + .room-lobby-br-fixed .btn-voice-icon { + position: static !important; + margin: 0 !important; + transform: none !important; + } + .room-lobby-br-fixed .lobby-b-sq-btn, + .room-lobby-br-fixed .btn-voice-icon { + width: var(--lobby-br-btn); + height: var(--lobby-br-btn); + min-width: var(--lobby-br-btn); + min-height: var(--lobby-br-btn); + max-width: var(--lobby-br-btn); + max-height: var(--lobby-br-btn); + } + .room-lobby-chat-peers.chat-panel-collapsed.chat-panel { + width: 122px; + height: 120px; + bottom: 12rem; + right: max(0.85rem, env(safe-area-inset-right)); + } + .room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn { + width: 122px; + height: 120px; + min-width: 122px; + min-height: 120px; + max-width: 122px; + max-height: 120px; + aspect-ratio: 122 / 120; + margin-right: -20px; + } + .room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn img { + width: 122px; + height: 120px; + aspect-ratio: 122 / 120; + } +} + +/* แฟ้มหลักฐาน LobbyB — ดู css/evidence-view-overlay.css (layout ev-*) */ + +/* กระดานอันดับ LobbyB — ดู css/leaderboard-popup.css */ + +.version-tag { + position: fixed; + right: 8px; + bottom: 4px; + left: auto; + font-size: 10px; + color: #a9b1d6; + opacity: 0.7; + pointer-events: none; +} + +/* Editor — เกมตอบคำถาม */ +.quiz-editor-wrap { + margin: 1rem 0; + padding: 1rem; + background: #24283b; + border-radius: 8px; + border: 1px solid #414868; +} +.quiz-editor-wrap h3 { + margin: 0 0 0.5rem; + font-size: 1rem; + color: #7aa2f7; +} +.quiz-questions-list { + display: flex; + flex-direction: column; + gap: 0.6rem; + margin: 0.75rem 0; +} +.quiz-q-row { + display: grid; + grid-template-columns: 1fr auto auto; + gap: 0.5rem; + align-items: center; +} +@media (max-width: 600px) { + .quiz-q-row { + grid-template-columns: 1fr; + } +} +.quiz-q-row input[type="text"] { + min-width: 0; + padding: 0.4rem 0.5rem; + border-radius: 6px; + border: 1px solid #565f89; + background: #1a1b26; + color: #c0caf5; +} +.quiz-q-row select { + padding: 0.35rem; + border-radius: 6px; + border: 1px solid #565f89; + background: #1a1b26; + color: #c0caf5; +} +.btn-quiz-add, +.quiz-q-remove { + padding: 0.35rem 0.65rem; + border-radius: 6px; + cursor: pointer; + border: 1px solid #565f89; + background: #414868; + color: #c0caf5; + font: inherit; +} +.quiz-q-remove { + font-size: 0.8rem; +} + +/* design 2026-05: แสดงปุ่มตั้งค่าโฮสต์ + ปรับแต่ง มุมขวาบน (ตาม TryChangeCSS/CSS ใหม่ — ไม่ใช้ JS เก่า) */ +body.room-lobby-page .room-lobby-top-right-actions { + display: none !important; +} + +/* ---- Player Pick Vote overlay (Card Ban / Silence) — โหวตเลือกผู้เล่น ---- + สร้างด้วย JS ใน room-lobby.js (#pick-vote-overlay) แต่เดิมไม่มี CSS เลย → div จมหลัง UI lobby มองไม่เห็น */ +#pick-vote-overlay { + position: fixed; + inset: 0; + z-index: 12000; + display: flex; + align-items: center; + justify-content: center; + padding: 4vh 4vw; + background: rgba(4, 8, 16, 0.74); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity 0.22s ease, visibility 0.22s ease; + font-family: 'Kanit', sans-serif; +} +#pick-vote-overlay.is-open { + opacity: 1; + visibility: visible; + pointer-events: auto; +} +#pick-vote-overlay .pv-shell { + width: min(460px, 92vw); + max-height: 88vh; + overflow-y: auto; + box-sizing: border-box; + padding: 1.4rem 1.5rem 1.6rem; + border-radius: 18px; + text-align: center; + color: #e8f6ff; + background: linear-gradient(165deg, rgba(16, 30, 50, 0.97), rgba(8, 16, 30, 0.97)); + border: 1px solid rgba(83, 224, 255, 0.55); + box-shadow: 0 0 28px rgba(83, 224, 255, 0.35), inset 0 0 24px rgba(80, 180, 240, 0.14); + transform: translateY(12px) scale(0.97); + transition: transform 0.26s cubic-bezier(0.2, 0.9, 0.3, 1.2); +} +#pick-vote-overlay.is-open .pv-shell { + transform: translateY(0) scale(1); +} +#pick-vote-overlay .pv-badge { + display: inline-block; + padding: 0.2rem 0.85rem; + border-radius: 999px; + font-size: 0.74rem; + font-weight: 700; + letter-spacing: 0.08em; + color: #04121e; + background: linear-gradient(90deg, #53e0ff, #8ad8ff); + box-shadow: 0 0 14px rgba(83, 224, 255, 0.55); +} +#pick-vote-overlay .pv-title { + margin: 0.7rem 0 0.3rem; + font-size: 1.32rem; + font-weight: 700; + text-shadow: 0 0 12px rgba(83, 224, 255, 0.45); +} +#pick-vote-overlay .pv-sub { + margin: 0 0 0.7rem; + font-size: 0.86rem; + line-height: 1.35; + color: #a9c7da; +} +#pick-vote-overlay .pv-timer { + font-size: 1.5rem; + font-weight: 700; + color: #53e0ff; + margin-bottom: 0.6rem; + min-height: 1.4em; +} +#pick-vote-overlay .pv-timer.low { + color: #ff7a7a; + animation: pvPulse 0.7s ease-in-out infinite; +} +@keyframes pvPulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.12); } +} +#pick-vote-overlay .pv-list { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-bottom: 0.6rem; +} +#pick-vote-overlay .pv-cand { + position: relative; + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + width: 100%; + padding: 0.7rem 1rem; + border-radius: 12px; + font: 600 1rem 'Kanit', sans-serif; + color: #e8f6ff; + cursor: pointer; + background: rgba(28, 48, 74, 0.85); + border: 1px solid rgba(83, 224, 255, 0.3); + transition: transform 0.12s ease, border-color 0.15s ease, background 0.15s ease; +} +#pick-vote-overlay .pv-cand:hover { + transform: translateY(-1px); + border-color: rgba(83, 224, 255, 0.7); + background: rgba(36, 62, 94, 0.95); +} +#pick-vote-overlay .pv-cand.is-picked { + border-color: #53e0ff; + background: linear-gradient(90deg, rgba(83, 224, 255, 0.28), rgba(83, 224, 255, 0.14)); + box-shadow: 0 0 14px rgba(83, 224, 255, 0.5); +} +#pick-vote-overlay .pv-me { + font-size: 0.78rem; + color: #8ad8ff; +} +#pick-vote-overlay .pv-bot { + font-size: 0.72rem; + color: #04121e; + background: #7fd4a8; + padding: 0.05rem 0.45rem; + border-radius: 999px; +} +#pick-vote-overlay .pv-count { + position: absolute; + right: 0.7rem; + min-width: 1.5em; + height: 1.5em; + line-height: 1.5em; + border-radius: 999px; + font-size: 0.82rem; + font-weight: 700; + color: #04121e; + background: #53e0ff; + opacity: 0; + transform: scale(0.6); + transition: opacity 0.15s ease, transform 0.15s ease; +} +#pick-vote-overlay .pv-count.show { + opacity: 1; + transform: scale(1); +} +#pick-vote-overlay .pv-result { + margin: 0.4rem 0; + padding: 0.7rem; + border-radius: 12px; + font-size: 1.05rem; + font-weight: 700; + color: #fff; + background: rgba(83, 224, 255, 0.16); + border: 1px solid rgba(83, 224, 255, 0.5); +} +#pick-vote-overlay .pv-foot { + font-size: 0.82rem; + color: #a9c7da; + min-height: 1.2em; +} + +/* ===== มือถือ: ย่อปุ่ม AI chat ที่ใหญ่เกิน (213x201) + ปุ่ม interact (F) ให้พอดีจอ ===== */ +@media (max-width: 600px) { + .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn, + .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { + width: 92px !important; + height: 87px !important; + min-width: 92px !important; + min-height: 87px !important; + max-width: 92px !important; + max-height: 87px !important; + } + .room-lobby-chat-ai.chat-panel .chat-close-btn, + .room-lobby-chat-ai.chat-panel .chat-close-btn img { + width: 42px !important; + height: 42px !important; + } +} + +/* ===== มือถือแนวนอน (จอเตี้ย) — ย่อ/จัด UI ห้องเกม (LobbyA) ให้พอดีไม่ล้น · อิงแนวทาง Main-Lobby · ไม่แตะ PC ===== */ +@media (orientation: landscape) and (max-height: 540px) { + /* ปุ่มมุมขวาล่าง (ไมค์ + แว่น/ถ้วย) — ย่อตามความสูงจอ */ + .room-lobby-br-fixed { --lobby-br-btn: clamp(46px, 11vh, 64px); gap: 7px; } + /* แผงแชท — เดิม 576x525 ล้นจอแนวนอน → ย่อให้พอดีความสูงจอ */ + .room-lobby-chat-peers.chat-panel { + width: min(360px, 52vw); + height: min(248px, calc(100dvh - 80px)); + bottom: max(0.5rem, env(safe-area-inset-bottom)); + padding: 0.9rem 1rem; + } + /* ปุ่มแชท AI (collapsed) — ย่อลงอีกบนแนวนอน */ + .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn, + .room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { + width: 62px !important; height: 58px !important; + min-width: 62px !important; min-height: 58px !important; + max-width: 62px !important; max-height: 58px !important; + } + /* ปุ่ม ready — เตี้ยลงเล็กน้อย ไม่ชนปุ่มอื่น */ + .room-lobby-ready-fixed .ready-label-img { height: clamp(38px, 9.5vh, 58px); } + /* ปุ่ม exit/howto มุมซ้ายบน — อิงความสูงจอ */ + .room-lobby-exit-fixed .btn-exit-icon { + width: clamp(46px, 10vh, 62px); + height: clamp(46px, 10vh, 62px); + min-width: clamp(46px, 10vh, 62px); + } +} diff --git a/www/html/Game/public/css/style.css b/www/html/Game/public/css/style.css index f9e04a3..acec7b3 100644 --- a/www/html/Game/public/css/style.css +++ b/www/html/Game/public/css/style.css @@ -1,1988 +1,1999 @@ -* { box-sizing: border-box; } -body { font-family: sans-serif; margin: 0; background: #1a1b26; color: #c0caf5; } -.container { max-width: 720px; margin: 1rem auto; padding: 1rem; } - -/* โครง Editor — แยกแถบเครื่องมือ / พื้นที่วาด */ -.editor-page { - display: block; -} - -/* Editor ฝังใน Admin (?embed=1) — เต็มความสูง iframe, พื้นที่แคนวาสใหญ่ + เลื่อนแยก */ -html.editor-embed-admin { - height: 100%; -} -html.editor-embed-admin body { - height: 100%; - margin: 0; - overflow: hidden; -} -body.editor-embed-admin .version-tag { - display: none !important; -} -body.editor-embed-admin .container.editor-page { - max-width: none !important; - width: 100%; - height: 100%; - margin: 0 !important; - padding: 0.35rem 0.5rem 0.45rem; - display: flex; - flex-direction: column; - min-height: 0; - box-sizing: border-box; -} -body.editor-embed-admin .container.editor-page > h1 { - display: none; -} -body.editor-embed-admin .editor-toolbar-wrap { - /* อย่าให้แถบเครื่องมือถูก flex บีบแล้วล้นไปทับแคนวาส (body overflow:hidden) */ - flex: 0 0 auto; - min-height: 0; - max-height: min(56vh, 520px); - overflow-x: hidden; - overflow-y: auto; - overscroll-behavior: contain; - -webkit-overflow-scrolling: touch; - padding: 0.15rem 0.35rem 0.5rem 0; - margin: 0 0 0.35rem; - border-bottom: 1px solid rgba(65, 72, 104, 0.9); - position: relative; - z-index: 1; - background: linear-gradient(180deg, #1a1b26 0%, #16171f 100%); -} -body.editor-embed-admin .editor-workspace { - flex: 1 1 auto; - min-height: 0; - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; - z-index: 0; -} -body.editor-embed-admin .canvas-wrap { - flex: 1 1 auto; - min-height: 140px; - overflow: auto; - margin: 0 !important; - border-radius: 10px; - border: 1px solid #414868; - background: #0f1018; - -webkit-overflow-scrolling: touch; - touch-action: pan-x pan-y; -} -body.editor-embed-admin #editor-status { - flex: 0 0 auto; - margin: 0.3rem 0 0; - font-size: 0.8rem; - line-height: 1.35; -} -body.editor-embed-admin .editor-legend-short { - margin: 0; - font-size: 0.76rem; - line-height: 1.45; - color: #a8b0d0; -} -body.editor-embed-admin .editor-toolbar-grid { - gap: 0.45rem; -} -/* การ์ด «ประเภทเกม» ข้อความยาว — ให้กว้างเต็มแถวบนจอแคบ ลดการอัดคอลัมน์ */ -@media (max-width: 720px) { - body.editor-embed-admin .editor-toolbar-grid .editor-card:first-child { - grid-column: 1 / -1; - } -} -body.editor-embed-admin .editor-card { - padding: 0.45rem 0.55rem; - margin-bottom: 0; -} -body.editor-embed-admin .editor-card__title { - font-size: 0.68rem; - margin-bottom: 0.3rem; -} -body.editor-embed-admin .editor-card__hint { - font-size: 0.72rem; - margin-top: 0.3rem; - overflow-wrap: break-word; - word-break: break-word; -} -body.editor-embed-admin .game-type-hint .editor-hint-lead { - font-size: 0.78rem; - margin-bottom: 0.35rem; -} -body.editor-embed-admin .game-type-hint .editor-hint-bullets { - padding-left: 1.05rem; -} -body.editor-embed-admin .game-type-hint .editor-hint-bullets li { - margin: 0.26rem 0; - font-size: 0.72rem; - line-height: 1.45; -} -body.editor-embed-admin .frogger-lanes { - margin: 0.35rem 0; - position: relative; - z-index: auto; -} -body.editor-embed-admin .editor-card--bg { - margin-top: 0.25rem; -} -body.editor-embed-admin .editor-card--help { - margin-top: 0.2rem; -} -h1 { color: #7aa2f7; } -a { color: #9ece6a; } -label { display: inline-block; margin: 0.25rem 0.5rem 0.25rem 0; } -input, button { padding: 0.4rem 0.6rem; margin: 0 0.25rem 0 0; border-radius: 6px; border: 1px solid #414868; } -input { background: #24283b; color: #c0caf5; } -button { background: #7aa2f7; color: #1a1b26; cursor: pointer; border: none; } -.legend { font-size: 0.9rem; color: #a9b1d6; margin: 0.5rem 0; } -.frogger-lanes { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; position: relative; z-index: 2; min-height: 80px; } -.frogger-lanes h3 { margin: 0 0 0.5rem 0; color: #7aa2f7; font-size: 1rem; } -.frogger-lanes table { width: 100%; border-collapse: collapse; font-size: 0.85rem; } -.frogger-lanes th, .frogger-lanes td { padding: 0.25rem 0.5rem; text-align: left; border: 1px solid #414868; } -.frogger-lanes select, .frogger-lanes input[type="number"] { padding: 0.35rem 0.5rem; min-width: 4rem; background: #1a1b26; color: #c0caf5; border: 1px solid #414868; border-radius: 4px; cursor: pointer; font-size: 0.9rem; } -.frogger-lanes select { min-width: 6rem; } -.frogger-lanes .lane-speed { width: 4rem; } -.frogger-lanes .lane-spacing { width: 4rem; } -.frogger-lanes td { vertical-align: middle; } -.frogger-lanes select:disabled, .frogger-lanes input:disabled { opacity: 0.6; cursor: not-allowed; } -.game-type-hint { - font-size: 0.85rem; - color: #a9b1d6; - margin: 0; - line-height: 1.5; - display: block; -} -.game-type-hint .editor-hint-lead { - margin: 0 0 0.45rem; - font-size: 0.9rem; - font-weight: 500; - color: #c0caf5; - line-height: 1.4; -} -.game-type-hint .editor-hint-lead:last-child { - margin-bottom: 0; -} -.editor-hint-bullets { - margin: 0; - padding-left: 1.2rem; - list-style: disc; -} -.editor-hint-bullets li { - margin: 0.35rem 0; -} -.editor-hint-bullets li:first-child { - margin-top: 0; -} -.editor-hint-bullets li:last-child { - margin-bottom: 0; -} -.game-type-hint .editor-hint-bullets code { - font-size: 0.88em; -} -.game-type-hint kbd { - display: inline-block; - font-size: 0.82em; - padding: 0.1em 0.38em; - margin: 0 0.06em; - border-radius: 4px; - background: #1a1b26; - border: 1px solid #414868; - font-family: ui-monospace, monospace; - color: #c0caf5; -} - -/* Editor — การ์ดจัดกลุ่มเครื่องมือ (อ่านง่าย ไม่บีบเป็นแถบเดียวยาว) */ -.editor-toolbar-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); - gap: 0.65rem; - margin: 0.75rem 0 0.5rem; - align-items: start; -} -.editor-card { - margin: 0; - padding: 0.65rem 0.75rem; - background: #24283b; - border: 1px solid rgba(65, 72, 104, 0.95); - border-radius: 10px; -} -.editor-card--wide { - grid-column: 1 / -1; -} -.editor-card__title { - margin: 0 0 0.45rem 0; - padding: 0; - font-size: 0.72rem; - font-weight: 700; - letter-spacing: 0.04em; - text-transform: uppercase; - color: #7aa2f7; -} -.editor-card__row { - display: flex; - flex-wrap: wrap; - align-items: flex-end; - gap: 0.45rem 0.75rem; -} -.editor-card__row--wrap { - align-items: center; -} -.editor-card__row--actions { - margin-top: 0.55rem; - padding-top: 0.5rem; - border-top: 1px solid rgba(65, 72, 104, 0.75); - gap: 0.5rem; -} -.editor-card__hint { - margin: 0.4rem 0 0; - padding: 0.45rem 0.55rem; - background: rgba(15, 16, 24, 0.55); - border-radius: 6px; - border-left: 3px solid #7aa2f7; -} -.editor-card label { margin: 0; } -/* กลุ่มกล่องตรวจ: ชนกำแพง vs โซนห้ามซ้อน — แยกมองชัดจากแถว label เปล่า ๆ */ -.editor-footprint-row { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 0.45rem 0.85rem; - width: 100%; - padding: 0.42rem 0.55rem 0.48rem; - border-radius: 8px; - border: 1px solid rgba(122, 162, 247, 0.38); - background: rgba(20, 22, 34, 0.72); - box-sizing: border-box; -} -.editor-footprint-row--wall { - border-color: rgba(122, 162, 247, 0.45); - background: rgba(26, 32, 52, 0.65); -} -.editor-footprint-row--no-overlap { - border-color: rgba(158, 206, 106, 0.5); - background: rgba(22, 34, 26, 0.55); -} -.editor-footprint-row__head { - flex: 0 0 100%; - margin: 0 0 0.08rem 0; - padding: 0; - font-size: 0.68rem; - font-weight: 700; - letter-spacing: 0.06em; - text-transform: uppercase; - color: #7aa2f7; -} -.editor-footprint-row--no-overlap .editor-footprint-row__head { - color: #9ece6a; -} -.editor-footprint-row .editor-footprint-row__field input[type="number"] { - width: 3.1rem; - margin-left: 0.2rem; -} -.editor-field-grow { - flex: 1 1 180px; - min-width: min(100%, 200px); -} -.editor-field-grow select, -.editor-field-grow input[type="text"] { - width: 100%; - max-width: 100%; - min-width: 0; -} -.editor-field-drawmode { - flex: 1 1 280px; - min-width: min(100%, 240px); -} -.editor-field-drawmode select { - width: 100%; - max-width: 100%; - min-width: 0; -} -.editor-cell-color { - display: inline-flex; - flex-wrap: wrap; - align-items: center; - gap: 0.35rem 0.75rem; -} -.editor-grid-image-tools { - display: none; - flex-direction: column; - align-items: stretch; - gap: 0.5rem; - max-width: 100%; - width: min(100%, 520px); -} -.editor-grid-image-size-row { - display: flex; - flex-wrap: wrap; - gap: 0.5rem 1rem; - align-items: center; -} -.editor-grid-image-size-row input[type="number"] { - width: 3.2rem; - margin-left: 0.25rem; -} -.editor-grid-image-carry-bind-row { - display: flex; - flex-wrap: wrap; - gap: 0.35rem 0.75rem; - align-items: center; - font-size: 0.72rem; - color: #a9b1d6; -} -.editor-grid-image-carry-bind-row select { - margin-left: 0.35rem; - max-width: 12rem; -} -.editor-hint-inline { - font-size: 0.68rem; - color: #787c99; - line-height: 1.35; - flex: 1 1 140px; -} -.editor-grid-image-gallery-wrap { - display: flex; - flex-direction: column; - gap: 0.25rem; -} -.editor-grid-image-gallery-label { - font-size: 0.72rem; - color: #a9b1d6; - font-weight: 600; -} -.editor-grid-image-gallery-note { - margin: 0.1rem 0 0.35rem; - font-size: 0.65rem; - line-height: 1.35; - color: #787c99; - max-width: 36rem; -} -.grid-cell-image-gallery { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(68px, 1fr)); - gap: 0.4rem; - max-height: 200px; - overflow-y: auto; - padding: 0.35rem; - border-radius: 8px; - border: 1px solid rgba(65, 72, 104, 0.85); - background: rgba(15, 16, 24, 0.6); -} -.grid-cell-image-gallery-empty { - font-size: 0.72rem; - color: #787c99; - padding: 0.35rem; -} -.grid-cell-image-gallery-item { - position: relative; - padding: 0; - margin: 0; - border: 2px solid transparent; - border-radius: 8px; - overflow: hidden; - cursor: pointer; - background: #24283b; - line-height: 0; -} -.grid-cell-image-gallery-item.is-selected { - border-color: #9ece6a; - box-shadow: 0 0 0 1px rgba(158, 206, 106, 0.35); -} -.grid-cell-image-gallery-item img { - display: block; - width: 100%; - height: 56px; - object-fit: cover; -} -.grid-cell-image-gallery-row { - display: flex; - flex-direction: column; - gap: 0.35rem; - align-items: stretch; -} -.grid-cell-image-gallery-same-hint { - font-size: 0.62rem; - line-height: 1.35; - color: #f7768e; - padding: 0.2rem 0.35rem; - border-radius: 4px; - background: rgba(247, 118, 142, 0.12); - border: 1px solid rgba(247, 118, 142, 0.35); -} -.grid-cell-image-gallery-held-side { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.2rem; - padding: 0.15rem 0.1rem 0.25rem; - border-radius: 6px; - background: rgba(0, 0, 0, 0.22); -} -.grid-cell-image-gallery-held-label { - font-size: 0.58rem; - font-weight: 700; - color: #7dcfff; - letter-spacing: 0.04em; -} -.grid-cell-image-gallery-held-thumb { - display: block; - width: 100%; - max-height: 44px; - object-fit: cover; - border-radius: 4px; - background: #1a1b26; -} -.grid-cell-image-gallery-held-btn { - font-size: 0.58rem; - padding: 0.15rem 0.35rem; - border-radius: 4px; - border: 1px solid rgba(125, 207, 255, 0.45); - background: rgba(26, 27, 38, 0.95); - color: #c0caf5; - cursor: pointer; -} -.grid-cell-image-gallery-held-btn:hover { - border-color: rgba(158, 206, 106, 0.65); - color: #9ece6a; -} -.grid-cell-image-gallery-clear-held { - font-size: 0.7rem; - line-height: 1; - padding: 0.05rem 0.25rem; - border: none; - border-radius: 4px; - background: rgba(247, 118, 142, 0.25); - color: #f7768e; - cursor: pointer; -} -.grid-cell-image-gallery-clear-held:hover { - background: rgba(247, 118, 142, 0.45); -} -.grid-cell-image-gallery-cap { - display: block; - font-size: 0.65rem; - text-align: center; - padding: 0.15rem 0; - color: #c0caf5; - background: rgba(0, 0, 0, 0.35); -} -.editor-grid-image-upload-row { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 0.5rem; -} -body.editor-embed-admin .grid-cell-image-gallery { - max-height: 160px; -} -body.editor-embed-admin .grid-cell-image-gallery-item img { - height: 48px; -} -.editor-btn-primary { - font-weight: 600; -} -.editor-card--bg { - margin: 0.5rem 0 0.35rem; -} -.editor-card--help { - margin: 0.35rem 0 0.15rem; -} -.editor-help-list { - margin: 0; - padding-left: 1.15rem; - list-style: disc; -} -.editor-help-list li { - margin-bottom: 0.28rem; -} -@media (min-width: 900px) { - .editor-help-list { - columns: 2; - column-gap: 1.5rem; - } - .editor-help-list li { - break-inside: avoid; - } -} -.canvas-wrap { margin: 1rem 0; } -.container { padding-left: 1rem; padding-right: 1rem; } -#editor-canvas { - background: #1a1b26; - display: block; - touch-action: none; - image-rendering: pixelated; - image-rendering: crisp-edges; -} -.editor-map-zoom-bar { - display: flex; - align-items: center; - gap: 5px; - padding: 6px 10px; - border-radius: 999px; - background: rgba(8, 12, 28, 0.88); - border: 1px solid #2a3357; - box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45); -} -.editor-map-zoom-btn { - border: 1px solid #2a3357; - background: #0d1430; - color: #eef2ff; - border-radius: 8px; - min-width: 34px; - height: 32px; - padding: 0 8px; - cursor: pointer; - font: inherit; - font-weight: 700; - line-height: 1; -} -.editor-map-zoom-btn:hover { filter: brightness(1.2); } -.editor-map-zoom-label { - min-width: 46px; - text-align: center; - font-size: 12px; - font-weight: 700; - color: #c7d2fe; - user-select: none; -} -.game-wrap { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 0; } -.game-header { flex-shrink: 0; background: #24283b; padding: 0.5rem 1rem; display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; } -.game-header span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.game-header button { flex-shrink: 0; } -#game-canvas { - flex: 1 1 auto; - display: block; - width: 100%; - min-height: 0; - min-width: 0; - touch-action: none; - image-rendering: pixelated; - image-rendering: crisp-edges; -} -.game-wrap .chat-panel { flex-shrink: 0; } -.chat-panel { height: 160px; border-top: 1px solid #414868; display: flex; flex-direction: column; } -#chat-messages { flex: 1; overflow-y: auto; padding: 0.5rem; font-size: 0.9rem; } -#chat-form { display: flex; padding: 0.5rem; gap: 0.5rem; } -#chat-input { flex: 1; } - -.lobby-section { margin: 1.25rem 0; padding: 1rem; background: #24283b; border-radius: 8px; } -.lobby-section h2 { margin: 0 0 0.75rem 0; font-size: 1rem; color: #7aa2f7; } -#room-list { list-style: none; margin: 0; padding: 0; } -#room-list .room-item { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid #414868; } -#room-list .room-item:last-child { border-bottom: none; } -#room-list .room-name { font-weight: 600; color: #c0caf5; min-width: 0; } -#room-list .room-meta { font-size: 0.85rem; color: #a9b1d6; } -#room-list .room-meta-inline { font-size: 0.8rem; color: #565f89; font-weight: normal; } -#room-list-status { margin: 0; color: #a9b1d6; font-size: 0.9rem; } - -.room-lobby-peers { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; } -.room-lobby-peer { padding: 0.35rem 0; color: #c0caf5; } -.room-lobby-peer:not(:last-child) { border-bottom: 1px solid #414868; } -#lobby-map-wrap { position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; min-width: 100vw; min-height: 100vh; z-index: 0; } -#lobby-map-canvas { - display: block; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - width: 100%; - height: 100%; - min-width: 100%; - min-height: 100%; - margin: 0; - padding: 0; - background: #303770; - box-sizing: border-box; -} -#lobby-map-canvas:focus { - outline: none; -} -#lobby-map-canvas:focus-visible { - outline: 2px solid rgba(122, 162, 247, 0.45); - outline-offset: -2px; -} -/* LobbyB (mn8nx46h) — ไม่แสดงปุ่มพร้อม */ -body.room-lobby--lobby-b .room-lobby-ready-fixed { - display: none !important; -} -.lobby-interact-hint { - position: absolute; - bottom: max(10px, env(safe-area-inset-bottom)); - left: 50%; - transform: translateX(-50%); - z-index: 2; - margin: 0; - padding: 0.2rem 0.55rem; - font-size: clamp(0.72rem, 1.8vw, 0.85rem); - color: rgba(203, 213, 245, 0.9); - text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55); - pointer-events: none; - font-family: system-ui, 'Kanit', sans-serif; - white-space: nowrap; -} -.lobby-interact-hint kbd { - display: inline-block; - padding: 0.06em 0.32em; - border-radius: 4px; - background: rgba(26, 27, 38, 0.88); - border: 1px solid rgba(122, 162, 247, 0.45); - font-size: 0.88em; - font-family: inherit; -} -.lobby-zoom-pct { - position: absolute; - top: 12px; - left: 50%; - transform: translateX(-50%); - z-index: 2; - padding: 6px 12px; - border-radius: 8px; - background: rgba(26, 27, 38, 0.85); - color: #c0caf5; - font-size: 1rem; - font-weight: 600; - pointer-events: none; - opacity: 0; - transition: opacity 0.2s ease; -} -.lobby-zoom-pct.lobby-zoom-pct-visible { opacity: 1; } -/* ซ่อนแผง overlay รายชื่อ / host / แชท — โถงโฟกัสแผนที่ + ปุ่ม READY/ไมค์ ด้านนอก */ -.room-lobby-overlay { display: none !important; } -.room-lobby-top-left-cluster { - position: fixed; - top: max(12px, env(safe-area-inset-top)); - left: max(12px, env(safe-area-inset-left)); - z-index: 55; - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 0.65rem; - pointer-events: none; -} -.room-lobby-top-left-cluster .room-lobby-exit-fixed { - pointer-events: auto; -} - -/* มุมขวาบน — โปรไฟล์ตัวละคร */ -.room-lobby-top-right-cluster { - position: fixed; - top: max(12px, env(safe-area-inset-top)); - right: max(12px, env(safe-area-inset-right)); - z-index: 56; - display: flex; - flex-direction: row; - align-items: flex-start; - gap: 0.65rem; - pointer-events: none; -} -.room-lobby-top-right-cluster > * { - pointer-events: auto; -} -.room-lobby-profile-wrap { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.2rem; -} -.room-lobby-profile-frame { - width: clamp(56px, 12vw, 72px); - height: clamp(56px, 12vw, 72px); - border-radius: 14px; - border: 2px solid rgba(0, 212, 255, 0.65); - overflow: hidden; - background: rgba(18, 22, 42, 0.92); - box-shadow: - 0 0 0 1px rgba(34, 211, 238, 0.2), - 0 0 22px rgba(34, 211, 238, 0.28); -} -.room-lobby-profile-frame img { - display: block; - width: 100%; - height: 100%; - object-fit: cover; - object-position: center bottom; - image-rendering: pixelated; - image-rendering: crisp-edges; -} -.room-lobby-actions { margin-top: 1rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; } -.room-lobby-actions .room-lobby-btn-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; opacity: 0; pointer-events: none; } -.room-lobby-actions label { margin: 0; } -.room-lobby-actions #btn-start { background: #9ece6a; color: #1a1b26; } -#host-only { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; } -#host-only select { padding: 0.4rem 0.6rem; border-radius: 6px; border: 1px solid #414868; background: #24283b; color: #c0caf5; } -.host-start-area-hint { - flex-basis: 100%; - margin: 0; - font-size: 0.88rem; - color: #e0af68; - line-height: 1.35; - max-width: 100%; -} -#host-only #btn-start:disabled { - opacity: 0.5; - cursor: not-allowed; - filter: grayscale(0.25); -} -.room-lobby-chat { margin-top: 1rem; } -.room-lobby-chat.chat-panel { - border-radius: 12px; - overflow: hidden; - box-shadow: none; -} -.room-lobby-chat-peers.chat-panel { - position: fixed; - right: 1.25rem; - bottom: 5.5rem; - width: 576px; - height: 525px; - max-width: calc(100vw - 2.5rem); - z-index: 52; - margin-top: 0; - display: flex; - flex-flow: column; - padding: 2rem; - box-sizing: border-box; - border-top: 0px solid #414868; - background: url(/Game/img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; - background-color: transparent; -} -.room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img img { width: 90px; height: 77px; } -.room-lobby-chat-peers.chat-panel .chat-close-btn { width: 48px; height: 48px; } -.room-lobby-chat-peers.chat-panel .chat-close-btn img { width: 50px; height: 50px; } -.room-lobby-chat-peers.chat-panel #chat-messages { padding: 0.75rem; font-size: 1.05rem; gap: 0.5rem; } -.room-lobby-chat-peers.chat-panel .chat-form-bar { padding: 0.6rem 0; gap: 0.5rem; } -.room-lobby-chat-peers.chat-panel #chat-input { padding: 0.6rem 0.85rem; font-size: 1.05rem; } -.room-lobby-chat-peers.chat-panel .chat-send-btn { width: 52px; height: 52px; } -.room-lobby-chat-peers.chat-panel .chat-send-btn img { width: 58px; height: 58px; } -.room-lobby-chat-peers.chat-panel .chat-msg { padding: 0.6rem 1rem; font-size: 1.05rem; } -.room-lobby-chat-peers.chat-panel .chat-header-bar { - margin: 0 -2rem 0 -2rem; - padding-left: 2rem; - padding-right: 2rem; - justify-content: space-between; - align-items: center; - min-height: 72px; - height: 72px; -} -.room-lobby-chat-peers.chat-panel #chat-messages { - flex: 1; - min-height: 0; - height: auto; -} -.room-lobby-chat .chat-header-bar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0; - min-height: 48px; - height: 48px; - background: url(/Game/img/chat-line.png) bottom repeat-x; - background-size: 100% 4px; - background-color: transparent; -} -.room-lobby-chat-peers .chat-header-title.chat-header-title-img { - display: inline-flex; - align-items: center; - line-height: 0; -} -.room-lobby-chat-peers .chat-header-title.chat-header-title-img img { - width: 60px; - height: 51px; - object-fit: contain; - display: block; -} -.room-lobby-chat-ai .chat-header-title.chat-header-title-img { - display: flex; - align-items: flex-end; - gap: 0.5rem; - line-height: 0; -} -.room-lobby-chat-ai .chat-header-title.chat-header-title-img .ai-chat-title-label { - height: 52px; - width: auto; - object-fit: contain; - display: block; - flex-shrink: 0; - margin-bottom: -2px; -} -/* รูปหัวแชท AI — ยกขึ้นเหนือเส้น */ -.room-lobby-chat-ai .chat-header-title.chat-header-title-img img { - width: 86px; - height: 92px; - object-fit: cover; - display: block; - flex-shrink: 0; - margin-top: -27px; - margin-left: -6px; - position: relative; - z-index: 1; -} -.room-lobby-chat .chat-header-title { - font-size: 1rem; - font-weight: 600; - color: #a0aec0; -} -.room-lobby-chat .chat-close-btn { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - padding: 0; - border: none; - border-radius: 8px; - background: transparent; - cursor: pointer; - margin-left: auto; -} -.room-lobby-chat-peers .chat-header-bar .chat-close-btn { margin-left: 0; } -.room-lobby-chat .chat-close-btn img { width: 34px; height: 34px; object-fit: contain; } -.room-lobby-chat .chat-close-btn:hover { opacity: 0.9; } -.room-lobby-chat.chat-panel-collapsed #chat-messages, -.room-lobby-chat.chat-panel-collapsed .chat-form-bar { display: none !important; } -.room-lobby-chat-peers.chat-panel-collapsed .chat-header-title { display: none !important; } -.room-lobby-chat-peers.chat-panel-collapsed .chat-header-bar { - justify-content: center; - padding: 0; - background: none !important; - border: none; -} -.room-lobby-chat-peers.chat-panel-collapsed.chat-panel { - width: 80px; - height: 80px; - min-height: 0; - padding: 0; - right: 1.25rem; - bottom: 6.25rem; - display: flex; - align-items: center; - justify-content: center; - background: none !important; - background-color: transparent !important; - border: none; - box-shadow: none; -} -.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn { - width: 80px; - height: 80px; - overflow: visible; -} -.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn img { - width: 100%; - height: 100%; - object-fit: contain; - object-position: center; - display: block; -} -.room-lobby-chat #chat-messages, -.room-lobby-chat #ai-chat-messages { - height: 100px; - overflow-y: auto; - padding: 0.5rem; - font-size: 0.85rem; - border: none; - margin: 0; - display: flex; - flex-direction: column; - gap: 0.35rem; - background: none; - background-color: transparent; - box-shadow: none; -} -.room-lobby-chat .chat-messages-bg { border-radius: 0; } -.room-lobby-chat #chat-form.chat-form-bar, -.room-lobby-chat #ai-chat-form.chat-form-bar { - display: flex; - gap: 0.4rem; - align-items: center; - padding: 0.4rem 0; - background: none; - background-color: transparent; - border-top: none; - flex-shrink: 0; -} -.room-lobby-chat-peers .chat-form-bar { - padding-left: 0; - padding-right: 0; -} -.room-lobby-chat #chat-input, -.room-lobby-chat #ai-chat-input { - flex: 1; - min-width: 0; - padding: 0.45rem 0.6rem; - border-radius: 10px; - border: 1px solid rgba(0, 212, 255, 0.25); - background: rgba(30, 35, 50, 0.8); - color: #c0caf5; - font-size: 0.9rem; - box-sizing: border-box; - margin-left: 9px; -} -.room-lobby-chat .chat-send-btn { - display: flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - flex-shrink: 0; - padding: 0; - border: none; - border-radius: 10px; - background: transparent; - cursor: pointer; -} -.room-lobby-chat .chat-send-btn img { width: 45px; height: 45px; object-fit: contain; } -.room-lobby-chat .chat-send-btn:hover { opacity: 0.9; } -.room-lobby-chat .chat-msg { - padding: 0.4rem 0.75rem; - border-radius: 12px; - max-width: 85%; - background-size: 100% 100%; - background-repeat: no-repeat; - background-position: center; -} -.room-lobby-chat .chat-msg-mine { - align-self: flex-end; - text-align: right; - background-image: url(/Game/img/chat-bubble-me.png); - background-color: rgba(122, 162, 247, 0.9); - color: #1a1b26; -} -.room-lobby-chat .chat-msg-other { - align-self: flex-start; - text-align: left; - background-image: url(/Game/img/chat-bubble-friend.png); - background-color: rgba(65, 72, 104, 0.9); - color: #c0caf5; -} -.room-lobby-chat .chat-msg-ai { - align-self: flex-start; - text-align: left; - background-image: url(/Game/img/chat-bubble-friend.png); - background-color: rgba(158, 206, 106, 0.9); - color: #1a1b26; -} -.room-lobby-chat .chat-msg-system { - align-self: center; - text-align: center; - max-width: 95%; - background-image: none; - background-color: rgba(26, 27, 38, 0.72); - color: #9aa5ce; - font-size: 0.88rem; - font-style: italic; - padding: 0.35rem 0.6rem; -} - -/* AI chat — loading แบบ Messenger (จุดกระโดด 3 จุด), อยู่ติดข้อความล่าสุดในลิสต์ */ -.room-lobby-chat .ai-chat-typing { - display: flex; - align-items: center; - gap: 4px; - padding: 12px 14px; - min-height: 24px; - flex-shrink: 0; - background-image: url(/Game/img/chat-bubble-friend.png); - background-color: rgba(158, 206, 106, 0.9); - background-size: 100% 100%; - background-repeat: no-repeat; - background-position: center; -} -.room-lobby-chat .ai-typing-dot { - width: 6px; - height: 6px; - border-radius: 50%; - background: #1a1b26; - animation: ai-typing-bounce 1.4s ease-in-out infinite both; -} -.room-lobby-chat .ai-typing-dot:nth-child(1) { animation-delay: 0s; } -.room-lobby-chat .ai-typing-dot:nth-child(2) { animation-delay: 0.2s; } -.room-lobby-chat .ai-typing-dot:nth-child(3) { animation-delay: 0.4s; } -@keyframes ai-typing-bounce { - 0%, 60%, 100% { transform: translateY(0); } - 30% { transform: translateY(-6px); } -} - -/* AI chat panel — ขนาดและตำแหน่งตาม reference (วงซ้าย) */ -.room-lobby-chat-ai.chat-panel { - position: fixed; - left: 20px; - right: auto; - bottom: 5.5rem; - width: 576px; - height: 525px; - max-width: calc(100vw - 2.5rem); - z-index: 51; - margin-top: 0; - display: flex; - flex-flow: column; - padding: 2rem; - box-sizing: border-box; - border-top: 0; - background: url(/Game/img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; - background-color: transparent; -} -.room-lobby-chat-ai.chat-panel .chat-header-bar { - margin: 0 -2rem 0 -2rem; - padding-left: 2rem; - padding-right: 2rem; - justify-content: space-between; - align-items: center; - min-height: 80px; - height: 80px; - overflow: visible; -} -.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img img { width: 130px; height: 138px; margin-top: -38px; margin-left: -8px; } -.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img .ai-chat-title-label { height: 78px; } -.room-lobby-chat-ai.chat-panel .chat-close-btn { width: 48px; height: 48px; } -.room-lobby-chat-ai.chat-panel .chat-close-btn img { width: 50px; height: 50px; } -.room-lobby-chat-ai.chat-panel #ai-chat-messages { padding: 0.75rem; font-size: 1.05rem; gap: 0.5rem; } -.room-lobby-chat-ai.chat-panel .chat-form-bar { padding: 0.6rem 0; gap: 0.5rem; } -.room-lobby-chat-ai.chat-panel #ai-chat-input { padding: 0.6rem 0.85rem; font-size: 1.05rem; } -.room-lobby-chat-ai.chat-panel .chat-send-btn { width: 52px; height: 52px; } -.room-lobby-chat-ai.chat-panel .chat-send-btn img { width: 58px; height: 58px; } -.room-lobby-chat-ai.chat-panel .chat-msg { padding: 0.6rem 1rem; font-size: 1.05rem; } -.room-lobby-chat-ai.chat-panel .ai-chat-typing { padding: 14px 18px; min-height: 28px; } -.room-lobby-chat-ai.chat-panel .ai-typing-dot { width: 8px; height: 8px; } -.room-lobby-chat-ai.chat-panel { - overflow: visible; -} -.room-lobby-chat-ai.chat-panel #ai-chat-messages { - flex: 1; - min-height: 0; - height: auto; -} -.room-lobby-chat-ai .chat-form-bar { - padding-left: 0; - padding-right: 0; -} -.room-lobby-chat-ai .ai-chat-admin-link { - margin: 0.35rem 0 0 0; - font-size: 0.75rem; - flex-shrink: 0; -} -/* AI chat collapsed */ -.room-lobby-chat-ai.chat-panel-collapsed #ai-chat-messages, -.room-lobby-chat-ai.chat-panel-collapsed .chat-form-bar, -.room-lobby-chat-ai.chat-panel-collapsed .ai-chat-admin-link { display: none !important; } -.room-lobby-chat-ai.chat-panel-collapsed .chat-header-title { display: none !important; } -.room-lobby-chat-ai.chat-panel-collapsed .chat-header-bar { - justify-content: center; - padding: 0; - background: none !important; - border: none; -} -.room-lobby-chat-ai.chat-panel-collapsed.chat-panel { - width: 80px; - height: 80px; - min-height: 0; - padding: 0; - left: 20px; - bottom: 1.25rem; - display: flex; - align-items: center; - justify-content: center; - background: none !important; - background-color: transparent !important; - border: none; - box-shadow: none; -} -.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn { - width: 80px; - height: 80px; - overflow: visible; -} -.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { - width: 100%; - height: 100%; - object-fit: contain; - object-position: center; - display: block; -} - -.room-lobby-exit-fixed { - position: static; - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-items: center; - justify-content: flex-start; - gap: 10px; - width: max-content; - max-width: calc(100vw - 24px); - box-sizing: border-box; -} -.room-lobby-exit-fixed .btn-exit-icon { - display: flex; - align-items: center; - justify-content: center; - flex: 0 0 auto; - width: 80px; - height: 80px; - min-width: 80px; - padding: 0; - border: none; - border-radius: 12px; - background: transparent; - cursor: pointer; -} -.room-lobby-exit-fixed .btn-exit-icon:hover { - opacity: 0.9; -} -.room-lobby-exit-fixed .btn-exit-icon img { - width: 100%; - height: auto; - object-fit: contain; - display: block; -} - -.room-lobby-ready-fixed { - position: fixed; - bottom: 1.25rem; - left: 50%; - transform: translateX(-50%); - z-index: 120; - pointer-events: none; -} -.room-lobby-ready-fixed .ready-label, -.room-lobby-ready-fixed .ready-check-input { - pointer-events: auto; -} -.room-lobby-ready-fixed .ready-label { - position: relative; - display: inline-block; - padding: 0; - margin: 0; - border: none; - border-radius: 0; - background: transparent; - box-shadow: none; - cursor: pointer; - transition: transform 0.15s ease, filter 0.15s ease; - line-height: 0; -} -.room-lobby-ready-fixed .ready-label:hover { - transform: scale(1.04); - filter: brightness(1.08); -} -.room-lobby-ready-fixed .ready-label:active { - transform: scale(0.98); -} -.room-lobby-ready-fixed .ready-check-input { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - margin: 0; - opacity: 0; - cursor: pointer; - z-index: 2; -} -.room-lobby-ready-fixed .ready-label-img { - display: block; - height: clamp(44px, 8vh, 72px); - width: auto; - max-width: min(240px, 78vw); - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} -.room-lobby-ready-fixed .ready-label--active .ready-label-img { - filter: drop-shadow(0 0 10px rgba(158, 206, 106, 0.45)); -} - -/* มุมขวาล่าง — ไมค์ทุกห้อง + ปุ่ม LobbyB (แว่น/ถ้วย) */ -.room-lobby-br-fixed { - --lobby-br-btn: 80px; - position: fixed; - bottom: 1.25rem; - right: max(1.25rem, env(safe-area-inset-right)); - z-index: 400; - display: flex; - flex-direction: row; - align-items: flex-end; - gap: 10px; - pointer-events: none; -} -.room-lobby-br-fixed .lobby-b-extra-row, -.room-lobby-br-fixed .btn-voice-icon { - pointer-events: auto; -} -.lobby-b-extra-row { - display: flex; - flex-direction: row; - align-items: flex-end; - gap: 10px; -} -.lobby-b-extra-row.is-hidden { - display: none !important; -} -/* โหมดเกม (ควิซ) ใน room-lobby — ไม่โชว์แว่น/ถ้วย LobbyB */ -body.room-lobby--quiz-active .lobby-b-extra-row { - display: none !important; - visibility: hidden !important; - pointer-events: none !important; -} -/* ปุ่มมุมขวาล่าง — ขนาดเดียวกัน (กัน UA border / box model ต่างกัน) */ -.room-lobby-br-fixed .lobby-b-sq-btn, -.room-lobby-br-fixed .btn-voice-icon { - box-sizing: border-box; - width: var(--lobby-br-btn); - height: var(--lobby-br-btn); - min-width: var(--lobby-br-btn); - min-height: var(--lobby-br-btn); - max-width: var(--lobby-br-btn); - max-height: var(--lobby-br-btn); - margin: 0; - padding: 0; - border: none; - border-radius: 12px; - appearance: none; - -webkit-appearance: none; - flex-shrink: 0; - cursor: pointer; -} -/* สไตล์เดียวกับปุ่มไมค์ — ไม่มีกรอบ cyan / bg-item */ -.lobby-b-sq-btn { - display: flex; - align-items: center; - justify-content: center; - background: transparent; - box-shadow: none; - transition: transform 0.15s ease, filter 0.15s ease; -} -.lobby-b-sq-btn:hover { - transform: scale(1.04); - filter: brightness(1.08); -} -.lobby-b-sq-btn:active { transform: scale(0.98); } -.room-lobby-br-fixed .lobby-b-sq-btn img, -.room-lobby-br-fixed .btn-voice-icon img { - width: 100%; - height: 100%; - max-width: 100%; - max-height: 100%; - object-fit: contain; - object-position: center; - display: block; - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} -.room-lobby-br-fixed .btn-voice-icon { - display: flex; - align-items: center; - justify-content: center; - background: transparent; -} - -/* —— แฟ้มหลักฐาน LobbyB (รูปจาก /Main-Lobby/IMAGE/See evidence) —— */ -.lobby-evidence-overlay { - position: fixed; - inset: 0; - z-index: 10047; - display: flex; - align-items: center; - justify-content: center; - padding: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left)); - box-sizing: border-box; -} -.lobby-evidence-overlay.is-hidden { - display: none !important; -} -.lobby-evidence-backdrop { - position: absolute; - inset: 0; - background: rgba(4, 8, 22, 0.78); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - cursor: pointer; -} -.lobby-evidence-dialog { - position: relative; - z-index: 1; - width: min(96vw, 900px); - max-height: min(92vh, 920px); - pointer-events: none; -} -.lobby-evidence-dialog * { - pointer-events: auto; -} -.lobby-evidence-frame { - position: relative; - width: 100%; - aspect-ratio: 1684 / 963; - filter: drop-shadow(0 0 24px rgba(0, 255, 255, 0.12)) drop-shadow(0 0 40px rgba(255, 0, 255, 0.08)); -} -.lobby-evidence-bg { - display: block; - width: 100%; - height: 100%; - object-fit: contain; - object-position: center top; - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} -.lobby-evidence-close { - position: absolute; - top: 5.5%; - right: 4%; - width: 8%; - max-width: 56px; - aspect-ratio: 1; - padding: 0; - margin: 0; - border: none; - border-radius: 10px; - background: transparent; - color: rgba(0, 255, 255, 0.95); - font-size: clamp(1.25rem, 4vw, 2rem); - line-height: 1; - cursor: pointer; - text-shadow: 0 0 12px rgba(0, 255, 255, 0.9); - display: flex; - align-items: center; - justify-content: center; - transition: transform 0.15s ease, filter 0.15s ease; -} -.lobby-evidence-close:hover { - transform: scale(1.08); - filter: brightness(1.15); -} -.lobby-evidence-tabs-layer { - position: absolute; - left: 7%; - right: 7%; - top: 15.5%; - height: 13.5%; - min-height: 36px; -} -.lobby-evidence-tabs-img { - display: block; - width: 100%; - height: 100%; - object-fit: contain; - object-position: left center; - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} -.lobby-evidence-tab-hits { - position: absolute; - inset: 0; - display: flex; - flex-direction: row; - align-items: stretch; - padding-left: 1.5%; - padding-right: 0; - box-sizing: border-box; -} -.lobby-evidence-tab-hit { - flex: 0 0 13.2%; - min-width: 0; - height: 100%; - padding: 0; - margin: 0; - border: none; - background: transparent; - cursor: pointer; - border-radius: 8px; -} -.lobby-evidence-tab-hit:focus-visible { - outline: 2px solid rgba(0, 255, 255, 0.9); - outline-offset: 2px; -} -.lobby-evidence-tab-hit-spacer { - flex: 1 1 auto; - pointer-events: none; -} -.lobby-evidence-cards-root { - position: absolute; - left: 5%; - right: 5%; - top: 31%; - bottom: 7%; - display: flex; - flex-direction: row; - flex-wrap: nowrap; - gap: clamp(6px, 1.2vw, 14px); - align-items: stretch; - justify-content: center; - overflow-x: auto; - overflow-y: hidden; - scrollbar-width: thin; - padding-bottom: 4px; - box-sizing: border-box; -} -.lobby-evidence-card { - flex: 1 1 0; - min-width: min(200px, 28vw); - max-width: 320px; - display: flex; - flex-direction: column; - border-radius: 10px; - padding: clamp(6px, 1vw, 10px); - background: rgba(15, 20, 36, 0.92); - box-sizing: border-box; - box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 8px 24px rgba(0, 0, 0, 0.35); -} -.lobby-evidence-card--common { - box-shadow: 0 0 0 2px rgba(180, 190, 200, 0.65), 0 0 16px rgba(200, 210, 220, 0.2), 0 8px 24px rgba(0, 0, 0, 0.35); -} -.lobby-evidence-card--rare { - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.85), 0 0 20px rgba(59, 130, 246, 0.35), 0 8px 24px rgba(0, 0, 0, 0.35); -} -.lobby-evidence-card--legendary { - box-shadow: 0 0 0 2px rgba(234, 179, 8, 0.9), 0 0 22px rgba(250, 204, 21, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35); -} -.lobby-evidence-card-head { - display: flex; - flex-direction: row; - align-items: flex-start; - gap: 8px; - margin-bottom: 6px; -} -.lobby-evidence-card-icon { - flex-shrink: 0; - width: 28px; - height: 28px; - border-radius: 6px; - background: linear-gradient(135deg, rgba(0, 255, 255, 0.25), rgba(255, 0, 255, 0.15)); - display: flex; - align-items: center; - justify-content: center; - font-size: 14px; - line-height: 1; -} -.lobby-evidence-card-titles { - flex: 1; - min-width: 0; -} -.lobby-evidence-card-title-th { - font-family: 'Sarabun', 'Kanit', system-ui, sans-serif; - font-size: clamp(0.68rem, 1.35vw, 0.82rem); - font-weight: 700; - color: #e8ecff; - line-height: 1.25; - margin: 0; -} -.lobby-evidence-card-title-en { - font-family: system-ui, sans-serif; - font-size: clamp(0.58rem, 1.05vw, 0.68rem); - color: rgba(180, 190, 220, 0.85); - margin: 2px 0 0; - line-height: 1.2; -} -.lobby-evidence-card-art { - flex: 1 1 auto; - min-height: clamp(72px, 14vh, 140px); - max-height: min(22vh, 200px); - border-radius: 8px; - background: linear-gradient(160deg, rgba(30, 40, 70, 0.95), rgba(12, 16, 32, 0.98)); - border: 1px solid rgba(0, 255, 255, 0.12); - margin-bottom: 6px; - display: flex; - align-items: center; - justify-content: center; - color: rgba(0, 255, 255, 0.35); - font-size: clamp(1.5rem, 4vw, 2.25rem); - user-select: none; -} -.lobby-evidence-card-body { - font-family: 'Sarabun', 'Kanit', system-ui, sans-serif; - font-size: clamp(0.6rem, 1.15vw, 0.72rem); - color: rgba(210, 218, 240, 0.92); - line-height: 1.4; - margin: 0 0 8px; - flex-shrink: 0; - max-height: 4.5em; - overflow: hidden; - display: -webkit-box; - -webkit-line-clamp: 4; - -webkit-box-orient: vertical; -} -.lobby-evidence-card-foot { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - gap: 8px; - margin-top: auto; - flex-shrink: 0; -} -.lobby-evidence-link { - display: flex; - flex-direction: row; - align-items: center; - gap: 6px; - min-width: 0; -} -.lobby-evidence-avatar { - width: 26px; - height: 26px; - border-radius: 50%; - background: linear-gradient(145deg, #7aa2f7, #565f89); - color: #1a1b26; - font-size: 11px; - font-weight: 800; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - box-shadow: 0 0 0 2px rgba(0, 255, 255, 0.25); -} -.lobby-evidence-link-name { - font-size: clamp(0.62rem, 1.1vw, 0.74rem); - font-weight: 600; - color: #c0caf5; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -.lobby-evidence-foot-meta { - text-align: right; - flex-shrink: 0; -} -.lobby-evidence-rarity { - display: block; - font-size: clamp(0.55rem, 0.95vw, 0.65rem); - color: rgba(170, 180, 210, 0.9); - margin-bottom: 2px; -} -.lobby-evidence-stars { - font-size: clamp(0.65rem, 1.2vw, 0.78rem); - letter-spacing: 1px; - line-height: 1; -} -.lobby-evidence-card--common .lobby-evidence-stars { color: #d4d4d8; text-shadow: 0 0 8px rgba(200, 200, 210, 0.4); } -.lobby-evidence-card--rare .lobby-evidence-stars { color: #60a5fa; text-shadow: 0 0 10px rgba(59, 130, 246, 0.5); } -.lobby-evidence-card--legendary .lobby-evidence-stars { color: #fcd34d; text-shadow: 0 0 10px rgba(234, 179, 8, 0.55); } -@media (max-width: 720px) { - .lobby-evidence-cards-root { - flex-wrap: wrap; - overflow-y: auto; - align-content: flex-start; - } - .lobby-evidence-card { - flex: 1 1 100%; - max-width: none; - min-width: 0; - } -} - -/* —— กระดานอันดับ LobbyB (เหรียญ leaderboard-1/2/3 จาก Main-Lobby) —— */ -.lobby-rank-overlay { - position: fixed; - inset: 0; - z-index: 10048; - display: flex; - align-items: center; - justify-content: center; - padding: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left)); - box-sizing: border-box; -} -.lobby-rank-overlay.is-hidden { - display: none !important; -} -.lobby-rank-backdrop { - position: absolute; - inset: 0; - background: rgba(2, 4, 14, 0.82); - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); - cursor: pointer; -} -.lobby-rank-dialog { - position: relative; - z-index: 1; - width: min(96vw, 520px); - max-height: min(90vh, 720px); - pointer-events: none; -} -.lobby-rank-dialog * { - pointer-events: auto; -} -.lobby-rank-panel { - background: linear-gradient(165deg, rgba(28, 36, 58, 0.96), rgba(12, 16, 32, 0.98)); - border-radius: 16px; - border: 2px solid rgba(0, 255, 255, 0.45); - box-shadow: - 0 0 0 1px rgba(255, 0, 200, 0.25), - 0 0 32px rgba(0, 255, 255, 0.12), - 0 0 48px rgba(255, 0, 180, 0.08), - inset 0 1px 0 rgba(255, 255, 255, 0.06); - padding: clamp(10px, 2.5vw, 16px); - display: flex; - flex-direction: column; - min-height: 0; - font-family: 'Kanit', 'Sarabun', system-ui, sans-serif; -} -.lobby-rank-head { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - position: relative; - padding: 6px 44px 12px 12px; - border-bottom: 1px solid rgba(0, 255, 255, 0.28); - margin-bottom: 8px; -} -.lobby-rank-case-title { - margin: 0; - font-size: clamp(0.95rem, 2.8vw, 1.15rem); - font-weight: 700; - color: #e8f4ff; - text-align: center; - text-shadow: 0 0 12px rgba(0, 255, 255, 0.35); - line-height: 1.25; -} -.lobby-rank-close { - position: absolute; - top: 2px; - right: 4px; - width: 44px; - height: 44px; - padding: 0; - border: none; - border-radius: 10px; - background: transparent; - color: rgba(0, 255, 255, 0.95); - font-size: 1.75rem; - line-height: 1; - cursor: pointer; - text-shadow: 0 0 14px rgba(0, 255, 255, 0.85); - display: flex; - align-items: center; - justify-content: center; - transition: transform 0.15s ease, filter 0.15s ease; -} -.lobby-rank-close:hover { - transform: scale(1.06); - filter: brightness(1.12); -} -.lobby-rank-podium { - display: flex; - flex-direction: row; - align-items: flex-end; - justify-content: center; - gap: clamp(6px, 2vw, 14px); - padding: 8px 4px 14px; - flex-shrink: 0; -} -.lobby-rank-ped { - flex: 1 1 0; - min-width: 0; - max-width: 150px; - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - padding: 10px 6px 12px; - border-radius: 14px; - background: rgba(0, 0, 0, 0.28); - border: 1px solid rgba(0, 255, 255, 0.22); - box-sizing: border-box; -} -.lobby-rank-ped--2 { - order: 1; - min-height: 148px; -} -.lobby-rank-ped--1 { - order: 2; - min-height: 188px; - border-color: rgba(255, 215, 0, 0.45); - box-shadow: 0 0 22px rgba(255, 200, 0, 0.12); -} -.lobby-rank-ped--3 { - order: 3; - min-height: 132px; -} -.lobby-rank-crown { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - gap: 4px; - margin-bottom: 4px; - font-size: 1.1rem; - line-height: 1; - filter: drop-shadow(0 0 6px rgba(255, 215, 0, 0.6)); -} -.lobby-rank-crown-n { - font-size: 0.85rem; - font-weight: 800; - color: #ffe066; -} -.lobby-rank-medal-wrap { - height: 36px; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 6px; -} -.lobby-rank-medal-img { - width: auto; - height: 34px; - object-fit: contain; - display: block; -} -.lobby-rank-ped-avatar { - width: 48px; - height: 48px; - border-radius: 50%; - background: linear-gradient(145deg, #7aa2f7, #565f89); - color: #1a1b26; - font-size: 1.1rem; - font-weight: 800; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 6px; - box-shadow: 0 0 0 2px rgba(0, 255, 255, 0.3); - flex-shrink: 0; -} -.lobby-rank-ped--1 .lobby-rank-ped-avatar { - width: 56px; - height: 56px; - font-size: 1.25rem; -} -.lobby-rank-ped-name { - font-size: clamp(0.68rem, 2vw, 0.8rem); - font-weight: 600; - color: #e8ecff; - line-height: 1.2; - word-break: break-word; - max-width: 100%; -} -.lobby-rank-ped-score { - margin-top: 4px; - font-size: clamp(0.75rem, 2.2vw, 0.9rem); - font-weight: 700; - color: #fff; - text-shadow: 0 0 8px rgba(255, 255, 255, 0.2); -} -.lobby-rank-table-wrap { - flex: 1 1 auto; - min-height: 0; - overflow-y: auto; - overflow-x: hidden; - margin: 0 -4px; - padding: 0 4px; - scrollbar-width: thin; -} -.lobby-rank-table { - width: 100%; - border-collapse: collapse; - font-size: clamp(0.65rem, 1.9vw, 0.78rem); -} -.lobby-rank-table thead th { - text-align: left; - text-transform: uppercase; - letter-spacing: 0.06em; - color: rgba(0, 255, 255, 0.85); - font-weight: 700; - padding: 8px 6px; - border-bottom: 1px solid rgba(0, 255, 255, 0.25); - position: sticky; - top: 0; - background: linear-gradient(180deg, rgba(20, 26, 44, 0.98), rgba(20, 26, 44, 0.92)); - z-index: 1; -} -.lobby-rank-table thead th:nth-child(1) { width: 3.2rem; } -.lobby-rank-table thead th:nth-child(3) { text-align: right; width: 4rem; } -.lobby-rank-table tbody td { - padding: 7px 6px; - border-bottom: 1px solid rgba(255, 255, 255, 0.06); - color: #e2e8f0; - vertical-align: middle; -} -.lobby-rank-table tbody td:nth-child(3) { - text-align: right; - font-weight: 600; - color: #fff; -} -.lobby-rank-table .lobby-rank-row-av { - display: inline-flex; - align-items: center; - gap: 8px; - min-width: 0; -} -.lobby-rank-table .lobby-rank-mini-av { - width: 26px; - height: 26px; - border-radius: 50%; - background: linear-gradient(145deg, #9ece6a, #565f89); - color: #1a1b26; - font-size: 0.65rem; - font-weight: 800; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - box-shadow: 0 0 0 1px rgba(0, 255, 255, 0.2); -} -.lobby-rank-table .lobby-rank-row-name { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 180px; -} -.lobby-rank-self { - flex-shrink: 0; - display: flex; - flex-direction: row; - align-items: center; - gap: 10px; - padding: 12px 10px 6px; - margin-top: 6px; - border-top: 1px solid rgba(255, 0, 180, 0.42); - background: linear-gradient(90deg, rgba(255, 0, 180, 0.07), transparent); -} -.lobby-rank-self-rank { - font-weight: 800; - color: #c0caf5; - min-width: 2.5rem; - font-size: clamp(0.75rem, 2vw, 0.88rem); -} -.lobby-rank-self-av { - width: 40px; - height: 40px; - border-radius: 50%; - background: linear-gradient(145deg, #f472b6, #a855f7); - color: #fff; - font-size: 1rem; - font-weight: 800; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - box-shadow: 0 0 0 2px rgba(255, 100, 200, 0.45); -} -.lobby-rank-self-meta { - flex: 1; - min-width: 0; -} -.lobby-rank-self-name { - font-size: clamp(0.85rem, 2.4vw, 1rem); - font-weight: 800; - color: #fff; - line-height: 1.2; -} -.lobby-rank-self-score { - font-size: clamp(0.85rem, 2.4vw, 1rem); - font-weight: 800; - color: #ff4ecd; - text-shadow: 0 0 12px rgba(255, 78, 205, 0.45); - flex-shrink: 0; -} - -.version-tag { - position: fixed; - right: 8px; - bottom: 4px; - left: auto; - font-size: 10px; - color: #a9b1d6; - opacity: 0.7; - pointer-events: none; -} - -/* play — quiz carry pregame (สอดคล้อง play.html) */ -.quiz-carry-pregame-card { - position: relative; - z-index: 1; - display: flex; - flex-direction: column; - align-items: stretch; - max-width: min(94vw, 900px); - width: 100%; - max-height: min(94vh, 900px); - overflow: hidden; - background: rgba(10, 12, 26, 0.55); - border: none; - border-radius: 4px; - box-shadow: none; - pointer-events: auto; -} -.quiz-carry-pregame-footer { - flex: 0 0 auto; - padding: 0.85rem 1rem 1rem; - background: linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.96)); - border-top: none; - display: flex; - flex-direction: column; - align-items: center; - gap: 0.65rem; -} - -/* Editor — เกมตอบคำถาม */ -.quiz-editor-wrap { - margin: 1rem 0; - padding: 1rem; - background: #24283b; - border-radius: 8px; - border: 1px solid #414868; -} -.quiz-editor-wrap h3 { - margin: 0 0 0.5rem; - font-size: 1rem; - color: #7aa2f7; -} -.quiz-questions-list { - display: flex; - flex-direction: column; - gap: 0.6rem; - margin: 0.75rem 0; -} -.quiz-q-row { - display: grid; - grid-template-columns: 1fr auto auto; - gap: 0.5rem; - align-items: center; -} -@media (max-width: 600px) { - .quiz-q-row { - grid-template-columns: 1fr; - } -} -.quiz-q-row input[type="text"] { - min-width: 0; - padding: 0.4rem 0.5rem; - border-radius: 6px; - border: 1px solid #565f89; - background: #1a1b26; - color: #c0caf5; -} -.quiz-q-row select { - padding: 0.35rem; - border-radius: 6px; - border: 1px solid #565f89; - background: #1a1b26; - color: #c0caf5; -} -.btn-quiz-add, -.quiz-q-remove { - padding: 0.35rem 0.65rem; - border-radius: 6px; - cursor: pointer; - border: 1px solid #565f89; - background: #414868; - color: #c0caf5; - font: inherit; -} -.quiz-q-remove { - font-size: 0.8rem; -} - -/* Stack Tower play — เฟรมกล้องต้อง "คงที่ทุก resolution" - cover สเกลตามด้านที่ใหญ่กว่า → จอกว้าง/เตี้ย ต่างกัน = เฟรม/ซูมเปลี่ยน (กล้องเพี้ยนเวลาเปลี่ยน resolution + บล็อกห้อย/จุดวางหลุดเฟรม) - contain = เห็นทั้งฉาก 16:9 (บล็อกห้อย+จุดวาง+หอ) เหมือนกันเป๊ะทุกจอ; แถบ letterbox กลืนสีฉาก (#0a0e22) ไม่ดูจอเสีย */ -html.play-stack-tower-pixel-canvas #play-canvas-stage.play-canvas-stage { - background: #0a0e22 !important; -} -html.play-stack-tower-pixel-canvas #play-canvas-stage #game-canvas { - object-fit: contain !important; - object-position: center center !important; - background: #0a0e22 !important; -} +* { box-sizing: border-box; } +body { font-family: sans-serif; margin: 0; background: #1a1b26; color: #c0caf5; } +.container { max-width: 720px; margin: 1rem auto; padding: 1rem; } + +/* โครง Editor — แยกแถบเครื่องมือ / พื้นที่วาด */ +.editor-page { + display: block; +} + +/* Editor ฝังใน Admin (?embed=1) — เต็มความสูง iframe, พื้นที่แคนวาสใหญ่ + เลื่อนแยก */ +html.editor-embed-admin { + height: 100%; +} +html.editor-embed-admin body { + height: 100%; + margin: 0; + overflow: hidden; +} +body.editor-embed-admin .version-tag { + display: none !important; +} +body.editor-embed-admin .container.editor-page { + max-width: none !important; + width: 100%; + height: 100%; + margin: 0 !important; + padding: 0.35rem 0.5rem 0.45rem; + display: flex; + flex-direction: column; + min-height: 0; + box-sizing: border-box; +} +body.editor-embed-admin .container.editor-page > h1 { + display: none; +} +body.editor-embed-admin .editor-toolbar-wrap { + /* อย่าให้แถบเครื่องมือถูก flex บีบแล้วล้นไปทับแคนวาส (body overflow:hidden) */ + flex: 0 0 auto; + min-height: 0; + max-height: min(56vh, 520px); + overflow-x: hidden; + overflow-y: auto; + overscroll-behavior: contain; + -webkit-overflow-scrolling: touch; + padding: 0.15rem 0.35rem 0.5rem 0; + margin: 0 0 0.35rem; + border-bottom: 1px solid rgba(65, 72, 104, 0.9); + position: relative; + z-index: 1; + background: linear-gradient(180deg, #1a1b26 0%, #16171f 100%); +} +body.editor-embed-admin .editor-workspace { + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; + overflow: hidden; + position: relative; + z-index: 0; +} +body.editor-embed-admin .canvas-wrap { + flex: 1 1 auto; + min-height: 140px; + overflow: auto; + margin: 0 !important; + border-radius: 10px; + border: 1px solid #414868; + background: #0f1018; + -webkit-overflow-scrolling: touch; + touch-action: pan-x pan-y; +} +body.editor-embed-admin #editor-status { + flex: 0 0 auto; + margin: 0.3rem 0 0; + font-size: 0.8rem; + line-height: 1.35; +} +body.editor-embed-admin .editor-legend-short { + margin: 0; + font-size: 0.76rem; + line-height: 1.45; + color: #a8b0d0; +} +body.editor-embed-admin .editor-toolbar-grid { + gap: 0.45rem; +} +/* การ์ด «ประเภทเกม» ข้อความยาว — ให้กว้างเต็มแถวบนจอแคบ ลดการอัดคอลัมน์ */ +@media (max-width: 720px) { + body.editor-embed-admin .editor-toolbar-grid .editor-card:first-child { + grid-column: 1 / -1; + } +} +body.editor-embed-admin .editor-card { + padding: 0.45rem 0.55rem; + margin-bottom: 0; +} +body.editor-embed-admin .editor-card__title { + font-size: 0.68rem; + margin-bottom: 0.3rem; +} +body.editor-embed-admin .editor-card__hint { + font-size: 0.72rem; + margin-top: 0.3rem; + overflow-wrap: break-word; + word-break: break-word; +} +body.editor-embed-admin .game-type-hint .editor-hint-lead { + font-size: 0.78rem; + margin-bottom: 0.35rem; +} +body.editor-embed-admin .game-type-hint .editor-hint-bullets { + padding-left: 1.05rem; +} +body.editor-embed-admin .game-type-hint .editor-hint-bullets li { + margin: 0.26rem 0; + font-size: 0.72rem; + line-height: 1.45; +} +body.editor-embed-admin .frogger-lanes { + margin: 0.35rem 0; + position: relative; + z-index: auto; +} +body.editor-embed-admin .editor-card--bg { + margin-top: 0.25rem; +} +body.editor-embed-admin .editor-card--help { + margin-top: 0.2rem; +} +h1 { color: #7aa2f7; } +a { color: #9ece6a; } +label { display: inline-block; margin: 0.25rem 0.5rem 0.25rem 0; } +input, button { padding: 0.4rem 0.6rem; margin: 0 0.25rem 0 0; border-radius: 6px; border: 1px solid #414868; } +input { background: #24283b; color: #c0caf5; } +button { background: #7aa2f7; color: #1a1b26; cursor: pointer; border: none; } +.legend { font-size: 0.9rem; color: #a9b1d6; margin: 0.5rem 0; } +.frogger-lanes { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; position: relative; z-index: 2; min-height: 80px; } +.frogger-lanes h3 { margin: 0 0 0.5rem 0; color: #7aa2f7; font-size: 1rem; } +.frogger-lanes table { width: 100%; border-collapse: collapse; font-size: 0.85rem; } +.frogger-lanes th, .frogger-lanes td { padding: 0.25rem 0.5rem; text-align: left; border: 1px solid #414868; } +.frogger-lanes select, .frogger-lanes input[type="number"] { padding: 0.35rem 0.5rem; min-width: 4rem; background: #1a1b26; color: #c0caf5; border: 1px solid #414868; border-radius: 4px; cursor: pointer; font-size: 0.9rem; } +.frogger-lanes select { min-width: 6rem; } +.frogger-lanes .lane-speed { width: 4rem; } +.frogger-lanes .lane-spacing { width: 4rem; } +.frogger-lanes td { vertical-align: middle; } +.frogger-lanes select:disabled, .frogger-lanes input:disabled { opacity: 0.6; cursor: not-allowed; } +.game-type-hint { + font-size: 0.85rem; + color: #a9b1d6; + margin: 0; + line-height: 1.5; + display: block; +} +.game-type-hint .editor-hint-lead { + margin: 0 0 0.45rem; + font-size: 0.9rem; + font-weight: 500; + color: #c0caf5; + line-height: 1.4; +} +.game-type-hint .editor-hint-lead:last-child { + margin-bottom: 0; +} +.editor-hint-bullets { + margin: 0; + padding-left: 1.2rem; + list-style: disc; +} +.editor-hint-bullets li { + margin: 0.35rem 0; +} +.editor-hint-bullets li:first-child { + margin-top: 0; +} +.editor-hint-bullets li:last-child { + margin-bottom: 0; +} +.game-type-hint .editor-hint-bullets code { + font-size: 0.88em; +} +.game-type-hint kbd { + display: inline-block; + font-size: 0.82em; + padding: 0.1em 0.38em; + margin: 0 0.06em; + border-radius: 4px; + background: #1a1b26; + border: 1px solid #414868; + font-family: ui-monospace, monospace; + color: #c0caf5; +} + +/* Editor — การ์ดจัดกลุ่มเครื่องมือ (อ่านง่าย ไม่บีบเป็นแถบเดียวยาว) */ +.editor-toolbar-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); + gap: 0.65rem; + margin: 0.75rem 0 0.5rem; + align-items: start; +} +.editor-card { + margin: 0; + padding: 0.65rem 0.75rem; + background: #24283b; + border: 1px solid rgba(65, 72, 104, 0.95); + border-radius: 10px; +} +.editor-card--wide { + grid-column: 1 / -1; +} +.editor-card__title { + margin: 0 0 0.45rem 0; + padding: 0; + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.04em; + text-transform: uppercase; + color: #7aa2f7; +} +.editor-card__row { + display: flex; + flex-wrap: wrap; + align-items: flex-end; + gap: 0.45rem 0.75rem; +} +.editor-card__row--wrap { + align-items: center; +} +.editor-card__row--actions { + margin-top: 0.55rem; + padding-top: 0.5rem; + border-top: 1px solid rgba(65, 72, 104, 0.75); + gap: 0.5rem; +} +.editor-card__hint { + margin: 0.4rem 0 0; + padding: 0.45rem 0.55rem; + background: rgba(15, 16, 24, 0.55); + border-radius: 6px; + border-left: 3px solid #7aa2f7; +} +.editor-card label { margin: 0; } +/* กลุ่มกล่องตรวจ: ชนกำแพง vs โซนห้ามซ้อน — แยกมองชัดจากแถว label เปล่า ๆ */ +.editor-footprint-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.45rem 0.85rem; + width: 100%; + padding: 0.42rem 0.55rem 0.48rem; + border-radius: 8px; + border: 1px solid rgba(122, 162, 247, 0.38); + background: rgba(20, 22, 34, 0.72); + box-sizing: border-box; +} +.editor-footprint-row--wall { + border-color: rgba(122, 162, 247, 0.45); + background: rgba(26, 32, 52, 0.65); +} +.editor-footprint-row--no-overlap { + border-color: rgba(158, 206, 106, 0.5); + background: rgba(22, 34, 26, 0.55); +} +.editor-footprint-row__head { + flex: 0 0 100%; + margin: 0 0 0.08rem 0; + padding: 0; + font-size: 0.68rem; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + color: #7aa2f7; +} +.editor-footprint-row--no-overlap .editor-footprint-row__head { + color: #9ece6a; +} +.editor-footprint-row .editor-footprint-row__field input[type="number"] { + width: 3.1rem; + margin-left: 0.2rem; +} +.editor-field-grow { + flex: 1 1 180px; + min-width: min(100%, 200px); +} +.editor-field-grow select, +.editor-field-grow input[type="text"] { + width: 100%; + max-width: 100%; + min-width: 0; +} +.editor-field-drawmode { + flex: 1 1 280px; + min-width: min(100%, 240px); +} +.editor-field-drawmode select { + width: 100%; + max-width: 100%; + min-width: 0; +} +.editor-cell-color { + display: inline-flex; + flex-wrap: wrap; + align-items: center; + gap: 0.35rem 0.75rem; +} +.editor-grid-image-tools { + display: none; + flex-direction: column; + align-items: stretch; + gap: 0.5rem; + max-width: 100%; + width: min(100%, 520px); +} +.editor-grid-image-size-row { + display: flex; + flex-wrap: wrap; + gap: 0.5rem 1rem; + align-items: center; +} +.editor-grid-image-size-row input[type="number"] { + width: 3.2rem; + margin-left: 0.25rem; +} +.editor-grid-image-carry-bind-row { + display: flex; + flex-wrap: wrap; + gap: 0.35rem 0.75rem; + align-items: center; + font-size: 0.72rem; + color: #a9b1d6; +} +.editor-grid-image-carry-bind-row select { + margin-left: 0.35rem; + max-width: 12rem; +} +.editor-hint-inline { + font-size: 0.68rem; + color: #787c99; + line-height: 1.35; + flex: 1 1 140px; +} +.editor-grid-image-gallery-wrap { + display: flex; + flex-direction: column; + gap: 0.25rem; +} +.editor-grid-image-gallery-label { + font-size: 0.72rem; + color: #a9b1d6; + font-weight: 600; +} +.editor-grid-image-gallery-note { + margin: 0.1rem 0 0.35rem; + font-size: 0.65rem; + line-height: 1.35; + color: #787c99; + max-width: 36rem; +} +.grid-cell-image-gallery { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(68px, 1fr)); + gap: 0.4rem; + max-height: 200px; + overflow-y: auto; + padding: 0.35rem; + border-radius: 8px; + border: 1px solid rgba(65, 72, 104, 0.85); + background: rgba(15, 16, 24, 0.6); +} +.grid-cell-image-gallery-empty { + font-size: 0.72rem; + color: #787c99; + padding: 0.35rem; +} +.grid-cell-image-gallery-item { + position: relative; + padding: 0; + margin: 0; + border: 2px solid transparent; + border-radius: 8px; + overflow: hidden; + cursor: pointer; + background: #24283b; + line-height: 0; +} +.grid-cell-image-gallery-item.is-selected { + border-color: #9ece6a; + box-shadow: 0 0 0 1px rgba(158, 206, 106, 0.35); +} +.grid-cell-image-gallery-item img { + display: block; + width: 100%; + height: 56px; + object-fit: cover; +} +.grid-cell-image-gallery-row { + display: flex; + flex-direction: column; + gap: 0.35rem; + align-items: stretch; +} +.grid-cell-image-gallery-same-hint { + font-size: 0.62rem; + line-height: 1.35; + color: #f7768e; + padding: 0.2rem 0.35rem; + border-radius: 4px; + background: rgba(247, 118, 142, 0.12); + border: 1px solid rgba(247, 118, 142, 0.35); +} +.grid-cell-image-gallery-held-side { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.2rem; + padding: 0.15rem 0.1rem 0.25rem; + border-radius: 6px; + background: rgba(0, 0, 0, 0.22); +} +.grid-cell-image-gallery-held-label { + font-size: 0.58rem; + font-weight: 700; + color: #7dcfff; + letter-spacing: 0.04em; +} +.grid-cell-image-gallery-held-thumb { + display: block; + width: 100%; + max-height: 44px; + object-fit: cover; + border-radius: 4px; + background: #1a1b26; +} +.grid-cell-image-gallery-held-btn { + font-size: 0.58rem; + padding: 0.15rem 0.35rem; + border-radius: 4px; + border: 1px solid rgba(125, 207, 255, 0.45); + background: rgba(26, 27, 38, 0.95); + color: #c0caf5; + cursor: pointer; +} +.grid-cell-image-gallery-held-btn:hover { + border-color: rgba(158, 206, 106, 0.65); + color: #9ece6a; +} +.grid-cell-image-gallery-clear-held { + font-size: 0.7rem; + line-height: 1; + padding: 0.05rem 0.25rem; + border: none; + border-radius: 4px; + background: rgba(247, 118, 142, 0.25); + color: #f7768e; + cursor: pointer; +} +.grid-cell-image-gallery-clear-held:hover { + background: rgba(247, 118, 142, 0.45); +} +.grid-cell-image-gallery-cap { + display: block; + font-size: 0.65rem; + text-align: center; + padding: 0.15rem 0; + color: #c0caf5; + background: rgba(0, 0, 0, 0.35); +} +.editor-grid-image-upload-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; +} +body.editor-embed-admin .grid-cell-image-gallery { + max-height: 160px; +} +body.editor-embed-admin .grid-cell-image-gallery-item img { + height: 48px; +} +.editor-btn-primary { + font-weight: 600; +} +.editor-card--bg { + margin: 0.5rem 0 0.35rem; +} +.editor-card--help { + margin: 0.35rem 0 0.15rem; +} +.editor-help-list { + margin: 0; + padding-left: 1.15rem; + list-style: disc; +} +.editor-help-list li { + margin-bottom: 0.28rem; +} +@media (min-width: 900px) { + .editor-help-list { + columns: 2; + column-gap: 1.5rem; + } + .editor-help-list li { + break-inside: avoid; + } +} +.canvas-wrap { margin: 1rem 0; } +.container { padding-left: 1rem; padding-right: 1rem; } +#editor-canvas { + background: #1a1b26; + display: block; + touch-action: none; + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.editor-map-zoom-bar { + display: flex; + align-items: center; + gap: 5px; + padding: 6px 10px; + border-radius: 999px; + background: rgba(8, 12, 28, 0.88); + border: 1px solid #2a3357; + box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45); +} +.editor-map-zoom-btn { + border: 1px solid #2a3357; + background: #0d1430; + color: #eef2ff; + border-radius: 8px; + min-width: 34px; + height: 32px; + padding: 0 8px; + cursor: pointer; + font: inherit; + font-weight: 700; + line-height: 1; +} +.editor-map-zoom-btn:hover { filter: brightness(1.2); } +.editor-map-zoom-label { + min-width: 46px; + text-align: center; + font-size: 12px; + font-weight: 700; + color: #c7d2fe; + user-select: none; +} +.game-wrap { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 0; } +.game-header { flex-shrink: 0; background: #24283b; padding: 0.5rem 1rem; display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; } +.game-header span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.game-header button { flex-shrink: 0; } +#game-canvas { + flex: 1 1 auto; + display: block; + width: 100%; + /* [2026-07-31] ล็อกอัตราส่วนภาพ — เดิมมีแต่ width:100% ไม่มี height เลย + ผลคือกล่องแสดงผล "กว้างตามจอ แต่สูงตามบัฟเฟอร์" พอ canvas.width ยังเป็นค่าเก่า + (ช่วงหมุนจอ / แถบ URL ของมือถือยุบ) เบราว์เซอร์จะยืดบิตแมปตามแนวนอนอย่างเดียว + = อาการ "ภาพในเกมยืดแปลก ๆ" ที่ผู้เล่นมือถือเจอ + object-fit: contain ทำให้ยืดแบบไม่เท่ากันสองแกน "เป็นไปไม่ได้" แม้ในเฟรมที่ค่ายังค้าง + (ระหว่างนั้นเห็นเป็นขอบว่างแทน ซึ่งดีกว่าภาพเพี้ยน) + บน PC บัฟเฟอร์เท่ากล่องเสมอ → contain ไม่ทำอะไร = ภาพเดิมทุกพิกเซล + ต้นแบบ: MG3 ใช้วิธีนี้อยู่แล้ว (ดู html.play-stack-tower-pixel-canvas ด้านล่าง) */ + height: 100%; + object-fit: contain; + object-position: center center; + min-height: 0; + min-width: 0; + touch-action: none; + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.game-wrap .chat-panel { flex-shrink: 0; } +.chat-panel { height: 160px; border-top: 1px solid #414868; display: flex; flex-direction: column; } +#chat-messages { flex: 1; overflow-y: auto; padding: 0.5rem; font-size: 0.9rem; } +#chat-form { display: flex; padding: 0.5rem; gap: 0.5rem; } +#chat-input { flex: 1; } + +.lobby-section { margin: 1.25rem 0; padding: 1rem; background: #24283b; border-radius: 8px; } +.lobby-section h2 { margin: 0 0 0.75rem 0; font-size: 1rem; color: #7aa2f7; } +#room-list { list-style: none; margin: 0; padding: 0; } +#room-list .room-item { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid #414868; } +#room-list .room-item:last-child { border-bottom: none; } +#room-list .room-name { font-weight: 600; color: #c0caf5; min-width: 0; } +#room-list .room-meta { font-size: 0.85rem; color: #a9b1d6; } +#room-list .room-meta-inline { font-size: 0.8rem; color: #565f89; font-weight: normal; } +#room-list-status { margin: 0; color: #a9b1d6; font-size: 0.9rem; } + +.room-lobby-peers { margin: 1rem 0; padding: 0.75rem; background: #24283b; border-radius: 8px; } +.room-lobby-peer { padding: 0.35rem 0; color: #c0caf5; } +.room-lobby-peer:not(:last-child) { border-bottom: 1px solid #414868; } +#lobby-map-wrap { position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; min-width: 100vw; min-height: 100vh; min-height: 100dvh; z-index: 0; } +#lobby-map-canvas { + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + width: 100%; + height: 100%; + min-width: 100%; + min-height: 100%; + margin: 0; + padding: 0; + background: #303770; + box-sizing: border-box; +} +#lobby-map-canvas:focus { + outline: none; +} +#lobby-map-canvas:focus-visible { + outline: 2px solid rgba(122, 162, 247, 0.45); + outline-offset: -2px; +} +/* LobbyB (mn8nx46h) — ไม่แสดงปุ่มพร้อม */ +body.room-lobby--lobby-b .room-lobby-ready-fixed { + display: none !important; +} +.lobby-interact-hint { + position: absolute; + bottom: max(10px, env(safe-area-inset-bottom)); + left: 50%; + transform: translateX(-50%); + z-index: 2; + margin: 0; + padding: 0.2rem 0.55rem; + font-size: clamp(0.72rem, 1.8vw, 0.85rem); + color: rgba(203, 213, 245, 0.9); + text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55); + pointer-events: none; + font-family: system-ui, 'Kanit', sans-serif; + white-space: nowrap; +} +.lobby-interact-hint kbd { + display: inline-block; + padding: 0.06em 0.32em; + border-radius: 4px; + background: rgba(26, 27, 38, 0.88); + border: 1px solid rgba(122, 162, 247, 0.45); + font-size: 0.88em; + font-family: inherit; +} +.lobby-zoom-pct { + position: absolute; + top: 12px; + left: 50%; + transform: translateX(-50%); + z-index: 2; + padding: 6px 12px; + border-radius: 8px; + background: rgba(26, 27, 38, 0.85); + color: #c0caf5; + font-size: 1rem; + font-weight: 600; + pointer-events: none; + opacity: 0; + transition: opacity 0.2s ease; +} +.lobby-zoom-pct.lobby-zoom-pct-visible { opacity: 1; } +/* ซ่อนแผง overlay รายชื่อ / host / แชท — โถงโฟกัสแผนที่ + ปุ่ม READY/ไมค์ ด้านนอก */ +.room-lobby-overlay { display: none !important; } +.room-lobby-top-left-cluster { + position: fixed; + top: max(12px, env(safe-area-inset-top)); + left: max(12px, env(safe-area-inset-left)); + z-index: 55; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0.65rem; + pointer-events: none; +} +.room-lobby-top-left-cluster .room-lobby-exit-fixed { + pointer-events: auto; +} + +/* มุมขวาบน — โปรไฟล์ตัวละคร */ +.room-lobby-top-right-cluster { + position: fixed; + top: max(12px, env(safe-area-inset-top)); + right: max(12px, env(safe-area-inset-right)); + z-index: 56; + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 0.65rem; + pointer-events: none; +} +.room-lobby-top-right-cluster > * { + pointer-events: auto; +} +.room-lobby-profile-wrap { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.2rem; +} +.room-lobby-profile-frame { + width: clamp(56px, 12vw, 72px); + height: clamp(56px, 12vw, 72px); + border-radius: 14px; + border: 2px solid rgba(0, 212, 255, 0.65); + overflow: hidden; + background: rgba(18, 22, 42, 0.92); + box-shadow: + 0 0 0 1px rgba(34, 211, 238, 0.2), + 0 0 22px rgba(34, 211, 238, 0.28); +} +.room-lobby-profile-frame img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center bottom; + image-rendering: pixelated; + image-rendering: crisp-edges; +} +.room-lobby-actions { margin-top: 1rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; } +.room-lobby-actions .room-lobby-btn-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; opacity: 0; pointer-events: none; } +.room-lobby-actions label { margin: 0; } +.room-lobby-actions #btn-start { background: #9ece6a; color: #1a1b26; } +#host-only { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; } +#host-only select { padding: 0.4rem 0.6rem; border-radius: 6px; border: 1px solid #414868; background: #24283b; color: #c0caf5; } +.host-start-area-hint { + flex-basis: 100%; + margin: 0; + font-size: 0.88rem; + color: #e0af68; + line-height: 1.35; + max-width: 100%; +} +#host-only #btn-start:disabled { + opacity: 0.5; + cursor: not-allowed; + filter: grayscale(0.25); +} +.room-lobby-chat { margin-top: 1rem; } +.room-lobby-chat.chat-panel { + border-radius: 12px; + overflow: hidden; + box-shadow: none; +} +.room-lobby-chat-peers.chat-panel { + position: fixed; + right: 1.25rem; + bottom: 5.5rem; + width: 576px; + height: 525px; + max-width: calc(100vw - 2.5rem); + z-index: 52; + margin-top: 0; + display: flex; + flex-flow: column; + padding: 2rem; + box-sizing: border-box; + border-top: 0px solid #414868; + background: url(/Game/img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; + background-color: transparent; +} +.room-lobby-chat-peers.chat-panel .chat-header-title.chat-header-title-img img { width: 90px; height: 77px; } +.room-lobby-chat-peers.chat-panel .chat-close-btn { width: 48px; height: 48px; } +.room-lobby-chat-peers.chat-panel .chat-close-btn img { width: 50px; height: 50px; } +.room-lobby-chat-peers.chat-panel #chat-messages { padding: 0.75rem; font-size: 1.05rem; gap: 0.5rem; } +.room-lobby-chat-peers.chat-panel .chat-form-bar { padding: 0.6rem 0; gap: 0.5rem; } +.room-lobby-chat-peers.chat-panel #chat-input { padding: 0.6rem 0.85rem; font-size: 1.05rem; } +.room-lobby-chat-peers.chat-panel .chat-send-btn { width: 52px; height: 52px; } +.room-lobby-chat-peers.chat-panel .chat-send-btn img { width: 58px; height: 58px; } +.room-lobby-chat-peers.chat-panel .chat-msg { padding: 0.6rem 1rem; font-size: 1.05rem; } +.room-lobby-chat-peers.chat-panel .chat-header-bar { + margin: 0 -2rem 0 -2rem; + padding-left: 2rem; + padding-right: 2rem; + justify-content: space-between; + align-items: center; + min-height: 72px; + height: 72px; +} +.room-lobby-chat-peers.chat-panel #chat-messages { + flex: 1; + min-height: 0; + height: auto; +} +.room-lobby-chat .chat-header-bar { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0; + min-height: 48px; + height: 48px; + background: url(/Game/img/chat-line.png) bottom repeat-x; + background-size: 100% 4px; + background-color: transparent; +} +.room-lobby-chat-peers .chat-header-title.chat-header-title-img { + display: inline-flex; + align-items: center; + line-height: 0; +} +.room-lobby-chat-peers .chat-header-title.chat-header-title-img img { + width: 60px; + height: 51px; + object-fit: contain; + display: block; +} +.room-lobby-chat-ai .chat-header-title.chat-header-title-img { + display: flex; + align-items: flex-end; + gap: 0.5rem; + line-height: 0; +} +.room-lobby-chat-ai .chat-header-title.chat-header-title-img .ai-chat-title-label { + height: 52px; + width: auto; + object-fit: contain; + display: block; + flex-shrink: 0; + margin-bottom: -2px; +} +/* รูปหัวแชท AI — ยกขึ้นเหนือเส้น */ +.room-lobby-chat-ai .chat-header-title.chat-header-title-img img { + width: 86px; + height: 92px; + object-fit: cover; + display: block; + flex-shrink: 0; + margin-top: -27px; + margin-left: -6px; + position: relative; + z-index: 1; +} +.room-lobby-chat .chat-header-title { + font-size: 1rem; + font-weight: 600; + color: #a0aec0; +} +.room-lobby-chat .chat-close-btn { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + border: none; + border-radius: 8px; + background: transparent; + cursor: pointer; + margin-left: auto; +} +.room-lobby-chat-peers .chat-header-bar .chat-close-btn { margin-left: 0; } +.room-lobby-chat .chat-close-btn img { width: 34px; height: 34px; object-fit: contain; } +.room-lobby-chat .chat-close-btn:hover { opacity: 0.9; } +.room-lobby-chat.chat-panel-collapsed #chat-messages, +.room-lobby-chat.chat-panel-collapsed .chat-form-bar { display: none !important; } +.room-lobby-chat-peers.chat-panel-collapsed .chat-header-title { display: none !important; } +.room-lobby-chat-peers.chat-panel-collapsed .chat-header-bar { + justify-content: center; + padding: 0; + background: none !important; + border: none; +} +.room-lobby-chat-peers.chat-panel-collapsed.chat-panel { + width: 80px; + height: 80px; + min-height: 0; + padding: 0; + right: 1.25rem; + bottom: 6.25rem; + display: flex; + align-items: center; + justify-content: center; + background: none !important; + background-color: transparent !important; + border: none; + box-shadow: none; +} +.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn { + width: 80px; + height: 80px; + overflow: visible; +} +.room-lobby-chat-peers.chat-panel-collapsed .chat-close-btn img { + width: 100%; + height: 100%; + object-fit: contain; + object-position: center; + display: block; +} +.room-lobby-chat #chat-messages, +.room-lobby-chat #ai-chat-messages { + height: 100px; + overflow-y: auto; + padding: 0.5rem; + font-size: 0.85rem; + border: none; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.35rem; + background: none; + background-color: transparent; + box-shadow: none; +} +.room-lobby-chat .chat-messages-bg { border-radius: 0; } +.room-lobby-chat #chat-form.chat-form-bar, +.room-lobby-chat #ai-chat-form.chat-form-bar { + display: flex; + gap: 0.4rem; + align-items: center; + padding: 0.4rem 0; + background: none; + background-color: transparent; + border-top: none; + flex-shrink: 0; +} +.room-lobby-chat-peers .chat-form-bar { + padding-left: 0; + padding-right: 0; +} +.room-lobby-chat #chat-input, +.room-lobby-chat #ai-chat-input { + flex: 1; + min-width: 0; + padding: 0.45rem 0.6rem; + border-radius: 10px; + border: 1px solid rgba(0, 212, 255, 0.25); + background: rgba(30, 35, 50, 0.8); + color: #c0caf5; + font-size: 0.9rem; + box-sizing: border-box; + margin-left: 9px; +} +.room-lobby-chat .chat-send-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + flex-shrink: 0; + padding: 0; + border: none; + border-radius: 10px; + background: transparent; + cursor: pointer; +} +.room-lobby-chat .chat-send-btn img { width: 45px; height: 45px; object-fit: contain; } +.room-lobby-chat .chat-send-btn:hover { opacity: 0.9; } +.room-lobby-chat .chat-msg { + padding: 0.4rem 0.75rem; + border-radius: 12px; + max-width: 85%; + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; +} +.room-lobby-chat .chat-msg-mine { + align-self: flex-end; + text-align: right; + background-image: url(/Game/img/chat-bubble-me.png); + background-color: rgba(122, 162, 247, 0.9); + color: #1a1b26; +} +.room-lobby-chat .chat-msg-other { + align-self: flex-start; + text-align: left; + background-image: url(/Game/img/chat-bubble-friend.png); + background-color: rgba(65, 72, 104, 0.9); + color: #c0caf5; +} +.room-lobby-chat .chat-msg-ai { + align-self: flex-start; + text-align: left; + background-image: url(/Game/img/chat-bubble-friend.png); + background-color: rgba(158, 206, 106, 0.9); + color: #1a1b26; +} +.room-lobby-chat .chat-msg-system { + align-self: center; + text-align: center; + max-width: 95%; + background-image: none; + background-color: rgba(26, 27, 38, 0.72); + color: #9aa5ce; + font-size: 0.88rem; + font-style: italic; + padding: 0.35rem 0.6rem; +} + +/* AI chat — loading แบบ Messenger (จุดกระโดด 3 จุด), อยู่ติดข้อความล่าสุดในลิสต์ */ +.room-lobby-chat .ai-chat-typing { + display: flex; + align-items: center; + gap: 4px; + padding: 12px 14px; + min-height: 24px; + flex-shrink: 0; + background-image: url(/Game/img/chat-bubble-friend.png); + background-color: rgba(158, 206, 106, 0.9); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; +} +.room-lobby-chat .ai-typing-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: #1a1b26; + animation: ai-typing-bounce 1.4s ease-in-out infinite both; +} +.room-lobby-chat .ai-typing-dot:nth-child(1) { animation-delay: 0s; } +.room-lobby-chat .ai-typing-dot:nth-child(2) { animation-delay: 0.2s; } +.room-lobby-chat .ai-typing-dot:nth-child(3) { animation-delay: 0.4s; } +@keyframes ai-typing-bounce { + 0%, 60%, 100% { transform: translateY(0); } + 30% { transform: translateY(-6px); } +} + +/* AI chat panel — ขนาดและตำแหน่งตาม reference (วงซ้าย) */ +.room-lobby-chat-ai.chat-panel { + position: fixed; + left: 20px; + right: auto; + bottom: 5.5rem; + width: 576px; + height: 525px; + max-width: calc(100vw - 2.5rem); + z-index: 51; + margin-top: 0; + display: flex; + flex-flow: column; + padding: 2rem; + box-sizing: border-box; + border-top: 0; + background: url(/Game/img/chat-msg-bg-alpha.png) center/100% 100% no-repeat; + background-color: transparent; +} +.room-lobby-chat-ai.chat-panel .chat-header-bar { + margin: 0 -2rem 0 -2rem; + padding-left: 2rem; + padding-right: 2rem; + justify-content: space-between; + align-items: center; + min-height: 80px; + height: 80px; + overflow: visible; +} +.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img img { width: 130px; height: 138px; margin-top: -38px; margin-left: -8px; } +.room-lobby-chat-ai.chat-panel .chat-header-title.chat-header-title-img .ai-chat-title-label { height: 78px; } +.room-lobby-chat-ai.chat-panel .chat-close-btn { width: 48px; height: 48px; } +.room-lobby-chat-ai.chat-panel .chat-close-btn img { width: 50px; height: 50px; } +.room-lobby-chat-ai.chat-panel #ai-chat-messages { padding: 0.75rem; font-size: 1.05rem; gap: 0.5rem; } +.room-lobby-chat-ai.chat-panel .chat-form-bar { padding: 0.6rem 0; gap: 0.5rem; } +.room-lobby-chat-ai.chat-panel #ai-chat-input { padding: 0.6rem 0.85rem; font-size: 1.05rem; } +.room-lobby-chat-ai.chat-panel .chat-send-btn { width: 52px; height: 52px; } +.room-lobby-chat-ai.chat-panel .chat-send-btn img { width: 58px; height: 58px; } +.room-lobby-chat-ai.chat-panel .chat-msg { padding: 0.6rem 1rem; font-size: 1.05rem; } +.room-lobby-chat-ai.chat-panel .ai-chat-typing { padding: 14px 18px; min-height: 28px; } +.room-lobby-chat-ai.chat-panel .ai-typing-dot { width: 8px; height: 8px; } +.room-lobby-chat-ai.chat-panel { + overflow: visible; +} +.room-lobby-chat-ai.chat-panel #ai-chat-messages { + flex: 1; + min-height: 0; + height: auto; +} +.room-lobby-chat-ai .chat-form-bar { + padding-left: 0; + padding-right: 0; +} +.room-lobby-chat-ai .ai-chat-admin-link { + margin: 0.35rem 0 0 0; + font-size: 0.75rem; + flex-shrink: 0; +} +/* AI chat collapsed */ +.room-lobby-chat-ai.chat-panel-collapsed #ai-chat-messages, +.room-lobby-chat-ai.chat-panel-collapsed .chat-form-bar, +.room-lobby-chat-ai.chat-panel-collapsed .ai-chat-admin-link { display: none !important; } +.room-lobby-chat-ai.chat-panel-collapsed .chat-header-title { display: none !important; } +.room-lobby-chat-ai.chat-panel-collapsed .chat-header-bar { + justify-content: center; + padding: 0; + background: none !important; + border: none; +} +.room-lobby-chat-ai.chat-panel-collapsed.chat-panel { + width: 80px; + height: 80px; + min-height: 0; + padding: 0; + left: 20px; + bottom: 1.25rem; + display: flex; + align-items: center; + justify-content: center; + background: none !important; + background-color: transparent !important; + border: none; + box-shadow: none; +} +.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn { + width: 80px; + height: 80px; + overflow: visible; +} +.room-lobby-chat-ai.chat-panel-collapsed .chat-close-btn img { + width: 100%; + height: 100%; + object-fit: contain; + object-position: center; + display: block; +} + +.room-lobby-exit-fixed { + position: static; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + justify-content: flex-start; + gap: 10px; + width: max-content; + max-width: calc(100vw - 24px); + box-sizing: border-box; +} +.room-lobby-exit-fixed .btn-exit-icon { + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + width: 80px; + height: 80px; + min-width: 80px; + padding: 0; + border: none; + border-radius: 12px; + background: transparent; + cursor: pointer; +} +.room-lobby-exit-fixed .btn-exit-icon:hover { + opacity: 0.9; +} +.room-lobby-exit-fixed .btn-exit-icon img { + width: 100%; + height: auto; + object-fit: contain; + display: block; +} + +.room-lobby-ready-fixed { + position: fixed; + bottom: 1.25rem; + left: 50%; + transform: translateX(-50%); + z-index: 120; + pointer-events: none; +} +.room-lobby-ready-fixed .ready-label, +.room-lobby-ready-fixed .ready-check-input { + pointer-events: auto; +} +.room-lobby-ready-fixed .ready-label { + position: relative; + display: inline-block; + padding: 0; + margin: 0; + border: none; + border-radius: 0; + background: transparent; + box-shadow: none; + cursor: pointer; + transition: transform 0.15s ease, filter 0.15s ease; + line-height: 0; +} +.room-lobby-ready-fixed .ready-label:hover { + transform: scale(1.04); + filter: brightness(1.08); +} +.room-lobby-ready-fixed .ready-label:active { + transform: scale(0.98); +} +.room-lobby-ready-fixed .ready-check-input { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + margin: 0; + opacity: 0; + cursor: pointer; + z-index: 2; +} +.room-lobby-ready-fixed .ready-label-img { + display: block; + height: clamp(44px, 8vh, 72px); + width: auto; + max-width: min(240px, 78vw); + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} +.room-lobby-ready-fixed .ready-label--active .ready-label-img { + filter: drop-shadow(0 0 10px rgba(158, 206, 106, 0.45)); +} + +/* มุมขวาล่าง — ไมค์ทุกห้อง + ปุ่ม LobbyB (แว่น/ถ้วย) */ +.room-lobby-br-fixed { + --lobby-br-btn: 80px; + position: fixed; + bottom: 1.25rem; + right: max(1.25rem, env(safe-area-inset-right)); + z-index: 400; + display: flex; + flex-direction: row; + align-items: flex-end; + gap: 10px; + pointer-events: none; +} +.room-lobby-br-fixed .lobby-b-extra-row, +.room-lobby-br-fixed .btn-voice-icon { + pointer-events: auto; +} +.lobby-b-extra-row { + display: flex; + flex-direction: row; + align-items: flex-end; + gap: 10px; +} +.lobby-b-extra-row.is-hidden { + display: none !important; +} +/* โหมดเกม (ควิซ) ใน room-lobby — ไม่โชว์แว่น/ถ้วย LobbyB */ +body.room-lobby--quiz-active .lobby-b-extra-row { + display: none !important; + visibility: hidden !important; + pointer-events: none !important; +} +/* ปุ่มมุมขวาล่าง — ขนาดเดียวกัน (กัน UA border / box model ต่างกัน) */ +.room-lobby-br-fixed .lobby-b-sq-btn, +.room-lobby-br-fixed .btn-voice-icon { + box-sizing: border-box; + width: var(--lobby-br-btn); + height: var(--lobby-br-btn); + min-width: var(--lobby-br-btn); + min-height: var(--lobby-br-btn); + max-width: var(--lobby-br-btn); + max-height: var(--lobby-br-btn); + margin: 0; + padding: 0; + border: none; + border-radius: 12px; + appearance: none; + -webkit-appearance: none; + flex-shrink: 0; + cursor: pointer; +} +/* สไตล์เดียวกับปุ่มไมค์ — ไม่มีกรอบ cyan / bg-item */ +.lobby-b-sq-btn { + display: flex; + align-items: center; + justify-content: center; + background: transparent; + box-shadow: none; + transition: transform 0.15s ease, filter 0.15s ease; +} +.lobby-b-sq-btn:hover { + transform: scale(1.04); + filter: brightness(1.08); +} +.lobby-b-sq-btn:active { transform: scale(0.98); } +.room-lobby-br-fixed .lobby-b-sq-btn img, +.room-lobby-br-fixed .btn-voice-icon img { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + object-fit: contain; + object-position: center; + display: block; + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} +.room-lobby-br-fixed .btn-voice-icon { + display: flex; + align-items: center; + justify-content: center; + background: transparent; +} + +/* —— แฟ้มหลักฐาน LobbyB (รูปจาก /Main-Lobby/IMAGE/See evidence) —— */ +.lobby-evidence-overlay { + position: fixed; + inset: 0; + z-index: 10047; + display: flex; + align-items: center; + justify-content: center; + padding: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left)); + box-sizing: border-box; +} +.lobby-evidence-overlay.is-hidden { + display: none !important; +} +.lobby-evidence-backdrop { + position: absolute; + inset: 0; + background: rgba(4, 8, 22, 0.78); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + cursor: pointer; +} +.lobby-evidence-dialog { + position: relative; + z-index: 1; + width: min(96vw, 900px); + max-height: min(92vh, 920px); + pointer-events: none; +} +.lobby-evidence-dialog * { + pointer-events: auto; +} +.lobby-evidence-frame { + position: relative; + width: 100%; + aspect-ratio: 1684 / 963; + filter: drop-shadow(0 0 24px rgba(0, 255, 255, 0.12)) drop-shadow(0 0 40px rgba(255, 0, 255, 0.08)); +} +.lobby-evidence-bg { + display: block; + width: 100%; + height: 100%; + object-fit: contain; + object-position: center top; + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} +.lobby-evidence-close { + position: absolute; + top: 5.5%; + right: 4%; + width: 8%; + max-width: 56px; + aspect-ratio: 1; + padding: 0; + margin: 0; + border: none; + border-radius: 10px; + background: transparent; + color: rgba(0, 255, 255, 0.95); + font-size: clamp(1.25rem, 4vw, 2rem); + line-height: 1; + cursor: pointer; + text-shadow: 0 0 12px rgba(0, 255, 255, 0.9); + display: flex; + align-items: center; + justify-content: center; + transition: transform 0.15s ease, filter 0.15s ease; +} +.lobby-evidence-close:hover { + transform: scale(1.08); + filter: brightness(1.15); +} +.lobby-evidence-tabs-layer { + position: absolute; + left: 7%; + right: 7%; + top: 15.5%; + height: 13.5%; + min-height: 36px; +} +.lobby-evidence-tabs-img { + display: block; + width: 100%; + height: 100%; + object-fit: contain; + object-position: left center; + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} +.lobby-evidence-tab-hits { + position: absolute; + inset: 0; + display: flex; + flex-direction: row; + align-items: stretch; + padding-left: 1.5%; + padding-right: 0; + box-sizing: border-box; +} +.lobby-evidence-tab-hit { + flex: 0 0 13.2%; + min-width: 0; + height: 100%; + padding: 0; + margin: 0; + border: none; + background: transparent; + cursor: pointer; + border-radius: 8px; +} +.lobby-evidence-tab-hit:focus-visible { + outline: 2px solid rgba(0, 255, 255, 0.9); + outline-offset: 2px; +} +.lobby-evidence-tab-hit-spacer { + flex: 1 1 auto; + pointer-events: none; +} +.lobby-evidence-cards-root { + position: absolute; + left: 5%; + right: 5%; + top: 31%; + bottom: 7%; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + gap: clamp(6px, 1.2vw, 14px); + align-items: stretch; + justify-content: center; + overflow-x: auto; + overflow-y: hidden; + scrollbar-width: thin; + padding-bottom: 4px; + box-sizing: border-box; +} +.lobby-evidence-card { + flex: 1 1 0; + min-width: min(200px, 28vw); + max-width: 320px; + display: flex; + flex-direction: column; + border-radius: 10px; + padding: clamp(6px, 1vw, 10px); + background: rgba(15, 20, 36, 0.92); + box-sizing: border-box; + box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 8px 24px rgba(0, 0, 0, 0.35); +} +.lobby-evidence-card--common { + box-shadow: 0 0 0 2px rgba(180, 190, 200, 0.65), 0 0 16px rgba(200, 210, 220, 0.2), 0 8px 24px rgba(0, 0, 0, 0.35); +} +.lobby-evidence-card--rare { + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.85), 0 0 20px rgba(59, 130, 246, 0.35), 0 8px 24px rgba(0, 0, 0, 0.35); +} +.lobby-evidence-card--legendary { + box-shadow: 0 0 0 2px rgba(234, 179, 8, 0.9), 0 0 22px rgba(250, 204, 21, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35); +} +.lobby-evidence-card-head { + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 8px; + margin-bottom: 6px; +} +.lobby-evidence-card-icon { + flex-shrink: 0; + width: 28px; + height: 28px; + border-radius: 6px; + background: linear-gradient(135deg, rgba(0, 255, 255, 0.25), rgba(255, 0, 255, 0.15)); + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + line-height: 1; +} +.lobby-evidence-card-titles { + flex: 1; + min-width: 0; +} +.lobby-evidence-card-title-th { + font-family: 'Sarabun', 'Kanit', system-ui, sans-serif; + font-size: clamp(0.68rem, 1.35vw, 0.82rem); + font-weight: 700; + color: #e8ecff; + line-height: 1.25; + margin: 0; +} +.lobby-evidence-card-title-en { + font-family: system-ui, sans-serif; + font-size: clamp(0.58rem, 1.05vw, 0.68rem); + color: rgba(180, 190, 220, 0.85); + margin: 2px 0 0; + line-height: 1.2; +} +.lobby-evidence-card-art { + flex: 1 1 auto; + min-height: clamp(72px, 14vh, 140px); + max-height: min(22vh, 200px); + border-radius: 8px; + background: linear-gradient(160deg, rgba(30, 40, 70, 0.95), rgba(12, 16, 32, 0.98)); + border: 1px solid rgba(0, 255, 255, 0.12); + margin-bottom: 6px; + display: flex; + align-items: center; + justify-content: center; + color: rgba(0, 255, 255, 0.35); + font-size: clamp(1.5rem, 4vw, 2.25rem); + user-select: none; +} +.lobby-evidence-card-body { + font-family: 'Sarabun', 'Kanit', system-ui, sans-serif; + font-size: clamp(0.6rem, 1.15vw, 0.72rem); + color: rgba(210, 218, 240, 0.92); + line-height: 1.4; + margin: 0 0 8px; + flex-shrink: 0; + max-height: 4.5em; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; +} +.lobby-evidence-card-foot { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 8px; + margin-top: auto; + flex-shrink: 0; +} +.lobby-evidence-link { + display: flex; + flex-direction: row; + align-items: center; + gap: 6px; + min-width: 0; +} +.lobby-evidence-avatar { + width: 26px; + height: 26px; + border-radius: 50%; + background: linear-gradient(145deg, #7aa2f7, #565f89); + color: #1a1b26; + font-size: 11px; + font-weight: 800; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + box-shadow: 0 0 0 2px rgba(0, 255, 255, 0.25); +} +.lobby-evidence-link-name { + font-size: clamp(0.62rem, 1.1vw, 0.74rem); + font-weight: 600; + color: #c0caf5; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.lobby-evidence-foot-meta { + text-align: right; + flex-shrink: 0; +} +.lobby-evidence-rarity { + display: block; + font-size: clamp(0.55rem, 0.95vw, 0.65rem); + color: rgba(170, 180, 210, 0.9); + margin-bottom: 2px; +} +.lobby-evidence-stars { + font-size: clamp(0.65rem, 1.2vw, 0.78rem); + letter-spacing: 1px; + line-height: 1; +} +.lobby-evidence-card--common .lobby-evidence-stars { color: #d4d4d8; text-shadow: 0 0 8px rgba(200, 200, 210, 0.4); } +.lobby-evidence-card--rare .lobby-evidence-stars { color: #60a5fa; text-shadow: 0 0 10px rgba(59, 130, 246, 0.5); } +.lobby-evidence-card--legendary .lobby-evidence-stars { color: #fcd34d; text-shadow: 0 0 10px rgba(234, 179, 8, 0.55); } +@media (max-width: 720px) { + .lobby-evidence-cards-root { + flex-wrap: wrap; + overflow-y: auto; + align-content: flex-start; + } + .lobby-evidence-card { + flex: 1 1 100%; + max-width: none; + min-width: 0; + } +} + +/* —— กระดานอันดับ LobbyB (เหรียญ leaderboard-1/2/3 จาก Main-Lobby) —— */ +.lobby-rank-overlay { + position: fixed; + inset: 0; + z-index: 10048; + display: flex; + align-items: center; + justify-content: center; + padding: max(12px, env(safe-area-inset-top)) max(12px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left)); + box-sizing: border-box; +} +.lobby-rank-overlay.is-hidden { + display: none !important; +} +.lobby-rank-backdrop { + position: absolute; + inset: 0; + background: rgba(2, 4, 14, 0.82); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + cursor: pointer; +} +.lobby-rank-dialog { + position: relative; + z-index: 1; + width: min(96vw, 520px); + max-height: min(90vh, 720px); + pointer-events: none; +} +.lobby-rank-dialog * { + pointer-events: auto; +} +.lobby-rank-panel { + background: linear-gradient(165deg, rgba(28, 36, 58, 0.96), rgba(12, 16, 32, 0.98)); + border-radius: 16px; + border: 2px solid rgba(0, 255, 255, 0.45); + box-shadow: + 0 0 0 1px rgba(255, 0, 200, 0.25), + 0 0 32px rgba(0, 255, 255, 0.12), + 0 0 48px rgba(255, 0, 180, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.06); + padding: clamp(10px, 2.5vw, 16px); + display: flex; + flex-direction: column; + min-height: 0; + font-family: 'Kanit', 'Sarabun', system-ui, sans-serif; +} +.lobby-rank-head { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + position: relative; + padding: 6px 44px 12px 12px; + border-bottom: 1px solid rgba(0, 255, 255, 0.28); + margin-bottom: 8px; +} +.lobby-rank-case-title { + margin: 0; + font-size: clamp(0.95rem, 2.8vw, 1.15rem); + font-weight: 700; + color: #e8f4ff; + text-align: center; + text-shadow: 0 0 12px rgba(0, 255, 255, 0.35); + line-height: 1.25; +} +.lobby-rank-close { + position: absolute; + top: 2px; + right: 4px; + width: 44px; + height: 44px; + padding: 0; + border: none; + border-radius: 10px; + background: transparent; + color: rgba(0, 255, 255, 0.95); + font-size: 1.75rem; + line-height: 1; + cursor: pointer; + text-shadow: 0 0 14px rgba(0, 255, 255, 0.85); + display: flex; + align-items: center; + justify-content: center; + transition: transform 0.15s ease, filter 0.15s ease; +} +.lobby-rank-close:hover { + transform: scale(1.06); + filter: brightness(1.12); +} +.lobby-rank-podium { + display: flex; + flex-direction: row; + align-items: flex-end; + justify-content: center; + gap: clamp(6px, 2vw, 14px); + padding: 8px 4px 14px; + flex-shrink: 0; +} +.lobby-rank-ped { + flex: 1 1 0; + min-width: 0; + max-width: 150px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: 10px 6px 12px; + border-radius: 14px; + background: rgba(0, 0, 0, 0.28); + border: 1px solid rgba(0, 255, 255, 0.22); + box-sizing: border-box; +} +.lobby-rank-ped--2 { + order: 1; + min-height: 148px; +} +.lobby-rank-ped--1 { + order: 2; + min-height: 188px; + border-color: rgba(255, 215, 0, 0.45); + box-shadow: 0 0 22px rgba(255, 200, 0, 0.12); +} +.lobby-rank-ped--3 { + order: 3; + min-height: 132px; +} +.lobby-rank-crown { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 4px; + margin-bottom: 4px; + font-size: 1.1rem; + line-height: 1; + filter: drop-shadow(0 0 6px rgba(255, 215, 0, 0.6)); +} +.lobby-rank-crown-n { + font-size: 0.85rem; + font-weight: 800; + color: #ffe066; +} +.lobby-rank-medal-wrap { + height: 36px; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 6px; +} +.lobby-rank-medal-img { + width: auto; + height: 34px; + object-fit: contain; + display: block; +} +.lobby-rank-ped-avatar { + width: 48px; + height: 48px; + border-radius: 50%; + background: linear-gradient(145deg, #7aa2f7, #565f89); + color: #1a1b26; + font-size: 1.1rem; + font-weight: 800; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 6px; + box-shadow: 0 0 0 2px rgba(0, 255, 255, 0.3); + flex-shrink: 0; +} +.lobby-rank-ped--1 .lobby-rank-ped-avatar { + width: 56px; + height: 56px; + font-size: 1.25rem; +} +.lobby-rank-ped-name { + font-size: clamp(0.68rem, 2vw, 0.8rem); + font-weight: 600; + color: #e8ecff; + line-height: 1.2; + word-break: break-word; + max-width: 100%; +} +.lobby-rank-ped-score { + margin-top: 4px; + font-size: clamp(0.75rem, 2.2vw, 0.9rem); + font-weight: 700; + color: #fff; + text-shadow: 0 0 8px rgba(255, 255, 255, 0.2); +} +.lobby-rank-table-wrap { + flex: 1 1 auto; + min-height: 0; + overflow-y: auto; + overflow-x: hidden; + margin: 0 -4px; + padding: 0 4px; + scrollbar-width: thin; +} +.lobby-rank-table { + width: 100%; + border-collapse: collapse; + font-size: clamp(0.65rem, 1.9vw, 0.78rem); +} +.lobby-rank-table thead th { + text-align: left; + text-transform: uppercase; + letter-spacing: 0.06em; + color: rgba(0, 255, 255, 0.85); + font-weight: 700; + padding: 8px 6px; + border-bottom: 1px solid rgba(0, 255, 255, 0.25); + position: sticky; + top: 0; + background: linear-gradient(180deg, rgba(20, 26, 44, 0.98), rgba(20, 26, 44, 0.92)); + z-index: 1; +} +.lobby-rank-table thead th:nth-child(1) { width: 3.2rem; } +.lobby-rank-table thead th:nth-child(3) { text-align: right; width: 4rem; } +.lobby-rank-table tbody td { + padding: 7px 6px; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + color: #e2e8f0; + vertical-align: middle; +} +.lobby-rank-table tbody td:nth-child(3) { + text-align: right; + font-weight: 600; + color: #fff; +} +.lobby-rank-table .lobby-rank-row-av { + display: inline-flex; + align-items: center; + gap: 8px; + min-width: 0; +} +.lobby-rank-table .lobby-rank-mini-av { + width: 26px; + height: 26px; + border-radius: 50%; + background: linear-gradient(145deg, #9ece6a, #565f89); + color: #1a1b26; + font-size: 0.65rem; + font-weight: 800; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + box-shadow: 0 0 0 1px rgba(0, 255, 255, 0.2); +} +.lobby-rank-table .lobby-rank-row-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 180px; +} +.lobby-rank-self { + flex-shrink: 0; + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; + padding: 12px 10px 6px; + margin-top: 6px; + border-top: 1px solid rgba(255, 0, 180, 0.42); + background: linear-gradient(90deg, rgba(255, 0, 180, 0.07), transparent); +} +.lobby-rank-self-rank { + font-weight: 800; + color: #c0caf5; + min-width: 2.5rem; + font-size: clamp(0.75rem, 2vw, 0.88rem); +} +.lobby-rank-self-av { + width: 40px; + height: 40px; + border-radius: 50%; + background: linear-gradient(145deg, #f472b6, #a855f7); + color: #fff; + font-size: 1rem; + font-weight: 800; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + box-shadow: 0 0 0 2px rgba(255, 100, 200, 0.45); +} +.lobby-rank-self-meta { + flex: 1; + min-width: 0; +} +.lobby-rank-self-name { + font-size: clamp(0.85rem, 2.4vw, 1rem); + font-weight: 800; + color: #fff; + line-height: 1.2; +} +.lobby-rank-self-score { + font-size: clamp(0.85rem, 2.4vw, 1rem); + font-weight: 800; + color: #ff4ecd; + text-shadow: 0 0 12px rgba(255, 78, 205, 0.45); + flex-shrink: 0; +} + +.version-tag { + position: fixed; + right: 8px; + bottom: 4px; + left: auto; + font-size: 10px; + color: #a9b1d6; + opacity: 0.7; + pointer-events: none; +} + +/* play — quiz carry pregame (สอดคล้อง play.html) */ +.quiz-carry-pregame-card { + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + align-items: stretch; + max-width: min(94vw, 900px); + width: 100%; + max-height: min(94vh, 900px); + overflow: hidden; + background: rgba(10, 12, 26, 0.55); + border: none; + border-radius: 4px; + box-shadow: none; + pointer-events: auto; +} +.quiz-carry-pregame-footer { + flex: 0 0 auto; + padding: 0.85rem 1rem 1rem; + background: linear-gradient(180deg, rgba(8, 10, 22, 0.2), rgba(8, 10, 22, 0.96)); + border-top: none; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.65rem; +} + +/* Editor — เกมตอบคำถาม */ +.quiz-editor-wrap { + margin: 1rem 0; + padding: 1rem; + background: #24283b; + border-radius: 8px; + border: 1px solid #414868; +} +.quiz-editor-wrap h3 { + margin: 0 0 0.5rem; + font-size: 1rem; + color: #7aa2f7; +} +.quiz-questions-list { + display: flex; + flex-direction: column; + gap: 0.6rem; + margin: 0.75rem 0; +} +.quiz-q-row { + display: grid; + grid-template-columns: 1fr auto auto; + gap: 0.5rem; + align-items: center; +} +@media (max-width: 600px) { + .quiz-q-row { + grid-template-columns: 1fr; + } +} +.quiz-q-row input[type="text"] { + min-width: 0; + padding: 0.4rem 0.5rem; + border-radius: 6px; + border: 1px solid #565f89; + background: #1a1b26; + color: #c0caf5; +} +.quiz-q-row select { + padding: 0.35rem; + border-radius: 6px; + border: 1px solid #565f89; + background: #1a1b26; + color: #c0caf5; +} +.btn-quiz-add, +.quiz-q-remove { + padding: 0.35rem 0.65rem; + border-radius: 6px; + cursor: pointer; + border: 1px solid #565f89; + background: #414868; + color: #c0caf5; + font: inherit; +} +.quiz-q-remove { + font-size: 0.8rem; +} + +/* Stack Tower play — เฟรมกล้องต้อง "คงที่ทุก resolution" + cover สเกลตามด้านที่ใหญ่กว่า → จอกว้าง/เตี้ย ต่างกัน = เฟรม/ซูมเปลี่ยน (กล้องเพี้ยนเวลาเปลี่ยน resolution + บล็อกห้อย/จุดวางหลุดเฟรม) + contain = เห็นทั้งฉาก 16:9 (บล็อกห้อย+จุดวาง+หอ) เหมือนกันเป๊ะทุกจอ; แถบ letterbox กลืนสีฉาก (#0a0e22) ไม่ดูจอเสีย */ +html.play-stack-tower-pixel-canvas #play-canvas-stage.play-canvas-stage { + background: #0a0e22 !important; +} +html.play-stack-tower-pixel-canvas #play-canvas-stage #game-canvas { + object-fit: contain !important; + object-position: center center !important; + background: #0a0e22 !important; +} diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index 91df0ea..b9cb45a 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -2371,6 +2371,47 @@ ctx.restore(); } + /* ===== [2026-07-31] เติมขอบว่างด้วยอาร์ต (มือถือ/แท็บเล็ตเท่านั้น) ===== + * เกมส่วนใหญ่ fit แบบ contain → จอที่สัดส่วนไม่ตรงแมปจะเหลือขอบสีพื้น = ผู้เล่นรู้สึก "ไม่เต็มจอ" + * แก้โดยปูภาพพื้นหลังตัวเดียวกันแบบ cover + เบลอ + หรี่ ไว้ "ใต้" ฉากจริง + * ⚠️ ห้ามเอาภาพ cover ไปแทนฉากจริง — ฉากต้องล็อกกับกริดโลก (งานจัดทางเดิน QB 17 รอบอยู่บนสมมติฐานนี้) + * ตัวนี้เป็นแค่ฉากหลังที่จะถูกฉากจริงทับทั้งหมดในพื้นที่ของโลก จึงไม่กระทบพิกัดใด ๆ + * perf: เรนเดอร์ครั้งเดียวเก็บใส่ canvas สำรอง (เบลอทุกเฟรมกินแรงเกินไปสำหรับมือถือ) + * ขอบเขต: เฉพาะ pointer: coarse → บน PC ภาพยังเป็นแบบเดิมเป๊ะ */ + let _bleedCache = null; + let _bleedCoarse = null; + function playIsCoarsePointer() { + if (_bleedCoarse != null) return _bleedCoarse; + try { _bleedCoarse = !!(window.matchMedia && window.matchMedia('(pointer: coarse)').matches); } + catch (e) { _bleedCoarse = false; } + return _bleedCoarse; + } + function drawBleedBackdropPlay(ctx2, img, cw, ch, fallbackColor) { + ctx2.fillStyle = fallbackColor; + ctx2.fillRect(0, 0, cw, ch); + if (!playIsCoarsePointer()) return; + if (!img || !img.complete || !img.naturalWidth) return; + const key = (img.currentSrc || img.src || '') + '|' + cw + 'x' + ch; + if (!_bleedCache || _bleedCache.key !== key) { + try { + const off = document.createElement('canvas'); + off.width = Math.max(1, Math.round(cw)); + off.height = Math.max(1, Math.round(ch)); + const octx = off.getContext('2d'); + const s = Math.max(cw / img.naturalWidth, ch / img.naturalHeight); + const dw = img.naturalWidth * s; + const dh = img.naturalHeight * s; + try { octx.filter = 'blur(18px) brightness(0.42) saturate(0.85)'; } catch (e) { /* เบราว์เซอร์ไม่รองรับ filter */ } + octx.drawImage(img, (cw - dw) / 2, (ch - dh) / 2, dw, dh); + try { octx.filter = 'none'; } catch (e) { /* ignore */ } + octx.fillStyle = 'rgba(10, 14, 34, 0.35)'; + octx.fillRect(0, 0, off.width, off.height); + _bleedCache = { key, canvas: off }; + } catch (e) { _bleedCache = null; return; } + } + if (_bleedCache) ctx2.drawImage(_bleedCache.canvas, 0, 0, cw, ch); + } + /** กล้องมองเหนือขอบบนแมป (worldMinY<0) + ใช้รูปแผนที่ — ยัด loop ท้องฟ้าเติมครึ่งบนจอ */ function drawStackTowerLoopSkyFillAboveMap(ctx, worldMinY, zDraw, cw, ch) { if (!isStackTowerMissionUiMapPlay() || worldMinY >= 0) return; @@ -6781,9 +6822,24 @@ zDraw = Math.min(canvas.width / mwPx, canvas.height / mhPx) * 0.96; } else if (isJumpSurvive()) { /* MG5 (jump_survive) — เกมเดียวที่ตกไปใช้ zoom ดิบ 1.4 (ไม่ fit จอ = เหลือขอบซ้าย-ขวา) - → fit ความกว้างเต็มจอ (vertical scroller เลื่อนแนวตั้งด้วย jumpSurviveCamCenterY อยู่แล้ว) */ + → fit ความกว้างเต็มจอ (vertical scroller เลื่อนแนวตั้งด้วย jumpSurviveCamCenterY อยู่แล้ว) + [2026-08-02] user: "mg5 ในมือถือเห็นไม่เท่า pc 1920×1080 · ควรเห็นทั้งเกม" + สูตรเดิม `zDraw = cw / mwPx` fit **แค่แนวนอน** → แนวตั้งเห็นเท่าไรขึ้นกับความสูงจอล้วน ๆ + จอเตี้ยจึงเห็นแท่นข้างบน/ข้างล่างน้อยกว่า PC (วัดแล้วเหลือ ~81% ของ PC และแย่ลงอีกเมื่อแถบ URL กางอยู่) + แก้แบบเดียวกับ lobby/MG4: บนจอสัมผัสให้เห็น "โลกแนวตั้ง" ไม่น้อยกว่าที่เดสก์ท็อป 1920×1080 เห็น + zRef = 1920/mwPx · โลกแนวตั้งที่ PC เห็น = 1080/zRef + zDraw = min(cw/mwPx, ch / โลกแนวตั้งที่ PC เห็น) + ⇒ ได้ทั้งความกว้างเต็มแมป และแนวตั้งไม่น้อยกว่า PC (จอกว้างมากจะเหลือขอบซ้ายขวาแทน ซึ่งดีกว่ามองไม่เห็นแท่น) + ⚠️ PC ไม่กระทบ — pointer: fine คืนสูตรเดิมเป๊ะ */ const mwPx = w * tileSize; - if (mwPx > 0) zDraw = canvas.width / mwPx; + if (mwPx > 0) { + zDraw = canvas.width / mwPx; + if (playIsCoarsePointer()) { + const zRef = JS_REF_VIEW_W / mwPx; + const refVertWorld = JS_REF_VIEW_H / zRef; /* โลกแนวตั้งที่เดสก์ท็อป 1920×1080 เห็น */ + if (refVertWorld > 0) zDraw = Math.min(zDraw, canvas.height / refVertWorld); + } + } } else if (isQuizQuestionMissionRenderLockPlay()) { const qmc = getQuizQuestionMissionMapCenterWorldPxPlay(); if (qmc) { @@ -6793,9 +6849,16 @@ } else if (isQuizCarry()) { const mwPx = w * tileSize; const mhPx = h * tileSize; - zDraw = Math.min(canvas.width / mwPx, canvas.height / mhPx) * 0.96; + zDraw = quizCarryEffectiveZoomPlay(mwPx, mhPx, canvas.width, canvas.height); } else if (isQuizBattle()) { zDraw *= quizBattleUserZoomMul; + /* [2026-08-02] Quiz Battle **ไม่มีการ fit จอเลย** (ซูมดิบ × ตัวคูณของผู้ใช้) ⇒ จอเล็กเห็นโลกน้อยกว่า PC ตามส่วน + วัดได้: iPhone 13 Pro แนวนอน เห็น 67% กว้าง · 64% สูง ของเดสก์ท็อป 1920×1080 + แก้แบบเดียวกับ lobby/MG5: จอสัมผัสคูณด้วย min(1, cw/1920, ch/1080) → เห็นไม่น้อยกว่า PC + ⚠️ PC ได้ตัวคูณ 1 พอดี = ไม่ขยับ · และไม่แตะ quizBattleUserZoomMul (ผู้เล่นยังบีบซูมเองได้) */ + if (playIsCoarsePointer() && canvas.width > 0 && canvas.height > 0) { + zDraw *= Math.min(1, canvas.width / QB_REF_VIEW_W, canvas.height / QB_REF_VIEW_H); + } } else if (isGauntletCrownHeistMapPlay() && !(previewMode && editorEmbedReturn)) { /* #1 map fit: gauntlet เกมจริง — fit "ความสูงแมป (ลู่ทั้งหมด)" ให้พอดีจอ resolution-adaptive (เดิมใช้ zoom ดิบ ไม่ปรับตาม resolution = ไม่พอดี) · fit สูงอย่างเดียว เพราะ runway เลื่อนแนวนอน */ @@ -9373,11 +9436,51 @@ return !!(isDetectiveMinigamePlay() && quizCarryUseMissionSummaryOverlay()); } /** quiz_carry: จุดกลางแมป (world px) — กล้องไม่ตามตัวละคร; ใช้ร่วม draw + overlay DOM */ + /* ===== [2026-08-02] MG4 บนจอเล็ก — ซูมอย่างน้อยเท่าที่เดสก์ท็อป 1920×1080 ใช้ ===== + ปัญหา (user: "mg4 อ่านไม่รู้เรื่อง"): ป้ายคำตอบ **วาดบน canvas** และฟอนต์มีพื้นล่างตายตัว 10px + (`drawQuizCarryChoiceLabels`: `Math.max(10, Math.min(24, ts * 0.24 * ps))`) + กล่องป้ายกว้างตามความกว้างข้อความ ⇒ พอฟอนต์ติดพื้น ป้ายค้างขนาดเดิมในหน่วยพิกเซลจอ + แต่แมปหดลงตาม zoom ⇒ **ป้ายใหญ่เกินแมปจนทับกัน** + วัดจริง: เดสก์ท็อป ts≈29px (ฟอนต์ที่ควรได้ 9.0 → ใช้ 10 = เกินนิดเดียว) + iPhone 13 Pro แนวนอน ts≈9.5px (ควรได้ 2.8 → ใช้ 10 = **เกิน 3.6 เท่า**) · แนวตั้ง เกิน 4.3 เท่า + แก้ (ทางเลือก B ที่ user เคาะ): จอสัมผัสใช้ zoom ไม่ต่ำกว่าที่เดสก์ท็อป 1920×1080 ใช้ + ⇒ อัตราส่วน "ป้ายต่อช่อง" เท่ากับ PC เป๊ะ = ไม่ทับ และอ่านออก · แลกกับเห็นแมปแคบลงต้องเดินดู + ⚠️ PC ไม่กระทบเลย — `pointer: fine` คืนค่า fit เดิมทุกกรณี */ + const QUIZ_CARRY_REF_VIEW_W = 1920; + const QUIZ_CARRY_REF_VIEW_H = 1080; + /* จอเดสก์ท็อปอ้างอิงของ MG5 — ใช้เป็นเกณฑ์ "ต้องเห็นไม่น้อยกว่านี้" บนจอสัมผัส (ดู computePlayCameraZDrawPlay) */ + const JS_REF_VIEW_W = 1920; + const JS_REF_VIEW_H = 1080; + /* เกณฑ์เดียวกันสำหรับ Quiz Battle */ + const QB_REF_VIEW_W = 1920; + const QB_REF_VIEW_H = 1080; + function quizCarryFitZoomPlay(mwPx, mhPx, cw, ch) { + return Math.min(cw / mwPx, ch / mhPx) * 0.96; + } + function quizCarryEffectiveZoomPlay(mwPx, mhPx, cw, ch) { + const fit = quizCarryFitZoomPlay(mwPx, mhPx, cw, ch); + if (!playIsCoarsePointer()) return fit; + const ref = quizCarryFitZoomPlay(mwPx, mhPx, QUIZ_CARRY_REF_VIEW_W, QUIZ_CARRY_REF_VIEW_H); + return Math.max(fit, ref); + } + function getQuizCarryMapCameraWorldCenterPxPlay() { if (!mapData || mapData.gameType !== 'quiz_carry') return null; const ww = mapData.width || 20, hh = mapData.height || 15; const ts = tileSize; - return { cx: ww * ts * 0.5, cy: hh * ts * 0.5 }; + const mwPx = ww * ts, mhPx = hh * ts; + const center = { cx: mwPx * 0.5, cy: mhPx * 0.5 }; + if (!canvas || !canvas.width || !canvas.height) return center; + const fit = quizCarryFitZoomPlay(mwPx, mhPx, canvas.width, canvas.height); + const zd = quizCarryEffectiveZoomPlay(mwPx, mhPx, canvas.width, canvas.height); + if (zd <= fit + 1e-6) return center; /* แมปยังพอดีจอ → กลางแมปเหมือนเดิมเป๊ะ */ + /* ซูมเข้าจนแมปไม่พอดีแล้ว → กล้องตามตัวเรา แต่ห้ามเลื่อนจนเห็นนอกขอบแมป */ + const halfW = canvas.width / (2 * zd); + const halfH = canvas.height / (2 * zd); + const px = ((me && typeof me.x === 'number') ? me.x : ww * 0.5) * ts; + const py = ((me && typeof me.y === 'number') ? me.y : hh * 0.5) * ts; + const clamp = (v, half, span) => (half * 2 >= span ? span * 0.5 : Math.max(half, Math.min(span - half, v))); + return { cx: clamp(px, halfW, mwPx), cy: clamp(py, halfH, mhPx) }; } function isQuizBattle() { return mapData && mapData.gameType === 'quiz_battle'; } @@ -17793,6 +17896,11 @@ if (keys['ArrowRight'] || keys['KeyD']) vx += 1; if (keys['ArrowUp'] || keys['KeyW']) vy -= 1; if (keys['ArrowDown'] || keys['KeyS']) vy += 1; + /* virtual joystick (จอสัมผัส) — บังคับยานเหมือน WASD · clamp ±1 กันกดคีย์+จอยพร้อมกันแล้วเร็วเป็นสองเท่า */ + if (shouldShowVirtualJoystickPlay()) { + vx = Math.max(-1, Math.min(1, vx + (Number(quizQuestionMissionJoyVecX) || 0))); + vy = Math.max(-1, Math.min(1, vy + (Number(quizQuestionMissionJoyVecY) || 0))); + } } const moveSpd = 280; const canPilotMe = !(isSpaceShooterMissionUiMapPlay() && me.spaceShooterEliminated); @@ -20281,8 +20389,9 @@ if (jq && jumpSurviveOnGround && window.jdSound) { try { window.jdSound.playSfx('jump', 'mg5'); } catch (e) { /* ignore */ } } if (jq && jumpSurviveOnGround) { try { if (socket && myId != null) socket.emit('js-jump'); } catch (e) { /* ignore */ } } /* broadcast กระโดด → peer ได้ยินเสียง (mg5 ไม่มีสัญญาณ jump แยกใน sync) */ - /* virtual joystick (touch) — แกน x ป้อนซ้าย/ขวาเหมือนคีย์ A/D (deadzone จัดการในตัว update แล้ว) */ - const joyX = isJumpSurviveMissionHudActivePlay() ? (Number(quizQuestionMissionJoyVecX) || 0) : 0; + /* virtual joystick (touch) — แกน x ป้อนซ้าย/ขวาเหมือนคีย์ A/D (deadzone จัดการในตัว update แล้ว) + MG5 ไม่ใช้แกน y: กระโดดอยู่ที่ปุ่มกระโดดมุมขวาล่างตามเดิม */ + const joyX = shouldShowVirtualJoystickPlay() ? (Number(quizQuestionMissionJoyVecX) || 0) : 0; const moveLeftIn = !!(keys['ArrowLeft'] || keys['KeyA']) || joyX < -0.001; const moveRightIn = !!(keys['ArrowRight'] || keys['KeyD']) || joyX > 0.001; @@ -25181,6 +25290,77 @@ }); } + /** [2026-08-01] ฉากนี้ "ต้องบังคับทิศ" ไหม — ตัวตัดสินว่าจอยเสมือนควรมีอยู่ในฉากนี้หรือเปล่า + (การแสดงผลจริงถูกกรองอีกชั้นด้วย @media (pointer: coarse) ใน play.html ⇒ PC ไม่เห็น) + ไม่เอา: MG2 gauntlet (วิ่งอัตโนมัติ · มีแต่ปุ่มกระโดด) · MG3 stack (ไม่เดินเลย) + · MG7 balloon_boss (ยานลอยตามลม **ไม่มีอินพุตทิศทางในโค้ดเลย** มีแต่ปุ่มยิง) · frogger (กดทีละช่อง) */ + function playSceneUsesWalkJoystick() { + if (!mapData) return false; + if (isGauntlet() || isStack() || isBalloonBoss() || isFrogger()) return false; + return isQuiz() || isQuizCarry() || isJumpSurvive() || isSpaceShooter() || isQuizBattle() || isLobby(); + } + + /** จอยเสมือนควรโชว์ "ตอนนี้" ไหม — ต้องตรงกับช่วงที่เดินได้จริง + ไม่งั้นจะได้จอยที่กดแล้วตัวไม่ขยับ (เฟส howto/นับถอยหลัง/อ่านคำถาม/ป๊อปอัพคำถาม QB) */ + /** [2026-08-02] ตกรอบแล้วไหม — เฉพาะ MG5/MG6 ที่ "ตายแล้วบังคับอะไรไม่ได้เลย" (เดินก็ไม่ได้ ยิงก็ไม่ได้) + คืนข้อความที่จะขึ้นบนป้าย · คืนค่าว่างถ้ายังเล่นอยู่ + เหตุผล: เดิมไม่มีอะไรบอกว่าตายแล้ว ผู้เล่นอ่านว่า "ปุ่มเสีย" (user แจ้งมาเองทั้ง MG5 และ MG6) + วัดจริง MG6: ยานถูกทำลายที่วินาทีที่ 5.5-6.2 · เกมจริง 2-6 คน ต้องนั่งรอจนหมดเวลา ~83 วินาที */ + function meEliminatedNoticePlay() { + if (isJumpSurvive() && isJumpSurviveMissionHudActivePlay() && jumpSurviveEliminated) { + return 'ตกรอบแล้ว — รอเพื่อนเล่นให้จบรอบ'; + } + if (isSpaceShooter() && isSpaceShooterMissionHudActivePlay() && me && me.spaceShooterEliminated) { + return 'ยานถูกทำลาย — รอรอบจบ'; + } + return ''; + } + + /** ป้าย "ตกรอบแล้ว" + หรี่ปุ่มแอ็กชันให้เข้าชุดกับจอย (จอยหรี่เองผ่าน shouldShowVirtualJoystickPlay) */ + function syncEliminatedBannerPlay() { + const txt = meEliminatedNoticePlay(); + const on = !!txt; + const el = document.getElementById('play-eliminated-banner'); + if (el) { + el.classList.toggle('is-on', on); + el.setAttribute('aria-hidden', on ? 'false' : 'true'); + if (on) { + const t = document.getElementById('play-eliminated-text'); + if (t && t.textContent !== txt) t.textContent = txt; + } + } + /* MG5 มีปุ่มกระโดดฝั่งขวา — ตกรอบแล้วต้องหรี่+กดไม่ติดเหมือนจอย (MG6 ยิงอัตโนมัติ ไม่มีปุ่ม) */ + const jb = document.getElementById('gauntlet-crown-jump-btn'); + if (jb) jb.classList.toggle('is-inert', on); + } + + function shouldShowVirtualJoystickPlay() { + if (!playSceneUsesWalkJoystick()) return false; + if (isChatFocused()) return false; + if (meEliminatedNoticePlay()) return false; /* ตกรอบแล้ว → จอยหรี่ กดไม่ติด */ + if (isQuizCarryEmbedLobbyBlockingMovement() || isQuizCarryEmbedCountdownBlockingMovement()) return false; + if (isQuizBattleQuestionBlockingMovementPlay()) return false; + if (isQuizCarry() && quizCarryReadFreezeActive()) return false; + if (isQuiz() && isQuizQuestionMissionUiMapPlay()) return isQuizQuestionMissionHudActivePlay(); + if (isJumpSurvive() && isJumpSurviveMissionUiMapPlay()) return isJumpSurviveMissionHudActivePlay(); + if (isSpaceShooter() && isSpaceShooterMissionUiMapPlay()) return isSpaceShooterMissionHudActivePlay(); + return true; + } + + /** url ของรูปจอยที่โหลดไม่ขึ้น — จำไว้ถาวรเพื่อ **กันลูป 404 ทุกเฟรม** (sync จะไปหยิบ url เดิมซ้ำไม่รู้จบ) */ + const virtualJoystickFailedImgUrls = Object.create(null); + + /** รูปจอยตามสกินของฉาก — `btn-joystick-1/2.png` มีครบทุกโฟลเดอร์สกิน (md5 ตรงกันทั้ง 7 ณ 2026-08-01) + ฉากที่ไม่มีสกิน mock (Quiz Battle / lobby map) → ใช้ของ /img/QUESTION/ */ + function virtualJoystickAssetUrlPlay(file) { + const fb = questionMissionAssetUrl(file); + let url = fb; + try { + if (isMissionMockHudPlay()) url = missionMockHudAssetUrl(file); + } catch (e) { /* ignore */ } + return virtualJoystickFailedImgUrls[url] ? fb : url; + } + function quizQuestionMissionJoystickResetVisual() { quizQuestionMissionJoyVecX = 0; quizQuestionMissionJoyVecY = 0; @@ -25217,25 +25397,33 @@ knob.style.transform = 'translate(calc(-50% + ' + dx + 'px), calc(-50% + ' + dy + 'px))'; } - function syncQuizQuestionMissionJoystickPlay() { + function syncVirtualJoystickPlay() { const root = document.getElementById('quiz-question-mission-joystick'); if (!root) return; - const jumperOn = isJumpSurviveMissionHudActivePlay(); - const on = !!((isQuizQuestionMissionHudActivePlay() || jumperOn) && !isChatFocused()); - root.classList.toggle('is-hidden', !on); + /* [2026-08-01] แยก 2 ระดับ: + ซ่อนสนิท (.is-hidden) = ฉากนี้ไม่มีการบังคับทิศเลย (MG2/MG3/MG7) + หรี่+กดไม่ได้ (.is-inert) = ฉากนี้เดินได้ แต่ "ตอนนี้" เกมบล็อกการเดินชั่วคราว + เหตุ: user แจ้ง QB/MG4 "ขยับไม่ค่อยได้" — ต้นเหตุคือเดิมพอบล็อกแล้ว **จอยหายไปทั้งอัน** + (QB = ป๊อปอัพคำถามเปิด · MG4 = เฟสอ่านคำถามที่ freeze ทุกคน) นิ้วที่วางอยู่จึงหลุด pointer capture + ต้องยกนิ้วแล้วกดใหม่ทุกรอบ = รู้สึกเหมือนคุมไม่ได้. คงปุ่มไว้แต่หรี่ = เห็นว่า "ยังอยู่ แค่ยังเดินไม่ได้" */ + const sceneOk = playSceneUsesWalkJoystick(); + const on = sceneOk && shouldShowVirtualJoystickPlay(); + root.classList.toggle('is-hidden', !sceneOk); + root.classList.toggle('is-inert', sceneOk && !on); root.setAttribute('aria-hidden', on ? 'false' : 'true'); if (on) { - /* สลับรูป joystick ตามฉาก: jumper → /img/Jumper/, quiz คำถาม → /img/QUESTION/ (เปลี่ยน src เฉพาะตอน skin เปลี่ยน) */ - const skin = jumperOn ? 'jumper' : 'question'; + /* สลับรูป joystick ตามสกินของฉาก (เปลี่ยน src เฉพาะตอน url เปลี่ยน — ไม่ยิงโหลดซ้ำทุกเฟรม) */ + const bgUrl = virtualJoystickAssetUrlPlay('btn-joystick-1.png'); + const knobUrl = virtualJoystickAssetUrlPlay('btn-joystick-2.png'); const bg = document.getElementById('quiz-q-mission-joystick-bg'); const knobImg = document.getElementById('quiz-q-mission-joystick-knob-img'); - if (bg && bg.dataset.joySkin !== skin) { - bg.src = jumperOn ? jumperAssetUrl('btn-joystick-1.png') : questionMissionAssetUrl('btn-joystick-1.png'); - bg.dataset.joySkin = skin; + if (bg && bg.dataset.joyUrl !== bgUrl) { + bg.dataset.joyUrl = bgUrl; + bg.src = bgUrl; } - if (knobImg && knobImg.dataset.joySkin !== skin) { - knobImg.src = jumperOn ? jumperAssetUrl('btn-joystick-2.png') : questionMissionAssetUrl('btn-joystick-2.png'); - knobImg.dataset.joySkin = skin; + if (knobImg && knobImg.dataset.joyUrl !== knobUrl) { + knobImg.dataset.joyUrl = knobUrl; + knobImg.src = knobUrl; } } if (!on) { @@ -26073,6 +26261,21 @@ } /* Stack Tower (mnn93hpi): ไม่เลื่อนกล้องตาม floorWorldY — ใช้ cam จาก getStackCameraCentersPx() เหมือน Stack ทั่วไป (วางบล็อกแล้วจอไม่ไหล) */ lastPlayZDrawForInput = zDraw; + /* [2026-08-02] เปิดค่ากล้องที่ใช้วาดจริงให้ driver อ่านได้ (อ่านอย่างเดียว ไม่มีผลต่อเกม) + จำเป็นเพราะวัด "โลกที่มองเห็นกี่ช่อง" จากภาพไม่ได้ — ฉากที่เต็มจอจะคืนขนาดแมปเสมอ ไม่ว่าซูมเท่าไร + (เจอมาแล้ว: scene-view-parity-check วัด MG5 ได้ 35.0×20.0 = ขนาดแมปเป๊ะทั้งมือถือและ PC = อ่านไม่ออกว่าซูมต่างกัน) */ + try { + window.__jdPlayView = { + gameType: (mapData && mapData.gameType) || '', + zDraw, + tileSize, + cw: canvas.width, + ch: canvas.height, + tilesW: canvas.width / (tileSize * zDraw), + tilesH: canvas.height / (tileSize * zDraw), + coarse: playIsCoarsePointer(), + }; + } catch (e) { /* ignore */ } const stackTowerWorldScrollScreenY = getStackTowerWorldLayerScrollScreenOffsetYPlay(zDraw); const halfW = canvas.width / (2 * zDraw); const halfH = canvas.height / (2 * zDraw); @@ -26122,8 +26325,10 @@ ctx.drawImage(mapBackgroundImg, (canvas.width - _bbDw) / 2, (canvas.height - _bbDh) / 2, _bbDw, _bbDh); } else if (mapBackgroundImg && mapBackgroundImg.complete && mapBackgroundImg.naturalWidth) { /* กล้องเห็นพื้นที่นอก [0,map] ได้ — ห้ามสุ่มต้นทาง drawImage เกินขอบภาพ (จะเกิดซ้ำ/เส้นตัด/ซ้อนกันที่ขอบจอ) */ - ctx.fillStyle = (isSpaceShooter() || isBalloonBoss()) ? '#0a0e22' : '#1a1b26'; - ctx.fillRect(0, 0, canvas.width, canvas.height); + /* [2026-07-31] แทน fillRect สีพื้นเปล่า ๆ ด้วยฉากหลังเบลอจากภาพเดียวกัน (เฉพาะจอสัมผัส) + → ขอบว่างจากการ fit แบบ contain ไม่เป็นแถบทึบอีก · ฉากจริงวาดทับด้านล่างนี้ตามพิกัดโลกเหมือนเดิม */ + drawBleedBackdropPlay(ctx, mapBackgroundImg, canvas.width, canvas.height, + (isSpaceShooter() || isBalloonBoss()) ? '#0a0e22' : '#1a1b26'); drawStackTowerLoopSkyFillAboveMap(ctx, worldMinY, zDraw, canvas.width, canvas.height); const natW = mapBackgroundImg.naturalWidth; const natH = mapBackgroundImg.naturalHeight; @@ -27081,7 +27286,8 @@ } drawQuizTfScorePopupsLayer(ctx, worldToScreen, zDraw, timeMs); syncPlayCyberHud(); - syncQuizQuestionMissionJoystickPlay(); + syncVirtualJoystickPlay(); + syncEliminatedBannerPlay(); syncQuizCarryGrabButton(); syncGauntletCrownJumpButton(); syncStackTowerDropButtonPlay(); @@ -27538,9 +27744,11 @@ if (keys['ArrowRight'] || keys['KeyD']) kx += 1; if (keys['ArrowUp'] || keys['KeyW']) ky -= 1; if (keys['ArrowDown'] || keys['KeyS']) ky += 1; + /* virtual joystick (จอสัมผัส) — ป้อนทิศเหมือนคีย์ WASD ให้ทุกฉากที่ใช้ลูปเดินนี้ + (MG1 quiz · MG4 quiz_carry · Quiz Battle · lobby map) */ let jx = 0; let jy = 0; - if (isQuizQuestionMissionHudActivePlay()) { + if (shouldShowVirtualJoystickPlay()) { jx = quizQuestionMissionJoyVecX; jy = quizQuestionMissionJoyVecY; } @@ -27561,7 +27769,17 @@ const antiStuckGame = !pathStrict && (isQuiz() || isQuizCarry()); let normalMoved = false; if (pathStrict) { - const moved = quizBattleTryStepMovePlay(me.x, me.y, tox, toy, (nx, ny, ox, oy) => canWalkLikeLobby(nx, ny, ox, oy)); + const canWalkQb = (nx, ny, ox, oy) => canWalkLikeLobby(nx, ny, ox, oy); + const moved = quizBattleTryStepMovePlay(me.x, me.y, tox, toy, canWalkQb); + /* [2026-08-01] ❌ **เคยลองเพิ่ม "ไถลตามผนัง" ตรงนี้แล้วถอดออก — อย่าใส่กลับโดยไม่แก้แผนที่ก่อน** + เหตุผลที่อยากใส่: ก้าวทแยงที่ชนขอบเลนตันทั้งก้าว (สาขานี้ไม่มี fallback รายแกนเหมือนฉากอื่น) + เลน QB สูง 3 แถว กล่องชนสูง 1.35 → นิ้วบนจอยที่เอียงตลอดเวลารู้สึกว่าเดินไม่ค่อยได้ + เหตุผลที่ต้องถอด (วัดด้วย A/B บนเครื่องจริง `justice-qb-playall` 10 ห้อง): + ไม่มีไถล = **10/10, 10/10** · มีไถล (สองแกน) = 7/10, 9/10 · มีไถล (แกนหลักอย่างเดียว) = 8/10, 9/10 + ทุกห้องที่ล้ม **จบที่ (11,6) เหมือนกันเป๊ะ** = มุมขวาสุดของเลนแถว 6 + ต้นเหตุจริงอยู่ที่ **รูปร่างแผนที่**: แถว 4-6 กว้าง x1-11 แต่ทางลง (แถว 7) กว้างแค่ x2-10 + ⇒ x=11 บนแถว 6 เป็น "กระเป๋าตัน" (กดลงไม่ลง) · การไถลทำให้ไหลเข้าไปติดง่ายมาก + ถ้าจะเอาการไถลกลับมา ต้องแก้แผนที่ให้แถว 6 กับทางลงกว้างเท่ากันก่อน (งานข้อมูล ปลอดภัยกว่าแก้ฟิสิกส์) */ me.x = moved.x; me.y = moved.y; normalMoved = true; @@ -27731,26 +27949,66 @@ }); })(); - (function wireQuizQuestionMissionJoystick() { + /* [2026-08-01] "เครื่องที่ไม่ได้โฟกัสจบไม่พร้อมเครื่องอื่น" (MG2) + ต้นเหตุ: เบราว์เซอร์หยุด requestAnimationFrame ทั้งหมดเมื่อแท็บถูกซ่อน → ตัวตัดสิน "จบเกม" ของ MG2 + ซึ่งอยู่ใน tickGauntletCrownRunwayBgPlay() (ทั้งเส้นทาง "ตกขอบหมด" และ "ถึงเส้นชัย") ไม่ถูกเรียกเลย + เครื่องนั้นจึงต้องรอ event จาก server ที่มี grace 3 วิ = จบช้ากว่าเพื่อนเห็น ๆ + แก้: ระหว่างถูกซ่อน เดินลูปเดิมด้วย setInterval แทน — timer ในแท็บพื้นหลังถูก clamp (~1 วิ) แต่ยังทำงาน + และ `gauntlet-sync` ทาง socket ยังเข้ามาเต็มอัตรา → state สดพอให้ตัดสินได้ตรงจังหวะกับเครื่องอื่น + กลับมาแสดงผลเมื่อไหร่ ปล่อยให้ rAF คุมต่อทันที (กันเดินลูปซ้อนสองทาง) */ + let hiddenRunwayHeartbeatTimer = null; + let hiddenRunwayHeartbeatLastMs = 0; + function stopHiddenRunwayHeartbeatPlay() { + if (hiddenRunwayHeartbeatTimer) { + clearInterval(hiddenRunwayHeartbeatTimer); + hiddenRunwayHeartbeatTimer = null; + } + hiddenRunwayHeartbeatLastMs = 0; + } + function startHiddenRunwayHeartbeatPlay() { + if (hiddenRunwayHeartbeatTimer) return; + hiddenRunwayHeartbeatLastMs = performance.now(); + hiddenRunwayHeartbeatTimer = setInterval(function () { + if (typeof document !== 'undefined' && !document.hidden) { stopHiddenRunwayHeartbeatPlay(); return; } + if (!mapData || !isGauntlet()) return; + const now = performance.now(); + const dt = Math.min(0.5, Math.max(0, (now - hiddenRunwayHeartbeatLastMs) / 1000)); + hiddenRunwayHeartbeatLastMs = now; + try { tickGauntletCrownRunwayBgPlay(dt); } catch (_e) { /* ignore */ } + }, 250); + } + if (typeof document !== 'undefined') { + document.addEventListener('visibilitychange', function () { + if (document.hidden) startHiddenRunwayHeartbeatPlay(); + else stopHiddenRunwayHeartbeatPlay(); + }); + } + + (function wireVirtualJoystickPlay() { const base = document.getElementById('quiz-q-mission-joystick-base'); const bg = document.getElementById('quiz-q-mission-joystick-bg'); const knobImg = document.getElementById('quiz-q-mission-joystick-knob-img'); if (!base) return; - if (bg) { - bg.src = questionMissionAssetUrl('btn-joystick-1.png'); - bg.dataset.joySkin = 'question'; - bg.onerror = function () { - this.onerror = null; - this.removeAttribute('src'); + /* สกินไหนไม่มีไฟล์ → จำ url ที่พังไว้ (กัน sync หยิบซ้ำทุกเฟรม) แล้วตกไปใช้ของ /img/QUESTION/ ซึ่งมีแน่ */ + const fallbackJoyImg = function (file) { + return function () { + const failed = this.dataset.joyUrl || this.getAttribute('src') || ''; + if (failed) virtualJoystickFailedImgUrls[failed] = 1; + const fb = questionMissionAssetUrl(file); + if (failed === fb) { this.onerror = null; this.removeAttribute('src'); return; } + this.dataset.joyUrl = fb; + this.src = fb; }; + }; + if (bg) { + bg.dataset.joyUrl = questionMissionAssetUrl('btn-joystick-1.png'); + bg.src = bg.dataset.joyUrl; + bg.onerror = fallbackJoyImg('btn-joystick-1.png'); } if (knobImg) { - knobImg.src = questionMissionAssetUrl('btn-joystick-2.png'); - knobImg.dataset.joySkin = 'question'; - knobImg.onerror = function () { - this.onerror = null; - this.removeAttribute('src'); - }; + knobImg.dataset.joyUrl = questionMissionAssetUrl('btn-joystick-2.png'); + knobImg.src = knobImg.dataset.joyUrl; + knobImg.onerror = fallbackJoyImg('btn-joystick-2.png'); } function endJoy(e) { if (quizQuestionMissionJoyPointerId == null || e.pointerId !== quizQuestionMissionJoyPointerId) return; @@ -27761,7 +28019,7 @@ quizQuestionMissionJoystickResetVisual(); } base.addEventListener('pointerdown', (e) => { - if (!(isQuizQuestionMissionHudActivePlay() || isJumpSurviveMissionHudActivePlay()) || isChatFocused()) return; + if (!shouldShowVirtualJoystickPlay()) return; if (e.button != null && e.button !== 0) return; e.preventDefault(); try { @@ -27991,6 +28249,48 @@ resizeCanvas(); draw(); }); + /** [2026-07-31] วัดขนาดใหม่ให้ครบทุกเหตุที่ "จอเปลี่ยนแต่ resize ไม่บอกความจริง" บนมือถือ + * - orientationchange: เดิมไม่ได้ผูกกับแคนวาสหลักเลย (ที่มีอยู่เป็นของ HUD MG1 คนละตัว) + * - visualViewport.resize: แถบ URL ยุบ/กาง จอสูงเปลี่ยนโดยไม่มี window resize ในบางเบราว์เซอร์ + * ทั้งสองเหตุ เบราว์เซอร์มือถือรายงานขนาด "ค่าเก่า" อยู่ 1-2 เฟรม → วัดซ้ำอีก 2 จังหวะ + * (rAF ถัดไป + 250ms) กันค่าค้าง · กันเรียกซ้อนด้วย flag ตัวเดียว */ + (function setupPlayViewportChangeRemeasure() { + let pending = false; + const remeasure = () => { + if (!mapData || !canvas) return; + resizeCanvas(); + draw(); + }; + const schedule = () => { + remeasure(); + if (pending) return; + pending = true; + requestAnimationFrame(() => { remeasure(); }); + setTimeout(() => { pending = false; remeasure(); }, 250); + }; + window.addEventListener('orientationchange', schedule); + try { + if (window.visualViewport && window.visualViewport.addEventListener) { + window.visualViewport.addEventListener('resize', schedule); + } + } catch (e) { /* เบราว์เซอร์เก่าไม่มี visualViewport — resize เดิมยังทำงานอยู่ */ } + })(); + /** [2026-07-31] hint ชวนหมุนจอ — การ "แสดง/ซ่อน" คุมด้วย CSS ล้วน + * (@media orientation: portrait and pointer: coarse) เดสก์ท็อปจึงไม่มีทางเห็น โดยไม่ต้อง sniff อุปกรณ์ + * JS ทำแค่เรื่องเดียว: จำว่าผู้เล่นกด "ข้าม" แล้ว จะได้ไม่ขึ้นกวนซ้ำในรอบเล่นเดียวกัน */ + (function setupRotateHintDismiss() { + const KEY = 'jdRotateHintOff'; + try { if (sessionStorage.getItem(KEY) === '1') document.documentElement.classList.add('rotate-hint-off'); } + catch (e) { /* private mode ปิด sessionStorage — ปล่อยให้ hint ขึ้นตามปกติ */ } + const btn = document.getElementById('rotate-hint-close'); + if (!btn) return; + btn.addEventListener('click', (ev) => { + ev.preventDefault(); + ev.stopPropagation(); + document.documentElement.classList.add('rotate-hint-off'); + try { sessionStorage.setItem(KEY, '1'); } catch (e) { /* ignore */ } + }); + })(); /** แคนวาส flex ขยายทีหลัง (จอใหญ่ / editor iframe) — ResizeObserver จับได้ดีกว่า resize อย่างเดียว */ (function setupPlayCanvasStackResizeObserver() { const stack = document.getElementById('play-canvas-stack'); diff --git a/www/html/Game/public/js/room-lobby.js b/www/html/Game/public/js/room-lobby.js index a157516..98d9db8 100644 --- a/www/html/Game/public/js/room-lobby.js +++ b/www/html/Game/public/js/room-lobby.js @@ -1338,10 +1338,38 @@ let lobbyLastTickTs = 0; /* timestamp เฟรมก่อน (ms) ใช้คำนวณ dt */ let lastMoveSend = 0; const moveCodes = ['KeyW', 'KeyA', 'KeyS', 'KeyD', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']; + /* [2026-08-01] virtual joystick มุมซ้ายล่าง (จอสัมผัสเท่านั้น — การแสดงผลคุมด้วย @media (pointer: coarse) ใน room-lobby.html) + ทั้ง LobbyA และ LobbyB ต้องเดิน → ใช้จอยชุดเดียวกับ play.html (คลาส/ไอดีเดียวกัน) */ + let lobbyJoyVecX = 0; + let lobbyJoyVecY = 0; + let lobbyJoyPointerId = null; let lobbyInteractPulse = null; - /* มือถือจอแคบ → zoom ต่ำลง ให้เห็นพื้นที่ lobby กว้างขึ้น (PC ย่อส่วน) · PC คงเดิม 1.2 */ - let lobbyZoom = (typeof window !== 'undefined' && (window.innerWidth || 0) > 0 && window.innerWidth < 600) ? 0.85 : 1.2; - const LOBBY_ZOOM_MIN = 0.4; + /* [2026-08-02] zoom ของ lobby — user: "iPhone 13 Pro แนวนอน ซูมมากไป อยากเห็นเท่า desktop 1920×1080" + ของเดิมเป็นค่าคงที่ (`innerWidth < 600 ? 0.85 : 1.2`) ไม่ผูกกับขนาดจอเลย + iPhone 13 Pro แนวนอน (750×342) จึงได้ 1.2 เท่าเดสก์ท็อป แต่จอเล็กกว่า ⇒ วัดได้ว่าเห็นโลกแค่ + **39% ของความกว้าง · 32% ของความสูง** ที่เดสก์ท็อป 1920×1080 เห็น + แก้: บนจอสัมผัส คิด zoom ให้ "พื้นที่โลกที่เห็น" เท่าเดสก์ท็อป 1920×1080 + zoom = 1.2 × min(1, vw/1920, vh/1080) → iPhone 13 Pro ได้ ≈ 0.380 (ตรงกับที่วัดไว้) + ⚠️ PC ไม่แตะ — `pointer: fine` คืน 1.2 เท่าเดิมทุกกรณี (กฎ "ห้ามกระทบการเล่นบน PC") */ + const LOBBY_ZOOM_DESKTOP = 1.2; + const LOBBY_VIEW_REF_W = 1920; + const LOBBY_VIEW_REF_H = 1080; + function lobbyDefaultZoom() { + try { + if (typeof window === 'undefined') return LOBBY_ZOOM_DESKTOP; + const coarse = !!(window.matchMedia && window.matchMedia('(pointer: coarse)').matches); + if (!coarse) return LOBBY_ZOOM_DESKTOP; + const vw = Math.max(1, window.innerWidth || 0); + const vh = Math.max(1, window.innerHeight || 0); + const k = Math.min(1, vw / LOBBY_VIEW_REF_W, vh / LOBBY_VIEW_REF_H); + return Math.max(0.2, LOBBY_ZOOM_DESKTOP * k); + } catch (e) { return LOBBY_ZOOM_DESKTOP; } + } + let lobbyZoom = lobbyDefaultZoom(); + /** ผู้เล่นหมุนล้อ/ซูมเองแล้วหรือยัง — ถ้าเองแล้ว ห้ามไปคำนวณทับตอนหมุนจอ */ + let lobbyZoomUserSet = false; + /* เพดานล่างต้องไม่ตัดค่า default ทิ้ง (จอเล็กมากคำนวณได้ต่ำกว่า 0.4) */ + const LOBBY_ZOOM_MIN = Math.min(0.4, lobbyDefaultZoom()); const LOBBY_ZOOM_MAX = 2.5; let mapTransform = { offsetX: 0, offsetY: 0, ts: 32, w: 20, h: 15 }; /** true เฉพาะช่องพิมพ์ข้อความ — ไม่รวม READY / แผนที่ (ให้กด F โต้ตอบได้โดยไม่ต้องกดพร้อมก่อน) */ @@ -1496,6 +1524,8 @@ const meY = (me && typeof me.y === 'number') ? me.y : 1; const ts = tileSize * lobbyZoom; mapTransform = { cw, ch, lobbyZoom, tileSize, meX, meY, w, h }; + /* เปิดค่าที่ใช้วาดให้ตรวจได้จากภายนอก (driver วัด "โลกที่มองเห็นกี่ช่อง") — อ่านอย่างเดียว ไม่มีผลต่อเกม */ + try { window.__jdLobbyView = { zoom: lobbyZoom, tileSize, cw, ch, tilesW: cw / (tileSize * lobbyZoom), tilesH: ch / (tileSize * lobbyZoom) }; } catch (e) { /* ignore */ } ctx.fillStyle = '#303770'; ctx.fillRect(0, 0, cw, ch); @@ -2310,7 +2340,16 @@ var byWidth = rect.width / baseWidth; var byHeight = rect.height / baseHeight; var targetScale = 1.08; - var scale = Math.max(0.56, Math.min(targetScale, Math.min(byWidth, byHeight) * targetScale)); + /* ⚠️ ห้ามคูณ targetScale เข้าไปในค่า "พอดีจอ" — targetScale คือ **เพดานขยายบนจอใหญ่** ไม่ใช่ตัวคูณ + ของเดิมคิด fit = min(byW,byH) × 1.08 ⇒ จอสูง 342px ได้ 0.38×1.08 = 0.41 → เนื้อหาสูง 369px = ยังล้น + ที่ถูกคือ fit = min(byW,byH) ตรง ๆ ⇒ 0.38 → 342px พอดีจอ · จอใหญ่ยังโดน clamp ที่ 1.08 เหมือนเดิม */ + var fit = Math.min(byWidth, byHeight); + /* [2026-08-02] เดิมมีพื้นล่างตายตัว `Math.max(0.56, …)` + จอเตี้ย (iPhone แนวนอน + แถบ URL/บุ๊กมาร์กกินความสูง เหลือ ~342px) ต้องการแค่ ~0.41 จึงพอดีจอ + แต่ถูกดันขึ้นเป็น 0.56 ⇒ เนื้อหาสูง 0.56×900 = 504px ในจอสูง 342px = **การ์ดคดีโดนตัดขอบล่าง** + (user ส่งภาพจากเครื่องจริงมายืนยัน) · แก้: พื้นล่างห้ามดันจนล้นจอ เหลือแค่กันเล็กเกินอ่านไม่ออก + PC ไม่กระทบ — จอใหญ่ fit > 1.08 อยู่แล้ว ค่าจึงถูก clamp ที่ targetScale เหมือนเดิม */ + var scale = Math.max(0.25, Math.min(targetScale, fit)); preplayStepCase.style.setProperty('--lobby-preplay-case-scale', scale.toFixed(4)); } @@ -2519,7 +2558,11 @@ wrapper ตั้ง aspect-ratio ไว้ → ถ้าคดีไหนไม่มีไฟล์ข้อความ (404) ซ่อนแค่รูป ปุ่มไม่เลื่อน */ ov.innerHTML = '' + - '
' + + /* [2026-08-02] เดิมยึด `top:75%` + ความสูงล็อกตามอัตราส่วนจากความกว้าง + จอเตี้ยกว้าง (iPhone แนวนอน) → กล่องสูงเกินที่เหลือ ⇒ ตัวหนังสือกับปุ่ม "ถัดไป" ตกใต้ขอบล่าง + แก้เป็น **ยึดขอบล่าง** + คุมความสูงสูงสุด: บนเดสก์ท็อป 1920×1080 ตำแหน่งเท่าเดิมเป๊ะ + (top 75% ของ 1080 = 810 · กล่องสูง 233 ⇒ ห่างขอบล่าง 37px = 3.4%) แต่จอเตี้ยจะไม่มีวันล้น */ + '
' + '' + '
+ +
+ + หมุนจอเป็นแนวนอนจะเห็นภาพเต็มกว่า + +
@@ -5055,6 +5192,14 @@
+ +