LiamKhoaLe's picture
Upd JS
f1ef6af
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: system-ui, sans-serif;
}
body {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
padding: 1rem;
max-width: 960px;
margin-inline: auto;
}
header {
text-align: center;
}
#upload-section {
display: flex;
flex-wrap: wrap;
gap: 2rem;
justify-content: center;
width: 100%;
}
.upload-wrapper {
border: 2px dashed #aaa;
border-radius: 0.75rem;
padding: 1rem;
flex: 1 1 280px;
max-width: 420px;
text-align: center;
}
.file-block {
display: flex;
flex-direction: column;
align-items: center;
}
input[type="file"] {
margin-block: 0.75rem;
}
#action-container {
margin-top: 1rem;
}
button.generate-btn {
padding: 0.5rem 1.25rem;
font-size: 1.1rem;
background: #1e88e5;
color: #fff;
border: none;
border-radius: 0.5rem;
cursor: pointer;
}
button.generate-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.loader {
border: 4px solid #f3f3f3;
border-top: 4px solid #1e88e5;
border-radius: 50%;
width: 42px;
height: 42px;
animation: spin 1s linear infinite;
margin-inline: auto;
margin-top: 1rem;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
#results {
position: relative;
width: 100%;
margin-top: 2rem;
display: flex;
gap: 2rem;
justify-content: flex-start;
overflow-x: auto;
}
/* ─── RESULT LAYOUT ───────────────────────────────── */
#result-layout{
display:flex;
justify-content:center;
align-items:center;
position:relative;
width:100%;
padding:2rem 0;
gap:clamp(3rem,8vw,6rem); /* ⬅︎ lớn hơn ⇒ label + line không bị chạm */
overflow-x:auto; /* nếu màn nhỏ sẽ scroll ngang */
}
/* Tester đứng giữa cột trái */
#tester-column{
display:flex;
justify-content:center;
align-items:center;
}
/* Sampler xếp cột phải */
#sampler-column{
display:flex;
flex-direction:column;
gap:2.5rem; /* giãn từng ảnh */
align-items:center;
}
/* Ảnh vuông */
.square{
width:120px;
height:120px;
border-radius:0.5rem;
overflow:hidden;
flex-shrink:0;
}
.square img{width:100%;height:100%;object-fit:cover}
/* Canvas + nhãn */
#lines-canvas{position:absolute;top:0;left:0;pointer-events:none;z-index:0}
.label{position:absolute;transform:translate(-50%,-50%);z-index:1}
/* ─── MOBILE ≤600 px: giữ hai cột nhưng thu nhỏ ảnh ─── */
@media (max-width:600px){
#result-layout{gap:2rem} /* hẹp lại */
.square{width:72px;height:72px;} /* nhỏ hơn */
}
.tester-node {
box-shadow: 0 0 10px rgba(59,130,246,0.5);
}