/* =====================================================================
   FINN-CLASSIC · LANDING PAGE
   Hero · Quick Access · News · Server Status · Game Highlights
   ===================================================================== */

/* =====================================================================
   HERO — "THE GATE BANNER"
   ---------------------------------------------------------------------
   The source art is bilaterally symmetric with a bright, visually EMPTY
   centre corridor (the sunlit staircase between the two towers). That
   corridor is not a problem to be dimmed — it is a slot. We hang an
   opaque, edge-feathered navy banner in it.

   Consequences:
   · Contrast is won by OPACITY, not by a gradient wrestling a sunburst.
     The worst background pixel that can physically sit behind the H1 is
     #12223E → 15.86:1 against white. That is a guarantee, not a sample.
   · The ice-blue logo lands on navy — its only legal habitat (LAW 2).
   · The ten painted chibis and both towers are never covered: they live
     in the outer 34% of the frame, the banner occupies the middle 66%.
   · It survives image failure. .hero is navy before the image arrives,
     so the H1 and both CTAs are readable even if the art never loads.
   · The grade (blend modes) is isolated inside .hero__media. If blending
     is unsupported, the page degrades to a plain navy banner over bright
     art and every ratio above still holds.
   ===================================================================== */
.hero{
	position:relative;
	isolation:isolate;
	display:flex; align-items:flex-end; justify-content:center;
	/* min-height, NOT height. With a fixed height plus overflow:hidden, a tall
	   stack (3-line H1 + 4-line Thai subtitle) overflows upward on a short
	   viewport and silently guillotines the logo. Letting the hero grow keeps
	   the crest on screen at every aspect ratio; the art still fills via
	   object-fit:cover. svh, never vh — no iOS URL-bar jump. */
	min-height:clamp(640px, 88svh, 1040px);
	padding-top:calc(var(--nav-h) + var(--space-5));
	padding-bottom:var(--space-5);
	background:var(--color-navy-900);     /* pre-image + image-failure ground */
	overflow:hidden;
}

/* Short viewports (laptops, landscape tablets) cannot afford a 200px crown.
   The crown and the banner's opaque point must move together — that equality
   IS the contrast invariant, so both tokens are re-set as a pair. */
@media (max-height:820px){
	:root{ --hero-crown-min:150px; --hero-fade-3:150px; }
}
@media (max-height:680px){
	:root{ --hero-crown-min:120px; --hero-fade-3:120px; --hero-fade-2:90px; }
}

/* ---------- Layer 1 · the art -------------------------------------- */
.hero__media{
	position:absolute; inset:0;
	isolation:isolate;                    /* provably contains all blending */
	overflow:hidden;
	z-index:0;
}
.hero__img{
	position:absolute; left:0; top:-8%;
	width:100%; height:116%;              /* 8% of headroom top & bottom for parallax */
	object-fit:cover;
	object-position:50% 45%;
	display:block;
	filter:saturate(1.06) contrast(1.04);
	/* --par is driven by JS on scroll (capped inside the 8% headroom, so an edge
	   is never revealed). The entrance is opacity-only, so it never fights the
	   scroll transform the way a scale keyframe with fill:both would. */
	transform:translate3d(0, var(--par, 0px), 0);
	will-change:transform;
	animation:hero-fade var(--dur-settle) ease-out both;
}
@keyframes hero-fade{ from{ opacity:0; } to{ opacity:1; } }
/* Re-tint the daylight toward navy; do NOT dim it. Shadows go blue, the
   sun stays gold. This is what marries bright art to a navy identity. */
.hero__duotone{
	position:absolute; inset:0; pointer-events:none;
	background:linear-gradient(180deg,#1B3A7A 0%, #2A5AA8 100%);
	mix-blend-mode:soft-light;
	opacity:.30;
}
/* Shadow pooling at the base of the staircase — seats the flanking
   chibis on the ground. Protects no text; purely atmospheric. */
.hero__floor{
	position:absolute; inset:0; pointer-events:none;
	background:linear-gradient(to top,
		rgba(11,27,56,.86)  0%,
		rgba(11,27,56,.52) 10%,
		rgba(11,27,56,.16) 22%,
		rgba(11,27,56,0)   34%);
}

/* ---------- Layer 2 · the gate banner (carries ALL contrast) --------- */
.hero__banner{
	position:relative; z-index:1;
	width:var(--hero-banner-w);
	/* Feather and padding are in PIXELS, not percentages, and deliberately so.
	   A percentage padding resolves against the CONTAINING BLOCK (the .hero,
	   ~1013px) — not against the banner's own width (~678px) — while a mask
	   percentage resolves against the banner. Mixing the two silently ate
	   ~240px of inline padding and collapsed the content column, which forced
	   the two CTAs to stack on desktop.
	   The only rule that matters here is --hero-pad > --hero-feather, so text
	   always lands in the fully opaque core and never in the fade. */
	padding:12px var(--hero-pad) var(--space-7);
	/* A "pool of dusk", not a box.
	   The vertical linear ramp still owns the contrast — it is dense where the
	   text sits — but the PEAK is now .90 (13.2:1 worst case over a pure-white
	   sun pixel, still AAA) instead of the old near-black .97, so the middle no
	   longer reads as a black slab dropped onto bright art.
	   A radial mask then dissolves the top and both sides into the scene, so the
	   banner has no hard rectangular edge — it fuses with the gate behind it. */
	background:linear-gradient(180deg,
		rgba(9,21,46,0)    0px,
		rgba(9,21,46,.36)  var(--hero-fade-1),   /*  44px — crest zone, mostly image */
		rgba(9,21,46,.74)  var(--hero-fade-2),   /* 120px — ~8:1 for white           */
		rgba(9,21,46,.90)  var(--hero-fade-3),   /* 200px — 13.2:1 for white         */
		rgba(9,21,46,.90)  100%);
	/* Solid where the text lives (out to 60% of the radius), then feathered to
	   nothing by the edges. Text is centred and stays well inside the core. */
	-webkit-mask-image:radial-gradient(140% 116% at 50% 60%,
		#000 58%, rgba(0,0,0,.55) 84%, transparent 100%);
	        mask-image:radial-gradient(140% 116% at 50% 60%,
		#000 58%, rgba(0,0,0,.55) 84%, transparent 100%);
}
/* The gold lintel — ornament 1 of 3 identical appearances page-wide. */
.hero__banner::after{
	content:"";
	position:absolute;
	left:var(--hero-feather); right:var(--hero-feather); bottom:0; height:2px;
	background:var(--color-gold);            /* 9.07:1 — legal, it is on navy */
	-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 18%,#000 82%,transparent 100%);
	        mask-image:linear-gradient(90deg,transparent 0,#000 18%,#000 82%,transparent 100%);
}

.hero__col{
	display:flex; flex-direction:column; align-items:center;
	text-align:center;
	max-width:640px; margin-inline:auto;
}
.hero__col > *{ animation:hero-rise var(--dur-slow) var(--ease-out) both; }
.hero__col > *:nth-child(1){ animation-delay:0ms;   }
.hero__col > *:nth-child(2){ animation-delay:80ms;  }
.hero__col > *:nth-child(3){ animation-delay:160ms; }
.hero__col > *:nth-child(4){ animation-delay:240ms; }
.hero__col > *:nth-child(5){ animation-delay:320ms; }

/* ================= THE INVARIANT =====================================
   The crown reserves 200px of vertical space and holds ONLY the logo.
   Because the H1 is the crown's next sibling, nothing typographic can
   ever start higher than the point at which the banner gradient has
   reached alpha .97. This single rule is what makes the contrast ledger
   true. Do not lower --hero-crown-min. Do not make the crest absolute.
   ==================================================================== */
.hero__crown{
	min-height:var(--hero-crown-min);   /* 200px === --hero-fade-3 */
	display:flex; align-items:flex-end; justify-content:center;
	width:100%;
	margin-bottom:var(--space-4);
}

/* The crest sits in the translucent zone, but it is a logotype (exempt
   from WCAG 1.4.3 / 1.4.11) and it carries its own navy pool. */
.hero__crest{ position:relative; width:clamp(160px, 14vw, 220px); }
.hero__crest::before{
	content:"";
	position:absolute; inset:-10% -16%;
	background:radial-gradient(62% 62% at 50% 55%,
		rgba(8,20,44,.78) 0%, rgba(8,20,44,.48) 46%, rgba(8,20,44,0) 74%);
	filter:blur(18px);
}
.hero__crest .crest{
	position:relative;
	display:block; width:100%; height:auto;
	filter:drop-shadow(0 1px 0 rgba(255,255,255,.35))
	       drop-shadow(0 10px 28px rgba(6,14,32,.55));
}

/* Solid navy pill — carries its own background, so it is contrast-safe
   at any vertical position within the banner. */
.hero__eyebrow{
	display:inline-flex; align-items:center; gap:var(--space-2);
	margin:0 0 var(--space-4);
	padding:7px 16px;
	background:var(--color-navy-900);
	border-radius:999px;
	color:var(--color-text-on-dark);       /* 14.30:1 */
	font-size:var(--t-label); font-weight:600;
	letter-spacing:.10em; text-transform:uppercase;
	line-height:1.4;
}
.hero__eyebrow:lang(th){ letter-spacing:.02em; }
.hero__eyebrow .dot{
	width:8px; height:8px; border-radius:50%;
	background:var(--color-success-on-dark);
	flex:none;
}

.hero h1{
	color:var(--color-text-on-dark-max);   /* 15.86:1 worst case */
	margin:0 0 var(--space-4);
	text-wrap:balance;
}
.hero__sub{
	margin:0 0 var(--space-6);
	max-width:52ch;
	font-size:var(--t-lead);
	line-height:var(--lh-thai);
	color:#FFFFFF;
	opacity:.94;                           /* ≈14.6:1 — still AAA */
}
.hero__cta{
	display:flex; gap:var(--space-4);
	flex-wrap:wrap; justify-content:center;
}
.hero__platforms{
	margin:var(--space-4) 0 0;
	font-size:var(--t-small);
	color:var(--color-text-on-dark-dim);   /* 8.56:1 */
	letter-spacing:.08em;
}

/* =====================================================================
   HERO · AMBIENT LIFE
   A restrained set of effects — the crystal logo breathes and catches
   light, a few twinkles play around the angel, and two RO monsters drift
   in the sky. No screen-filling particles, no heavy glow. All of it is
   decorative and switches off under prefers-reduced-motion.
   ===================================================================== */

/* The whole crest drifts gently. Its entrance (hero-rise) is on the parent
   .hero__crown, so this continuous float never fights the load animation. */
.hero__crest{ animation:logo-float 6s ease-in-out infinite; }
@keyframes logo-float{ 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-8px); } }

/* The navy pool behind the logo breathes, so the crest feels lit from within. */
.hero__crest::before{
	transform-origin:50% 55%;
	animation:crest-glow 6s ease-in-out infinite;
}
@keyframes crest-glow{
	0%,100%{ opacity:.82; transform:scale(1); }
	50%    { opacity:1;   transform:scale(1.07); }
}

/* Ice-crystal shine sweep — a diagonal glint masked to the exact logo shape,
   so light travels across the crystal wordmark, then rests. */
.crest-shine{
	position:absolute; inset:0; pointer-events:none;
	-webkit-mask:url('../images/logo-560.webp') center/contain no-repeat;
	        mask:url('../images/logo-560.webp') center/contain no-repeat;
	background:linear-gradient(115deg,
		transparent 42%, rgba(255,255,255,.55) 50%, transparent 58%);
	background-size:260% 100%;
	background-position:190% 0;
	mix-blend-mode:screen;
	opacity:0;
	animation:crest-shine 7s ease-in-out 1.6s infinite;
}
@keyframes crest-shine{
	0%      { background-position:190% 0; opacity:0; }
	4%      { opacity:1; }
	20%     { background-position:-90% 0; opacity:1; }
	24%,100%{ background-position:-90% 0; opacity:0; }
}

/* A handful of twinkles around the angel — four-point stars, not a field. */
.hero__sparkles{ position:absolute; inset:-10%; pointer-events:none; }
.hero__sparkles i{
	position:absolute; left:var(--x); top:var(--y);
	width:12px; height:12px;
	background:#FFFFFF;
	clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%);
	filter:drop-shadow(0 0 3px rgba(255,240,200,.8));
	opacity:0;
	animation:sparkle 4.5s ease-in-out var(--d) infinite;
}
@keyframes sparkle{
	0%,100%{ opacity:0; transform:scale(.3) rotate(0deg); }
	50%    { opacity:1; transform:scale(1)  rotate(45deg); }
}

/* Two RO monsters bob in the sky, out in the flanks, well clear of the text. */
.hero__mob{
	position:absolute; z-index:1;
	image-rendering:pixelated;
	filter:drop-shadow(0 6px 10px rgba(0,0,0,.4));
	opacity:.92;
}
.hero__mob--l{ left:9%;  top:17%; animation:mob-bob 4.6s ease-in-out infinite; }
.hero__mob--r{ right:9%; top:13%; animation:mob-bob 5.4s ease-in-out .7s infinite; }
@keyframes mob-bob{ 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-12px); } }
@media (max-width:1023px){ .hero__mob{ display:none; } }

@media (max-width:1023px){
	/* The banner narrows to 78vw here, so the 100px inline padding would eat a
	   third of it. Scale pad and feather down together — the invariant is only
	   that --hero-pad stays greater than --hero-feather. */
	:root{ --hero-banner-w:78vw; --hero-pad:64px; --hero-feather:44px; }
	.hero{ min-height:clamp(620px, 82svh, 900px); }
	.hero__img{ object-position:50% 52%; }
	.hero__cta .btn{ flex:1 1 48%; min-width:0; }
}

/* ---------- MOBILE: split poster. height:auto, so it cannot clip. ---- */
@media (max-width:767px){
	.hero{
		display:block;
		height:auto;                  /* content sets the height — the whole fix */
		min-height:100svh;
		padding-top:var(--nav-h-mobile);
		background:var(--color-navy-900);
	}
	.hero__media{
		position:relative;
		height:34svh; min-height:200px;
		/* the art dissolves into the navy field — no visible seam */
		-webkit-mask-image:linear-gradient(180deg,#000 0%,#000 62%,transparent 100%);
		        mask-image:linear-gradient(180deg,#000 0%,#000 62%,transparent 100%);
	}
	.hero__img{ object-position:50% 38%; }   /* keeps gate + sun + inner chibis */
	.hero__floor{ display:none; }

	.hero__banner{
		width:100%;
		margin-top:-40px;             /* laps up into the mask's fade */
		padding:0 var(--gutter) var(--space-8);
		background:linear-gradient(180deg,
			rgba(11,27,56,0)   0px,
			rgba(11,27,56,.92) 40px,
			var(--color-navy-900) 76px,
			var(--color-navy-900) 100%);
		-webkit-mask-image:none; mask-image:none;   /* solid navy — 17.10:1 */
	}
	.hero__banner::after{ left:var(--gutter); right:var(--gutter); }
	.hero__crown{ min-height:0; margin-bottom:var(--space-3); }
	.hero__crest{ width:132px; }
	.hero__cta{ flex-direction:column; width:100%; gap:12px; }
	.hero__cta .btn{ width:100%; min-height:56px; }
}
@media (max-width:380px){
	.hero__crest{ width:112px; }
}

/* =====================================================================
   QUICK ACCESS — ONE navy plinth, not four cards.
   It overlaps the hero by -56px: that is the depth move, it proves hero
   and page are one composition, and it carries the navy identity down
   into the body so the page reads navy-led rather than cream-led.
   One surface. Zero cards. Zero borders. Three internal hairlines.
   ===================================================================== */
.qa{ position:relative; z-index:2; margin-top:-56px; }
.qa__plinth{
	position:relative;
	display:grid; grid-template-columns:repeat(5,1fr);
	/* Dividers: each item paints a 1px ring (box-shadow spread) that bleeds into
	   the 1px grid gap, so adjacent items share a hairline. This stays correct
	   at every wrap and breakpoint — unlike a `+ sibling` rule, which strands a
	   stray left-hand line on the first item of each new row. The plinth's own
	   background stays navy so a trailing EMPTY grid cell (5 items in a 3-col
	   layout) reads as plinth, not as a pale block of divider colour. */
	gap:1px;
	background:var(--color-navy-900);
	border-radius:var(--radius-large);
	box-shadow:var(--shadow-card);
	overflow:hidden;
}
/* The gold lintel, appearance 2 of 3. */
.qa__plinth::before{
	content:"";
	position:absolute; top:0; left:0; right:0; height:2px; z-index:1;
	background:var(--color-gold);
	-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 15%,#000 85%,transparent 100%);
	        mask-image:linear-gradient(90deg,transparent 0,#000 15%,#000 85%,transparent 100%);
}
.qa__item{
	position:relative;
	display:flex; flex-direction:column; align-items:flex-start; gap:6px;
	padding:var(--space-6) var(--space-4);
	min-height:132px;
	background:var(--color-navy-900);
	box-shadow:0 0 0 1px var(--color-divider-on-navy);   /* fills the 1px gaps */
	text-decoration:none;
	transition:background var(--dur-fast) var(--ease-press);
}
.qa__sprite{
	image-rendering:pixelated;   /* crisp 90s pixels — the unfakeable game signal */
	transition:transform var(--dur-fast) var(--ease-press);
}
.qa__label{
	color:var(--color-text-on-dark);          /* 14.30:1 */
	font-size:var(--t-body); font-weight:600;
	transition:color var(--dur-fast) var(--ease-press);
}
.qa__sub{
	color:var(--color-text-on-dark-dim);      /* 8.56:1 */
	font-size:var(--t-small);
	line-height:1.5;
}
.qa__item:hover,
.qa__item:focus-visible{ background:var(--color-navy-800); }
.qa__item:hover .qa__sprite{ transform:scale(1.08); }
.qa__item:hover .qa__label{ color:var(--color-gold); }
.qa__item:hover::after,
.qa__item:focus-visible::after{ transform:scaleX(1); }

@media (max-width:1199px){
	.qa__plinth{ grid-template-columns:repeat(3,1fr); }
}
@media (max-width:767px){
	.qa__plinth{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:600px){
	.qa{ margin-top:-32px; }
	.qa__plinth{ grid-template-columns:1fr; }
	.qa__item{
		flex-direction:row; align-items:center; flex-wrap:wrap;
		gap:var(--space-4); min-height:72px;
		padding:var(--space-4) var(--space-5);
	}
	.qa__sub{ flex-basis:100%; }
}

/* =====================================================================
   NEWS & EVENTS — cream, editorial split.
   Featured 58% + list 42%. Not a grid of uniform cards.
   The whole <section> is omitted from the DOM when the store is empty,
   so no placeholder or invented content can ever reach production.
   ===================================================================== */
.news{
	position:relative;
	padding:var(--space-section) 0;
	background:var(--color-bg-primary);
}
.news__split{
	display:grid; grid-template-columns:58fr 42fr;
	gap:var(--space-8);
	align-items:start;
}

.news__featured-link{ display:block; text-decoration:none; }
.news__media{
	position:relative;
	aspect-ratio:16/9;
	overflow:hidden;
	border-radius:var(--radius-large);
	background:var(--color-navy-800);
	box-shadow:var(--shadow-card);
	margin-bottom:var(--space-5);
}
.news__media img{
	width:100%; height:100%;
	object-fit:cover; display:block;
	transition:transform var(--dur-mid) var(--ease-press);
}
.news__featured-link:hover .news__media img{ transform:scale(1.03); }
/* No grey placeholder box: a navy plate carrying the category crest. */
.news__plate{ position:absolute; inset:0; display:grid; place-items:center; }
.news__plate img{ width:96px; height:96px; opacity:.22; image-rendering:pixelated; }

.news__chip{
	display:inline-flex; align-items:center; gap:8px;
	margin:0 0 var(--space-3);
	font-size:var(--t-small); font-weight:600;
	color:var(--color-text-secondary);          /* 6.62:1 */
}
.news__chip img{ width:20px; height:20px; }
/* The event/promotion chip is the ENTIRE red budget of the page. */
.news__chip--event,
.news__chip--promotion,
.news__chip--notice{ color:var(--color-ember); }   /* 5.05:1 */

.news__title{
	font-size:var(--t-tile);
	color:var(--color-text-primary);            /* 16.88:1 */
	margin:0 0 var(--space-3);
}
.news__excerpt{
	color:var(--color-text-secondary);          /* 6.62:1 */
	margin:0 0 var(--space-3);
}
.news__date{
	font-size:var(--t-small); font-weight:600;
	color:var(--color-gold-ink);                /* 5.49:1 — LAW 1 on light */
	font-variant-numeric:tabular-nums;
}

/* The list: hairlines BETWEEN rows. No boxes. */
.news__list{ list-style:none; margin:0; padding:0; }
.news__list li + li{ border-top:1px solid var(--color-border); }   /* 4.09:1 — perceivable */
.news__row{
	position:relative;
	display:grid; grid-template-columns:72px 1fr;
	gap:var(--space-4); align-items:baseline;
	min-height:64px; padding:var(--space-4) var(--space-3);
	text-decoration:none;
	transition:background var(--dur-fast) var(--ease-press);
}
.news__row .news__date{ transition:transform var(--dur-fast) var(--ease-press); }
.news__row-title{
	color:var(--color-text-primary);            /* 15.93:1 */
	font-weight:500;
}
.news__row:hover,
.news__row:focus-visible{ background:var(--color-surface-hover); }
.news__row:hover .news__date{ transform:translateX(2px); }
.news__row:hover::after,
.news__row:focus-visible::after{ transform:scaleX(1); }
/* The shared gold wipe must become gold-ink on a light surface (LAW 1). */
.news__row::after{ background:var(--color-gold-ink); }

/* Gutter heralds — the two chibi characters, shown ONLY where a real
   gutter exists (>=1800px). Static, behind content, never near text. */
.herald{ display:none; }
@media (min-width:1800px){
	.herald{
		display:block;
		position:absolute; bottom:0; z-index:0;
		pointer-events:none;
		max-height:440px; width:auto;
	}
	.herald--l{ left:calc(50% - (var(--container-width) / 2) - 232px); }
	.herald--r{ right:calc(50% - (var(--container-width) / 2) - 232px); }
	.news .container{ position:relative; z-index:1; }
}
@media (max-width:1023px){
	.news__split{ grid-template-columns:1fr; gap:var(--space-7); }
}

/* =====================================================================
   SERVER STATUS — navy band, three measured states, no fake data.
   There is no player count anywhere: not as a variable, a class, or a
   string. The public site has no trustworthy source for one.
   ===================================================================== */
.status{
	position:relative; overflow:hidden;
	padding:var(--space-section) 0;
	background:var(--color-navy-900);
}
.status__art{
	position:absolute; inset:-4% -2% -4% -2%;   /* over-size so the slow drift never bares an edge */
	background:url('../images/band-prontera-1920.webp') center/cover no-repeat;
	opacity:.22;
	mix-blend-mode:luminosity;
	animation:band-drift 26s ease-in-out infinite alternate;
}
@keyframes band-drift{ from{ transform:translate3d(-1.5%,0,0) scale(1.04); } to{ transform:translate3d(1.5%,0,0) scale(1.04); } }
.status::before{
	content:"";
	position:absolute; inset:0;
	background:linear-gradient(90deg,
		var(--color-navy-900) 0%,
		rgba(11,27,56,.64)   45%,
		rgba(11,27,56,.95)  100%);
}
.status__inner{ position:relative; z-index:1; }

/* Facts in one row, separated by hairlines. No cards, no borders, no glass. */
.status__facts{
	display:flex; flex-wrap:wrap;
	margin:0;
	border-top:1px solid var(--color-hairline);
}
/* Scoped to .status__facts: sub-pages (server-info.php) use a bare .stat
   inside .hero-stats, and must not inherit this band's layout. */
.status__facts .stat{
	flex:1 1 0; min-width:200px;
	padding:var(--space-6) var(--space-5);
}
.status__facts .stat + .stat{ box-shadow:inset 1px 0 0 var(--color-hairline); }
.stat__label{
	font-size:var(--t-small); font-weight:500;
	color:var(--color-text-on-dark-dim);        /* 8.56:1 */
	margin:0 0 var(--space-2);
}
.stat__value{
	margin:0;
	font-family:var(--font-display);
	font-size:var(--t-stat); font-weight:700;
	line-height:var(--lh-display);
	color:var(--color-gold);                    /* 9.07:1 */
	display:flex; align-items:center; gap:12px;
	font-variant-numeric:tabular-nums;
}
.stat__value:lang(th){ font-family:var(--font-body); }
.stat__meta{
	margin:var(--space-2) 0 0;
	font-size:var(--t-small);
	color:var(--color-text-on-dark-dim);
}

/* Three states. All designed. All honest. */
.status__dot{ width:10px; height:10px; border-radius:50%; flex:none; }
.stat--state.is-online  .stat__value{ color:var(--color-success-on-dark); }  /* 11.12:1 */
.stat--state.is-online  .status__dot{
	background:var(--color-success-on-dark);
	animation:status-pulse 2400ms ease-in-out infinite;   /* the ONLY loop on the page */
}
.stat--state.is-offline .stat__value{ color:var(--color-alert-on-dark); }    /*  7.44:1 */
.stat--state.is-offline .status__dot{ background:var(--color-alert-on-dark); }
.stat--state.is-unknown .stat__value{ color:var(--color-muted-on-dark); }    /*  8.56:1 */
.stat--state.is-unknown .status__dot{ background:var(--color-muted-on-dark); }

@media (max-width:767px){
	.status__facts{ flex-direction:column; }
	.status__facts .stat + .stat{ box-shadow:inset 0 1px 0 var(--color-hairline); }
}

/* =====================================================================
   GAME HIGHLIGHTS — parchment, bento, three unequal tiles, one inverted.
   The single dark tile inside a light grid IS the hierarchy strategy —
   it replaces the usual row of four identical cards.
   ===================================================================== */
.hl{
	padding:var(--space-section) 0;
	background:var(--color-bg-secondary);
}
.hl__bento{
	display:grid;
	grid-template-columns:2fr 1fr;
	grid-template-rows:auto auto;
	gap:20px;
}
.tile--a{ grid-row:span 2; }

.tile{
	position:relative; overflow:hidden;
	padding:var(--space-7);
	/* Reserve the sprite's footprint. The sprite is absolutely positioned at
	   bottom-right (24px inset, 72px tall = 96px of occupied height), so the
	   copy must never be allowed to flow into that band or the monster lands
	   on top of the words. */
	padding-bottom:calc(var(--space-7) + 80px);
	background:var(--color-surface);
	border-radius:var(--radius-large);
	border:0;                                    /* zero borders */
	box-shadow:var(--shadow-card);
	transition:transform var(--dur-fast) var(--ease-press),
	           box-shadow var(--dur-fast) var(--ease-press);
}
.tile:hover{ transform:translateY(-3px); box-shadow:var(--shadow-lift); }
.tile__title{
	color:var(--color-text-primary);             /* 16.88:1 */
	margin:0 0 var(--space-3);
}
.tile__body{
	color:var(--color-text-secondary);           /* 7.01:1 */
	margin:0;
	max-width:46ch;
}
.tile__sprite{
	position:absolute; right:var(--space-5); bottom:var(--space-5);
	image-rendering:pixelated;
	pointer-events:none;
}
.tile--a{ padding-bottom:calc(var(--space-7) + 104px); }   /* 96px sprite */
.tile--a .tile__sprite{ width:96px; height:96px; }

/* The inversion. */
.tile--invert{ background:var(--color-navy-800); }
.tile--invert::before{
	content:"";
	position:absolute; top:0; left:var(--space-7);
	width:40px; height:3px;
	background:var(--color-gold);                /* 8.09:1 — legal, it is on navy */
}
.tile--invert .tile__title{ color:var(--color-gold); }          /*  8.09:1 */
.tile--invert .tile__body { color:var(--color-text-on-dark); }  /* 12.76:1 */

@media (max-width:1023px){
	.hl__bento{ grid-template-columns:1fr; }
	.tile--a{ grid-row:auto; }
}
