moved all of the css to global because why not

This commit is contained in:
2026-05-28 16:54:35 +01:00
parent cce45fc57e
commit 99a29cc92b
4 changed files with 751 additions and 338 deletions

View File

@@ -26,7 +26,6 @@
eventEndpoint = new EventSource('/api/registeredEvents');
eventEndpoint.onmessage = (e) => {
eventTable = JSON.parse(e.data);
console.log(eventTable);
};
});
@@ -172,6 +171,10 @@
<div class="bracket-sep" aria-hidden="true"></div>
{/if}
<div class="bracket-row">
<div class="brackets-name flex items-center">
<span class="brackets-name-text align-text-middle">{bracket.name}</span>
<div class="bracket-vertical-sep"></div>
</div>
{#each bracket.items as player}
<div class="player-box" style="--c:{player.teamColor}">
<div class="player-ghost" aria-hidden="true">
@@ -209,337 +212,354 @@
</section>
</div>
<style>
@import url('https://fonts.googleapis.com/css2?family=Black+Ops+One&display=swap');
:global(html),
:global(body) {
min-height: 100vh;
}
:global(body > div), /* SvelteKit's root wrapper */
:global(#svelte) {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.page {
display: flex;
flex-direction: column;
max-height: 150vh;
max-width: 1000px;
margin: 0 auto;
width: 100%;
}
.goldman {
font-family: 'Black Ops One', system-ui;
font-weight: 400;
}
/* ── Leaderboard ── */
.leaderboard {
display: flex;
flex-direction: column;
gap: 10px;
padding: 14px 14px 6px;
}
.score-box {
position: relative;
overflow: hidden;
border-radius: 14px;
border: 2px solid var(--c);
color: var(--c);
background: color-mix(in srgb, var(--c) 10%, transparent);
/* Grid stacking: ghost + fg share the same cell */
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
text-decoration: none;
transition: filter 0.15s ease;
}
.score-box:hover {
filter: brightness(1.15);
}
.score-box > * {
grid-column: 1;
grid-row: 1;
}
.winner {
aspect-ratio: 2 / 1;
border-width: 3px;
min-height: 80px;
}
.runner {
aspect-ratio: 4 / 1;
min-height: 56px;
}
/* Ghost SVG: fill the cell edge-to-edge, text flush to bottom */
.score-ghost {
width: 100%;
height: 100%;
opacity: 0.18;
fill: currentColor;
}
.ghost-svg {
width: 100%;
height: 100%;
display: block;
}
/* Foreground */
.score-fg {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 14px;
gap: 8px;
}
.score-meta {
display: flex;
flex-direction: column;
min-width: 0;
flex: 1;
}
.score-rank {
font-size: 10px;
letter-spacing: 1.5px;
text-transform: uppercase;
opacity: 0.5;
line-height: 1;
margin-bottom: 3px;
}
.score-name {
font-size: clamp(11px, 3vw, 20px);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.score-pts {
font-size: clamp(20px, 5.5vw, 40px);
letter-spacing: 2px;
flex-shrink: 0;
}
.winner .score-name {
font-size: clamp(16px, 5vw, 32px);
}
.winner .score-pts {
font-size: clamp(26px, 7.5vw, 52px);
}
/*
* Runners-up grid:
* - 1 column on small screens (<480px)
* - 2 columns on medium (480699px)
* - 4 columns on large (≥700px), max 5
* --runner-count drives the actual column count on large screens
* so fewer than 5 teams still fill the whole row.
*/
.runners-grid {
display: grid;
gap: 10px;
grid-template-columns: 1fr;
}
@media (min-width: 480px) {
.runners-grid {
grid-template-columns: repeat(2, 1fr);
}
.winner {
aspect-ratio: 2 / 1;
}
.runner {
aspect-ratio: 2 / 1;
}
}
@media (min-width: 700px) {
.runners-grid {
/* clamp actual count to 4 on large, but use --runner-count
so e.g. 2 teams still fill 2 equal columns not 2 of 4 */
grid-template-columns: repeat(min(var(--runner-count), 4), 1fr);
}
.winner {
aspect-ratio: 3 / 1;
}
.runner {
aspect-ratio: 3 / 2;
}
}
/* ── Section label ── */
.section-label {
font-size: 10px;
letter-spacing: 2.5px;
text-transform: uppercase;
opacity: 0.4;
padding: 12px 16px 4px;
margin: 0;
}
/* ── Events scrollable container ── */
.events-scroll {
flex: 1;
overflow-y: auto;
/* max-height: 900px; */
min-height: 0;
padding: 0 14px 24px;
/* Thin custom scrollbar */
scrollbar-width: thin;
scrollbar-color: color-mix(in srgb, currentColor 30%, transparent) transparent;
}
.events {
display: flex;
flex-direction: column;
gap: 10px;
}
/* ── Event card ── */
.event-card {
border-radius: 12px;
border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
overflow: hidden;
transition: box-shadow 0.3s ease;
}
/* Focus highlight pulse — added/removed by $effect */
.event-card.highlight-pulse {
animation: card-pulse 1.2s ease-out forwards;
}
@keyframes card-pulse {
0% {
box-shadow: 0 0 0 3px currentColor;
}
100% {
box-shadow: 0 0 0 0px currentColor;
}
}
.event-header {
display: flex;
align-items: baseline;
gap: 10px;
padding: 9px 13px 7px;
border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent);
flex-wrap: wrap;
}
.event-name {
font-size: 15px;
text-decoration: none;
color: inherit;
}
.event-name:hover {
text-decoration: underline;
}
.event-division {
font-size: 10px;
letter-spacing: 1.2px;
text-transform: uppercase;
opacity: 0.4;
}
/* ── Brackets ── */
.brackets {
display: flex;
flex-direction: column;
}
.bracket-sep {
height: 1px;
background: color-mix(in srgb, currentColor 10%, transparent);
margin: 0 10px;
}
.bracket-row {
display: flex;
gap: 6px;
padding: 7px 9px;
flex-wrap: wrap;
}
/* ── Player boxes ── */
.player-box {
flex: 1 1 0; /* equal widths, no min-content bias */
max-width: 160px;
position: relative;
overflow: hidden;
border-radius: 8px;
border: 1.5px solid var(--c);
color: var(--c);
background: color-mix(in srgb, var(--c) 10%, transparent);
padding: 5px 7px 5px;
display: flex;
flex-direction: column;
min-height: 52px;
}
/* 1 col on small screens, 4 across on large */
@media (max-width: 479px) {
.bracket-row {
flex-direction: column;
}
.player-box {
max-width: 100%;
}
}
@media (min-width: 700px) {
.player-box {
max-width: calc(25% - 6px);
} /* 4 per row */
}
.player-ghost {
position: absolute;
inset: 0;
opacity: 0.15;
fill: currentColor;
pointer-events: none;
}
.ghost-svg {
width: 100%;
height: 100%;
display: block;
}
.player-name-wrap {
position: relative;
z-index: 1;
overflow: hidden;
white-space: nowrap;
}
.marquee-inner {
display: inline-block;
font-size: 11px;
font-weight: 600;
white-space: nowrap;
}
.marquee-inner.scrolling {
animation: marquee-scroll 7s ease-in-out infinite;
}
@keyframes marquee-scroll {
0%,
20% {
transform: translateX(0);
}
70%,
90% {
transform: translateX(var(--scroll-dist, 0px));
}
100% {
transform: translateX(0);
}
}
.player-placement {
position: relative;
z-index: 1;
font-size: 17px;
line-height: 1.1;
margin-top: 2px;
}
.player-placement-gap {
height: 20px;
}
</style>
<!-- <style> -->
<!-- @import url('https://fonts.googleapis.com/css2?family=Black+Ops+One&display=swap'); -->
<!---->
<!-- :global(html), -->
<!-- :global(body) { -->
<!-- min-height: 100vh; -->
<!-- } -->
<!---->
<!-- :global(body > div), /* SvelteKit's root wrapper */ -->
<!-- :global(#svelte) { -->
<!-- min-height: 100vh; -->
<!-- display: flex; -->
<!-- flex-direction: column; -->
<!-- } -->
<!---->
<!-- .page { -->
<!-- display: flex; -->
<!-- flex-direction: column; -->
<!-- max-height: 150vh; -->
<!-- max-width: 1000px; -->
<!-- margin: 0 auto; -->
<!-- width: 100%; -->
<!-- } -->
<!-- .goldman { -->
<!-- font-family: 'Black Ops One', system-ui; -->
<!-- font-weight: 400; -->
<!-- } -->
<!---->
<!-- /* ── Leaderboard ── */ -->
<!-- .leaderboard { -->
<!-- display: flex; -->
<!-- flex-direction: column; -->
<!-- gap: 10px; -->
<!-- padding: 14px 14px 6px; -->
<!-- } -->
<!---->
<!-- .score-box { -->
<!-- position: relative; -->
<!-- overflow: hidden; -->
<!-- border-radius: 14px; -->
<!-- border: 2px solid var(--c); -->
<!-- color: var(--c); -->
<!-- background: color-mix(in srgb, var(--c) 10%, transparent); -->
<!-- /* Grid stacking: ghost + fg share the same cell */ -->
<!-- display: grid; -->
<!-- grid-template-columns: 1fr; -->
<!-- grid-template-rows: 1fr; -->
<!-- text-decoration: none; -->
<!-- transition: filter 0.15s ease; -->
<!-- } -->
<!-- .score-box:hover { -->
<!-- filter: brightness(1.15); -->
<!-- } -->
<!-- .score-box > * { -->
<!-- grid-column: 1; -->
<!-- grid-row: 1; -->
<!-- } -->
<!---->
<!-- .winner { -->
<!-- aspect-ratio: 2 / 1; -->
<!-- border-width: 3px; -->
<!-- min-height: 80px; -->
<!-- } -->
<!-- .runner { -->
<!-- aspect-ratio: 4 / 1; -->
<!-- min-height: 56px; -->
<!-- } -->
<!---->
<!-- /* Ghost SVG: fill the cell edge-to-edge, text flush to bottom */ -->
<!-- .score-ghost { -->
<!-- width: 100%; -->
<!-- height: 100%; -->
<!-- opacity: 0.18; -->
<!-- fill: currentColor; -->
<!-- } -->
<!-- .ghost-svg { -->
<!-- width: 100%; -->
<!-- height: 100%; -->
<!-- display: block; -->
<!-- } -->
<!---->
<!-- /* Foreground */ -->
<!-- .score-fg { -->
<!-- position: relative; -->
<!-- z-index: 1; -->
<!-- display: flex; -->
<!-- align-items: center; -->
<!-- justify-content: space-between; -->
<!-- padding: 0 14px; -->
<!-- gap: 8px; -->
<!-- } -->
<!-- .score-meta { -->
<!-- display: flex; -->
<!-- flex-direction: column; -->
<!-- min-width: 0; -->
<!-- flex: 1; -->
<!-- } -->
<!-- .score-rank { -->
<!-- font-size: 10px; -->
<!-- letter-spacing: 1.5px; -->
<!-- text-transform: uppercase; -->
<!-- opacity: 0.5; -->
<!-- line-height: 1; -->
<!-- margin-bottom: 3px; -->
<!-- } -->
<!-- .score-name { -->
<!-- font-size: clamp(11px, 3vw, 20px); -->
<!-- white-space: nowrap; -->
<!-- overflow: hidden; -->
<!-- text-overflow: ellipsis; -->
<!-- } -->
<!-- .score-pts { -->
<!-- font-size: clamp(20px, 5.5vw, 40px); -->
<!-- letter-spacing: 2px; -->
<!-- flex-shrink: 0; -->
<!-- } -->
<!-- .winner .score-name { -->
<!-- font-size: clamp(16px, 5vw, 32px); -->
<!-- } -->
<!-- .winner .score-pts { -->
<!-- font-size: clamp(26px, 7.5vw, 52px); -->
<!-- } -->
<!---->
<!-- /* -->
<!-- * Runners-up grid: -->
<!-- * - 1 column on small screens (<480px) -->
<!-- * - 2 columns on medium (480699px) -->
<!-- * - 4 columns on large (≥700px), max 5 -->
<!-- * --runner-count drives the actual column count on large screens -->
<!-- * so fewer than 5 teams still fill the whole row. -->
<!-- */ -->
<!-- .runners-grid { -->
<!-- display: grid; -->
<!-- gap: 10px; -->
<!-- grid-template-columns: 1fr; -->
<!-- } -->
<!-- @media (min-width: 480px) { -->
<!-- .runners-grid { -->
<!-- grid-template-columns: repeat(2, 1fr); -->
<!-- } -->
<!---->
<!-- .winner { -->
<!-- aspect-ratio: 2 / 1; -->
<!-- } -->
<!---->
<!-- .runner { -->
<!-- aspect-ratio: 2 / 1; -->
<!-- } -->
<!-- } -->
<!-- @media (min-width: 700px) { -->
<!-- .runners-grid { -->
<!-- /* clamp actual count to 4 on large, but use --runner-count -->
<!-- so e.g. 2 teams still fill 2 equal columns not 2 of 4 */ -->
<!-- grid-template-columns: repeat(min(var(--runner-count), 4), 1fr); -->
<!-- } -->
<!-- .winner { -->
<!-- aspect-ratio: 3 / 1; -->
<!-- } -->
<!-- .runner { -->
<!-- aspect-ratio: 3 / 2; -->
<!-- } -->
<!-- } -->
<!---->
<!-- /* ── Section label ── */ -->
<!-- .section-label { -->
<!-- font-size: 10px; -->
<!-- letter-spacing: 2.5px; -->
<!-- text-transform: uppercase; -->
<!-- opacity: 0.4; -->
<!-- padding: 12px 16px 4px; -->
<!-- margin: 0; -->
<!-- } -->
<!---->
<!-- /* ── Events scrollable container ── */ -->
<!-- .events-scroll { -->
<!-- flex: 1; -->
<!-- overflow-y: auto; -->
<!-- /* max-height: 900px; */ -->
<!-- min-height: 0; -->
<!-- padding: 0 14px 24px; -->
<!-- /* Thin custom scrollbar */ -->
<!-- scrollbar-width: thin; -->
<!-- scrollbar-color: color-mix(in srgb, currentColor 30%, transparent) transparent; -->
<!-- } -->
<!-- .events { -->
<!-- display: flex; -->
<!-- flex-direction: column; -->
<!-- gap: 10px; -->
<!-- } -->
<!---->
<!-- /* ── Event card ── */ -->
<!-- .event-card { -->
<!-- border-radius: 12px; -->
<!-- border: 1px solid color-mix(in srgb, currentColor 18%, transparent); -->
<!-- overflow: hidden; -->
<!-- transition: box-shadow 0.3s ease; -->
<!-- } -->
<!-- /* Focus highlight pulse — added/removed by $effect */ -->
<!-- .event-card.highlight-pulse { -->
<!-- animation: card-pulse 1.2s ease-out forwards; -->
<!-- } -->
<!-- @keyframes card-pulse { -->
<!-- 0% { -->
<!-- box-shadow: 0 0 0 3px currentColor; -->
<!-- } -->
<!-- 100% { -->
<!-- box-shadow: 0 0 0 0px currentColor; -->
<!-- } -->
<!-- } -->
<!---->
<!-- .event-header { -->
<!-- display: flex; -->
<!-- align-items: baseline; -->
<!-- gap: 10px; -->
<!-- padding: 9px 13px 7px; -->
<!-- border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent); -->
<!-- flex-wrap: wrap; -->
<!-- } -->
<!-- .event-name { -->
<!-- font-size: 15px; -->
<!-- text-decoration: none; -->
<!-- color: inherit; -->
<!-- } -->
<!-- .event-name:hover { -->
<!-- text-decoration: underline; -->
<!-- } -->
<!-- .event-division { -->
<!-- font-size: 10px; -->
<!-- letter-spacing: 1.2px; -->
<!-- text-transform: uppercase; -->
<!-- opacity: 0.4; -->
<!-- } -->
<!---->
<!-- /* ── Brackets ── */ -->
<!-- .brackets { -->
<!-- display: flex; -->
<!-- flex-direction: column; -->
<!-- } -->
<!-- .brackets-name { -->
<!-- font-size: 20px; -->
<!-- letter-spacing: 1.2px; -->
<!-- text-transform: uppercase; -->
<!-- opacity: 0.4; -->
<!-- margin-left: 1px; -->
<!-- } -->
<!-- .brackets-name-text { -->
<!-- display: table-cell; -->
<!-- vertical-align: middle; -->
<!-- } -->
<!-- .bracket-vertical-sep { -->
<!-- width: 1px; -->
<!-- height: 100%; -->
<!-- background: var(--ctp-mocha-surface2); -->
<!-- margin: 10px 5px; -->
<!-- } -->
<!-- .bracket-sep { -->
<!-- height: 1px; -->
<!-- background: color-mix(in srgb, currentColor 10%, transparent); -->
<!-- margin: 0 10px; -->
<!-- } -->
<!-- .bracket-row { -->
<!-- display: flex; -->
<!-- gap: 6px; -->
<!-- padding: 7px 9px; -->
<!-- flex-wrap: wrap; -->
<!-- } -->
<!---->
<!-- /* ── Player boxes ── */ -->
<!-- .player-box { -->
<!-- flex: 1 1 0; /* equal widths, no min-content bias */ -->
<!-- max-width: 160px; -->
<!-- position: relative; -->
<!-- overflow: hidden; -->
<!-- border-radius: 8px; -->
<!-- border: 1.5px solid var(--c); -->
<!-- color: var(--c); -->
<!-- background: color-mix(in srgb, var(--c) 10%, transparent); -->
<!-- padding: 5px 7px 5px; -->
<!-- display: flex; -->
<!-- flex-direction: column; -->
<!-- min-height: 52px; -->
<!-- } -->
<!---->
<!-- /* 1 col on small screens, 4 across on large */ -->
<!-- @media (max-width: 479px) { -->
<!-- .bracket-row { -->
<!-- flex-direction: column; -->
<!-- } -->
<!-- .player-box { -->
<!-- max-width: 100%; -->
<!-- } -->
<!-- } -->
<!-- @media (min-width: 700px) { -->
<!-- .player-box { -->
<!-- max-width: calc(25% - 6px); -->
<!-- } /* 4 per row */ -->
<!-- } -->
<!---->
<!-- .player-ghost { -->
<!-- position: absolute; -->
<!-- inset: 0; -->
<!-- opacity: 0.15; -->
<!-- fill: currentColor; -->
<!-- pointer-events: none; -->
<!-- } -->
<!-- .ghost-svg { -->
<!-- width: 100%; -->
<!-- height: 100%; -->
<!-- display: block; -->
<!-- } -->
<!---->
<!-- .player-name-wrap { -->
<!-- position: relative; -->
<!-- z-index: 1; -->
<!-- overflow: hidden; -->
<!-- white-space: nowrap; -->
<!-- } -->
<!-- .marquee-inner { -->
<!-- display: inline-block; -->
<!-- font-size: 11px; -->
<!-- font-weight: 600; -->
<!-- white-space: nowrap; -->
<!-- } -->
<!-- .marquee-inner.scrolling { -->
<!-- animation: marquee-scroll 7s ease-in-out infinite; -->
<!-- } -->
<!-- @keyframes marquee-scroll { -->
<!-- 0%, -->
<!-- 20% { -->
<!-- transform: translateX(0); -->
<!-- } -->
<!-- 70%, -->
<!-- 90% { -->
<!-- transform: translateX(var(--scroll-dist, 0px)); -->
<!-- } -->
<!-- 100% { -->
<!-- transform: translateX(0); -->
<!-- } -->
<!-- } -->
<!---->
<!-- .player-placement { -->
<!-- position: relative; -->
<!-- z-index: 1; -->
<!-- font-size: 17px; -->
<!-- line-height: 1.1; -->
<!-- margin-top: 2px; -->
<!-- } -->
<!-- .player-placement-gap { -->
<!-- height: 20px; -->
<!-- } -->
<!-- </style> -->

View File

@@ -9,7 +9,6 @@ export async function GET() {
let eventList = async () => {
// Get eventList with structure from database
let newEventList = await getRegisteredEventsWithPlayers();
console.log(newEventList);
// send to client
enqueue(newEventList);
};

View File

@@ -3,6 +3,30 @@
import type { PageProps } from './$types';
let { params }: PageProps = $props();
function ordinal(n: number) {
const s = ['th', 'st', 'nd', 'rd'];
const v = n % 100;
return n + (s[(v - 20) % 10] ?? s[v] ?? s[0]);
}
function marquee(node: HTMLElement) {
function measure() {
const inner = node.querySelector<HTMLElement>('.marquee-inner');
if (!inner) return;
const overflow = inner.scrollWidth - node.clientWidth;
if (overflow > 2) {
node.style.setProperty('--scroll-dist', `-${overflow + 6}px`);
inner.classList.add('scrolling');
} else {
inner.classList.remove('scrolling');
}
}
measure();
const ro = new ResizeObserver(measure);
ro.observe(node);
return { destroy: () => ro.disconnect() };
}
let eventId = params.eventId;
let eventEndpoint: EventSource;
@@ -40,8 +64,45 @@
<div class="w-full flex-col px-[5vw] text-center">
{console.log(event)}
<div class="align-text-middle h-10 w-full bg-red-500">{event.name} - {event.division}</div>
{#each event.registeredPlayers as division}
<div>{division.name}</div>
div
{#each event.registeredPlayers as bracket, bi}
{#if bi > 0}
<div class="bracket-sep" aria-hidden="true"></div>
{/if}
<div class="bracket-row">
<div class="brackets-name flex items-center">
<span class="brackets-name-text align-text-middle">{bracket.name}</span>
<div class="bracket-vertical-sep"></div>
</div>
{#each bracket.items as player}
<div class="player-box" style="--c:{player.teamColor}">
<div class="player-ghost" aria-hidden="true">
<svg viewBox="0 0.1 100 0.6" preserveAspectRatio="none" class="ghost-svg">
<text
x="0"
y="0.7"
font-size="1"
dominant-baseline="auto"
textLength="100"
lengthAdjust="spacingAndGlyphs"
font-family="'Black Ops One',system-ui">{player.firstName}</text
>
</svg>
</div>
<div class="player-name-wrap" use:marquee>
<span class="marquee-inner">
{player.firstName}
{player.lastName}
</span>
</div>
{#if player.placement !== 0}
<div class="player-placement goldman">{ordinal(player.placement)}</div>
{:else}
<div class="player-placement-gap"></div>
{/if}
</div>
{/each}
</div>
{/each}
</div>
</div>

View File

@@ -1,5 +1,338 @@
@import url('https://cdn.jsdelivr.net/npm/@catppuccin/palette/css/catppuccin.css');
@import url('https://fonts.googleapis.com/css2?family=Black+Ops+One&display=swap');
@import 'tailwindcss';
@import '@catppuccin/tailwindcss/mocha.css';
@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';
:global(html),
:global(body) {
min-height: 100vh;
}
:global(body > div), /* SvelteKit's root wrapper */
:global(#svelte) {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.page {
display: flex;
flex-direction: column;
max-height: 150vh;
max-width: 1000px;
margin: 0 auto;
width: 100%;
}
.goldman {
font-family: 'Black Ops One', system-ui;
font-weight: 400;
}
/* ── Leaderboard ── */
.leaderboard {
display: flex;
flex-direction: column;
gap: 10px;
padding: 14px 14px 6px;
}
.score-box {
position: relative;
overflow: hidden;
border-radius: 14px;
border: 2px solid var(--c);
color: var(--c);
background: color-mix(in srgb, var(--c) 10%, transparent);
/* Grid stacking: ghost + fg share the same cell */
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
text-decoration: none;
transition: filter 0.15s ease;
}
.score-box:hover {
filter: brightness(1.15);
}
.score-box > * {
grid-column: 1;
grid-row: 1;
}
.winner {
aspect-ratio: 2 / 1;
border-width: 3px;
min-height: 80px;
}
.runner {
aspect-ratio: 4 / 1;
min-height: 56px;
}
/* Ghost SVG: fill the cell edge-to-edge, text flush to bottom */
.score-ghost {
width: 100%;
height: 100%;
opacity: 0.18;
fill: currentColor;
}
.ghost-svg {
width: 100%;
height: 100%;
display: block;
}
/* Foreground */
.score-fg {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 14px;
gap: 8px;
}
.score-meta {
display: flex;
flex-direction: column;
min-width: 0;
flex: 1;
}
.score-rank {
font-size: 10px;
letter-spacing: 1.5px;
text-transform: uppercase;
opacity: 0.5;
line-height: 1;
margin-bottom: 3px;
}
.score-name {
font-size: clamp(11px, 3vw, 20px);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.score-pts {
font-size: clamp(20px, 5.5vw, 40px);
letter-spacing: 2px;
flex-shrink: 0;
}
.winner .score-name {
font-size: clamp(16px, 5vw, 32px);
}
.winner .score-pts {
font-size: clamp(26px, 7.5vw, 52px);
}
/*
* Runners-up grid:
* - 1 column on small screens (<480px)
* - 2 columns on medium (480699px)
* - 4 columns on large (≥700px), max 5
* --runner-count drives the actual column count on large screens
* so fewer than 5 teams still fill the whole row.
*/
.runners-grid {
display: grid;
gap: 10px;
grid-template-columns: 1fr;
}
@media (min-width: 480px) {
.runners-grid {
grid-template-columns: repeat(2, 1fr);
}
.winner {
aspect-ratio: 2 / 1;
}
.runner {
aspect-ratio: 2 / 1;
}
}
@media (min-width: 700px) {
.runners-grid {
/* clamp actual count to 4 on large, but use --runner-count
so e.g. 2 teams still fill 2 equal columns not 2 of 4 */
grid-template-columns: repeat(min(var(--runner-count), 4), 1fr);
}
.winner {
aspect-ratio: 3 / 1;
}
.runner {
aspect-ratio: 3 / 2;
}
}
/* ── Section label ── */
.section-label {
font-size: 10px;
letter-spacing: 2.5px;
text-transform: uppercase;
opacity: 0.4;
padding: 12px 16px 4px;
margin: 0;
}
/* ── Events scrollable container ── */
.events-scroll {
flex: 1;
overflow-y: auto;
/* max-height: 900px; */
min-height: 0;
padding: 0 14px 24px;
/* Thin custom scrollbar */
scrollbar-width: thin;
scrollbar-color: color-mix(in srgb, currentColor 30%, transparent) transparent;
}
.events {
display: flex;
flex-direction: column;
gap: 10px;
}
/* ── Event card ── */
.event-card {
border-radius: 12px;
border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
overflow: hidden;
transition: box-shadow 0.3s ease;
}
/* Focus highlight pulse — added/removed by $effect */
.event-card.highlight-pulse {
animation: card-pulse 1.2s ease-out forwards;
}
@keyframes card-pulse {
0% {
box-shadow: 0 0 0 3px currentColor;
}
100% {
box-shadow: 0 0 0 0px currentColor;
}
}
.event-header {
display: flex;
align-items: baseline;
gap: 10px;
padding: 9px 13px 7px;
border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent);
flex-wrap: wrap;
}
.event-name {
font-size: 15px;
text-decoration: none;
color: inherit;
}
.event-name:hover {
text-decoration: underline;
}
.event-division {
font-size: 10px;
letter-spacing: 1.2px;
text-transform: uppercase;
opacity: 0.4;
}
/* ── Brackets ── */
.brackets {
display: flex;
flex-direction: column;
}
.bracket-sep {
height: 1px;
background: color-mix(in srgb, currentColor 10%, transparent);
margin: 0 10px;
}
.bracket-row {
display: flex;
gap: 6px;
padding: 7px 9px;
flex-wrap: wrap;
}
/* ── Player boxes ── */
.player-box {
flex: 1 1 0; /* equal widths, no min-content bias */
max-width: 160px;
position: relative;
overflow: hidden;
border-radius: 8px;
border: 1.5px solid var(--c);
color: var(--c);
background: color-mix(in srgb, var(--c) 10%, transparent);
padding: 5px 7px 5px;
display: flex;
flex-direction: column;
min-height: 52px;
}
/* 1 col on small screens, 4 across on large */
@media (max-width: 479px) {
.bracket-row {
flex-direction: column;
}
.player-box {
max-width: 100%;
}
}
@media (min-width: 700px) {
.player-box {
max-width: calc(25% - 6px);
} /* 4 per row */
}
.player-ghost {
position: absolute;
inset: 0;
opacity: 0.15;
fill: currentColor;
pointer-events: none;
}
.ghost-svg {
width: 100%;
height: 100%;
display: block;
}
.player-name-wrap {
position: relative;
z-index: 1;
overflow: hidden;
white-space: nowrap;
}
.marquee-inner {
display: inline-block;
font-size: 11px;
font-weight: 600;
white-space: nowrap;
}
.marquee-inner.scrolling {
animation: marquee-scroll 7s ease-in-out infinite;
}
@keyframes marquee-scroll {
0%,
20% {
transform: translateX(0);
}
70%,
90% {
transform: translateX(var(--scroll-dist, 0px));
}
100% {
transform: translateX(0);
}
}
.player-placement {
position: relative;
z-index: 1;
font-size: 17px;
line-height: 1.1;
margin-top: 2px;
}
.player-placement-gap {
height: 20px;
}