@tailwind base; @tailwind components; @tailwind utilities; @layer base { html, body, #root { @apply min-h-screen; } /* Single global type lever: enlarges all rem-based Tailwind text (menu/list/ auth/history screens). The game board uses fixed px + transform zoom, so it stays pixel-precise. Bump this one value to scale the menus up or down. */ html { font-size: 18px; } body { @apply bg-table text-green-score font-sans; background: radial-gradient(ellipse at 50% -10%, rgba(48, 104, 69, 0.16), transparent 60%), #090e0b; background-attachment: fixed; } /* Form fields keep the velvet look across the app */ input::placeholder { @apply text-green-dim/60; } } /* Slim, on-theme scrollbar (velvet felt + gold accent) for opt-in scroll areas such as the in-game score list, instead of the chunky OS default. */ .velvet-scroll { scrollbar-width: thin; scrollbar-color: rgba(201, 168, 76, 0.35) transparent; } .velvet-scroll::-webkit-scrollbar { width: 7px; height: 7px; } .velvet-scroll::-webkit-scrollbar-track { background: transparent; } .velvet-scroll::-webkit-scrollbar-thumb { background: rgba(201, 168, 76, 0.28); border-radius: 4px; } .velvet-scroll::-webkit-scrollbar-thumb:hover { background: rgba(201, 168, 76, 0.5); } /* Velvet-table animations (design handoff). Declared as raw CSS so they work both via Tailwind's animate-* utilities and inline `animation:` strings. */ @keyframes tp { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } @keyframes ci { from { opacity: 0; transform: translateY(-6px) scale(0.9); } to { opacity: 1; transform: none; } } @keyframes ar { 0%, 100% { box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.18), 0 0 18px rgba(201, 168, 76, 0.5), 0 0 42px rgba(201, 168, 76, 0.2); } 50% { box-shadow: 0 0 0 5px rgba(201, 168, 76, 0.34), 0 0 32px rgba(201, 168, 76, 0.85), 0 0 56px rgba(201, 168, 76, 0.3); } } @keyframes g1 { 0%, 100% { box-shadow: 0 0 18px rgba(201, 168, 76, 0.55), 0 6px 18px rgba(0, 0, 0, 0.55); } 50% { box-shadow: 0 0 34px rgba(201, 168, 76, 0.85), 0 6px 18px rgba(0, 0, 0, 0.55); } } /* A played card slides into the centre from the direction of its player. */ @keyframes fly-top { from { opacity: 0; transform: translateY(-90px) scale(0.82); } to { opacity: 1; transform: none; } } @keyframes fly-bottom { from { opacity: 0; transform: translateY(90px) scale(0.82); } to { opacity: 1; transform: none; } } @keyframes fly-left { from { opacity: 0; transform: translateX(-110px) scale(0.82); } to { opacity: 1; transform: none; } } @keyframes fly-right { from { opacity: 0; transform: translateX(110px) scale(0.82); } to { opacity: 1; transform: none; } } /* A completed trick is swept off the table towards the seat that won it. */ @keyframes collect-bottom { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(150px) scale(0.66); } } @keyframes collect-top { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-150px) scale(0.66); } } @keyframes collect-left { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(-190px) scale(0.66); } } @keyframes collect-right { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(190px) scale(0.66); } }