mirror of
https://github.com/tiennm99/loto.git
synced 2026-10-15 04:18:47 +00:00
style(player): tân tân BAMBOORAFT card look — tall cells, condensed black numbers, blue paper
Match the BAMBOORAFT physical sheet: - Cell aspect changed from square to 3:5 (taller than wide), matching the printed paper proportions - Number cells rendered with .tan-tan-num: condensed system-font stack (Arial Narrow / Avenir Next Condensed / Roboto Condensed), font-weight 900, negative letter-spacing for tight fall-back on platforms without a true condensed face. Sized text-2xl / sm:text-3xl to fill the taller cells. Black number on white cell. - Default empty-cell color flipped from Minh Tân brown (#7a4a2b) to BAMBOORAFT blue (#1e88e5). Settings store + test updated. Users who picked a different color in settings keep their choice. - Section dividers and labels recolored from orange to matching blue. - Section labels relabelled to the BAMBOORAFT trio: "Tân Tân" / "An khang thịnh vượng" / "Tân Tân tốt nhất"
This commit is contained in:
1 parent
1440c9daf5
commit
7665252607
6 files changed
+48
-30
No files matched your search
@@ -12,7 +12,7 @@
|
||||
### Shared Components
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `src/lib/PlayerBoard.svelte` | Reusable player card (9×9 grid rendered as 3 stacked 3×9 mini-cards: Minh Tân / Loại đặc biệt / Tấn tài tấn lộc). Handles crossed state, bingo popup, "Chờ X" toast. Accepts `storagePrefix` prop for multi-card isolation. Empty cells use `--empty-cell-bg` CSS var from settings store. |
|
||||
| `src/lib/PlayerBoard.svelte` | Reusable player card (9×9 grid rendered as 3 stacked 3×9 mini-cards: Tân Tân / An khang thịnh vượng / Tân Tân tốt nhất). Tall (3:5) cells with condensed bold black numbers (`tan-tan-num` font stack), white number cells, blue empty cells. Handles crossed state, bingo popup, "Chờ X" toast. Accepts `storagePrefix` prop for multi-card isolation. Empty cells use `--empty-cell-bg` CSS var from settings store. |
|
||||
| `src/lib/SettingsButton.svelte` | Gear icon + modal. Color picker + 8 preset swatches for empty-cell color. Reset-to-default button. Mounted on both `/` and `/master` headers. |
|
||||
|
||||
### Game Logic
|
||||
|
||||
@@ -16,8 +16,10 @@ That format is intentionally out of scope.
|
||||
- **Card**: 9 rows × 9 columns. Exactly **5 numbers per row** AND exactly
|
||||
**5 numbers per column** (45 numbers per card; 36 blanks).
|
||||
- **Visual layout**: card displayed as 3 stacked 3×9 mini-cards with
|
||||
traditional separator labels — *Minh Tân*, *Loại đặc biệt*,
|
||||
*Tấn tài tấn lộc* — matching the physical Minh Tân paper sheet.
|
||||
traditional separator labels — *Tân Tân*, *An khang thịnh vượng*,
|
||||
*Tân Tân tốt nhất* — matching the physical Tân Tân BAMBOORAFT paper
|
||||
sheet (tall non-square cells, condensed bold black numbers on white,
|
||||
blue empty-cell background by default).
|
||||
- **Column ranges**: col 0 = 1–9, col 1 = 10–19, …, col 7 = 70–79,
|
||||
col 8 = 80–90.
|
||||
- **Within a column**: numbers placed top-to-bottom in **ascending** order.
|
||||
|
||||
+29
-13
@@ -3,9 +3,9 @@
|
||||
:root {
|
||||
--background: #f8fafc;
|
||||
--foreground: #1e293b;
|
||||
/* Default empty-cell color matches a Minh Tân paper card. Overridden
|
||||
at runtime by the settings store via documentElement.style. */
|
||||
--empty-cell-bg: #7a4a2b;
|
||||
/* Default empty-cell color matches a Tân Tân BAMBOORAFT paper card.
|
||||
Overridden at runtime by the settings store via documentElement.style. */
|
||||
--empty-cell-bg: #1e88e5;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@@ -34,41 +34,57 @@ body {
|
||||
}
|
||||
|
||||
/* Decorative cross-hatch divider between mini-cards on the player sheet,
|
||||
echoing the ✚✚✚ borders on a physical Minh Tân card. */
|
||||
echoing the ✚✚✚ blue borders on a Tân Tân BAMBOORAFT card. */
|
||||
.section-divider {
|
||||
height: 8px;
|
||||
background-image: repeating-linear-gradient(
|
||||
90deg,
|
||||
transparent 0 6px,
|
||||
#c2410c 6px 8px,
|
||||
#1e88e5 6px 8px,
|
||||
transparent 8px 14px
|
||||
);
|
||||
background-color: rgb(255 247 237 / 0.6);
|
||||
background-color: rgb(227 242 253 / 0.7);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.section-divider {
|
||||
background-color: rgb(67 20 7 / 0.4);
|
||||
background-color: rgb(13 71 161 / 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.section-label {
|
||||
text-align: center;
|
||||
font-size: 0.7rem;
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
padding: 6px 0;
|
||||
color: #c2410c;
|
||||
background-color: rgb(255 247 237 / 0.5);
|
||||
color: #1565c0;
|
||||
background-color: rgb(227 242 253 / 0.6);
|
||||
font-style: italic;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.section-label {
|
||||
color: #fb923c;
|
||||
background-color: rgb(67 20 7 / 0.4);
|
||||
color: #64b5f6;
|
||||
background-color: rgb(13 71 161 / 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tân Tân BAMBOORAFT-style number — tall, condensed, heavy black. Stack
|
||||
prefers a system condensed face; falls back to negative letter-spacing
|
||||
on platforms without one so the digits still read tall-and-tight. */
|
||||
.tan-tan-num {
|
||||
font-family:
|
||||
"Arial Narrow",
|
||||
"Avenir Next Condensed",
|
||||
"Roboto Condensed",
|
||||
"Liberation Sans Narrow",
|
||||
system-ui,
|
||||
sans-serif;
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.04em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes pop-in { 0% { opacity: 0; transform: scale(0.5); } 70% { transform: scale(1.05); } 100% { opacity: 1; transform: scale(1); } }
|
||||
@keyframes bounce-slow { 0%, 100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(-12px); } }
|
||||
|
||||
+10
-10
@@ -140,9 +140,9 @@
|
||||
// visual segmentation.
|
||||
const SECTIONS = /** @type {const} */ ([0, 3, 6]);
|
||||
const SECTION_LABELS = [
|
||||
"Minh Tân",
|
||||
"Loại đặc biệt",
|
||||
"Tấn tài tấn lộc",
|
||||
"Tân Tân",
|
||||
"An khang thịnh vượng",
|
||||
"Tân Tân tốt nhất",
|
||||
];
|
||||
</script>
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
{#if !hasNumber}
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="relative flex items-center justify-center aspect-square border-r border-b border-slate-200/80 dark:border-slate-700/60"
|
||||
class="relative aspect-[3/5] border-r border-b border-slate-300/60 dark:border-slate-700/60"
|
||||
style:background-color="var(--empty-cell-bg)"
|
||||
></div>
|
||||
{:else}
|
||||
@@ -189,16 +189,16 @@
|
||||
aria-label="Số {num}{isCrossed ? ', đã đánh dấu' : ''}"
|
||||
aria-pressed={isCrossed}
|
||||
onclick={() => handleCellClick(row, col)}
|
||||
class="relative flex items-center justify-center
|
||||
aspect-square text-base sm:text-xl font-bold
|
||||
border-r border-b border-slate-200/80 dark:border-slate-700/60
|
||||
class="tan-tan-num relative flex items-center justify-center
|
||||
aspect-[3/5] text-2xl sm:text-3xl
|
||||
border-r border-b border-slate-300/60 dark:border-slate-700/60
|
||||
transition-all select-none cursor-pointer
|
||||
focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-400
|
||||
{isCrossed
|
||||
? rowComplete
|
||||
? 'cell-crossed bg-emerald-100 dark:bg-emerald-900/40 text-emerald-500 dark:text-emerald-400'
|
||||
: 'cell-crossed bg-red-50 dark:bg-red-950/30 text-red-400 dark:text-red-500'
|
||||
: 'bg-white dark:bg-slate-800 text-slate-800 dark:text-slate-100 hover:bg-indigo-50 dark:hover:bg-indigo-950/30 hover:text-indigo-600 dark:hover:text-indigo-400'}"
|
||||
? 'cell-crossed bg-emerald-100 dark:bg-emerald-900/40 text-emerald-600 dark:text-emerald-400'
|
||||
: 'cell-crossed bg-red-50 dark:bg-red-950/30 text-red-500 dark:text-red-500'
|
||||
: 'bg-white dark:bg-slate-800 text-black dark:text-slate-100 hover:bg-indigo-50 dark:hover:bg-indigo-950/30 hover:text-indigo-600 dark:hover:text-indigo-400'}"
|
||||
>
|
||||
{num}
|
||||
</button>
|
||||
|
||||
@@ -11,8 +11,8 @@ const STORAGE_KEY = "loto_settings";
|
||||
const HEX6 = /^#[0-9a-fA-F]{6}$/;
|
||||
|
||||
export const DEFAULT_SETTINGS = Object.freeze({
|
||||
/** Brown — matches a Minh Tân paper card. */
|
||||
emptyCellColor: "#7a4a2b",
|
||||
/** Blue — matches a Tân Tân BAMBOORAFT paper card. */
|
||||
emptyCellColor: "#1e88e5",
|
||||
});
|
||||
|
||||
export const settings = $state({ ...DEFAULT_SETTINGS });
|
||||
|
||||
@@ -22,8 +22,8 @@ describe("settings-store — defaults", () => {
|
||||
expect(Object.isFrozen(DEFAULT_SETTINGS)).toBe(true);
|
||||
});
|
||||
|
||||
it("default empty-cell color is brown (#7a4a2b)", () => {
|
||||
expect(DEFAULT_SETTINGS.emptyCellColor).toBe("#7a4a2b");
|
||||
it("default empty-cell color is Tân Tân blue (#1e88e5)", () => {
|
||||
expect(DEFAULT_SETTINGS.emptyCellColor).toBe("#1e88e5");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user