update flow design

This commit is contained in:
2026-05-27 13:56:57 +00:00
parent 841995e2f9
commit 27ca643995
481 changed files with 4369 additions and 549 deletions
@@ -0,0 +1,331 @@
/**
* แฟ้มหลักฐาน LobbyB — layout 06-3-evidence-view (ev-*)
* Design canvas: 1920 × 1080
*/
#lobby-evidence-overlay {
--ev-w: 1920;
--ev-h: 1080;
position: fixed;
inset: 0;
z-index: 10047;
overflow: hidden;
font-family: 'Kanit', 'Noto Sans Thai', system-ui, sans-serif;
color: #1c2235;
background: transparent;
}
#lobby-evidence-overlay.is-hidden {
display: none !important;
}
#lobby-evidence-overlay .lobby-evidence-backdrop {
position: absolute;
inset: 0;
background: rgba(4, 8, 22, 0.9);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
cursor: pointer;
z-index: 0;
}
#lobby-evidence-overlay .stage-wrap {
position: absolute;
inset: 0;
z-index: 1;
overflow: hidden;
pointer-events: none;
}
#lobby-evidence-overlay .stage-wrap * {
pointer-events: auto;
}
#lobby-evidence-overlay .ev-stage {
position: absolute;
left: 0;
top: 0;
width: calc(var(--ev-w) * 1px);
height: calc(var(--ev-h) * 1px);
transform-origin: 0 0;
will-change: transform;
background: transparent;
}
#lobby-evidence-overlay .layer {
position: absolute;
box-sizing: border-box;
}
#lobby-evidence-overlay .ev-bg-fallback {
inset: 0;
/* background: radial-gradient(ellipse at 50% 35%, #1c2547 0%, #0a0f24 60%, #04050d 100%); */
pointer-events: none;
}
#lobby-evidence-overlay .ev-popup {
left: calc(118 / var(--ev-w) * 100%);
top: calc(58 / var(--ev-h) * 100%);
width: calc(1684 / var(--ev-w) * 100%);
height: calc(963 / var(--ev-h) * 100%);
pointer-events: none;
}
#lobby-evidence-overlay .ev-popup img {
display: block;
width: 100%;
height: 100%;
object-fit: fill;
pointer-events: none;
user-select: none;
-webkit-user-drag: none;
}
#lobby-evidence-overlay .ev-close {
left: calc(1640 / var(--ev-w) * 100%);
top: calc(145 / var(--ev-h) * 100%);
width: calc(90 / var(--ev-w) * 100%);
height: calc(90 / var(--ev-h) * 100%);
padding: 0;
margin: 0;
border: none;
border-radius: 14px;
cursor: pointer;
background: transparent;
}
#lobby-evidence-overlay .ev-close:hover,
#lobby-evidence-overlay .ev-close:focus-visible {
background: transparent;
box-shadow: none;
}
#lobby-evidence-overlay .ev-tabs {
left: calc(220 / var(--ev-w) * 100%);
top: calc(200 / var(--ev-h) * 100%);
width: calc(1481 / var(--ev-w) * 100%);
height: calc(129 / var(--ev-h) * 100%);
}
#lobby-evidence-overlay .ev-tab {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: fill;
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
user-select: none;
-webkit-user-drag: none;
}
#lobby-evidence-overlay .ev-tab.is-active {
opacity: 1;
}
#lobby-evidence-overlay .ev-tab-click {
position: absolute;
top: calc(5 / var(--ev-h) * 100%);
height: calc(110 / var(--ev-h) * 100%);
width: calc(240 / var(--ev-w) * 100%);
padding: 0;
margin: 0;
border: none;
background: transparent;
cursor: pointer;
border-radius: 8px;
}
#lobby-evidence-overlay .ev-tab-click[data-evidence-tab="0"] {
left: 0;
}
#lobby-evidence-overlay .ev-tab-click[data-evidence-tab="1"] {
left: calc(260 / var(--ev-w) * 100%);
}
#lobby-evidence-overlay .ev-tab-click[data-evidence-tab="2"] {
left: calc(520 / var(--ev-w) * 100%);
}
#lobby-evidence-overlay .ev-tab-click:focus-visible {
outline: 2px solid rgba(0, 255, 255, 0.9);
outline-offset: 2px;
}
#lobby-evidence-overlay .ev-cards {
left: calc(270 / var(--ev-w) * 100%);
top: calc(380 / var(--ev-h) * 100%);
width: calc(940 / var(--ev-w) * 100%);
height: calc(560 / var(--ev-h) * 100%);
display: flex;
gap: calc(24 / var(--ev-w) * 100%);
pointer-events: none;
}
#lobby-evidence-overlay .ev-card {
position: relative;
flex: 1 1 0;
min-width: 0;
height: 100%;
border-radius: 14px;
background: linear-gradient(180deg, #cfd5dd 0%, #b2bac4 100%);
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
overflow: hidden;
pointer-events: auto;
}
#lobby-evidence-overlay .ev-card.rarity-common {
border: 4px solid #9aa3b2;
}
#lobby-evidence-overlay .ev-card.rarity-rare {
border: 4px solid #6cc7ff;
background: linear-gradient(180deg, #d2dde7 0%, #adbecd 100%);
box-shadow: 0 0 24px rgba(80, 175, 240, 0.35);
}
#lobby-evidence-overlay .ev-card.rarity-legendary {
border: 4px solid #f1b94a;
background: linear-gradient(180deg, #e4d3a8 0%, #c7a667 100%);
box-shadow: 0 0 28px rgba(241, 185, 74, 0.55);
}
#lobby-evidence-overlay .ev-card-head {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
background: rgba(255, 255, 255, 0.55);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
flex-shrink: 0;
}
#lobby-evidence-overlay .ev-card-head .icon {
width: 34px;
height: 34px;
border-radius: 8px;
background: rgba(0, 0, 0, 0.55);
display: grid;
place-items: center;
color: #fff;
font-size: 18px;
font-weight: 700;
flex-shrink: 0;
}
#lobby-evidence-overlay .ev-card-head .name {
line-height: 1.05;
min-width: 0;
}
#lobby-evidence-overlay .ev-card-head .name .th {
font-size: 18px;
font-weight: 700;
margin: 0;
}
#lobby-evidence-overlay .ev-card-head .name .en {
font-size: 12px;
font-weight: 500;
color: #444;
margin: 0;
}
#lobby-evidence-overlay .ev-card-art {
flex: 1 1 auto;
min-height: 120px;
margin: 8px;
border-radius: 8px;
background: #707a8a;
color: rgba(255, 255, 255, 0.55);
font-size: 14px;
font-weight: 600;
display: grid;
place-items: center;
text-align: center;
}
#lobby-evidence-overlay .ev-card-desc {
padding: 8px 12px 6px;
font-size: 13px;
font-weight: 500;
color: #2a2f3c;
line-height: 1.35;
flex-shrink: 0;
text-align: center;
margin: 0;
}
#lobby-evidence-overlay .ev-card-link-wrap {
margin: 6px 8px 10px;
flex-shrink: 0;
}
#lobby-evidence-overlay .ev-card-link {
margin: 0 0 6px;
padding: 6px 8px;
border-radius: 8px;
background: linear-gradient(180deg, #e8edf3 0%, #c8cfdb 100%);
border: 1px solid rgba(0, 0, 0, 0.18);
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
#lobby-evidence-overlay .ev-card-link:last-child {
margin-bottom: 0;
}
#lobby-evidence-overlay .ev-card-link .label {
font-size: 11px;
font-weight: 700;
color: #2a2f3c;
}
#lobby-evidence-overlay .ev-card-link .stars {
color: #c79e3a;
font-size: 11px;
font-weight: 700;
}
#lobby-evidence-overlay .ev-card-link .suspect {
display: flex;
align-items: center;
gap: 6px;
width: 100%;
background: rgba(255, 255, 255, 0.7);
padding: 4px 8px;
border-radius: 6px;
box-sizing: border-box;
}
#lobby-evidence-overlay .ev-card-link .suspect .avatar {
width: 22px;
height: 22px;
border-radius: 50%;
background: #4a5566;
color: #fff;
font-size: 11px;
font-weight: 800;
display: grid;
place-items: center;
flex-shrink: 0;
}
#lobby-evidence-overlay .ev-card-link .suspect .sname {
font-size: 13px;
font-weight: 700;
}
#lobby-evidence-overlay .visually-hidden {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
}
+1 -294
View File
@@ -1758,300 +1758,7 @@ body.room-lobby--quiz-active .lobby-b-extra-row {
}
}
/* —— แฟ้มหลักฐาน 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 — ดู css/evidence-view-overlay.css (layout ev-*) */
/* กระดานอันดับ LobbyB — ดู css/leaderboard-popup.css */
@@ -0,0 +1,944 @@
/**
* ห้องสรุปหลักฐาน — layout 11-1-2-evidence-summary-3 (es3-*)
* Design canvas: 1920 × 1080
*/
#testimony-overlay {
--es3-w: 1920;
--es3-h: 1080;
--sc: '/Main-Lobby/IMAGE/Showcard/';
position: fixed;
inset: 0;
z-index: 9000;
display: flex;
align-items: flex-start;
justify-content: center;
overflow: hidden;
font-family: 'Kanit', 'Noto Sans Thai', system-ui, sans-serif;
color: #e7ecff;
background: #04050d;
}
#testimony-overlay.is-hidden {
display: none !important;
}
#testimony-overlay .stage-wrap {
position: relative;
width: 100%;
height: 100%;
min-height: 100dvh;
display: flex;
align-items: flex-start;
justify-content: center;
overflow: hidden;
}
#testimony-overlay .es3-stage {
position: relative;
width: calc(var(--es3-w) * 1px);
height: calc(var(--es3-h) * 1px);
flex-shrink: 0;
transform-origin: top center;
background: #04050d;
}
#testimony-overlay .layer {
position: absolute;
box-sizing: border-box;
}
#testimony-overlay .layer.btn,
#testimony-overlay .es3-card,
#testimony-overlay .ev-tab-click {
pointer-events: auto;
}
/* พื้นหลังเต็มจอ */
#testimony-overlay .es3-bg {
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
}
#testimony-overlay .es3-bg img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
/* ส่วนบน: popup CSS */
#testimony-overlay .es3-top-popup {
left: calc(50 / var(--es3-w) * 100%);
top: calc(25 / var(--es3-h) * 100%);
width: calc(1820 / var(--es3-w) * 100%);
height: calc(295 / var(--es3-h) * 100%);
background: linear-gradient(180deg, rgba(28, 50, 90, 0.55) 0%, rgba(15, 30, 60, 0.55) 100%);
border: 2px solid #5bd8ff;
border-radius: 26px;
box-shadow: inset 0 0 36px rgba(80, 180, 240, 0.18), 0 0 24px rgba(80, 180, 240, 0.35);
z-index: 2;
pointer-events: none;
}
#testimony-overlay .es3-top-popup .corner {
position: absolute;
width: calc(86 / var(--es3-w) * 100%);
height: calc(86 / var(--es3-h) * 100%);
pointer-events: none;
}
#testimony-overlay .es3-top-popup .c-tl {
top: calc(-5 / var(--es3-h) * 100%);
left: calc(-5 / var(--es3-w) * 100%);
border-top-left-radius: 26px;
}
#testimony-overlay .es3-top-popup .c-tr {
top: calc(-5 / var(--es3-h) * 100%);
right: calc(-5 / var(--es3-w) * 100%);
border-top-right-radius: 26px;
}
#testimony-overlay .es3-top-popup .c-bl {
bottom: calc(-5 / var(--es3-h) * 100%);
left: calc(-5 / var(--es3-w) * 100%);
border-bottom-left-radius: 26px;
}
#testimony-overlay .es3-top-popup .c-br {
bottom: calc(-5 / var(--es3-h) * 100%);
right: calc(-5 / var(--es3-w) * 100%);
border-bottom-right-radius: 26px;
}
#testimony-overlay .es3-popup-tab {
position: absolute;
left: 50%;
top: calc(-22 / var(--es3-h) * 100%);
transform: translateX(-50%);
padding: 8px 70px;
background: linear-gradient(180deg, #2a5588 0%, #1a3a6a 100%);
border: 2px solid #5bd8ff;
border-radius: 14px;
font-weight: 700;
font-size: 22px;
color: #d6e7ff;
text-shadow: 0 0 8px rgba(120, 200, 255, 0.5);
box-shadow: 0 0 14px rgba(80, 180, 240, 0.4), inset 0 0 8px rgba(80, 180, 240, 0.25);
white-space: nowrap;
z-index: 5;
letter-spacing: 0.5px;
}
/* suspect */
#testimony-overlay .es3-suspect {
left: calc(90 / var(--es3-w) * 100%);
top: calc(38 / var(--es3-h) * 100%);
width: calc(215 / var(--es3-w) * 100%);
height: calc(213 / var(--es3-h) * 100%);
z-index: 5;
}
#testimony-overlay .es3-suspect-frame {
position: absolute;
inset: 0;
pointer-events: none;
}
#testimony-overlay .es3-suspect-frame > img {
width: 100%;
height: 100%;
object-fit: fill;
}
#testimony-overlay .es3-suspect-portrait {
position: absolute;
left: calc(26 / 215 * 100%);
top: calc(36 / 213 * 100%);
width: calc(163 / 215 * 100%);
height: calc(138 / 213 * 100%);
border-radius: 4px;
overflow: hidden;
z-index: 1;
background: radial-gradient(circle at 50% 30%, #b89cbf 0%, #6a4d7a 60%, #2b1a36 100%);
}
#testimony-overlay .es3-suspect-portrait > img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 12%;
}
#testimony-overlay .es3-suspect-name {
position: absolute;
left: calc(20 / 215 * 100%);
right: calc(20 / 215 * 100%);
bottom: calc(12 / 213 * 100%);
text-align: center;
color: #cfeeff;
font-weight: 800;
font-size: 22px;
letter-spacing: 1px;
line-height: 1;
z-index: 2;
text-shadow: 0 0 6px rgba(0, 0, 0, 0.85), 0 0 14px rgba(120, 220, 255, 0.55);
}
/* title */
#testimony-overlay .es3-title-wrap {
left: calc(320 / var(--es3-w) * 100%);
top: calc(72 / var(--es3-h) * 100%);
width: calc(1500 / var(--es3-w) * 100%);
height: calc(50 / var(--es3-h) * 100%);
display: flex;
align-items: center;
justify-content: center;
z-index: 4;
pointer-events: none;
}
#testimony-overlay .es3-title {
margin: 0;
font-weight: 800;
font-size: 46px;
color: #ffffff;
text-shadow: 0 0 14px rgba(120, 200, 255, 0.55), 0 2px 4px rgba(0, 0, 0, 0.7);
letter-spacing: 0.5px;
line-height: 1;
white-space: nowrap;
}
/* player status row */
#testimony-overlay .es3-ps-row {
left: calc(320 / var(--es3-w) * 100%);
top: calc(148 / var(--es3-h) * 100%);
width: calc(1500 / var(--es3-w) * 100%);
height: calc(170 / var(--es3-h) * 100%);
display: grid;
grid-template-columns: repeat(5, 1fr);
column-gap: calc(24 / var(--es3-w) * 100%);
padding: 0 calc(30 / var(--es3-w) * 100%);
z-index: 4;
}
#testimony-overlay .es3-ps {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
#testimony-overlay .es3-ps-name {
display: inline-flex;
align-items: center;
gap: 6px;
font-weight: 800;
font-size: 22px;
color: #e6f4ff;
letter-spacing: 1.2px;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
height: 28px;
}
#testimony-overlay .es3-ps-name .host-icon {
width: 28px;
height: 24px;
background: url('/Main-Lobby/IMAGE/Showcard/host-icon-2.png') center / contain no-repeat;
flex-shrink: 0;
}
#testimony-overlay .es3-ps-card {
position: relative;
width: 110px;
height: 138px;
display: grid;
place-items: center;
}
#testimony-overlay .es3-ps-card .card-bg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: fill;
}
#testimony-overlay .es3-ps-card .status-icon {
position: absolute;
width: 78px;
height: auto;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
}
#testimony-overlay .es3-ps-card .loading-icon {
position: absolute;
width: 42px;
height: 42px;
top: 28px;
left: 50%;
transform: translateX(-50%);
z-index: 2;
animation: es3-spin 1.4s linear infinite;
opacity: 0.55;
}
@keyframes es3-spin {
to { transform: translateX(-50%) rotate(360deg); }
}
#testimony-overlay .es3-ps-card .loading-text {
position: absolute;
width: 86px;
height: auto;
bottom: 18px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
opacity: 0.7;
}
#testimony-overlay .es3-ps.is-me .es3-ps-card {
outline: 2px solid #6df0ff;
outline-offset: 2px;
border-radius: 6px;
}
/* ส่วนล่าง */
#testimony-overlay .es3-bottom-box {
left: calc(160 / var(--es3-w) * 100%);
bottom: 0;
width: calc(1600 / var(--es3-w) * 100%);
height: calc(580 / var(--es3-h) * 100%);
z-index: 1;
pointer-events: none;
}
#testimony-overlay .es3-bottom-box img {
width: 100%;
height: 100%;
object-fit: fill;
}
#testimony-overlay .es3-evidence-text {
left: calc(200 / var(--es3-w) * 100%);
top: calc(583 / var(--es3-h) * 100%);
width: calc(720 / var(--es3-w) * 100%);
height: calc(36 / var(--es3-h) * 100%);
display: flex;
align-items: center;
pointer-events: none;
z-index: 3;
}
#testimony-overlay .es3-evidence-text img {
height: 100%;
width: auto;
}
#testimony-overlay .es3-counter {
left: calc(1409 / var(--es3-w) * 100%);
top: calc(626 / var(--es3-h) * 100%);
width: calc(320 / var(--es3-w) * 100%);
height: calc(36 / var(--es3-h) * 100%);
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: calc(30 / var(--es3-w) * 100%);
font-weight: 700;
font-size: 24px;
color: #b7e6ff;
z-index: 3;
}
#testimony-overlay .es3-cards {
left: calc(200 / var(--es3-w) * 100%);
top: calc(635 / var(--es3-h) * 100%);
width: calc(800 / var(--es3-w) * 100%);
height: calc(380 / var(--es3-h) * 100%);
display: flex;
gap: calc(22 / var(--es3-w) * 100%);
z-index: 3;
}
#testimony-overlay .es3-card {
position: relative;
flex: 1 1 0;
min-width: 0;
height: 100%;
border-radius: 12px;
background: linear-gradient(180deg, #cfd5dd 0%, #9ea7b4 100%);
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
overflow: hidden;
color: #1b2030;
border: 3px solid rgba(150, 165, 185, 0.55);
transition: box-shadow 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
cursor: pointer;
}
#testimony-overlay .es3-card:hover {
transform: translateY(-2px);
}
#testimony-overlay .es3-card.is-selected {
border-color: #6df0ff;
border-width: 4px;
box-shadow: 0 0 0 2px rgba(109, 240, 255, 0.55), 0 0 28px rgba(91, 216, 255, 0.85), 0 0 60px rgba(91, 216, 255, 0.35), 0 6px 18px rgba(0, 0, 0, 0.45);
background: linear-gradient(180deg, #d8e6f0 0%, #a8b8c8 100%);
}
#testimony-overlay .es3-card-head {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 10px;
background: rgba(255, 255, 255, 0.55);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
flex-shrink: 0;
}
#testimony-overlay .es3-card-head .ico {
width: 28px;
height: 28px;
background: rgba(0, 0, 0, 0.55);
color: #fff;
border-radius: 6px;
display: grid;
place-items: center;
font-size: 15px;
font-weight: 700;
flex-shrink: 0;
}
#testimony-overlay .es3-card-head .nm {
line-height: 1.05;
min-width: 0;
}
#testimony-overlay .es3-card-head .nm .th {
font-size: 14px;
font-weight: 700;
}
#testimony-overlay .es3-card-head .nm .en {
font-size: 10px;
font-weight: 500;
color: #444;
}
#testimony-overlay .es3-card-art {
flex: 1 1 auto;
min-height: 80px;
margin: 8px;
border-radius: 6px;
background: #707a8a;
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.45);
font-size: 12px;
font-weight: 600;
text-align: center;
}
#testimony-overlay .es3-card-desc {
padding: 8px 12px;
font-size: 12px;
line-height: 1.3;
color: #2a2f3c;
font-weight: 500;
text-align: center;
flex-shrink: 0;
margin: 0;
}
#testimony-overlay .es3-card-link {
margin: 4px 8px 8px;
padding: 5px 8px;
background: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(0, 0, 0, 0.18);
border-radius: 6px;
display: flex;
align-items: center;
gap: 8px;
font-size: 11px;
flex-shrink: 0;
}
#testimony-overlay .es3-card-link .avatar {
width: 20px;
height: 20px;
border-radius: 50%;
background: #4a5566;
color: #fff;
font-size: 10px;
font-weight: 800;
display: grid;
place-items: center;
flex-shrink: 0;
}
#testimony-overlay .es3-card-link .sname {
font-weight: 700;
color: #1b2030;
}
#testimony-overlay .es3-card-link .stars {
margin-left: auto;
color: #444;
font-weight: 700;
}
#testimony-overlay .es3-status-text {
left: calc(1243 / var(--es3-w) * 100%);
top: calc(915 / var(--es3-h) * 100%);
width: calc(460 / var(--es3-w) * 100%);
text-align: right;
font-weight: 600;
font-size: 18px;
color: #ff5f8a;
letter-spacing: 0.3px;
text-shadow: 0 0 8px rgba(255, 80, 130, 0.4);
z-index: 3;
pointer-events: none;
}
#testimony-overlay .btn {
border: none;
cursor: pointer;
padding: 0;
background: transparent;
font-size: 0;
color: transparent;
}
#testimony-overlay .btn:disabled {
filter: grayscale(0.7) opacity(0.45);
cursor: not-allowed;
}
#testimony-overlay .es3-btn-submit {
left: calc(920 / var(--es3-w) * 100%);
top: calc(944 / var(--es3-h) * 100%);
width: calc(234 / var(--es3-w) * 100%);
height: calc(100 / var(--es3-h) * 100%);
max-width: 234px;
max-height: 100px;
min-width: 120px;
min-height: 48px;
background: url('/Main-Lobby/IMAGE/Showcard/btn-send.png') center / contain no-repeat;
z-index: 5;
}
#testimony-overlay .es3-btn-open {
left: calc(1329 / var(--es3-w) * 100%);
top: calc(944 / var(--es3-h) * 100%);
width: calc(400 / var(--es3-w) * 100%);
height: calc(120 / var(--es3-h) * 100%);
max-width: 400px;
max-height: 120px;
z-index: 5;
}
#testimony-overlay .es3-btn-open img {
width: 100%;
height: 100%;
object-fit: contain;
}
#testimony-overlay .es3-btn-open.is-hidden {
display: none !important;
}
#testimony-overlay .es3-mic {
left: calc(1830 / var(--es3-w) * 100%);
bottom: calc(10 / var(--es3-h) * 100%);
width: calc(70 / var(--es3-w) * 100%);
height: calc(90 / var(--es3-h) * 100%);
max-width: 70px;
max-height: 90px;
border-radius: 50%;
border: 2px solid #22d3ee;
background: rgba(8, 20, 38, 0.75);
z-index: 6;
font-size: 26px;
color: #e7ecff;
display: flex;
align-items: center;
justify-content: center;
}
/* โหมดเปิดเผย — 11-1-2-evidence-summary (es-*) */
#testimony-overlay .es3-stage--reveal .es3-mode-select {
display: none !important;
}
#testimony-overlay .es-reveal-wrap {
position: absolute;
inset: 0;
z-index: 8;
}
#testimony-overlay .es-reveal-wrap[hidden] {
display: none !important;
}
#testimony-overlay .es-reveal-wrap .es-bg {
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
#testimony-overlay .es-reveal-wrap .es-bg img {
width: 100%;
height: 100%;
object-fit: cover;
}
#testimony-overlay .es-reveal-wrap .es-popup {
left: calc(120 / var(--es3-w) * 100%);
top: calc(22 / var(--es3-h) * 100%);
width: calc(1680 / var(--es3-w) * 100%);
height: calc(1036 / var(--es3-h) * 100%);
pointer-events: none;
z-index: 1;
}
#testimony-overlay .es-reveal-wrap .es-popup img {
width: 100%;
height: 100%;
object-fit: fill;
}
#testimony-overlay .es-reveal-wrap .es-suspect {
left: calc(150 / var(--es3-w) * 100%);
top: calc(35 / var(--es3-h) * 100%);
width: calc(230 / var(--es3-w) * 100%);
height: calc(228 / var(--es3-h) * 100%);
z-index: 5;
}
#testimony-overlay .es-reveal-wrap .es-suspect-frame {
position: absolute;
inset: 0;
pointer-events: none;
}
#testimony-overlay .es-reveal-wrap .es-suspect-frame img {
width: 100%;
height: 100%;
object-fit: fill;
}
#testimony-overlay .es-reveal-wrap .es-suspect-portrait {
position: absolute;
left: calc(30 / 230 * 100%);
top: calc(40 / 228 * 100%);
width: calc(170 / 230 * 100%);
height: calc(150 / 228 * 100%);
border-radius: 4px;
overflow: hidden;
z-index: 1;
background: radial-gradient(circle at 50% 35%, #cdb89b 0%, #8f7a63 70%, #2f2620 100%);
}
#testimony-overlay .es-reveal-wrap .es-suspect-portrait img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 12%;
}
#testimony-overlay .es-reveal-wrap .es-suspect-name {
position: absolute;
left: calc(20 / 230 * 100%);
right: calc(20 / 230 * 100%);
bottom: calc(12 / 228 * 100%);
text-align: center;
color: #fff3a8;
font-weight: 800;
font-size: 22px;
letter-spacing: 1px;
line-height: 1;
z-index: 2;
text-shadow: 0 0 6px rgba(0, 0, 0, 0.85), 0 0 14px rgba(255, 200, 0, 0.45);
}
#testimony-overlay .es-reveal-wrap .es-title-wrap {
left: calc(285 / var(--es3-w) * 100%);
top: calc(102 / var(--es3-h) * 100%);
width: calc(1340 / var(--es3-w) * 100%);
height: calc(175 / var(--es3-h) * 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 4;
pointer-events: none;
}
#testimony-overlay .es-reveal-wrap .es-title {
margin: 0;
font-weight: 800;
font-size: 44px;
color: #ffffff;
text-shadow: 0 0 12px rgba(120, 200, 255, 0.5), 0 2px 4px rgba(0, 0, 0, 0.7);
letter-spacing: 0.5px;
line-height: 1;
text-align: center;
white-space: nowrap;
padding: 14px 60px;
}
#testimony-overlay .es-reveal-wrap .es-subtitle {
margin: 0;
font-weight: 600;
font-size: 22px;
color: #d6e7ff;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
line-height: 1;
text-align: center;
padding: 8px 40px;
}
#testimony-overlay .es-reveal-wrap .es-players {
left: calc(120 / var(--es3-w) * 100%);
top: calc(300 / var(--es3-h) * 100%);
width: calc(1680 / var(--es3-w) * 100%);
height: calc(650 / var(--es3-h) * 100%);
display: grid;
grid-template-columns: repeat(5, 1fr);
column-gap: calc(24 / var(--es3-w) * 100%);
padding: 0 calc(70 / var(--es3-w) * 100%);
z-index: 3;
}
#testimony-overlay .es-reveal-wrap .es-player {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
min-width: 0;
}
#testimony-overlay .es-reveal-wrap .es-player-name {
display: inline-flex;
align-items: center;
gap: 8px;
font-weight: 800;
font-size: 30px;
color: #e6f4ff;
letter-spacing: 1.5px;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
height: 40px;
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-player-name .host-icon {
width: 36px;
height: 32px;
background: url('/Main-Lobby/IMAGE/Showcard/host-icon-2.png') center / contain no-repeat;
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-watch-badge {
font-size: 14px;
font-weight: 600;
color: #94a3b8;
text-align: center;
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-card {
position: relative;
width: 100%;
max-width: 220px;
height: 275px;
border-radius: 10px;
background: linear-gradient(180deg, #cfd5dd 0%, #b2bac4 100%);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
overflow: hidden;
color: #1b2030;
border: 3px solid rgba(150, 200, 255, 0.7);
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-card.rarity-common {
border-color: #9aa3b2;
}
#testimony-overlay .es-reveal-wrap .es-card.rarity-rare {
border-color: #6cc7ff;
box-shadow: 0 0 16px rgba(80, 175, 240, 0.4);
}
#testimony-overlay .es-reveal-wrap .es-card.rarity-legendary {
border-color: #f1b94a;
background: linear-gradient(180deg, #e4d3a8 0%, #c7a667 100%);
box-shadow: 0 0 18px rgba(241, 185, 74, 0.55);
}
#testimony-overlay .es-reveal-wrap .es-card-head {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 8px;
background: rgba(255, 255, 255, 0.45);
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-card-head .ico {
width: 24px;
height: 24px;
background: rgba(0, 0, 0, 0.55);
color: #fff;
border-radius: 5px;
display: grid;
place-items: center;
font-size: 13px;
font-weight: 700;
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-card-head .nm {
line-height: 1;
min-width: 0;
}
#testimony-overlay .es-reveal-wrap .es-card-head .nm .th {
font-size: 13px;
font-weight: 700;
color: #1b2030;
}
#testimony-overlay .es-reveal-wrap .es-card-head .nm .en {
font-size: 9px;
font-weight: 500;
color: #444;
}
#testimony-overlay .es-reveal-wrap .es-card-art {
flex: 1;
min-height: 60px;
margin: 6px;
border-radius: 6px;
background: #707a8a;
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.5);
font-size: 11px;
font-weight: 600;
text-align: center;
}
#testimony-overlay .es-reveal-wrap .es-card-desc {
padding: 4px 8px;
font-size: 10px;
line-height: 1.25;
color: #2a2f3c;
font-weight: 500;
text-align: center;
min-height: 32px;
flex-shrink: 0;
margin: 0;
}
#testimony-overlay .es-reveal-wrap .es-card-link {
margin: 4px 6px 6px;
padding: 4px 6px;
background: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 5px;
display: flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-card-link .avatar {
width: 18px;
height: 18px;
border-radius: 50%;
background: #4a5566;
color: #fff;
font-size: 9px;
font-weight: 800;
display: grid;
place-items: center;
flex-shrink: 0;
}
#testimony-overlay .es-reveal-wrap .es-card-link .sname {
font-size: 11px;
font-weight: 700;
color: #1b2030;
}
#testimony-overlay .es-reveal-wrap .es-card-link .label {
margin-left: auto;
font-size: 9px;
color: #444;
font-weight: 700;
}
#testimony-overlay .es-reveal-wrap .es-rev-none {
font-weight: 600;
font-size: 14px;
color: #ffd54a;
text-align: center;
padding: 24px 8px;
}
#testimony-overlay .es-reveal-wrap .es-ready {
left: calc(818 / var(--es3-w) * 100%);
top: calc(951 / var(--es3-h) * 100%);
width: calc(280 / var(--es3-w) * 100%);
height: calc(96 / var(--es3-h) * 100%);
max-width: 280px;
max-height: 96px;
z-index: 10;
position: absolute;
}
#testimony-overlay .es-reveal-wrap .es-ready img {
width: 100%;
height: 100%;
object-fit: contain;
}
#testimony-overlay .es-reveal-wrap .es-ready .ready-default {
opacity: 1;
transition: opacity 0.2s;
}
#testimony-overlay .es-reveal-wrap .es-ready .ready-active {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.2s;
}
#testimony-overlay .es-reveal-wrap .es-ready.is-active .ready-default,
#testimony-overlay .es-reveal-wrap .es-ready:disabled .ready-default {
opacity: 0;
}
#testimony-overlay .es-reveal-wrap .es-ready.is-active .ready-active,
#testimony-overlay .es-reveal-wrap .es-ready:disabled .ready-active {
opacity: 1;
}
+2 -2
View File
@@ -2254,11 +2254,11 @@
return null;
}
/** วาดตัวละคร — ทิศลง + useLobbyIdleComposite: composite เดียวกับล็อบบี้ (เฉพาะผู้เล่นจริง); คนอื่นใช้เลเยอร์+สีตาม peer */
/** วาดตัวละคร — ทิศลง + useLobbyIdleComposite: composite เดียวกับล็อบบี้ (เฉพาะผู้เล่นจริง ตอนยืน); ตอนเดินใช้ strip เดิน down_0..3 */
function resolvePlayDrawCharSource(characterId, direction, now, isWalking, playTint, useLobbyIdleComposite) {
const dir = direction || 'down';
const walk = !!isWalking;
if (dir === 'down' && useLobbyIdleComposite) {
if (dir === 'down' && useLobbyIdleComposite && !walk) {
const lobbyImg = getPlayLobbyIdleAvatarImageSync(characterId);
if (lobbyImg) return lobbyImg;
}
+403 -236
View File
@@ -42,6 +42,7 @@
const LOBBY_EVIDENCE_ASSET_BASE = typeof appPath === 'function' ? appPath('/Main-Lobby/IMAGE/See%20evidence') : '/Main-Lobby/IMAGE/See%20evidence';
const LOBBY_EVIDENCE_RARITY = { common: 'Common', rare: 'Rare', legendary: 'Legendary' };
const LOBBY_EVIDENCE_CARD_ICONS = ['🚬', '👓', '🔪'];
/** ข้อมูลตัวอย่างตาม caseId — แก้/โหลดจาก API ได้ภายหลัง */
const LOBBY_EVIDENCE_CASES = {
'1': {
@@ -3577,11 +3578,104 @@
}
}
function setLobbyEvidenceTabImage(idx) {
const img = document.getElementById('lobby-evidence-tabs-img');
if (!img) return;
const n = Math.max(0, Math.min(2, idx)) + 1;
img.src = `${LOBBY_EVIDENCE_ASSET_BASE}/evidence-tab-${n}.png`;
var evidenceScaleBound = false;
function syncLobbyEvidenceScale() {
var wrap = document.querySelector('#lobby-evidence-overlay .stage-wrap');
var stage = document.querySelector('#lobby-evidence-overlay .ev-stage');
if (!wrap || !stage) return;
var dw = 1920;
var dh = 1080;
var w = wrap.clientWidth || window.innerWidth;
var h = wrap.clientHeight || window.innerHeight;
var scale = Math.min(w / dw, h / dh);
if (!Number.isFinite(scale) || scale <= 0) scale = 1;
var scaledW = dw * scale;
var scaledH = dh * scale;
var tx = Math.max(0, (w - scaledW) / 2);
var ty = Math.max(0, (h - scaledH) / 2);
stage.style.transform = 'translate(' + tx + 'px, ' + ty + 'px) scale(' + scale + ')';
stage.style.marginBottom = '0';
}
function bindLobbyEvidenceScale() {
if (evidenceScaleBound) return;
evidenceScaleBound = true;
window.addEventListener('resize', syncLobbyEvidenceScale);
window.addEventListener('orientationchange', syncLobbyEvidenceScale);
}
function ensureLobbyEvidenceEvLayout() {
var ov = document.getElementById('lobby-evidence-overlay');
if (!ov || ov.querySelector('.ev-stage')) return ov;
var base = LOBBY_EVIDENCE_ASSET_BASE;
var backdrop = ov.querySelector('.lobby-evidence-backdrop');
ov.textContent = '';
if (backdrop) ov.appendChild(backdrop);
var wrap = document.createElement('div');
wrap.className = 'stage-wrap';
wrap.setAttribute('role', 'dialog');
wrap.setAttribute('aria-modal', 'true');
wrap.setAttribute('aria-labelledby', 'lobby-evidence-sr-title');
wrap.innerHTML =
'<h2 id="lobby-evidence-sr-title" class="visually-hidden">แฟ้มหลักฐาน</h2>' +
'<div class="stage ev-stage">' +
'<div class="layer ev-bg-fallback" aria-hidden="true"></div>' +
'<div class="layer ev-popup"><img src="' + base + '/evidence-bg.png" alt="" width="1684" height="963" decoding="async"></div>' +
'<button type="button" class="layer ev-close" id="lobby-evidence-close" title="ปิด" aria-label="ปิดแฟ้มหลักฐาน"></button>' +
'<div class="layer ev-tabs" id="lobby-evidence-tabs" role="tablist" aria-label="เลือกผู้ต้องสงสัย">' +
'<img class="ev-tab is-active" data-state="1" src="' + base + '/evidence-tab-1.png" alt="" decoding="async">' +
'<img class="ev-tab" data-state="2" src="' + base + '/evidence-tab-2.png" alt="" decoding="async">' +
'<img class="ev-tab" data-state="3" src="' + base + '/evidence-tab-3.png" alt="" decoding="async">' +
'<button type="button" class="ev-tab-click" role="tab" data-evidence-tab="0" aria-selected="true" aria-label="ผู้ต้องสงสัย 1"></button>' +
'<button type="button" class="ev-tab-click" role="tab" data-evidence-tab="1" aria-selected="false" aria-label="ผู้ต้องสงสัย 2"></button>' +
'<button type="button" class="ev-tab-click" role="tab" data-evidence-tab="2" aria-selected="false" aria-label="ผู้ต้องสงสัย 3"></button>' +
'</div>' +
'<div class="layer ev-cards" id="lobby-evidence-cards-root"></div>' +
'</div>';
ov.appendChild(wrap);
return ov;
}
function evLobbyEvidenceCardEl(c, linkName, cardIdx) {
var rar = String(c.rarity || 'common').toLowerCase();
if (!LOBBY_EVIDENCE_RARITY[rar]) rar = 'common';
var nStar = Math.max(1, Math.min(3, Number(c.stars) || 1));
var stars = '';
for (var st = 0; st < nStar; st++) stars += '★';
var nm = linkName || '?';
var icon = LOBBY_EVIDENCE_CARD_ICONS[cardIdx] || '🔎';
var card = document.createElement('article');
card.className = 'ev-card rarity-' + rar;
card.innerHTML =
'<div class="ev-card-head">' +
'<div class="icon" aria-hidden="true"></div>' +
'<div class="name">' +
'<div class="th"></div>' +
'<div class="en"></div>' +
'</div>' +
'</div>' +
'<div class="ev-card-art" aria-hidden="true">◆</div>' +
'<p class="ev-card-desc"></p>' +
'<div class="ev-card-link-wrap">' +
'<div class="ev-card-link">' +
'<span class="label">Suspect Link</span>' +
'<span class="stars"></span>' +
'</div>' +
'<div class="ev-card-link">' +
'<div class="suspect">' +
'<div class="avatar"></div>' +
'<div class="sname"></div>' +
'</div>' +
'</div>' +
'</div>';
card.querySelector('.icon').textContent = icon;
card.querySelector('.th').textContent = c.titleTh || '';
card.querySelector('.en').textContent = c.titleEn ? '(' + c.titleEn + ')' : '';
card.querySelector('.ev-card-desc').textContent = c.body || '';
card.querySelector('.stars').textContent = stars + ' (' + LOBBY_EVIDENCE_RARITY[rar] + ')';
card.querySelector('.avatar').textContent = nm.charAt(0);
card.querySelector('.sname').textContent = nm;
return card;
}
function renderLobbyEvidenceCards(suspectIdx) {
@@ -3593,95 +3687,38 @@
const s = suspects[si];
root.textContent = '';
if (!s || !s.cards) return;
s.cards.forEach((c) => {
let rar = String(c.rarity || 'common').toLowerCase();
if (!LOBBY_EVIDENCE_RARITY[rar]) rar = 'common';
const nStar = Math.max(1, Math.min(3, Number(c.stars) || 1));
let stars = '';
for (let st = 0; st < nStar; st++) stars += '★';
const card = document.createElement('article');
card.className = `lobby-evidence-card lobby-evidence-card--${rar}`;
const head = document.createElement('div');
head.className = 'lobby-evidence-card-head';
const icon = document.createElement('span');
icon.className = 'lobby-evidence-card-icon';
icon.textContent = '🔎';
icon.setAttribute('aria-hidden', 'true');
const titles = document.createElement('div');
titles.className = 'lobby-evidence-card-titles';
const hTh = document.createElement('p');
hTh.className = 'lobby-evidence-card-title-th';
hTh.textContent = c.titleTh || '';
const hEn = document.createElement('p');
hEn.className = 'lobby-evidence-card-title-en';
hEn.textContent = c.titleEn ? `(${c.titleEn})` : '';
titles.appendChild(hTh);
titles.appendChild(hEn);
head.appendChild(icon);
head.appendChild(titles);
const art = document.createElement('div');
art.className = 'lobby-evidence-card-art';
art.setAttribute('aria-hidden', 'true');
art.textContent = '◆';
const body = document.createElement('p');
body.className = 'lobby-evidence-card-body';
body.textContent = c.body || '';
const foot = document.createElement('div');
foot.className = 'lobby-evidence-card-foot';
const link = document.createElement('div');
link.className = 'lobby-evidence-link';
const av = document.createElement('span');
av.className = 'lobby-evidence-avatar';
const nm = s.linkName || '?';
av.textContent = nm.charAt(0);
const nmEl = document.createElement('span');
nmEl.className = 'lobby-evidence-link-name';
nmEl.textContent = nm;
link.appendChild(av);
link.appendChild(nmEl);
const fm = document.createElement('div');
fm.className = 'lobby-evidence-foot-meta';
const rl = document.createElement('span');
rl.className = 'lobby-evidence-rarity';
rl.textContent = `(${LOBBY_EVIDENCE_RARITY[rar]})`;
const stEl = document.createElement('div');
stEl.className = 'lobby-evidence-stars';
stEl.textContent = stars;
fm.appendChild(rl);
fm.appendChild(stEl);
foot.appendChild(link);
foot.appendChild(fm);
card.appendChild(head);
card.appendChild(art);
card.appendChild(body);
card.appendChild(foot);
root.appendChild(card);
s.cards.forEach((c, cardIdx) => {
root.appendChild(evLobbyEvidenceCardEl(c, s.linkName, cardIdx));
});
}
let lobbyEvidenceSuspectIdx = 0;
function syncLobbyEvidenceTabUi(idx) {
lobbyEvidenceSuspectIdx = Math.max(0, Math.min(2, idx));
setLobbyEvidenceTabImage(lobbyEvidenceSuspectIdx);
document.querySelectorAll('[data-evidence-tab]').forEach((b) => {
var tabsEl = document.getElementById('lobby-evidence-tabs');
if (tabsEl) {
tabsEl.querySelectorAll('.ev-tab').forEach(function (img) {
var state = parseInt(img.getAttribute('data-state'), 10);
img.classList.toggle('is-active', state === lobbyEvidenceSuspectIdx + 1);
});
}
document.querySelectorAll('#lobby-evidence-overlay [data-evidence-tab]').forEach((b) => {
const i = parseInt(b.getAttribute('data-evidence-tab'), 10);
b.setAttribute('aria-selected', i === lobbyEvidenceSuspectIdx ? 'true' : 'false');
});
renderLobbyEvidenceCards(lobbyEvidenceSuspectIdx);
syncLobbyEvidenceScale();
}
function openLobbyEvidenceModal() {
ensureLobbyEvidenceEvLayout();
bindLobbyEvidenceScale();
const ov = document.getElementById('lobby-evidence-overlay');
if (!ov) return;
ov.classList.remove('is-hidden');
ov.setAttribute('aria-hidden', 'false');
syncLobbyEvidenceTabUi(0);
requestAnimationFrame(syncLobbyEvidenceScale);
document.getElementById('lobby-evidence-close')?.focus();
}
@@ -3697,14 +3734,14 @@
openLobbyEvidenceModal();
});
document.getElementById('lobby-evidence-backdrop')?.addEventListener('click', () => {
closeLobbyEvidenceModal();
});
document.getElementById('lobby-evidence-close')?.addEventListener('click', () => {
closeLobbyEvidenceModal();
});
ensureLobbyEvidenceEvLayout();
bindLobbyEvidenceScale();
document.getElementById('lobby-evidence-overlay')?.addEventListener('click', (e) => {
const hit = e.target.closest('[data-evidence-tab]');
if (e.target.id === 'lobby-evidence-backdrop' || e.target.closest('#lobby-evidence-close')) {
closeLobbyEvidenceModal();
return;
}
const hit = e.target.closest('.ev-tab-click[data-evidence-tab]');
if (!hit) return;
const i = parseInt(hit.getAttribute('data-evidence-tab'), 10);
if (!Number.isNaN(i)) syncLobbyEvidenceTabUi(i);
@@ -4279,76 +4316,63 @@
var tmState = { round: 0, members: [], picks: [], submitted: false, mode: 'select' };
var SUSPECT_NAMES_EN = ['SOMCHAI', 'ARIN', 'JIRAPHA'];
function injectTestimonyStyle() {
if (document.getElementById('testimony-style')) return;
var st = document.createElement('style');
st.id = 'testimony-style';
var SC = '/Main-Lobby/IMAGE/Showcard/';
st.textContent =
'#testimony-overlay{position:fixed;inset:0;z-index:9000;background:#04060c center/cover no-repeat;display:flex;align-items:center;justify-content:center;font-family:Kanit,system-ui,sans-serif;color:#e7ecff;overflow:hidden}' +
'#testimony-overlay.is-hidden{display:none}' +
'.tm-stage{position:relative;width:min(96vw,1560px);aspect-ratio:16/9;max-height:97vh;max-height:97dvh}' +
// ---- กรอบบน box-1 (title baked) ----
'.tm-top{position:absolute;left:6%;top:1.5%;width:88%;height:42%;background:url(' + SC + 'box-1.png) center/100% 100% no-repeat}' +
'.tm-title{position:absolute;left:50%;top:14%;transform:translateX(-50%);white-space:nowrap;font:800 clamp(15px,2.1vw,30px)/1 Kanit;color:#fff;text-shadow:0 0 14px rgba(34,211,238,.6)}' +
'.tm-sub2{position:absolute;left:50%;top:25%;transform:translateX(-50%);font:600 clamp(10px,1.1vw,16px)/1 Kanit;color:#9fe7ff;white-space:nowrap;max-width:80%;overflow:hidden;text-overflow:ellipsis}' +
'.tm-suspect{position:absolute;left:3.5%;top:30%;width:12%}' +
'.tm-sus-frame{position:relative;width:100%;aspect-ratio:291/289;background:url(' + SC + 'suspect-bg.png) center/contain no-repeat;display:flex;align-items:center;justify-content:center}' +
'.tm-sus-frame img{width:78%;height:78%;object-fit:cover;object-position:center 16%;border-radius:10px}' +
'.tm-sus-name{text-align:center;margin-top:2px;font:700 clamp(10px,1vw,15px)/1.1 Kanit;color:#bfe9ff}' +
'.tm-members{position:absolute;left:18%;right:2%;top:34%;bottom:8%;display:flex;gap:1%;align-items:flex-start;justify-content:center;flex-wrap:nowrap;overflow:hidden}' +
'.tm-member{flex:0 1 17%;max-width:17%;border:2px solid #1e6f8c;border-radius:10px;padding:clamp(4px,0.6vh,8px) 4px;text-align:center;background:rgba(8,20,38,.6);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(2px,0.4vh,6px)}' +
'.tm-member .tm-mname{font:700 clamp(9px,0.85vw,14px)/1 Kanit;color:#bfe9ff;white-space:nowrap;display:flex;align-items:center;justify-content:center;gap:4px}' +
'.tm-member .tm-mstat{font:600 clamp(9px,0.8vw,13px)/1.1 Kanit;color:#8aa0c0;display:flex;flex-direction:column;align-items:center;gap:4px}' +
'.tm-member .tm-mstat img{height:26%;max-height:34px;width:auto}' +
'.tm-member.tm-ready{border-color:#22c55e;box-shadow:0 0 14px rgba(34,197,94,.5)}.tm-member.tm-ready .tm-mstat{color:#22c55e}' +
'.tm-member.tm-me{outline:2px solid #22d3ee;outline-offset:2px}' +
'.tm-crown img{height:14px;width:auto;vertical-align:middle}' +
// ---- กรอบล่าง tab-0N (แท็บ baked) ----
'.tm-bottom{position:absolute;left:6%;right:6%;top:47%;bottom:1.5%;background:top center/100% 100% no-repeat}' +
'.tm-bhead{position:absolute;left:3%;top:17%;font:600 clamp(11px,1.2vw,18px)/1.2 Kanit;color:#cfe9ff}' +
'.tm-count{position:absolute;right:3%;top:17%;color:#ffd54a;font:700 clamp(12px,1.3vw,20px)/1 Kanit}' +
'.tm-cards{position:absolute;left:3%;right:3%;top:22%;bottom:6%;display:flex;gap:1.5%;align-items:stretch;justify-content:center}' +
'.tm-cards .lobby-evidence-card{cursor:pointer;transition:transform .12s,box-shadow .12s;max-height:100%;height:100%;flex:0 1 200px;overflow:hidden}' +
'#testimony-overlay .lobby-evidence-card-art{height:clamp(40px,8vh,80px);min-height:36px;font-size:0;margin:2px 0;display:flex;align-items:center;justify-content:center;background:rgba(0,40,60,.3);border-radius:6px;overflow:hidden}#testimony-overlay .lobby-evidence-card-art img{width:100%;height:100%;object-fit:cover;border-radius:6px}' +
'#testimony-overlay .tm-cards .lobby-evidence-card-body{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}' +
'.tm-cards .lobby-evidence-card.tm-sel{outline:3px solid #22d3ee;outline-offset:2px;transform:translateY(-6px);box-shadow:0 8px 26px rgba(34,211,238,.55)}' +
'.tm-status{position:absolute;left:3%;bottom:6%;text-align:left;color:#ffd54a;font:600 clamp(11px,1.1vw,16px)/1.3 Kanit}' +
'.tm-actions{position:absolute;right:3%;bottom:4%;display:flex;gap:1.2%;align-items:center;z-index:4}' +
'.tm-imgbtn{background:center/contain no-repeat;border:none;cursor:pointer;font-size:0;color:transparent;padding:0}' +
'.tm-imgbtn:disabled{filter:grayscale(.65) opacity(.45);cursor:not-allowed}' +
'#tm-submit{width:clamp(150px,15vw,234px);height:clamp(64px,6.5vw,100px);background-image:url(' + SC + 'btn-send.png)}' +
'#tm-force-reveal{width:clamp(170px,17vw,280px);height:clamp(50px,5vw,84px);background-image:url(' + SC + 'btn-open-card.png)}' +
// ---- โหมดเปิดเผย (reveal) ----
'.tm-reveal-grid{position:absolute;left:2%;right:2%;top:5%;bottom:18%;display:flex;gap:1.2%;align-items:flex-start;justify-content:center;overflow-y:auto;overflow-x:hidden}' +
'.tm-rev-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0;max-width:19.5%}' +
'.tm-rev-col .tm-rev-name{font:700 clamp(9px,0.9vw,14px)/1 Kanit;color:#bfe9ff;display:flex;align-items:center;gap:4px}' +
'.tm-rev-col .lobby-evidence-card{width:100%;max-width:118px;transform:none;font-size:10px}' +
'.tm-rev-col .lobby-evidence-card .lobby-evidence-card-body{display:none}' +
'#tm-ready{position:absolute;left:50%;bottom:2%;transform:translateX(-50%);width:clamp(160px,15vw,240px);height:clamp(62px,6vw,94px);background-image:url(' + SC + 'btn-ready.png)}#tm-mic{position:absolute;right:1%;bottom:1%;width:clamp(44px,4.5vw,68px);height:clamp(44px,4.5vw,68px);border-radius:50%;border:2px solid #22d3ee;background:rgba(8,20,38,.7) center/60% no-repeat;cursor:pointer;z-index:5;display:flex;align-items:center;justify-content:center;font-size:clamp(18px,2vw,28px)}#tm-mic:hover{background-color:rgba(34,211,238,.15)}';
document.head.appendChild(st);
function ensureTestimonyStyle() {
var link = document.getElementById('testimony-style');
if (!link) {
link = document.createElement('link');
link.id = 'testimony-style';
link.rel = 'stylesheet';
document.head.appendChild(link);
}
link.href = 'css/testimony-overlay.css?v=5';
}
function tmEvidenceCardEl(c, linkName, cardIndex, selectable) {
var testimonyScaleBound = false;
function syncTestimonyScale() {
var wrap = document.querySelector('#testimony-overlay .stage-wrap');
var stage = document.querySelector('#testimony-overlay .es3-stage');
if (!wrap || !stage) return;
var dw = 1920;
var dh = 1080;
var w = wrap.clientWidth || window.innerWidth;
var h = wrap.clientHeight || window.innerHeight;
var scale = Math.min(w / dw, h / dh);
if (!Number.isFinite(scale) || scale <= 0) scale = 1;
stage.style.transform = 'scale(' + scale + ')';
stage.style.marginBottom = ((dh * scale) - dh) + 'px';
}
function bindTestimonyScale() {
if (testimonyScaleBound) return;
testimonyScaleBound = true;
window.addEventListener('resize', syncTestimonyScale);
window.addEventListener('orientationchange', syncTestimonyScale);
}
function es3EvidenceCardEl(c, linkName, cardIndex, selectable) {
var rar = String(c.rarity || 'common').toLowerCase();
if (!LOBBY_EVIDENCE_RARITY[rar]) rar = 'common';
var nStar = Math.max(1, Math.min(3, Number(c.stars) || 1));
var stars = ''; for (var st = 0; st < nStar; st++) stars += '★';
var stars = '';
for (var st = 0; st < nStar; st++) stars += '★';
var nm = linkName || '?';
var icon = LOBBY_EVIDENCE_CARD_ICONS[cardIndex] || '🔎';
var card = document.createElement('article');
card.className = 'lobby-evidence-card lobby-evidence-card--' + rar;
card.className = 'es3-card';
if (selectable) card.setAttribute('data-card-index', String(cardIndex));
card.innerHTML =
'<div class="lobby-evidence-card-head"><span class="lobby-evidence-card-icon" aria-hidden="true">🔎</span>' +
'<div class="lobby-evidence-card-titles"><p class="lobby-evidence-card-title-th"></p><p class="lobby-evidence-card-title-en"></p></div></div>' +
'<div class="lobby-evidence-card-art" aria-hidden="true"><img src="/Main-Lobby/IMAGE/Showcard/card-bg.png" alt=""></div>' +
'<p class="lobby-evidence-card-body"></p>' +
'<div class="lobby-evidence-card-foot"><div class="lobby-evidence-link"><span class="lobby-evidence-avatar"></span><span class="lobby-evidence-link-name"></span></div>' +
'<div class="lobby-evidence-foot-meta"><span class="lobby-evidence-rarity">(' + LOBBY_EVIDENCE_RARITY[rar] + ')</span><div class="lobby-evidence-stars">' + stars + '</div></div></div>';
card.querySelector('.lobby-evidence-card-title-th').textContent = c.titleTh || '';
card.querySelector('.lobby-evidence-card-title-en').textContent = c.titleEn ? '(' + c.titleEn + ')' : '';
card.querySelector('.lobby-evidence-card-body').textContent = c.body || '';
card.querySelector('.lobby-evidence-avatar').textContent = (linkName || '?').charAt(0);
card.querySelector('.lobby-evidence-link-name').textContent = linkName || '';
'<div class="es3-card-head"><div class="ico" aria-hidden="true"></div>' +
'<div class="nm"><div class="th"></div><div class="en"></div></div></div>' +
'<div class="es3-card-art" aria-hidden="true"></div>' +
'<p class="es3-card-desc"></p>' +
'<div class="es3-card-link"><div class="avatar"></div><div class="sname"></div><div class="stars"></div></div>';
card.querySelector('.ico').textContent = icon;
card.querySelector('.th').textContent = c.titleTh || '';
card.querySelector('.en').textContent = c.titleEn ? '(' + c.titleEn + ')' : '';
card.querySelector('.es3-card-desc').textContent = c.body || '';
card.querySelector('.avatar').textContent = nm.charAt(0);
card.querySelector('.sname').textContent = nm;
card.querySelector('.stars').textContent = stars + ' (' + LOBBY_EVIDENCE_RARITY[rar] + ')';
return card;
}
@@ -4361,85 +4385,220 @@
function ensureTestimonyOverlay() {
var ov = document.getElementById('testimony-overlay');
if (ov && (!ov.querySelector('.es3-bottom-box') || !ov.querySelector('.es-reveal-wrap'))) {
ov.remove();
ov = null;
}
if (ov) return ov;
injectTestimonyStyle();
var SC = '/Main-Lobby/IMAGE/Showcard/';
ensureTestimonyStyle();
bindTestimonyScale();
ov = document.createElement('div');
ov.id = 'testimony-overlay';
ov.className = 'is-hidden';
ov.setAttribute('aria-hidden', 'true');
var SC = '/Main-Lobby/IMAGE/Showcard/';
ov.innerHTML =
'<div class="tm-stage" id="tm-stage">' +
'<div class="tm-top">' +
'<div class="tm-title" id="tm-title"></div>' +
'<div class="tm-sub2" id="tm-sub2"></div>' +
'<div class="tm-suspect"><div class="tm-sus-frame"><img id="tm-sus-img" alt=""></div><div class="tm-sus-name" id="tm-sus-name"></div></div>' +
'<div class="tm-members" id="tm-members"></div>' +
'</div>' +
'<div class="tm-bottom" id="tm-bottom">' +
'<div id="tm-select-wrap">' +
'<div class="tm-bhead">[เลือกพยานหลักฐาน 2 ชิ้น เพื่อประกอบสำนวนคดีนี้]</div>' +
'<div class="tm-count" id="tm-count">เลือกหลักฐาน 0/2</div>' +
'<div class="tm-cards" id="tm-cards"></div>' +
'<div class="tm-status" id="tm-status"></div>' +
'<div class="tm-actions"><button type="button" class="tm-imgbtn" id="tm-submit" disabled aria-label="ส่งหลักฐาน"></button><button type="button" class="tm-imgbtn" id="tm-force-reveal" style="display:none" aria-label="เปิดหลักฐานทั้งหมด"></button></div>' +
'<button type="button" id="tm-mic" aria-label="ไมค์">🎤</button>' +
'<div class="stage-wrap">' +
'<div class="stage es3-stage">' +
'<div class="layer es3-bg" aria-hidden="true"><img src="' + SC + 'bg-showcard.png" alt=""></div>' +
'<div class="layer es3-top-popup es3-mode-select">' +
'<span class="corner c-tl"></span><span class="corner c-tr"></span><span class="corner c-bl"></span><span class="corner c-br"></span>' +
'<div class="es3-popup-tab">ห้องสรุปหลักฐาน</div>' +
'</div>' +
'<div id="tm-reveal-wrap" style="display:none">' +
'<div class="tm-reveal-grid" id="tm-reveal-grid"></div>' +
'<button type="button" class="tm-imgbtn" id="tm-ready" aria-label="READY"></button>' +
'<div class="layer es3-suspect es3-mode-select">' +
'<div class="es3-suspect-frame"><img src="' + SC + 'suspect-bg.png" alt=""></div>' +
'<div class="es3-suspect-portrait"><img id="es3-sus-img" alt=""></div>' +
'<div class="es3-suspect-name" id="es3-sus-name"></div>' +
'</div>' +
'<div class="layer es3-title-wrap es3-mode-select"><h2 class="es3-title" id="es3-title"></h2></div>' +
'<div class="layer es3-ps-row es3-mode-select" id="es3-ps-row"></div>' +
'<div class="layer es3-bottom-box es3-mode-select" id="es3-bottom-box"><img src="' + SC + 'tab-01.png" alt=""></div>' +
'<div class="layer es3-evidence-text es3-mode-select"><img src="' + SC + 'txt-2.png" alt=""></div>' +
'<div class="layer es3-counter es3-mode-select" id="es3-count">เลือกหลักฐาน 0/2</div>' +
'<div class="layer es3-cards es3-mode-select" id="es3-cards"></div>' +
'<div class="layer es3-status-text es3-mode-select" id="es3-status">Status : กำลังรอ..ผู้เล่นเลือกหลักฐาน</div>' +
'<button type="button" class="layer es3-btn-submit btn es3-mode-select" id="es3BtnSubmit" disabled aria-label="ส่งหลักฐาน"></button>' +
'<div class="layer es3-btn-open btn es3-mode-select" id="es3BtnOpen" role="button" tabindex="0" aria-label="เปิดหลักฐานทั้งหมด">' +
'<img src="' + SC + 'btn-open-card.png" alt="">' +
'</div>' +
'<div class="es-reveal-wrap" id="es-reveal-wrap" hidden>' +
'<div class="layer es-bg" aria-hidden="true"><img src="' + SC + 'bg-showcard.png" alt=""></div>' +
'<div class="layer es-popup"><img src="' + SC + 'popup-0.png" alt=""></div>' +
'<div class="layer es-suspect">' +
'<div class="es-suspect-frame"><img src="' + SC + 'suspect-bg.png" alt=""></div>' +
'<div class="es-suspect-portrait"><img id="es-popup-sus-img" alt=""></div>' +
'<div class="es-suspect-name" id="es-popup-sus-name"></div>' +
'</div>' +
'<div class="layer es-title-wrap">' +
'<h2 class="es-title" id="es-popup-title"></h2>' +
'<p class="es-subtitle" id="es-popup-sub">[วิเคราะห์พยานหลักฐานกับทีม ก่อนไปปากคำถัดไป]</p>' +
'</div>' +
'<div class="layer es-players" id="es-players"></div>' +
'<button type="button" class="layer es-ready btn" id="esBtnReady" aria-label="READY">' +
'<img class="ready-default" src="' + SC + 'btn-ready.png" alt="">' +
'<img class="ready-active" src="' + SC + 'btn-ready-active.png" alt="">' +
'</button>' +
'</div>' +
'<button type="button" class="es3-mic btn" id="es3-mic" aria-label="ไมค์">🎤</button>' +
'</div>' +
'</div>';
document.body.appendChild(ov);
var stg = ov.querySelector('#tm-stage');
if (stg) stg.style.background = 'url(' + SC + 'bg-showcard.png) center/cover no-repeat #04060c';
ov.querySelector('#tm-cards').addEventListener('click', function (e) {
var card = e.target.closest('.lobby-evidence-card'); if (!card || tmState.submitted) return;
var cardsEl = ov.querySelector('#es3-cards');
if (cardsEl) cardsEl.addEventListener('click', function (e) {
var card = e.target.closest('.es3-card'); if (!card || tmState.submitted) return;
var idx = parseInt(card.getAttribute('data-card-index'), 10);
if (!(idx >= 0)) return;
var pos = tmState.picks.indexOf(idx);
if (pos >= 0) { tmState.picks.splice(pos, 1); card.classList.remove('tm-sel'); }
else { if (tmState.picks.length >= 2) return; tmState.picks.push(idx); card.classList.add('tm-sel'); }
tmUpdateCount();
if (pos >= 0) { tmState.picks.splice(pos, 1); card.classList.remove('is-selected'); }
else { if (tmState.picks.length >= 2) return; tmState.picks.push(idx); card.classList.add('is-selected'); }
es3UpdateCount();
});
ov.querySelector('#tm-submit').addEventListener('click', function () {
var submitEl = ov.querySelector('#es3BtnSubmit');
if (submitEl) submitEl.addEventListener('click', function () {
if (tmState.picks.length !== 2 || tmState.submitted) return;
socket.emit('testimony-submit', { picks: tmState.picks.slice(0, 2) }, function (res) {
if (res && res.ok) { tmState.submitted = true; tmSetStatus('ส่งหลักฐานแล้ว — รอผู้เล่นอื่น...'); document.getElementById('tm-submit').disabled = true; }
else appendLobbySystemChat('— ส่งหลักฐานไม่สำเร็จ' + (res && res.error ? (' · ' + res.error) : ''));
if (res && res.ok) {
tmState.submitted = true;
es3SetStatus('ส่งหลักฐานแล้ว — รอผู้เล่นอื่น...');
var sub = document.getElementById('es3BtnSubmit'); if (sub) sub.disabled = true;
} else appendLobbySystemChat('— ส่งหลักฐานไม่สำเร็จ' + (res && res.error ? (' · ' + res.error) : ''));
});
});
ov.querySelector('#tm-force-reveal').addEventListener('click', function () {
socket.emit('testimony-reveal', {}, function (res) { if (!(res && res.ok)) appendLobbySystemChat('— เปิดเผยไม่สำเร็จ' + (res && res.error ? (' · ' + res.error) : '')); });
});
ov.querySelector('#tm-ready').addEventListener('click', function () {
var openEl = ov.querySelector('#es3BtnOpen');
if (openEl) {
openEl.addEventListener('click', function () {
socket.emit('testimony-reveal', {}, function (res) { if (!(res && res.ok)) appendLobbySystemChat('— เปิดเผยไม่สำเร็จ' + (res && res.error ? (' · ' + res.error) : '')); });
});
openEl.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); this.click(); }
});
}
var readyEl = ov.querySelector('#esBtnReady');
if (readyEl) readyEl.addEventListener('click', function () {
if (this.disabled) return;
this.classList.add('is-active');
this.disabled = true;
socket.emit('testimony-ready-next', {}, function (res) { if (!(res && res.ok)) { document.getElementById('tm-ready').disabled = false; appendLobbySystemChat('— READY ไม่สำเร็จ' + (res && res.error ? (' · ' + res.error) : '')); } });
socket.emit('testimony-ready-next', {}, function (res) {
if (!(res && res.ok)) {
var rd = document.getElementById('esBtnReady');
if (rd) { rd.disabled = false; rd.classList.remove('is-active'); }
appendLobbySystemChat('— READY ไม่สำเร็จ' + (res && res.error ? (' · ' + res.error) : ''));
}
});
});
return ov;
}
function tmSetStatus(txt) { var el = document.getElementById('tm-status'); if (el) el.textContent = txt || ''; }
function tmUpdateCount() {
var el = document.getElementById('tm-count'); if (el) el.textContent = 'เลือกหลักฐาน ' + tmState.picks.length + '/2';
var sub = document.getElementById('tm-submit'); if (sub) sub.disabled = (tmState.picks.length !== 2 || tmState.submitted);
function es3SetStatus(txt) {
var el = document.getElementById('es3-status');
if (el) el.textContent = 'Status : ' + (txt || 'กำลังรอ..ผู้เล่นเลือกหลักฐาน');
}
function tmRenderMembers(submittedIds, readyIds, revealMode) {
var root = document.getElementById('tm-members'); if (!root) return;
function es3UpdateCount() {
var el = document.getElementById('es3-count'); if (el) el.textContent = 'เลือกหลักฐาน ' + tmState.picks.length + '/2';
var sub = document.getElementById('es3BtnSubmit'); if (sub) sub.disabled = (tmState.picks.length !== 2 || tmState.submitted);
}
function esRevealCardEl(c, linkName, cardIdx) {
var rar = String(c.rarity || 'common').toLowerCase();
if (!LOBBY_EVIDENCE_RARITY[rar]) rar = 'common';
var nm = linkName || '?';
var icon = LOBBY_EVIDENCE_CARD_ICONS[cardIdx] || '🔎';
var card = document.createElement('div');
card.className = 'es-card rarity-' + rar;
card.innerHTML =
'<div class="es-card-head"><div class="ico" aria-hidden="true"></div>' +
'<div class="nm"><div class="th"></div><div class="en"></div></div></div>' +
'<div class="es-card-art" aria-hidden="true">◆</div>' +
'<p class="es-card-desc"></p>' +
'<div class="es-card-link"><div class="avatar"></div><div class="sname"></div><div class="label">Link</div></div>';
card.querySelector('.ico').textContent = icon;
card.querySelector('.th').textContent = c.titleTh || '';
card.querySelector('.en').textContent = c.titleEn ? '(' + c.titleEn + ')' : '';
card.querySelector('.es-card-desc').textContent = c.body || '';
card.querySelector('.avatar').textContent = nm.charAt(0);
card.querySelector('.sname').textContent = nm;
return card;
}
function esRenderRevealPlayers(members, picks, suspectData) {
var root = document.getElementById('es-players');
if (!root) return;
root.textContent = '';
var sd = suspectData || { linkName: '?', cards: [] };
(members || []).forEach(function (m) {
var col = document.createElement('div');
col.className = 'es-player';
col.setAttribute('data-member-id', m.id || '');
var crown = m.isHost ? '<span class="host-icon"></span>' : '';
var nick = String(m.nickname || '').toUpperCase();
var nameEl = document.createElement('div');
nameEl.className = 'es-player-name';
nameEl.innerHTML = crown + nick;
col.appendChild(nameEl);
var sel = (picks && picks[m.id]) || [];
if (!sel.length) {
var none = document.createElement('div');
none.className = 'es-rev-none';
none.textContent = '(ไม่ได้ส่ง)';
col.appendChild(none);
} else {
sel.forEach(function (ci) {
var c = (sd.cards || [])[ci];
if (c) col.appendChild(esRevealCardEl(c, sd.linkName, ci));
});
}
root.appendChild(col);
});
}
function es3RenderMembers(submittedIds, readyIds, revealMode) {
if (revealMode) {
var ready = readyIds || [];
document.querySelectorAll('#es-players .es-player').forEach(function (col) {
var mid = col.getAttribute('data-member-id');
var watching = !!(mid && ready.indexOf(mid) < 0);
col.classList.toggle('is-watching', watching);
var badge = col.querySelector('.es-watch-badge');
if (watching) {
if (!badge) {
badge = document.createElement('div');
badge.className = 'es-watch-badge';
badge.textContent = 'กำลังดู..';
var anchor = col.querySelector('.es-card, .es-rev-none');
if (anchor) col.insertBefore(badge, anchor);
else col.appendChild(badge);
}
} else if (badge) badge.remove();
});
return;
}
var root = document.getElementById('es3-ps-row'); if (!root) return;
root.textContent = '';
var SC = '/Main-Lobby/IMAGE/Showcard/';
(tmState.members || []).forEach(function (m) {
var d = document.createElement('div');
d.className = 'tm-member' + (m.id === socket.id ? ' tm-me' : '');
var wrap = document.createElement('div');
wrap.className = 'es3-ps' + (m.id === socket.id ? ' is-me' : '');
var done = revealMode ? (readyIds && readyIds.indexOf(m.id) >= 0) : (submittedIds && submittedIds.indexOf(m.id) >= 0);
if (done) d.classList.add('tm-ready');
var SC = '/Main-Lobby/IMAGE/Showcard/';
var crown = m.isHost ? '<span class="tm-crown"><img src="' + SC + 'host-icon.png" alt=""></span>' : '';
var stat = done
? '<img src="' + SC + 'ready-icon.png" alt=""> พร้อม'
: '<img src="' + SC + 'loading.png" alt=""> ' + (revealMode ? 'กำลังดู..' : 'กำลังเลือก..');
d.innerHTML = '<div class="tm-mname">' + crown + (m.nickname || '') + '</div><div class="tm-mstat">' + stat + '</div>';
root.appendChild(d);
var crown = m.isHost ? '<span class="host-icon"></span>' : '';
var nick = String(m.nickname || '').toUpperCase();
if (done) {
wrap.innerHTML =
'<div class="es3-ps-name">' + crown + nick + '</div>' +
'<div class="es3-ps-card is-ready">' +
'<img class="card-bg" src="' + SC + 'card-bg.png" alt="">' +
'<img class="status-icon" src="' + SC + 'ready-icon.png" alt="พร้อม">' +
'</div>';
} else {
wrap.innerHTML =
'<div class="es3-ps-name">' + crown + nick + '</div>' +
'<div class="es3-ps-card is-loading">' +
'<img class="card-bg" src="' + SC + 'card-bg.png" alt="">' +
'<img class="loading-icon" src="' + SC + 'loading.png" alt="">' +
'<img class="loading-text" src="' + SC + 'loading-txt.png" alt="กำลังเลือก">' +
'</div>';
}
root.appendChild(wrap);
});
}
@@ -4454,68 +4613,76 @@
var SC = '/Main-Lobby/IMAGE/Showcard/';
var CS = '/Main-Lobby/IMAGE/Choose%20a%20suspect/';
var sd = tmSuspectData(tmState.round);
document.getElementById('tm-title').textContent = 'การไต่สวน : ปากคำที่ ' + (tmState.round + 1) + ' - ' + (sd.linkName || ('ผู้ต้องสงสัย ' + (tmState.round + 1)));
document.getElementById('tm-sub2').textContent = '';
// avatar ผู้ต้องสงสัย + ชื่อ
var susImg = document.getElementById('tm-sus-img');
document.getElementById('es3-title').textContent = 'การไต่สวน : ปากคำที่ ' + (tmState.round + 1) + ' - ' + (sd.linkName || ('ผู้ต้องสงสัย ' + (tmState.round + 1)));
var susImg = document.getElementById('es3-sus-img');
if (susImg) susImg.src = CS + 'suspect-' + (tmState.round + 1) + '.png';
var susName = document.getElementById('tm-sus-name'); if (susName) susName.textContent = sd.linkName || '';
// กรอบล่าง = tab ของผู้ต้องสงสัยปัจจุบัน
var bottom = document.getElementById('tm-bottom');
if (bottom) { bottom.classList.remove('tm-bottom--reveal'); bottom.style.backgroundImage = 'url(' + SC + 'tab-0' + (tmState.round + 1) + '.png)'; }
document.getElementById('tm-select-wrap').style.display = 'block';
document.getElementById('tm-reveal-wrap').style.display = 'none';
var fr = document.getElementById('tm-force-reveal');
if (fr) fr.style.display = ((data && data.hostId) === socket.id) ? 'inline-block' : 'none';
tmSetStatus('');
// การ์ดของผู้ต้องสงสัยปัจจุบัน (ทุกคนเห็นครบ)
var cardsRoot = document.getElementById('tm-cards'); cardsRoot.textContent = '';
(sd.cards || []).forEach(function (c, i) { cardsRoot.appendChild(tmEvidenceCardEl(c, sd.linkName, i, true)); });
tmUpdateCount();
tmRenderMembers([], [], false);
var susName = document.getElementById('es3-sus-name'); if (susName) susName.textContent = sd.linkName || '';
var stage = ov.querySelector('.es3-stage');
if (stage) stage.classList.remove('es3-stage--reveal');
var revealWrap = document.getElementById('es-reveal-wrap'); if (revealWrap) revealWrap.hidden = true;
var readyBtn = document.getElementById('esBtnReady');
if (readyBtn) { readyBtn.disabled = false; readyBtn.classList.remove('is-active'); }
var tabImg = document.querySelector('#es3-bottom-box img');
if (tabImg) tabImg.src = SC + 'tab-0' + (tmState.round + 1) + '.png';
var btnOpen = document.getElementById('es3BtnOpen');
if (btnOpen) {
var isHost = (data && data.hostId) === socket.id;
btnOpen.classList.toggle('is-hidden', !isHost);
btnOpen.style.display = isHost ? '' : 'none';
}
es3SetStatus('กำลังรอ..ผู้เล่นเลือกหลักฐาน');
var cardsRoot = document.getElementById('es3-cards'); cardsRoot.textContent = '';
(sd.cards || []).forEach(function (c, i) { cardsRoot.appendChild(es3EvidenceCardEl(c, sd.linkName, i, true)); });
es3UpdateCount();
es3RenderMembers([], [], false);
ov.classList.remove('is-hidden');
ov.setAttribute('aria-hidden', 'false');
requestAnimationFrame(syncTestimonyScale);
}
function testimonyStatusUpdate(data) {
if (!data) return;
tmRenderMembers(data.submitted || [], [], false);
es3RenderMembers(data.submitted || [], [], false);
if (data.submitted && data.submitted.length) es3SetStatus('กำลังรอ..ผู้เล่นเลือกหลักฐาน');
}
function testimonyReveal(data) {
tmState.mode = 'reveal';
var ov = ensureTestimonyOverlay();
ov.classList.remove('is-hidden');
ov.setAttribute('aria-hidden', 'false');
if (data && Array.isArray(data.members)) tmState.members = data.members;
document.getElementById('tm-select-wrap').style.display = 'none';
document.getElementById('tm-reveal-wrap').style.display = 'block';
var bottom = document.getElementById('tm-bottom');
if (bottom) { bottom.classList.add('tm-bottom--reveal'); bottom.style.backgroundImage = 'none'; }
document.getElementById('tm-sub2').textContent = '[วิเคราะห์พยานหลักฐานกับทีม ก่อนไปปากคำถัดไป]';
var rd = document.getElementById('tm-ready'); if (rd) rd.disabled = false;
var sd = tmSuspectData(tmState.round);
var SC = '/Main-Lobby/IMAGE/Showcard/';
var grid = document.getElementById('tm-reveal-grid'); grid.textContent = '';
var CS = '/Main-Lobby/IMAGE/Choose%20a%20suspect/';
var sd = tmSuspectData(tmState.round);
var stage = ov.querySelector('.es3-stage');
if (stage) stage.classList.add('es3-stage--reveal');
var revealWrap = document.getElementById('es-reveal-wrap');
if (revealWrap) revealWrap.hidden = false;
var titleEl = document.getElementById('es-popup-title');
if (titleEl) titleEl.textContent = 'การไต่สวน : ปากคำที่ ' + (tmState.round + 1) + ' - ' + (sd.linkName || ('ผู้ต้องสงสัย ' + (tmState.round + 1)));
var susImg = document.getElementById('es-popup-sus-img');
if (susImg) susImg.src = CS + 'suspect-' + (tmState.round + 1) + '.png';
var susName = document.getElementById('es-popup-sus-name');
if (susName) susName.textContent = sd.linkName || '';
var rd = document.getElementById('esBtnReady');
if (rd) { rd.disabled = false; rd.classList.remove('is-active'); }
var picks = (data && data.picks) || {};
(tmState.members || []).forEach(function (m) {
var col = document.createElement('div'); col.className = 'tm-rev-col';
var nm = document.createElement('div'); nm.className = 'tm-rev-name';
nm.innerHTML = (m.isHost ? '<span class="tm-crown"><img src="' + SC + 'host-icon.png" alt=""></span> ' : '') + (m.nickname || '');
col.appendChild(nm);
var sel = picks[m.id] || [];
if (!sel.length) { var none = document.createElement('div'); none.className = 'tm-status'; none.textContent = '(ไม่ได้ส่ง)'; col.appendChild(none); }
sel.forEach(function (ci) { var c = (sd.cards || [])[ci]; if (c) col.appendChild(tmEvidenceCardEl(c, sd.linkName, ci, false)); });
grid.appendChild(col);
});
tmRenderMembers([], [], true);
esRenderRevealPlayers(tmState.members, picks, sd);
es3RenderMembers([], (data && data.ready) || [], true);
requestAnimationFrame(syncTestimonyScale);
}
function testimonyReadyUpdate(data) {
tmRenderMembers([], (data && data.ready) || [], true);
es3RenderMembers([], (data && data.ready) || [], true);
}
function hideTestimonyOverlay() {
var ov = document.getElementById('testimony-overlay');
if (ov) ov.classList.add('is-hidden');
if (ov) {
ov.classList.add('is-hidden');
ov.setAttribute('aria-hidden', 'true');
}
}
function applySuspectSelectionVisual(idx) {
+1 -1
View File
@@ -3214,7 +3214,7 @@
<script src="/app-base.js?v=2"></script>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0306"></script>
<script src="js/play.js?v=0.0459"></script>
<script src="js/play.js?v=0.0460"></script>
<div class="version-tag">v —</div>
</body>
</html>
+20 -16
View File
@@ -11,6 +11,8 @@
<link rel="stylesheet" href="css/profile-popup.css?v=6">
<link rel="stylesheet" href="css/customize-popup.css?v=40">
<link rel="stylesheet" href="css/leaderboard-popup.css?v=2">
<link rel="stylesheet" href="css/testimony-overlay.css?v=5">
<link rel="stylesheet" href="css/evidence-view-overlay.css?v=5">
<style>
html, body.room-lobby-page { margin: 0; padding: 0; overflow: hidden; width: 100%; height: 100%; min-height: 100%; }
#mic-permission-overlay {
@@ -1495,24 +1497,26 @@
<img src="img/btn-mic-mute.png" alt="เปิดเสียง" id="btn-voice-icon-img">
</button>
</div>
<!-- แฟ้มหลักฐาน LobbyB — รูปกรอบ/แท็บจาก /Main-Lobby/IMAGE/See evidence -->
<!-- แฟ้มหลักฐาน LobbyB — layout 06-3-evidence-view (ev-*) -->
<div id="lobby-evidence-overlay" class="lobby-evidence-overlay is-hidden" aria-hidden="true">
<div class="lobby-evidence-backdrop" id="lobby-evidence-backdrop" aria-hidden="true"></div>
<div class="lobby-evidence-dialog" role="dialog" aria-modal="true" aria-labelledby="lobby-evidence-sr-title">
<h2 id="lobby-evidence-sr-title" class="visually-hidden" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);">แฟ้มหลักฐาน</h2>
<div class="lobby-evidence-frame">
<img class="lobby-evidence-bg" src="/Main-Lobby/IMAGE/See%20evidence/evidence-bg.png" alt="" width="1684" height="963" decoding="async">
<button type="button" class="lobby-evidence-close" id="lobby-evidence-close" title="ปิด" aria-label="ปิดแฟ้มหลักฐาน">×</button>
<div class="lobby-evidence-tabs-layer">
<img id="lobby-evidence-tabs-img" class="lobby-evidence-tabs-img" src="/Main-Lobby/IMAGE/See%20evidence/evidence-tab-1.png" alt="" width="1481" height="129" decoding="async">
<div class="lobby-evidence-tab-hits" role="tablist" aria-label="เลือกผู้ต้องสงสัย">
<button type="button" class="lobby-evidence-tab-hit" role="tab" data-evidence-tab="0" aria-selected="true" aria-label="ผู้ต้องสงสัย 1"></button>
<button type="button" class="lobby-evidence-tab-hit" role="tab" data-evidence-tab="1" aria-selected="false" aria-label="ผู้ต้องสงสัย 2"></button>
<button type="button" class="lobby-evidence-tab-hit" role="tab" data-evidence-tab="2" aria-selected="false" aria-label="ผู้ต้องสงสัย 3"></button>
<span class="lobby-evidence-tab-hit-spacer" aria-hidden="true"></span>
</div>
<div class="stage-wrap" role="dialog" aria-modal="true" aria-labelledby="lobby-evidence-sr-title">
<h2 id="lobby-evidence-sr-title" class="visually-hidden">แฟ้มหลักฐาน</h2>
<div class="stage ev-stage">
<div class="layer ev-bg-fallback" aria-hidden="true"></div>
<div class="layer ev-popup">
<img src="/Main-Lobby/IMAGE/See%20evidence/evidence-bg.png" alt="" width="1684" height="963" decoding="async">
</div>
<div class="lobby-evidence-cards-root" id="lobby-evidence-cards-root"></div>
<button type="button" class="layer ev-close" id="lobby-evidence-close" title="ปิด" aria-label="ปิดแฟ้มหลักฐาน"></button>
<div class="layer ev-tabs" id="lobby-evidence-tabs" role="tablist" aria-label="เลือกผู้ต้องสงสัย">
<img class="ev-tab is-active" data-state="1" src="/Main-Lobby/IMAGE/See%20evidence/evidence-tab-1.png" alt="" width="1481" height="129" decoding="async">
<img class="ev-tab" data-state="2" src="/Main-Lobby/IMAGE/See%20evidence/evidence-tab-2.png" alt="" width="1481" height="129" decoding="async">
<img class="ev-tab" data-state="3" src="/Main-Lobby/IMAGE/See%20evidence/evidence-tab-3.png" alt="" width="1481" height="129" decoding="async">
<button type="button" class="ev-tab-click" role="tab" data-evidence-tab="0" aria-selected="true" aria-label="ผู้ต้องสงสัย 1"></button>
<button type="button" class="ev-tab-click" role="tab" data-evidence-tab="1" aria-selected="false" aria-label="ผู้ต้องสงสัย 2"></button>
<button type="button" class="ev-tab-click" role="tab" data-evidence-tab="2" aria-selected="false" aria-label="ผู้ต้องสงสัย 3"></button>
</div>
<div class="layer ev-cards" id="lobby-evidence-cards-root"></div>
</div>
</div>
</div>
@@ -1553,7 +1557,7 @@
<script src="js/display-name.js?v=2"></script>
<script src="js/version.js?v=0.0122"></script>
<script src="js/customize-popup.js?v=29" data-customize-triggers="" data-customize-asset-base="img/03-5-Customize"></script>
<script src="js/room-lobby.js?v=0.0220"></script>
<script src="js/room-lobby.js?v=0.0227"></script>
<div class="version-tag">v —</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

@@ -0,0 +1,120 @@
/* =========================================================
Base CSS Cut [Justice Game] Mockup HTML
Base resolution : 1920 x 1080 (16:9)
ใช้ <div class="stage"> เป็นกรอบหลัก 1920x1080
แล้ว scale ด้วย JS (assets/js/scale.js) ให้พอดี viewport
========================================================= */
@font-face {
font-family: "NotoSansThai";
src: url("../../Font/NotoSansThai-Medium.ttf") format("truetype");
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "NotoSansThai";
src: url("../../Font/NotoSansThai-SemiBold.ttf") format("truetype");
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "NotoSansThai";
src: url("../../Font/NotoSansThai-Bold.ttf") format("truetype");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "NotoSansThai";
src: url("../../Font/NotoSansThai-ExtraBold.ttf") format("truetype");
font-weight: 800;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "NotoSansThai";
src: url("../../Font/NotoSansThai-Black.ttf") format("truetype");
font-weight: 900;
font-style: normal;
font-display: swap;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
width: 100%;
height: 100%;
background: #050813;
color: #ffffff;
font-family: "NotoSansThai", "Segoe UI", sans-serif;
overflow: hidden;
user-select: none;
-webkit-font-smoothing: antialiased;
}
img {
display: block;
pointer-events: none;
-webkit-user-drag: none;
}
/* ---------- 1920x1080 Stage ---------- */
.stage-wrap {
position: fixed;
inset: 0;
background: #050813;
overflow: hidden;
}
.stage {
position: absolute;
left: 0;
top: 0;
width: 1920px;
height: 1080px;
transform-origin: 0 0;
/* JS จะคำนวณ scale + translate ให้ stage อยู่กลาง viewport พอดี */
transform: scale(0.5);
}
/* ทุก element ภายใน stage ใช้พิกัด/ขนาดเป็น px ของ 1920x1080 */
.layer {
position: absolute;
}
/* placeholder กรอบกำกับช่องที่ยังไม่มี PNG */
.placeholder {
position: absolute;
border: 2px dashed rgba(255, 255, 255, 0.18);
border-radius: 12px;
color: rgba(255, 255, 255, 0.35);
font-size: 18px;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
background: rgba(255, 255, 255, 0.02);
pointer-events: none;
}
/* ปุ่มทั่วไป */
.btn {
cursor: pointer;
transition: transform 0.15s ease, filter 0.15s ease;
}
.btn:hover {
filter: brightness(1.15);
transform: translateY(-1px);
}
.btn:active {
transform: translateY(1px);
filter: brightness(0.95);
}
@@ -0,0 +1,471 @@
/* =========================================================
evidence-summary-3.css (หน้า 11-1-2 ห้องสรุปหลักฐาน - 3
"การไต่สวน : ปากคำที่ 2 - อริน")
Base: 1920 x 1080
Layout:
• ส่วนบน: box-1 popup (ห้องสรุปหลักฐาน) → suspect + title + 5 player status
• ส่วนล่าง: tab-02 (ผู้ต้องสงสัย 2) → 3 evidence cards + open button
========================================================= */
.es3-stage {
background: #04050d;
}
/* ---------------- พื้นหลังเต็มจอ ---------------- */
.es3-bg {
left: 0;
top: 0;
width: 1920px;
height: 1080px;
}
.es3-bg img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* =========================================================
ส่วนบน: popup (วาดด้วย CSS เพื่อรักษา ratio ทุก size)
========================================================= */
.es3-top-popup {
left: 50px;
top: 25px;
width: 1820px;
height: 295px;
background:
linear-gradient(180deg,
rgba(28, 50, 90, 0.55) 0%,
rgba(15, 30, 60, 0.55) 100%);
border: 2px solid #5bd8ff;
border-radius: 26px;
box-shadow:
inset 0 0 36px rgba(80, 180, 240, 0.18),
0 0 24px rgba(80, 180, 240, 0.35);
}
/* ---------- pink corner brackets ---------- */
.es3-top-popup .corner {
position: absolute;
width: 86px;
height: 86px;
/* border: 5px solid #ff5fd8; */
/* box-shadow: 0 0 18px rgba(255, 95, 220, 0.65), inset 0 0 12px rgba(255, 95, 220, 0.45); */
pointer-events: none;
}
.es3-top-popup .corner.c-tl {
top: -5px;
left: -5px;
border-right: none;
border-bottom: none;
border-top-left-radius: 26px;
}
.es3-top-popup .corner.c-tr {
top: -5px;
right: -5px;
border-left: none;
border-bottom: none;
border-top-right-radius: 26px;
}
.es3-top-popup .corner.c-bl {
bottom: -5px;
left: -5px;
border-right: none;
border-top: none;
border-bottom-left-radius: 26px;
}
.es3-top-popup .corner.c-br {
bottom: -5px;
right: -5px;
border-left: none;
border-top: none;
border-bottom-right-radius: 26px;
}
/* ---------- tab title "ห้องสรุปหลักฐาน" ---------- */
.es3-popup-tab {
position: absolute;
left: 50%;
top: -22px;
transform: translateX(-50%);
padding: 8px 70px;
background: linear-gradient(180deg, #2a5588 0%, #1a3a6a 100%);
border: 2px solid #5bd8ff;
border-radius: 14px;
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 22px;
color: #d6e7ff;
text-shadow: 0 0 8px rgba(120, 200, 255, 0.5);
box-shadow:
0 0 14px rgba(80, 180, 240, 0.4),
inset 0 0 8px rgba(80, 180, 240, 0.25);
white-space: nowrap;
z-index: 5;
letter-spacing: 0.5px;
}
/* ---------- กรอบ suspect (ซ้ายของ popup) ---------- */
.es3-suspect {
left: 90px;
top: 38px;
width: 215px;
height: 213px;
z-index: 5;
}
.es3-suspect-frame {
position: absolute;
inset: 0;
pointer-events: none;
}
.es3-suspect-frame img {
width: 100%;
height: 100%;
}
.es3-suspect-portrait {
position: absolute;
left: 26px;
top: 36px;
width: 163px;
height: 138px;
border-radius: 4px;
background:
radial-gradient(circle at 50% 30%, #b89cbf 0%, #6a4d7a 60%, #2b1a36 100%);
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.4);
font-size: 11px;
font-weight: 600;
overflow: hidden;
z-index: 1;
}
.es3-suspect-name {
position: absolute;
left: 20px;
right: 20px;
bottom: 12px;
text-align: center;
/* mockup-3 ใช้สี cyan/ฟ้า (ไม่ใช่ yellow แบบ Somchai) */
color: #cfeeff;
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 22px;
letter-spacing: 1px;
line-height: 1;
z-index: 2;
text-shadow:
0 0 6px rgba(0, 0, 0, 0.85),
0 0 14px rgba(120, 220, 255, 0.55);
}
/* ---------- title ---------- */
.es3-title-wrap {
left: 320px;
top: 72px;
width: 1500px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}
.es3-title {
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 46px;
color: #ffffff;
text-shadow:
0 0 14px rgba(120, 200, 255, 0.55),
0 2px 4px rgba(0, 0, 0, 0.7);
letter-spacing: 0.5px;
line-height: 1;
white-space: nowrap;
}
/* ---------- 5 Player status cards ---------- */
.es3-ps-row {
left: 320px;
top: 148px;
width: 1500px;
height: 170px;
display: grid;
grid-template-columns: repeat(5, 1fr);
column-gap: 24px;
padding: 0 30px;
}
.es3-ps {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
.es3-ps-name {
display: inline-flex;
align-items: center;
gap: 6px;
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 22px;
color: #e6f4ff;
letter-spacing: 1.2px;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
height: 28px;
}
.es3-ps-name .host-icon {
width: 28px;
height: 24px;
background-image: url("../../cut/11-1-2-รวมหลักฐาน/host-icon-2.png");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
/* card-bg.png native 166x209 (portrait, aspect 0.794) → ใช้ portrait เพื่อไม่ให้เพี้ยน */
.es3-ps-card {
position: relative;
width: 110px;
height: 138px;
display: grid;
place-items: center;
}
.es3-ps-card .card-bg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
/* ready-icon.png native 72x82 (aspect 0.878) → คงไว้ใกล้เคียง native */
.es3-ps-card .status-icon {
position: absolute;
width: 78px;
height: auto;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
}
/* loading: ใช้ spinner + ข้อความแยก (loading.png native 42x43 ใกล้เคียง square) */
.es3-ps-card .loading-icon {
position: absolute;
width: 42px;
height: 42px;
top: 28px;
left: 50%;
transform: translateX(-50%);
z-index: 2;
animation: es3-spin 1.4s linear infinite;
opacity: 0.55;
}
@keyframes es3-spin {
to { transform: translateX(-50%) rotate(360deg); }
}
/* loading-txt.png native 86x24 (aspect 3.58) → ขนาด proportional */
.es3-ps-card .loading-text {
position: absolute;
width: 86px;
height: auto;
bottom: 18px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
opacity: 0.7;
}
/* =========================================================
ส่วนล่าง: tab-02 + content
tab-02.png native 1600x551 (aspect 2.90:1)
→ ใช้ 1600x580 (aspect 2.76:1) คลาดเคลื่อนเพียง 5% เทียบกับเดิม 28%
========================================================= */
.es3-bottom-box {
left: 160px;
bottom: 0;
width: 1600px;
height: 580px;
}
.es3-bottom-box img {
width: 100%;
height: 100%;
}
/* ---------- text แถวบน ของ box (ใต้ tabs) ---------- */
.es3-evidence-text {
left: 200px;
top: 583px;
width: 720px;
height: 36px;
display: flex;
align-items: center;
}
/* txt-2.png native 708x84 (aspect 8.43) → ใช้ height-based เพื่อรักษา aspect */
.es3-evidence-text img {
height: 100%;
width: auto;
}
.es3-counter {
left: 1409px;
top: 626px;
width: 320px;
height: 36px;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 30px;
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 24px;
color: #b7e6ff;
letter-spacing: 0.3px;
}
/* ---------- 3 evidence cards ---------- */
.es3-cards {
left: 200px;
top: 635px;
width: 800px;
height: 380px;
display: flex;
gap: 22px;
}
.es3-card {
position: relative;
width: 240px;
height: 380px;
border-radius: 12px;
background: linear-gradient(180deg, #cfd5dd 0%, #9ea7b4 100%);
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
overflow: hidden;
color: #1b2030;
border: 3px solid rgba(150, 165, 185, 0.55);
transition: box-shadow 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
cursor: pointer;
}
.es3-card:hover {
transform: translateY(-2px);
}
/* การ์ดที่เลือก: เรืองแสง cyan สว่างชัด เหมือน mockup */
.es3-card.is-selected {
border-color: #6df0ff;
border-width: 4px;
box-shadow:
0 0 0 2px rgba(109, 240, 255, 0.55),
0 0 28px rgba(91, 216, 255, 0.85),
0 0 60px rgba(91, 216, 255, 0.35),
0 6px 18px rgba(0, 0, 0, 0.45);
background: linear-gradient(180deg, #d8e6f0 0%, #a8b8c8 100%);
}
.es3-card-head {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 10px;
background: rgba(255, 255, 255, 0.55);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
.es3-card-head .ico {
width: 28px;
height: 28px;
background: rgba(0, 0, 0, 0.55);
color: #fff;
border-radius: 6px;
display: grid;
place-items: center;
font-size: 15px;
font-weight: 700;
}
.es3-card-head .nm {
line-height: 1.05;
}
.es3-card-head .nm .th {
font-size: 14px;
font-weight: 700;
}
.es3-card-head .nm .en {
font-size: 10px;
font-weight: 500;
color: #444;
}
.es3-card-art {
height: 170px;
margin: 8px;
border-radius: 6px;
background: #707a8a;
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.45);
font-size: 12px;
font-weight: 600;
text-align: center;
}
.es3-card-desc {
padding: 8px 12px;
font-size: 12px;
line-height: 1.3;
color: #2a2f3c;
font-weight: 500;
text-align: center;
flex: 1;
}
.es3-card-link {
margin: 4px 8px 8px;
padding: 5px 8px;
background: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(0, 0, 0, 0.18);
border-radius: 6px;
display: flex;
align-items: center;
gap: 8px;
font-size: 11px;
}
.es3-card-link .avatar {
width: 20px;
height: 20px;
border-radius: 50%;
background: #4a5566;
}
.es3-card-link .sname {
font-weight: 700;
color: #1b2030;
}
.es3-card-link .stars {
margin-left: auto;
color: #444;
font-weight: 700;
}
/* ---------- Status text + open button ---------- */
.es3-status-text {
left: 1243px;
top: 915px;
width: 460px;
text-align: right;
font-family: "NotoSansThai", sans-serif;
font-weight: 600;
font-size: 18px;
color: #ff5f8a;
letter-spacing: 0.3px;
text-shadow: 0 0 8px rgba(255, 80, 130, 0.4);
}
/* btn-open-card.png native 421x126 (aspect 3.34) → ใช้ขนาด proportional */
.es3-btn-open {
left: 1329px;
top: 944px;
width: 400px;
height: 120px;
}
.es3-btn-open img {
width: 100%;
height: 100%;
}
/* ---------- placeholder mic (อยู่มุมขวาล่างนอก box) ---------- */
.es3-ph-mic {
left: 1830px;
bottom: 10px;
width: 70px;
height: 90px;
}
@@ -0,0 +1,341 @@
/* =========================================================
evidence-summary.css (หน้า 11-1-2 ห้องสรุปหลักฐาน)
Base: 1920 x 1080
Asset: cut/11-1-2-รวมหลักฐาน/
- bg-showcard.png 1921x1081 (พื้นหลังห้องประชุม)
- popup-0.png 1680x1036 (กรอบ popup หลัก)
- box-1.png 1685x580 (กรอบสำรอง ใช้สำหรับ pop-up อื่น)
- suspect-bg.png 291x289 (กรอบรูปผู้ต้องสงสัย)
- host-icon.png 31x28 (มงกุฎ host)
- host-icon-2.png 44x30 (มงกุฎ host ขนาดใหญ่)
- card-bg.png 166x209 (กรอบการ์ดเปล่า)
- card-back.png 117x161 (หลังการ์ด)
- name-frame.png 141x56
- name-frame-2.png 194x71
- btn-ready.png 321x126
- btn-ready-active.png 321x126
- btn-open-card.png 421x126
- btn-start-vote.png 430x151
- btn-send.png 351x151
- ready-icon.png 72x82
- loading.png 42x43
- loading-txt.png 86x24
- txt-2.png 708x84
- tab-01/02/03.png 1600x551
========================================================= */
.es-stage {
background: #04050d;
}
/* ---------------- พื้นหลังเต็มจอ ---------------- */
.es-bg {
left: 0;
top: 0;
width: 1920px;
height: 1080px;
}
.es-bg img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* ---------------- กรอบ popup หลัก ---------------- */
.es-popup {
left: 120px;
top: 22px;
width: 1680px;
height: 1036px;
}
.es-popup img {
width: 100%;
height: 100%;
}
/* ---------------- ส่วน header ผู้ต้องสงสัย ---------------- */
/* mockup: กรอบ suspect โผล่เหนือ popup เล็กน้อย + ลงไปจนถึงระดับ JACKSON
asset native 291x289 → แสดง 230x228 ≈ 0.79x
suspect-bg.png มี marker ภายใน:
- กรอบรูปภายใน: padding ~9% รอบด้าน → 20px
- แถบชื่อด้านล่าง: ~22% ของความสูง → ~50px */
.es-suspect {
left: 150px;
top: 35px;
width: 230px;
height: 228px;
z-index: 5;
}
.es-suspect-frame {
position: absolute;
inset: 0;
pointer-events: none;
}
.es-suspect-frame img {
width: 100%;
height: 100%;
}
.es-suspect-portrait {
position: absolute;
/* ภายใน marker ของ suspect-bg (รักษาช่องว่างให้กรอบโชว์ขอบ) */
left: 30px;
top: 40px;
width: 170px;
height: 150px;
border-radius: 4px;
background:
radial-gradient(circle at 50% 35%, #cdb89b 0%, #8f7a63 70%, #2f2620 100%);
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.35);
font-size: 12px;
font-weight: 600;
overflow: hidden;
z-index: 1;
}
.es-suspect-name {
position: absolute;
/* อยู่ในแถบล่าง (height ~50px) */
left: 20px;
right: 20px;
bottom: 12px;
text-align: center;
color: #fff3a8;
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 22px;
letter-spacing: 1px;
line-height: 1;
z-index: 2;
text-shadow:
0 0 6px rgba(0, 0, 0, 0.85),
0 0 14px rgba(255, 200, 0, 0.45);
}
/* ---------------- title ----------------
วางใต้ tab "ห้องสรุปหลักฐาน" ทางขวาของ suspect frame
(ไม่มี panel bg แล้ว ใช้แค่ตัวหนังสือ ตามที่ design ต้องการ) */
.es-title-wrap {
left: 285px;
top: 102px;
width: 1340px;
height: 175px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.es-title {
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 44px;
color: #ffffff;
text-shadow:
0 0 12px rgba(120, 200, 255, 0.5),
0 2px 4px rgba(0, 0, 0, 0.7);
letter-spacing: 0.5px;
line-height: 1;
text-align: center;
white-space: nowrap;
padding: 14px 60px;
}
.es-subtitle {
font-family: "NotoSansThai", sans-serif;
font-weight: 600;
font-size: 22px;
color: #d6e7ff;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
line-height: 1;
text-align: center;
padding: 8px 40px;
}
/* ---------------- ส่วนคอลัมน์ผู้เล่น ---------------- */
.es-players {
left: 120px;
top: 300px;
width: 1680px;
height: 650px;
display: grid;
grid-template-columns: repeat(5, 1fr);
column-gap: 24px;
padding: 0 70px;
}
.es-player {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
/* ชื่อผู้เล่น */
.es-player-name {
position: relative;
display: inline-flex;
align-items: center;
gap: 8px;
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 30px;
color: #e6f4ff;
letter-spacing: 1.5px;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
height: 40px;
}
.es-player-name .host-icon {
width: 36px;
height: 32px;
background-image: url("../../cut/11-1-2-รวมหลักฐาน/host-icon-2.png");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
/* การ์ด */
.es-card {
position: relative;
width: 220px;
height: 275px;
border-radius: 10px;
background: linear-gradient(180deg, #cfd5dd 0%, #b2bac4 100%);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
overflow: hidden;
color: #1b2030;
border: 3px solid rgba(150, 200, 255, 0.7);
}
.es-card.rarity-common {
border-color: #9aa3b2;
}
.es-card.rarity-rare {
border-color: #6cc7ff;
box-shadow: 0 0 16px rgba(80, 175, 240, 0.4);
}
.es-card.rarity-legendary {
border-color: #f1b94a;
background: linear-gradient(180deg, #e4d3a8 0%, #c7a667 100%);
box-shadow: 0 0 18px rgba(241, 185, 74, 0.55);
}
.es-card-head {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 8px;
background: rgba(255, 255, 255, 0.45);
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
}
.es-card-head .ico {
width: 24px;
height: 24px;
background: rgba(0, 0, 0, 0.55);
color: #fff;
border-radius: 5px;
display: grid;
place-items: center;
font-size: 13px;
font-weight: 700;
}
.es-card-head .nm {
line-height: 1;
}
.es-card-head .nm .th {
font-size: 13px;
font-weight: 700;
color: #1b2030;
}
.es-card-head .nm .en {
font-size: 9px;
font-weight: 500;
color: #444;
}
.es-card-art {
flex: 1;
margin: 6px;
border-radius: 6px;
background: #707a8a;
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.5);
font-size: 11px;
font-weight: 600;
text-align: center;
}
.es-card-desc {
padding: 4px 8px;
font-size: 10px;
line-height: 1.25;
color: #2a2f3c;
font-weight: 500;
text-align: center;
min-height: 32px;
}
.es-card-link {
margin: 4px 6px 6px;
padding: 4px 6px;
background: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 5px;
display: flex;
align-items: center;
gap: 6px;
}
.es-card-link .avatar {
width: 18px;
height: 18px;
border-radius: 50%;
background: #4a5566;
}
.es-card-link .sname {
font-size: 11px;
font-weight: 700;
color: #1b2030;
}
.es-card-link .label {
margin-left: auto;
font-size: 9px;
color: #444;
font-weight: 700;
}
/* ---------------- ปุ่ม READY ----------------
ปุ่ม native 321x126 → ลดให้พอดี mockup ขนาด 280x96
วางคร่อมเส้น cyan ล่างของ popup ตรงกลาง
*/
.es-ready {
left: 818px;
top: 951px;
width: 280px;
height: 96px;
z-index: 10;
}
.es-ready img {
width: 100%;
height: 100%;
}
.es-ready .ready-default {
opacity: 1;
transition: opacity 0.2s;
}
.es-ready .ready-active {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.2s;
}
.es-ready.is-active .ready-default {
opacity: 0;
}
.es-ready.is-active .ready-active {
opacity: 1;
}
/* ---------------- placeholder ---------------- */
.es-ph-mic {
left: 1820px;
top: 940px;
width: 80px;
height: 100px;
}
@@ -0,0 +1,267 @@
/* =========================================================
evidence-view.css (หน้า 06-3 ดูหลักฐาน)
Base: 1920 x 1080
Asset: cut/06-3-ดูหลักฐาน/
- evidence-bg.png 1684x963
- evidence-tab-1.png 1481x129
- evidence-tab-2.png 1481x129
- evidence-tab-3.png 1481x129
========================================================= */
.ev-stage {
background: #0a0f24;
}
/* พื้นหลังแบบไล่สี (เลียนแบบฉาก mockup) */
.ev-bg-fallback {
position: absolute;
inset: 0;
background:
radial-gradient(ellipse at 50% 35%, #1c2547 0%, #0a0f24 60%, #04050d 100%);
}
/* ----------- popup กรอบหลักฐาน ----------- */
.ev-popup {
left: 118px;
top: 58px;
width: 1684px;
height: 963px;
}
.ev-popup img {
width: 100%;
height: 100%;
}
/* ปุ่มปิด (X) – วาดอยู่ใน evidence-bg.png แล้ว แค่เพิ่ม hotspot ให้คลิกได้
พิกัดเทียบกับ stage 1920x1080 (มุมขวาบนของ popup) */
.ev-close {
left: 1640px;
top: 145px;
width: 90px;
height: 90px;
border-radius: 14px;
cursor: pointer;
background: rgba(0, 0, 0, 0);
transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
}
.ev-close:hover {
background: rgba(255, 110, 220, 0.18);
box-shadow: 0 0 18px rgba(255, 110, 220, 0.55);
}
.ev-close:active {
transform: scale(0.94);
}
/* ----------- แถว tab ----------- */
.ev-tabs {
left: 220px;
top: 200px;
width: 1481px;
height: 129px;
}
.ev-tab {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.2s ease;
cursor: pointer;
}
.ev-tab.is-active {
opacity: 1;
}
/* hotspot คลิกของแต่ละ tab (อิงตามสัดส่วนใน evidence-tab-1.png) */
.ev-tab-click {
position: absolute;
top: 5px;
height: 110px;
width: 240px;
cursor: pointer;
}
.ev-tab-click[data-tab="1"] {
left: 0;
}
.ev-tab-click[data-tab="2"] {
left: 260px;
}
.ev-tab-click[data-tab="3"] {
left: 520px;
}
/* ----------- 3 การ์ดหลักฐาน ----------- */
.ev-cards {
left: 270px;
top: 380px;
width: 940px;
height: 560px;
display: flex;
gap: 24px;
}
.ev-card {
position: relative;
width: 296px;
height: 540px;
border-radius: 14px;
background: linear-gradient(180deg, #cfd5dd 0%, #b2bac4 100%);
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
overflow: hidden;
font-family: "NotoSansThai", sans-serif;
color: #1c2235;
}
/* rarity / ขอบนอก */
.ev-card.rarity-common {
border: 4px solid #9aa3b2;
}
.ev-card.rarity-rare {
border: 4px solid #6cc7ff;
background: linear-gradient(180deg, #d2dde7 0%, #adbecd 100%);
box-shadow: 0 0 24px rgba(80, 175, 240, 0.35);
}
.ev-card.rarity-legendary {
border: 4px solid #f1b94a;
background: linear-gradient(180deg, #e4d3a8 0%, #c7a667 100%);
box-shadow: 0 0 28px rgba(241, 185, 74, 0.55);
}
.ev-card-head {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
background: rgba(255, 255, 255, 0.55);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
.ev-card-head .icon {
width: 34px;
height: 34px;
border-radius: 8px;
background: rgba(0, 0, 0, 0.55);
display: grid;
place-items: center;
color: #fff;
font-size: 18px;
font-weight: 700;
}
.ev-card-head .name {
line-height: 1.05;
}
.ev-card-head .name .th {
font-size: 18px;
font-weight: 700;
}
.ev-card-head .name .en {
font-size: 12px;
font-weight: 500;
color: #444;
}
.ev-card-art {
height: 290px;
margin: 8px;
border-radius: 8px;
background: #707a8a;
color: rgba(255, 255, 255, 0.55);
font-size: 14px;
font-weight: 600;
display: grid;
place-items: center;
text-align: center;
}
.ev-card-desc {
padding: 8px 12px 6px;
font-size: 13px;
font-weight: 500;
color: #2a2f3c;
line-height: 1.35;
flex: 1;
text-align: center;
}
.ev-card-link {
margin: 6px 8px 8px;
padding: 6px 8px;
border-radius: 8px;
background: linear-gradient(180deg, #e8edf3 0%, #c8cfdb 100%);
border: 1px solid rgba(0, 0, 0, 0.18);
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.ev-card-link .label {
font-size: 11px;
font-weight: 700;
color: #2a2f3c;
}
.ev-card-link .stars {
color: #c79e3a;
font-size: 11px;
font-weight: 700;
}
.ev-card-link .suspect {
display: flex;
align-items: center;
gap: 6px;
margin-top: 4px;
background: rgba(255, 255, 255, 0.7);
padding: 4px 8px;
border-radius: 6px;
width: 100%;
}
.ev-card-link .suspect .avatar {
width: 22px;
height: 22px;
border-radius: 50%;
background: #4a5566;
}
.ev-card-link .suspect .sname {
font-size: 13px;
font-weight: 700;
}
.ev-card-link-wrap {
margin: 6px 8px 10px;
}
/* ---------- placeholder ของส่วนที่ยังไม่มี PNG ---------- */
.ev-ph-header {
left: 0;
top: 0;
width: 1920px;
height: 60px;
}
.ev-ph-leftbar {
left: 12px;
top: 12px;
width: 70px;
height: 220px;
}
.ev-ph-rightbar {
left: 1838px;
top: 12px;
width: 70px;
height: 220px;
}
.ev-ph-character {
left: 1240px;
top: 280px;
width: 360px;
height: 600px;
}
.ev-ph-bottom-left {
left: 18px;
top: 920px;
width: 220px;
height: 140px;
}
.ev-ph-bottom-right {
left: 1680px;
top: 920px;
width: 220px;
height: 140px;
}
@@ -0,0 +1,378 @@
/* =========================================================
suspect-vote.css
ใช้กับ 2 หน้า:
• 11-2-suspect-vote.html (พิจารณาคดี - เลือกคนร้าย)
• 11-3-vote-result.html (พิจารณาคดี - ผลคะแนนโหวต)
Base: 1920 x 1080
ทุก asset PNG ใช้ขนาด/aspect-ratio ตาม native
========================================================= */
.sv-stage {
background: #04050d;
}
/* ---------------- พื้นหลังเต็มจอ ---------------- */
.sv-bg {
left: 0;
top: 0;
width: 1920px;
height: 1080px;
}
.sv-bg img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* =========================================================
Top HUD (มุมซ้ายบน) - handcuff icon + X1
========================================================= */
.sv-handcuff {
left: 16px;
top: 14px;
width: 160px;
height: 56px;
display: flex;
align-items: center;
gap: 8px;
padding: 0 14px;
background: linear-gradient(180deg, rgba(20, 45, 90, 0.65) 0%, rgba(10, 25, 55, 0.65) 100%);
border: 1.5px solid rgba(100, 220, 255, 0.6);
border-radius: 12px;
box-shadow:
inset 0 0 12px rgba(80, 200, 255, 0.25),
0 0 12px rgba(80, 200, 255, 0.3);
}
.sv-handcuff .ico {
width: 36px;
height: 36px;
border-radius: 8px;
background:
radial-gradient(circle at 30% 30%, #7be0ff 0%, #2ba0d4 60%, #0e3a5a 100%);
border: 1px solid rgba(120, 240, 255, 0.7);
display: grid;
place-items: center;
color: #fff;
font-size: 18px;
font-weight: 800;
}
.sv-handcuff .x {
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 24px;
color: #ffffff;
text-shadow: 0 0 8px rgba(120, 220, 255, 0.6);
letter-spacing: 1px;
}
/* =========================================================
Top-right - ลงมติแล้ว : 4/5
========================================================= */
.sv-vote-count {
right: 30px;
top: 28px;
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 28px;
color: #ffffff;
letter-spacing: 0.5px;
text-shadow: 0 0 10px rgba(120, 200, 255, 0.5);
}
.sv-vote-count .num {
color: #ff5588;
font-size: 36px;
font-weight: 800;
margin-left: 6px;
text-shadow: 0 0 12px rgba(255, 80, 140, 0.55);
}
/* =========================================================
Title bar (พิจารณาคดี) - วางใน title bar ของ roomvote-bg
========================================================= */
.sv-title {
/* roomvote-txt.png 482x142 (aspect 3.39) → ใช้ความสูงพอดี title bar */
left: 50%;
top: 145px;
transform: translateX(-50%);
height: 80px;
display: flex;
align-items: center;
justify-content: center;
z-index: 3;
}
.sv-title img {
height: 100%;
width: auto;
}
/* ---------- subtitle [เลือกผู้ร้าย...] / [ผลการพิจารณาคดี] ---------- */
.sv-subtitle {
left: 50%;
top: 250px;
transform: translateX(-50%);
height: 30px;
display: flex;
align-items: center;
justify-content: center;
z-index: 3;
}
.sv-subtitle img {
height: 100%;
width: auto;
}
/* =========================================================
3 Suspect cards (กลางจอ)
========================================================= */
.sv-cards {
left: 220px;
top: 295px;
width: 1480px;
height: 560px;
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 110px;
}
/* ---------- การ์ดเดี่ยว ---------- */
.sv-card {
position: relative;
width: 260px;
height: 440px;
justify-self: center;
border-radius: 14px;
background:
radial-gradient(circle at 50% 30%, rgba(60, 140, 220, 0.45) 0%, rgba(20, 50, 95, 0.55) 70%, rgba(8, 20, 45, 0.65) 100%),
linear-gradient(180deg, #14305c 0%, #0a1c3d 100%);
border: 2px solid #4dc0ff;
box-shadow:
inset 0 0 18px rgba(100, 200, 255, 0.35),
0 8px 22px rgba(0, 0, 0, 0.55);
color: #d7eaff;
/* overflow: visible เพื่อให้ปุ่ม "เลือกแล้ว" ที่อยู่ใต้การ์ดแสดงได้ */
overflow: visible;
display: flex;
flex-direction: column;
transition: transform 0.15s ease, box-shadow 0.2s ease, border-color 0.2s ease;
cursor: pointer;
}
.sv-card:hover {
transform: translateY(-3px);
}
/* ---------- ส่วนหัวของการ์ด: SUSPECT: NAME + age + icon ---------- */
.sv-card-head {
position: relative;
padding: 10px 12px;
display: flex;
align-items: center;
gap: 8px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0));
border-bottom: 1px solid rgba(120, 220, 255, 0.25);
}
.sv-card-head .age {
width: 30px;
height: 30px;
border-radius: 50%;
background: linear-gradient(180deg, #ffe27a, #f3a23a);
color: #4a2a08;
font-weight: 800;
font-size: 14px;
display: grid;
place-items: center;
box-shadow: 0 0 6px rgba(255, 200, 80, 0.55);
}
.sv-card-head .label {
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 15px;
color: #ffffff;
letter-spacing: 0.6px;
text-shadow: 0 0 6px rgba(120, 220, 255, 0.6);
flex: 1;
}
.sv-card-head .corner-ico {
width: 22px;
height: 22px;
border-radius: 4px;
background: rgba(120, 220, 255, 0.2);
border: 1px solid rgba(120, 220, 255, 0.5);
}
/* ---------- ภาพ portrait ของผู้ต้องสงสัย (placeholder) ---------- */
.sv-card-portrait {
flex: 1;
margin: 8px;
border-radius: 8px;
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.55);
font-family: "NotoSansThai", sans-serif;
font-size: 12px;
text-align: center;
line-height: 1.3;
overflow: hidden;
border: 1px dashed rgba(120, 220, 255, 0.35);
}
.sv-card.suspect-somchai .sv-card-portrait {
background:
radial-gradient(circle at 50% 30%, #cdb89b 0%, #8f7a63 60%, #2f2620 100%);
}
.sv-card.suspect-arin .sv-card-portrait {
background:
radial-gradient(circle at 50% 30%, #b89cbf 0%, #6a4d7a 60%, #2b1a36 100%);
}
.sv-card.suspect-jirapha .sv-card-portrait {
background:
radial-gradient(circle at 50% 30%, #f1bd8e 0%, #b8754a 60%, #4a2614 100%);
}
/* ---------- กล่องชื่อ/คำบรรยายใต้รูป ---------- */
.sv-card-info {
margin: 0 8px 8px;
padding: 8px 10px;
background: rgba(8, 20, 45, 0.7);
border: 1px solid rgba(120, 220, 255, 0.35);
border-radius: 6px;
font-family: "NotoSansThai", sans-serif;
font-size: 11px;
line-height: 1.35;
color: #cfe5ff;
text-align: center;
}
.sv-card-info .nm {
font-weight: 800;
color: #ffffff;
font-size: 13px;
margin-bottom: 2px;
}
.sv-card-info .desc {
color: rgba(207, 229, 255, 0.85);
font-size: 10px;
}
/* ---------- ไอคอนเล็ก ๆ 2 อันด้านล่างการ์ด ---------- */
.sv-card-bottom-icons {
display: flex;
gap: 8px;
padding: 0 12px 10px;
}
.sv-card-bottom-icons .mini {
width: 26px;
height: 26px;
border-radius: 6px;
background: rgba(120, 220, 255, 0.18);
border: 1px solid rgba(120, 220, 255, 0.5);
}
/* ---------- การ์ดที่ "เลือกแล้ว" - green glow + border ---------- */
.sv-card.is-selected {
border-color: #5bff8d;
border-width: 4px;
box-shadow:
0 0 0 2px rgba(91, 255, 141, 0.5),
0 0 28px rgba(91, 255, 141, 0.75),
0 0 60px rgba(91, 255, 141, 0.3),
0 8px 22px rgba(0, 0, 0, 0.55);
}
/* ---------- ปุ่ม "เลือกแล้ว" (btn-selected.png) ใต้การ์ดที่เลือก ---------- */
.sv-btn-selected {
/* btn-selected.png ใช้ความสูง fixed เพื่อรักษา aspect ratio */
position: absolute;
left: 50%;
bottom: -60px;
transform: translateX(-50%);
height: 56px;
width: auto;
z-index: 4;
pointer-events: none;
}
.sv-btn-selected img {
height: 100%;
width: auto;
filter: drop-shadow(0 0 12px rgba(91, 255, 141, 0.6));
}
/* =========================================================
ผลการตัดสิน (แสดงเฉพาะหน้า 11-3)
วางแถวเดียวกัน 3 ช่อง ใต้การ์ด 3 ใบ
========================================================= */
.sv-results {
left: 220px;
top: 760px;
width: 1480px;
height: 60px;
z-index: 4;
}
.sv-results-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 110px;
align-items: center;
}
.sv-result-text {
text-align: center;
font-family: "NotoSansThai", sans-serif;
font-weight: 700;
font-size: 20px;
color: #ffffff;
text-shadow: 0 0 8px rgba(120, 200, 255, 0.5);
letter-spacing: 0.5px;
justify-self: center;
width: 260px;
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
.sv-result-text .label {
color: #cfe5ff;
}
.sv-result-text .marks {
color: #ffffff;
font-weight: 800;
letter-spacing: 6px;
font-size: 32px;
line-height: 1;
text-shadow: 0 0 10px rgba(120, 220, 255, 0.75);
min-width: 60px;
text-align: left;
}
/* =========================================================
Bottom center counter (18 / 5)
อยู่ในส่วนล่างของ bg ที่มีปุ่มกลางแถบ
========================================================= */
.sv-center-counter {
left: 50%;
bottom: 36px;
transform: translateX(-50%);
font-family: "NotoSansThai", sans-serif;
font-weight: 800;
font-size: 22px;
color: #ffffff;
text-shadow: 0 0 8px rgba(120, 200, 255, 0.6);
z-index: 3;
}
/* =========================================================
Bottom-right - mic placeholder
========================================================= */
.sv-mic {
right: 60px;
bottom: 50px;
width: 64px;
height: 64px;
border-radius: 12px;
background: linear-gradient(180deg, rgba(80, 30, 50, 0.6), rgba(40, 10, 25, 0.6));
border: 1.5px solid rgba(255, 110, 160, 0.6);
box-shadow:
inset 0 0 10px rgba(255, 110, 160, 0.35),
0 0 12px rgba(255, 90, 140, 0.35);
display: grid;
place-items: center;
color: #ffb0c8;
font-size: 28px;
z-index: 4;
}
@@ -0,0 +1,27 @@
/**
* scale.js - ปรับขนาด .stage (1920x1080) ให้พอดี viewport
* รักษาอัตราส่วน 16:9 เสมอ (letterbox ถ้าจำเป็น)
*/
(function () {
const BASE_W = 1920;
const BASE_H = 1080;
function fit() {
const stage = document.querySelector(".stage");
if (!stage) return;
const vw = window.innerWidth;
const vh = window.innerHeight;
const scale = Math.min(vw / BASE_W, vh / BASE_H);
const scaledW = BASE_W * scale;
const scaledH = BASE_H * scale;
const tx = (vw - scaledW) / 2;
const ty = (vh - scaledH) / 2;
// transform-origin: 0 0
stage.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;
}
window.addEventListener("resize", fit);
window.addEventListener("orientationchange", fit);
document.addEventListener("DOMContentLoaded", fit);
window.addEventListener("load", fit);
})();

Some files were not shown because too many files have changed in this diff Show More