mancala/apps/frontend/src/components/board/BoardView.css
Halit Aksoy e3e7916265 feat(frontend): draw the new board
Pits and stores are wells with scattered stones and count badges, the
viewer's store on the right. Below 600 px the board stands upright.
Playable pits preview their move on hover, animated pits are ringed and
the pit of the last move has a dashed ring.
2026-10-16 09:37:50 +03:00

188 lines
4.6 KiB
CSS

/* The board. Sized by its container: pits are a ninth of the width, up to 124 px. Below 600 px the board stands
upright: the top player's store at the top, the viewer's at the bottom, the viewer's pits in the left column. */
.bwrap { container-type: inline-size; }
.board {
--pit: min(124px, calc(100cqw / 9.7));
--pw: var(--pit);
--ph: var(--pit);
--stone: calc(var(--ph) * .21);
display: grid;
grid-template-columns: calc(var(--pit) * 1.1) repeat(6, var(--pit)) calc(var(--pit) * 1.1);
grid-template-rows: var(--pit) var(--pit);
column-gap: calc(var(--pit) * .13);
row-gap: calc(var(--pit) * .26);
width: max-content;
margin: 0 auto;
padding: calc(var(--pit) * .22);
border-radius: calc(var(--pit) * .34);
background: var(--boardBg);
box-shadow: var(--boardShadow);
transition: background .3s;
}
.pit {
position: relative;
grid-row: var(--hr);
grid-column: var(--hc);
width: var(--pw);
height: var(--ph);
border-radius: 50%;
border: none;
padding: 0;
margin: 0;
background: var(--pit);
box-shadow: var(--pitShadow);
font: inherit;
color: inherit;
cursor: default;
transition: transform .18s ease, box-shadow .18s ease;
}
.pit.mine { cursor: pointer; }
@media (hover: hover) {
.pit.mine:hover { transform: translateY(-2px); box-shadow: var(--pitShadow), 0 0 0 2px var(--accentSoft); }
}
.pit:focus-visible { outline: 3px solid var(--accent); outline-offset: 4px; }
.pit.pv, .store.pv, .pit.sel { box-shadow: var(--pitShadow), 0 0 0 2px var(--accentSoft); }
.pit.land, .store.land, .pit.drop, .store.drop { box-shadow: var(--pitShadow), 0 0 0 3px var(--accent), 0 0 22px var(--accentGlow); }
.pit.cap, .store.cap { box-shadow: var(--pitShadow), 0 0 0 3px var(--live), 0 0 22px var(--live); }
.pit.last::after {
content: '';
position: absolute;
inset: -7px;
border-radius: 50%;
border: 2px dashed var(--lastRing);
pointer-events: none;
}
.store {
position: relative;
grid-row: 1 / 3;
border-radius: 999px;
background: var(--pit);
box-shadow: var(--pitShadow);
transition: box-shadow .18s;
}
.store.l { grid-column: 1; }
.store.r { grid-column: 8; }
.st {
position: absolute;
width: var(--stone);
height: var(--stone);
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: var(--stoneShadow), inset 0 -2px 4px rgba(0, 0, 0, .25);
transition: left .3s ease, top .3s ease;
pointer-events: none;
}
.st::after {
content: '';
position: absolute;
left: 22%;
top: 15%;
width: 32%;
height: 20%;
border-radius: 50%;
background: rgba(255, 255, 255, .6);
}
.badge {
position: absolute;
left: 50%;
transform: translateX(-50%);
min-width: 30px;
height: 22px;
padding: 0 8px;
border-radius: 11px;
background: var(--chip);
color: var(--chipInk);
font-weight: 700;
font-size: 13px;
line-height: 22px;
box-sizing: border-box;
z-index: 2;
box-shadow: 0 0 0 2px var(--rim);
text-align: center;
font-variant-numeric: tabular-nums;
pointer-events: none;
}
.badge.t { top: -11px; }
.badge.b { bottom: -11px; }
.sbadge {
position: absolute;
left: 50%;
bottom: -14px;
transform: translateX(-50%);
min-width: 44px;
height: 28px;
padding: 0 10px;
border-radius: 14px;
background: var(--chip);
color: var(--chipInk);
font-weight: 800;
font-size: 16px;
line-height: 28px;
box-sizing: border-box;
box-shadow: 0 0 0 2px var(--rim);
text-align: center;
z-index: 2;
font-variant-numeric: tabular-nums;
}
.store.r .sbadge { background: var(--accent); color: var(--onAccent); }
.pvchip {
position: absolute;
right: -6px;
top: -6px;
height: 22px;
min-width: 26px;
padding: 0 6px;
box-sizing: border-box;
border-radius: 11px;
background: var(--accent);
color: var(--onAccent);
font-weight: 800;
font-size: 12px;
line-height: 22px;
z-index: 3;
text-align: center;
pointer-events: none;
}
@container (max-width: 600px) {
.board {
--pw: min(170px, calc((100cqw - 70px) / 2));
--ph: clamp(52px, 15cqw, 66px);
--stone: calc(var(--ph) * .24);
grid-template-columns: var(--pw) var(--pw);
grid-template-rows: calc(var(--ph) * 1.05) repeat(6, var(--ph)) calc(var(--ph) * 1.05);
column-gap: 22px;
row-gap: 10px;
padding: 24px 22px;
border-radius: 32px;
}
.pit { grid-row: var(--vr); grid-column: var(--vc); }
.store.l, .store.r { grid-column: 1 / 3; }
.store.l { grid-row: 1; }
.store.r { grid-row: 8; }
.badge.t { top: 50%; left: auto; right: -13px; transform: translateY(-50%); }
.badge.b { top: 50%; bottom: auto; left: -13px; transform: translateY(-50%); }
.store.l .sbadge { bottom: auto; top: -14px; }
}