/*
 * Aitch Rewards — "Machine room"
 *
 * Colour, type and spacing values come from theme.json as --wp--preset--*
 * custom properties, aliased to shorter names here. Nothing in this file should
 * hard-code a hex that theme.json already defines, so the palette stays
 * editable in one place.
 *
 * Depth in this direction is built from stacked shadows, never from transforms
 * or from blur alone: a hard block layer (0 Npx 0 <near-black>) that reads as
 * physical thickness, an ambient layer under it, and an inset top highlight.
 * The --lift-* tokens compose all three. Use them rather than writing a fresh
 * box-shadow, or surfaces stop agreeing about where the light is coming from.
 */

:root {
	--c-base: var(--wp--preset--color--base, #080B11);
	--c-surface: var(--wp--preset--color--surface, #14171D);
	--c-surface-deep: var(--wp--preset--color--surface-deep, #0B0E14);
	--c-raised: var(--wp--preset--color--raised, #1B2534);
	--c-raised-deep: var(--wp--preset--color--raised-deep, #0C121C);
	--c-rail: var(--wp--preset--color--rail, #0F1218);
	--c-rail-deep: var(--wp--preset--color--rail-deep, #0A0D12);
	--c-well: var(--wp--preset--color--well, #060911);

	--c-accent: var(--wp--preset--color--accent, #FFC629);
	--c-accent-soft: var(--wp--preset--color--accent-soft, #FFDE7A);
	--c-accent-warm: var(--wp--preset--color--accent-warm, #FFECBC);
	--c-accent-mid: var(--wp--preset--color--accent-mid, #EDA80F);
	--c-accent-deep: var(--wp--preset--color--accent-deep, #8A5A04);

	/* The accent is a yellow now, so nothing white can sit on top of it and stay
	   readable. Every accent-filled surface — buttons, icon tiles, the brand mark
	   — takes its ink from this token instead of #fff. */
	--c-on-accent: var(--wp--preset--color--on-accent, #1A1204);

	/* The one cool note on the page: the Discord button and the high background
	   plane. Kept a shade brighter and more azure than Discord's own blurple, so
	   it holds its own against the yellow instead of going muddy next to it. */
	--c-blue: var(--wp--preset--color--blue, #2F9BFF);
	--c-blue-soft: var(--wp--preset--color--blue-soft, #6FBAFF);
	--c-blue-mid: var(--wp--preset--color--blue-mid, #1E7FDB);
	--c-blue-deep: var(--wp--preset--color--blue-deep, #12508F);

	/* Ink for anything sitting on a filled blue tile. Near-black with the blue
	   left in it rather than plain #000, so the tile reads as one lit object
	   instead of a hole punched in it. */
	--c-on-blue: var(--wp--preset--color--on-blue, #04131F);

	--c-gold: var(--wp--preset--color--gold, #F3DFA2);
	--c-danger: var(--wp--preset--color--danger, #FF4D5E);
	/* A win on a house game. Green, and only there: yellow is the conversion
	   colour on the rest of the site and a win is not a call to action. */
	--c-win: #3DDC84;
	--win-rgb: 61, 220, 132;
	--c-text: var(--wp--preset--color--text, #EDF2F8);

	/* Alpha values are composed from these channels rather than written as
	   literals, so changing the palette reaches the washes and borders too —
	   that is what let the old green survive in 21 places after the last swap. */
	--accent-rgb: 255, 198, 41;
	--gold-rgb: 243, 223, 162;
	--blue-rgb: 47, 155, 255;
	--text-rgb: 237, 242, 248;
	/* The ground itself, for the one surface that has to be see-through: the
	   sticky bar sits over the page and takes the base at 92% rather than a
	   literal, so it follows the ramp if the ramp moves again. */
	--base-rgb: 8, 11, 17;

	--c-muted: var(--wp--preset--color--muted, #8B97A7);
	--c-faint: #7C8899;
	/* Was #5C6779, which measured 3.5:1 on the base and failed WCAG AA on every
	   ground on the site. That would be arguable for pure ornament, but this rung
	   carries the footer's legal line, the ticker's stake figures and the rail's
	   section labels — all of it real content set at 9.5 to 12px, which is the
	   worst possible combination of small and low contrast. #737F92 is 4.9:1 on
	   the base and 4.6:1 on the raised card wash, and it is still visibly a rung
	   below --c-faint, which is all this token was ever asked to be. */
	--c-dim: #737F92;
	/* Two more rungs the mockup uses: rail links, and the two section subheads. */
	--c-nav: #93A0B1;
	--c-sub: #9AA6B6;

	--c-border-soft: rgba(255, 255, 255, 0.07);
	--c-border: rgba(var(--accent-rgb), 0.45);
	--c-hairline: rgba(255, 255, 255, 0.06);
	/* --c-raised composited with a 30% black wash, as a solid: the leaderboard
	   header is sticky over scrolling rows and must not be see-through. */
	--c-board-head: #131A24;

	/* Surface gradients. Every raised plane is a 180deg two-stop, which is what
	   makes the block shadow underneath read as a solid edge rather than a blur. */
	--g-surface: linear-gradient(180deg, var(--c-surface), var(--c-surface-deep));
	--g-raised: linear-gradient(180deg, var(--c-raised), var(--c-raised-deep));
	--g-rail: linear-gradient(180deg, var(--c-rail), var(--c-rail-deep));
	--g-accent: linear-gradient(180deg, var(--c-accent-soft), var(--c-accent) 40%, var(--c-accent-mid));
	--g-accent-hover: linear-gradient(180deg, #FFDD6B, #F5AE05);
	--g-tile: linear-gradient(160deg, var(--c-accent-soft), #DE9600);
	/* The same tile in the cool half of the palette, for the "How to Earn"
	   icons. 160deg like its yellow twin so the two are lit identically. */
	--g-tile-blue: linear-gradient(160deg, var(--c-blue-soft), var(--c-blue-mid));
	--g-chip: linear-gradient(180deg, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.03));
	--g-chip-soft: linear-gradient(180deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.03));

	/* The three block-shadow blacks. Deeper surfaces sit on darker blocks so a
	   tall stack does not flatten into one grey slab. */
	--block-1: #04060A;
	--block-2: #05070C;
	--block-3: #06090F;

	/* Same again for the small pressable chips: the balance pill, the account
	   toggle, ghost buttons, pager links and the footy tags. */
	--lift-sm: none;
	--lift-chip: none;
	--lift-card: 0 12px 0 var(--block-1), 0 34px 46px -20px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.16);
	--lift-card-sm: 0 10px 0 var(--block-2), 0 30px 44px -20px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.13);
	--lift-bar: 0 14px 0 var(--block-1), 0 44px 60px -26px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.16);
	--lift-podium: 0 16px 0 var(--block-2), 0 40px 50px -22px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.14);
	--lift-podium-sm: 0 12px 0 var(--block-2), 0 40px 50px -22px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.14);
	--lift-winner: 0 26px 0 var(--block-3), 0 54px 64px -24px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.2);
	/* Buttons and icon tiles are flat.
	   These three used to carry the same block-and-highlight bevel as the cards:
	   a hard colour step under the object and a white inset along its top edge.
	   On a 54px button that reads as a key you could press, which is one more
	   thing than a link needs to say, and at 42px on an icon tile it was mostly
	   bevel by area. The cards keep their lift — a surface holding content is
	   what the depth was for. Anything you click is now flat, and colour alone
	   separates primary from secondary.

	   Kept as tokens rather than deleted so the call sites do not change and
	   the decision stays in one place. */
	--lift-btn: none;
	--lift-tile: none;
	--lift-tile-blue: none;
	--well-inset: inset 0 3px 10px rgba(0, 0, 0, 0.9);

	/* Display type used to carry the same hard stacked steps as the surfaces —
	   two solid offset copies of every letter. At heading sizes that reads as a
	   double image rather than as depth, so type now gets a single soft shadow
	   and nothing else. Depth stays a property of surfaces; letters stay flat. */
	--text-block: 0 2px 18px rgba(0, 0, 0, 0.55);
	--text-block-lg: 0 3px 26px rgba(0, 0, 0, 0.6);
	--text-sink: 0 3px 30px rgba(0, 0, 0, 0.75);
	--text-sink-sm: 0 2px 20px rgba(0, 0, 0, 0.7);

	/* Self-hosted variable face, same as Archivo — the theme serves its own
	   fonts rather than reaching for a CDN. The stack behind it still matters
	   for the swap window before the woff2 lands. */
	--font-mono: var(--wp--preset--font-family--jetbrains-mono, 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);

	--sidebar-w: 286px;
	--topbar-h: 64px;

	/* One radius, not a scale. The six steps here used to run 26px down to 9px,
	   which on a page of stacked hard-edged block shadows read as six different
	   opinions about how soft the object was — a 26px bar above a 12px card
	   above a 9px chip, all lit the same way. Everything square-ish is 8px now
	   and the block shadow does the talking. The names are kept as aliases so
	   the forty-odd call sites do not have to change, and so a future retune is
	   still one edit.

	   Pills and circles are exempt: 999px and 50% are shapes, not corners. */
	--radius: 8px;
	--radius-lg: var(--radius);
	--radius-bar: var(--radius);
	--radius-md: var(--radius);
	--radius-sm: var(--radius);
	--radius-xs: var(--radius);

	--ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

*,
*::before,
*::after {
	box-sizing: border-box;
}

/* `hidden` has to win, and by default it loses. The attribute's display:none
   lives in the browser's own stylesheet, and every author rule beats every UA
   rule no matter how weak its selector is, so one `display: flex` on a class is
   enough to put a hidden element back on the screen.

   That is not theoretical: the Kick panel showed a yellow LINKED chip directly
   above the steps for linking, to everybody who was not linked, because
   `.settings__row` sets display:flex and the chip is hidden by attribute. Every
   state this codebase toggles from PHP or from settings.js goes through the same
   attribute, so it is settled once, here, rather than per component. */
[hidden] {
	display: none !important;
}

/* The body gradient is attachment:fixed, so it paints only the viewport. Any
   page taller than one screen would otherwise show the browser's default white
   below the fold — html carries the base colour so that cannot happen. */
html {
	background: var(--c-base);
}

/* One gradient, nothing layered on top of it. An earlier pass cut four diagonal
   bands into this on two different axes; crossing axes read as cross-hatch, not
   as depth. The two angled planes inside .shell carry the whole idea, and they
   are near-parallel on purpose. */
body {
	margin: 0;
	background: linear-gradient(135deg, var(--c-base) 0%, #0B111B 100%);
	background-attachment: fixed;
	color: var(--c-text);
	font-family: var(--wp--preset--font-family--archivo, Archivo, system-ui, sans-serif);
	line-height: 1.6;
	min-height: 100vh;
	overflow-x: hidden;
}

a {
	color: var(--c-accent);
	text-decoration: none;
	transition: color 0.15s var(--ease);
}

a:hover,
a:focus-visible {
	text-decoration: underline;
}

img {
	max-width: 100%;
	height: auto;
}

.accent {
	color: var(--c-accent);
}

.icon {
	flex: none;
	vertical-align: middle;
}

:focus-visible {
	outline: 2px solid var(--c-accent);
	outline-offset: 2px;
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.skip-link:focus-visible {
	position: fixed;
	top: 8px;
	left: 8px;
	z-index: 1000;
	width: auto;
	height: auto;
	clip-path: none;
	padding: 0.75rem 1rem;
	background: var(--c-accent);
	color: var(--c-on-accent);
	border-radius: var(--radius-sm);
}

/* In the top bar the Discord control is a text link and nothing more. Scoped to
   the topbar on purpose: the same button is the full-width primary action on
   shop cards and the dice gate, where it should stay a button.

   It used to be a tinted, ringed chip, which made three things on a logged-out
   homepage look like calls to action — this, the Kick link and the sign-up. It
   is none of them. Signing in is for people who already have an account, so it
   keeps its corner and gives up everything that was asking to be pressed: no
   ring, no tint, no blue on the mark at rest.

   The blue comes back on hover, and only there. Yellow is spent on the
   conversion path and this is not on it, so reaching for the site's other
   colour keeps the two apart — and the colour it reaches for is Discord's,
   which is what the control is. */
.topbar .btn--discord {
	padding: 0.42rem 0;
	gap: 0.45rem;
	background: none;
	box-shadow: none;
	color: var(--c-muted);
	font-size: 0.83rem;
}

.topbar .btn--discord:hover,
.topbar .btn--discord:focus-visible {
	background: none;
	box-shadow: none;
	color: var(--c-blue-soft);
}

/* currentColor, so the glyph lights up with the label rather than being blue on
   its own while the words beside it are grey. */
.topbar .btn--discord .btn__icon {
	width: 15px;
	height: 15px;
	color: currentColor;
}

/* ------------------------------------------------------------ shell + rail */

/* Two full-height columns. The rail is a real grid track rather than a fixed
   overlay with a matching margin on .main — that arrangement made two rules
   responsible for one width, and they drifted every time the rail changed. */
.shell {
	position: relative;
	display: grid;
	grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
	align-items: stretch;
	min-height: 100vh;
}

/* The clipper for the two angled planes. It exists so .shell itself does not
   need overflow:hidden, which would stop the rail below from sticking. */
.shell__planes {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
}

/* ------------------------------------------------------- ambient layers */

/* Six planes over the two angled slabs. Every stop below is under 6% alpha;
   none of them is meant to be visible on its own, and the atmosphere is the
   sum. They live in .shell__planes so they inherit its clipping and its
   pointer-events:none, and so they scroll with the page rather than with the
   viewport — a fixed backdrop behind a sticky rail reads as the page sliding
   over a still photograph. */
.shell__amb {
	position: absolute;
}

.shell__amb--horizon,
.shell__amb--grid,
.shell__amb--vignette,
.shell__amb--grain {
	inset: 0;
}

/* Two slow washes, drifting out of phase so the lighting never settles into a
   fixed arrangement. Sized in px rather than % because they are lens flare, not
   layout: on a tall page a percentage height would stretch them into columns. */
.shell__amb--warm {
	top: -320px;
	right: -220px;
	width: 1100px;
	height: 900px;
	border-radius: 50%;
	background: radial-gradient(closest-side, rgba(var(--accent-rgb), 0.11), transparent 70%);
	filter: blur(20px);
	animation: amb-drift 26s ease-in-out infinite;
}

.shell__amb--cool {
	bottom: -380px;
	left: 120px;
	width: 1000px;
	height: 820px;
	border-radius: 50%;
	background: radial-gradient(closest-side, rgba(var(--blue-rgb), 0.09), transparent 70%);
	filter: blur(24px);
	animation: amb-drift 34s ease-in-out infinite reverse;
}

/* A broad soft light behind the hero, so the headline sits on a lit field
   instead of floating on flat base colour. Capped in px: it belongs to the
   hero, and on a long page a percentage would drag it down the whole document. */
.shell__amb--horizon {
	bottom: auto;
	height: 900px;
	background: radial-gradient(72% 100% at 40% 4%, rgba(255, 255, 255, 0.04), transparent 66%);
}

/* Fades out before the fold, so it reads as a surface the page is printed on
   rather than as a chart drawn over it. */
.shell__amb--grid {
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.02) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
	background-size: 88px 88px;
	-webkit-mask-image: radial-gradient(132% 92% at 58% 0%, #000 22%, transparent 80%);
	mask-image: radial-gradient(132% 92% at 58% 0%, #000 22%, transparent 80%);
}

/* Edge falloff is linear, not radial, on purpose: the front page runs well past
   one screen, and a radial centre would land somewhere in the card grid and
   light the hero unevenly. */
.shell__amb--vignette {
	background:
		linear-gradient(90deg, rgba(0, 0, 0, 0.32), transparent 22%, transparent 78%, rgba(0, 0, 0, 0.32)),
		linear-gradient(180deg, transparent 62%, rgba(0, 0, 0, 0.26));
}

/* Grain last, to keep the large flat fields from banding on cheap panels. No
   mix-blend-mode: .shell__planes is its own stacking context, so a blend would
   composite against its transparent siblings rather than against the body
   gradient, and do nothing at all. Plain opacity actually paints. */
.shell__amb--grain {
	opacity: 0.04;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

@keyframes amb-drift {
	0%, 100% { transform: translate3d(0, 0, 0); }
	50% { transform: translate3d(-24px, 18px, 0); }
}

.rail {
	position: sticky;
	top: 0;
	z-index: 1;
	align-self: start;
	display: flex;
	flex-direction: column;
	height: 100vh;
	padding: 24px 16px 22px;
	background: var(--g-rail);
	border-right: 1px solid var(--c-hairline);
	box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.04);
	overflow-y: auto;
	/* The rail is taller than most screens, so it scrolls, and the browser's own bar
	   is a pale slab on this near-black. Thin, with no track and a thumb that is only
	   a shade lighter than the rail, so it is there when needed and quiet otherwise. */
	scrollbar-width: thin;
	scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}

.col {
	/* The layout question on this page is "how much room does the content column
	   have", never "how wide is the screen" — the rail takes 286px of the answer
	   and only above 1100. Sizing off the viewport got that wrong in both
	   directions: two columns were refused at 1100 with 1100px of room, and
	   would have been forced at 1112 with 826px. */
	container-type: inline-size;
	container-name: shell;
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	min-width: 0;
}

/* The measure the page centres in. Wide enough that a 1440 viewport is filled
   edge to edge rather than boxed — at 1440 the content column is the full
   1114px available and this cap never bites; it only starts holding the line
   somewhere past a 1650px monitor, which is the point of it. The top bar
   deliberately sits outside this and spans the full width. */
.hero,
.ways,
.loop,
.faq,
.footer {
	width: 100%;
	max-width: 1320px;
	margin-inline: auto;
}

.main {
	flex: 1;
	min-width: 0;
	padding: 2.5rem clamp(1rem, 4vw, 3rem) 4rem;
}

/* ------------------------------------------------------------------- brand */

/* The lockup is one drawn wordmark now, not a rounded yellow "A" beside two
   lines of Archivo. The crown sits on the I, the letters are cut with angled
   terminals, and neither survives being rebuilt from a font — so the theme
   serves the artwork and the CSS only has to say how tall it is. */
.brand {
	display: block;
	/* 10px on top of the rail's own 24px puts 34px above the wordmark. Below it,
	   .nav__list already contributes 22px of its own margin, so 12px here makes
	   the same 34px — the logo sits in equal air rather than hanging off the top
	   of a gap half again as deep as the one above it. */
	padding: 10px 8px 12px;
	color: inherit;
}

.brand:hover {
	text-decoration: none;
}

/* Height fixed, width from the aspect ratio. The intrinsic width/height on the
   img reserves the right box before the PNG lands, so the nav under it does not
   jump. .custom-logo is the same rule for a logo set in the Customizer, which
   will not be this file's proportions. The crown logo there is nearly square
   (about 1.9:1, against the old wordmark's 3.9:1), so it needs far more height
   than 52px to be as wide on screen: 88px makes it about 170px across. */
.brand__logo,
.brand .custom-logo {
	display: block;
	width: auto;
	height: 88px;
	max-width: 100%;
	margin-inline: auto;
}

/* --------------------------------------------------------------- rail: nav */

.nav__list,
.nav__sub {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.nav__list {
	margin-top: 22px;
}

.nav__label {
	margin: 0;
	padding: 16px 13px 7px;
	font-size: 9.5px;
	font-weight: 500;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--c-dim);
	font-family: var(--font-mono);
}

.nav__link,
.nav__list a {
	display: flex;
	align-items: center;
	gap: 11px;
	padding: 10px 13px;
	border: 1px solid transparent;
	border-radius: var(--radius);
	font-size: 14.5px;
	font-weight: 500;
	color: rgba(var(--text-rgb), 0.66);
	transition: background-color 0.15s var(--ease), color 0.15s var(--ease);
}

.nav__link .icon {
	flex: none;
	opacity: 0.7;
}

.nav__link:hover,
.nav__list a:hover {
	background: rgba(255, 255, 255, 0.07);
	color: #fff;
	text-decoration: none;
}

/* A rule and yellow type, not a yellow block.

   It was a solid accent gradient the full width of the rail, which made the
   heaviest yellow on the whole screen a label telling you where you already
   are. It sat two hundred pixels from the sign-up button and won, and a page
   with two primaries has none.

   The rule does the same job for a fraction of the ink: an inset shadow rather
   than a border-left, so the row keeps exactly the padding of the six inactive
   rows beside it and the labels stay on one left edge. */
.nav__link.is-active {
	box-shadow: inset 2px 0 0 var(--c-accent);
	background: rgba(var(--accent-rgb), 0.07);
	color: var(--c-accent);
	font-weight: 700;
}

.nav__link.is-active:hover {
	background: rgba(var(--accent-rgb), 0.11);
	color: var(--c-accent-soft);
}

.nav__link.is-active .icon {
	color: var(--c-accent);
	opacity: 1;
}

/* -------------------------------------------------------------- rail: foot */

.rail__foot {
	display: flex;
	flex-direction: column;
	gap: 18px;
	margin-top: auto;
	padding-top: 18px;
}

/* The two big buttons. Full rail width, tall enough to be the heaviest thing in
   the column. Kick takes the blue ring (off-site, not the conversion); the
   sign-up keeps the yellow fill and its own .btn--primary look. */
.rail__cta {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.btn.btn--rail {
	width: 100%;
	height: 58px;
	padding: 0 18px;
	font-size: 15px;
	font-weight: 800;
	letter-spacing: -0.01em;
	white-space: normal;
	text-align: center;
}

.btn--rail-kick {
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.55);
	background: rgba(var(--blue-rgb), 0.08);
	color: var(--c-text);
}

.btn--rail-kick:hover,
.btn--rail-kick:focus-visible {
	background: rgba(var(--blue-rgb), 0.16);
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.9);
	color: var(--c-text);
	text-decoration: none;
}

.btn--rail-kick .icon {
	color: var(--c-blue-soft);
}

/* ------------------------------------------------------------------ topbar */

/* A strip inside the content column, not a bar across the page: the rail owns
   the brand now, so all this carries is the balance and the account control. */
.topbar {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 12px;
	padding: 22px clamp(1.25rem, 3vw, 36px) 0;
}

.topbar__right {
	display: flex;
	align-items: center;
	gap: 12px;
}

/* Only appears once the rail has collapsed into the drawer. */
.topbar__toggle {
	display: none;
}

.topbar__toggle {
	flex-direction: column;
	justify-content: center;
	gap: 4px;
	width: 40px;
	height: 40px;
	padding: 0 9px;
	margin-right: auto;
	background: transparent;
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	cursor: pointer;
	transition: border-color 0.15s var(--ease);
}

.topbar__toggle:hover {
	border-color: var(--c-accent);
}

.topbar__toggle span {
	display: block;
	height: 2px;
	background: var(--c-text);
	border-radius: 2px;
}

/* The stream dashboard: no rail, so one column, with the logo in the top bar
   where the rail would have carried it, at the same 88px as the rail's. */
.shell--bare {
	grid-template-columns: minmax(0, 1fr);
}

.brand--topbar {
	margin-right: auto;
	padding: 0;
}

.brand--topbar .brand__logo,
.brand--topbar .custom-logo {
	margin-inline: 0;
}

/* ----------------------------------------------------------------- balance */

/* Deliberately the same chip as the account control beside it. As a filled
   orange pill it was the loudest thing in the row, which put the emphasis on
   a number you cannot act on instead of the sign-up button below it. */
.balance {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	/* Height matched to the account chip, which is sized by its 28px avatar —
	   two chips of different heights in one row read as a mistake. */
	min-height: 44px;
	padding: 0 16px;
	border: 1px solid rgba(255, 255, 255, 0.12);
	border-radius: var(--radius);
	background: var(--g-chip);
	box-shadow: var(--lift-chip);
	color: var(--c-text);
}

.balance:hover {
	border-color: rgba(var(--accent-rgb), 0.45);
	color: var(--c-text);
	text-decoration: none;
}

.balance__value {
	font-size: 17px;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	line-height: 1;
	font-family: var(--font-mono);
}

.balance__label {
	font-size: 10px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--c-faint);
	font-family: var(--font-mono);
	font-weight: 500;
}

/* ------------------------------------------------------------ account chip */

.chip {
	position: relative;
}

.chip__toggle {
	display: flex;
	align-items: center;
	gap: 9px;
	padding: 7px 16px 7px 7px;
	border: 1px solid rgba(255, 255, 255, 0.12);
	border-radius: var(--radius);
	background: var(--g-chip);
	box-shadow: var(--lift-chip);
	cursor: pointer;
	list-style: none;
	transition: border-color 0.15s var(--ease);
}

/* Safari draws its own disclosure triangle on summary; the chevron is ours. */
.chip__toggle::-webkit-details-marker {
	display: none;
}

.chip__toggle:hover,
.chip[open] .chip__toggle {
	border-color: rgba(var(--accent-rgb), 0.45);
}

.chip[open] .chip__toggle .icon {
	transform: rotate(180deg);
}

.chip__toggle .icon {
	color: var(--c-faint);
	transition: transform 0.15s var(--ease);
}

.chip__menu {
	position: absolute;
	right: 0;
	top: calc(100% + 0.5rem);
	z-index: 60;
	min-width: 190px;
	display: flex;
	flex-direction: column;
	padding: 0.35rem;
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-md);
	background: var(--g-surface);
	box-shadow: var(--lift-card-sm);
}

.chip__item {
	padding: 0.55rem 0.7rem;
	border-radius: var(--radius);
	font-size: 13px;
	font-weight: 600;
	color: var(--c-text);
	text-decoration: none;
}

.chip__item:hover {
	background: rgba(var(--accent-rgb), 0.12);
	color: var(--c-accent-soft);
	text-decoration: none;
}

.chip__item--out:hover {
	background: rgba(255, 77, 94, 0.12);
	color: var(--c-danger);
}

.chip__avatar {
	width: 28px;
	height: 28px;
	flex: none;
	border-radius: var(--radius-xs);
	object-fit: cover;
}

.chip__name {
	font-size: 13px;
	font-weight: 650;
}

/* ----------------------------------------------------------------- buttons */

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	padding: 0.72rem 1.2rem;
	border: 1px solid transparent;
	border-radius: var(--radius-md);
	font: inherit;
	font-size: 0.9rem;
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
	text-decoration: none;
	transition: background 0.15s var(--ease), border-color 0.15s var(--ease), color 0.15s var(--ease);
}

.btn:disabled,
.btn[aria-disabled="true"] {
	opacity: 0.5;
	cursor: not-allowed;
}

/* --primary is the hero's sign-up button; --accent is the same treatment under
   the name the rest of the site already calls it by, so every existing button
   picks up the new direction without touching its template. */
.btn--primary,
.btn--accent {
	border: 0;
	/* Flat fill, not the 180deg ramp. The ramp was the top half of the bevel —
	   light along the top edge falling to a darker bottom — and with the block
	   shadow gone underneath it, it just read as a gradient nobody asked for.
	   One colour, and the hover moves the whole chip rather than its lighting. */
	background: var(--c-accent);
	box-shadow: var(--lift-btn);
	color: var(--c-on-accent);
	transition: background 0.15s var(--ease), color 0.15s var(--ease);
}

.btn--primary:hover,
.btn--accent:hover {
	background: var(--c-accent-soft);
	color: var(--c-on-accent);
	text-decoration: none;
}

.btn--primary {
	padding: 17px 30px;
	font-size: 16px;
	font-weight: 800;
	letter-spacing: -0.01em;
	white-space: nowrap;
}

.btn--ghost {
	border-color: var(--c-border-soft);
	background: var(--g-chip-soft);
	box-shadow: var(--lift-chip);
	color: var(--c-text);
}

.btn--ghost:hover {
	border-color: rgba(var(--accent-rgb), 0.45);
	color: #fff;
	text-decoration: none;
}

/* A blue ring and nothing else, which is the treatment .live__cta already uses
   for the identical button on the front page. The site's two "Watch on Kick"
   controls should be one control.

   It replaced a .btn--primary on the Top Chatters band, and the swap is the
   counting rule rather than a preference: yellow is the conversion, Kick is
   somewhere else Aitch exists, and a filled yellow chip was the loudest thing in
   a section about a raffle that is free to enter. Sized to .live__cta's 44px
   instead of to .btn--primary, because a blue button at the sign-up button's
   size is still a button asking to be pressed first. */
.btn--blue {
	height: 44px;
	padding: 0 1.25rem;
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.55);
	color: var(--c-text);
	font-size: 14.5px;
	transition: box-shadow 0.18s var(--ease), background 0.18s var(--ease);
}

.btn--blue:hover,
.btn--blue:focus-visible {
	background: rgba(var(--blue-rgb), 0.08);
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.9);
	color: var(--c-text);
	text-decoration: none;
}

/* Tinted and ringed, not filled. A solid blue button in the top corner was the
   loudest thing on a logged-out page and it was competing with the sign-up for
   it — this is the way in for people who already have an account, not the
   conversion. The label is set in the mono face, uppercase and tracked out, so
   it reads as a control rather than a third piece of display type. */
.btn--discord {
	padding: 11px 18px 11px 15px;
	background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.16), rgba(var(--blue-rgb), 0.06));
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.42);
	color: var(--c-text);
	font-family: var(--font-mono);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.btn--discord:hover {
	background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.26), rgba(var(--blue-rgb), 0.1));
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.7);
	color: var(--c-text);
	text-decoration: none;
}

/* The mark keeps the blue; the label does not need it. */
.btn--discord .btn__icon {
	color: var(--c-blue-soft);
}

.btn__icon {
	flex: none;
}

/* ----------------------------------------------------------------- socials */

.socials {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	gap: 0.5rem;
}

.socials__link {
	display: grid;
	place-items: center;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	color: var(--c-muted);
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid var(--c-border-soft);
	transition: color 0.16s var(--ease), border-color 0.16s var(--ease), box-shadow 0.16s var(--ease), transform 0.16s var(--ease);
	font-family: var(--font-mono);
}

/* --brand is set per link from PHP, so each platform lights up in its own
   colour without needing a rule per network. */
.socials__link:hover,
.socials__link:focus-visible {
	color: var(--brand, var(--c-accent));
	border-color: var(--brand, var(--c-accent));
	text-decoration: none;
}

/* Centred in the rail. Tried flush left on the pill edge and then indented onto
   the nav labels; both put the row on a line it did not need to be on. Four
   circles at the foot of a column are their own shape, and centring them reads
   as a deliberate end to the list rather than a fifth nav item. */
.socials--nav {
	justify-content: center;
	flex-wrap: wrap;
}

/* ------------------------------------------------------------- view header */

.view {
	max-width: 1100px;
	margin: 0 auto;
}

.view--narrow {
	max-width: 780px;
}

.view--center {
	text-align: center;
}

.view__header {
	/* Left, site-wide. Every view under this puts its content on a left edge —
	   a form, a card grid, a table — and a centred title had nothing lining up
	   beneath it. .view--center remains for pages that do want it centred. */
	text-align: left;
	margin-bottom: 2.5rem;
}

.view__title {
	margin: 0;
	font-size: clamp(2rem, 5.5vw, 3.6rem);
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--c-accent);
	/* The same soft shadow the hero gives its accent line, so a page title reads
	   as the same kind of object across the site. */
	text-shadow: var(--text-block-lg);
}

/* No measure of its own. It was capped at 56ch and that left a lone word on a
   second line whenever a sentence ran a few characters over, which the
   leaderboard's did. Subtitles are one or two short sentences, and the one
   page type that can carry a long one (page.php) is already in the narrow
   column, so the column is the measure. */
.view__sub {
	margin: 1.1rem 0 0;
	color: var(--c-muted);
	font-size: 1.02rem;
}

/* Only present when a header was given several lines. One per line, from the
   line-height rather than from a margin, so the sentences sit together as one
   block of copy instead of reading as three separate statements. */
.view__sub-line {
	display: block;
	line-height: 1.65;
}

.view__content > * + * {
	margin-top: 1.1rem;
}

.view__content h2 {
	margin-top: 2.2rem;
	font-size: 1.3rem;
	color: var(--c-text);
}

.view__content h3 {
	margin-top: 1.6rem;
	font-size: 1.08rem;
}

.view__content ul,
.view__content ol {
	padding-left: 1.3rem;
	color: var(--c-muted);
}

.view__content li + li {
	margin-top: 0.4rem;
}

.view__content p {
	color: var(--c-muted);
}

/* ------------------------------------------------------------------- cards */

/* The generic panel, and the one every inner page is built from — the game
   screens, the profile, the ledger and the shop all wrap themselves in it. It
   was a translucent white wash with no shadow, which is why those pages looked
   flat next to the home page once the palette changed. */
.card {
	padding: 1.4rem;
	background: var(--g-surface);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius);
	box-shadow: var(--lift-card-sm);
}

.cards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: 1rem;
}

/* A whole card as the target, rather than a link inside one. The card is the
   thing being chosen, so making only its title clickable would leave most of it
   inert and the pointer would say so. */
.card--link {
	display: block;
	color: inherit;
	text-decoration: none;
	transition: border-color 0.15s ease, transform 0.15s ease;
}

.card--link:hover,
.card--link:focus-visible {
	border-color: var(--c-border);
	transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
	.card--link {
		transition: none;
	}

	.card--link:hover,
	.card--link:focus-visible {
		transform: none;
	}
}

.card__title {
	margin: 0 0 0.5rem;
	font-size: 1.1rem;
}

.card__text {
	margin: 0;
	font-size: 15px;
	color: var(--c-sub);
}

.empty {
	color: var(--c-muted);
}

/* -------------------------------------------------------------------- hero */

/* The front page carries its own section padding, so .main's page padding is
   removed under it rather than fought with negative margins. */
.home .main {
	padding: 0;
}

/* The whole above-the-fold block: the claim, and what is on right now.

   Stacked here, two columns once the container can hold both — see the query
   further down. The headline is capped at 15ch so it stays a headline rather
   than a paragraph, which means on a wide monitor a one-column hero is a column
   of type against four hundred pixels of nothing. That reads as unfinished, not
   as air, and it was the most valuable space on the site. */
.hero {
	/* The foot was clamp(42px, 7cqi, 86px), and with the ticker's own 30px of
	   margin under it that put about 110px between the sign-up button and the
	   Big Wins label while the ticker sat 57px off the band below it. The strip
	   is evidence for the claim directly above it, so of the two gaps it is the
	   one that should be tighter. */
	padding: clamp(38px, 6cqi, 76px) clamp(1.25rem, 3vw, 36px) clamp(36px, 5cqi, 62px);
}

/* Under the lead while stacked. Its own margin rather than a grid gap, because
   there is no grid at this width. */
.hero__side {
	margin-top: 38px;
}

/* The box the headline is sized against. Both lines are about 7.9em wide with
   the logo at full size, so the type has to follow the room the headline
   actually has, which beside the live card is much less than the page column.
   A wrapper of its own and not .hero__lead, because .hero__prize sizes off the
   page column and would follow it too. */
.hero__head {
	container-type: inline-size;
}

.hero__title {
	margin: 0;
	/* 12cqi of .hero__head is an 8.33em line against the widest 7.9em one, which
	   leaves room for the shadows. On a phone that is the same as the 10.5vw it
	   replaced, and it reaches the 64px ceiling around a 600px window. */
	font-size: clamp(1.85rem, 12cqi, 64px);
	max-width: 15ch;
	font-weight: 900;
	/* 0.92 set the two lines almost touching; at 66px the descender of "Razed."
	   was crowding the cap height of the line under it. */
	line-height: 1.0;
	letter-spacing: -0.035em;
	text-shadow: 0 4px 34px rgba(0, 0, 0, 0.8);
}

.hero__line {
	display: block;
	color: #fff;
}

/* The casino's logo, set inline after "Play on". Sized in em so it scales with
   the headline, and small enough that "Play on" and the logo together are no
   wider than "Earn with" under it, which is what the headline's font size is
   fitted to; any bigger and the logo drops to a line of its own in the
   two-column hero. Images take no text-shadow, so the same shadow comes from
   drop-shadow. */
.hero__line:has(> .hero__brand) {
	white-space: nowrap;
}

/* The headline is a container only so the logo can ask how wide it is. The
   logo is 0.75em tall, which is as tall as the lettering. The headline's size
   is fitted to its own box with the logo at that size, so the logo should never
   need to shrink; min() is the safety net if it ever does, shrinking it just
   enough: what is left of the line after "Play on" (about 4em with its space
   and the margin), over the logo's 792:146 shape. Until 30 Oct 2026 the size
   was fitted to the page column, and beside the live card the logo shrank. */
.hero__title {
	container-type: inline-size;
}

.hero__brand {
	display: inline-block;
	height: min(0.75em, calc((100cqw - 4em) / 5.4247));
	width: auto;
	margin-left: 0.12em;
	vertical-align: -0.06em;
	filter: drop-shadow(0 4px 20px rgba(0, 0, 0, 0.8));
}

/* Upright, in the accent ramp. It was italic until 29 Oct 2026, when Neil asked
   for it upright. */
.hero__line--accent {
	color: var(--c-accent);
	background: linear-gradient(96deg, var(--c-accent-soft), var(--c-accent) 45%, var(--c-accent-mid));
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	/* drop-shadow rather than the inherited text-shadow. With a transparent fill
	   there is no ink to hide a text-shadow behind, so it shows straight through
	   the glyphs and muddies the ramp into brown. drop-shadow filters the
	   composited result, which is what we actually want a shadow of. */
	text-shadow: none;
	filter: drop-shadow(0 4px 26px rgba(0, 0, 0, 0.75));
}

/* Older engines that clip the background but ignore -webkit-text-fill-color
   would render this as invisible text. Falling back to the flat accent costs
   the ramp and keeps the headline. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
	.hero__line--accent {
		background: none;
		-webkit-text-fill-color: currentColor;
		filter: none;
		text-shadow: var(--text-block-lg);
	}
}

/* The pool and its qualifier, as one block behind a rule.

   This was a third display line for a while, at two thirds of the headline in
   solid yellow. Directly under a yellow "Earn with Aitch." that did not
   read as a fact about the offer, it read as a broken third line of the
   headline — and two lines competing to be the headline means there is no
   headline. The rule and the accent on the figure carry the emphasis now, and
   the sentence around the figure does not.

   The rule is the same 2px accent edge that marks first place on the
   leaderboard. Both mean the same thing: this is the one to look at. */
.hero__pool {
	margin: 26px 0 0;
	padding-left: 16px;
	border-left: 2px solid var(--c-accent);
}

.hero__prize {
	margin: 0;
	font-size: clamp(1.3rem, 2.8cqi, 32px);
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.02em;
	color: var(--c-text);
}

/* Weight only, no colour. The figure was yellow here and it was one yellow too
   many above the fold: the headline's second line is already gold and the
   sign-up button is already gold, and a third gold thing between them meant
   none of the three was the one to look at. The rule on the left says which
   block matters; inside it the number can be a number.

   Tabular figures because the pool comes from a config value, and a number that
   changes should not shift the words after it. */
.hero__figure {
	font-weight: 800;
	font-variant-numeric: tabular-nums;
}

/* Carries no number on purpose. The nightly drops are real and they vary, so
   naming a figure here would be a claim somebody could check on a quiet night
   and find short.

   Set in the mono face, which is this site's voice for a quiet aside: the
   ticker label, the 18+ line, the footer. As plain body text a size down it had
   no treatment at all and read as a sentence somebody forgot to finish.

   --c-faint, not --c-dim, and the same rung the 18+ line below it sits on. Dim
   is 3.3:1 against this background, which is under AA for text this size; faint
   is 5.3:1. Quiet is a decision, unreadable is a defect. */
.hero__plus {
	max-width: 52ch;
	margin: 7px 0 0;
	font-family: var(--font-mono);
	font-size: 12.5px;
	line-height: 1.55;
	letter-spacing: 0.04em;
	color: var(--c-faint);
}

.hero__sub {
	max-width: 46ch;
	margin: 22px 0 0;
	font-size: 18.5px;
	line-height: 1.5;
	color: var(--c-sub);
}

/* The code is named, not presented. It sits in the sentence in the mono face at
   full text colour, which is enough to lift it off the muted line without
   turning it back into the thing you have to copy — the sign-up link applies it
   on its own. */
.hero__code {
	font-family: var(--font-mono);
	font-size: 17px;
	font-weight: 700;
	letter-spacing: 0.05em;
	color: var(--c-text);
}

/* One call to action, so this is a wrapper for the sign-up and nothing else.

   It held a pair for a while: an outlined Watch the Kick Stream beside the
   sign-up. The live card in the second column now leads with the way in to
   Kick, and says which state Kick is in while it does, so the outline had
   become a second link to the same channel a hand's width from the first. */
.hero__actions {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	margin-top: 34px;
}

/* The sign-up and the line that qualifies it, as one column. */
.hero__signup {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 10px;
}

/* Height rather than vertical padding: the label sits on a face whose cap
   height would otherwise decide the button's size. */
.hero__signup > .btn--primary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 54px;
	padding: 0 28px;
	border-radius: var(--radius);
	font-size: 16px;
	white-space: nowrap;
}

/* Left while the button it qualifies runs the full column, so it keeps the same
   left edge as everything else in the hero. Back to centred on the button once
   the button is button-sized again. */
.hero__legal {
	margin: 0;
	text-align: left;
}

.hero__legal a {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.06em;
	color: var(--c-faint);
}

.hero__legal a:hover,
.hero__legal a:focus-visible {
	color: var(--c-text);
}

/* ------------------------------------------------------------- live status */

/* The hero's second column. Raised, because it is the one card on the page
   whose contents are different every time you look — everything else here is a
   claim that holds for a month. */
.live {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 14px;
	padding: 18px;
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: var(--radius);
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
}

/* The state line, in the label voice the rest of the page uses for anything the
   site computed rather than wrote. */
.live__state {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--c-faint);
}

/* Red, and neither of the two colours already carrying meaning here. Yellow is
   the conversion and blue is the two places Aitch exists off this site; a live
   indicator is neither, and red for on-air is the one convention on the whole
   page that needs no learning. */
.live--on .live__state {
	color: var(--c-danger);
}

/* The pip, and the reason it is allowed back.

   There was one in the rail and it was cut, correctly: it pulsed and glowed
   whether or not anybody was streaming, so it was decoration claiming to be
   status. This one only exists inside .live--on, which is a class the server
   only writes when Kick has said he is on air. Same halo, opposite honesty. */
.live__pip {
	flex: none;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--c-danger);
	box-shadow: 0 0 0 3px rgba(255, 77, 94, 0.18);
	animation: live-pulse 2.4s var(--ease) infinite;
}

@keyframes live-pulse {
	0%,
	100% {
		opacity: 1;
	}

	50% {
		opacity: 0.35;
	}
}

/* Nothing on this page moves for people who asked it not to. */
@media (prefers-reduced-motion: reduce) {
	.live__pip {
		animation: none;
	}
}

/* A fixed 16:9 box holding the embedded player, so a slow frame cannot change
   the height of the hero under somebody mid-read. */
.live__thumb {
	display: block;
	overflow: hidden;
	aspect-ratio: 16 / 9;
	border-radius: var(--radius);
	background: var(--c-well);
}

.live__thumb iframe {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

/* Two lines and then clipped. Stream titles run to whatever the streamer felt
   like typing, and this card sits beside a headline whose whole job is to be
   the largest thing on the screen. */
.live__title {
	display: -webkit-box;
	overflow: hidden;
	margin: 0;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--c-text);
}

/* The two facts that move. Mono, like every other computed figure on the site,
   and separated by a rule rather than a bullet so they read as two readings
   rather than one sentence. */
/* One uniform treatment across the whole row, and no emphasis inside it. The
   viewer count used to be wrapped in a <strong>, which made the one figure on
   the card that nobody came for the brightest thing under the title.

   Left at --c-faint rather than moved to --c-muted: faint is already a step
   quieter than muted, so switching would have brightened the row while trying
   to play it down. Nothing in here is emphasised now. */
.live__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 12px;
	margin: 0;
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: 0.04em;
	color: var(--c-faint);
}

.live__watching strong {
	font-weight: 700;
	color: var(--c-text);
	font-variant-numeric: tabular-nums;
}

/* A separator, so it only draws when there is something on the other side of
   it. Going live with nobody watching yet means .live__watching is never
   rendered, and an unconditional border-left showed up as a stray divider
   leading the row: "| 1 minute in". */
.live__since:not(:first-child) {
	padding-left: 12px;
	border-left: 1px solid var(--c-hairline);
}

/* Mono, and the only prose on the page set in it. Everywhere else the mono is
   reserved for values the site computed, which this is not, but it is also not
   quite prose: it is the card's standing terms, the one line that is true every
   night rather than true right now. The face marks it as fixed while the state
   line and the clock above it change. A step down in size, because mono runs
   wider than the sans at the same nominal size and this line has to fit the
   hero's narrow second column without wrapping to three. */
/* Stands in for the countdown once he is due, so it is sized against the
   digits it replaces rather than against the prose around it: the same white,
   a little smaller because these are words and not four two-character wells.
   It is the answer to the question the clock was answering, so it has to carry
   the clock's presence or the card reads as though something failed to load. */
.live__soon {
	margin: 0;
	font-size: clamp(16px, 1.8cqi, 19px);
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--c-text);
}

.live__cadence {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 11.5px;
	line-height: 1.45;
	letter-spacing: 0.01em;
	color: var(--c-muted);
}

/* Its own line, and the line-height above is what sets the distance. A second
   paragraph would have taken the card's 14px section gap, which would read as
   two unrelated notes rather than one two-line note. */
.live__reward {
	display: block;
}

/* Smaller than the leaderboard's, which is the section that clock is built
   around. This one is a supporting figure in a card, so the units keep their
   recessed wells and lose about a third of their size. */
.clock--mini {
	gap: 8px;
}

.clock--mini .clock__unit {
	flex: 1;
	min-width: 0;
	padding: 9px 6px 8px;
	gap: 5px;
}

/* White, not the accent the leaderboard's digits take. That clock is the peak
   of its own band and has earned the colour; this one is a supporting figure in
   the corner of the hero, and three yellow wells up there were pulling harder
   than the yellow line of the headline they sit beside. */
.clock--mini .clock__value {
	font-size: clamp(19px, 2.1cqi, 24px);
}

.clock--mini .clock__label {
	font-size: 8.5px;
	letter-spacing: 0.14em;
}

/* Blue, and this is what blue means now: a way to reach Aitch somewhere that is
   not this site. The rail's Kick pill, the top bar's Discord control, and the
   FAQ's way out are the same colour for the same reason. Nothing decorative
   takes it any more — the earn cards' icon tiles used to, and a colour spent on
   ornament cannot also carry a meaning. */
.live__cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	margin-top: auto;
	height: 44px;
	border-radius: var(--radius);
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.55);
	font-size: 14.5px;
	font-weight: 700;
	color: var(--c-text);
	transition: box-shadow 0.18s var(--ease), background 0.18s var(--ease);
}

.live__cta svg {
	color: var(--c-blue);
}

.live__cta:hover,
.live__cta:focus-visible {
	box-shadow: inset 0 0 0 1px rgba(var(--blue-rgb), 0.9);
	background: rgba(var(--blue-rgb), 0.08);
	color: var(--c-text);
	text-decoration: none;
}

/* ---------------------------------------------------------- floating live tab */

/* On every page but the front page, where the hero card does this job. Fixed to
   the bottom right: the rail is on the left, and the sticky sign-up bar only
   exists on the front page, so the two never meet.

   z-index 30 puts it under the mobile drawer's scrim (35) and drawer (40). The
   daily reward is a <dialog> and sits in the top layer above all of this. */
.dock {
	position: fixed;
	right: max(16px, env(safe-area-inset-right, 0px));
	bottom: max(16px, env(safe-area-inset-bottom, 0px));
	z-index: 30;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 10px;
	max-width: calc(100vw - 32px);
}

.dock__tab {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	height: 40px;
	padding: 0 14px;
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 999px;
	background: rgba(var(--base-rgb), 0.92);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--c-faint);
	cursor: pointer;
	transition: border-color 0.18s var(--ease), color 0.18s var(--ease);
}

.dock__tab:hover,
.dock__tab:focus-visible {
	border-color: rgba(255, 255, 255, 0.22);
}

/* Grey and still while he is off: a pulsing dot that is always on indicates
   nothing, which is the reason the card's pip is only drawn inside .live--on. */
.dock__pip {
	flex: none;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--c-faint);
	opacity: 0.55;
}

.dock--on .dock__tab {
	color: var(--c-danger);
	border-color: rgba(255, 77, 94, 0.35);
}

.dock--on .dock__pip {
	background: var(--c-danger);
	opacity: 1;
	box-shadow: 0 0 0 3px rgba(255, 77, 94, 0.18);
	animation: live-pulse 2.4s var(--ease) infinite;
}

.dock__chev {
	flex: none;
	transition: transform 0.18s var(--ease);
}

.dock__tab[aria-expanded="true"] .dock__chev {
	transform: rotate(180deg);
}

.dock__panel {
	display: flex;
	flex-direction: column;
	gap: 12px;
	width: min(360px, calc(100vw - 32px));
	padding: 12px;
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: var(--radius);
	background: var(--g-raised);
	box-shadow: 0 24px 60px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.13);
}

.dock__panel[hidden] {
	display: none;
}

.dock__player {
	overflow: hidden;
	aspect-ratio: 16 / 9;
	border-radius: var(--radius);
	background: var(--c-well);
}

.dock__player iframe {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

/* Which half shows is the one attribute main.js flips, so a change of state is
   a single write and the two halves cannot disagree. */
.dock[data-live="1"] .dock__off,
.dock[data-live="0"] .dock__on,
.dock[data-live="0"] .dock__player {
	display: none;
}

.dock__on,
.dock__off {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.dock__title {
	display: -webkit-box;
	overflow: hidden;
	margin: 0;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	font-size: 14px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--c-text);
}

.dock__meta {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: 0.04em;
	color: var(--c-faint);
}

.dock__meta[hidden] {
	display: none;
}

.dock__next {
	display: flex;
	flex-direction: column;
	gap: 2px;
	margin: 0;
	font-size: 15px;
	font-weight: 700;
	color: var(--c-text);
}

.dock__kicker {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--c-faint);
}

@media (prefers-reduced-motion: reduce) {
	.dock--on .dock__pip {
		animation: none;
	}

	.dock__chev,
	.dock__tab {
		transition: none;
	}
}

/* ------------------------------------------------------- home section heads */

/* The four front-page section heads, as one rule.

   They were four rules at 46 / 42 / 34 / 27, which was a deliberate ramp and a
   mistake. A size ramp states a hierarchy, and these four have none: Ways to
   Win, the leaderboard band, How points work and Questions are peer sections of
   one page, read in order, none subordinate to another. All the ramp did was
   make the last one look like it mattered least.

   One size, and one rule rather than four, so they cannot drift apart again the
   way they already did once. 38px sits clearly under the hero's 64 without any
   of them having to be small to prove it. */
.ways__title,
.ladder__title,
.loop__heading,
.faq__title {
	margin: 0;
	/* 3.2cqi reaches the ceiling as the content column does, so every head is at
	   full size on the desktop layout and they all give way together below it. */
	font-size: clamp(1.75rem, 3.2cqi, 38px);
	font-style: italic;
	font-weight: 900;
	line-height: 1.1;
	letter-spacing: -0.03em;
	color: #fff;
	text-shadow: none;
}

/* The only one that owns the gap to what follows it: the other three are
   followed by a subheading or a rule that carries its own spacing. */
.loop__heading {
	margin-bottom: 26px;
}

/* ------------------------------------------------------------- how to earn */

.ways {
	padding: 0 clamp(1.25rem, 3vw, 36px) clamp(46px, 6cqi, 82px);
}


/* Kept for the *asterisk* emphasis the heading field still supports. It is no
   longer used by the shipped copy. */
.ways__accent {
	color: var(--c-accent);
	text-shadow: none;
}

.ways__sub {
	max-width: 52ch;
	margin: 12px 0 34px;
	font-size: 17px;
	color: var(--c-sub);
}

.ways__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 22px;
	align-items: stretch;
}

.way {
	position: relative;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	padding: 26px;
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: var(--radius);
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
	transition: border-color 0.15s var(--ease);
}

/* Border only. This direction keeps everything planted — nothing lifts, skews
   or scales on hover, because the block shadows are what say "raised" and a
   transform would contradict them mid-gesture. */
.way:hover {
	border-color: rgba(var(--accent-rgb), 0.5);
}

/* The ghost 01 / 02 / 03 that used to sit behind each card is gone. It numbered
   the columns, and numbering implies a sequence to work through — these are
   four alternatives, and a visitor takes one or none of them. The corner now
   carries the prize instead, which is the thing that actually decides which one
   they take. */
.way > * {
	position: relative;
	z-index: 1;
}

/* The icon and the prize, on one line at the top of the card. */
.way__top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
	width: 100%;
	margin-bottom: 14px;
}

/* Grey, and it has been yellow and then white. Yellow went because four of
   these ran across the section in the same colour as the four links under them
   and the sign-up button, putting eight accent elements in one screen, and the
   whole argument for reserving yellow is that a page with eight primaries has
   none. White went because the title is white too, and two white elements on
   one card compete: the corner is supporting detail, so it now sits a step back
   in the muted grey and lets the title lead on colour as well as size.

   Still a figure rather than a label: right-aligned against the card edge,
   balanced so a two-line label breaks evenly rather than leaving one word on
   the second line, and set in the sans rather than the mono, because the mono
   is for values the site computed and this is a claim somebody typed. */
.way__corner {
	max-width: 60%;
	font-size: clamp(14px, 1.45cqi, 18px);
	font-weight: 800;
	line-height: 1.15;
	letter-spacing: -0.015em;
	text-align: right;
	color: var(--c-muted);
	text-wrap: balance;
}

/* Neither yellow nor blue. Yellow is spent on things you can act on, and four
   yellow tiles above four yellow links doubled that up without meaning anything
   by it — which was the reasoning that made these blue tiles in the first
   place. But blue now has a job: it marks the two places Aitch exists that are
   not this site, which is why the rail's Kick pill, the top bar's Discord
   control, the live card's way in and the FAQ's way out all share it. A colour
   spent on four decorative tiles cannot also carry a meaning, and the tiles
   were the cheapest of the two to give up.

   So they are drawn from the surface instead: a recessed plate with the glyph
   in the body colour. It is the quietest the cards have ever been at the top,
   and the corner figure beside it is what should be loud there anyway. */
.way__icon {
	flex: none;
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: var(--radius);
	background: rgba(var(--text-rgb), 0.06);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
	color: var(--c-sub);
	transition: color 0.15s var(--ease), background 0.15s var(--ease);
}

.way:hover .way__icon {
	background: rgba(var(--accent-rgb), 0.1);
	color: var(--c-accent);
}

.way__title {
	margin: 0;
	font-size: 25px;
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1.2;
}

.way__text {
	margin: 14px 0 22px;
	font-size: 15.5px;
	line-height: 1.55;
	color: var(--c-muted);
	text-wrap: pretty;
}

.way__cta {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	/* Pinned to the bottom so the three links sit on one line however unequal
	   the paragraphs above them are. */
	margin-top: auto;
	font-size: 14.5px;
	font-weight: 700;
	color: var(--c-accent);
}

.way__cta:hover {
	color: var(--c-accent-soft);
	text-decoration: none;
}

/* The chevron is drawn pointing down for the account menu; here it leads on. */
.way__cta svg {
	transform: rotate(-90deg);
}

/* --------------------------------------------------- razed leaderboard band */

/* The peak of the homepage, and the only section that gets its own ground.
   Everything above it is a claim about money; this is the money being spent,
   with names against it and a clock running out.

   Full bleed like the ticker, so the change of background reads as a band the
   page passes through rather than as a very large card sitting on it. The
   measure comes back on the inner. */
.ladder {
	margin: 0 0 clamp(46px, 6cqi, 82px);
	padding: clamp(34px, 4.6cqi, 62px) 0 clamp(36px, 4.6cqi, 64px);
	background: var(--c-surface);
	/* One coloured hairline along the top edge and a plain one along the
	   bottom. The band is entered, not left.

	   Blue rather than accent, and it is the same rule as everywhere else:
	   yellow is spent on things you can act on, blue marks the places Aitch
	   exists that are not this site. Nothing in this band is actionable, and
	   every figure in it comes from Razed, so a yellow edge was promising a
	   control that is not there while a blue one names where the numbers are
	   from. Same 0.3 alpha, so the weight of the line does not change. */
	border-top: 1px solid rgba(var(--blue-rgb), 0.3);
	border-bottom: 1px solid var(--c-hairline);
}

.ladder__inner {
	width: 100%;
	max-width: 1320px;
	margin-inline: auto;
	padding-inline: clamp(1.25rem, 3vw, 36px);
}

/* The header, the clock and the way in, as one group. Stacked here and laid out
   as a row on a wide column — see the container query. They are one element
   rather than three because the order is the same either way, so only the
   direction has to change. */
.ladder__bar {
	display: flex;
	flex-direction: column;
	gap: 24px;
	margin-bottom: 30px;
}

/* With no standings and no split saved, the bar is the whole band, and that
   margin is 30px of nothing above the section's own padding. */
.ladder__bar:last-child {
	margin-bottom: 0;
}

/* Nothing under it: the gap on .ladder__bar owns the spacing in both
   directions, and a margin here would only be right in one of them. */
.ladder__head {
	margin: 0;
}

.ladder__sub {
	max-width: 56ch;
	margin: 10px 0 0;
	font-size: 16.5px;
	color: var(--c-sub);
}

/* --- the clock ---------------------------------------------------------- */

/* Recessed, per the rule the rest of the site follows: things you read or act
   on are raised, things showing a computed value are sunk into the surface.
   A countdown is the purest computed value on the site. */
.clock {
	/* A grid of four, not a wrapping flex row, and the difference is only
	   visible at the right-hand edge. Wrapping, the box sizes itself to its
	   widest possible single line, which is the label plus all four wells: 328px
	   where the wells themselves come to 246. The label then forces a wrap and
	   the digits sit left inside a box 82px wider than they are, so aligning the
	   box to the right of the band left the digits visibly short of it. Nothing
	   in the flex version can see that space, because to flex the box is full.

	   Four columns the wells' own width, with the label spanning them, makes the
	   box exactly as wide as what is drawn in it. */
	display: grid;
	grid-template-columns: repeat(4, auto);
	gap: clamp(8px, 1.4cqi, 14px);
	justify-content: start;
	margin: 0;
}

/* What the clock is counting to. Spans the wells rather than sitting over the
   first one, which is what makes it the label for the whole row.

   aria-hidden, because the clock already carries a screen-reader sentence
   naming the event and the date in full. Two labels for one element read as two
   elements. */
.clock__title {
	grid-column: 1 / -1;
	margin: 0;
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 500;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--c-dim);
}

/* The moment the clock is counting to, written out with its zone. Under the
   wells rather than over them: the title says what, this says exactly when, and
   the digits stay the first thing in the row. aria-hidden for the same reason as
   the title, since the screen-reader sentence carries the full date and zone. */
.clock__when {
	grid-column: 1 / -1;
	margin: 0;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.04em;
	color: var(--c-dim);
}

.clock__unit {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 7px;
	min-width: 66px;
	padding: 12px 12px 10px;
	border-radius: var(--radius);
	background: var(--c-well);
	box-shadow: var(--well-inset);
}

/* Tabular figures, or the row rewraps four times a minute as 1s give way to
   0s. This is the one element on the page where that would be visible. */
/* Muted, at the weight of the copy around it, rather than in the accent. A
   countdown is the largest element in its band and it was also the loudest
   colour on the page, which spent the one colour that means "act on this" on a
   number nobody can act on. The size already says it matters. */
.clock__value {
	font-family: var(--font-mono);
	font-size: clamp(24px, 3.1cqi, 38px);
	font-weight: 700;
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--c-sub);
	font-variant-numeric: tabular-nums;
}

.clock__label {
	font-family: var(--font-mono);
	font-size: 9.5px;
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--c-dim);
}

/* Run out, and waiting on the next page load to learn what comes next. Dimmed
   rather than hidden: the digits are still the truth, they have simply stopped
   being urgent. */
.clock.is-done .clock__value {
	color: var(--c-dim);
}

/* --- the top five ------------------------------------------------------- */

/* The reader's own standing, and the empty week. Both sit between the bar and
   the table, both are one sentence, and neither belongs in the table itself:
   one is addressed to a single person and the other exists because there is no
   table to be inside. */
.ladder__you,
.ladder__empty {
	margin: 0 0 14px;
	padding: 12px 16px;
	border-radius: var(--radius);
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
	font-size: 15px;
	color: var(--c-sub);
}

.ladder__you strong {
	font-family: var(--font-mono);
	font-weight: 500;
	color: var(--c-text);
}

.ladder__table {
	overflow-x: auto;
	border-radius: var(--radius);
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
}

.ladder__table table {
	width: 100%;
	border-collapse: collapse;
}

.ladder__table th {
	padding: 11px 16px;
	background: var(--c-board-head);
	font-family: var(--font-mono);
	font-size: 9.5px;
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	text-align: left;
	color: var(--c-dim);
	white-space: nowrap;
}

.ladder__table td {
	padding: 13px 16px;
	border-top: 1px solid var(--c-hairline);
	font-size: 15px;
}

.ladder__table tbody tr:first-child td {
	border-top: 0;
}

/* And the heading over them. `.ladder__table th` is a class plus an element,
   which outranks a bare class, so the header stayed left while its column went
   right and every figure sat under the wrong word. */
.ladder__table th.ladder__num {
	text-align: right;
}

/* Figures right, and in the mono face with tabular figures, so the column reads
   as a column rather than as five separate amounts. */
.ladder__num {
	text-align: right;
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.ladder__rank {
	width: 1%;
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--c-muted);
	white-space: nowrap;
}

.ladder__player {
	font-weight: 600;
	color: var(--c-text);
	overflow-wrap: anywhere;
}

/* A player who has a profile here is a link, and most players do not, so the
   affordance has to sit on the name rather than on the row: half a column of
   links and half of plain text is exactly the case a whole-row treatment cannot
   express.

   Text coloured at rest with a faint rule under it, blue on hover, which is the
   meaning blue already carries in this band on .ladder__more: somewhere else you
   can go, as against the yellow thing to press. Yellow is spent on the clock,
   first place's rule and the whole Prize column already, and a fourth use of it
   running down the middle of the table would beat all three. */
.ladder__link {
	color: inherit;
	text-decoration: underline;
	text-decoration-color: rgba(var(--text-rgb), 0.26);
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}

.ladder__link:hover,
.ladder__link:focus-visible {
	color: var(--c-blue);
	text-decoration-color: currentColor;
}

/* When the figures were last true. Only on the full board: the homepage shows
   five names and a clock and does not need a second date under them, but a page
   somebody opened to check a standing should say how old it is, and it is the
   one line that explains a missing Wagered column rather than leaving the gap
   unaccounted for. */
.ladder__stamp {
	margin: 12px 0 0;
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--c-dim);
}

.ladder__prize {
	color: var(--c-accent);
	font-weight: 700;
}

/* First place gets the wash and the bar; everything else on the board is
   identical. One row of emphasis is what makes it emphasis. */
.ladder__table tr.is-first {
	background: rgba(var(--accent-rgb), 0.07);
}

.ladder__table tr.is-first .ladder__rank {
	box-shadow: inset 3px 0 0 var(--c-accent);
	color: var(--c-text);
}


/* --- monthly wager rewards ---------------------------------------------- */

/* Under the board, on the page's own ground rather than a second band: it is the
   same page and the same measure, and a second full-bleed section would make the
   leaderboard look like the first of two things. The heading, the table and the
   fine print reuse the board's own rules above so the two read as one family. */
.milestones {
	margin: clamp(34px, 4.6cqi, 62px) 0 clamp(46px, 6cqi, 82px);
}

.milestones .ladder__head {
	margin-bottom: 24px;
}

/* The table is the board's. Only the first column changes: it is a mark, not a
   player, so it is not given the name's weight on a narrow screen. */
.milestones__table .ladder__player {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
}

.milestones__more {
	margin: 16px 0 0;
	font-size: 15px;
	color: var(--c-sub);
}

/* The way in. A raised card, since it is something you act on, with the one
   button in blue because the ticket is in Discord, which is not this site. */
.milestones__claim {
	margin-top: 26px;
	padding: clamp(20px, 3cqi, 30px);
	border-radius: var(--radius);
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
}

.milestones__claim-title {
	margin: 0 0 12px;
	font-size: 19px;
	font-weight: 800;
	color: var(--c-text);
}

.milestones__steps {
	margin: 0;
	padding-left: 1.25em;
	font-size: 15.5px;
	color: var(--c-sub);
}

.milestones__steps li + li {
	margin-top: 6px;
}

.milestones__cta {
	margin: 20px 0 0;
}

.milestones__fine {
	max-width: 72ch;
	margin-top: 18px;
	line-height: 1.55;
}

/* The short form on the front page, inside the leaderboard band under the
   podium. Sunk rather than raised, per the rule the band follows: it shows
   figures, it is not a control, and the one thing to press is the link. */
.mstrip {
	margin-top: 30px;
	padding: clamp(16px, 2.4cqi, 24px);
	border-radius: var(--radius);
	background: var(--c-well);
	box-shadow: inset 0 0 0 1px var(--c-hairline);
}

.mstrip__head {
	margin-bottom: 14px;
}

.mstrip__title {
	margin: 0;
	font-size: 19px;
	font-weight: 800;
	color: var(--c-text);
}

.mstrip__sub {
	margin: 4px 0 0;
	font-size: 14.5px;
	color: var(--c-sub);
}

/* Four across when there is room, two by two on a phone. */
.mstrip__marks {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.mstrip__item {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 12px 14px;
	border-radius: 6px;
	background: var(--c-surface);
}

.mstrip__wager {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--c-dim);
}

/* The reward is the money, so it takes the band's one yellow, as the Prize
   column does on the board. */
.mstrip__prize {
	font-family: var(--font-mono);
	font-size: 22px;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--c-accent);
}

@media (min-width: 720px) {
	.mstrip__marks {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* --- the podium --------------------------------------------------------- */

/* The first three places, apart from the table and above it. Second on the
   left, first raised in the middle, third on the right, in a column wide enough
   for three cards; stacked 1, 2, 3 below that, which is also the order in the
   markup.

   The medal and the prize are what the card is made of, because there is no
   face to put in it. Each place carries one metal and spends it twice, on the
   numeral and on the figure, so the eye reads the two as belonging together.

   The metals stay in the yellow family's neighbourhood on purpose. First is the
   accent itself and so the only yellow on the card; silver is the neutral ramp
   and bronze a muted copper. Blue and red are taken (a way off this site, and
   live), and a fourth hue for third place would be the card reaching for
   something nothing else on the page uses.

   No halo on any of it. Depth is the block edge under the card and the ring
   round the medal, which is the rule the rest of the surfaces follow. */
.podium {
	--silver-a: #F4F7FB;
	--silver-b: #B7C1CF;
	--silver-c: #7E8A9B;
	--silver-rgb: 183, 193, 207;
	--bronze-a: #EDBB8C;
	--bronze-b: #C8803F;
	--bronze-c: #8A4E1E;
	--bronze-rgb: 200, 128, 63;

	display: grid;
	gap: 22px;
	margin: 0 0 40px;
	padding: 0;
	list-style: none;
}

.podium__card {
	--tier-a: var(--c-accent-warm);
	--tier-b: var(--c-accent);
	--tier-c: var(--c-accent-mid);
	--tier-rgb: var(--accent-rgb);

	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	padding: 26px 20px 28px;
	border-radius: 14px;
	/* A wash of the card's own metal down from the top, over the raised
	   surface, so first reads warm and the other two cool without any of them
	   being a flat colour. The ring is an inset shadow because the card has no
	   border to spend. */
	background:
		linear-gradient(180deg, rgba(var(--tier-rgb), 0.11), transparent 52%),
		var(--g-raised);
	box-shadow: var(--lift-podium-sm), inset 0 0 0 1px rgba(var(--tier-rgb), 0.3);
	text-align: center;
	overflow: hidden;
}

.podium__card--2 {
	--tier-a: var(--silver-a);
	--tier-b: var(--silver-b);
	--tier-c: var(--silver-c);
	--tier-rgb: var(--silver-rgb);
}

.podium__card--3 {
	--tier-a: var(--bronze-a);
	--tier-b: var(--bronze-b);
	--tier-c: var(--bronze-c);
	--tier-rgb: var(--bronze-rgb);
}

/* The bar across the top of the card, in the metal. Clipped to the card's
   corners by its overflow. */
.podium__card::before {
	content: "";
	position: absolute;
	inset: 0 0 auto;
	height: 4px;
	background: linear-gradient(90deg, var(--tier-c), var(--tier-a) 50%, var(--tier-c));
}

/* First place only: rays out from behind the medal. Texture rather than light,
   which is why it is a low-alpha pattern faded to nothing and not a bloom. */
.podium__card--1::after {
	content: "";
	position: absolute;
	inset: 0;
	background: repeating-conic-gradient(from 0deg at 50% 92px, rgba(var(--tier-rgb), 0.075) 0 5deg, transparent 5deg 15deg);
	-webkit-mask-image: radial-gradient(circle at 50% 92px, #000, transparent 62%);
	mask-image: radial-gradient(circle at 50% 92px, #000, transparent 62%);
	pointer-events: none;
}

.podium__card > * {
	position: relative;
	z-index: 1;
}

/* The place. A ring of the metal, a dark disc inside it, and the numeral cut
   from the same metal, so it reads as a struck medal and not as a number in a
   circle. */
.podium__medal {
	position: relative;
	display: grid;
	place-items: center;
	width: 84px;
	height: 84px;
	padding: 5px;
	border-radius: 50%;
	background: linear-gradient(150deg, var(--tier-a), var(--tier-b) 46%, var(--tier-c));
	box-shadow: 0 6px 0 rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

.podium__medal::before {
	content: "";
	position: absolute;
	inset: 5px;
	border-radius: 50%;
	background: radial-gradient(circle at 50% 30%, #1C2636, #0A0F18 75%);
	box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(0, 0, 0, 0.5);
}

.podium__place {
	position: relative;
	font-size: 44px;
	font-style: italic;
	font-weight: 900;
	line-height: 1;
	letter-spacing: -0.03em;
	background: linear-gradient(180deg, var(--tier-a), var(--tier-b) 55%, var(--tier-c));
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	/* A drop-shadow filter, not text-shadow: on a clipped, transparent fill the
	   shadow would paint straight through the glyph. */
	filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.6));
}

.podium__crown {
	position: absolute;
	top: -19px;
	left: 50%;
	z-index: 1;
	width: 34px;
	height: auto;
	transform: translateX(-50%);
	color: var(--tier-b);
	filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.55));
}

.podium__name {
	max-width: 100%;
	margin: 22px 0 0;
	font-size: clamp(19px, 2cqi, 24px);
	font-weight: 800;
	line-height: 1.15;
	color: var(--c-text);
	overflow-wrap: anywhere;
	text-wrap: balance;
}

.podium__wagered {
	display: inline-flex;
	align-items: baseline;
	gap: 8px;
	margin: 12px 0 0;
	padding: 6px 14px;
	border-radius: var(--radius);
	background: var(--c-well);
	box-shadow: var(--well-inset);
	font-family: var(--font-mono);
	font-size: 12px;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	color: var(--c-dim);
}

.podium__wagered strong {
	font-weight: 600;
	color: var(--c-sub);
}

.podium__prize {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	margin: 22px 0 0;
}

.podium__prize strong {
	font-size: clamp(34px, 3.5cqi, 44px);
	font-style: italic;
	font-weight: 900;
	line-height: 1;
	letter-spacing: -0.02em;
	font-variant-numeric: tabular-nums;
	background: linear-gradient(180deg, var(--tier-a), var(--tier-b) 52%, var(--tier-c));
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.55));
}

.podium__prize span {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 500;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--c-dim);
}

/* First is the largest of the three on every axis, and in the row it is also
   the tallest, which is what makes it a podium and not three cards. */
.podium__card--1 {
	padding-top: 42px;
	padding-bottom: 34px;
}

.podium__card--1 .podium__medal {
	width: 108px;
	height: 108px;
	padding: 6px;
}

.podium__card--1 .podium__medal::before {
	inset: 6px;
}

.podium__card--1 .podium__place {
	font-size: 58px;
}

.podium__card--1 .podium__name {
	margin-top: 26px;
	font-size: clamp(22px, 2.4cqi, 29px);
}

.podium__card--1 .podium__prize strong {
	font-size: clamp(40px, 4.4cqi, 56px);
}

@container shell (min-width: 760px) {
	.podium {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		align-items: end;
		gap: clamp(14px, 2cqi, 26px);
	}

	/* One row, whatever the markup order is. With fewer than three players the
	   missing places leave their column empty rather than sliding first to the
	   left. */
	.podium__card {
		grid-row: 1;
	}

	.podium__card--1 {
		grid-column: 2;
	}

	.podium__card--2 {
		grid-column: 1;
	}

	.podium__card--3 {
		grid-column: 3;
	}
}

@media (max-width: 560px) {
	.podium {
		gap: 18px;
	}

	.podium__card--1 .podium__prize strong {
		font-size: 44px;
	}
}

/* Blue, and this band is the reason the counting rule exists. Yellow in here
   carries the clock, first place's rule and every figure in the Prize column,
   and on the leaderboard page the sign-up button as well.

   So the link that just goes and reads more takes the other colour. Same blue
   as the FAQ's way out to Discord, and the same distinction: yellow is the
   thing this page wants you to do, blue is somewhere else you can go. */
.ladder__more {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-top: 14px;
	font-size: 14px;
	font-weight: 700;
	color: var(--c-blue);
}

.ladder__more:hover,
.ladder__more:focus-visible {
	color: var(--c-blue-soft);
	text-decoration: none;
}

/* Right, because it leads off the page. The FAQ rows further down point down
   and turn up instead, because those open in place. */
.ladder__more svg {
	transform: rotate(-90deg);
}

.ladder__cta {
	margin: 0;
}

/* ------------------------------------------------------------ points loop */

/* The lightest section on the page, and deliberately so: it sits between the
   earn grid and the FAQ and has to lose to both. No borders, no fills, no
   raised surfaces — three columns and two arrows. The counting rule that
   governs colour governs weight too, and this section has no claim on either. */
.loop {
	padding: 0 clamp(1.25rem, 3vw, 36px) clamp(46px, 6cqi, 82px);
}

/* 30px stacked, and the container query takes it to 40 in a row. The arrow that
   used to lead into each step was doing part of this job on a phone — badly,
   but it was doing it — so with the arrows gone the gap is the only thing left
   separating one step from the next, and 24px was not enough of it. */
.loop__steps {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 30px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* A column, so the three links can be pushed to a common baseline however
   unequal the sentences above them are. */
.loop__step {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

.loop__title {
	margin: 0 0 6px;
	font-size: 19px;
	font-weight: 700;
	letter-spacing: -0.015em;
	line-height: 1.25;
}

.loop__text {
	margin: 0 0 18px;
	max-width: 42ch;
	font-size: 15px;
	line-height: 1.55;
	color: var(--c-muted);
	text-wrap: pretty;
}

/* One link per step, and the one that step is about: the stream under earning,
   the games under multiplying, the shop under redeeming. They were a shared row
   under the section, which put the Points Shop link beneath "Earn points" as
   though that were where earning happened.

   Pinned to the bottom so the three sit on one line however unequal the
   paragraphs above them are, the same as the earn cards. */
.loop__cta {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-top: auto;
	font-size: 14.5px;
	font-weight: 700;
	color: var(--c-accent);
}

.loop__cta:hover {
	color: var(--c-accent-soft);
	text-decoration: none;
}

.loop__cta svg,
.faq__out svg {
	transform: rotate(-90deg);
}

/* ------------------------------------------------------------------- faq */

.faq {
	padding: 0 clamp(1.25rem, 3vw, 36px) clamp(46px, 6cqi, 82px);
}

.faq__head {
	margin-bottom: 20px;
}

/* Narrow and left-aligned. This is the one block of running prose on the page
   and it is read a line at a time, not scanned. 800px is about 90 characters of
   the answer copy, which is already at the top of what a line should carry.

   Stacked under the heading here; beside it once there is room for both — see
   the container query. That is what stops the cap reading as a section that
   stopped short of the page. */
.faq__list {
	max-width: 800px;
	border-top: 1px solid var(--c-hairline);
}

.faq__item {
	border-bottom: 1px solid var(--c-hairline);
}

.faq__q {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 16px 0;
	cursor: pointer;
	list-style: none;
	font-size: 16.5px;
	font-weight: 700;
	color: var(--c-text);
	transition: color 0.15s var(--ease);
}

.faq__q::-webkit-details-marker {
	display: none;
}

.faq__q:hover {
	color: var(--c-accent);
}

.faq__q svg {
	flex: none;
	color: var(--c-muted);
	transition: transform 0.18s var(--ease);
}

.faq__item[open] .faq__q svg {
	transform: rotate(180deg);
}

.faq__a {
	max-width: 68ch;
	padding: 0 0 18px;
	color: var(--c-muted);
	font-size: 15.5px;
	line-height: 1.6;
	text-wrap: pretty;
}

.faq__a p {
	margin: 0 0 10px;
}

.faq__a p:last-child {
	margin-bottom: 0;
}

.faq__out {
	margin: 18px 0 0;
	font-size: 14.5px;
}

/* Blue, not yellow. It is the way out of the page for somebody the page did not
   answer, which is the opposite of the conversion yellow is reserved for, and
   it is the same blue the Discord control in the top bar takes on hover. Two
   links to the same place, the same colour. */
.faq__out a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-weight: 700;
	color: var(--c-blue);
}

.faq__out a:hover,
.faq__out a:focus-visible {
	color: var(--c-blue-soft);
	text-decoration: none;
}

/* ------------------------------------------------------- sticky sign-up bar */

/* Stands in for the hero's sign-up once that button has scrolled away, and
   stands down again over the footer — a call to action floating over the
   responsible-gambling links is the wrong sentence in the wrong place.
   JavaScript toggles .is-on; see assets/js/main.js for what it watches.

   Closed state is visibility:hidden and not opacity alone, so the button is out
   of the tab order and out of the accessibility tree until it is really on the
   screen. Fixed, so nothing on the page moves when it arrives. */
.stickycta {
	position: fixed;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 45;
	visibility: hidden;
	opacity: 0;
	transform: translateY(100%);
	background: rgba(var(--base-rgb), 0.92);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
	border-top: 1px solid var(--c-hairline);
	box-shadow: 0 -18px 44px rgba(0, 0, 0, 0.55);
	transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s var(--ease);
}

.stickycta.is-on {
	visibility: visible;
	opacity: 1;
	transform: none;
}

.stickycta__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 14px;
	min-height: 56px;
	width: 100%;
	max-width: 1320px;
	margin-inline: auto;
	/* The viewport meta is viewport-fit=cover, so on a phone with a home
	   indicator the bar would otherwise sit under it. */
	padding: 8px clamp(1rem, 3vw, 36px) calc(8px + env(safe-area-inset-bottom, 0px));
}

.stickycta__line {
	margin: 0;
	font-size: 14px;
	line-height: 1.3;
	color: var(--c-sub);
}

/* Nothing at all. The figure renders exactly like the words either side of it.

   This took two passes to get right. It was accent yellow, sitting a centimetre
   from a solid yellow button doing the same job better, so the yellow came off
   — and it went to white at weight 800, which against this line's grey is still
   a highlight. Quieter is not the same as unhighlighted.

   Nothing in this bar should be competing with the button. The line is context
   for it, so the line is one colour at one weight, and the <strong> survives for
   what it means rather than for how it looks. Tabular figures stay: the pool is
   a number, and it should not shift the words after it if it ever changes. */
.stickycta__line strong {
	color: inherit;
	font-weight: inherit;
	font-variant-numeric: tabular-nums;
}

/* Smaller than the hero's. It is the same action, but it is riding along
   beside what somebody is reading rather than being the thing they are
   looking at. */
.stickycta__btn {
	flex: none;
	padding: 12px 20px;
	font-size: 14.5px;
}

/* --------------------------------------------------------------- games hub */

.games__grid {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1.25rem;
}

/* Three across so six games fill two even rows. An auto-fill grid left a lone
   card under four, with the whole right side of the second row empty. */
@media (max-width: 900px) {
	.games__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 560px) {
	.games__grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

.games__card {
	display: flex;
	flex-direction: column;
	height: 100%;
	padding: 1.5rem;
	color: var(--c-text);
	background: var(--g-surface);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius);
	box-shadow: var(--lift-card);
	transition: border-color 0.18s var(--ease);
}

/* Border only. A card sitting on a hard block shadow cannot also lift on
   hover — the shadow says where the surface is, and moving it contradicts
   that mid-gesture. */
/* The whole card is the link, so the card is what reacts. The default anchor
   underline was striking through the title and the Play label together, which
   reads as damage rather than as a hover. Same fix as .win__inner and
   .board__card. */
.games__card,
.games__card:hover,
.games__card:focus-visible {
	text-decoration: none;
}

.games__card:hover,
.games__card:focus-visible {
	border-color: rgba(var(--accent-rgb), 0.5);
	background: linear-gradient(180deg, #1B2028, #101319);
}

/* A game an admin has switched off. Still on the page so nobody wonders where it
   went, but greyed, not a link, and not something that reacts to the pointer. */
.games__card.is-off {
	opacity: 0.45;
	filter: grayscale(1);
	cursor: not-allowed;
}

.games__card.is-off:hover,
.games__card.is-off:focus-visible {
	border-color: var(--c-border-soft);
	background: var(--g-surface);
}

.games__card.is-off .games__go {
	color: var(--c-muted);
}

.game__off {
	align-items: flex-start;
}

.game__off-title {
	margin: 0;
	font-size: 1.15rem;
	font-weight: 800;
}

.games__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 60px;
	height: 60px;
	margin-bottom: 1.1rem;
	color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.08);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-sm);
}

.games__title {
	margin-bottom: 0.4rem;
	font-size: 1.4rem;
	font-weight: 800;
}

.games__blurb {
	margin-bottom: 1.4rem;
	color: var(--c-muted);
	font-size: 0.92rem;
	line-height: 1.45;
}


/* margin-top:auto keeps every "Play" on the same line whatever the blurb does. */
.games__go {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	margin-top: auto;
	color: var(--c-accent);
	font-size: 0.9rem;
	font-weight: 700;
}

.games__go svg {
	transform: rotate(-90deg);
}

/* ------------------------------------------------------ plinko and mines */


/* The board is the game, so it takes the wide column and the controls the
   narrow one. Above the breakpoint only: below it the shared rule stacks them. */
@media (min-width: 901px) {
	.plinko .game__layout,
	.mines .game__layout {
		grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
	}
}

.plinko__board {
	display: block;
	width: 100%;
	height: auto;
}

.plinko__peg {
	fill: var(--c-sub);
	opacity: 0.55;
}

/* A slot is dimmer when it pays under the stake and takes the accent as it pays
   more; the opacity is set per slot from the table, so the board reads without
   a legend. */
.plinko__slot-box {
	fill: var(--c-faint);
	stroke: var(--c-border-soft);
	stroke-width: 1;
}

.plinko__slot-box.is-pay {
	fill: var(--c-accent);
}

.plinko__slot-label {
	fill: var(--c-text);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	pointer-events: none;
}

.plinko__slot.is-hit .plinko__slot-box {
	stroke: var(--c-accent-warm);
	stroke-width: 2.5;
	fill-opacity: 1 !important;
}

.plinko__slot.is-hit.is-profit .plinko__slot-box {
	stroke: var(--c-win);
}

.plinko__ball {
	fill: var(--c-accent-warm);
	stroke: var(--c-accent);
	stroke-width: 2;
}

/* The last few drops, newest on the left. They are meant to be small: a new one
   pushes the rest right, and whatever no longer fits is clipped at the end. */
.plinko__history {
	display: flex;
	flex-wrap: nowrap;
	gap: 0.35rem;
	margin: 0.6rem 0 0;
	padding: 0;
	min-height: 1.5rem;
	list-style: none;
	overflow: hidden;
}

.plinko__chip {
	flex: 0 0 auto;
	padding: 0.15rem 0.5rem;
	border-radius: 999px;
	border: 1px solid var(--c-border-soft);
	background: var(--c-well);
	font-size: 0.75rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	line-height: 1.3;
}

.plinko__chip.is-win {
	color: var(--c-win);
	border-color: rgba(var(--win-rgb), 0.6);
}

.plinko__chip.is-loss {
	color: var(--c-danger);
	border-color: rgba(255, 77, 94, 0.55);
}

.plinko__risk,
.keno__risk {
	justify-content: center;
}

/* Mines: five by five, square tiles that stay square at any width. */
.mines__grid {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 0.5rem;
	max-width: 26rem;
	margin: 0 auto;
}

.mines__tile {
	aspect-ratio: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	background: var(--c-raised);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: var(--radius-sm);
	box-shadow: var(--lift-btn);
	color: var(--c-text);
	font: inherit;
	font-size: clamp(1.1rem, 4vw, 1.6rem);
	font-weight: 800;
	cursor: pointer;
	transition: border-color 0.15s var(--ease), background 0.15s var(--ease), transform 0.15s var(--ease);
}

.mines__tile:hover,
.mines__tile:focus-visible {
	border-color: rgba(var(--accent-rgb), 0.5);
}

.mines__tile.is-picked {
	border-color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.12);
}

.mines__tile.is-safe {
	background: rgba(var(--win-rgb), 0.16);
	border-color: var(--c-win);
	color: var(--c-win);
}

.mines__tile:disabled {
	cursor: default;
	opacity: 0.7;
}

.mines__tile.is-pending {
	opacity: 0.6;
}

.mines__tile.is-mine {
	background: rgba(255, 77, 94, 0.16);
	border-color: var(--c-danger);
	color: var(--c-danger);
}

.mines__tile.is-blast {
	transform: scale(1.06);
}

/* A mine the player did not open: shown, but recessed so the one they hit is
   the one that reads. */
.mines__tile.is-spent {
	opacity: 0.55;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.mines__tile {
		transition: none;
	}
}

/* Keno: forty numbers, eight across. A pick is outlined, a drawn number is
   filled, and one that was both is a hit and takes the win colour. */

.keno__grid {
	display: grid;
	grid-template-columns: repeat(8, minmax(0, 1fr));
	gap: 0.4rem;
	max-width: 34rem;
	margin: 0 auto;
}

.keno__tile {
	aspect-ratio: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	background: var(--c-raised);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: var(--radius-sm);
	color: var(--c-text);
	font: inherit;
	font-size: clamp(0.8rem, 2.4vw, 1.05rem);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	cursor: pointer;
	transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}

.keno__tile:hover,
.keno__tile:focus-visible {
	border-color: rgba(var(--accent-rgb), 0.5);
}

.keno__tile.is-picked {
	border-color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.12);
}

.keno__tile.is-drawn {
	background: var(--c-surface-deep);
	color: var(--c-sub);
	border-color: var(--c-sub);
}

.keno__tile.is-hit {
	background: rgba(var(--win-rgb), 0.2);
	border-color: var(--c-win);
	color: var(--c-win);
}

.keno__tile:disabled {
	cursor: default;
}

.keno__pays {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.4rem;
	margin: 0.9rem 0 0;
	padding: 0;
	list-style: none;
}

.keno__pay {
	min-width: 3.6rem;
	padding: 0.35rem 0.5rem;
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	text-align: center;
	font-size: 0.78rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.keno__pay small {
	display: block;
	color: var(--c-muted);
	font-size: 0.62rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.keno__pay.is-hit {
	border-color: var(--c-win);
	color: var(--c-win);
}

.keno__pay.is-dead {
	opacity: 0.45;
}

@media (min-width: 901px) {
	.keno .game__layout {
		grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
	}
}


/* --------------------------------------------------------------- big wins */

/* Ambient, not a feature. Everything here is deliberately a size down from the
   sections around it, and deliberately grey: accent green is the site's
   highlight colour and spending it on a ticker that runs continuously would
   make the loudest thing on the page the one nobody needs to act on. Colour
   arrives on hover, when somebody has actually looked. */

/* Full bleed. The ticker runs the whole width of the content column and off
   both edges — boxed inside the measure it reads as a widget on the page, and
   the point of it is motion passing through. Its heading still lines up with
   every other section, so only the moving strip breaks out. */
.wins {
	margin-top: 2.6rem;
	padding: 0 0 46px;
}

/* On the front page, under the leaderboard band, as the proof of what the band
   shows.

   Tight above and loose below. The band already carries its own bottom margin,
   so the strip only needs a small step of its own to sit as a follow-on to it;
   the how-to-win section under it is a different subject and needs the air. */
.wins--compact {
	margin-top: 0.6rem;
	padding-bottom: clamp(48px, 6.5cqi, 84px);
}

/* One label, left, on the same line every other section label starts on. It
   held a pair for a while — "Big Wins" here and "See all big wins" hard right —
   and both went to the same page. */
.wins__head {
	display: flex;
	align-items: baseline;
	width: 100%;
	max-width: 1320px;
	margin-inline: auto;
	padding-inline: clamp(1.25rem, 3vw, 36px);
}

.wins__title {
	margin: 0 0 0.7rem;
	font-size: 10.5px;
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	font-family: var(--font-mono);
}

/* Quiet, not accent. The strip is ambient and the way out of it should be too:
   this is for somebody who has already stopped to look, and a yellow link here
   would be asking them to. */
.wins__title a {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	color: var(--c-dim);
	transition: color 0.15s var(--ease);
}

.wins__title a:hover,
.wins__title a:focus-visible {
	color: var(--c-accent);
	text-decoration: none;
}

.wins__title svg {
	transform: rotate(-90deg);
}

/* The mask fades both ends so cards enter and leave rather than being clipped
   mid-word against a hard edge. */
.wins__ticker {
	display: flex;
	gap: 0.6rem;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
	padding-inline: clamp(1.25rem, 3vw, 36px);
}

.wins__track {
	display: flex;
	flex-shrink: 0;
	gap: 0.6rem;
	margin: 0;
	padding: 0;
	list-style: none;
	animation: wins-scroll 54s linear infinite;
}

/* Both copies pause together, so hovering does not tear the seam. */
.wins__ticker:hover .wins__track {
	animation-play-state: paused;
}

/*
 * Keyboard focus only, and this is a separate rule for two reasons.
 *
 * It was :focus-within, which meant clicking a card left the ticker stopped
 * long after the pointer had gone: the click opens the clip in a new tab and
 * leaves the link focused behind it, and focus does not go away because you
 * looked elsewhere. It only cleared when something else on the page was
 * clicked, which is not a thing anybody thinks to do.
 *
 * :focus-visible is the distinction that was wanted all along. A mouse click
 * does not raise it, so the ticker runs again the moment the pointer leaves;
 * tabbing does, so a keyboard user still gets the ticker held still rather than
 * having the card they are on slide out from under them.
 *
 * Separate from the :hover rule above because a selector list is dropped whole
 * when any part of it fails to parse. Sharing one rule would cost the hover
 * pause too on anything without :has().
 */
.wins__ticker:has(:focus-visible) .wins__track {
	animation-play-state: paused;
}

/* Half the distance, because the two identical tracks sit side by side: one
   full track's width is exactly 50% of the pair, plus the gap between them. */
@keyframes wins-scroll {
	from { transform: translateX(0); }
	to { transform: translateX(calc(-100% - 0.6rem)); }
}

.win {
	flex-shrink: 0;
	/* Wide enough for "Pragmatic Play · Sugar Rush Super Scatter" on the third
	   line. Longer titles still ellipsis, which is the right thing to lose. */
	width: 272px;
}

.win__inner {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	height: 100%;
	padding: 0.55rem 0.7rem;
	color: var(--c-muted);
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	transition: border-color 0.18s var(--ease);
}

/* The whole card is the link, so the card is what reacts — the default
   underline was striking through all three lines at once, which reads as
   damage rather than as a hover. */
.win__inner,
.win__inner:hover,
.win__inner:focus-visible {
	text-decoration: none;
}

/* Only the ones that go somewhere react to a pointer. */
a.win__inner:hover,
a.win__inner:focus-visible {
	border-color: rgba(var(--accent-rgb), 0.4);
	background: rgba(255, 255, 255, 0.06);
}

/* The ISO code the win was actually made in. Small and quiet on purpose: it is
   a qualifier on the figure, not part of it, and members win in half a dozen
   currencies we do not convert between. */
/* Two sizes carry every supporting line on a win card, and which one you get
   is decided by the face rather than by the line's importance: 11px for the
   mono, 12.5px for the sans. This used to be six sizes between 10 and 12.5,
   which is a range too narrow to read as hierarchy and wide enough to read as
   carelessness — nobody looking at a card could tell you the stake was meant
   to sit half a step under the payout, only that the card looked untidy.

   The split by face is optical, not arbitrary: the mono runs wider and taller
   in the eye at the same nominal size, so matching the numbers would make the
   mono lines look the larger ones. The multiplier is the only thing that
   breaks the pattern, and it breaks it by a factor of two. */
.win__cur,
.board__cur {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.08em;
	color: var(--c-faint);
}

.board__cur {
	margin-left: 0.15rem;
}

/* Payout and stake, on one line and low in the card. This was two lines at the
   top of it with the payout set 17px in accent yellow, and it was the thing the
   strip was being read wrong by: see big-wins.php for why an ARS figure at that
   size is worse than no figure. It keeps a rung above the dimmest text on the
   card because it is content somebody may actually want to read, not a label. */
/* Directly under the game, not pushed to the foot of the card.

   It was margin-top: auto, which on a row of equal-height cards parked the
   money line on the bottom edge of the tallest one and left every shorter card
   with a hole between its game name and its own money. Where a card has slack
   now, the slack collects at the bottom where there is nothing to separate. */
/* No margin of its own. The card is a flex column with a 0.2rem gap and this
   row was adding 0.3rem on top, so the step between the game and the payout
   was two and a half times every other step and the card read as two blocks
   that had drifted apart. One gap, set in one place. */
.win__money {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0 0.35rem;
}

.win__bet {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.04em;
	color: var(--c-faint);
}

.win__who {
	display: flex;
	align-items: center;
	gap: 0.45rem;
	min-width: 0;
}

.win__name {
	overflow: hidden;
	color: var(--c-muted);
	font-size: 12.5px;
	font-weight: 500;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.win__game,
.win__provider {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Same size, weight and colour as the member name it sits under. It was bold
   while everything around it was not, which made the studio's game the loudest
   line on a card whose subject is the person and the figure. It reads as one
   line of context now rather than as a heading. */
.win__game {
	font-size: 12.5px;
	font-weight: 500;
	color: var(--c-muted);
}

.win__provider {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.06em;
	color: var(--c-dim);
}

/* The figure the card is built around, set in the mono like every other value
   the site computed rather than wrote.

   It has been yellow, then white, and is now the same grey as the member name
   and the payout it sits with. Each step was the same argument carried one
   further: size already carries the hierarchy completely. At 23px against a
   12.5px game name there is nothing left for a colour to say, and eight
   figures scrolling in a brighter tone than everything around them read as a
   row of alerts rather than as a record of what people won. The strip is now
   one tone throughout, led by scale alone.

   It is not a chip any more either. The blue pill this replaces was the
   clearest case of blue meaning nothing on the page: the same colour as the
   Discord control, the Kick pill and the earn cards' icon tiles, on a number
   that has nothing to do with any of them. */
.win__mult {
	font-family: var(--font-mono);
	font-size: 26px;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: var(--c-muted);
	font-variant-numeric: tabular-nums;
}

/* Still a chip on the win board, where it sits inline beside the payout in a
   table-like card rather than leading one. Neutral, though: blue is spent on
   Kick and Discord now, and this is neither. */
.board__mult {
	flex: none;
	margin-left: 0.4rem;
	padding: 2px 7px;
	border-radius: 6px;
	background: rgba(var(--text-rgb), 0.08);
	color: var(--c-text);
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.02em;
}

/* Game over provider, on their own lines. No labels: a game name and a studio
   name do not need introducing, and the labels were reading louder than the
   names beside them. Weight carries the difference instead. */
.board__facts {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	margin-top: 0.55rem;
}

.board__game {
	font-size: 13.5px;
	font-weight: 700;
	color: var(--c-text);
}

.board__provider {
	font-family: var(--font-mono);
	font-size: 10.5px;
	letter-spacing: 0.06em;
	color: var(--c-dim);
}

.board__stake {
	margin: 0.25rem 0 0;
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--c-dim);
}

/* A payout, not the headline. It read at 17px in accent yellow for a while and
   it was the loudest thing in the strip, which meant the strip was being led by
   the one figure on it that cannot be compared to the figure beside it. It sits
   on the same rung as the stake beside it now, and shares its weight too: bold
   was the last thing making it argue with the multiplier above it. */
.win__amount {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 500;
	line-height: 1.3;
	color: var(--c-muted);
}

/* A quarter shorter, and it is the studio line that pays for most of it. On the
   homepage this strip is evidence that people win here; "Nolimit City" is the
   one line on the card carrying none of that, and it is also the line that set
   the card's width. The full card keeps it on /big-wins, where somebody has
   arrived to read rather than to be passed by. */
.wins--compact .win {
	width: 236px;
}

.wins--compact .win__inner {
	gap: 0.15rem;
	padding: 0.45rem 0.65rem;
}

.wins--compact .win__mult {
	font-size: 23px;
}

.win__meta {
	overflow: hidden;
	color: var(--c-muted);
	font-size: 12.5px;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-family: var(--font-mono);
}

/* ------------------------------------------------------------- win board */

.stat__cur {
	font-family: var(--font-mono);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.08em;
	color: var(--c-dim);
}

.board__stats {
	display: flex;
	gap: 1rem;
	margin-bottom: 1.6rem;
}

.board__stats .stat {
	flex: 1;
	padding: 1.1rem 1.2rem;
	background: var(--g-surface);
	box-shadow: var(--lift-card-sm);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius);
}

.board__stats .stat__value {
	display: block;
	color: var(--c-accent);
	font-size: 1.6rem;
	font-weight: 800;
}

.board__stats .stat__label {
	color: var(--c-muted);
	font-size: 0.8rem;
}

.board__form {
	margin-bottom: 2rem;
	padding: 1.6rem;
	background: var(--g-raised);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-bar);
	box-shadow: var(--lift-bar);
}

.board__form-title {
	margin: 0 0 1.2rem;
	font-size: 1.2rem;
}

.board__fields {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1rem;
}

.field {
	margin: 0;
}

.field--wide {
	grid-column: 1 / -1;
}

.field label {
	display: block;
	margin-bottom: 0.35rem;
	font-size: 0.85rem;
	font-weight: 700;
}

.field__hint {
	color: var(--c-muted);
	font-weight: 400;
}

.field input {
	width: 100%;
	padding: 0.65rem 0.8rem;
	color: var(--c-text);
	font-family: inherit;
	font-size: 0.95rem;
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	box-shadow: var(--well-inset);
}

.field input:focus {
	border-color: var(--c-accent);
	outline: none;
}

.board__submit {
	display: flex;
	gap: 0.9rem;
	align-items: center;
	margin-top: 1.2rem;
}

.board__note,
.board__signin,
.board__empty {
	color: var(--c-muted);
	font-size: 0.88rem;
}

.board__message {
	margin: 1rem 0 0;
	padding: 0.7rem 0.9rem;
	font-size: 0.9rem;
	border-radius: var(--radius-sm);
}

.board__message--ok {
	color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.08);
	border: 1px solid var(--c-border);
}

.board__message--bad {
	color: var(--c-danger);
	background: rgba(255, 77, 94, 0.08);
	border: 1px solid rgba(255, 77, 94, 0.3);
}

.board__grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
	gap: 1rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.board__card {
	display: block;
	padding: 1.1rem 1.2rem;
	color: var(--c-text);
	background: var(--g-surface);
	box-shadow: var(--lift-card-sm);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius);
	transition: border-color 0.18s var(--ease);
}

/* The whole card is the link, so the card is what reacts. Without this the
   default anchor underline strikes through every line inside it at once, which
   reads as damage rather than as a hover. Same fix as .win__inner. */
.board__card,
.board__card:hover,
.board__card:focus-visible {
	text-decoration: none;
}

/* Only a card with a clip behind it is a link, so only it reacts. */
a.board__card:hover,
a.board__card:focus-visible {
	border-color: rgba(var(--accent-rgb), 0.4);
	background: linear-gradient(180deg, #1B2028, #101319);
}

.board__amount {
	margin: 0;
	color: var(--c-muted);
	font-size: 1.4rem;
	font-weight: 800;
	line-height: 1.1;
	transition: color 0.18s var(--ease);
}

.board__card:hover .board__amount {
	color: var(--c-text);
}

.board__meta {
	margin: 0.3rem 0 0;
	color: var(--c-muted);
	font-size: 0.82rem;
}

.board__watch {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	margin-top: 0.7rem;
	color: var(--c-muted);
	font-size: 0.8rem;
	font-weight: 700;
	transition: color 0.18s var(--ease);
}

.board__card:hover .board__watch {
	color: var(--c-text);
}

/* ------------------------------------------------------------ daily reward */

/* The pill only exists while an unanswered offer does. It is the way back into
   the dialog after closing it, so the 10x draw is never lost to a stray Escape. */

.daily-pill {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.4rem 0.7rem;
	color: var(--c-gold);
	font-size: 0.85rem;
	font-weight: 700;
	background: rgba(var(--gold-rgb), 0.1);
	border: 1px solid rgba(var(--gold-rgb), 0.35);
	border-radius: 999px;
	cursor: pointer;
	animation: daily-pulse 2.4s var(--ease) infinite;
}

.daily-pill:hover {
	background: rgba(var(--gold-rgb), 0.18);
}

@keyframes daily-pulse {
	0%, 100% { box-shadow: 0 0 0 0 rgba(var(--gold-rgb), 0.35); }
	50% { box-shadow: 0 0 0 6px rgba(var(--gold-rgb), 0); }
}

.daily {
	width: min(440px, calc(100vw - 2rem));
	padding: 0;
	color: var(--c-text);
	background: var(--g-raised);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-lg);
	box-shadow: var(--lift-bar);
}

.daily::backdrop {
	background: rgba(0, 0, 0, 0.72);
}

.daily__dismiss {
	display: flex;
	justify-content: flex-end;
	padding: 0.6rem 0.6rem 0;
}

.daily__close {
	width: 32px;
	height: 32px;
	color: var(--c-muted);
	font-size: 1.4rem;
	line-height: 1;
	background: none;
	border: 0;
	border-radius: var(--radius-sm);
	cursor: pointer;
}

.daily__close:hover {
	color: var(--c-text);
	background: rgba(255, 255, 255, 0.06);
}

.daily__body {
	padding: 0.4rem 1.8rem 1.8rem;
	text-align: center;
}

.daily__kicker {
	margin: 0;
	color: var(--c-muted);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.daily__amount {
	margin: 0.3rem 0 0.2rem;
	color: var(--c-accent);
	font-size: clamp(2.6rem, 9vw, 3.4rem);
	font-weight: 800;
	line-height: 1;
	text-shadow: var(--text-block-lg);
}

.daily__plus {
	font-size: 0.6em;
	vertical-align: 0.28em;
}

.daily__unit {
	color: var(--c-muted);
	font-size: 0.32em;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-shadow: none;
	text-transform: uppercase;
}

/* A loss keeps the same shape but drops the green, so the two outcomes are not
   distinguishable only by reading the number. */
.daily__body--lost .daily__amount {
	color: var(--c-muted);
	text-shadow: none;
}

.daily__title {
	margin: 0.5rem 0 0.3rem;
	font-size: 1.25rem;
}

.daily__text {
	margin: 0;
	color: var(--c-muted);
	font-size: 0.92rem;
	line-height: 1.6;
}

.daily__milestone {
	margin: 0.9rem 0 0;
	padding: 0.6rem 0.8rem;
	color: var(--c-gold);
	font-size: 0.88rem;
	font-weight: 600;
	background: rgba(var(--gold-rgb), 0.09);
	border: 1px solid rgba(var(--gold-rgb), 0.28);
	border-radius: var(--radius-sm);
}

.daily__offer {
	margin-top: 1.4rem;
	padding-top: 1.3rem;
	border-top: 1px solid var(--c-border-soft);
}

.daily__offer-text {
	margin: 0 0 1rem;
	color: var(--c-muted);
	font-size: 0.88rem;
	line-height: 1.6;
}

.daily__actions {
	display: grid;
	gap: 0.6rem;
}

.daily__actions .btn {
	justify-content: center;
	width: 100%;
}

.btn.is-busy {
	opacity: 0.6;
	pointer-events: none;
}

.daily__error {
	margin: 0.9rem 0 0;
	color: var(--c-danger);
	font-size: 0.85rem;
}

.daily__body[data-daily-view='result'] .btn {
	margin-top: 1.3rem;
}

/* ------------------------------------------------------------------ footer */

/* The whole footer is one monospaced block at one size, left-aligned under the
   content. It used to be centred, with a 17px bold tagline over 12px links over
   11.5px fine print — three weights and three sizes to say three things nobody
   comes to the page for. Set in the mono face it stops performing and just sits
   there, which is the correct amount of attention for a legal strip.

   Set at 12px rather than 11.5. The mono at 10 or 11px is a texture the rest of
   the page uses for labels, and a label can afford to be nearly unreadable
   because nobody needs to read it. This block is the licensing and
   responsible-gambling line, which is the one piece of small print on the site
   that has to be legible to somebody who has gone looking for it. */
.footer {
	padding: 26px clamp(1.25rem, 3vw, 36px) 44px;
	border-top: 1px solid var(--c-hairline);
	font-family: var(--font-mono);
	font-size: 12px;
	line-height: 1.6;
	letter-spacing: 0.04em;
	color: var(--c-dim);
}

/* Across, not down. Stacked they needed the centre line to look deliberate;
   on one row against a left margin they already do, and wrap in order on a
   narrow screen. */
.footer__legal-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 1.4rem;
	margin-bottom: 0.85rem;
}

.footer__legal-links a {
	color: var(--c-faint);
}

.footer__legal-links a:hover,
.footer__legal-links a:focus-visible {
	color: var(--c-text);
}

.footer__fine {
	margin: 0;
}

/* ------------------------------------------------------------- house games */

/* Shared by every house game: the two-column layout, the controls card, the
   result panel and the provably-fair drawer. Only the pieces genuinely unique
   to one game carry that game's name. */

/* The way back to the hub, above the title. Quiet on purpose: it is a
   handrail, and the game under it is the thing to look at. */
.game__back {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	margin: 0 0 0.9rem;
	color: var(--c-muted);
	font-size: 0.85rem;
	font-weight: 700;
	text-decoration: none;
}

.game__back svg {
	transform: rotate(90deg);
}

.game__back:hover,
.game__back:focus-visible {
	color: var(--c-accent);
	text-decoration: none;
}

.game__layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
	gap: 1.25rem;
	align-items: start;
}

.game__gate {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1rem;
}

.game__controls {
	display: grid;
	gap: 1.1rem;
}

.field {
	display: grid;
	gap: 0.4rem;
}

.field--row {
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	gap: 0.5rem;
}

.field__label {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	font-size: 0.78rem;
	font-weight: 700;
	color: var(--c-muted);
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.field__output {
	font-size: 1.15rem;
	font-weight: 800;
	color: var(--c-accent);
	font-variant-numeric: tabular-nums;
}

.field__input {
	width: 100%;
	padding: 0.7rem 0.85rem;
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	box-shadow: var(--well-inset);
	color: var(--c-text);
	font: inherit;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	transition: border-color 0.15s var(--ease);
}

.field__input:focus {
	border-color: var(--c-accent);
}

.field__range {
	width: 100%;
	accent-color: var(--c-accent);
}

/* The chosen option in a toggle. Filled and sitting on its own block edge, the
   way the Roll button does — the old treatment kept a green-tinted text colour
   from the previous palette. */
.btn--ghost.is-active {
	background: var(--g-accent);
	border-color: transparent;
	color: var(--c-on-accent);
	box-shadow: var(--lift-btn);
}

.stats {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 0.5rem;
	margin: 0;
}

/* Recessed, not raised. These show a number the system worked out; the panels
   around them are things you act on. Sinking one and lifting the other is what
   keeps a screen full of boxes readable. */
.stats__item {
	padding: 0.7rem 0.5rem;
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	box-shadow: var(--well-inset);
	text-align: center;
}

.stats dt {
	font-size: 0.64rem;
	color: var(--c-muted);
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.stats dd {
	margin: 0.25rem 0 0;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
}

.game__go {
	padding: 0.95rem;
	font-size: 1.05rem;
}

/* A bet button waiting out the server's rate limit. It still looks like the
   button, but not like one that will do anything. */
.game__go.is-cooling {
	opacity: 0.55;
	cursor: not-allowed;
}

.game__error {
	margin: 0;
	padding: 0.65rem 0.85rem;
	background: rgba(255, 77, 94, 0.12);
	border: 1px solid var(--c-danger);
	border-radius: var(--radius-sm);
	color: var(--c-danger);
	font-size: 0.9rem;
}

.game__side {
	display: grid;
	gap: 1rem;
}

/* The playfield and its result are one thing. The stage is the card the game is
   played in; the readout is a strip along its foot that says what the last round
   was, and the popup sits over it on a win. Nothing about a result lives in a
   card of its own beside the game. */
.game__stage {
	position: relative;
	padding: 0.75rem;
}

.game__readout {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	margin: 1rem 0 0;
	padding: 0.7rem 1rem;
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	box-shadow: var(--well-inset);
	transition: border-color 0.2s var(--ease);
}

.game__readout.is-win {
	border-color: rgba(var(--win-rgb), 0.6);
}

.game__readout.is-loss {
	border-color: rgba(255, 77, 94, 0.55);
}

.game__value {
	margin: 0;
	font-size: 1.5rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	line-height: 1;
}

.game__readout.is-win .game__value {
	color: var(--c-win);
}

.game__readout.is-loss .game__value {
	color: var(--c-danger);
}

.game__outcome {
	margin: 0;
	color: var(--c-muted);
	font-weight: 700;
	text-align: right;
}

/* A win, said once over the playfield and then gone. Wins only: a loss only
   changes the readout, so losing is never louder than winning. */
.game__popup {
	white-space: nowrap;
	position: absolute;
	left: 50%;
	top: 42%;
	z-index: 5;
	padding: 1rem 1.7rem;
	background: rgba(8, 11, 17, 0.93);
	border: 2px solid var(--c-win);
	border-radius: var(--radius);
	box-shadow: 0 0 0 1px rgba(var(--win-rgb), 0.15), 0 14px 40px rgba(var(--win-rgb), 0.22);
	text-align: center;
	opacity: 0;
	pointer-events: none;
	transform: translate(-50%, -50%) scale(0.85);
	transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}

.game__popup.is-shown {
	opacity: 1;
	transform: translate(-50%, -50%) scale(1);
}

.game__popup.is-sticky {
	padding-right: 3rem;
}

.game__popup.is-sticky.is-shown {
	pointer-events: auto;
}

.game__popup-close {
	position: absolute;
	top: 0.35rem;
	right: 0.35rem;
	width: 2rem;
	height: 2rem;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	background: transparent;
	border: 1px solid var(--c-border-soft);
	border-radius: 50%;
	color: var(--c-muted);
	font-size: 1.3rem;
	line-height: 1;
	cursor: pointer;
}

.game__popup-close:hover,
.game__popup-close:focus-visible {
	color: var(--c-text);
	border-color: var(--c-win);
}

.game__popup-title {
	margin: 0;
	white-space: nowrap;
	color: var(--c-win);
	font-size: clamp(1.8rem, 5vw, 2.8rem);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	line-height: 1;
}

.game__popup-detail {
	margin: 0.4rem 0 0;
	color: var(--c-muted);
	font-size: 0.9rem;
	font-weight: 700;
}

.game__popup-detail:empty {
	display: none;
}

.game__sound {
	position: absolute;
	top: 0.6rem;
	right: 0.6rem;
	z-index: 6;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.1rem;
	height: 2.1rem;
	padding: 0;
	color: var(--c-muted);
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: 50%;
	cursor: pointer;
	transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.game__sound:hover,
.game__sound:focus-visible {
	color: var(--c-text);
	border-color: rgba(var(--accent-rgb), 0.5);
}

.game__sound[aria-pressed="true"] {
	color: var(--c-dim);
}

/* ------------------------------------------------------------------- dice */

/* The track is the target. The bar behind the handle is split in two colours
   to show what wins on each side of it, the cube above slides to the roll, and
   the real range input lies over the bar, invisible but for its handle, so
   dragging and the keyboard are the browser's own.

   Every position on the track uses the one formula: the middle of the handle
   sits at `tw/2 + (width - tw) * fraction` along it, which is where the browser
   puts a thumb of that width. Using it for the split, the cube and the ticks is
   what keeps all three on the handle. */
.dice__track {
	--tw: 22px;
	--pad: 0.7rem;
	--f: 0.5;
	--roll: 0.5;
	--l: var(--c-win);
	--r: var(--c-danger);

	position: relative;
	margin: 6.4rem 1.2rem 3.2rem;
}

.dice__track[data-direction="over"] {
	--l: var(--c-danger);
	--r: var(--c-win);
}

.dice__rail {
	position: relative;
	padding: 0.6rem var(--pad);
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: 999px;
	box-shadow: var(--well-inset);
}

.dice__bar {
	--split: calc(var(--tw) / 2 + (100% - var(--tw)) * var(--f));

	height: 0.95rem;
	border-radius: 999px;
	background: linear-gradient(to right, var(--l) 0, var(--l) var(--split), var(--r) var(--split), var(--r) 100%);
}

.dice__range {
	position: absolute;
	left: var(--pad);
	top: 50%;
	width: calc(100% - 2 * var(--pad));
	height: 2.4rem;
	margin: 0;
	background: transparent;
	transform: translateY(-50%);
	cursor: grab;
	-webkit-appearance: none;
	appearance: none;
}

.dice__range:active {
	cursor: grabbing;
}

.dice__range::-webkit-slider-runnable-track {
	height: 2.4rem;
	background: transparent;
}

.dice__range::-moz-range-track {
	height: 2.4rem;
	background: transparent;
}

.dice__range::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: var(--tw);
	height: 2.4rem;
	border: 0;
	border-radius: 0.65rem;
	background:
		linear-gradient(90deg, transparent 6px, #9aa3b2 6px, #9aa3b2 7px, transparent 7px, transparent 10px, #9aa3b2 10px, #9aa3b2 11px, transparent 11px, transparent 14px, #9aa3b2 14px, #9aa3b2 15px, transparent 15px),
		#fff;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.55);
}

.dice__range::-moz-range-thumb {
	width: var(--tw);
	height: 2.4rem;
	border: 0;
	border-radius: 0.65rem;
	background:
		linear-gradient(90deg, transparent 6px, #9aa3b2 6px, #9aa3b2 7px, transparent 7px, transparent 10px, #9aa3b2 10px, #9aa3b2 11px, transparent 11px, transparent 14px, #9aa3b2 14px, #9aa3b2 15px, transparent 15px),
		#fff;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.55);
}

.dice__range:focus-visible {
	outline: none;
}

.dice__range:focus-visible::-webkit-slider-thumb {
	outline: 2px solid var(--c-accent);
	outline-offset: 2px;
}

.dice__range:focus-visible::-moz-range-thumb {
	outline: 2px solid var(--c-accent);
	outline-offset: 2px;
}

.dice__cube {
	position: absolute;
	left: calc(var(--pad) + var(--tw) / 2 + (100% - 2 * var(--pad) - var(--tw)) * var(--roll));
	bottom: calc(100% + 0.4rem);
	display: grid;
	place-items: center;
	width: 4.8rem;
	height: 5.1rem;
	opacity: 0;
	pointer-events: none;
	transform: translateX(-50%) translateY(8px);
	transition: left 0.52s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.2s var(--ease), transform 0.2s var(--ease);
	filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.5));
}

.dice__cube.is-shown {
	opacity: 1;
	transform: translateX(-50%);
}

.dice__cube::before,
.dice__cube::after {
	content: "";
	position: absolute;
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.dice__cube::before {
	inset: 0;
	background: #3a4457;
}

.dice__cube::after {
	inset: 2px;
	background: linear-gradient(160deg, #262e3d, #131923);
}

.dice__cube-face {
	position: relative;
	z-index: 1;
	margin-top: -0.1rem;
	color: var(--c-text);
	font-size: 1.1rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
}

.dice__cube.is-win .dice__cube-face {
	color: var(--c-win);
}

.dice__cube.is-loss .dice__cube-face {
	color: var(--c-danger);
}

.dice__ticks {
	position: relative;
	height: 1.4rem;
	margin: 0.9rem 0 0;
	padding: 0;
	list-style: none;
}

.dice__ticks li {
	position: absolute;
	left: calc(var(--pad) + var(--tw) / 2 + (100% - 2 * var(--pad) - var(--tw)) * var(--f));
	transform: translateX(-50%);
	color: var(--c-text);
	font-size: 0.85rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
}

.dice__ticks li::before {
	content: "";
	position: absolute;
	left: 50%;
	top: -0.6rem;
	width: 2px;
	height: 0.4rem;
	background: var(--c-border);
	transform: translateX(-50%);
}

@media (max-width: 560px) {
	.dice__track {
		margin: 5.8rem 0.4rem 2.8rem;
	}

	.dice__cube {
		width: 4rem;
		height: 4.3rem;
	}

	.dice__cube-face {
		font-size: 0.95rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.dice__cube {
		transition: none;
	}
}

/* ---------------------------------------------------------------- blackjack */

.blackjack {
	--cw: clamp(3.4rem, 11vw, 4.8rem);
}

.blackjack .view__title,
.dice .view__title,
.keno .view__title,
.limbo .view__title,
.mines .view__title,
.plinko .view__title {
	margin-bottom: 1.2rem;
}

@media (min-width: 901px) {
	.blackjack .game__layout {
		grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
	}
}

/* On a phone the whole hand is played from one screen: balance in the top bar,
   the table, and the move buttons, with no explanatory copy pushing them down. */
@media (max-width: 560px) {
	.blackjack .view__title,
	.dice .view__title,
	.keno .view__title,
	.limbo .view__title,
	.mines .view__title,
	.plinko .view__title {
		font-size: 1.7rem;
		margin-bottom: 0.7rem;
	}

	.blackjack .game__layout,
	.blackjack .game__side {
		gap: 0.7rem;
	}

	.blackjack .game__controls {
		gap: 0.7rem;
		padding: 0.8rem;
	}

	.blackjack__moves {
		grid-template-columns: repeat(4, minmax(0, 1fr));
		gap: 0.4rem;
	}

	.blackjack__moves .btn {
		padding: 0.8rem 0.2rem;
		font-size: 0.85rem;
	}

	.blackjack__table {
		gap: 0.8rem;
		min-height: 0;
		padding: 0.4rem 0.2rem 0.2rem;
	}

	.blackjack__label {
		margin-bottom: 0.4rem;
	}

	.blackjack .game__readout {
		margin-top: 0.6rem;
		padding: 0.5rem 0.8rem;
	}
}

.blackjack__moves {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 0.6rem;
}

.blackjack__moves[hidden],
.blackjack__moves [hidden] {
	display: none;
}

.blackjack__moves .btn {
	justify-content: center;
	padding: 0.9rem;
}

.blackjack__table {
	display: grid;
	align-content: space-around;
	gap: 1.8rem;
	min-height: 25rem;
	padding: 2.6rem 0.8rem 1rem;
}

/* The hands have a 2px outline and padding of their own, so the dealer's row
   and both labels are inset to match and every card starts on the same line. */
.blackjack__row > .bj-cards {
	margin-left: calc(0.6rem + 2px);
}

.blackjack__label {
	padding-left: calc(0.6rem + 2px);
	display: flex;
	align-items: baseline;
	gap: 0.6rem;
	margin: 0 0 0.7rem;
	color: var(--c-muted);
	font-size: 0.78rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.blackjack__total {
	color: var(--c-text);
	font-size: 0.95rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	letter-spacing: 0;
	text-transform: none;
}

.bj-cards {
	display: flex;
	min-height: calc(var(--cw) * 1.4);
}

/* A playing card keeps its own colours whatever the theme: a card is paper, and
   the red suits are red. Nothing here is the site's win or loss colour. */
.bj-card {
	position: relative;
	display: inline-flex;
	flex: none;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.15rem;
	width: var(--cw);
	aspect-ratio: 5 / 7;
	background: #f3f0e7;
	border-radius: 0.5rem;
	box-shadow: 0 3px 10px rgba(0, 0, 0, 0.45);
	color: #16191f;
	font-weight: 800;
	line-height: 1;
}

.bj-card + .bj-card {
	margin-left: calc(var(--cw) * -0.3);
}

.bj-card.is-red {
	color: #c8283a;
}

.bj-card__rank {
	font-size: calc(var(--cw) * 0.36);
}

.bj-card__suit {
	font-size: calc(var(--cw) * 0.46);
}

.bj-card.is-back {
	background: repeating-linear-gradient(45deg, #1b2534 0 6px, #223048 6px 12px);
	border: 2px solid rgba(var(--accent-rgb), 0.55);
}

.bj-card.is-new {
	animation: bj-deal 0.38s var(--ease) both;
}

.bj-card.is-flip {
	animation: bj-flip 0.32s var(--ease) both;
}

@keyframes bj-deal {
	from {
		opacity: 0;
		transform: translate(40%, -90%) rotate(8deg) scale(0.9);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes bj-flip {
	from {
		transform: rotateY(90deg);
	}

	to {
		transform: none;
	}
}

.bj-hands {
	display: flex;
	flex-wrap: wrap;
	gap: 1.4rem;
}

.bj-hand {
	padding: 0.5rem 0.6rem 0.6rem;
	border: 2px solid transparent;
	border-radius: var(--radius-sm);
	transition: border-color 0.2s var(--ease);
}

.bj-hand.is-active {
	border-color: rgba(var(--accent-rgb), 0.6);
}

.bj-hand__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.6rem;
	margin: 0.6rem 0 0;
}

.bj-hand__stake {
	color: var(--c-muted);
	font-size: 0.8rem;
	font-weight: 700;
}

.bj-hand__badge {
	padding: 0.15rem 0.6rem;
	border: 1px solid var(--c-border);
	border-radius: 999px;
	color: var(--c-muted);
	font-size: 0.75rem;
	font-weight: 800;
}

.bj-hand__badge.is-win,
.bj-hand__badge.is-blackjack {
	border-color: var(--c-win);
	color: var(--c-win);
}

.bj-hand__badge.is-lose,
.bj-hand__badge.is-bust {
	border-color: var(--c-danger);
	color: var(--c-danger);
}

@media (prefers-reduced-motion: reduce) {
	.bj-card.is-new,
	.bj-card.is-flip {
		animation: none;
	}
}

/* Limbo has no board: the multiplier is the whole playfield, so its readout is
   the stage's centrepiece and not a strip along the foot. */
.limbo__stage {
	display: grid;
	place-items: center;
	min-height: 18rem;
}

.limbo__stage .game__readout {
	flex-direction: column;
	align-items: center;
	gap: 0.8rem;
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
	box-shadow: none;
}

.limbo__stage .game__value {
	font-size: clamp(3.5rem, 11vw, 6.5rem);
}

.limbo__stage .game__outcome {
	font-size: 1.1rem;
	text-align: center;
}

@media (prefers-reduced-motion: reduce) {
	.game__popup {
		transition: none;
	}
}

.fair__summary {
	font-weight: 700;
	cursor: pointer;
}

.fair__note {
	color: var(--c-muted);
	font-size: 0.85rem;
}

.fair__list {
	margin: 0 0 1rem;
	font-size: 0.8rem;
}

.fair__list dt {
	color: var(--c-muted);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 0.68rem;
	margin-top: 0.7rem;
}

.fair__list dd {
	margin: 0.2rem 0 0;
}

.fair__list code,
.fair__revealed {
	display: block;
	overflow-wrap: anywhere;
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 0.72rem;
	color: var(--c-text);
}

/* The revealed server seed: something the system produced for you to check,
   so it sinks like the other read-only values rather than sitting proud. */
.fair__revealed {
	margin-top: 0.8rem;
	padding: 0.6rem;
	background: var(--c-well);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	box-shadow: var(--well-inset);
	color: var(--c-accent);
}

/* -------------------------------------------------------------------- shop */

.shop__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	margin-bottom: 1.25rem;
}

.shop__count {
	margin: 0;
	color: var(--c-muted);
	font-size: 0.85rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.shop__sort {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

.shop__sort .btn {
	padding: 0.45rem 0.85rem;
	font-size: 0.82rem;
}

.shop__grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: 1rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.shop-item {
	display: flex;
	flex-direction: column;
	background: var(--g-surface);
	box-shadow: var(--lift-card-sm);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius);
	overflow: hidden;
	transition: border-color 0.16s var(--ease);
}

.shop-item:hover {
	border-color: rgba(var(--accent-rgb), 0.5);
}

/* Sold-out cards stay legible rather than being dimmed to nothing: members
   still want to read what they missed and what it cost. */
.shop-item.is-sold-out {
	opacity: 0.62;
}

.shop-item.is-sold-out:hover {
	border-color: var(--c-border-soft);
}

.shop-item__media {
	position: relative;
	aspect-ratio: 16 / 9;
	background: rgba(0, 0, 0, 0.45);
}

.shop-item__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.shop-item__img--blank {
	display: grid;
	place-items: center;
	color: rgba(var(--accent-rgb), 0.25);
}

.shop-item__price,
.shop-item__stock {
	position: absolute;
	top: 0.6rem;
	padding: 0.3rem 0.6rem;
	border-radius: 999px;
	font-size: 0.76rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	backdrop-filter: blur(6px);
}

.shop-item__price {
	left: 0.6rem;
	background: rgba(var(--accent-rgb), 0.16);
	border: 1px solid var(--c-border);
	color: var(--c-accent);
}

.shop-item__stock {
	right: 0.6rem;
	background: rgba(0, 0, 0, 0.55);
	border: 1px solid var(--c-border-soft);
	color: var(--c-muted);
}

.shop-item__stock--out {
	color: var(--c-danger);
	border-color: rgba(255, 77, 94, 0.4);
}

.shop-item__body {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	padding: 1rem;
	flex: 1;
}

.shop-item__title {
	margin: 0;
	font-size: 1rem;
	line-height: 1.3;
}

.shop-item__desc {
	margin: 0;
	color: var(--c-muted);
	font-size: 0.87rem;
	line-height: 1.5;
}

.shop-item__limit {
	margin: 0;
	font-size: 0.74rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--c-gold);
}

/* Pin the whole action group to the bottom, so buttons line up across a row of
   cards whose descriptions are different lengths. It has to be the group rather
   than the button alone: logged out the action is a Discord link, logged in it
   may be a text field plus a button, and all of those need to sit on the same
   baseline as the cards beside them. */
.shop-item__actions {
	margin-top: auto;
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	padding-top: 0.2rem;
}

.shop-item__actions > .btn {
	width: 100%;
}

/* The armed state has to be unmistakable — it is the difference between
   browsing and spending. */
.shop-item__buy.is-armed {
	background: var(--c-gold);
	color: var(--c-on-accent);
	box-shadow: 0 0 26px rgba(var(--gold-rgb), 0.45);
}

.shop-item__msg {
	margin: 0;
	font-size: 0.82rem;
	line-height: 1.45;
}

.shop-item__msg.is-ok {
	color: var(--c-accent);
}

.shop-item__msg.is-error {
	color: var(--c-danger);
}

.shop__empty {
	color: var(--c-muted);
}

/* ---------------------------------------------------------- redemptions */

.shop__orders {
	margin-top: 2.5rem;
}

.shop__orders-title {
	margin: 0 0 0.9rem;
	font-size: 1.05rem;
}

.shop__orders-empty {
	margin: 0;
	color: var(--c-muted);
}

.orders {
	margin: 0;
	padding: 0;
	list-style: none;
}

.orders__row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto auto auto;
	align-items: center;
	gap: 0.9rem;
	padding: 0.7rem 0;
	border-bottom: 1px solid var(--c-border-soft);
}

.orders__row:last-child {
	border-bottom: 0;
}

.orders__title {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: 600;
}

.orders__cost {
	color: var(--c-danger);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.orders__status {
	padding: 0.22rem 0.6rem;
	border-radius: 999px;
	border: 1px solid var(--c-border-soft);
	font-size: 0.72rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	white-space: nowrap;
	color: var(--c-muted);
}

.orders__status--pending {
	color: var(--c-gold);
	border-color: rgba(var(--gold-rgb), 0.35);
}

.orders__status--fulfilled {
	color: var(--c-accent);
	border-color: var(--c-border);
}

.orders__when {
	color: var(--c-muted);
	font-size: 0.78rem;
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------ login error */

.loginerror {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	margin: 0 0 1.5rem;
	padding: 0.9rem 1.1rem;
	background: rgba(255, 77, 94, 0.09);
	border: 1px solid rgba(255, 77, 94, 0.35);
	border-radius: var(--radius-sm);
	color: var(--c-text);
}

.loginerror p {
	margin: 0;
	font-weight: 600;
}

.loginerror__retry {
	font-weight: 800;
	color: var(--c-accent);
	white-space: nowrap;
}

/* ----------------------------------------------------------------- profile */

.profile__head {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	gap: 1.25rem;
	margin-bottom: 1.75rem;
}

.profile__avatar {
	width: 84px;
	height: 84px;
	border-radius: 50%;
	border: 2px solid var(--c-border);
	object-fit: cover;
}

.profile__name {
	margin: 0;
	font-size: 1.6rem;
	line-height: 1.15;
}

.profile__since {
	margin: 0.3rem 0 0;
	color: var(--c-muted);
	font-size: 0.85rem;
}

.profile__you {
	margin-left: 0.5rem;
	padding: 0.15rem 0.5rem;
	border-radius: 999px;
	border: 1px solid var(--c-border);
	color: var(--c-accent);
	font-size: 0.7rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.profile__stats {
	display: flex;
	gap: 1.75rem;
	margin: 0;
	text-align: right;
}

.profile__stat dt {
	margin: 0;
	color: var(--c-muted);
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.profile__stat dd {
	margin: 0.15rem 0 0;
	font-size: 1.5rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	color: var(--c-accent);
}

.profile__of {
	display: block;
	font-size: 0.72rem;
	font-weight: 600;
	color: var(--c-muted);
}

.profile__section {
	margin-bottom: 1.75rem;
}

.profile__heading {
	display: flex;
	align-items: baseline;
	gap: 0.6rem;
	margin: 0 0 0.75rem;
	font-size: 1.05rem;
}

/* Says plainly that something is not on show. A member looking at their own
   page should not have to wonder whether their address is public. */
.profile__private {
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--c-muted);
}

.profile__empty {
	margin: 0;
	color: var(--c-muted);
}

.orders__detail {
	padding: 0 0 0.7rem;
	margin-top: -0.4rem;
	color: var(--c-muted);
	font-size: 0.8rem;
	border-bottom: 1px solid var(--c-border-soft);
}

.ledger {
	margin: 0;
	padding: 0;
	list-style: none;
}

.ledger__row {
	display: grid;
	grid-template-columns: 6.5rem minmax(0, 1fr) auto auto;
	align-items: center;
	gap: 0.9rem;
	padding: 0.6rem 0;
	border-bottom: 1px solid var(--c-border-soft);
	font-size: 0.88rem;
}

.ledger__row:last-child {
	border-bottom: 0;
}

.ledger__when {
	color: var(--c-muted);
	font-size: 0.78rem;
	font-variant-numeric: tabular-nums;
}

.ledger__what {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ledger__delta,
.ledger__after {
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.ledger__after {
	color: var(--c-muted);
	min-width: 5rem;
	text-align: right;
}

/* ------------------------------------------------------------------ pager */

/* Sits inside the card the list is in, under the last row, so it reads as part
   of the table rather than as a control floating beneath it. */
.pager {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin-top: 0.9rem;
	padding-top: 0.9rem;
	border-top: 1px solid var(--c-border-soft);
}

.pager__link {
	display: inline-flex;
	align-items: center;
	padding: 8px 14px;
	border: 1px solid rgba(255, 255, 255, 0.12);
	border-radius: var(--radius);
	background: var(--g-chip);
	box-shadow: var(--lift-chip);
	font-size: 12.5px;
	font-weight: 650;
	color: var(--c-text);
	white-space: nowrap;
	transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}

.pager__link:hover {
	border-color: rgba(var(--accent-rgb), 0.45);
	color: #fff;
	text-decoration: none;
}

/* The end of the run keeps the button's footprint rather than removing it, so
   the status text does not jump sideways between the first page and the rest. */
.pager__link.is-off {
	opacity: 0.32;
	box-shadow: none;
	pointer-events: none;
}

.pager__status {
	margin: 0;
	font-size: 12px;
	color: var(--c-faint);
	font-variant-numeric: tabular-nums;
	text-align: center;
}

@media (max-width: 560px) {
	.pager {
		flex-wrap: wrap;
		justify-content: center;
	}

	/* The count is the least useful of the three on a narrow screen, so it goes
	   under the buttons rather than squeezing them. */
	.pager__status {
		order: 3;
		width: 100%;
	}
}

.is-up {
	color: var(--c-accent);
}

.is-down {
	color: var(--c-danger);
}

.shop__yours {
	margin: 2rem 0 0;
	text-align: center;
	font-weight: 600;
}

/* -------------------------------------------------------------- responsive */

@media (max-width: 900px) {
	.game__layout {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 620px) {
	.wins__head {
		flex-direction: column;
		align-items: flex-start;
	}

	.board__fields {
		grid-template-columns: 1fr;
	}

	.board__submit {
		align-items: flex-start;
		flex-direction: column;
	}
}

@media (max-width: 700px) {
	.profile__head {
		grid-template-columns: auto minmax(0, 1fr);
		text-align: left;
	}

	.profile__stats {
		grid-column: 1 / -1;
		justify-content: flex-start;
		text-align: left;
	}

	/* Four columns of ledger cannot hold; the description takes its own row. */
	.ledger__row {
		grid-template-columns: minmax(0, 1fr) auto;
		row-gap: 0.2rem;
	}

	.ledger__what {
		grid-column: 1 / -1;
		white-space: normal;
	}
}

@media (max-width: 560px) {
	.shop__bar {
		align-items: flex-start;
		flex-direction: column;
	}

	/* Four columns cannot hold at this width: the title takes the first row and
	   the metadata wraps beneath it rather than truncating to nothing. */
	.orders__row {
		grid-template-columns: 1fr auto;
		row-gap: 0.35rem;
	}

	.orders__title {
		grid-column: 1 / -1;
		white-space: normal;
	}

	.orders__when {
		text-align: right;
	}
}

/* Below this width the rail cannot hold its 254px and the three-up grids
   cannot hold a readable card at the same time, so the layout goes narrow in
   one step rather than degrading piece by piece: rail into the drawer, card
   grids to a single column, headline down to 64px. */

/* ----------------------------------------------------- container breakpoints */

/*
 * Everything that depends on how much room the content column actually has,
 * asked of the column rather than of the window. cqi is 1% of that column, so
 * the headline and the card both scale against the space they are really in —
 * which is 286px narrower the moment the rail appears.
 *
 * Container queries are Chrome 105 / Safari 16 / Firefox 110, all 2022-23. On
 * anything older every rule here is skipped and the page stays in its stacked
 * form, which is a layout rather than a breakage.
 */

/* The sign-up stops being a full-width bar and becomes a button. 230px of
   "Sign up on Razed.com" plus its padding wants about 300px, and the hero
   spends 40px of the column on its own padding down here, so 560 is where a
   button-sized button still leaves the row looking deliberate rather than
   stranded. Asked of the column and not the window: the rail takes 286px of
   the answer above 1100. */
@container shell (min-width: 560px) {
	.hero__actions {
		align-items: flex-start;
	}

	/* Centred on the button rather than on the column, which is the whole point
	   of the nesting. */
	.hero__signup {
		align-items: center;
	}

	.hero__legal {
		text-align: center;
	}
}

/* The hero splits, and the live card takes the column that was empty.

   940 is where both halves are still themselves. The headline caps at 64px and
   runs to 15ch, which sets about 480px; the card stops being a card much under
   300. 940 less the hero's own 72px of padding and a 44px gutter leaves 824 to
   split, so the lead keeps 504 and the card takes 320. Below that they stack,
   which is the right answer rather than a fallback: on a phone "is he on right
   now" is worth its own full-width block. */
@container shell (min-width: 940px) {
	.hero {
		display: grid;
		grid-template-columns: minmax(0, 1fr) clamp(300px, 24cqi, 360px);
		gap: clamp(36px, 4cqi, 56px);
		align-items: start;
	}

	.hero__side {
		margin-top: 0;
	}
}

/* The questions move beside their heading, on the same grid as the section
   directly above them.

   Why this section splits at all: the list is capped for reading, because it is
   the only running prose on the page and a line of body copy 1,200px long loses
   the reader on the carriage return. Stacked, that cap made the last section of
   the page stop 450px short of every edge above it, which reads as unfinished
   rather than as a measure. The fix is to put something in the space, not to
   widen the prose.

   Why these exact columns: they are the loop's columns, not a second set chosen
   for the FAQ. This block sits immediately under "How points work", and an
   arbitrary two-column split put the questions 78px to the right of where the
   step beside them started — close enough to read as a misalignment rather than
   as a different layout. Sharing the three-column grid puts the heading over
   step one and the list over steps two and three, and it holds at every width
   because it is literally the same rule.

   The cap comes off here. Two thirds of the measure is 818px at the widest this
   page ever gets, which is 18px past where the cap was set and buys a column
   edge that agrees with the whole page. */
@container shell (min-width: 820px) {
	.faq {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 40px;
		align-items: start;
	}

	.faq__head {
		margin-bottom: 0;
	}

	.faq__list {
		grid-column: 2 / -1;
		max-width: none;
	}

	/* The rule at the top of the list is the list's own top edge, and the title
	   should sit on it rather than float above it. */
	.faq__title {
		padding-top: 4px;
	}
}

/* Two cards across as soon as one is no longer using half the column. Four
   cards make this a 2x2 rather than the old 3-and-a-gap, which is the better
   shape anyway: the four are alternatives, and a grid says that where a row of
   three and a straggler says the fourth was an afterthought. */
@container shell (min-width: 640px) {
	.ways__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* The three steps go side by side and the arrows move out into the gutters. Not
   sooner: at a 768 column, three columns and two 44px gutters leave 211px each,
   which sets "Gamble your points in House Games" three words to a line. 820 is
   where a third of the column clears 230px and the sentences read. */
@container shell (min-width: 820px) {
	.loop__steps {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 40px;
	}
}

/*
 * The headline gets a higher ceiling on wider screens. The slope is the same
 * 12cqi as below, measured against .hero__head and not the page column, so the
 * live card beside it is already allowed for:
 *
 *   7.9em  the run of each line at weight 900, "Play on" with the logo at
 *          0.75em and "Earn with Aitch." alike.
 *   12cqi  an 8.33em line, which clears that with room for the shadows.
 *   92px   the ceiling, reached once the headline has about 770px.
 */
@container shell (min-width: 880px) {
	.hero__title {
		font-size: clamp(2.2rem, 12cqi, 92px);
	}
}

/* The band's header goes horizontal: what it is on the left, how long is left
   in the middle, the way in on the right.

   Three grid columns and not a flex row with space-between, because the clock
   is meant to be centred in the band rather than pushed up against the button.
   Two equal 1fr tracks either side of an auto one is the only arrangement that
   centres the middle item without knowing how wide the other two are.

   The display type comes down here. In a stack the title had the whole column
   and 42px was right; sharing that column three ways it has 270px to 450px, and
   "Razed Leaderboard" at 42px wants 400. The clock loses a few pixels for the
   same reason, and the title is balanced so that where it does take two lines
   it breaks as "Razed / Leaderboard" rather than dropping one word.

   980 is arithmetic, not taste: 375px of header plus a 246px clock plus a 234px
   button plus two 20px gaps plus the section's own 72px of padding is 967, and
   980 clears it. Below that the clock has to wrap to two rows of two, which is
   the one thing in this band that must never happen — it is the element the
   whole section is built around. It stacks instead.

   Low enough to still reach a 1280 laptop. The arithmetic behind the old 980
   was 1280 less the rail's 286, which is 994, and it left out the scrollbar: a
   real 1280 window has 1265 of layout width, so the column measures 979 and the
   bar stacked on exactly the machine the threshold was chosen for. 960 clears it
   with 19px to spare and still needs a genuinely wide column. Measure the
   element, not the viewport, when a rail and a scrollbar sit between them. */
@container shell (min-width: 960px) {
	.ladder__bar {
		display: grid;
		/* The header takes what its longest line needs, the button takes what it
		   needs, and the clock is centred in everything left over. Two equal
		   tracks either side would centre the clock against the band itself,
		   but they would also cap the header at the button's width, which is
		   234px — and the sub-heading needs 400. */
		grid-template-columns: minmax(0, auto) 1fr auto;
		align-items: center;
		gap: clamp(20px, 2.4cqi, 40px);
	}

	/* Only balance, no size of its own. This used to shrink the title to 34px
	   for the row layout, which was the single thing keeping the four section
	   heads from agreeing — and the row has the width for 38 without it. */
	.ladder__title {
		text-wrap: balance;
	}

	/* No cap, and this is the whole reason the line was breaking. 42ch is the
	   right measure for a paragraph that has a column to itself, and here it was
	   holding the sub to 336px when the line wants 400 and the track had 500 to
	   give. It kept "to enter." on a second line at every width.

	   The size ramp is what guarantees the single line rather than hoping for
	   it: 14.5px needs 375px and the narrowest row layout has 394. Still allowed
	   to wrap, because a longer pool figure or a longer code should fold rather
	   than run off the edge. */
	.ladder__sub {
		max-width: none;
		margin-top: 8px;
		font-size: clamp(14.5px, 1.35cqi, 16.5px);
	}

	/* Tighter, to buy the header those pixels back. */
	.clock {
		justify-self: center;
		gap: 10px;
	}

	.clock__unit {
		min-width: 54px;
		padding: 10px 8px 9px;
	}

	.clock__value {
		font-size: 30px;
	}

	.ladder__cta {
		justify-self: end;
	}

	/* Two things in the bar, not three. The front page band gave its sign-up
	   button up to the sticky bar, so the clock takes the end of the row and the
	   middle track goes with the button: with a 1fr still in the middle the clock
	   would sit centred against a track that ends nowhere, which reads as an
	   element that failed to reach its own edge.

	   Selected on what is in the bar rather than on the page, because Top
	   Chatters uses this same element and still has a button in it. Both shapes
	   are live and neither is a special case of the other. */
	.ladder__bar:not(:has(.ladder__cta)) {
		grid-template-columns: minmax(0, auto) 1fr;
	}

	.ladder__bar:not(:has(.ladder__cta)) .clock {
		justify-self: end;
	}
}

/* Four across. 1080 is where a quarter of the column, less the section's own
   72px of padding and three 22px gaps, is still 235px — about the narrowest a
   card holding a 42px tile, a prize label and four lines of body can be before
   the body starts breaking every three words. Below this it is the 2x2. */
@container shell (min-width: 1080px) {
	.ways__grid {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* The rail becomes a drawer. Still a viewport question, because it is about the
   window having room for a 286px column beside the content at all — not about
   what the content column then does with what it is given. */
@media (max-width: 1100px) {
	.shell {
		grid-template-columns: minmax(0, 1fr);
	}

	.rail {
		position: fixed;
		top: 0;
		bottom: 0;
		left: 0;
		z-index: 40;
		width: min(82vw, var(--sidebar-w));
		height: 100%;
		transform: translateX(-100%);
		transition: transform 0.22s var(--ease);
		/* Opaque as an overlay. The desktop rail is allowed a little
		   translucency; as a drawer it would let the page read through it. */
		background: var(--c-rail);
		box-shadow: 0 0 40px rgba(0, 0, 0, 0.7);
	}

	.rail.is-open {
		transform: translateX(0);
	}

	/* Scrim: above content (35), below the drawer (40). */
	body.has-nav-open::before {
		content: '';
		position: fixed;
		inset: 0;
		z-index: 35;
		background: rgba(0, 0, 0, 0.6);
	}

	/* No brand here. The drawer carries the lockup, and the page below already
	   says AITCH twice before the fold: the headline and the sign-up line. */
	.topbar__toggle {
		display: flex;
	}

	.topbar {
		justify-content: flex-start;
	}

	.topbar__right {
		margin-left: auto;
	}
}


@media (max-width: 768px) {
	.chip__name {
		display: none;
	}
}

/* The drawer carries logout on small screens, so the topbar can drop it and
   stay within a 320px viewport without truncating. */
@media (max-width: 480px) {
	.topbar {
		gap: 0.5rem;
		padding: 16px 0.6rem 0;
	}

	.topbar__right {
		gap: 0.5rem;
	}

	.topbar .btn--discord {
		padding: 0.4rem 0.7rem;
		font-size: 0.78rem;
	}

	.balance {
		padding: 0.32rem 0.6rem;
	}

	.balance__label {
		display: none;
	}

	.stats {
		gap: 0.35rem;
	}

	.stats__item {
		padding: 0.5rem 0.25rem;
	}

	.stats dt {
		font-size: 0.6rem;
		letter-spacing: 0.02em;
	}
}

/* The sticky bar sits outside .shell, so it is one of the few things on this
   site that really is a viewport question — it has no content column to ask.
   Bottom on a phone, where the thumb already is; top on a desktop, where a bar
   across the foot of a wide window reads as a cookie notice. The top bar is not
   sticky, so there is nothing up there for it to collide with. */
@media (min-width: 900px) {
	.stickycta {
		top: 0;
		bottom: auto;
		transform: translateY(-100%);
		border-top: 0;
		border-bottom: 1px solid var(--c-hairline);
		box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
	}

	.stickycta__inner {
		padding-bottom: 8px;
	}
}

/* Starts where the content column does, once there is a rail to clear. Run the
   full width of the window and the bar lies across the wordmark, which at 92%
   opacity ghosts through it — and its own text then starts over the rail rather
   than on the same left edge as every section it is scrolling past. Below 1100
   the rail is a drawer and there is nothing to clear. */
@media (min-width: 1101px) {
	.stickycta {
		left: var(--sidebar-w);
	}
}

/* Room under the footer for the bar to sit over. Only where the bar is at the
   bottom, and only on the page that has one: the bar no longer stands down over
   the footer, so the fine print has to clear it instead. That is the better
   trade — a legal strip can afford 56px of padding, and a call to action that
   disappears near the end of the page cannot be explained to whoever is
   reading. */
@media (max-width: 899px) {
	.home .footer {
		padding-bottom: calc(44px + 56px + env(safe-area-inset-bottom, 0px));
	}
}

/* The mobile crop. The hero's prize line and this band are the two things that
   have to survive it, so the table tightens rather than being left to the
   horizontal scroll: on the most important section on the page, a scroll would
   put the prize column off the right edge of every phone. */
@media (max-width: 560px) {
	.ladder__table th,
	.ladder__table td {
		padding: 11px 10px;
	}

	.ladder__table td {
		font-size: 13.5px;
	}

	.ladder__num {
		font-size: 12.5px;
	}

	.ladder__rank {
		font-size: 11.5px;
	}

	/* Four equal shares of the row rather than four 66px tiles that overflow it
	   at 320. Tracks rather than flex-basis, since the clock is a grid. */
	.clock {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}

	.clock__unit {
		min-width: 0;
		padding: 10px 6px 8px;
	}

	.stickycta__line {
		font-size: 12.5px;
	}

	.stickycta__btn {
		padding: 11px 15px;
		font-size: 13.5px;
	}
}

/* Respect a reduced-motion preference: the drawer slide, hover lifts and the
   live dot are decorative and should not fire for users who opted out. */
@media (prefers-reduced-motion: reduce) {
	.daily-pill {
		animation: none;
	}

	/* The ticker stops and becomes a scrollable strip instead. The second copy
	   only exists to make the loop seamless, so it goes with the animation —
	   otherwise every win appears twice. */
	.wins__track {
		animation: none;
	}

	.wins__track[aria-hidden='true'] {
		display: none;
	}

	.wins__ticker {
		overflow-x: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		transition-duration: 0.001ms !important;
	}

	/* An infinite animation squeezed to 0.001ms still churns, so the two
	   background washes are stopped outright rather than sped up. */
	.shell__amb--warm,
	.shell__amb--cool {
		animation: none;
	}

	.btn:hover,
	.way:hover,
	.games__card:hover,
	.socials__link:hover {
		transform: none;
	}
}

/* ==========================================================================
   Footy tipping
   ==========================================================================
   Grouped by the day a game is played, paged a week at a time. Rounds are a
   scheduling artefact — nobody plans their weekend around "Round 24", and a
   round sprawls Thursday to Sunday.

   Finals carry an accent spine and say the stakes in words. Depth and colour
   only: no glows, and no hover lift, in keeping with the rest of the theme.
   ========================================================================== */

.footy {
	max-width: 1120px;
	margin-inline: auto;
}

/* --- compact masthead: the selector and the games are the point --------- */
.footy__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 14px 26px;
	padding: 4px 0 16px;
}

.footy__title {
	display: flex;
	align-items: baseline;
	gap: 12px;
	flex-wrap: wrap;
}

.footy__title h1 {
	font-size: 26px;
	font-weight: 900;
	letter-spacing: -0.02em;
	text-shadow: var(--text-block);
	margin: 0;
}

.footy__season {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.15em;
	text-transform: uppercase;
	color: var(--c-accent);
}

.footy__me {
	display: flex;
	align-items: center;
	gap: 20px;
	margin: 0 0 0 auto;
}

.footy__me > div {
	display: flex;
	align-items: baseline;
	gap: 7px;
}

.footy__me dt {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.11em;
	text-transform: uppercase;
	color: var(--c-faint);
}

.footy__me dd {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 16px;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.footy__me dd.is-footy { color: var(--c-blue-soft); }
.footy__me dd small { font-size: 11px; color: var(--c-dim); font-weight: 400; }

/* --- sync line: a computed value, so it is recessed --------------------- */
.footy__sync {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 16px;
	background: var(--c-well);
	box-shadow: var(--well-inset);
	border-radius: var(--radius);
	padding: 9px 15px;
	margin: 0 0 16px;
	font-size: 12px;
	color: var(--c-faint);
}

.footy__sync b { color: var(--c-muted); font-weight: 600; }

/* The freshness reads as a status, so it is set like one. Uppercasing the whole
   value rather than the words "just now" keeps it steady: a minute later it
   becomes "5 MINS AGO" instead of flipping back to lower case. */
.footy__ago {
	text-transform: uppercase;
	letter-spacing: 0.09em;
	font-weight: 700;
	font-size: 11px;
	color: var(--c-muted);
}
.footy__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--c-accent); flex: none; }
.footy__next { margin-left: auto; font-family: var(--font-mono); color: var(--c-muted); }

/* --- week paginator ---------------------------------------------------- */
.footy__weeks {
	display: flex;
	align-items: stretch;
	gap: 2px;
	margin-bottom: 22px;
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
	border-radius: var(--radius);
	overflow: hidden;
}

.footy__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 58px;
	flex: none;
	font-size: 18px;
	line-height: 1;
	text-decoration: none;
	color: var(--c-nav);
	background: rgba(0, 0, 0, 0.2);
	transition: color 0.12s, background 0.12s;
}

.footy__arrow:hover,
.footy__arrow:focus-visible {
	color: var(--c-text);
	background: rgba(0, 0, 0, 0.35);
	/* The arrows are links, and links underline on hover site-wide. These are
	   controls, not prose, and an underline under a glyph reads as a mistake. */
	text-decoration: none;
}
.footy__arrow.is-off { color: #3a4353; }

.footy__weekface {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 4px;
	padding: 15px 12px;
	background: rgba(0, 0, 0, 0.2);
	text-align: center;
}

.footy__range { font-weight: 800; font-size: 19px; letter-spacing: -0.015em; }

.footy__sub {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--c-accent);
}

.footy__sub.is-tbc { color: var(--c-dim); }

/* --- the bonus, announced rather than revealed -------------------------- */
.footy__offer {
	display: flex;
	align-items: center;
	gap: 14px;
	background: var(--c-well);
	box-shadow: var(--well-inset);
	border-radius: var(--radius);
	padding: 13px 18px;
	margin: 0 0 16px;
	font-size: 13px;
	color: var(--c-faint);
}

.footy__offer b { color: var(--c-text); font-weight: 700; }

.footy__offer-amt {
	font-family: var(--font-mono);
	font-size: 17px;
	font-weight: 700;
	color: var(--c-accent);
	flex: none;
}

/* --- day grouping ------------------------------------------------------ */
.footy__day { margin-bottom: 26px; }

.footy__day > h2 {
	display: flex;
	align-items: baseline;
	gap: 12px;
	font-size: 12px;
	font-weight: 800;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--c-muted);
	padding-bottom: 11px;
	margin: 0 0 14px;
	border-bottom: 1px solid var(--c-hairline);
}

.footy__day > h2 em {
	font-style: normal;
	color: var(--c-dim);
	letter-spacing: 0.06em;
	font-weight: 600;
}

.footy__rel {
	margin-left: auto;
	font-family: var(--font-mono);
	letter-spacing: 0;
	text-transform: none;
	font-size: 12px;
	font-weight: 500;
	color: var(--c-faint);
}

.footy__games { display: flex; flex-direction: column; gap: 12px; }

/* --- one game ---------------------------------------------------------- */
.footy__game {
	position: relative;
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
	border-radius: var(--radius);
	padding: 16px 18px 16px 22px;
	border-left: 3px solid transparent;
}

.footy__game.is-wildcard { border-left-color: rgba(var(--blue-rgb), 0.55); }
.footy__game.is-qualifying { border-left-color: rgba(var(--accent-rgb), 0.55); }
.footy__game.is-elimination,
.footy__game.is-semi { border-left-color: var(--c-danger); }
.footy__game.is-prelim { border-left-color: var(--c-accent); }

.footy__game.is-grand {
	border-left: 0;
	box-shadow: var(--lift-card);
	padding-top: 22px;
}

.footy__game.is-grand::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: var(--radius);
	border: 1px solid rgba(var(--accent-rgb), 0.45);
	pointer-events: none;
}

.footy__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 9px;
	margin-bottom: 14px;
}

.footy__tag {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	padding: 5px 9px;
	border-radius: 6px;
	background: var(--g-chip);
	box-shadow: var(--lift-chip);
}

.footy__tag.is-wildcard { color: var(--c-blue-soft); }
.footy__tag.is-elimination,
.footy__tag.is-semi { color: #ff8a95; }
.footy__tag.is-qualifying { color: var(--c-accent-soft); }
.footy__tag.is-prelim { color: var(--c-accent); }

.footy__tag.is-grand {
	background: var(--g-accent);
	color: var(--c-on-accent);
	box-shadow: var(--lift-sm);
	letter-spacing: 0.16em;
}

.footy__stakes { font-size: 12.5px; color: var(--c-faint); }

.footy__when {
	margin-left: auto;
	display: flex;
	align-items: center;
	gap: 9px;
	font-size: 12px;
	color: var(--c-dim);
}

.footy__venue { font-weight: 600; color: var(--c-faint); }

.footy__lock {
	font-family: var(--font-mono);
	font-size: 11.5px;
	font-weight: 500;
	background: var(--c-well);
	box-shadow: var(--well-inset);
	border-radius: 6px;
	padding: 5px 9px;
	color: var(--c-muted);
	white-space: nowrap;
}

.footy__lock.is-soon { color: var(--c-accent); }
.footy__lock.is-shut { color: var(--c-dim); }
.footy__lock.is-live { color: var(--c-danger); font-weight: 700; }

/* --- picking ------------------------------------------------------------
   Each side is its own form so tipping works with JavaScript switched off.
   display:contents keeps the forms out of the grid's own layout. */
.footy__pick {
	display: grid;
	grid-template-columns: 1fr 46px 1fr;
	align-items: stretch;
	gap: 10px;
}

.footy__form { display: contents; }

.footy__side {
	display: flex;
	align-items: center;
	gap: 12px;
	width: 100%;
	text-align: left;
	font: inherit;
	color: var(--c-text);
	background: rgba(0, 0, 0, 0.22);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius);
	padding: 11px 15px;
	transition: border-color 0.12s, background 0.12s;
}

button.footy__side { cursor: pointer; }
button.footy__side:hover { border-color: rgba(var(--accent-rgb), 0.4); }

.footy__side.is-away {
	flex-direction: row-reverse;
	text-align: right;
}

.footy__crest {
	width: 36px;
	height: 36px;
	object-fit: contain;
	flex: none;
	background: rgba(255, 255, 255, 0.94);
	border-radius: 50%;
	padding: 3px;
	box-shadow: var(--lift-chip);
}

.footy__name {
	font-weight: 700;
	font-size: 15px;
	letter-spacing: -0.01em;
	flex: 1;
}

.footy__score {
	font-family: var(--font-mono);
	font-size: 19px;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--c-muted);
}

.footy__side.is-picked,
.footy__side.is-correct {
	border-color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.09);
}

.footy__side.is-picked .footy__name { color: var(--c-accent); }

.footy__side.is-wrong {
	border-color: rgba(255, 77, 94, 0.5);
	background: rgba(255, 77, 94, 0.07);
}

/* The winner of a settled game. After is-correct so it overrides the yellow a
   right pick would otherwise get: a win is green, as everywhere else on the site. */
.footy__side.is-winner {
	border-color: rgba(61, 220, 132, 0.6);
	background: rgba(61, 220, 132, 0.1);
}

.footy__side.is-winner .footy__name,
.footy__side.is-winner .footy__score { color: var(--c-win); }

.footy__side.is-tbc {
	border-style: dashed;
	border-color: rgba(255, 255, 255, 0.12);
}

.footy__side.is-tbc .footy__name {
	color: var(--c-dim);
	font-weight: 600;
	font-style: italic;
}

.footy__vs {
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--c-dim);
}

.footy__result {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 12px 0 0;
	font-size: 12.5px;
	color: var(--c-faint);
}

.footy__pill {
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	border-radius: 5px;
	padding: 4px 8px;
}

.footy__pill.is-ok { background: rgba(var(--accent-rgb), 0.16); color: var(--c-accent); }
.footy__pill.is-no { background: rgba(255, 77, 94, 0.15); color: #ff8a95; }
.footy__pill.is-wait { background: rgba(255, 255, 255, 0.06); color: var(--c-dim); }
.footy__pill.is-void { background: rgba(255, 255, 255, 0.07); color: var(--c-muted); }

/* --- the draw is not set yet -------------------------------------------- */
.footy__tbc h2 { font-size: 17px; font-weight: 800; margin: 0 0 8px; }
.footy__tbc p { color: var(--c-muted); font-size: 14px; margin: 0 0 16px; max-width: 62ch; }

.footy__tbclist {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.footy__tbclist li {
	display: flex;
	gap: 14px;
	align-items: baseline;
	background: rgba(0, 0, 0, 0.24);
	border: 1px dashed rgba(255, 255, 255, 0.11);
	border-radius: var(--radius);
	padding: 10px 13px;
	font-size: 13px;
}

.footy__tbcwhen { font-family: var(--font-mono); color: var(--c-muted); }
.footy__tbcvenue { color: var(--c-dim); }

/* --- leaderboard -------------------------------------------------------- */
.footy__board { margin-top: 48px; }
.footy__board > h2 { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; margin: 0 0 6px; }
.footy__boardsub {
	color: var(--c-muted);
	font-size: 14px;
	margin: 0 0 18px;
	max-width: 68ch;
	/* Two lines either way at this length, so balance them rather than let the
	   first run full and break mid-clause at "converted into / site points". */
	text-wrap: balance;
}

/* Was .board, and the rename is a bug fix rather than tidying.

   There were two unrelated components on this site called "board": the footy
   standings table, which is this one and wants an opaque panel because rows
   scroll under a sticky header inside it, and the win board page, whose root
   element is <div class="view board">. So /big-wins was picking up a solid
   raised plane across the whole page and burying the angled planes and the grid
   the rest of the site floats on — a background nobody wrote for it, from a
   component it shares nothing with.

   Two BEM families under one block name is the actual defect. This one is the
   table, so it is named for what it is and .board is left to the page that
   already owns every other .board__ class. */
.standings {
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
	border-radius: var(--radius);
	overflow: hidden;
}

/* The board is as tall as it has rows and the page grows to fit. It used to be a
   scroll box, which put a second scrollbar inside the page's own. */
.standings__scroll { overflow: visible; }

.standings table {
	width: 100%;
	border-collapse: collapse;
	font-size: 14px;
	/* No min-width. Forcing one put a horizontal scrollbar under the board on
	   every phone, and squeezed the columns into widths that no longer lined up
	   with their headings. The two detail columns drop instead. */
	table-layout: auto;
}

.standings thead th {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--c-faint);
	text-align: left;
	padding: 14px 16px;
	white-space: nowrap;
	background: var(--c-board-head);
	box-shadow: 0 1px 0 var(--c-hairline);
}

.standings__n { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* .standings thead th sets text-align: left and outweighs .standings__n on its own, so
   the numeric headings sat hard left while their figures sat hard right. Match
   the specificity to put each heading over its own column. */
.standings thead th.standings__n { text-align: right; }
.standings tbody td { padding: 13px 16px; border-top: 1px solid var(--c-hairline); }
.standings tbody tr.is-you { background: rgba(var(--accent-rgb), 0.07); }
.standings tbody tr.is-you td { border-top-color: rgba(var(--accent-rgb), 0.22); }

.standings__rk { font-family: var(--font-mono); font-weight: 700; color: var(--c-dim); width: 56px; }
.standings tbody tr.is-m1 .standings__rk { color: var(--c-gold); }
.standings tbody tr.is-m2 .standings__rk { color: #c9d3e0; }
.standings tbody tr.is-m3 .standings__rk { color: #c88b4a; }

.standings__who { display: flex; align-items: center; gap: 9px; font-weight: 700; }

.standings__you {
	font-size: 9.5px;
	font-weight: 800;
	letter-spacing: 0.1em;
	background: var(--g-accent);
	color: var(--c-on-accent);
	border-radius: 4px;
	padding: 2px 6px;
}

.standings__pts { font-weight: 700; color: var(--c-blue-soft); }

.standings__bar {
	display: block;
	height: 4px;
	border-radius: 2px;
	background: rgba(var(--blue-rgb), 0.3);
	margin-top: 5px;
}

.standings__foot {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 12px 16px;
	border-top: 1px solid var(--c-hairline);
	background: rgba(0, 0, 0, 0.3);
	font-size: 12px;
	color: var(--c-faint);
}

.standings__jump {
	margin-left: auto;
	font: inherit;
	font-size: 12px;
	font-weight: 700;
	cursor: pointer;
	color: var(--c-text);
	background: var(--g-chip);
	box-shadow: var(--lift-chip);
	border: 0;
	border-radius: 7px;
	padding: 7px 13px;
}

.standings__jump:hover { color: var(--c-accent); }

/* Below this the board keeps rank, member and the points that order it.
   Correct and Tipped are detail: worth having on a desktop, not worth a
   sideways scroll on a phone. */
@media (max-width: 620px) {
	.standings__opt { display: none; }

	.standings table { font-size: 13px; }
	.standings thead th,
	.standings tbody td { padding: 11px 10px; }
	.standings__rk { width: 34px; }
}

.footy__empty p { color: var(--c-muted); margin: 0; }

@media (max-width: 640px) {
	.footy__pick { grid-template-columns: 1fr; gap: 8px; }
	.footy__side.is-away { flex-direction: row; text-align: left; }
	.footy__vs { padding: 2px 0; }
	.footy__when { margin-left: 0; width: 100%; }
	.footy__me { margin-left: 0; flex-wrap: wrap; gap: 14px; }
}

/* --- a settled round -----------------------------------------------------
   Says the round is closed before anybody clicks a team and finds out. It is
   recessed rather than raised: it reports a finished state, it is not
   something you act on. */
.footy__settled {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 14px;
	background: var(--c-well);
	box-shadow: var(--well-inset);
	border-radius: var(--radius);
	padding: 11px 16px;
	margin: 0 0 14px;
	font-size: 12.5px;
	color: var(--c-faint);
}

.footy__settled-tag {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--c-muted);
	background: rgba(255, 255, 255, 0.07);
	border-radius: 5px;
	padding: 4px 9px;
	flex: none;
}

.footy__settled-score {
	font-family: var(--font-mono);
	font-size: 14px;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--c-text);
}

.footy__settled-bonus {
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.16);
	border-radius: 5px;
	padding: 4px 8px;
}

.footy__settled.is-perfect .footy__settled-tag {
	color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.16);
}

.footy__settled-note { margin-left: auto; text-align: right; }

/* --- a tip that would not save ------------------------------------------
   Shown against the game it belongs to. A page-level banner would make you
   hunt for which of nine games it meant. */
.footy__error {
	margin: 10px 0 0;
	font-size: 12.5px;
	font-weight: 600;
	color: #ff8a95;
}

@media (max-width: 640px) {
	.footy__settled-note { margin-left: 0; text-align: left; width: 100%; }
}

/* --- the code switcher -------------------------------------------------
   Both sports sit behind one menu item, so this is the only thing telling
   you which one you are looking at. It sits above the week paginator
   because the sport outranks the week: changing it changes the whole board
   underneath, where changing the week does not. */
.footy__codes {
	display: flex;
	gap: 2px;
	margin-bottom: 12px;
	background: var(--c-well);
	box-shadow: var(--well-inset);
	border-radius: var(--radius);
	padding: 4px;
	width: fit-content;
}

.footy__code {
	display: block;
	padding: 8px 20px;
	border-radius: 7px;
	font-size: 12px;
	font-weight: 800;
	letter-spacing: 0.11em;
	text-transform: uppercase;
	color: var(--c-nav);
	text-decoration: none;
	transition: color 0.12s, background 0.12s;
}

.footy__code:hover,
.footy__code:focus-visible {
	color: var(--c-text);
	/* Links underline on hover site-wide. This is a control, not prose. */
	text-decoration: none;
}

.footy__code.is-on {
	color: var(--c-on-accent);
	background: var(--g-accent);
	box-shadow: var(--lift-sm);
}

.footy__code.is-on:hover {
	color: var(--c-on-accent);
}

/* --- footy tipping: the front door -------------------------------------
   Two cards rather than a tab strip. A tab is a thing you notice once you
   already know to look for it; a card the size of the decision is not. */
.footy--hub { max-width: 1120px; margin-inline: auto; }

.hub__head { padding: 8px 0 28px; }

.hub__eyebrow {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--c-accent);
	margin: 0 0 12px;
}

.hub__head h1 {
	font-size: clamp(28px, 4vw, 40px);
	font-weight: 900;
	letter-spacing: -0.02em;
	text-shadow: var(--text-block);
	margin: 0;
}

.hub__lead {
	color: var(--c-muted);
	font-size: 15px;
	margin: 14px 0 0;
	max-width: 68ch;
	text-wrap: pretty;
}

/* --- the two entry cards ----------------------------------------------- */
.hub__codes {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: 28px 16px;
}

/* Each code is a card and its board, laid on two shared rows. The AFL card has a
   next game in it and the NRL card may not, so on their own the two cards come out
   different heights and the boards start at different places. Subgrid puts both
   cards on one row and both boards on the next. */
.hub__col {
	display: grid;
	grid-row: span 2;
	grid-template-rows: subgrid;
	/* A grid item will not shrink below its content by default, and a table is
	   wider than the column on a phone. */
	min-width: 0;
}

/* --- a code's standings, under its card --------------------------------- */
.hub__board > h2 {
	font-size: 20px;
	font-weight: 800;
	letter-spacing: -0.01em;
	margin: 0 0 14px;
}

.hub__board-empty {
	margin: 0;
	padding: 18px 20px;
	border-radius: var(--radius);
	background: rgba(0, 0, 0, 0.2);
	border: 1px solid var(--c-border-soft);
	color: var(--c-faint);
	font-size: 14px;
}

.hub__card {
	display: flex;
	flex-direction: column;
	gap: 16px;
	padding: 22px 24px;
	border-radius: var(--radius);
	background: var(--g-raised);
	box-shadow: var(--lift-card-sm);
	border: 1px solid var(--c-border-soft);
	text-decoration: none;
	color: var(--c-text);
	transition: border-color 0.14s;
}

.hub__card:hover,
.hub__card:focus-visible {
	border-color: rgba(var(--accent-rgb), 0.45);
	/* Links underline site-wide. This is a card, not a sentence. */
	text-decoration: none;
}

.hub__card-top {
	display: flex;
	align-items: baseline;
	gap: 10px;
}

.hub__code {
	font-size: 30px;
	font-weight: 900;
	letter-spacing: -0.02em;
	line-height: 1;
}

.hub__season {
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--c-dim);
}

/* --- the next game, which is the reason to click ------------------------ */
.hub__next {
	display: flex;
	flex-direction: column;
	gap: 4px;
	background: var(--c-well);
	box-shadow: var(--well-inset);
	border-radius: var(--radius);
	padding: 13px 15px;
}

.hub__next-label {
	font-size: 9.5px;
	font-weight: 800;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--c-faint);
}

.hub__next-teams {
	font-weight: 700;
	font-size: 15px;
	letter-spacing: -0.01em;
}

.hub__next-when {
	font-family: var(--font-mono);
	font-size: 11.5px;
	color: var(--c-muted);
}

.hub__next.is-done .hub__next-teams { color: var(--c-dim); font-weight: 600; }

.hub__stats {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 18px;
	font-size: 12px;
	color: var(--c-faint);
}

.hub__stats b {
	font-family: var(--font-mono);
	font-size: 15px;
	font-weight: 700;
	color: var(--c-text);
	margin-right: 4px;
}

.hub__mine b { color: var(--c-blue-soft); }
.hub__mine sup { font-size: 9px; }

.hub__go {
	margin-top: auto;
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 12px;
	font-weight: 800;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--c-accent);
}

.hub__card:hover .hub__go span { transform: translateX(3px); }
.hub__go span { transition: transform 0.14s; }

/* --- how it works ------------------------------------------------------- */
.hub__how { margin: 0 0 36px; }

.hub__how > h2 {
	font-size: 20px;
	font-weight: 800;
	letter-spacing: -0.01em;
	margin: 0 0 18px;
}

.hub__steps {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 14px;
	counter-reset: hubstep;
}

/* Numbered because these genuinely are a sequence: you cannot collect a
   point before you have picked, or place before you have collected. */
.hub__steps li {
	counter-increment: hubstep;
	background: rgba(0, 0, 0, 0.2);
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius);
	padding: 18px 20px;
}

.hub__steps li::before {
	content: counter(hubstep);
	display: block;
	font-family: var(--font-mono);
	font-size: 40px;
	font-weight: 800;
	line-height: 1;
	color: var(--c-accent);
	margin-bottom: 12px;
}

.hub__steps h3 {
	font-size: 15px;
	font-weight: 800;
	margin: 0 0 6px;
}

.hub__steps p {
	font-size: 13px;
	color: var(--c-faint);
	margin: 0;
	line-height: 1.55;
}

/* --- the way back, on a code's own page --------------------------------- */
.footy__code--back {
	color: var(--c-faint);
	letter-spacing: 0.06em;
	text-transform: none;
	font-weight: 600;
}

.footy__code--back:hover { color: var(--c-text); }

@media (prefers-reduced-motion: reduce) {
	.hub__go span { transition: none; }
}

/* ------------------------------------------------------------------ settings

   The account page. Sections are cards because each one is a separate thing you
   act on, and the page reads as a short stack of them rather than a form.
   ------------------------------------------------------------------------- */

.settings {
	max-width: 1120px;
	margin-inline: auto;
}

.settings__head {
	margin-bottom: 1.5rem;
}

.settings__eyebrow {
	margin: 0 0 0.25rem;
	color: var(--c-accent);
	font-size: 0.75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.settings__title {
	margin: 0 0 0.5rem;
	font-size: clamp(1.7rem, 3vw, 2.3rem);
	line-height: 1.15;
}

.settings__lede {
	margin: 0 0 0.75rem;
	max-width: 56ch;
	color: var(--c-muted);
}

.settings__panel {
	margin-bottom: 1.25rem;
}

.settings__heading {
	margin: 0 0 0.9rem;
	font-size: 1.05rem;
}

.settings__row {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin: 0 0 0.6rem;
	flex-wrap: wrap;
}

/* Reads as a status, not a button: nothing here is clickable. */
.settings__state {
	padding: 0.15rem 0.5rem;
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--c-muted);
}

.settings__state.is-on {
	color: var(--c-accent);
	border-color: color-mix(in srgb, var(--c-accent) 45%, transparent);
}

.settings__value {
	font-weight: 700;
}

.settings__note {
	margin: 0;
	color: var(--c-muted);
	font-size: 0.85rem;
}

.settings__steps {
	margin: 0 0 1rem;
	padding-left: 1.2rem;
	color: var(--c-muted);
	line-height: 1.7;
}

/* The welcome step, which is the same panel arriving uninvited. An accent edge
   down one side and nothing else: it is already the first thing on the page and
   the only one with a question in it, so a second treatment on top of that would
   be emphasis competing with itself. */
.settings__panel--welcome {
	border-left: 2px solid var(--c-accent);
}

.settings__form {
	margin: 0 0 0.9rem;
	max-width: 26rem;
}

.settings__actions {
	display: flex;
	align-items: center;
	gap: 1rem;
	margin: 0.9rem 0 0;
	flex-wrap: wrap;
}

/* Blue, the way out. The counting rule again: the accent is on the button that
   saves, so the link that leaves without answering cannot also be yellow or the
   two read as a pair of equal choices. */
.settings__skip {
	color: var(--c-blue);
	font-size: 0.9rem;
	font-weight: 700;
}

.settings__skip:hover,
.settings__skip:focus-visible {
	color: var(--c-blue-soft);
}

.settings__msg {
	margin: 0 0 0.9rem;
	font-size: 0.9rem;
	font-weight: 600;
}

.settings__msg.is-good {
	color: var(--c-accent);
}

.settings__msg.is-bad {
	color: var(--c-danger);
}

.settings__steps code {
	color: var(--c-text);
}

/* The code itself is recessed: it is a value the server computed, not a
   control, and the depth rule on this site says so. */
.kick__code {
	margin-bottom: 1rem;
	padding: 0.9rem 1rem;
	border-radius: var(--radius-sm);
	box-shadow: var(--well-inset);
}

.kick__command {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin: 0 0 0.4rem;
	flex-wrap: wrap;
}

.kick__command code {
	font-size: 1.15rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	color: var(--c-text);
	word-break: break-all;
}

.kick__copy {
	padding: 0.25rem 0.7rem;
	font-size: 0.78rem;
}

.kick__expiry {
	margin: 0;
	color: var(--c-muted);
	font-size: 0.8rem;
	font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- the draw */
/*
 * The reel. No glow anywhere in here on purpose: the counting rule says two
 * haloed elements on the site and they are the promo code and the sign-up
 * button. The winner is marked with an accent border and accent ink instead,
 * which reads as clearly at a glance and does not spend the third halo.
 */

.draw {
	/* The band above already ends in its own margin, 46 to 82px. Adding a
	   second one on top is what left a hand's width of nothing above the
	   heading. */
	margin-top: 0;
}

.draw__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 18px;
}

.draw__won {
	margin: 0;
	font-size: 1.05rem;
	color: var(--c-muted);
}

.draw__range {
	margin: 2px 0 0;
	color: var(--c-muted);
	font-family: var(--font-mono, monospace);
	font-size: 0.8rem;
}

.draw__won strong {
	color: var(--c-accent);
}

/*
 * The window. overflow hidden is what makes it a reel rather than a list, and
 * the mask fades the ends so tiles arrive and leave instead of popping at a
 * hard edge.
 */
/*
 * Hidden until the script has filled it. The reel is decoration and an empty
 * bordered box is worse than no box at all for anybody whose JavaScript did not
 * load: they still get the winners, the prizes and the whole proof.
 */
/* The reel's row, and the only thing that changes height on this page.

   The 1fr/0fr grid row is what makes the collapse animate at all: height cannot
   transition from a content-derived value, and a max-height big enough to be
   safe spends the first half of its transition doing nothing visible. Overflow
   is clipped here as well as on the reel, because a grid item will sit at its
   own padding and border rather than shrink to a zero track. */
.reel__box {
	display: grid;
	/* Both ends written as minmax, and they have to match: a transition between
	   1fr and minmax(0, 0fr) has no common form to interpolate and snaps. The
	   explicit 0 minimum is load-bearing too, because a bare fr track keeps an
	   automatic minimum of the item's own padding and border, which leaves a
	   30px seam where the reel used to be. */
	grid-template-rows: minmax(0, 1fr);
	overflow: hidden;
	transition: grid-template-rows 0.34s var(--ease), opacity 0.24s var(--ease);
}

.reel__box > .reel {
	min-height: 0;
}

/* Away, once the last name is on the board. Put back by the replay button,
   which is why this is a class on the section rather than a display:none: the
   reel has to be able to come back, and to come back the same way it left. */
.draw.is-over .reel__box {
	grid-template-rows: minmax(0, 0fr);
	opacity: 0;
}

/* Nothing to watch, so nothing to animate away. The class still lands, the reel
   is still gone; it is simply gone immediately. */
@media (prefers-reduced-motion: reduce) {
	.reel__box {
		transition: none;
	}
}

.reel {
	display: none;
	position: relative;
	overflow: hidden;
	padding: 14px 0;
	border: 1px solid rgba(var(--text-rgb), 0.08);
	border-radius: 14px;
	background: var(--c-raised-deep);
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}

.reel.is-ready {
	display: block;
}

/* The marker the winning tile stops under. */
.reel::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 50%;
	width: 2px;
	margin-left: -1px;
	background: var(--c-accent);
	z-index: 2;
	pointer-events: none;
}

.reel__strip {
	display: flex;
	gap: 8px;
	/*
	 * The strip is built so the winning tile is last, and it travels until that
	 * tile sits under the marker. Half the window less half a tile is the offset
	 * that centres it, and it is applied as padding rather than folded into the
	 * transform so the JS only ever has one number to work out.
	 */
	padding-left: calc(50% - 44px);
	will-change: transform;
}

.reel__tile {
	flex: 0 0 88px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	gap: 6px;
	min-height: 110px;
	padding: 12px 6px;
	border: 1px solid rgba(var(--text-rgb), 0.07);
	border-radius: 10px;
	background: var(--c-surface);
	text-align: center;
}

.reel__pfp {
	width: 44px;
	height: 44px;
	border-radius: 50%;
	object-fit: cover;
	background: var(--c-surface-deep);
}

.reel__name {
	display: -webkit-box;
	max-width: 100%;
	overflow: hidden;
	overflow-wrap: anywhere;
	color: var(--c-muted);
	font-family: var(--font-mono, monospace);
	font-size: 0.7rem;
	line-height: 1.25;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

/*
 * The winner is only marked once the reel has stopped. Marking it up front
 * would give the answer away before the spin, which is the one thing the
 * animation is for.
 */
.reel.is-done .reel__tile.is-winner {
	border-color: var(--c-accent);
	background: rgba(var(--accent-rgb), 0.1);
}

.reel.is-done .reel__tile.is-winner .reel__name {
	color: var(--c-accent);
}

.draw__replay {
	display: none;
	margin-top: 14px;
}

.draw.has-reel .draw__replay {
	display: block;
}

/* The working, folded away. Open it and every number can be recomputed. */
.draw__proof {
	margin-top: 20px;
	border: 1px solid rgba(var(--text-rgb), 0.08);
	border-radius: 12px;
	background: var(--c-surface-deep);
}

.draw__proof > summary {
	padding: 14px 18px;
	color: var(--c-muted);
	cursor: pointer;
	font-size: 0.9rem;
}

.draw__proof[open] > summary {
	border-bottom: 1px solid rgba(var(--text-rgb), 0.08);
	color: var(--c-text);
}

.draw__proof-body {
	padding: 16px 18px;
}

.draw__proof-body p {
	margin: 0 0 12px;
	color: var(--c-muted);
	font-size: 0.88rem;
	line-height: 1.6;
}

.draw__proof-body ol {
	margin: 0 0 12px;
	padding-left: 20px;
	color: var(--c-muted);
	font-size: 0.88rem;
	line-height: 1.7;
}

.draw__field {
	margin: 0 0 10px;
}

.draw__field dt {
	margin-bottom: 3px;
	color: var(--c-dim);
	font-size: 0.72rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

/*
 * A seed is 64 characters and has to be copyable in full, so it wraps rather
 * than truncating. Anything hidden behind an ellipsis here cannot be checked,
 * which would defeat the point of printing it.
 */
.draw__field dd {
	margin: 0;
	overflow-wrap: anywhere;
	color: var(--c-text);
	font-family: var(--font-mono, monospace);
	font-size: 0.78rem;
}

.draw__checks {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 14px;
	padding: 0;
	list-style: none;
}

.draw__check {
	padding: 5px 10px;
	border: 1px solid rgba(var(--text-rgb), 0.1);
	border-radius: 999px;
	color: var(--c-muted);
	font-size: 0.76rem;
}

.draw__check.is-ok {
	border-color: rgba(var(--accent-rgb), 0.4);
	color: var(--c-accent-soft);
}

.draw__commit {
	margin: 14px 0 0;
	color: var(--c-dim);
	font-size: 0.82rem;
	line-height: 1.6;
}

.draw__commit code {
	overflow-wrap: anywhere;
	color: var(--c-muted);
	font-family: var(--font-mono, monospace);
	font-size: 0.76rem;
}

@media (prefers-reduced-motion: reduce) {
	.reel__strip {
		transition: none !important;
	}
}


/* ------------------------------------------------- the draw, results */

.draw__now:empty {
	/* Empty before and after a draw. Its margin and minimum height were being
	   paid for in both states, and between the date and the first winner that
	   was a 30px strip of nothing. It only takes space while it has something
	   to say. */
	display: none;
}

.draw__now {
	min-height: 1.4em;
	margin: 14px 0 0;
	color: var(--c-accent);
	font-family: var(--font-mono, monospace);
	font-size: 0.82rem;
	letter-spacing: 0.03em;
}

.draw__winners {
	margin: 12px 0 0;
	padding: 0;
	list-style: none;
}

.draw__winner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	padding: 11px 14px;
	border: 1px solid rgba(var(--text-rgb), 0.07);
	border-radius: 10px;
	background: var(--c-surface);
}

.draw__winner + .draw__winner {
	margin-top: 8px;
}

/*
 * Held back only while a spin is actually running, and only by a class the
 * script adds. With JavaScript off the winners are simply there, which is the
 * right way round: they are the answer, and the animation is a way of enjoying
 * it rather than a gate in front of it.
 *
 * Taken out of the layout rather than made transparent. Transparent rows still
 * hold their height, so a draw of four places sat above three rows of nothing
 * for most of its length and the page read as broken. Now the list is exactly
 * as tall as the places drawn so far and grows as each one lands.
 */
.draw.is-teasing .draw__winner:not(.is-shown) {
	display: none;
}

/*
 * An animation rather than a transition, because the row arrives from
 * display: none and a transition has no starting state to leave from. Scoped to
 * is-teasing so a returning visitor, whose rows are marked shown on load, does
 * not watch a list fade in that was never hidden.
 */
.draw.is-teasing .draw__winner.is-shown {
	animation: draw-winner-in 0.4s ease both;
}

@keyframes draw-winner-in {
	from {
		opacity: 0;
		transform: translateY(4px);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.draw.is-teasing .draw__winner.is-shown {
		animation: none;
	}
}

.draw__place {
	flex: none;
	min-width: 34px;
	color: var(--c-accent);
	font-family: var(--font-mono, monospace);
	font-size: 0.8rem;
}

.draw__pfp {
	flex: none;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	object-fit: cover;
	background: var(--c-surface-deep);
}

/* A name with its picture beside it, in a ladder table. Used by Slot Wars. */
.ladder__who {
	display: inline-flex;
	align-items: center;
	gap: 0.7rem;
	min-width: 0;
}

.ladder__initial {
	display: inline-grid;
	flex: none;
	place-items: center;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	background: var(--c-raised);
	color: var(--c-sub);
	font-size: 0.85rem;
	font-weight: 800;
}

.ladder__name {
	overflow-wrap: anywhere;
}

.draw__wname {
	overflow-wrap: anywhere;
	color: var(--c-text);
	font-weight: 600;
}

.draw__ticket {
	color: var(--c-dim);
	font-family: var(--font-mono, monospace);
	font-size: 0.74rem;
}

.draw__prize {
	margin-left: auto;
	color: var(--c-accent);
	font-family: var(--font-mono, monospace);
	font-size: 0.9rem;
}

/* ------------------------------------------------- the draw, history */

.draw__past-title {
	margin: 28px 0 12px;
	color: var(--c-muted);
	font-size: 0.95rem;
}

.draw__past {
	margin: 0;
	padding: 0;
	list-style: none;
}

.draw__past-item + .draw__past-item {
	margin-top: 8px;
}

.draw__past details {
	border: 1px solid rgba(var(--text-rgb), 0.07);
	border-radius: 10px;
	background: var(--c-surface-deep);
}

.draw__past summary {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 12px;
	padding: 11px 14px;
	cursor: pointer;
}

.draw__past-when {
	flex: none;
	min-width: 140px;
	color: var(--c-muted);
	font-family: var(--font-mono, monospace);
	font-size: 0.78rem;
}

.draw__past-who {
	overflow-wrap: anywhere;
	color: var(--c-text);
	font-size: 0.85rem;
}

.draw__past-ok {
	margin-left: auto;
	color: var(--c-dim);
	font-size: 0.74rem;
}

.draw__past-ok.is-ok {
	color: var(--c-accent-soft);
}

@media (max-width: 640px) {
	.draw__prize,
	.draw__past-ok {
		margin-left: 0;
	}
}


/* ==========================================================================
   Stream dashboard (/stream)

   Staff only, and on screen to the whole audience, so it carries the two stream
   games and nothing else. The reel is the raffle's own (.reel, .reel__tile); only
   the frame around it is new.
   ========================================================================== */

.stream__error {
	margin: 0 0 1rem;
	padding: 0.7rem 0.9rem;
	border: 1px solid color-mix(in srgb, var(--c-danger) 50%, transparent);
	border-radius: var(--radius-sm);
	background: color-mix(in srgb, var(--c-danger) 10%, transparent);
	color: var(--c-text);
}

.stream__grid {
	display: grid;
	gap: 1.25rem;
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 900px) {
	.stream__grid {
		/* Slot requests take three quarters and Guess the balance one quarter. Slot
		   requests is the busy one, a queue of names and slot titles, and Guess the
		   balance is a count and a few buttons. */
		grid-template-columns: minmax(0, 3fr) minmax(0, 1fr);
	}
}

/* The two cards stretch to the taller one, so the pair reads as a row whether
   or not either has anything in it. align-content keeps the contents packed at
   the top, or the spare height would be shared out between the rows. */
.stream__panel {
	display: grid;
	gap: 1rem;
	align-content: start;
}

.stream__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 0.75rem;
}

/* On the quarter-width panel the status cannot sit beside the heading, and
   letting it wrap inside its own pill made a three-line chip. It drops below the
   heading instead and stays on one line. */
.stream__head .settings__state {
	white-space: nowrap;
}

.stream__heading {
	margin: 0;
	font-size: 1.15rem;
}

.stream__controls {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}

.stream__controls .btn {
	min-height: 48px;
}

.stream__pick {
	min-height: 1.6em;
	margin: 0;
	color: var(--c-muted);
	font-size: 1.05rem;
}

/* The two pick lines always hold their space, empty or not, and stay on one line
   each. Hiding them when empty made the panel grow and shrink as a pick came and
   went, and a long slot name wrapping to a second line did the same, which showed
   as the whole screen jumping while the reel spun and landed. */
.stream__pick,
.stream__prev {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* The winner's name and the slot they asked for, both bold and yellow. */
.stream__pick strong {
	color: var(--c-accent);
	font-weight: 800;
}

/* The pick before it, all muted: what was picked a moment ago, not what is next. */
.stream__prev {
	min-height: 1.4em;
	margin: -0.5rem 0 0;
	color: var(--c-muted);
	font-size: 0.9rem;
}

.stream__prev strong {
	color: inherit;
	font-weight: 600;
}

.stream__count,
.stream__big {
	margin: 0;
	color: var(--c-muted);
	font-family: var(--font-mono, monospace);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.stream__big {
	color: var(--c-text);
	font-size: 1.6rem;
	letter-spacing: 0;
	text-transform: none;
}

/* The same thin, dark scrollbar as the side menu: no track, and a thumb only a shade
   lighter than the card, instead of the browser's pale slab. */
.stream__queue,
.stream__panel {
	scrollbar-width: thin;
	scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}

.stream__queue {
	display: grid;
	/* Rows keep their own height and stack from the top. In a box taller than its
	   rows a grid would otherwise share the spare height out between them. */
	align-content: start;
	grid-auto-rows: min-content;
	gap: 0.35rem;
	max-height: 26rem;
	margin: 0;
	padding: 0;
	overflow-y: auto;
	list-style: none;
}

.stream__item {
	display: grid;
	grid-template-columns: minmax(0, 11rem) minmax(0, 1fr) auto;
	align-items: center;
	gap: 0.6rem;
	padding: 0.5rem 0.7rem;
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	background: var(--c-surface-deep);
}

.stream__who {
	overflow: hidden;
	font-weight: 700;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.stream__slot {
	overflow: hidden;
	color: var(--c-sub);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.stream__remove {
	width: 1.9rem;
	height: 1.9rem;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--c-muted);
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
}

.stream__remove:hover,
.stream__remove:focus-visible {
	background: rgba(var(--text-rgb), 0.08);
	color: var(--c-text);
}

.stream__final {
	display: grid;
	gap: 0.4rem;
}

.stream__final label {
	color: var(--c-muted);
	font-size: 0.8rem;
}

.stream__final-row {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}

.stream__final input {
	flex: 1 1 9rem;
	min-width: 0;
	min-height: 48px;
	padding: 0 0.9rem;
	border: 1px solid var(--c-border-soft);
	border-radius: var(--radius-sm);
	background: var(--c-surface-deep);
	color: var(--c-text);
	font-family: var(--font-mono, monospace);
	font-size: 1.1rem;
}

.stream__final input:focus-visible {
	border-color: var(--c-accent);
	outline: 2px solid color-mix(in srgb, var(--c-accent) 40%, transparent);
	outline-offset: 1px;
}

/* A result is a win, and wins are green. */
.stream__won {
	margin: 0 0 0.6rem;
	font-size: 1.1rem;
}

.stream__won strong {
	color: var(--c-win);
}

.stream__tie {
	display: block;
	margin-top: 0.15rem;
	color: var(--c-text);
	font-weight: 600;
}

.stream__top {
	margin: 0;
	padding-left: 1.4rem;
	color: var(--c-muted);
	line-height: 1.7;
}

.stream__top strong {
	color: var(--c-text);
}

/* The winner is 1 and reads as the winner: green, as a win is everywhere else. */
.stream__top li.is-winner,
.stream__top li.is-winner strong {
	color: var(--c-win);
}

/* ------------------------------------------------------- one screen, no scroll

   There are about thirty people in the slot request queue at any time, so on a wide
   window the page is exactly as tall as the window and the queue scrolls inside its
   own box. The logo in the top bar is then always on screen, and the legal footer is
   not drawn at all (see footer.php). Below this size the two panels stack and the
   page scrolls as a page does. */
@media (min-width: 900px) and (min-height: 560px) {
	body.stream-page {
		height: 100dvh;
		overflow: hidden;
	}

	.stream-page .shell,
	.stream-page .shell > .col {
		height: 100dvh;
		min-height: 0;
	}

	.stream-page .main {
		display: flex;
		flex-direction: column;
		min-height: 0;
		padding-top: 0.75rem;
		padding-bottom: 0.75rem;
	}

	.stream {
		flex: 1;
		min-height: 0;
	}

	.stream__grid {
		flex: 1;
		grid-template-rows: minmax(0, 1fr);
		min-height: 0;
	}

	.stream__panel {
		display: flex;
		flex-direction: column;
		min-height: 0;
		overflow-y: auto;
	}

	/* The queue takes whatever height is left under the reel and the buttons, and
	   scrolls when thirty names do not fit. */
	.stream__queue {
		flex: 1;
		max-height: none;
		min-height: 6rem;
	}
}

@media (max-width: 560px) {
	.stream__item {
		grid-template-columns: minmax(0, 1fr) auto;
	}

	.stream__slot {
		grid-column: 1 / -1;
		grid-row: 2;
	}
}

/* The marker means "this one", so it is only there while the reel is choosing or
   has chosen. At rest it sat on a random tile and read as an answer. */
.stream .reel::after {
	opacity: 0;
	transition: opacity 0.2s var(--ease);
}

.stream .reel.is-rolling::after,
.stream .reel.is-done::after {
	opacity: 1;
}

/* The number waiting sits beside the Slot requests title, so the queue's length is
   readable without looking down at the list. */
.stream__titles {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.15rem 0.7rem;
	min-width: 0;
}

/* ------------------------------------------------------------ green screen mode

   For keying the roll into the stream. Only the reel changes: its background is
   flat chroma green, and the edge fade, the border and the rounded corners go, so
   the key has nothing but green to remove. The green box is always there, queue
   or no queue, so it can be cropped to in OBS. What is drawn on it is not: the
   tiles and the marker only show while a roll is live (see live() in stream.js),
   and fade in and out. They are faded, not removed, so the box keeps its size. */
.stream.is-chroma .reel {
	display: block;
	min-height: 140px;
	background: #00ff00;
	border-color: transparent;
	border-radius: 0;
	-webkit-mask-image: none;
	mask-image: none;
}

/* The names fade with the roll. The fade is on a wrapper and not on the strip
   itself, because the script sets the strip's own transition inline and that
   would swallow an opacity transition written here. */
.stream.is-chroma .reel__fade {
	transition: opacity 0.45s var(--ease);
}

.stream.is-chroma .reel::after {
	transition: opacity 0.45s var(--ease);
}

.stream.is-chroma .reel:not(.is-live) .reel__fade,
.stream.is-chroma .reel:not(.is-live)::after {
	opacity: 0;
}

/* The winner's tile is translucent in the normal look, which over green turns it
   green too. Here it keeps the same solid dark as every other tile and is marked by
   its yellow edge and name alone. */
.stream.is-chroma .reel.is-done .reel__tile.is-winner {
	background: var(--c-surface);
}

/* The Guess the Balance list: who guessed, and for how much, in the order they came
   in. Two columns instead of the slot queue's three. */
.stream__guesses[hidden] {
	display: none;
}

.stream__guesses .stream__item {
	grid-template-columns: minmax(0, 1fr) auto;
}

.stream__amount {
	color: var(--c-accent);
	font-family: var(--font-mono, monospace);
	font-weight: 700;
}
