games: a ladder you climb against the clock
This commit is contained in:
@@ -1081,6 +1081,122 @@ html[data-phase="night"] {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
/* ---- trivia --------------------------------------------------------------
|
||||
The clock is the game, so the clock is the biggest thing on the felt: a bar
|
||||
that drains across the top of the question, going hot as it runs out. It is
|
||||
*decoration* — the server timed the answer the moment it arrived — but it
|
||||
has to be honest decoration, so it's driven from the seconds the server said
|
||||
were left rather than from when the browser happened to paint. */
|
||||
|
||||
.pete-clock {
|
||||
position: relative;
|
||||
height: 0.6rem;
|
||||
border-radius: 999px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
.pete-clock-fill {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 999px;
|
||||
background: var(--accent);
|
||||
transform-origin: left center;
|
||||
/* Driven by a transform the browser can run on its own: a width animated on
|
||||
every frame from JS is a layout on every frame. */
|
||||
transform: scaleX(1);
|
||||
}
|
||||
/* The last few seconds. The bar stops being a progress meter and starts being
|
||||
a warning. */
|
||||
.pete-clock[data-hot="1"] .pete-clock-fill { background: #cc3d4a; }
|
||||
.pete-clock[data-hot="1"] { animation: pete-clock-pulse 0.7s ease-in-out infinite; }
|
||||
@keyframes pete-clock-pulse {
|
||||
0%, 100% { box-shadow: inset 0 0 0 2px rgba(204, 61, 74, 0.35); }
|
||||
50% { box-shadow: inset 0 0 0 2px rgba(204, 61, 74, 0.95); }
|
||||
}
|
||||
|
||||
/* The four answers. Big targets, because the clock is already the hard part —
|
||||
a question you lose to a mis-tap is a question about pointing. */
|
||||
.pete-answer {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
width: 100%;
|
||||
border-radius: 1rem;
|
||||
padding: 0.85rem 1rem;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
background: rgba(0, 0, 0, 0.26);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.1);
|
||||
transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
.pete-answer:hover:not(:disabled) {
|
||||
background: rgba(0, 0, 0, 0.36);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.28);
|
||||
}
|
||||
.pete-answer:active:not(:disabled) { transform: translateY(1px); }
|
||||
.pete-answer:disabled { cursor: default; }
|
||||
|
||||
/* The letter down the side, so an answer can be picked with the keyboard and
|
||||
the key you press is printed on the thing you're pressing it for. */
|
||||
.pete-answer-key {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
height: 1.75rem;
|
||||
width: 1.75rem;
|
||||
flex: none;
|
||||
border-radius: 0.6rem;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
font-family: "Fredoka", ui-sans-serif, system-ui, sans-serif;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
/* How it went. Only ever set once the server has decided — the browser has no
|
||||
idea which of these is right until it's told. */
|
||||
.pete-answer[data-state="right"] {
|
||||
background: rgba(46, 160, 103, 0.9);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.pete-answer[data-state="wrong"] {
|
||||
background: rgba(204, 61, 74, 0.9);
|
||||
box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.35);
|
||||
animation: pete-answer-no 0.45s ease;
|
||||
}
|
||||
/* The one they *should* have picked, shown alongside the one they did. */
|
||||
.pete-answer[data-state="missed"] {
|
||||
box-shadow: inset 0 0 0 2px rgba(46, 160, 103, 0.95);
|
||||
}
|
||||
.pete-answer[data-state="dim"] { opacity: 0.4; }
|
||||
@keyframes pete-answer-no {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
20% { transform: translateX(-6px); }
|
||||
45% { transform: translateX(5px); }
|
||||
70% { transform: translateX(-3px); }
|
||||
}
|
||||
|
||||
/* The ladder: one pip per rung, filling as they're climbed. It is the only
|
||||
picture of how far there is left to fall. */
|
||||
.pete-ladder {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
.pete-rung {
|
||||
height: 0.5rem;
|
||||
width: 1.1rem;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.14);
|
||||
transition: background 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
.pete-rung[data-on="1"] {
|
||||
background: var(--accent);
|
||||
transform: scaleY(1.35);
|
||||
}
|
||||
|
||||
/* ---- solitaire -----------------------------------------------------------
|
||||
Seven columns, four foundations, a stock and a waste, all of which have to
|
||||
fit across the felt on a phone as well as a desk. So the card size is one
|
||||
@@ -1299,6 +1415,11 @@ html[data-phase="night"] {
|
||||
.pete-nope,
|
||||
.pete-home-flash { animation: none; }
|
||||
.pete-card[data-held="1"] { transition: none; }
|
||||
/* The clock still drains — it is information, not decoration — but it stops
|
||||
pulsing at you, and a wrong answer stops shaking. */
|
||||
.pete-clock[data-hot="1"],
|
||||
.pete-answer[data-state="wrong"] { animation: none; }
|
||||
.pete-rung { transition: none; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user