/* ============================================================================
   SITE — components. Composed only from tokens.css; no raw colour, size or
   duration appears below this line. If a value is missing, it belongs in the
   token layer, not here.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }

html {
	/* Anchors land below the fixed bar instead of underneath it. */
	scroll-padding-top: calc(var(--bar-h) + var(--s-4));
	scroll-behavior: smooth;
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
	/* THE PAGE IS A COLUMN THAT REACHES THE FLOOR, so the footer is at the
	   bottom of the window on a short page and after the content on a long
	   one. Without this the 404, the "we sent the letter" endings and an empty
	   ranking left the footer hanging in the middle of the screen with the
	   body's own ground below it.
	   Only two of body's children are in the flow -- <main> and <footer>. The
	   announcement strip, the masthead and the Greek-key rule under it are all
	   position:fixed, so they are not flex items and cost the column nothing.
	   svh rather than vh: on a phone vh is measured against the browser's
	   toolbar-collapsed height, which would make the column taller than the
	   screen and put a scrollbar on every short page. */
	min-height: 100svh;
	display: flex;
	flex-direction: column;
	background: var(--c-ground);
	color: var(--c-ink);
	font-family: var(--f-text);
	font-size: var(--step-0);
	font-weight: var(--w-regular);
	line-height: var(--lh-body);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

/* <main> IS THE PART THAT STRETCHES. It takes whatever height the window has
   left over after the footer, which is what holds the footer on the floor.
   flex-shrink 0 so a page taller than the window is never squeezed into it.

   AND IT IS A COLUMN ITSELF, so the slack can be handed on. Left as a plain
   block, a stretched <main> on a short page would be a 400px band of the
   message screen's own plate with the body's darker ground showing between it
   and the footer -- a seam across the window, which is the exact fault the
   message band used to answer by asking for the whole screen. Passing the
   slack to the page's LAST band instead means the band that ends the page is
   the thing that reaches the footer, whichever page it is: every template's
   content block ends in a full-width section. */
main {
	flex: 1 0 auto;
	display: flex;
	flex-direction: column;
}
main > :last-child { flex-grow: 1; }

h1, h2, h3 {
	font-family: var(--f-display);
	/* 600 for the two lower ranks and 700 for h1, which is the atlas's split:
	   in a condensed face the step between 600 and 700 is most of what tells
	   a page title apart from a section title, since neither can lean on
	   width to do it. */
	font-weight: var(--w-semibold);
	line-height: var(--lh-heading);
	letter-spacing: var(--ls-tight);
	margin: 0;
	text-wrap: balance;
}
h1 { font-weight: var(--w-bold); }

p { margin: 0; max-width: var(--measure); }

/* EVERY SMALL ALL-CAPS LABEL IS SET IN THE DISPLAY FACE, and they are listed
   together rather than repeating two declarations twenty times. This is the
   atlas's own division of labour: an eyebrow, a column head, a chip and a
   form label are signage, not prose, and Oswald at 500 is what the atlas
   signs with. Declared here, near the top, so the rules further down that own
   these selectors keep their size, colour and spacing and inherit only the
   face -- adding a family line to each of them would be the same change made
   twenty times and wrong in one of them.

   Medium, not semibold: at this size with .13em of tracking the heavier
   weight fills its own counters and the word turns into a bar. */
/* THE LIVE COUNT IN THE BAR. Quiet on purpose: it sits beside the brand and
   must not compete with the two buttons on the other side. The dot is what
   makes the number mean "now" rather than "in total". */
/* THE AUTO MARGIN MOVES HERE when this chip exists. .beta-chip carries it
   normally -- brand and chip are a pair at the start, everything else is pushed
   to the end -- but with a second item after it the free space split between
   two auto margins and left the count adrift in the middle of the bar.
   Whichever of the two is last in the group is the one that pushes. */
.bar > .wrap:has(.live-chip) .beta-chip { margin-inline-end: 0; }
.live-chip {
	margin-inline-end: auto;
	display: inline-flex;
	align-items: center;
	gap: var(--s-2);
	font-size: var(--step--1);
	color: var(--c-ink-dim);
	white-space: nowrap;
}
.live-chip b { color: var(--c-ink); font-weight: var(--w-semibold); }
.live-dot {
	inline-size: .5rem;
	block-size: .5rem;
	border-radius: 50%;
	background: var(--c-ok);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-ok) 22%, transparent);
	flex: none;
}
/* Below the breakpoint the bar has the brand, the chip and the burger to fit;
   the count is the one of the three nobody came for. */
@media (max-width: 60rem) { .live-chip { display: none; } }

.beta-chip, .eyebrow, .kicker,
.tiles dt, .fact dt, .band-k, .field > span,
.rate-group h3, .req h3, .facts-card h3, .maint-note h2,
table.rank th, table.spec th,
/* .podium-meta is NOT among these any more: it stopped being a label and went
   back to being a quantity -- see the note on the rule itself. */
.tagx, .ann .tag, .newsrow-meta,
.news-date span, .price span {
	font-family: var(--f-display);
	font-weight: var(--w-medium);
}

a { color: var(--c-gold-soft); text-decoration: none; }
a:hover { color: var(--c-gold-hi); }

:focus-visible {
	outline: 2px solid var(--c-gold);
	outline-offset: 3px;
	border-radius: var(--r-sm);
}

img { max-width: 100%; display: block; }

.wrap {
	width: 100%;
	max-width: var(--w-page);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

/* Visible to a screen reader, not to the eye. Used for the skip link and for
   labels that the layout communicates visually but the markup must still say. */
.sr {
	position: absolute; width: 1px; height: 1px;
	padding: 0; margin: -1px; overflow: hidden;
	clip-path: inset(50%); white-space: nowrap;
}
.skip:focus {
	position: fixed; inset-block-start: var(--s-3); inset-inline-start: var(--s-3);
	width: auto; height: auto; clip-path: none; z-index: 100;
	background: var(--c-gold); color: var(--c-gold-ink);
	padding: var(--s-3) var(--s-4); border-radius: var(--r);
}

/* ---- BAR ---------------------------------------------------------------- */

.bar {
	position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 50;
	height: var(--bar-h);
	display: flex; align-items: center;
	background: color-mix(in srgb, var(--c-ground-2) 88%, transparent);
	backdrop-filter: blur(10px);
	border-block-end: var(--bw) solid var(--c-hair);
}
.bar > .wrap { display: flex; align-items: center; gap: var(--s-5); }

.brand {
	font-family: var(--f-display);
	font-size: var(--step-2);
	font-weight: var(--w-bold);
	letter-spacing: var(--ls-display);
	color: var(--c-ink);
}
.brand:hover { color: var(--c-gold-hi); }
/* The "2" carries the accent. <em> is the markup because the digit is the part
   of the name that is emphasised; the italics it would bring are turned off,
   since the wordmark is upright everywhere else it appears. */
.brand em { color: var(--c-gold); font-style: normal; }

.bar nav { display: flex; align-items: center; gap: var(--s-5); }
/* The links in the bar are styled by ".menu > .main a:not(.btn)" further down.
   A ".bar nav a" rule used to do it here as well, and because it is one step
   more specific than ".btn-gold" it also dimmed the one gold button in the bar
   -- its label came out faint on gold. One rule, and it keeps the :not(.btn). */

/* Exactly one filled gold control per screen. The launcher does the same with
   its single action button; two golds on one page means neither is the action. */
.btn {
	display: inline-flex; align-items: center; justify-content: center;
	gap: var(--s-2);
	font-family: var(--f-text);
	/* THE ATLAS'S BUTTON IS SMALLER THAN THE ONE THE SITE HAD DRAWN: .86rem of
	   type in .42rem of padding, where the site was setting body size in .75rem
	   of it. That is the whole reason a row of controls was running 140 to
	   233px wide and 49 to 72px tall -- a button whose padding is half a line
	   of text takes its size from its label instead of from the design. */
	font-size: var(--step--1);
	font-weight: var(--w-semibold);
	/* The atlas tracks its buttons at nothing. A button is a word the eye
	   grabs whole, not a line it reads across, and the headings' tracking
	   pulls the two halves of a two-word label apart. */
	letter-spacing: normal;
	padding: var(--s-2) var(--s-4);
	border: var(--bw) solid transparent;
	border-radius: var(--r);
	cursor: pointer;
	transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
	            border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.btn-gold {
	background: var(--c-gold); color: var(--c-gold-ink);
	box-shadow: var(--sh-gold);
}
.btn-gold:hover { background: var(--c-gold-hi); color: var(--c-gold-ink); transform: translateY(-1px); }
.btn-ghost {
	background: transparent; color: var(--c-ink);
	border-color: var(--c-line);
}
.btn-ghost:hover { border-color: var(--c-gold-dim); color: var(--c-gold-soft); }
.btn-lg { font-size: var(--step-0); padding: var(--s-3) var(--s-5); }

/* ---- HERO --------------------------------------------------------------
   Fills the first screen exactly once. svh, not vh: on mobile the browser's
   collapsing toolbar makes vh taller than what is actually visible, which
   pushes the buttons under the fold on the one device class where the fold
   matters most. */

.hero {
	/* A BAND, NOT A SCREEN. The atlas opens on 440px of picture; the site was
	   asking for the whole window because a second column -- the sign-in card
	   -- had to fit inside it, and with the card gone a full screen of plate
	   under four lines of type is a page that starts by saying nothing. The
	   height itself is --h-hero, restated in the atlas block at the foot of
	   this file; what is decided here is the padding around the words.
	   The masthead is fixed, so the head of the band carries it and the foot
	   carries the atlas's measure alone. */
	min-height: var(--h-hero);
	display: grid;
	align-content: center;
	padding-block: calc(var(--bar-h) + var(--s-hero)) var(--s-hero);
	position: relative;
	overflow: hidden;
}
/* THE PICTURE IS THE GAME'S OWN. The band behind this section is built from
   the four class paintings that ship in the client (uiloading pack), composed
   into one full-width plate by tools/site/build-art.py.
   It sits in ::before and the curtain in ::after, so the picture can be
   swapped by a media query while the curtain stays put. */
.hero::before {
	content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
	background: url("/assets/img/hero.jpg") no-repeat 50% 42% / cover;
}
.hero::after {
	/* The curtain. Heavy on the left where the words are, nearly clear in the
	   middle where the figures are, and closing again at the bottom so the
	   section ends in the page's own ground rather than a cut. */
	content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
	background:
		linear-gradient(90deg, var(--c-veil-3) 0%, var(--c-veil-2) 30%,
		                       var(--c-veil-1) 58%, var(--c-veil-2) 100%),
		linear-gradient(180deg, var(--c-veil-2) 0%, var(--c-veil-0) 26%,
		                        var(--c-veil-3) 100%);
}
.hero > .wrap { position: relative; z-index: 1; }

/* The Greek-key rule that frames every loading screen in the game, used here
   as the one ornament on the page: it marks the masthead's lower edge and the
   footer's upper one, and nothing else. */
/* The closed-beta chip beside the wordmark. Outlined rather than filled: it
   is a label, and a second gold block next to the brand would read as a second
   button. */
.beta-chip {
	/* Carries the auto margin the wordmark used to: brand and chip stay a pair
	   at the start of the bar, everything else is pushed to the end. */
	margin-inline-end: auto;
	align-self: center;
	font-size: var(--step--2);
	letter-spacing: var(--ls-wide);
	text-transform: uppercase;
	color: var(--c-gold-soft);
	border: var(--bw) solid var(--c-gold-dim);
	border-radius: 3px;
	padding: .15rem .5rem;
	white-space: nowrap;
}

.key {
	/* Pinned under the fixed masthead rather than left in the flow. In the flow
	   its 15 pixels sat on top of a section already asking for the full screen
	   height, so the page was 15px taller than the window and scrolled for no
	   reason. Fixed, it belongs to the bar it decorates. */
	position: fixed;
	inset-block-start: var(--bar-h);
	inset-inline: 0;
	z-index: 49;
	height: var(--h-key);
	background: url("/assets/img/ornament.png") repeat-x center / auto var(--h-key);
	opacity: .5;
	pointer-events: none;
}

/* The same strip, used once between sections. It is the page's ONLY divider:
   the game frames every loading screen with this rule, and a border colour in
   its place is what makes a fan site look like a fan site. */
.orn {
	height: var(--h-orn);
	background: url("/assets/img/ornament.png") repeat-x center / auto var(--h-orn);
	opacity: .55;
}

.eyebrow {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-gold-soft);
	/* The atlas sets an eyebrow .35rem to .6rem off the line under it: it is
	   the opening word of a heading, not a paragraph before one. */
	margin-block-end: var(--s-2);
}

.hero h1 {
	/* One step down from the old size and a short measure: at step-5 over 20ch
	   the headline wrapped to six lines and pushed the card off the first
	   screen. The slogan sets its own break, so it is not balanced for it. */
	font-size: var(--step-4);
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-display);
	max-width: 18ch;
	text-wrap: balance;
	/* atlas .hero h1: .55rem. The headline and the sentence under it are one
	   statement; a step of body text between them breaks it into two. */
	margin-block-end: var(--s-2);
}

/* THE SLOGAN BREAKS WHERE THE PROMISE TURNS. Two lines, and the second one
   carries the accent -- the first says what it is, the second is the claim, so
   the gold lands on the half that has to be believed. */
.hero-slogan { text-wrap: pretty; }
.hero-slogan em {
	display: block;
	font-style: normal;
	color: var(--c-gold);
}
/* THE GREETING IS ONE LINE, and the slogan's reasoning does not carry over to
   it. The slogan is two halves of a claim and the break is the claim's; this
   is one short sentence with a name at the end of it -- "Tekrar hoş geldin,
   test6" -- and breaking after the comma left a line ending in punctuation
   over a line holding a single word, which reads as a heading that ran out of
   room rather than as a greeting. The atlas sets .hi as one line with the name
   inline, and a name long enough to need a second line now takes one only when
   it actually does.

   IT IS ALSO SMALLER THAN THE SLOGAN. A returning player is not being sold
   anything, so the line that says hello does not need the hero's full size --
   see --step-hello, and the atlas's 2.2rem against its 3.2rem. */
/* The element selector is carried down from `.hero h1` on purpose: that rule
   sets the size and the measure for BOTH heroes and is a class plus an
   element, so a lone `.hero-hello` loses to it and neither line below would
   have taken effect. */
.hero h1.hero-hello {
	font-size: var(--step-hello);
	font-weight: var(--w-semibold);   /* atlas .hi: 600, a step under the
	                                     slogan's 700                       */
	max-width: none;                  /* .hero h1 caps at 18ch, which is the
	                                     slogan's measure and half a greeting */
}
.hero-hello em {
	font-style: normal;
	color: var(--c-gold-hi);
	/* A player-chosen name can be anything, so it breaks inside itself rather
	   than pushing the band open. */
	overflow-wrap: anywhere;
}

.lede {
	font-size: var(--step-1);
	color: var(--c-ink-dim);
	max-width: 42ch;
	/* atlas .hero .say: 1.4rem, and it is the one real gap in the hero -- what
	   follows it is the row of buttons. */
	margin-block-end: var(--s-5);
}

/* The signed-in visitor's own numbers. Only the ones the site can read: see
   render.PlayerSummary for why rank and EP are not among them. */
.tiles {
	/* Row gap to the atlas's .live (1.7rem); the column gap is the site's own
	   and is left where it was. */
	display: flex; flex-wrap: wrap; gap: var(--s-5) var(--s-6);
	margin: 0;
}
.tiles .tile { display: grid; gap: var(--s-1); }
.tiles dt {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
}
/* A NUMBER A PLAYER COMPARES AGAINST ANOTHER NUMBER IS SET IN THE MONO FACE.
   The atlas draws every level, rank, balance and countdown in IBM Plex Mono
   and it is not decoration: the figures are the same width, so two rows of a
   ranking line up down the column and "1.240" and "980" can be told apart at
   a glance instead of read. Headings stay in the display face -- a step
   number or a 404 is a mark, not a quantity. */
.tiles dd {
	margin: 0;
	font-family: var(--f-mono);
	font-size: var(--step-2);
	line-height: var(--lh-tight);
	color: var(--c-ink);
	font-variant-numeric: tabular-nums;
}


/* THE GAP UNDER THE BUTTONS BELONGS TO WHAT COMES NEXT. The atlas's .acts
   carries no bottom margin: the counters below it set their own margin-top,
   and so does the maintenance note. Here the row had 3.5rem of its own AND
   the counters had 2.25rem of theirs, which is 92px between a button and the
   figure under it. Gap to the atlas's .7rem. */
.actions { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* ---- SECTION ------------------------------------------------------------ */

.section { padding-block: var(--s-section); border-block-start: var(--bw) solid var(--c-hair); }
.section-alt { background: var(--c-ground-2); }

/* atlas .khead: 1.4rem. A section head is a title with one line under it,
   and the band's own padding is what separates it from the section above. */
.section-head { max-width: var(--w-narrow); margin-block-end: var(--s-5); }
.kicker {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
	margin-block-end: var(--s-2);   /* atlas .pghead .kk / .kick             */
}
/* THE SECTION HEAD IS SET IN CAPITALS, and that is the atlas's, not a
   flourish: Oswald's lower case is narrow enough that a heading set in it
   reads as a longer line of the same body text, and the page loses its
   landmarks. Capitals plus the wider tracking is what turns it back into a
   heading. Page titles, post titles and the hero keep their mixed case --
   they are names, and a name shouted is a different word. */
/* .section h1 stands beside .section h2 in both lists below. THE PAGE'S OWN
   NAME IS AN h1, and on /ranking, /news and /account it was an h2 -- three
   pages whose document outline began at level two, which is a page with no
   title as far as anything reading the structure is concerned. Promoting the
   tag without adding it here would have changed the size and the case with it. */
.section h1, .section h2, .duo-head h2, .dl-call h2, .card h3, .class-cap h3,
.acct-box h3, .dl-box h3, .acct-head h3, .auth-h {
	text-transform: uppercase;
	letter-spacing: var(--ls-head);
}
/* atlas .khead h2 / .dl h2: .2rem and .25rem. The heading and its sentence
   are a pair, and the pair is what carries the margin below it. */
.section h1, .section h2 { font-size: var(--step-3); margin-block-end: var(--s-1); }
/* :not(.kicker), and it is the fix for a real collision rather than a
   precaution. The kicker sets --step--2 a few rules above; this one is a class
   PLUS a type selector, so it outranked it and every eyebrow on the site came
   out at lede size -- 18.3px where 11.9px was meant, measured at 1246px. The
   heading above it then had nothing to lead. Excluding the kicker here removes
   the collision at its source; raising the kicker's own specificity would only
   have moved the fight. */
.section-head p:not(.kicker) { color: var(--c-ink-dim); font-size: var(--step-1); }

/* ---- GRID / CARD -------------------------------------------------------- */

.grid {
	display: grid;
	gap: var(--s-4);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.card {
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	/* The atlas pads its boxes .85rem to 1rem in the block direction. Only the
	   block direction changes here -- the inline padding is the site's. */
	padding: var(--s-4) var(--s-5);
	transition: border-color var(--t) var(--ease), transform var(--t) var(--ease),
	            box-shadow var(--t) var(--ease);
}
.card:hover {
	border-color: var(--c-gold-dim);
	transform: translateY(-2px);
	box-shadow: var(--sh-1);
}
.card .glyph {
	font-size: var(--step-2);
	color: var(--c-gold);
	line-height: 1;
	margin-block-end: var(--s-2);   /* atlas .empty .ic -> h4: .5rem        */
}
.card h3 { font-size: var(--step-2); margin-block-end: var(--s-1); }
.card p { color: var(--c-ink-dim); font-size: var(--step--1); }

/* ---- RATES -------------------------------------------------------------- */

/* Row gap to the atlas's two-column split (.two, 1.8rem); the column gap
   stays the site's. */
.rates { display: grid; gap: var(--s-5) var(--s-6); grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr)); }
.rate-group h3 {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
	/* No counterpart in the atlas: the nearest relative is .sbx .lede, the one
	   line that introduces a box's contents, at .7rem. */
	margin-block-end: var(--s-3);
}
.rate-list { list-style: none; margin: 0; padding: 0; }
.rate {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: var(--s-4);
	padding-block: var(--s-2);      /* atlas .lst .r: .5rem                 */
	border-block-end: var(--bw) solid var(--c-hair);
}
.rate:last-child { border-block-end: 0; }
.rate dt { color: var(--c-ink-dim); font-size: var(--step-0); }
.rate dd {
	margin: 0;
	font-family: var(--f-mono);
	font-size: var(--step-2);
	font-weight: var(--w-semibold);
	letter-spacing: var(--ls-tight);
	color: var(--c-ink);
	font-variant-numeric: tabular-nums;
}
.rate-hero dd { color: var(--c-gold); font-size: var(--step-3); }

/* ---- FACTS -------------------------------------------------------------- */

.facts {
	display: grid; gap: 0;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	overflow: hidden;
	background: var(--c-panel);
}
.fact {
	padding: var(--s-4) var(--s-5);
	border-inline-end: var(--bw) solid var(--c-hair);
	border-block-end: var(--bw) solid var(--c-hair);
}
.fact dt {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
	margin-block-end: var(--s-1);   /* atlas .kv row gap: .3rem             */
}
.fact dd {
	margin: 0;
	font-family: var(--f-mono);
	font-size: var(--step-2);
	color: var(--c-ink);
	letter-spacing: var(--ls-tight);
}

/* ---- DOWNLOAD ----------------------------------------------------------- */

/* A VERTICAL TRACK, NOT A ROW OF CARDS. The atlas draws the installation as
   one numbered line running down the column: a rule the badges sit on, and the
   instructions to the right of it. Four boxes side by side read as four
   choices -- which is the opposite of what a sequence is -- and in the page's
   left-hand column there is no room for four of anything anyway.

   THE NUMBER IS A BADGE AND IT IS READABLE. It used to be set in
   --c-gold-deep directly on the step's ground, which measured 1.66:1 against
   --c-well: the digit was there, and on a laptop screen it was not visible.
   The atlas puts it in a bordered box in --c-gold-hi, which is 9.25:1 on
   --c-panel -- past the 4.5:1 that text has to clear.

   A CSS counter rather than a number typed into the markup: the digits then
   cannot disagree with the order of the list, and with the stylesheet off the
   <ol> prints its own numbering instead of two sets. */
.steps { counter-reset: step; list-style: none; margin: 0; padding: 0; }
.step {
	counter-increment: step;
	position: relative;
	/* The badge straddles the rule, so it hangs half its width outside the
	   list; the text clears a whole badge plus a gutter. Both derive from the
	   badge's own size -- change the token and the track stays true. */
	margin-inline-start: calc(var(--sz-step-num) / 2);
	padding-inline-start: calc(var(--sz-step-num) + var(--s-4));
	padding-block-end: var(--s-5);
	border-inline-start: var(--bw) solid var(--c-line);
}
/* The rule is a connector between steps, so it stops at the last one -- a line
   running on past the final step points at nothing. The colour rather than the
   border goes transparent: removing the border would shift the text. */
.step:last-child { border-inline-start-color: transparent; padding-block-end: 0; }
.step::before {
	content: counter(step);
	position: absolute;
	inset-inline-start: calc(var(--sz-step-num) / -2);
	inset-block-start: 0;
	inline-size: var(--sz-step-num);
	block-size: var(--sz-step-num);
	border: var(--bw) solid var(--c-line-hi);
	background: var(--c-panel);
	color: var(--c-gold-hi);
	font-family: var(--f-display);
	font-weight: var(--w-semibold);
	font-size: var(--step--1);
	display: grid;
	place-items: center;
}
/* The heading lines up with the badge beside it rather than with the badge's
   box, so the step reads as one row and not as a caption under a number. */
.step h3 { font-size: var(--step-1); margin-block-end: var(--s-1); line-height: var(--lh-heading); }
.step p { color: var(--c-ink-dim); font-size: var(--step--1); }

/* ---- FAQ ---------------------------------------------------------------- */

.faq { max-width: var(--w-narrow); }
.faq details {
	border-block-end: var(--bw) solid var(--c-hair);
}
.faq summary {
	cursor: pointer; list-style: none;
	/* No disclosure in the atlas. Its nearest relative is the bordered list
	   row -- .lst .r and .lgnav a, both .5rem -- lifted one step because this
	   row carries a heading rather than a line of text. */
	padding-block: var(--s-3);
	font-family: var(--f-display);
	font-size: var(--step-2);
	letter-spacing: var(--ls-tight);
	display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
	content: "+";
	font-family: var(--f-text);
	color: var(--c-gold);
	font-size: var(--step-2);
	transition: transform var(--t) var(--ease);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details p { color: var(--c-ink-dim); padding-block-end: var(--s-3); }



/* ---- HERO LAYOUT (two columns) ------------------------------------------ */

.hero-grid {
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
	/* Row gap only: the column gap is the hero's two-column gutter. */
	gap: var(--s-5) var(--s-8);
	align-items: center;
}
.hero-copy { min-width: 0; }

/* The panel column. No artwork stacked on it any more -- the band behind the
   whole section is the picture now, and a second image here fought it. */
.hero-side {
	display: grid;
	justify-items: end;
	min-width: 0;
	width: 100%;
}

.panel-hello {
	margin-block-end: var(--s-4);
	color: var(--c-ink-dim);
}
.panel-hello strong { color: var(--c-ink); }

/* ---- ACCOUNT PANEL ------------------------------------------------------ */

.panel {
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r-lg);
	box-shadow: var(--sh-2);
	padding: var(--s-4) var(--s-5);
	max-width: 26rem;
	justify-self: end;
	width: 100%;
	/* It now sits over a photograph rather than a flat ground: without a
	   deeper shadow and a slightly opaque surface the card floats and the
	   figures read through it. */
	position: relative;
	z-index: 1;
	background: linear-gradient(180deg, rgb(31 26 21 / .97), rgb(24 20 16 / .97));
	box-shadow: 0 24px 60px rgb(0 0 0 / .55), 0 0 0 1px rgb(201 162 39 / .06);
	backdrop-filter: blur(2px);
}

/* Tabs without script: a radio per panel, hidden, and sibling selectors do
   the switching. The inputs stay focusable so the keyboard still drives it. */
.tab-in { position: absolute; opacity: 0; pointer-events: none; }
/* atlas .tabs: .9rem under the row, whether it is a card's two halves or the
   ranking's filters. */
.tabs { display: flex; gap: var(--s-1); margin-block-end: var(--s-4); }
.tabs-pill { flex-wrap: wrap; margin-block-end: var(--s-4); }
.tab {
	flex: 1 1 auto;
	text-align: center;
	cursor: pointer;
	/* A tab is a sign, like the column heads above: display face, small,
	   upper case. The atlas tracks it narrower than an eyebrow because a tab
	   has a box around it and the tracking would push the word into it. */
	font-family: var(--f-display);
	font-size: var(--step--1);
	font-weight: var(--w-medium);
	text-transform: uppercase;
	letter-spacing: var(--ls-tab);
	color: var(--c-ink-dim);
	padding: var(--s-2) var(--s-4);  /* atlas .tab: .45rem                  */
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
	            border-color var(--t-fast) var(--ease);
}
.tab:hover { color: var(--c-ink); border-color: var(--c-gold-dim); }
.tabs-pill .tab { flex: 0 0 auto; }

/* THE CARD CHANGES HEIGHT, THE PAGE DOES NOT. The register form is taller
   than the sign-in one, and it used to push the section -- and everything in
   it -- downwards. Two things fixed that and both are needed: the section is
   pinned to the screen height (see .hero), and the register form was made
   short enough to fit inside it. Reserving the taller form's height under the
   shorter one was tried first and rejected: it left a third of the card empty
   in the view most people see. */
.tab-body { display: none; }

#panel-login:checked ~ .tabs [for="panel-login"],
#panel-reg:checked   ~ .tabs [for="panel-reg"],
#rank-players:checked ~ .tabs [for="rank-players"],
#rank-guilds:checked  ~ .tabs [for="rank-guilds"] {
	/* Solid gold, not the dim olive it used to be. Over a photograph the olive
	   read as a disabled tab: the selected one has to be the brightest thing in
	   the card, or nobody can tell which half of the form they are looking at. */
	background: var(--c-gold);
	border-color: var(--c-gold);
	color: var(--c-gold-ink);
}
#panel-login:checked ~ .tab-body[data-for="login"],
#panel-reg:checked   ~ .tab-body[data-for="reg"],
#rank-players:checked ~ .tab-body[data-for="players"],
#rank-guilds:checked  ~ .tab-body[data-for="guilds"] { display: block; }

/* Keyboard focus has to be visible even though the input itself is not. */
.tab-in:focus-visible ~ .tabs .tab { outline: 2px solid var(--c-gold); outline-offset: 2px; }

/* ---- FORM --------------------------------------------------------------- */

/* atlas .f: .85rem between one field and the next. */
.form { display: grid; gap: var(--s-3); }
/* align-content, and it is what keeps a pair of fields on one row the same
   shape. Two .field boxes side by side stretch to the height of the taller
   one, and a stretched grid stretches its ROWS -- so the box next to a field
   carrying a sentence under it grew into a rectangle twice the height with its
   label floating away from it. Packing the rows to the top means a hint under
   one of a pair changes what is below the pair, not the pair. */
.field { display: grid; gap: var(--s-1); align-content: start; }  /* atlas .f label: .28rem */

/* Two fields on one line. The register form in one column stood 871px tall on
   an 860px screen -- taller than the space it had -- so the page had to grow
   to hold it. Pairing the two password boxes is the one place where a split
   costs nothing: they are the same kind of thing and they are typed together. */
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3) var(--s-4); }
.field > span {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
}
.field input {
	font: inherit;
	font-size: var(--step-0);
	color: var(--c-ink);
	background: var(--c-well);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	/* atlas .f .in: .55rem. With the site's line height that is a 44px box,
	   so the field is still a finger's target at the atlas's measure. */
	padding: var(--s-2) var(--s-4);
	width: 100%;
}
.field input::placeholder { color: var(--c-ink-faint); }
.field input:focus-visible { border-color: var(--c-gold-dim); }
/* The red border, and WHEN it may appear.
   It was `:invalid:not(:placeholder-shown)`, and the guard only works on a
   field that has a placeholder: the account box has one, the password boxes do
   not, so every untouched password rendered red before anyone typed a
   character -- the form opened looking like it had already been failed. The
   deletion-code field would have joined it.
   `:user-invalid` is the selector that means what the guard was reaching for:
   invalid AND the person has interacted with it. A browser too old to know it
   shows no red at all, which loses a hint but never accuses anyone of an error
   they have not made yet. */
.field input:user-invalid { border-color: var(--c-danger); }
.field small { font-size: var(--step--2); color: var(--c-ink-faint); }

/* A heading over a GROUP of fields, used where two boxes hold two codes that
   look alike and are not. The register form asks for a deletion code and a
   login PIN one after the other; without a line saying they are two different
   numbers, the second box reads as a repeat of the first. */
.field-head {
	/* The negative half-step pulls the group heading down onto the field it
	   introduces. It is half of .form's gap, so it moved with it. */
	margin: var(--s-2) 0 calc(var(--s-1) * -1);
	font-size: var(--step--1);
	color: var(--c-ink-dim);
}

.check { display: flex; align-items: flex-start; gap: var(--s-3); font-size: var(--step--1); color: var(--c-ink-dim); }
.check input { margin-block-start: 0.25em; accent-color: var(--c-gold); }

.field-note { font-size: var(--step--2); color: var(--c-ink-faint); }
/* The sign-in page's two recovery links, on one row. Column-gap is wide enough
   that the pair reads as two offers rather than one run-on sentence; row-gap
   is what they fall back to when the column is too narrow for both. */
.login-help {
	display: flex;
	flex-wrap: wrap;
	column-gap: var(--s-5);
	row-gap: var(--s-1);
	font-size: var(--step--2);
	color: var(--c-ink-faint);
	max-width: none;
}
/* A different offer, so a line between it and the help above. */
.login-alt {
	margin-block-start: var(--s-3);
	padding-block-start: var(--s-3);
	border-block-start: var(--bw) solid var(--c-hair);
	font-size: var(--step--2);
	color: var(--c-ink-faint);
}
.linky { color: var(--c-gold-soft); cursor: pointer; text-decoration: underline; }

/* ---- A REJECTED FIELD ---------------------------------------------------
   The server's complaint, and it is a different thing from the browser's.
   `:user-invalid` above is the browser refusing a shape before anything is
   sent; this is the site refusing a value it had to ask the database about --
   a name already taken, a password that did not match the one on file. Only
   the server can know those, so only the server can mark them.

   COLOUR IS NOT THE ONLY SIGNAL, and it is not two signals either. A rejected
   box changes THREE things at once, which is what the design asks for and what
   a person who cannot tell the red border from the ordinary one needs:

     the box      its border reddens AND its well is washed red, so the field
                  reads as different in shape and in weight, not only in hue
     the label    the word above it reddens with it
     the sentence a line appears underneath saying what is wrong, led by a
                  bordered "!" -- a mark with an outline around it, which is
                  legible as a shape at a glance on a screen showing no colour
                  at all

   The calm hint that box normally carries is not hidden by a rule: the
   template writes the hint OR the complaint, never both (see register.html),
   so there is nothing left under the box to hide. */
.field-bad > input {
	border-color: var(--c-danger-line);
	background: var(--c-danger-tint);
}
.field-bad > span  { color: var(--c-danger-ink); }
/* TWO CLASSES, not one, and the reason is arithmetic. The element is the same
   <small> that carries a field's calm hint, and `.field small` is a class plus
   an element -- more specific than a lone `.field-err`, so the bare class lost
   and every server-side complaint rendered in the faint grey of a hint. */
.field > .field-err {
	font-size: var(--step--2);
	color: var(--c-danger-ink);
	display: flex;
	gap: var(--s-1);                  /* atlas .emsg: .35rem                */
	align-items: flex-start;
	margin-block-start: var(--s-1);   /* atlas .emsg: .28rem                */
}
/* THE MARK IS PART OF THE MESSAGE, NOT AN ORNAMENT BESIDE IT. Red text under a
   red box is still one signal wearing two hats; a small square with an
   exclamation mark in it is a SHAPE, and a shape survives a monochrome screen,
   a colour-blind reader and a photograph of a phone in bad light. Generated
   rather than written into every template because there are eleven of these
   boxes across two forms and the twelfth would be the one that forgot it.
   flex: 0 0 auto so a long sentence wrapping beside it cannot squeeze the
   square into a rectangle. */
.field > .field-err::before {
	content: "!";
	flex: 0 0 auto;
	inline-size: var(--sz-err-mark);
	block-size: var(--sz-err-mark);
	border: var(--bw) solid var(--c-danger-ink);
	display: grid;
	place-items: center;
	font-family: var(--f-display);
	font-weight: var(--w-bold);
	font-size: var(--step--2);
	line-height: 1;
}

/* The summary over a rejected form. It says WHICH form failed and where to
   look; what is wrong is written under each box that is wrong, because a
   person fixing the third field should not have to count down a list at the
   top to work out which one it is about. */
.banner {
	display: grid;
	gap: var(--s-1);
	padding: var(--s-2) var(--s-4);  /* atlas .banner: .6rem                */
	border-radius: var(--r);
	border: var(--bw) solid var(--c-line);
	margin-block-end: var(--s-4);    /* atlas .banner: 1.1rem               */
	font-size: var(--step--1);
}
.banner b { font-family: var(--f-display); font-size: var(--step-1); font-weight: var(--w-semibold); }
.banner span { color: var(--c-ink-dim); }
.banner-bad {
	background: var(--c-danger-tint);
	border-color: var(--c-danger-line);
}
.banner-bad b { color: var(--c-danger-ink); }
/* The same strip in the other tone, for the one thing on this site that
   succeeds quietly: a redeemed code. The balance beside it changes, but a
   number the reader never memorised is not a confirmation. */
.banner-ok {
	background: var(--c-ok-tint);
	border-color: var(--c-ok-line);
}
.banner-ok strong { color: var(--c-ok); }

/* ---- SIGN IN / REGISTER -------------------------------------------------
   Two halves: one of the client's own class paintings and the form. The
   picture is not decoration looking for a wall -- it is the same plate the
   landing page shows and the same figure the player meets at character
   select, which is what keeps the site, the launcher and the game reading as
   one product.

   The painting half is a fixed fraction rather than half the page: a 440x600
   portrait blown up to 960px wide is a crop of a shoulder. */

.auth {
	min-height: var(--h-auth);
	display: grid;
	/* Form first, painting second: sign-in is the screen somebody arrives at
	   knowing what they want, so the boxes get the reading side and the wider
	   column. The registration screen swaps both, below. */
	grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
	/* stretch, not start: the painting column has to reach the bottom of the
	   row. The form inside its own column still sits at the top -- that is
	   .auth-body's job, not this one's. */
	align-items: stretch;
	/* Clears the fixed masthead AND the key strip pinned under it. The rest of
	   the site gets away with section padding that happens to be larger than
	   the bar; this screen is asked to fill the window exactly once, so it has
	   to be told the real number. */
	padding-block-start: calc(var(--bar-h) + var(--h-key));
}
/* The registration screen leads with the picture. Two screens a click apart
   that are mirror images of each other read as two places; two screens drawn
   identically read as one that did not change. */
.auth-mirror { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr); }

.auth-art {
	overflow: hidden;
	background: var(--c-ground-2);
	position: relative;
	/* THE PLATE FILLS ITS COLUMN. It used to be a fixed 520px inside a row
	   that is usually taller -- the page stretches to push the footer to the
	   bottom of the window -- so the picture stopped partway down and left a
	   black band under itself on every one of these screens.
	   min-height keeps the atlas's band on a short viewport; the row decides
	   the rest. object-fit: cover below means a taller column shows more of
	   the painting rather than stretching it. */
	min-height: var(--h-auth);
	border-inline-start: var(--bw) solid var(--c-hair);
}
.auth-art img {
	position: absolute; inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
	object-position: 50% 16%;
}
/* THE VEIL, AND IT IS DARKEST WHERE THE FORM IS. The boxes sit beside the
   painting rather than on it, but the two share a screen and an undimmed plate
   at full strength pulls the eye off the only thing anybody opened this page
   to use. The same three named steps the hero and the class captions use, so
   no two places darken the game's artwork by different amounts. */
.auth-art::after {
	content: "";
	position: absolute; inset: 0;
	background: linear-gradient(270deg, var(--c-veil-1) 0%, var(--c-veil-2) 40%, var(--c-veil-3) 100%);
}
/* Picture on the left: the divider and the dark end of the veil change sides
   with it, or the gradient dims the window edge instead of the form. */
/* THE PICTURE GOES LEFT, THE FORM RIGHT -- and the form still comes first in
   the markup. Source order is reading order for a screen reader and for a
   browser with no CSS, and on a sign-in page the first thing had better be the
   boxes rather than a painting. So the two are swapped here instead of in the
   template, and both pages can keep the form written first. */
.auth-mirror .auth-art {
	order: -1;
	border-inline-start: 0;
	border-inline-end: var(--bw) solid var(--c-hair);
}
.auth-mirror .auth-art::after {
	background: linear-gradient(90deg, var(--c-veil-1) 0%, var(--c-veil-2) 40%, var(--c-veil-3) 100%);
}

.auth-body {
	display: grid;
	align-content: center;
	justify-items: center;
	padding: var(--s-6) var(--gutter);   /* atlas .auth .side: 2.2rem        */
	min-height: var(--h-auth);
	min-width: 0;
}

/* The card is the landing page's panel -- same surface, same border, same
   shadow -- released from the width and the right-hand alignment the hero
   column imposes on it. */
.auth-card {
	max-width: 30rem;
	justify-self: center;
	padding: var(--s-6);
}
.auth-h { font-size: var(--step-3); margin-block-end: var(--s-1); }  /* atlas .auth h2: .2rem */
.auth-lede {
	color: var(--c-ink-dim);
	font-size: var(--step--1);
	margin-block-end: var(--s-4);   /* atlas .auth .lede: 1.2rem            */
}
/* The registration form is twice as tall as the sign-in one. It is allowed to
   scroll rather than shrinking its type until the two codes look like one
   thing asked twice -- and the atlas gives it a taller band to do it in. */
.auth-tall .auth-body { align-content: start; min-height: var(--h-auth-tall); }
.auth-tall { min-height: var(--h-auth-tall); }
.auth-tall .auth-art { min-height: var(--h-auth-tall); }

/* ---- MY ACCOUNT ---------------------------------------------------------
   A narrow column about the account on the left, what the account HAS on the
   right. Both columns are stacks of the same box, so the page has one
   component in it rather than four that look alike. */

.acct {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	/* Row gap to the atlas's .acct (1.4rem); the column gutter stays. */
	gap: var(--s-5) var(--s-6);
	align-items: start;
}
/* minmax(0, 1fr) rather than the implicit column.
   A grid's automatic column is sized to max-content, and min-width: 0 on the
   grid itself does not reach it: the orders table declares a 40rem minimum and
   the column grew to fit it, so on a phone the whole page scrolled sideways --
   the safebox button was cut off and the table's last two columns sat past the
   edge. Naming the column with a zero minimum is what lets it shrink and hands
   the overflow back to the box that is supposed to scroll. */
.acct-col { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); min-width: 0; }  /* atlas .box: 1rem apart */
/* .panel is the landing page's card. Here it is a box in a column rather than
   a card floating over a photograph, so it gives up the hero column's width
   cap and its right-hand alignment and keeps everything else. */
/* .dl-box is the same object in the download page's right-hand column -- the
   atlas's .box/.bh/.bc, a panel with a ruled heading. It shares the rules
   rather than copying them: two boxes that are meant to look alike and are
   described twice stop looking alike at the first change to one of them. */
.acct-box, .dl-box { max-width: none; justify-self: stretch; }
/* A LABEL ON A BAR, NOT A HEADING. The atlas's .box .bh h3 is 0.75rem, the
   faintest ink, tracked wide -- signage naming what is in the box, not a title
   competing with the page's own. Ours was --step-1 (18.3px at 1246px against
   the atlas's 12px) and read as a second page title in every card. The bottom
   rule stays: it stands in for the atlas's darker header bar. */
.acct-box h3, .dl-box h3 {
	font-size: var(--step--2);
	color: var(--c-ink-faint);
	/* atlas: the .bh bar pads .55rem under its own rule and the .bc body opens
	   .85rem below it. */
	margin-block-end: var(--s-3);
	padding-block-end: var(--s-2);
	border-block-end: var(--bw) solid var(--c-hair);
}

.kv { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: var(--s-1) var(--s-5); }  /* atlas .kv: .3rem .8rem */
.kv dt { color: var(--c-ink-faint); font-size: var(--step--1); }
.kv dd { margin: 0; font-family: var(--f-mono); color: var(--c-ink); font-size: var(--step--1); overflow-wrap: anywhere; }
/* Scoped, for the same reason .field-err is: `.kv dd` is a class plus an
   element and would beat a lone class, so an unqualified .kv-ok painted
   nothing and the account's status read in plain ink whatever it said. */
.kv .kv-ok   { color: var(--c-ok); }
.kv .kv-warn { color: var(--c-gold-soft); }

/* The two security forms are disclosures. Shut, the box is two buttons and a
   line; open, it is the form that was always there. No script: <details> is
   keyboard-driven and Escape-closing on its own, which is the same bargain the
   masthead menu makes. */
.acct-open + .acct-open { margin-block-start: var(--s-2); }
.acct-toggle { width: 100%; list-style: none; }
.acct-toggle::-webkit-details-marker { display: none; }
.acct-open[open] > .acct-toggle { border-color: var(--c-gold-dim); color: var(--c-gold-soft); }
.acct-form { margin-block-start: var(--s-2); }  /* atlas .inline: .6rem */
.acct-note {
	font-size: var(--step--2);
	color: var(--c-ink-dim);
	margin-block-start: var(--s-2);
	/* THE LAST WORD MUST NOT STAND ALONE. These notes are two-line sentences
	   in a narrow rail, and "E-postandan yeni PIN al" was breaking with "al"
	   by itself on the second line -- which reads as a heading, or as a link
	   that lost its text. `pretty` asks the browser to pull a word down from
	   the line above instead of leaving an orphan, and a browser that does not
	   know the keyword wraps exactly as it does today. */
	text-wrap: pretty;
}
/* Inside a box the tiles are a summary, not a headline: the hero's display
   size here would out-shout the heading above them. */
.acct-box .tiles dd { font-size: var(--step-2); }

/* A heading with something in its right-hand corner -- the orders box carries
   a link to the full list there. Wrapping is allowed: the heading and the link
   are both text and a narrow column must not push the link off the edge. */
.acct-head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--s-3);
}
.acct-head h3 { flex: 1 1 auto; }
.acct-more {
	font-size: var(--step--2);
	color: var(--c-gold-soft);
	white-space: nowrap;
}

/* The EP balance. One number, and the largest thing in its box, because it is
   the only thing in the box anybody came for. */
/* THE EP BOX'S LOWER HALF. The balance stays the big figure; what is added is
   the two things somebody actually wants beside it -- what the number is for,
   and when it last moved. */
.ep-what { font-size: var(--step--1); color: var(--c-ink-dim); margin-block-end: var(--s-3); }
.ep-last {
	display: grid;
	gap: 2px;
	padding-block: var(--s-3);
	border-block-start: var(--bw) solid var(--c-hair);
	margin-block-end: var(--s-3);
}
.ep-last-h {
	font-size: var(--step--2);
	letter-spacing: var(--ls-wide);
	text-transform: uppercase;
	color: var(--c-ink-faint);
}
.ep-last-when { font-family: var(--f-mono); font-size: var(--step--1); color: var(--c-ink); }
.ep-last-what { font-size: var(--step--1); color: var(--c-ink-dim); }
.ep-all { display: block; margin-block-start: var(--s-2); font-size: var(--step--1); }

.acct-big {
	font-family: var(--f-mono);
	font-size: var(--step-4);
	line-height: 1;
	color: var(--c-gold);
	/* atlas .msgc .sig, the other place a figure is the whole of its block:
	   .3rem. */
	margin: 0 0 var(--s-2);
}
/* "2 karakter" above the list: a number the eye should land on, set in running
   text rather than as a heading. The safebox's counter used to share this rule;
   it now lives on the jade line inside the box, as .sbx-cd. */
.acct-count {
	font-size: var(--step--1);
	color: var(--c-ink-dim);
	margin: 0 0 var(--s-3);
}
.acct-count strong { color: var(--c-ink); font-size: var(--step-1); }

/* THE CHARACTER LIST IS A GRID OF CARDS, TWO ACROSS, and each card is a
   portrait, a name with a subtitle, and a level. The atlas's .chars/.ch.

   WHY CARDS AND NOT THE ROWS THIS WAS. An account has two, three, maybe five
   characters, and they are the thing the player came to the page for. Drawn as
   hairline-separated rows they read as a settings list; drawn as cards with a
   face on each they read as the characters themselves -- which is what the
   picture is doing there, since a person recognises their own warrior before
   they have read a word.

   Two fixed columns rather than auto-fit: the box is wide on a desktop and
   auto-fit would put three or four across, which makes a card the size of a
   list row again and wastes the portrait. */
.chars {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--s-3);   /* atlas .chars: .7rem                                */
}
.ch {
	display: flex;
	align-items: center;
	gap: var(--s-3);   /* atlas .ch: .8rem                                   */
	min-width: 0;
	border: var(--bw) solid var(--c-line);
	background: var(--c-panel);
	padding: var(--s-3);  /* atlas .ch: .7rem .85rem                         */
}
/* The portrait. A background on an empty box rather than an <img>, because it
   is decoration: the class is written out in words on the very next line, so a
   picture of it carries nothing a screen reader needs and any alt text would be
   an invention. It keeps the well ground underneath, which is what an unmatched
   class is left showing. */
.ch-ic {
	inline-size: var(--sz-portrait);
	block-size: var(--sz-portrait);
	flex: 0 0 auto;
	border: var(--bw) solid var(--c-line-hi);
	background-color: var(--c-well);
	background-size: cover;
	background-position: var(--pos-portrait);
}
/* THE FOUR CLASSES, KEYED OFF THE GAME'S JOB BYTE, not off the printed name --
   see render.Character.ClassSlug. A character whose job byte is outside the
   game's table matches none of these: it keeps the empty square and the meta
   line's ordinary ink, which is the honest answer. A default face would tell a
   player their character is a class it is not.
   The paintings are the ones the sign-in and class sections already use, so the
   face on the card is the face on the poster. */
.ch-warrior  .ch-ic { background-image: url("/assets/img/class-warrior.jpg"); }
.ch-assassin .ch-ic { background-image: url("/assets/img/class-assassin.jpg"); }
.ch-sura     .ch-ic { background-image: url("/assets/img/class-sura.jpg"); }
.ch-shaman   .ch-ic { background-image: url("/assets/img/class-shaman.jpg"); }
/* The class colours the atlas gives the four classes. Set as a custom property
   on the card rather than as a colour on the word, so the card is the one place
   that knows which class it is.

   THESE FOUR RULES ARE THE SITE'S ONLY CLASS-TO-COLOUR TABLE, and the ranking
   reaches for them too: a podium card and a row of the landing page's preview
   carry the same ch-<slug> and get the same four colours out of it. A second
   table under a ranking-flavoured name would be the same decision written
   twice, and the copy that is wrong is the one nobody is looking at.

   THE SLUG IS THE JOB BYTE, NOT THE CLASS WORD. Every template writes it with
   {{classSlug .Job}} (gamename.ClassSlug), so a corrected Turkish class name
   cannot repaint the ranking, and a job number the site does not know produces
   no class at all -- the word then keeps the ordinary ink through the fallback
   in --c-class's var(), which is the honest answer. */
.ch-warrior  { --c-class: var(--c-class-warrior); }
.ch-assassin { --c-class: var(--c-class-ninja); }
.ch-sura     { --c-class: var(--c-class-sura); }
.ch-shaman   { --c-class: var(--c-class-shaman); }

.ch-who { display: grid; gap: 2px; min-width: 0; }
/* Player-chosen text, so it can be anything: it wraps rather than stretching
   the box or escaping it. */
.ch-name {
	font-family: var(--f-display);
	font-weight: var(--w-medium);
	font-size: var(--step-0);
	line-height: var(--lh-heading);
	color: var(--c-ink);
	overflow-wrap: anywhere;
}
.ch-meta {
	font-size: var(--step--2);
	color: var(--c-ink-faint);
	overflow-wrap: anywhere;
}
/* The class word, in the class's own colour. <em> in the markup because it is
   the one distinguishing word in the line; the italic it would otherwise get is
   turned off, since the colour and the caps are doing that work. The fallback
   is the ordinary meta ink, which is what an unmatched class keeps. */
.ch-class {
	font-style: normal;
	text-transform: uppercase;
	letter-spacing: var(--ls-class);
	color: var(--c-class, var(--c-ink-faint));
}
.ch-lvl {
	margin-inline-start: auto;
	font-size: var(--step--1);
	color: var(--c-gold-soft);
	white-space: nowrap;
}

/* THE STATE BADGE IN A BOX HEADING. Jade filled for the state that is unusual
   and running out -- an open safebox -- and a plain outline for the ordinary
   one, so that "shut" does not read as a warning about something being wrong.
   Atlas .box .bh .st and .st.off. */
.acct-st {
	font-family: var(--f-display);
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-tab);
	white-space: nowrap;
	padding: 0 var(--s-2);
	border: var(--bw) solid var(--c-ok-line);
	background: var(--c-ok-tint);
	color: var(--c-ok);
}
.acct-st-off {
	border-color: var(--c-line-hi);
	background: none;
	color: var(--c-ink-faint);
}
/* The open safebox: the sentence and how long is left on one jade line, so the
   counter is read as belonging to the sentence rather than as a stray number
   under it. Atlas .sbx .open. */
.sbx-open {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--s-2) var(--s-3);
	margin: 0;
	padding: var(--s-2) var(--s-3);
	border: var(--bw) solid var(--c-ok-line);
	background: var(--c-ok-tint);
	font-size: var(--step--1);
	color: var(--c-ink);
}
.sbx-cd {
	margin-inline-start: auto;
	font-family: var(--f-mono);
	font-size: var(--step--1);
	color: var(--c-ok);
	white-space: nowrap;
}
.sbx-cd strong { font-weight: var(--w-medium); }

/* The order table borrows the ranking's table, which already handles a narrow
   column by scrolling inside .table-scroll. Only the product column differs:
   it is prose and must wrap instead of widening the table. */
.orders td:nth-child(2) { overflow-wrap: anywhere; white-space: normal; }
/* THREE TONES, NOT SIX. The six order statuses are grouped into the three
   answers a player is after -- it arrived, it is on its way, it did not happen
   -- and the colours carry the group while the word beside them carries the
   detail. Six colours would hide the one row that went wrong as thoroughly as
   none would. The three are the site's existing meanings and no fourth was
   invented: jade for finished, the soft gold the account's own status row uses
   for not-settled-yet, and the red every refused form is set in. A status the
   site cannot classify carries no class here and keeps the table's ink.
   Scoped under .orders td for the same reason .kv-ok is scoped: the table's own
   `td` rule is an element inside a class and would otherwise win. */
.orders td.orders-ok   { color: var(--c-ok); }
.orders td.orders-wait { color: var(--c-gold-soft); }
.orders td.orders-bad  { color: var(--c-danger-ink); }
/* ---- LIVE BAND ---------------------------------------------------------- */

.band {
	background: var(--c-ground-2);
	border-block: var(--bw) solid var(--c-hair);
}
.band > .wrap {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--s-4);
	padding-block: var(--s-4);   /* atlas .live: 1rem above the figures     */
}
.band-cell { display: grid; gap: var(--s-1); }
.band-k {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
}
.band-v {
	font-family: var(--f-mono);
	font-size: var(--step-2);
	color: var(--c-ink);
	letter-spacing: var(--ls-tight);
	font-variant-numeric: tabular-nums;
	display: inline-flex; align-items: center; gap: var(--s-2);
}
.band-v.ok { color: var(--c-ok); }
.pulse {
	width: 0.55em; height: 0.55em; border-radius: 50%;
	background: var(--c-ok);
	animation: pulse 2s var(--ease) infinite;
}
@keyframes pulse {
	0%, 100% { box-shadow: 0 0 0 0 rgba(94,155,110,.55); }
	70%      { box-shadow: 0 0 0 0.5em rgba(94,155,110,0); }
}

/* ---- NEWS --------------------------------------------------------------- */

.filter-in { position: absolute; opacity: 0; pointer-events: none; }
#news-all:checked        ~ .tabs [for="news-all"],
#news-duyuru:checked     ~ .tabs [for="news-duyuru"],
#news-guncelleme:checked ~ .tabs [for="news-guncelleme"],
#news-etkinlik:checked   ~ .tabs [for="news-etkinlik"] {
	background: var(--c-gold-deep);
	border-color: var(--c-gold-dim);
	color: var(--c-gold-soft);
}
#news-duyuru:checked     ~ .news .news-item:not([data-tag="duyuru"]),
#news-guncelleme:checked ~ .news .news-item:not([data-tag="guncelleme"]),
#news-etkinlik:checked   ~ .news .news-item:not([data-tag="etkinlik"]) { display: none; }

.news { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); }
.news-item {
	display: grid;
	grid-template-columns: 5.5rem 1fr;
	gap: var(--s-5);
	padding: var(--s-4) var(--s-5);
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	transition: border-color var(--t) var(--ease);
}
.news-item:hover { border-color: var(--c-gold-dim); }
.news-date {
	display: grid; justify-items: center; align-content: start;
	padding-block: var(--s-2);
	border-inline-end: var(--bw) solid var(--c-hair);
}
.news-date b {
	font-family: var(--f-mono);
	font-size: var(--step-3);
	line-height: 1;
	color: var(--c-gold);
}
.news-date span { font-size: var(--step--2); color: var(--c-ink-faint); text-transform: uppercase; letter-spacing: var(--ls-wide); }
.tagx {
	display: inline-block;
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	padding: var(--s-1) var(--s-3);
	border-radius: var(--r-sm);
	margin-block-end: var(--s-2);
}
.tag-duyuru     { background: var(--c-gold-tint); color: var(--c-gold-soft); }
.tag-guncelleme { background: rgba(94,155,110,.12); color: var(--c-ok); }
.tag-etkinlik   { background: rgba(178,86,79,.14); color: var(--c-danger-ink); }
.news-item h3 { font-size: var(--step-2); margin-block-end: var(--s-1); }  /* atlas .nw h4: .15rem */
.news-item p { color: var(--c-ink-dim); font-size: var(--step--1); }

/* ---- RANK TABLE --------------------------------------------------------- */

/* min-width: 0 for the same reason as the column above: inside a grid or a
   flex line, a box whose content declares a minimum will not shrink below it
   unless it is told it may, and then it never scrolls -- it pushes the page. */
.table-scroll { overflow-x: auto; min-width: 0; }
table.rank {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--step-0);
	min-width: 40rem;
	/* A PANEL, NOT A BARE TABLE. The atlas draws .rank on the card ground with
	   a hairline around it, the same box the podium above it stands in -- and
	   ours had neither, so the table floated on the page while every other
	   block on the screen sat in something. Measured against the atlas at
	   1246px: theirs background #1C1510 + 1px #3A2A1E, ours transparent and
	   border 0. */
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
}
table.rank th {
	text-align: start;
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
	padding: var(--s-2) var(--s-4);   /* atlas .rank th: .45rem             */
	border-block-end: var(--bw) solid var(--c-line);
	white-space: nowrap;
}
table.rank td {
	padding: var(--s-2) var(--s-4);   /* atlas .rank td: .42rem             */
	border-block-end: var(--bw) solid var(--c-hair);
	color: var(--c-ink-dim);
}
/* The name is the one column a person is scanning for, so it carries the
   page's full ink and a heavier weight than the facts around it -- atlas
   .rank td.n. */
table.rank td:nth-child(2) { color: var(--c-ink); font-weight: var(--w-semibold); }
table.rank .num { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
/* A QUANTITY IS RIGHT-ALIGNED AND GOLD, and both halves of that are the
   ranking's, not every table's: the place, the level and the score are three
   columns of figures read DOWN rather than across, and ragged-left figures in
   the mono face defeat the point of setting them in it. Gold because they are
   the numbers the page exists to show; the guild beside them is context.
   :not(.orders) because the account page's purchase table borrows .rank for
   its shape only -- the atlas draws that one as its own .ord, with no gold and
   no column of places, and a right-aligned gold EP figure there would make a
   receipt look like a leaderboard. */
table.rank:not(.orders) .num { text-align: end; color: var(--c-gold-hi); }
table.rank tbody tr { transition: background var(--t-fast) var(--ease); }
table.rank tbody tr:hover { background: var(--c-gold-tint); }
/* THE VISITOR'S OWN ROW. The wash is the atlas's .rank tr.me; the gold edge
   and the word beside the name are what keep the mark legible on a screen
   where the wash cannot be seen -- and the edge is reserved as transparent on
   every other row so that marking one does not shift the column under it.
   Declared after :hover so that a row which is mine stays marked while the
   pointer is over it. */
table.rank tbody tr.rank-mine { background: var(--c-mine-tint); }
table.rank:not(.orders) tbody tr td:first-child {
	border-inline-start: var(--bw-mark) solid transparent;
}
table.rank tbody tr.rank-mine td:first-child { border-inline-start-color: var(--c-gold); }
.rank-you {
	font-family: var(--f-display);
	font-weight: var(--w-medium);
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-gold);
	/* The name it marks is player-chosen and wraps; the mark must not be left
	   stranded on a line of its own above or below it. */
	white-space: nowrap;
}
/* The podium is information, not decoration: the first three rows are what a
   ranking exists to show. */
table.rank .top1 td:first-child { color: var(--c-gold);      font-weight: var(--w-semibold); }
table.rank .top2 td:first-child { color: var(--c-gold-soft); font-weight: var(--w-semibold); }
table.rank .top3 td:first-child { color: var(--c-gold-dim);  font-weight: var(--w-semibold); }
.dot { display: inline-block; width: 0.6em; height: 0.6em; border-radius: 50%; margin-inline-end: var(--s-2); }

/* ---- SHOP --------------------------------------------------------------- */

.card-shop { position: relative; }
.price {
	margin-block-start: var(--s-3);   /* atlas .dl .meta: .85rem            */
	font-family: var(--f-mono);
	font-size: var(--step-2);
	color: var(--c-gold);
	letter-spacing: var(--ls-tight);
	font-variant-numeric: tabular-nums;
}
.price span { font-size: var(--step--2); color: var(--c-ink-faint); text-transform: uppercase; letter-spacing: var(--ls-wide); }
.note {
	/* A callout after a grid. The atlas's own callout (.warn) sits .6rem off
	   what it qualifies and pads .6rem; this one closes a whole section, so it
	   keeps a section-sized approach and takes the atlas's padding. */
	margin-block-start: var(--s-5);
	padding: var(--s-3) var(--s-5);
	background: var(--c-gold-tint);
	border-inline-start: 3px solid var(--c-gold-dim);
	border-radius: var(--r);
	color: var(--c-ink-dim);
	font-size: var(--step--1);
	max-width: none;
}

/* ---- REQUIREMENTS ------------------------------------------------------- */

.reqs {
	margin-block-start: var(--s-5);
	display: grid; gap: var(--s-4);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
}
.req {
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	padding: var(--s-4) var(--s-5);
}
.req h3 {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
	margin-block-end: var(--s-3);
}
.req dl { margin: 0; display: grid; gap: var(--s-2); }  /* atlas .req td: .42rem */
.req dl > div { display: flex; justify-content: space-between; gap: var(--s-4); }
.req dt { color: var(--c-ink-faint); font-size: var(--step--1); }
.req dd { margin: 0; color: var(--c-ink); font-size: var(--step--1); }

/* ---- REGISTER ----------------------------------------------------------- */

.reg { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: var(--s-6) var(--s-8); align-items: start; }
.reg-steps {
	list-style: none; counter-reset: s; margin: 0 0 var(--s-5); padding: 0;
	display: grid; gap: var(--s-4);   /* atlas .steps li: 1rem apart         */
}
.reg-steps li {
	counter-increment: s;
	display: grid; grid-template-columns: 2.5rem 1fr; gap: var(--s-4);
	align-items: baseline;
	color: var(--c-ink-dim);
}
.reg-steps li::before {
	content: counter(s);
	font-family: var(--f-display);
	font-size: var(--step-2);
	color: var(--c-gold-deep);
	line-height: 1;
}
.reg-steps b { color: var(--c-ink); font-weight: var(--w-semibold); }

.facts-card {
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	padding: var(--s-4) var(--s-5);
}
.facts-card h3 {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
	margin-block-end: var(--s-3);
}
.facts-card .facts { border: 0; border-radius: 0; background: none; grid-template-columns: 1fr; }
.facts-card .fact { padding: var(--s-2) 0; border-inline-end: 0; }  /* atlas .ord td: .42rem */

/* ---- DISCORD ------------------------------------------------------------
   The gold-bordered "the community lives on Discord" block used to stand here
   and the download page was its only caller. The atlas draws that offer as an
   ordinary box in the page's right-hand column instead -- see .dl-box -- so a
   second, louder box competing with the page's one gold button is gone, and
   the rules that drew it went with it. */

/* ---- MENU (disclosure, no script) --------------------------------------
   Wide: the panel is always open and the toggle is gone, so <details> costs
   nothing on desktop. Narrow: it becomes a drop panel under the bar.

   <details> rather than a hidden checkbox: the browser already gives it a
   toggle role, keyboard operation and an open/closed state a screen reader can
   announce, all of which the checkbox trick has to fake. And the launch page
   ships no JavaScript -- a menu that needs a script is a menu that fails while
   the script is still in flight, on exactly the connections where it matters.*/

.menu { margin-inline-start: auto; }
/* THE WHOLE DESKTOP NAVIGATION DEPENDS ON THIS ONE LINE. A closed <details>
   now hides its contents through ::details-content { content-visibility:
   hidden } in the user-agent sheet (Chrome 131+, and the rest are following),
   and content-visibility does not care that .main below sets display:flex --
   so on a wide screen, where the disclosure is deliberately left closed and
   its toggle removed, every link in the masthead rendered into nothing.
   Measured in Chrome 152: brand and beta chip visible, nav gone.
   Browsers that do not know the pseudo-element drop the rule and were never
   affected in the first place. */
.menu::details-content { content-visibility: visible; }
.menu > summary { display: none; }        /* wide: no toggle */
.menu > .main { display: flex; align-items: center; gap: var(--s-5); }
.menu > .main a:not(.btn) {
	font-size: var(--step--1);
	color: var(--c-ink-dim);
	letter-spacing: var(--ls-tight);
	white-space: nowrap;
	transition: color var(--t-fast) var(--ease);
}
.menu > .main a:not(.btn):hover { color: var(--c-ink); }

/* The account name and its badge are one link. Padding rather than bare text
   so the target is a target: the pair used to be two spans beside a button and
   the words themselves did nothing. */
.who-link {
	display: inline-flex;
	align-items: center;
	gap: var(--s-2);
	padding: var(--s-1) var(--s-2);
	border-radius: var(--r-sm);
	text-decoration: none;
	color: inherit;
}
.who-link:hover { background: var(--c-raise); }
.who-link:hover .who { color: var(--c-ink); }
.who { font-size: var(--step--1); color: var(--c-ink-dim); }
/* The initial beside the name. A circle rather than an avatar because there is
   no picture to show and there never will be -- the game has no profile image
   -- and a grey silhouette would be a promise of one. Fixed size in both
   directions so a wide letter cannot stretch it into an egg. */
.who-badge {
	flex: none;
	inline-size: 1.75rem;
	block-size: 1.75rem;
	display: inline-grid;
	place-items: center;
	border-radius: 50%;
	border: var(--bw) solid var(--c-gold-dim);
	background: var(--c-ground-2);
	color: var(--c-gold-soft);
	font-size: var(--step--1);
	line-height: 1;
}
.inline { display: inline; margin: 0; }

/* ---- THE FOUR CLASSES ---------------------------------------------------
   Four paintings from the client, each with its name and one line under it.
   The caption sits ON the picture rather than under it: the paintings are
   full-bleed portraits and a caption bar below them would cut each card in
   two, which is what makes a class list read as a product grid. */

.class-grid {
	list-style: none; margin: 0; padding: 0;
	display: grid;
	gap: var(--s-4);
	grid-template-columns: repeat(4, minmax(0, 1fr));
}
.class-card {
	position: relative;
	overflow: hidden;
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	background: var(--c-panel);
	/* The plates are 440x600. Stating the ratio here means the row does not
	   jump when the pictures arrive. */
	aspect-ratio: 11 / 15;
	transition: border-color var(--t) var(--ease), transform var(--t) var(--ease);
}
.class-card:hover { border-color: var(--c-gold-dim); transform: translateY(-2px); }
.class-card img {
	position: absolute; inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
	object-position: 50% 18%;
}
.class-cap {
	position: absolute; inset-inline: 0; inset-block-end: 0;
	padding: var(--s-3) var(--s-4) var(--s-4);   /* atlas .card .cap        */
	background: linear-gradient(180deg, var(--c-veil-0) 0%, var(--c-veil-2) 45%, var(--c-veil-3) 100%);
}
/* THE CAPTION IS THE LINK, and the whole caption rather than just the name:
   the card already behaved like something clickable -- it lifts on hover -- and
   for a long time it was not. A link the size of the caption is a target a
   finger finds; a link the size of the word is one it misses.

   The picture stays OUTSIDE the anchor in the markup -- its alt is empty
   because the name is right there, and wrapping a decorative image in the link
   would give a screen reader a second, nameless copy of the same destination.
   It is still clickable: see .class-link::after below. */
.class-link { display: block; color: inherit; text-decoration: none; }
.class-link:hover { color: inherit; }
/* THE WHOLE CARD IS THE TARGET, not just the words. The picture is the obvious
   thing to click and it was the one part that did nothing: the anchor wrapped
   only the caption, so a visitor aiming at the painting hit nothing and
   concluded the cards were decoration.
   Stretched with a pseudo-element rather than by moving the <img> inside the
   anchor, so the link keeps exactly one accessible name -- the class name -- and
   a screen reader is not read a second, nameless copy of the same destination.
   The card is already position:relative; the bar drawn by ::before sits at
   z-index 1, so this goes above it. */
.class-link::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 2;
}
.class-name {
	display: block;
	font-family: var(--f-display);
	font-weight: var(--w-semibold);
	font-size: var(--step-2);
	line-height: var(--lh-heading);
	letter-spacing: var(--ls-head);
	text-transform: uppercase;
	margin-block-end: var(--s-1);
}
.class-tactic { display: block; font-size: var(--step--1); color: var(--c-ink-dim); }
/* Keyboard and mouse reach the same state. Without :focus-within a keyboard
   user tabbing through four cards would see nothing move. */
.class-card:focus-within { border-color: var(--c-gold-dim); transform: translateY(-2px); }
/* The class's own colour, as a rule along the top edge -- the same four colours
   the ranking rows and the character cards draw from, used here for the first
   time. Drawn on the card rather than on the picture so it survives a slow
   image. */
.class-card::before {
	content: "";
	position: absolute; inset-inline: 0; inset-block-start: 0;
	block-size: var(--h-class-bar);
	background: var(--c-class, transparent);
	z-index: 1;
}

/* ---- RANKING + NEWS, SIDE BY SIDE ---------------------------------------
   Both halves are previews of pages that already exist, so each carries its
   own link out and neither tries to be the full list. Either half is drawn
   only when its source answered -- see templates/home.html. */

.duo {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
	/* Row gap to the atlas's .two (1.8rem); the column gutter stays. */
	gap: var(--s-6) var(--s-7);
	align-items: start;
}
/* THE RANKING COLUMN IS THE WIDER ONE. The atlas's .two is 1.1fr .9fr, not two
   halves, and the ratio is doing work rather than decorating: the ranking row
   carries a place, a colour, a name, a class, a guild and a level on one line
   and the news entry carries a heading over a sentence that can wrap. Split
   down the middle, the ranking is the column that runs out of room first.
   896px, not the width the auto-fit itself folds at: the two are close enough
   that at the fold the ratio would be deciding the number of columns as well
   as their sizes, and a stated ratio has no fallback to one column.

   EITHER HALF MAY BE ABSENT. The template draws a column only when its own
   source answered, so a failed news read leaves the ranking alone in a grid
   that has been told it has two columns -- and it would sit in 55% of the row
   with the rest of it empty. :only-child is that case, and it takes the whole
   width. */
@media (min-width: 56rem) {
	.duo { grid-template-columns: 1.1fr 0.9fr; }
	.duo > .duo-col:only-child { grid-column: 1 / -1; }
}
.duo-col { min-width: 0; }
.duo-head {
	display: flex; align-items: baseline; gap: var(--s-4);
	margin-block-end: var(--s-4);   /* atlas .hd: .9rem                     */
	padding-block-end: var(--s-2);  /* atlas h2.sec: .45rem                 */
	border-block-end: var(--bw) solid var(--c-hair);
}
.duo-head h2 { font-size: var(--step-3); margin: 0; }
.duo-more { margin-inline-start: auto; font-size: var(--step--1); white-space: nowrap; }
.duo-note { font-size: var(--step--2); color: var(--c-ink-faint); margin-block-start: var(--s-4); }

/* A FLEX LINE, NOT A GRID OF COLUMNS, and the atlas's .lst is why. The row is
   a place, a colour, a name with its class beside it, then whatever is left
   pushed to the right -- the guild and the level. A grid would give the class
   word a column of its own and leave a ragged gap after every short class
   name; in a line it sits against the name it belongs to, which is what makes
   "Kızılbörü SAVAŞÇI" read as one thing. */
.mini-rank { list-style: none; margin: 0; padding: 0; }
.mini-rank li {
	display: flex;
	align-items: center;
	gap: var(--s-3);                /* atlas .lst .r: .75rem                */
	padding-block: var(--s-2);      /* atlas .lst .r: .5rem                 */
	padding-inline: var(--s-2);
	border-block-end: var(--bw) solid var(--c-hair);
	/* The mark on the visitor's own row takes this border, so the space for
	   it is reserved on EVERY row -- otherwise the one marked row would be two
	   pixels wider than the rest and the whole list would step sideways at it. */
	border-inline-start: var(--bw-mark) solid transparent;
}
.mini-rank li:last-child { border-block-end: 0; }
.mini-pos {
	font-family: var(--f-mono);
	font-size: var(--step-1);
	color: var(--c-gold);
	font-variant-numeric: tabular-nums;
	/* Right-aligned in a fixed column, so two- and three-figure places line up
	   under each other instead of pushing the names apart -- see --w-rank-pos. */
	inline-size: var(--w-rank-pos);
	flex: 0 0 auto;
	text-align: end;
}
/* THE CLASS AS A SHAPE. A short rule in the class's own colour down the left
   of the name -- the one mark in the row that is visible at a glance from the
   other side of the list. Decorative on its own (the class word beside it says
   the same thing in words), so it is hidden from a screen reader in the
   markup. A class the site cannot place falls back to the row's own hairline
   rather than borrowing another class's colour. */
.mini-bar {
	flex: 0 0 auto;
	inline-size: var(--bw-class);
	block-size: var(--h-class-bar);
	background: var(--c-class, var(--c-line-hi));
}
.mini-name { color: var(--c-ink); overflow-wrap: anywhere; min-width: 0; }
/* The class word, in the class's own colour and tracked out like the one on a
   character card -- it is the same word doing the same job, so it is set the
   same way. Caps rather than sentence case because at this size, beside a
   name in the body face, the lower case version reads as part of the name. */
.mini-class {
	flex: 0 0 auto;
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-class);
	color: var(--c-class, var(--c-ink-faint));
}
.mini-guild {
	/* Everything after this is pushed to the right-hand end of the row. */
	margin-inline-start: auto;
	font-size: var(--step--1);
	color: var(--c-ink-faint);
	overflow-wrap: anywhere;
}
/* ---- THE VISITOR'S OWN ROW -----------------------------------------------
   COLOUR IS THE QUIET HALF OF THIS MARK. The wash and the gold edge are what
   catch the eye scanning the list; the word is what the mark says, and it is
   the half that still works for somebody who cannot tell the washed row from
   the others. Same pair of signals, and the same reasoning, as a rejected
   form field further up this file. */
.mini-rank li.mini-me {
	background: var(--c-mine-tint);
	border-inline-start-color: var(--c-gold);
}
.mini-you {
	flex: 0 0 auto;
	font-family: var(--f-display);
	font-weight: var(--w-medium);
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-gold);
}
/* A character's level and the date on a news row are quantities as much as a
   score is, and the atlas sets both in the mono face. They are listed with
   .mini-lv rather than given rules of their own because they are the same
   decision made once. */
.ch-lvl, .newsrow-meta time, .news-item time { font-family: var(--f-mono); }
/* The date sits inside the meta line and would otherwise inherit its label
   tracking. A monospaced figure is already as wide as it is going to get;
   tracked out on top of that it stops reading as one date. */
.newsrow-meta time, .news-item time { letter-spacing: normal; }
.mini-lv {
	flex: 0 0 auto;
	/* A fixed end column is what keeps the levels in a straight line whatever
	   the names in front of them do -- see --w-rank-lv. */
	inline-size: var(--w-rank-lv);
	text-align: end;
	font-family: var(--f-mono);
	font-variant-numeric: tabular-nums;
	color: var(--c-gold-hi);
	font-size: var(--step--1);
}

/* atlas .nw: 1.1rem between one entry and the next, and a quarter of that
   inside one. */
.mini-news { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); }
.mini-news li { display: grid; gap: var(--s-1); }
.mini-top { display: flex; align-items: center; gap: var(--s-3); }
.mini-top .tagx { margin-block-end: 0; }
.mini-top time { font-size: var(--step--2); color: var(--c-ink-faint); }
.mini-news h3 { font-size: var(--step-1); }
.mini-news p { font-size: var(--step--1); color: var(--c-ink-dim); }

/* ---- DOWNLOAD CALL ------------------------------------------------------ */

.dl-call > .wrap { display: grid; justify-items: center; gap: var(--s-4); text-align: center; }
.dl-call h2 { font-size: var(--step-3); }
.dl-call p { color: var(--c-ink-dim); }
.dl-call .btn { margin-block-start: var(--s-2); }
.dl-meta { font-size: var(--step--1); color: var(--c-ink-faint); }

/* ---- RESPONSIVE ---------------------------------------------------------
   Three breakpoints mirroring the prototype's 1040 / 820 / 520 px, written in
   rem so they scale with a reader who has enlarged their default font size.
   A px breakpoint ignores that reader completely. */

/* 1040px -- the hero stops being a two-column composition. */
@media (max-width: 65rem) {
	.hero-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
	/* One column: the pair stops hugging the right edge and centres, so the
	   figures sit over the card instead of over the page margin. */
	.hero-side { justify-items: center; justify-self: center; max-width: 26rem; }
	/* SCOPED TO THE HERO. These three widths are about the card standing in
	   the landing page's second column; the same .panel is also the sign-in
	   card and every box on the account page, and an unscoped rule here
	   shrank those to 25rem and shoved them left. */
	.hero-side .panel { justify-self: start; max-width: 25rem; }
	.reg { grid-template-columns: 1fr; gap: var(--s-5); }
	/* THE ACCOUNT PAGE GIVES UP ITS SECOND COLUMN HERE, not at the menu
	   breakpoint. Two columns at 1024 leave each one 410px wide inside its
	   panel, and the order table needs 448 -- so the status column sat outside
	   the box at every width between 820 and 1040 with nothing to say so.
	   Measured: 40px hidden at 1024. At 1440 the column is 543px and the table
	   fits, which is why the desktop layout is untouched. */
	.acct { grid-template-columns: minmax(0, 1fr); }
	.band > .wrap { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.hero h1 { max-width: min(100%, 30ch); }
	.facts   { grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); }
	/* Four across stops working before the hero does: at this width each
	   painting is under 200px and the four faces stop being distinguishable. */
	.class-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--w-class)), 1fr)); }
}

/* 820px -- the bar's links collapse into the disclosure. */
/* 820px -- THE BAND CHANGES JOB. Above this width it is a backdrop and the
   words sit on its dark left side. Below it there is no dark left side to sit
   on: the section is one column, so the picture becomes a banner across the
   top and the text starts underneath it, on the page's own ground where it is
   always readable. One file at both widths, cropped rather than swapped: the
   picture a visitor sees on a phone must be the one they saw on a desktop. */
@media (max-width: 51.25rem) {
	.hero {
		min-height: 0;
		align-content: start;
		padding-block: calc(var(--bar-h) + 46vw + var(--s-5)) var(--s-7);
	}
	.hero::before {
		inset: var(--bar-h) 0 auto 0;
		height: 46vw;
		max-height: 17rem;
		background-position: 50% 30%;
	}
	.hero::after {
		/* Only the banner's own bottom edge needs dissolving now; the wide
		   layout's left-hand curtain would just grey out the picture. */
		inset: var(--bar-h) 0 auto 0;
		height: calc(46vw + 3rem);
		max-height: 20rem;
		background:
			linear-gradient(180deg, var(--c-veil-1) 0%, var(--c-veil-0) 34%,
			                        var(--c-veil-3) 78%, var(--c-ground) 100%);
	}
	.hero-side { justify-self: stretch; max-width: none; }
	.hero-side .panel { max-width: none; }
	/* One column means the button and the card are the same column, one under
	   the other. The desktop spacing between them was a gutter between two
	   columns; kept here it reads as a hole. */
	.hero-grid { gap: var(--s-5); }

	.menu > summary {
		display: block;
		list-style: none;
		cursor: pointer;
		border: var(--bw) solid var(--c-line);
		border-radius: var(--r);
		padding: var(--s-3);
		color: var(--c-ink);
		line-height: 0;
	}
	.menu > summary::-webkit-details-marker { display: none; }
	/* Three rules drawn with borders instead of an icon font or an SVG: fewer
	   bytes, and it inherits the text colour including on focus. */
	.menu > summary > span {
		display: block; width: 1.25rem; height: 2px;
		background: currentColor;
		box-shadow: 0 6px 0 currentColor, 0 -6px 0 currentColor;
	}
	.menu[open] > summary > span { box-shadow: none; transform: rotate(45deg); }
	.menu[open] > summary > span::after {
		content: ""; display: block; width: 1.25rem; height: 2px;
		background: currentColor; transform: rotate(-90deg);
	}

	.menu > .main { display: none; }
	.menu[open] > .main {
		display: flex;
		flex-direction: column;
		align-items: stretch;
		gap: var(--s-4);
		position: absolute;
		inset-inline: 0;
		inset-block-start: var(--bar-h);
		background: var(--c-ground-2);
		border-block-end: var(--bw) solid var(--c-line);
		padding: var(--s-5) var(--gutter);
		box-shadow: var(--sh-2);
	}
	.menu[open] > .main a:not(.btn) { font-size: var(--step-0); }

	/* THE PAINTING BECOMES A BANNER. Beside a one-column form there is no
	   column left for it to stand in, and a portrait plate squeezed into a
	   third of a phone screen is a crop of a shoulder. It goes across the top
	   at a landscape crop, the form starts underneath it on the page's own
	   ground, and it stops being sticky -- a picture pinned to the top of a
	   phone screen is a picture covering the form. */
	.auth, .auth-mirror { grid-template-columns: minmax(0, 1fr); }
	.auth { min-height: 0; }
	.auth-art, .auth-mirror .auth-art {
		position: static;
		height: 40vw;
		max-height: 15rem;
		border-inline: 0;
		border-block-end: var(--bw) solid var(--c-hair);
		order: -1;
	}
	.auth-art img { object-position: 50% 8%; }
	/* Only the bottom edge needs dissolving now; the side curtain would grey
	   out the picture rather than the ground under the form. */
	.auth-art::after, .auth-mirror .auth-art::after {
		background: linear-gradient(180deg, var(--c-veil-0) 0%, var(--c-veil-1) 55%, var(--c-veil-3) 100%);
	}
	.auth-body { min-height: 0; padding-block: var(--s-6); }
	.auth-card { max-width: none; }

	.acct { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }

	/* .steps is no longer among these: it is a vertical track at every width,
	   so there is no column count left to collapse. */
	.rates, .reqs { grid-template-columns: 1fr; }
	/* No narrow-screen reduction for .section any more: --s-section already
	   bottoms out at the atlas's shortest band (1.9rem) on a phone, and the
	   3.5rem that used to stand here is now LARGER than the desktop value. */
	.class-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.duo { gap: var(--s-5); }
	/* The ornament is a rule, not a subject: on a phone it takes the same
	   height as the one under the masthead rather than a third of the gap
	   between two sections. */
	.orn { height: var(--h-key); background-size: auto var(--h-key); }
	.news-item { grid-template-columns: 4rem 1fr; gap: var(--s-4); }
	.news-date { border-inline-end: 0; justify-items: start; }
}

/* 520px -- one column throughout; the two hero actions become full-width so
   neither is a thumb-stretch on a phone. */
@media (max-width: 32.5rem) {
	.facts { grid-template-columns: 1fr; }
	.fact  { border-inline-end: 0; }
	.hero h1 { max-width: none; }
	/* Phone: the drawing keeps its place but gives up height to the form
	   below it -- the panel is what the page is asking the visitor to use. */
	.actions { flex-direction: column; align-items: stretch; }
	.actions .btn { width: 100%; }
	.band > .wrap { grid-template-columns: 1fr; }
	/* Every card loses a step of padding on a phone; only the hero's loses its
	   width cap, because only the hero's had one that meant anything here. */
	.panel { padding: var(--s-4); }
	.hero-side .panel { max-width: none; }
	.auth-card { padding: var(--s-4); }
	.news-item { grid-template-columns: 1fr; }
	.news-date { flex-direction: row; display: flex; gap: var(--s-2); align-items: baseline; }
	.news-date b { font-size: var(--step-2); }
	.tabs { flex-wrap: wrap; }
	/* One painting per row rather than two postage stamps. */
	.class-grid { grid-template-columns: 1fr; }
	.class-card { aspect-ratio: 4 / 3; }
	/* A landscape crop of a portrait plate cuts the head off unless the frame
	   is pulled almost to the top of the picture. */
	.class-card img { object-position: 50% 4%; }
	/* The ranking row's phone shape is set further down, with the rest of the
	   phone layout -- see "THE RANKING ROW FOLDS IN TWO". */
	.tiles { gap: var(--s-5); }
	.dl-call .btn { width: 100%; }
}

/* A coarse pointer gets a real target regardless of viewport width: a 24px
   link is a miss on a phone even when the layout around it is wide. */
@media (pointer: coarse) {
	.menu > .main a { padding-block: var(--s-2); }
}

/* ====================================================================   RANKING AND NEWS PAGES
   Appended rather than merged into the blocks above: the classes here belong
   to /ranking, /news and /news/<slug> only, and the landing page's own
   ranking preview and news strip keep the older ones. Sharing them would mean
   a change made for one page silently redrawing the other.
   =========================================================================== */

.rank-when { color: var(--c-ink-dim); font-size: var(--step--1); }

/* ---- podium ---------------------------------------------------------------
   Second, first, third -- in that order in the MARKUP, because that is the
   reading order of a podium and CSS ordering would leave a screen reader
   hearing 1, 2, 3 in three boxes of different heights for no reason.
   The list numbers are drawn from the data, so the ordered list's own markers
   are suppressed: they would count 1, 2, 3 down a row that reads 2, 1, 3. */
.podium {
	list-style: none;
	margin: 0 0 var(--s-3);         /* atlas .podium: .7rem                 */
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--s-3) var(--s-4);
	align-items: end;
}
.podium-card {
	/* relative because the class's colour is drawn as a rule ACROSS THE TOP of
	   the card rather than beside the class word -- see ::before below. */
	position: relative;
	display: grid;
	gap: var(--s-1);
	justify-items: center;
	text-align: center;
	padding: var(--s-3);            /* atlas .pod: .9rem .8rem .8rem        */
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	/* The rule is drawn inside the border radius rather than over it. */
	overflow: hidden;
}
/* THE CLASS COLOUR ACROSS THE HEAD OF THE CARD. The atlas gives a podium card
   no coloured word and no coloured border -- it gives it a band, which is what
   lets three cards side by side be told apart before a single word is read.
   Decorative and drawn by the stylesheet, so there is nothing here for a
   screen reader to find; the class word inside the card is the text version.
   A card whose class the site could not place carries no band at all: the
   fallback is the ground it is drawn on rather than another class's colour. */
.podium-card::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: var(--bw-class);
	background: var(--c-class, transparent);
}
/* The winner's card is the tall one. A podium where all three are the same
   height is three cards. */
/* The atlas gives the winner no extra height at all -- only a gradient. The
   site keeps one step of it, because its podium is not bottom-aligned against
   a table the way the atlas's is. */
.podium-1 { padding-block: var(--s-4); border-color: var(--c-gold-dim); box-shadow: var(--sh-1); }
.podium-pos {
	font-family: var(--f-display);
	font-weight: var(--w-bold);
	font-size: var(--step-3);
	line-height: var(--lh-tight);
	color: var(--c-ink-faint);
}
.podium-1 .podium-pos { color: var(--c-gold); }
.podium-2 .podium-pos { color: var(--c-gold-soft); }
.podium-3 .podium-pos { color: var(--c-gold-dim); }
.podium-name {
	font-size: var(--step-1);
	font-weight: var(--w-semibold);
	color: var(--c-ink);
	/* A player picks this name and it can be long. It wraps rather than
	   pushing the three columns out of shape. */
	overflow-wrap: anywhere;
}
/* The class word in the class's own colour, tracked out and in caps -- the
   atlas's .pod .cl. The fallback is the ink a class the site cannot place
   keeps, which is the same fallback the character card uses. */
.podium-class {
	color: var(--c-class, var(--c-ink-dim));
	font-size: var(--step--1);
	text-transform: uppercase;
	letter-spacing: var(--ls-class);
}
/* THE LEVEL LINE IS A SENTENCE, NOT A LABEL, so it is not shouted. It reads
   "Sv 99 · 21 gün" -- a number, a separator and a word -- and putting it
   through uppercase turned the one lower-case word in it ("gün") into part of
   a run of caps that the eye reads as a heading over the card rather than as a
   fact inside it. The atlas sets .pod .lv in the mono face at ordinary case,
   and that is what this is. */
.podium-meta {
	color: var(--c-ink-dim);
	font-family: var(--f-mono);
	font-size: var(--step--1);
	font-variant-numeric: tabular-nums;
	margin-block-start: var(--s-1);  /* atlas .pod .lv: .35rem              */
}

/* An em dash standing in for a value nobody has: a guildless player, an empty
   ranking. Dimmed so a column of them does not read as content. */
.dash { color: var(--c-ink-faint); }

/* ---- empty states --------------------------------------------------------- */
.empty {
	text-align: center;
	padding: var(--s-6) var(--s-4);   /* atlas .empty: 2.4rem               */
	border: var(--bw) dashed var(--c-line);
	border-radius: var(--r);
}
/* CENTRED LIKE THE LINE UNDER IT. text-align on .empty centres the words
   inside each paragraph, not the paragraph inside the box -- and the global
   p{max-width:measure} makes that box narrower than the panel, so without an
   auto margin the heading sat left of the sentence below it and the pair
   looked broken. */
.empty-head {
	margin-block-start: var(--s-2);
	margin-inline: auto;
	max-width: var(--measure);
	font-size: var(--step-1);
	color: var(--c-ink);
}
.empty-body {
	margin-block-start: var(--s-1);   /* atlas .empty h4: .2rem under it    */
	margin-inline: auto;
	max-width: var(--measure);
	color: var(--c-ink-dim);
	font-size: var(--step--1);
}

/* ---- news list ------------------------------------------------------------ */
.newslist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); }
.newsrow {
	padding: var(--s-4) var(--s-5);
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	transition: border-color var(--t-fast) var(--ease);
}
.newsrow:hover { border-color: var(--c-gold-dim); }
.newsrow-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--s-3);
	margin-block-end: var(--s-2);
	color: var(--c-ink-faint);
	font-size: var(--step--2);
	letter-spacing: var(--ls-wide);
	text-transform: uppercase;
}
.newsrow-title { font-size: var(--step-2); margin-block-end: var(--s-1); }
.newsrow-title a { color: var(--c-ink); text-decoration: none; }
.newsrow-title a:hover { color: var(--c-gold-hi); }
.newsrow-sum { color: var(--c-ink-dim); font-size: var(--step--1); max-width: var(--measure); }
.newsrow-more { margin-block-start: var(--s-2); font-size: var(--step--1); }
.newsrow-more a { color: var(--c-gold-soft); text-decoration: none; }
.newsrow-more a:hover { color: var(--c-gold-hi); }

/* ---- one post ------------------------------------------------------------- */
/* atlas .art-h .back: 1rem; .art-b opens 1.2rem below what precedes it. */
.back { font-size: var(--step--1); margin-block-end: var(--s-4); }
.back-end { margin-block: var(--s-5) 0; }
.back a { color: var(--c-gold-soft); text-decoration: none; }
.back a:hover { color: var(--c-gold-hi); }
.post { max-width: var(--w-narrow); }
.post-title {
	font-family: var(--f-display);
	font-size: var(--step-3);
	line-height: var(--lh-heading);
	letter-spacing: var(--ls-tight);
	margin-block-end: var(--s-5);
}
/* pre-line, not <br>. The body arrives from the database as plain text and is
   printed as element text; keeping its line breaks in CSS means the template
   never has to build markup out of that string. */
.post-body {
	white-space: pre-line;
	color: var(--c-ink);
	font-size: var(--step-0);
	line-height: var(--lh-body);
	max-width: var(--measure);
	overflow-wrap: anywhere;
}

@media (max-width: 40rem) {
	/* Three podium cards side by side on a phone are three slivers. Stacked,
	   the winner still leads because it is first in the column. */
	.podium { grid-template-columns: 1fr; align-items: stretch; }
	.podium-1 { order: -1; }
	.podium-card { padding-block: var(--s-2); }
	.podium-1 { padding-block: var(--s-3); }
}

/* The hero's counters, when there are four of them.
   The signed-in hero carries character count, best level, rank and EP, and at
   the column's width those four plus the wider gap come to 670px in a 649px
   column -- so EP dropped to a second row on its own with a hole beside it.
   A tighter column gap here, and only here, keeps the four on one line; the
   row gap stays wide so a genuinely narrow screen still separates them. */
.hero .tiles { column-gap: var(--s-5); }

/* The orders table is not the ranking table, and it should not inherit the
   ranking's 40rem minimum. It has four short columns -- a date, a name, a
   number and a word -- and it lives in the account page's narrower right
   column: at 1920 the box is 536px wide and a 640px minimum meant the last
   column, "Durum", was off the edge at EVERY window width. Measured before:
   box 536 / table 640, 104px hidden, the status column never once visible.
   28rem is what the four columns actually need. */
table.rank.orders { min-width: 28rem; }
/* ---- THE MESSAGE BAND ----------------------------------------------------
   THE ENDING OF EVERY FLOW IS ONE SCREEN, and it is not a section. A section
   is a band of content in a page of bands: full width, left-aligned, a heading
   over a paragraph. These pages have no page around them -- there is one
   sentence and a way out, and the atlas draws them as a centred column
   standing in a band of its own. Drawn as a section they came out as a title
   pinned to the left edge of a 1440px window with nothing beside it.

   Used by the message template and by 404, which is the same screen with a
   numeral where the mark goes. */
.msg-page {
	/* The masthead is ADDED to the band's height rather than taken out of it.
	   The atlas measures 400px of room around the column on a page whose nav
	   is in the flow; ours is pinned over the top of <main>, so asking for a
	   flat 400px would have spent a third of the band on empty chrome and left
	   the column sitting high. Same arithmetic .auth uses.

	   IT ALSO USED TO ASK FOR THE WHOLE WINDOW -- max(..., 100svh) -- and that
	   half of the rule was there only because the site had no footer. The band
	   was the LAST thing in the document, so at 400px on a tall window it
	   stopped a third of the way down and left the body's own ground showing
	   below it; the band carries its own plate and wash, so that edge read as a
	   seam across the screen rather than as the end of the page.
	   WITH A FOOTER UNDER IT THE SAME RULE IS THE FAULT: a band the height of
	   the window plus a footer is taller than the window, so the footer would be
	   pushed off the bottom of every ending screen. Filling the window is now
	   the column's job -- `main > :last-child { flex-grow: 1 }` at the top of
	   this file hands the leftover height to whatever band ends the page -- and
	   that fills the screen without claiming a height. So the measurement here
	   goes back to the atlas's own. */
	min-height: calc(var(--h-msg) + var(--bar-h) + var(--h-key));
	display: grid;
	place-items: center;
	/* The band pays for the pinned masthead itself, the way .auth and the hero
	   do: it is the first thing in <main> and there is no section padding
	   above it to hide behind. */
	padding-block: calc(var(--bar-h) + var(--h-key) + var(--s-6)) var(--s-6);
	padding-inline: var(--gutter);
	background: var(--g-msg), var(--c-well);
	border-block-start: var(--bw) solid var(--c-hair);
}
.msg-card { max-width: var(--w-msg); text-align: center; }
/* The heading is a NAME of an outcome ("Hesabın hazır"), not a section head,
   so it keeps its mixed case -- .section h2's capitals are not inherited here
   because this is not a section. */
.msg-card h1 {
	font-size: var(--step-3);
	letter-spacing: var(--ls-tight);
	margin-block-end: var(--s-2);   /* atlas .msgc h1: .5rem                */
}
/* THE SENTENCE IS NAMED RATHER THAN MATCHED AS `.msg-card p`. Four of the
   things in this column are paragraphs -- the kicker, the mark, the numeral
   and the sentence -- and a type selector on the parent outranks the class on
   each of them: written as `.msg-card p` this rule painted the 404's numeral
   in body ink and pushed the tick a line away from its heading. */
.msg-body {
	color: var(--c-ink-dim);
	max-width: var(--measure-msg);
	margin-inline: auto;
	margin-block-end: var(--s-5);   /* atlas .msgc p: 1.3rem                */
}
/* The kicker is gold here rather than the section head's faint ink. It is the
   only thing above the mark and it has to read as a label of the flow the
   visitor is in, not as a stray line of body text. */
.msg-card .kicker { color: var(--c-gold); letter-spacing: var(--ls-kicker); }
.msg-card .actions { justify-content: center; }
/* A <button class="btn"> and an <a class="btn"> do not come out the same
   height: the link inherits the body's 1.6 line height and the button element
   defaults to `normal`, about 1.2. Elsewhere the two never stand together, so
   nobody can see it; on the expired-link ending the resend submit sits
   directly above the actions row, and 6px between two controls of the same
   rank reads as a mistake rather than as a hierarchy. Scoped to this card --
   evening the two out site-wide is a separate change to every screen. */
.msg-card .btn { line-height: var(--lh-body); }

/* The 404's numeral. It stands where the tick or the cross stands on every
   other ending, so it is a sibling of .msg-mark rather than a thing of its
   own -- and it is set in the deep gold the atlas uses for its ghost numerals,
   not in the live gold: a number that large in the accent colour reads as the
   page's headline, and the headline is the sentence under it.
   Line height stays above 1: the display face's figures are taller than their
   em box and a line height of exactly 1 shears their tops off. */
.nf-code {
	font-family: var(--f-display);
	font-size: var(--step-6);
	font-weight: var(--w-bold);
	line-height: 1.15;
	letter-spacing: var(--ls-tight);
	color: var(--c-gold-deep);
	margin-block-end: var(--s-1);   /* atlas .msgc .sig: .3rem              */
}
/* ---------------------------------------------------------------------------
   The message page's mark, and the two rows of buttons that follow it.

   Every value here is a token. A raw colour would put the site's idea of
   "succeeded" in two places -- tokens.css and this rule -- and the two drift
   the first time one of them is adjusted. */
.msg-mark { margin: 0 0 var(--s-1); line-height: 1; }
/* step-4 ("big number"), not step-6: the mark sits above a heading, and the
   numeral's size would make it larger than the sentence it is marking. */
.msg-glyph { display: block; font-size: var(--step-4); }
/* The same green the account page uses for a verified status and the same red
   a rejected form's banner uses. A third pair invented here would teach a
   player that this page's colours mean something else. */
.msg-mark-ok .msg-glyph  { color: var(--c-ok); }
.msg-mark-bad .msg-glyph { color: var(--c-danger-ink); }

/* The resend form, INSIDE the centred column rather than beside it. Narrow on
   purpose: it holds one box, and a box stretched across the column reads as a
   search field rather than as the one thing the page is asking for. The label
   goes back to reading-order alignment -- a centred column does not make a
   centred form label, it makes a label nobody can line up with its box. */
.msg-form {
	max-width: 24rem;
	margin-inline: auto;
	margin-block-end: var(--s-4);   /* atlas .f.narrow: 1rem                */
	text-align: start;
}
/* The submit is the page's one action, so it is the same control the buttons
   below it are -- the atlas draws it in its own .acts row at the large size.
   Left as a grid item it stretched to the form's full 24rem and came out a
   third shorter than every other button on the screen: one page, three button
   heights. Centred and auto-width, it is the button the atlas draws. */
.msg-form > .btn { justify-self: center; }
/* The same 520px breakpoint the actions row uses, and it has to be written
   here rather than up there with the rest of that query: both rules weigh the
   same, so the one further down the file wins whatever the media query says.
   On a phone the buttons below this one are a stack of full-width controls,
   and a narrow one among them is the odd one out. */
@media (max-width: 32.5rem) {
	.msg-form > .btn { justify-self: stretch; }
}
.msg-actions { margin-block-start: var(--s-5); }

/* Submit and give-up, side by side, wrapping rather than overflowing on a
   narrow column. Used by both forms on the account page. */
.form-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }
/* ---- DOWNLOAD PAGE ------------------------------------------------------
   Added at the end of the file on purpose: everything above composes the
   landing page and the account screens, and a new page's rules sitting among
   them is how two sections end up sharing a class by accident.

   It borrows rather than invents -- .steps/.step for the installation track,
   .panel for the boxes in the right-hand column, .note for the caveat under
   the table. The new vocabulary is the page's own header, the two-column
   body, the single-line source rows and a two-column key/value table. */

.dl-hero > .wrap { display: grid; justify-items: start; gap: var(--s-3); }
.dl-hero h1 {
	font-size: var(--step-4);
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-display);
	margin: 0;
}
/* The meta line is one size down from body text and dimmed: it is the fact
   sheet under the title, not a sentence anybody reads twice. */
.dl-hero .dl-meta { margin: 0; }
/* The header and the body are one surface, so the header does not pay a full
   band's padding on its way out -- the atlas closes .pghead at .6rem and
   opens .body at .6rem, and the two of them are 1.8rem apart including the
   centred block's own lead-in. A --s-section gap here (2.7rem on a laptop)
   put a hole between the title and the button the title is about. */
.dl-hero { padding-block-end: var(--s-3); }

/* THE HEADER AND THE BODY ARE ONE SURFACE. The atlas gives both the page
   ground and no rule between them: the heading, the button under it and the
   columns under that are one block of page, and a hairline across it would
   read as the end of something. */
.dl-body { border-block-start: 0; padding-block-start: var(--s-3); }

/* The page's one action, centred, with the fact sheet repeated under it. */
.dl-cta {
	display: grid;
	justify-items: center;
	gap: var(--s-3);
	text-align: center;
	padding-block-end: var(--s-6);
}
/* Set in the mono face, which is the site's voice for a quantity -- this copy
   of the line is read as a spec, where the one under the heading is read as a
   sentence. */
.dl-meta-mono {
	font-family: var(--f-mono);
	font-size: var(--step--2);
	margin: 0;
}

/* HOW YOU INSTALL IT ON THE LEFT, WHAT IT NEEDS ON THE RIGHT. The atlas's
   1.15 / .85 split: the left column carries four steps of prose and the right
   carries a three-row table, so an even split would leave the table padded
   with air while the steps wrapped.

   minmax(0, ...) on both, not a bare fr. A grid column is sized to max-content
   by default, and table.spec declares an 18rem minimum -- with the implicit
   column the right-hand side refuses to go below that and pushes the page
   sideways instead of letting the table scroll inside .table-scroll. */
.dl-grid {
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
	gap: var(--s-5) var(--s-6);
	align-items: start;
}
.dl-main { min-width: 0; }
/* The boxes stack, at the same interval the account page's column uses. */
.dl-side { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); min-width: 0; }

/* The sources heading opens a second block inside a column that already has
   one, so it carries the gap the .section band would otherwise have given it. */
.dl-src-head { margin-block-start: var(--s-6); }

/* The second line in a step is the warning: what goes wrong when the step is
   done differently. A step further down than the instruction it qualifies. */
.dl-steps .step-warn {
	margin-block-start: var(--s-2);
	color: var(--c-ink-faint);
	font-size: var(--step--1);
}

/* ONE LINE PER SOURCE. Three cards for three one-phrase options gave each
   phrase a headline's worth of room and made choosing a mirror look like the
   decision the page is about; the decision the page is about is the gold
   button above. A strip is a name, a reason and a way to take it. */
.dl-mirror {
	display: flex;
	align-items: center;
	gap: var(--s-3);
	border: var(--bw) solid var(--c-line);
	background: var(--c-panel);
	border-radius: var(--r);
	padding: var(--s-3) var(--s-4);
	margin-block-end: var(--s-2);
}
/* The text takes the slack so the button lands on the right edge of every row
   whatever the caption's length -- margin-inline-start:auto on the button
   would do it too, but then a long caption would collide with it instead of
   wrapping. */
.dl-mirror-txt { display: grid; gap: var(--s-1); min-width: 0; flex: 1 1 auto; }
.dl-mirror .nm { font-weight: var(--w-semibold); font-size: var(--step--1); color: var(--c-ink); }
.dl-mirror .mt { font-size: var(--step--2); color: var(--c-ink-faint); }
/* The row's button must not shrink into its own label. */
.dl-mirror .btn { flex: 0 0 auto; }

/* A HEADING OVER A COLUMN, NOT OVER A BAND. .section h2 is --step-3, which
   is sized for a heading that spans the page; over a 680px column it ran
   nearly the column's width and outweighed the four steps under it. --step-2
   tops out at 1.35rem, which is the atlas's .hd h2 exactly. */
.dl-main .section-head h2 { font-size: var(--step-2); }

/* Inside a box the heading is a box heading, not a section heading. */
.dl-box h3 { font-size: var(--step-1); }
/* A FOOTNOTE, NOT A CALLOUT. This sentence says which numbers were NOT
   measured; the atlas sets it as quiet faint text under the table it
   qualifies. It used to wear .note, whose gold wash and gold bar are sized to
   close a full-width band -- inside the box it shouted louder than the three
   measurements above it. */
.dl-note {
	margin-block: var(--s-3) 0;
	color: var(--c-ink-faint);
	font-size: var(--step--2);
}
.dl-help-p { color: var(--c-ink-dim); font-size: var(--step--1); margin-block-end: var(--s-4); }

/* A two-column requirement/value table. Narrower minimum than table.rank's
   five columns: 40rem would force a scrollbar on a phone for two words a row.

   NOT CALLED .kv, and that is not a style preference: .kv above is the account
   page's definition list and it sets display:grid. A table wearing it turned
   its own head and body into two grid items sitting side by side -- a header
   stranded to the left of the rows it labels. A new class name is one word;
   the debugging was not. */
table.spec {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--step-0);
	/* 18rem, measured rather than picked: at 22rem the box scrolled by a single
	   pixel on a 390px phone, which is a scrollbar and no information. */
	min-width: 18rem;
}
table.spec th {
	text-align: start;
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-ink-faint);
	padding: var(--s-3) var(--s-4);
	border-block-end: var(--bw) solid var(--c-line);
	white-space: nowrap;
}
table.spec td {
	padding: var(--s-3) var(--s-4);
	border-block-end: var(--bw) solid var(--c-hair);
	color: var(--c-ink-dim);
}
table.spec td:first-child { color: var(--c-ink); }
table.spec tr:last-child td { border-block-end: 0; }

/* Narrow: ONE COLUMN, and the requirements come FIRST. Stacked in source
   order the reader would scroll through four installation steps before
   finding out whether the game runs on their machine, which is the question
   that decides whether the steps are worth reading. `order` moves the boxes
   above the steps without moving them in the markup, so the reading order a
   screen reader follows is unchanged.

   60rem rather than the site's usual 51.25rem, and the table is why. The
   right-hand column is .85 of the split, so at 51.25rem it computes to about
   18rem of content once the gutters, the gap and the box's own padding are
   taken out -- which is table.spec's declared minimum exactly. Collapsing a
   breakpoint early costs a wide phone nothing; collapsing it late is the
   requirements table scrolling inside a box barely wider than itself. */
@media (max-width: 60rem) {
	.dl-grid { grid-template-columns: minmax(0, 1fr); }
	.dl-side { order: -1; }
}

/* Phone: the same rule the hero's actions follow -- a primary button that is
   not full width is a thumb-stretch. The mirror rows are exempt: their button
   is a small one at the end of a line, and stretched across the row it would
   outweigh the name it belongs to. */
@media (max-width: 32.5rem) {
	.dl-cta .btn { width: 100%; text-align: center; }
}


/* ---- ANNOUNCEMENT STRIP -------------------------------------------------
   One line above the masthead, on every page, only when there is something to
   say. The markup is in layout.html and is drawn inside {{if .Ann}}: there is
   no empty state to style, because an empty strip is never rendered.

   HOW IT MAKES ROOM FOR ITSELF, with no JavaScript. tokens.css defines
   --bar-h as (--h-bar + --ann-top) -- the whole pinned masthead, not just the
   bar -- and every clearance on the site is already measured from --bar-h.
   Turning --ann-top on here therefore moves the bar, the ornament rule, the
   main padding, the hero, the anchor offset and the mobile drop panel down by
   exactly the strip's height, in one declaration. The two rules below are the
   only ones that have to know the strip exists at all.

   --ann-top is set on the ROOT element, not on body: custom properties are
   substituted where they are declared, and --bar-h is declared on :root. A
   flag on body would be read too late to change it. */
html.ann-on { --ann-top: var(--h-ann); }

/* The bar is pushed down by the strip, and its own height stops being the
   stack's height. Later in the file than the .bar rule above, so it wins on
   order at equal specificity; kept here rather than edited into that rule so
   everything the strip touches reads in one place. */
.bar { inset-block-start: var(--ann-top); height: var(--h-bar); }

.ann {
	position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 51;
	height: var(--h-ann);
	display: flex; align-items: center;
	/* THE STRIP IS RED, AND IT IS A GRADIENT RATHER THAN A BAR. Dark at both
	   ends and hot in the middle, so that across a 1920 monitor it reads as a
	   banner over the page instead of a solid wall of red -- which is the one
	   thing it must not look like, because a red wall across the top of a
	   site says "the site is broken" and this strip says "read this". */
	background: var(--g-ann);
	border-block-end: var(--bw) solid var(--c-ann-line);
	color: var(--c-ann-ink);
	font-size: var(--step--1);
	/* Above the bar's z-index and above its blur: the strip is opaque, so a
	   backdrop-filter underneath must not pick it up. */
}
.ann > .wrap {
	display: flex; align-items: center; gap: var(--s-3);
	/* The sentence is the part that may be long; it is the part that gets cut,
	   and the tag and the link stay whole. One line, always -- a strip that
	   wraps to two lines is taller than the space the page reserved for it and
	   would slide under the bar. */
	min-width: 0;
}
.ann .tag {
	flex: none;
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	padding: var(--s-1) var(--s-3);
	border-radius: var(--r-sm);
	/* On the strip's own ground, not the page's: the chip is a hole punched
	   in the banner, so it darkens what is behind it rather than picking up
	   the gold wash it would have worn on the dark bar. */
	background: rgba(0,0,0,.28);
	border: var(--bw) solid rgba(255,255,255,.18);
	color: inherit;
	line-height: 1;
}
.ann-text {
	min-width: 0;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	color: inherit;
}
.ann-more {
	flex: none;
	margin-inline-start: auto;
	color: #fff;
	white-space: nowrap;
	text-decoration: underline;
	text-underline-offset: .2em;
}
.ann-more:hover { color: var(--c-ann-ink); }

/* MAINTENANCE IS THE LOUDER ONE. Same shape, different weight: the tag turns
   red and the sentence comes up to full-strength ink, because a person who is
   about to be disconnected has to read it without deciding to. The strip's
   ground stays dark -- a red bar across the top of the site says "the site is
   broken", which is a different message from "the game is down at nine". */
/* MAINTENANCE IS STILL THE LOUDER ONE, and now that the ordinary strip is
   already red it has to get louder inside the same colour rather than by
   changing to another one. Same gradient, one stop brighter -- the atlas's
   --ember-hi in the middle instead of its mid red -- and the sentence comes
   up to full white. A person who is about to be disconnected has to read it
   without deciding to.

   The jade variant the atlas also draws is NOT used here: with the red strip
   spoken for by the announcement, a green bar for "the server is going down"
   would be the reassuring colour on the alarming message. Its tokens stay
   declared for the day a third kind of notice needs them. */
.ann-maint {
	background: var(--g-ann-maint);
	border-block-end-color: var(--c-ann-maint-line);
}
.ann-maint .ann-text { color: #fff; }

/* The menu item for the page you are on. Colour plus a rule under it, not one
   or the other: colour alone is not a state for anyone who cannot see this
   particular pair of colours apart. The marker is on the link, so it survives
   the drop panel on a narrow screen with no extra rule. */
.menu > .main a.on:not(.btn) {
	color: var(--c-ink);
	text-decoration: underline;
	text-decoration-color: var(--c-gold);
	text-decoration-thickness: 2px;
	text-underline-offset: .45em;
}

/* THE NARROW-SCREEN DROP PANEL MEASURES FROM THE BAR, NOT FROM THE PAGE.
   It is position:absolute and its containing block is .bar itself (the nearest
   positioned ancestor), so its offset has to be the bar's OWN height. With
   --bar-h now meaning the whole pinned stack, the panel would hang the strip's
   height below the bar and leave a gap of the page showing through. Measured
   at 390x844: 124.8px instead of 90.4px before this rule. */
@media (max-width: 51.25rem) {
	.menu[open] > .main { inset-block-start: var(--h-bar); }
}

/* ---- MAINTENANCE HERO ---------------------------------------------------
   The front page while the game is closed. Same section, same painting, same
   height -- only the column layout and what stands in it change, so the page
   does not appear to have been replaced by a different site.

   ONE COLUMN. The second column of the ordinary hero is the sign-in panel, and
   there is nothing to sign in to; leaving the grid at two columns would set
   the whole message in a narrow half with a hole beside it. */
.hero-maint .hero-grid { grid-template-columns: minmax(0, 1fr); }
/* The message reads as prose, so it gets a prose measure rather than the full
   page width -- a sentence 82rem wide is a sentence nobody finishes. */
.hero-maint .hero-copy { max-width: var(--w-narrow); }

/* What still works, under the buttons. A quiet box rather than another
   headline: it is reassurance, and reassurance shouted is not reassuring. */
.maint-note {
	/* atlas .maint p: 1.3rem before whatever closes the screen. */
	margin-block-start: var(--s-5);
	max-width: var(--measure);
	padding: var(--s-3) var(--s-5);
	background: var(--c-gold-tint);
	border-inline-start: 2px solid var(--c-gold-dim);
	border-radius: var(--r-sm);
}
.maint-note h2 {
	margin: 0 0 var(--s-2);
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	color: var(--c-gold-soft);
}
.maint-note p { margin: 0; font-size: var(--step--1); color: var(--c-ink-dim); }



/* ============================================================================
   THE ATLAS
   ==========================================================================
   The screen atlas (scratchpad/site/sancar2-atlas.html) is the approved
   design, and the site had drifted from its LAYOUT while matching its words.
   This block is the drift, corrected. It sits before the narrow-screen block
   below on purpose: several rules here are about the wide layout only, and the
   phone rules have to be able to win over them at equal specificity, which is
   decided by order.

   WHAT THE ATLAS SAYS ABOUT THE FRONT PAGE, and what the site was doing:
     - one full-width plate with the words on its dark left side; the site had
       cut the plate in half to make room for a sign-in card;
     - a 440px band, not a whole screen;
     - two buttons under the sentence, the download filled and first; the site
       had one;
     - the counters INSIDE the hero as a strip under a gold rule, value over
       label; the site had them below everything, label over value;
     - the four classes introduced by a CENTRED heading; the site left-aligned
       it;
     - sign-in and "open an account" both in the bar; the site had one.
   ========================================================================= */

/* ---- THE HERO IS ONE COLUMN AND ONE PICTURE ----------------------------- */
.hero { min-height: var(--h-hero); }
/* The returning player's hero is shorter: it carries a greeting and a row of
   figures, not a proposition -- and its inner padding is the shorter band's
   too, or a 330px plate would carry the 440px one's margins. */
.hero-back {
	min-height: var(--h-hero-back);
	padding-block: calc(var(--bar-h) + var(--s-hero-back)) var(--s-hero-back);
}
.hero-grid { grid-template-columns: minmax(0, 1fr); }
/* The words keep a measure; the picture keeps the page. */
.hero-copy { max-width: var(--w-hero-copy); }
/* The returning player's column is the wider of the two, and the width is what
   shapes the strip below the greeting -- see --w-hero-copy-back. */
.hero-back .hero-copy { max-width: var(--w-hero-copy-back); }

/* THE COUNTERS ARE PART OF THE HERO. A rule above them, the figure above its
   label, in a row. column-reverse rather than reordering the markup: the
   dictionary list is a list of terms and their definitions, and a <dd> written
   before its <dt> is not one. */
.hero .tiles.live {
	display: flex;
	flex-wrap: wrap;
	/* atlas .live: 1.7rem between the figures, 1.7rem above the rule and 1rem
	   below it. */
	gap: var(--s-5);
	margin-block-start: var(--s-5);
	padding-block-start: var(--s-4);
	border-block-start: var(--bw) solid var(--c-gold-dim);
}
.tiles.live .tile { display: flex; flex-direction: column-reverse; align-items: start; gap: 0; }
.tiles.live dd { font-size: var(--step-1); color: var(--c-gold-soft); }

/* THE SIGNED-IN HERO IS ONE STRIP: the download button, then the boxes. The
   button is centred against boxes that are taller than it rather than
   stretched to their height -- a 60px-tall primary button reads as a banner. */
.hero-strip { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--s-3); }
.hero-strip .actions { margin: 0; align-self: center; }
/* See --w-hero-cta: the button's width is half of what gives the row its
   shape, and the other half is the column it wraps inside.

   THE FLOOR IS ON THE WRAPPER, NOT ON THE BUTTON, and that is a flex-sizing
   detail rather than a preference. .actions is itself an item of the strip and
   takes its width from its content; a minimum expressed as a percentage inside
   it resolves against a width that is not known yet, so it contributes nothing
   and the wrapper stays at the button's text width -- measured: the button was
   still 136px with the floor on it. Stated on the wrapper the number is
   absolute, and the button fills it.

   368px IS WHERE THE FLOOR STOPS BEING SAFE, and it is arithmetic rather than
   a device: at 23rem of viewport the gutter leaves 330px of column, which is
   the last width a 320px button fits inside. Below it -- a 320px phone -- the
   floor would be wider than the plate it stands on, so it is simply not
   declared and the button takes its text width back. min-width rather than a
   reset inside the phone block further up: the reset would have to come AFTER
   this rule to win at equal specificity, and it does not. */
@media (min-width: 23rem) {
	.hero-strip .actions { min-inline-size: var(--w-hero-cta); }
}
.hero-strip .actions .btn { flex: 1 1 auto; }
/* ONE WRAPPING LINE, NOT A BUTTON AND THEN A ROW OF BOXES. The counters are a
   <dl>, and as long as that <dl> is a flex container of its own it is ONE item
   of the strip: it can only be beside the button or under it, all four boxes
   together. The atlas has no such grouping -- its .strip holds the button and
   the four .tile divs as five siblings, so the line fills and wraps wherever
   it runs out, which at the atlas's 46rem column is after the second counter.
   `display: contents` removes the list's box and leaves its children as those
   siblings, which is exactly the difference. The list is still a <dl> in the
   markup, so the terms and their definitions stay paired for anything reading
   the document rather than looking at it. */
.hero-strip .tiles { display: contents; }
.hero-strip .tile {
	/* atlas .tile: the gold at a third rather than --c-gold-dim, which is a
	   solid colour and draws a frame where the design wants an edge. */
	border: var(--bw) solid var(--c-gold-edge);
	background: color-mix(in srgb, var(--c-ground) 74%, transparent);
	padding: var(--s-2) var(--s-4);
	min-inline-size: 9rem;
	align-content: center;
}
/* atlas .tile .v: the brightest gold on the page, because these four figures
   are the only thing the signed-in hero has to say. */
.hero-strip .tiles dd { font-size: var(--step-1); color: var(--c-gold-hi); }
.hero-strip .tiles dd small { color: var(--c-ink-faint); }

/* ---- THE SIGN-IN CARD'S NEW HOME ----------------------------------------
   Its own strip under the hero. NOT in the atlas -- the atlas has no sign-in
   box on the front page at all -- so this is the nearest arrangement that
   keeps a box the site's returning players use. It is deliberately quiet: the
   alternate ground the site already uses for a secondary section, no heading
   of its own, and the card centred rather than pinned to one side, so it reads
   as an offer rather than as a second hero. */
/* The sign-in strip under the hero. PHONE ONLY -- see the comment in
   home.html for why: on a wide screen the bar's own "Giris" and "Hesap ac"
   lead to real pages and this band was a third way to do the same thing,
   sitting alone in an empty plate; on a phone those two are behind the menu
   button and a returning player should not have to open a menu to sign in. */
.join { display: none; }
.join .panel { max-width: 30rem; margin-inline: auto; justify-self: auto; }

/* ---- THE ACCOUNT PAGE IS A RAIL AND A COLUMN, NOT TWO HALVES ------------
   The atlas puts what the account IS -- its details, its safebox, its two
   security forms, its balance -- in a narrow rail, and what it HAS -- the
   characters and the orders -- in the wide column beside it. The site had
   them at 1fr 1fr, which gave a four-row key/value list the same width as a
   table of purchases and left the order table short of the 448px its four
   columns need.

   min-width, not max-width, and 65.01rem: below that the page is one column
   (see the 65rem block further up) because two columns there are both too
   narrow for the table. The two rules must not overlap or the later one wins
   at every width. */
@media (min-width: 65.01rem) {
	.acct { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); }
}

/* ---- THE SIGN-IN AND REGISTRATION SCREENS -------------------------------
   The atlas splits these down the middle and sets the form ON the page rather
   than inside a card: the picture is the card. The site had a 30rem panel
   floating in the middle of a wider column, which read as a dialogue box over
   a wallpaper -- two surfaces where the design has one.

   The panel class stays on the element. It is removed HERE rather than in the
   template because the same markup is what a narrow screen wants back: see the
   narrow block below, where the card returns so the form has an edge against
   the picture underneath it. */
@media (min-width: 51.3125rem) {
	.auth              { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
	.auth-mirror       { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
	.auth-body         { justify-items: stretch; }
	.auth-card {
		max-width: none;
		justify-self: stretch;
		padding: 0;
		background: none;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		backdrop-filter: none;
	}
	/* The one action fills the column it belongs to. A 140px button under a
	   600px row of boxes is the atlas's shape for a secondary control, not for
	   the button the screen exists for. */
	.auth-card .form > .btn { inline-size: 100%; }
}

/* ---- THE RANKING'S TABS ------------------------------------------------- */
.tabs-lead { justify-content: start; }
.tabs-lead .tab { flex: 0 0 auto; padding-inline: var(--s-5); }

/* ---- A CENTRED SECTION HEAD, USED ONCE ---------------------------------- */
.section-head-mid { margin-inline: auto; text-align: center; }
.section-head-mid p { margin-inline: auto; }

/* ---- THE SMALL BUTTON IN THE BAR ----------------------------------------
   The signed-in pair (the account, sign out) are buttons in the atlas and they
   are smaller than a page's own controls: the bar is not where the work is. */
.btn-sm { font-size: var(--step--2); padding: var(--s-1) var(--s-3); }

/* ============================================================================
   NARROW SCREENS -- THE SECOND PASS
   ==========================================================================
   Everything above made the page fit a phone. It did not make it usable on
   one: nothing scrolled sideways and the page was still wrong. This block is
   the design work that follows from that, and it is appended rather than
   merged into the three media queries above because every rule here has to win
   over one of them -- at equal specificity that is decided by order, and an
   edit in place would have meant re-reasoning about forty rules that are
   correct.

   FOUR THINGS ARE BEING FIXED, in the order a visitor meets them:
     1. the masthead's ornament sat on top of the first heading of every
        section page (measured: 14px of overlap at 390, 16.8 at 768);
     2. the hero's picture was a 180px letterbox strip with the figures'
        heads cut off, and the sign-in card was three screens below it;
     3. the ranking and the order tables hid two columns each inside a
        scroller with no sign that anything was there (measured: 289px of
        /ranking off-screen at 390, 131px of the order table);
     4. the burger, the menu links, the checkboxes and every small link were
        under 44px.
   ========================================================================= */

/* ---- 1. THE FIRST HEADING CLEARS THE PINNED MASTHEAD ---------------------
   The bar is fixed and the Greek-key rule is pinned under it, so the top of
   <main> is covered by --bar-h + --h-key of chrome. The hero and the sign-in
   screen each pay for that themselves; a plain section page paid with its
   ordinary section padding, which is large enough on a desktop and is not on a
   phone -- --s-section bottoms out at 3.5rem while the pinned stack is 4.4rem.
   max() takes whichever is larger, so the desktop keeps the rhythm it has and
   the phone stops printing its eyebrow through the ornament. */
main > .section:first-child {
	padding-block-start: max(var(--s-section), calc(var(--bar-h) + var(--h-key) + var(--s-4)));
}

/* ---- THE LEGAL PAGES -----------------------------------------------------
   The atlas's .lg screen: a document menu that stays put and the document
   beside it. It replaces the .prose block that used to be here, which styled
   a single column because that is all these pages had.

   THE MENU IS THE POINT, not the decoration. Four documents that each end by
   pointing at another one had no link between them: /kvkk, /privacy and /rules
   were reachable only by typing the address. A notice a reader cannot navigate
   to has not informed anybody, and "see the terms of use" is a dead sentence
   without a way to see them.

   This is a top-level layout rather than a .section, so it pays for the pinned
   masthead itself -- see main > .section:first-child above for the same
   arithmetic and the same reason. */
.lg {
	display: grid;
	grid-template-columns: var(--w-docnav) 1fr;
	gap: var(--s-5);
	/* The atlas mock is full-bleed because a mock has no masthead above it to
	   line up with. On the real page it does: the brand sits one --gutter in,
	   and a menu starting hard against the window edge under an inset bar
	   reads as a different page having loaded. So the grid takes the site's
	   own page box, and the two columns live inside it. */
	max-width: var(--w-page);
	margin-inline: auto;
	padding-inline: var(--gutter);
	padding-block: max(var(--s-5), calc(var(--bar-h) + var(--h-key) + var(--s-4))) var(--s-6);
	background: var(--c-ground);
}

/* ---- the document menu --------------------------------------------------- */
.lgnav {
	border: var(--bw) solid var(--c-line);
	background: var(--c-panel);
	align-self: start;   /* a menu of four does not stretch to a page of eight */
}
.lgnav a {
	display: block;
	padding: var(--s-2) var(--s-3);
	color: var(--c-ink-dim);
	text-decoration: none;
	font-size: var(--step--1);
	border-block-end: var(--bw) solid var(--c-hair);
}
.lgnav a:last-child { border-block-end: 0; }
.lgnav a:hover { color: var(--c-ink); background: var(--c-raise); }
/* The open document. Colour alone would not carry it -- these four titles sit
   in a column of near-identical rows -- so it takes the gold edge as well, and
   the template marks it with aria-current for anyone not seeing either. */
.lgnav a.on {
	color: var(--c-gold-hi);
	background: var(--c-gold-tint);
	border-inline-start: var(--bw-mark) solid var(--c-gold);
}

/* ---- the document -------------------------------------------------------- */
.lgbody { max-width: var(--w-narrow); }
.lgbody h1 {
	font-family: var(--f-display);
	font-weight: var(--w-bold);
	font-size: var(--step-3);
	line-height: var(--lh-heading);
	margin-block-end: var(--s-1);
}
/* The date line. Monospace and faint: it is a fact about the document rather
   than part of it, and it has to be scannable against the version a reader
   remembers agreeing to. */
.lgbody .upd {
	font-family: var(--f-mono);
	font-size: var(--step--2);
	color: var(--c-ink-faint);
	margin-block-end: var(--s-5);
}
.lgbody h3 {
	font-family: var(--f-display);
	font-weight: var(--w-medium);
	font-size: var(--step-2);
	color: var(--c-gold-hi);
	margin-block: var(--s-5) var(--s-1);
}
.lgbody p {
	color: var(--c-ink-dim);
	font-size: var(--step-0);
	line-height: var(--lh-body);
	max-width: none;   /* the column is already --w-narrow; --measure would
	                      narrow it a second time and leave a ragged edge */
	margin-block: 0 var(--s-3);
}

/* ---- who is accountable --------------------------------------------------
   ONE BOX, not the three-column fact grid this page drew before. The
   controller's name, its address and its contact are one answer to one
   question, and spread across a row of cards they read as three statistics.
   Two columns inside it, label and value, so the three values line up. */
.ident {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: var(--s-1) var(--s-4);
	border: var(--bw) solid var(--c-line);
	background: var(--c-panel);
	padding: var(--s-3) var(--s-4);
	margin-block: var(--s-1) var(--s-5);
}
.ident dt {
	color: var(--c-ink-faint);
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-wide);
	align-self: baseline;
}
.ident dd {
	margin: 0;
	color: var(--c-ink);
	font-size: var(--step--1);
}

/* ---- ONE COLUMN: THE MENU LIES DOWN ON TOP -------------------------------
   The same breakpoint the hero and the two-column blocks use. A 15rem menu
   beside a document is 15rem of a 24rem screen, so below this width the menu
   goes above the document instead -- still the whole list, still marking where
   the reader is, and now the first thing on the page rather than a column
   squeezed against the edge.

   The rows also grow to a real tap target here. At 0.5rem of padding they are
   about 38px tall, which is a comfortable click and a missed tap. */
@media (max-width: 51.25rem) {
	.lg {
		grid-template-columns: 1fr;
		gap: var(--s-4);
	}
	.lgnav a {
		display: flex;
		align-items: center;
		min-height: var(--tap);
	}
}

/* ---- 2. THE HERO, BELOW THE TWO-COLUMN BREAKPOINT -----------------------
   The picture goes BEHIND the words instead of above them. Two things follow
   from that and both are the point: the band is tall enough to be a picture
   (see --h-hero-art for the arithmetic), and the eyebrow, the slogan and the
   lede sit on it under a curtain rather than on a black rectangle underneath
   it. The curtain is the same three named veil steps the wide layout uses, run
   vertically, and it finishes in the page's own ground so the band has no cut
   edge to give itself away. */
@media (max-width: 51.25rem) {
	.hero {
		min-height: 0;
		align-content: start;
		padding-block: calc(var(--bar-h) + var(--s-6)) var(--s-7);
	}
	.hero::before {
		inset: 0 0 auto 0;
		height: var(--h-hero-art);
		/* Vertically centred: the crop is horizontal at this aspect ratio, so
		   the figures keep their heads and their feet and lose only the two
		   outer classes. */
		background-position: 50% 50%;
	}
	.hero::after {
		inset: 0 0 auto 0;
		/* A step taller than the picture, so the dissolve finishes on the
		   ground rather than on the picture's last row of pixels. */
		height: calc(var(--h-hero-art) + var(--s-7));
		background: linear-gradient(180deg,
			var(--c-veil-2) 0%, var(--c-veil-1) 16%, var(--c-veil-2) 50%,
			var(--c-veil-3) 82%, var(--c-ground) 100%);
	}

	/* THE ORDER OF THE HERO IS THE ORDER OF THE VISITOR'S NEEDS, and on one
	   column that is not the order of the source. display:contents dissolves
	   the copy column so its children become items of the hero's own grid and
	   can be sequenced against the panel; the panel then lands directly under
	   the call to action instead of below the counter, which is what put a
	   returning player three scrolls away from the box they came for.
	   Measured at 390: the sign-in card's top moved from 700px to 404px, which
	   is the difference between "on the first screen" and "not".

	   NOT ON THE MAINTENANCE HERO: that one has no panel to sequence against
	   and it does have a prose measure on .hero-copy, which display:contents
	   would throw away. */
	.hero:not(.hero-maint) .hero-copy { display: contents; }
	.hero-grid { gap: var(--s-4); }
	/* The margins go with the column that carried them; the grid's own gap is
	   the spacing now, or every seam would be a margin plus a gap. */
	.hero-copy > .eyebrow { order: 1; margin-block-end: 0; }
	.hero-copy > h1       { order: 2; margin-block-end: 0; max-width: none; }
	.hero-copy > .lede    { order: 3; margin-block-end: 0; max-width: none; }
	.hero-copy > .actions { order: 4; margin-block-end: 0; }
	.hero-side            { order: 5; }
	.hero-copy > .tiles   { order: 6; }
}

/* ---- 2b. THE SIGN-IN AND REGISTRATION SCREENS ---------------------------
   The painting used to come first on a narrow screen. It is a decorative
   plate with no alt text, and putting it first meant the page opened on 150
   pixels of cropped shoulder with the form below the fold -- on the one screen
   whose entire job is a pair of boxes. The form leads now and the picture
   closes the screen, which is also what the source order already said. */
@media (max-width: 51.25rem) {
	.auth-art, .auth-mirror .auth-art {
		/* relative, NOT static. The <img> inside is position:absolute inset:0
		   and the veil over it is another; with the box itself unpositioned
		   their containing block is the page, so the painting was drawn at
		   0,0 across the whole viewport -- behind the bar, behind the form,
		   844px tall on a 390px screen. Measured before this line: img top 0,
		   height 844, inside a 224px box. The wide layout never showed it
		   because there the box is position:sticky. */
		position: relative;
		/* The sticky offset comes off with the stickiness. It is a real offset
		   on a relatively positioned box too, and it pushed the picture 71px
		   past the bottom of its own section. */
		inset-block-start: auto;
		order: 1;
		height: var(--h-auth-art);
		max-height: none;
		/* The rule moves to the edge the picture now touches. */
		border-block-start: var(--bw) solid var(--c-hair);
		border-block-end: 0;
	}
	/* Higher up the plate than the wide layout asks for: the band is a
	   landscape slice of a 440x600 portrait and the face is in the top third. */
	.auth-art img { object-position: 50% 12%; }
	.auth-art::after, .auth-mirror .auth-art::after {
		background: linear-gradient(180deg, var(--c-veil-1) 0%, var(--c-veil-2) 58%, var(--c-veil-3) 100%);
	}
	.auth-body { padding-block: var(--s-5) var(--s-6); }
}

/* ---- 3. THE TABLES BECOME A LIST OF CARDS -------------------------------
   THE CHOICE, AND WHY IT IS NOT THE SCROLLING ONE. Both were allowed. A
   scroller with a fade at its edge keeps the page short, and it still asks a
   person to discover that a table they can read is only three fifths of a
   table. The ranking's last two columns are the guild and the score -- the
   score is what the ranking is SORTED BY, so the column being silently absent
   means the page never shows the reason the rows are in the order they are in.
   A card cannot hide a column: every field is written, with its own heading
   beside it, and nothing depends on the reader trying a gesture.

   THE COST IS HEIGHT and it was measured: /ranking at 390 goes from 1393px to
   about 1900px for eight rows -- a row costs 77px as a card against 44px as a
   table row. That is the price of the two columns being there at all.

   43.75rem, measured rather than borrowed from the breakpoints above:
   table.rank declares a 40rem minimum and the gutter at that width is 27px a
   side, so the table stops fitting -- and starts hiding columns -- at about
   700px. Above it the table is a table, which is the better shape when it
   fits. A tablet at 768 therefore keeps the real table; a phone never sees it.

   The heading row is not deleted, it is moved out of sight: the cells still
   need something to be the header OF, and the roles in the markup (role=table,
   rowgroup, row, cell, columnheader) are there because changing an element's
   display is what makes a browser stop treating a table as one. */
@media (max-width: 43.75rem) {
	.join {
		display: block;
		/* It is a band like any other section, so it takes the band's own
		   measure rather than a number of its own. */
		padding-block: var(--s-section);
		background: var(--c-ground-2);
		border-block-end: var(--bw) solid var(--c-hair);
	}
	/* Nothing to scroll any more, and a scroller that never scrolls still
	   clips a focus ring. */
	.table-scroll { overflow-x: visible; }

	/* ONE CHARACTER CARD ACROSS. Two of them here leaves each about 160px on a
	   phone, which is a 44px portrait and no room for the name beside it. The
	   collapse is at the same width the orders table redraws itself at, so the
	   whole box changes shape once rather than twice. */
	.chars { grid-template-columns: minmax(0, 1fr); }

	/* .orders carries its own min-width further up the file, and a class more
	   than this rule has -- so it has to be named, or the order table keeps a
	   448px floor, breaks out of the account column and scrolls the whole page
	   sideways. Measured before this line: the document was 485px wide on a
	   390px screen. */
	table.rank, table.rank.orders { display: block; min-width: 0; }
	table.rank thead {
		position: absolute; width: 1px; height: 1px;
		padding: 0; margin: -1px; overflow: hidden;
		clip-path: inset(50%); white-space: nowrap;
	}
	/* The row and its cells collapse too. A table-row inside a 1px box still
	   lays itself out at its natural width -- invisible, but it measures as a
	   box hanging 8px past the right edge of a 390px screen, which is exactly
	   the kind of thing an overflow check is supposed to catch. */
	table.rank thead tr, table.rank thead th { display: block; }
	table.rank tbody { display: grid; gap: var(--s-3); }
	table.rank tbody tr {
		display: grid;
		gap: var(--s-1) var(--s-3);
		padding: var(--s-3) var(--s-4);
		background: var(--c-well);
		border: var(--bw) solid var(--c-hair);
		border-radius: var(--r);
		/* A row is a target now: it is the height of a card, which is well past
		   the 44px a finger needs. */
		align-items: baseline;
	}
	table.rank td { display: block; border: 0; padding: 0; }
	/* THE HEADING TRAVELS WITH THE VALUE. data-label carries the same phrase
	   the column heading does -- the template writes both from one dictionary
	   key -- so the two cannot say different things. Dimmed and small: it is a
	   label, and a card whose labels are as loud as its values is a form. */
	table.rank td[data-label]::before {
		content: attr(data-label) " ";
		color: var(--c-ink-faint);
		font-family: var(--f-display);
		font-weight: var(--w-medium);
		font-size: var(--step--2);
		text-transform: uppercase;
		letter-spacing: var(--ls-wide);
	}

	/* FIVE COLUMNS -- both ranking tables have the same shape: a place, a
	   name, a level, a guild (or a leader) and a score. Two lines: who, then
	   the three facts about them, with the place down the left of both. */
	table.rank:not(.orders) tbody tr {
		grid-template-columns: 2.25rem minmax(0, 1fr) auto;
	}
	table.rank:not(.orders) td:nth-child(1) {
		grid-area: 1 / 1 / 3 / 2;
		font-family: var(--f-mono);
		font-size: var(--step-2);
		line-height: var(--lh-tight);
		font-variant-numeric: tabular-nums;
	}
	table.rank:not(.orders) td:nth-child(2) {
		grid-area: 1 / 2 / 2 / 3;
		font-weight: var(--w-semibold);
		overflow-wrap: anywhere;
	}
	table.rank:not(.orders) td:nth-child(3) { grid-area: 1 / 3 / 2 / 4; text-align: end; white-space: nowrap; }
	table.rank:not(.orders) td:nth-child(4) { grid-area: 2 / 2 / 3 / 3; font-size: var(--step--1); overflow-wrap: anywhere; }
	table.rank:not(.orders) td:nth-child(5) { grid-area: 2 / 3 / 3 / 4; font-size: var(--step--1); text-align: end; white-space: nowrap; }

	/* FOUR COLUMNS -- a purchase: what was bought, then when, for how much and
	   where it got to. The product leads because it is the one field a person
	   is scanning for. */
	table.rank.orders tbody tr { grid-template-columns: minmax(0, 1fr) auto; }
	table.rank.orders td:nth-child(2) {
		grid-area: 1 / 1 / 2 / 3;
		font-weight: var(--w-semibold);
		overflow-wrap: anywhere;
	}
	table.rank.orders td:nth-child(1) { grid-area: 2 / 1 / 3 / 2; font-size: var(--step--1); }
	table.rank.orders td:nth-child(3) { grid-area: 2 / 2 / 3 / 3; font-size: var(--step--1); text-align: end; white-space: nowrap; }
	table.rank.orders td:nth-child(4) { grid-area: 3 / 1 / 4 / 3; font-size: var(--step--1); }

	/* The podium's colour on the place, which used to come from the table's
	   first cell and still should. */
	table.rank .top1 td:first-child,
	table.rank .top2 td:first-child,
	table.rank .top3 td:first-child { font-weight: var(--w-regular); }

	/* The mark on the visitor's own row moves from the first CELL to the card,
	   because there are no cells here any more -- td has given up its border
	   along with its padding. The wash carries over untouched. */
	table.rank tbody tr.rank-mine { border-inline-start: var(--bw-mark) solid var(--c-gold); }

	/* The two-column specification table on /download fits as a table at every
	   width (18rem minimum), so it is left alone -- but its scroller no longer
	   needs to be one either. */
	table.spec { min-width: 0; }
}

/* ---- 4. THINGS A FINGER HAS TO HIT --------------------------------------
   44px in both directions, from --tap. Split in two: what is only on the page
   below the menu breakpoint goes in the width query, because the burger is
   display:none above it and a rule keyed on the pointer alone would bring it
   back on a touchscreen laptop. Everything that is a small link at any width
   goes in the pointer query. */
@media (max-width: 51.25rem) {
	.menu > summary {
		display: grid;
		place-items: center;
		min-inline-size: var(--tap);
		min-block-size: var(--tap);
		padding: 0;
		line-height: 0;
	}
	.menu[open] > .main a {
		min-block-size: var(--tap);
		display: flex;
		align-items: center;
	}
	/* The sign-out button in the drop panel is a form, and a form is not a flex
	   line on its own. */
	.menu[open] > .main .inline { display: flex; }
	.menu[open] > .main .inline .btn { flex: 1 1 auto; min-block-size: var(--tap); }
	/* The wordmark is the way home from every page. */
	.brand { display: inline-flex; align-items: center; min-block-size: var(--tap); }
	/* The strip's link: it stretches to the strip's full height, which is what
	   makes the taller --h-ann on a phone worth having. */
}

/* WIDTH OR POINTER, and the width is not a convenience. A real phone reports a
   coarse pointer and would be covered by the second half alone -- but a desktop
   window dragged down to 390px reports a fine one, and that is the window this
   work is checked in. A rule that only exists on hardware nobody is holding is
   a rule nobody can measure. */
@media (max-width: 51.25rem), (pointer: coarse) {
	/* A note under a form, a "see all" in a heading's corner, a way back to the
	   list, the two links inside the consent sentence: one line of small type
	   each, and all of them a miss without this. */
	.field-note a, .linky, .check a,
	.acct-more, .duo-more, .back a, .newsrow-more a {
		display: inline-block;
		min-block-size: var(--tap);
		min-inline-size: var(--tap);
		padding-block: var(--s-2);
		/* A one-word link ("Sıfırla", "Tümü") is 29px wide, so the box has to be
		   wider than the word; centring is what stops the word sitting against
		   the left edge of its own target. */
		text-align: center;
	}
	/* A headline link is already wide and must not be centred -- it is a
	   heading, and a centred one in a left-aligned card is a different design.
	   Only its height is short. */
	.newsrow-title a, .empty-body a {
		display: inline-block;
		min-block-size: var(--tap);
		padding-block: var(--s-2);
	}
	/* The tick is 13px whatever anyone does to it; the label around it is the
	   target, so the label is what gets the height. */
	.check { min-block-size: var(--tap); align-items: center; }
	.tab { min-block-size: var(--tap); display: grid; place-items: center; }
	/* The button came down to the atlas's padding and lost its 44px floor with
	   it (40px measured at 1440). The type and the padding stay the atlas's;
	   only the box grows, and only where a finger is what hits it. */
	.btn { min-block-size: var(--tap); }

	/* The masthead's links keep their type and their spacing and grow a hit
	   area around it. This is the one rule that matters on a touchscreen wide
	   enough to keep the desktop navigation: measured at 1024, the links were
	   41px tall. The bar centres its row, so nothing moves. */
	.menu > .main a {
		min-block-size: var(--tap);
		min-inline-size: var(--tap);
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}

	/* THE STRIP'S LINK STRETCHES TO THE STRIP'S FULL HEIGHT, and BOTH boxes
	   have to be told: the strip centres its .wrap, so stretching only inside
	   the wrap stretches to the wrap's own 23px and stops there. The strip
	   itself is taller here -- see --h-ann in tokens.css. */
	.ann { align-items: stretch; }
	.ann > .wrap { align-items: stretch; }
	.ann .tag, .ann-text { align-self: center; }
	.ann-more {
		display: flex;
		align-items: center;
		justify-content: center;
		min-inline-size: var(--tap);
	}
}

/* ---- 5. THE PHONE'S OWN LAYOUT ------------------------------------------ */
@media (max-width: 32.5rem) {
	/* THE RANKING ROW FOLDS IN TWO, and every part of it survives the fold.
	   The row carries six things on one line at desk width -- a place, a
	   colour, a name, a class, a guild and a level -- and at 320px that line
	   was breaking "testchar05" across two lines mid-word and "TestLonca1"
	   with it. MEASURED at 320: the name and the guild both split.

	   Deleting a column instead is the fault the tables were fixed for: a
	   column that disappears without saying so. So the row folds -- the name
	   and the level on top, the class and the guild under them, the place and
	   the class's colour down the left of both. That is the same shape the
	   tables take here, and for the same reason.

	   Grid rather than the flex line it is above this width: a fold needs
	   named positions, and a wrapping flex line cannot put the level on the
	   FIRST row while the guild goes to the second. Column 4 is the mark on
	   the visitor's own row, and it collapses to nothing on every row that
	   does not carry one. */
	.mini-rank li {
		display: grid;
		grid-template-columns: var(--w-rank-pos) var(--bw-class) minmax(0, 1fr) auto auto;
		column-gap: var(--s-2);
		row-gap: var(--s-1);
		align-items: center;
	}
	.mini-pos   { grid-area: 1 / 1 / 3 / 2; inline-size: auto; }
	.mini-bar   { grid-area: 1 / 2 / 3 / 3; block-size: 100%; }
	.mini-name  { grid-area: 1 / 3 / 2 / 4; }
	.mini-you   { grid-area: 1 / 4 / 2 / 5; }
	.mini-lv    { grid-area: 1 / 5 / 2 / 6; inline-size: auto; }
	.mini-class { grid-area: 2 / 3 / 3 / 4; }
	.mini-guild {
		grid-area: 2 / 4 / 3 / 6;
		/* The auto margin was what pushed it right in the flex line; in a grid
		   cell it would push the text out of its own box. */
		margin-inline-start: 0;
		text-align: end;
		font-size: var(--step--2);
	}

	/* Two password boxes side by side are 140px each at this width, and the
	   label over one of them wraps to three lines. They were paired to save the
	   registration card a row it did not have on a desktop; on a phone the card
	   is allowed to be as tall as it needs. */
	.field-row { grid-template-columns: minmax(0, 1fr); }

	/* The podium is three cards deep before the table starts. It keeps its
	   order and its colour and gives up the padding. */
	.podium { gap: var(--s-3); }
	.podium-card { padding: var(--s-2) var(--s-3); }
	.podium-1 { padding-block: var(--s-3); }

	/* An empty state was a screen and a half of dashed border on its own. */
	.empty { padding: var(--s-5) var(--s-4); }

	/* THE SIGNED-IN COUNTERS LINE UP INSTEAD OF WRAPPING. Four of them on a
	   flex line at this width put three on the first row and one on a second,
	   starting under whichever of the three happened to be narrowest. Two
	   columns is the shape they actually have. */
	.hero .tiles {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--s-4) var(--s-5);
	}
}

/* ============================================================================
   THE FOOTER

   NOT IN THE ATLAS. The approved screen atlas draws twenty-nine screens and
   none of them has a footer, so nothing here is copied from it -- it is built
   out of the atlas's own material: the same ground the strips use, the same
   Greek-key rule that marks the masthead's lower edge, column heads at the
   measure of the boxes' own headings (--step--2 at --ls-wide, medium weight in
   the display face) and links in body ink rather than gold, because eleven
   gold links in a block would be the loudest thing on a quiet page.

   WHY IT EXISTS AT ALL. Eight of the site's pages -- the two "I forgot" flows
   and the four legal documents among them -- were reachable only by typing the
   address or by arriving from a letter. The masthead carries the four places a
   player goes while playing and cannot carry eleven; this is where the rest of
   the site is written down.

   WHAT IS DELIBERATELY ABSENT. A "server is up" badge, which the approved
   design had: the site never asks the game server anything, so the badge would
   have been a green dot that means nothing. And a Discord button, because the
   invite is not a link this page can promise today. A footer's whole job is to
   be the part of the page that is true.
   ========================================================================= */

.ft {
	/* The strips' ground. The page's own is a shade lighter, which is enough of
	   a step to read as a different surface once the ornament is between them
	   -- the rule is the edge here, not a border. */
	background: var(--c-ground-2);
	font-size: var(--step--1);
}
/* The ornament spans the window, the words do not: the rule belongs to the
   page's full width the way it does under the masthead. */
.ft > .orn { margin-block-end: var(--s-5); }

/* LINKS IN INK, NOT IN GOLD. Gold is the site's one accent and it marks the
   thing being offered; a block of eleven gold links at the foot of every page
   would compete with whatever the page was actually asking for. They still
   answer to the hover the rest of the site uses. */
.ft a { color: var(--c-ink-dim); }
.ft a:hover { color: var(--c-gold-hi); }

/* The column heads are signage, and they take the measure the site's other
   all-caps labels take. Weight and tracking are set against the h1/h2/h3 rule
   at the top of this file, which gives every heading the display face at
   semibold with heading tracking -- correct for a page title, a bar at this
   size. */
.ft h2 {
	font-size: var(--step--2);
	font-weight: var(--w-medium);
	letter-spacing: var(--ls-wide);
	text-transform: uppercase;
	color: var(--c-ink-faint);
	margin-block-end: var(--s-2);
}
/* A REAL LIST, with its markers off. The markers are decoration here -- the
   heading above already says what the group is -- but the list itself is not:
   it is how a screen reader says "three links" before reading the first one. */
.ft ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--s-1);
}

.ft-cols {
	display: grid;
	/* The brand block is the widest and the three link columns are sized by
	   what is in them: four short lines, four longer ones, four document
	   titles. Ratios rather than equal quarters, because four equal columns
	   put "Parolamı unuttum" on two lines while the one beside it stood half
	   empty. */
	grid-template-columns: 1.4fr 0.8fr 0.9fr 1fr;
	gap: var(--s-6);
	padding-block-end: var(--s-5);
}

.ft-mark {
	font-family: var(--f-display);
	font-weight: var(--w-bold);
	font-size: var(--step-2);
	letter-spacing: var(--ls-display);
	color: var(--c-ink);
}
/* The accent on the "2", as in the masthead. Not italic -- <em> is here
   because it is the emphasised part of the name, and the emphasis is carried
   in colour. */
.ft-mark em { color: var(--c-gold); font-style: normal; }

.ft-brand p {
	margin-block-start: var(--s-2);
	max-width: var(--measure-brand);
	color: var(--c-ink-faint);
}

/* ---- THE CLOSING STRIPS -------------------------------------------------
   Two lines under the columns, each with a hairline over it, both inside the
   page's measure so the rules line up with the columns they close rather than
   running off to the window's edges. The identity strip is drawn only when
   there is an identity; the disclaimer is always there, and it is last because
   it is the thing a reader scrolls to the bottom looking for. */
.ft-id,
.ft-disc {
	border-block-start: var(--bw) solid var(--c-hair);
	font-size: var(--step--2);
	color: var(--c-ink-faint);
	/* p's default measure is a reading column; these two are strips. */
	max-width: none;
}
.ft-id {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--s-1) var(--s-3);
	padding-block: var(--s-3);
}
/* The e-mail address is the one thing in the strip a reader can act on, so it
   is a mailto and it is marked as a link -- in the strip's own ink rather than
   the footer's link ink, so the line stays one line rather than a label and a
   highlight. */
.ft-id a { color: inherit; text-decoration: underline; text-underline-offset: 0.2em; }
.ft-id a:hover { color: var(--c-gold-hi); }
.ft-sep { color: var(--c-line-hi); }

.ft-disc { padding-block: var(--s-3) var(--s-5); }

/* ---- THE FOOTER ON A NARROW SCREEN --------------------------------------
   Four columns at 390px would be four columns of one word each. Two, with the
   brand block across the top of them: that is the phone rendering of the
   approved design, and it is the shape the content actually has. */
@media (max-width: 51.25rem) {
	.ft-cols {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--s-5);
	}
	.ft-brand { grid-column: 1 / -1; }
}

/* A list of links at body-caption size is a column of 20px targets. The same
   fix the rest of the site's small links get, and the row gap comes off the
   list because the padding is now what separates one line from the next.
   NOT centred, unlike the one-word links elsewhere: these are up to three
   words each and they sit in a left-aligned column under a left-aligned
   heading. */
@media (max-width: 51.25rem), (pointer: coarse) {
	.ft-col ul { gap: 0; }
	/* The e-mail address in the identity strip is a link too, and it was the
	   one target left at 17px (measured at 390). */
	.ft-col a,
	.ft-id a {
		display: inline-block;
		min-block-size: var(--tap);
		padding-block: var(--s-2);
	}
}


/* ============================================================================
   THE CLASSES PAGE

   Built on .lg -- the legal screen's document menu beside a long body -- because
   the problem is the same one: four long sections somebody reads one of. What is
   added here is the class-specific furniture: the painting beside the
   introduction, and the two path boxes.
   ========================================================================= */

.cls-lede { font-size: var(--step-1); color: var(--c-ink-dim); margin-block-end: var(--s-6); }

/* THE MENU STAYS ON SCREEN HERE, and does not on /terms. The difference is the
   page, not a preference: the legal documents are one screen of menu beside two
   of text, while this page runs past five thousand pixels. Left in place, the
   menu is four rows at the top of an otherwise empty column the reader scrolls
   past in the first second and cannot use again without going back up. The
   modifier is on the page root so /terms keeps the behaviour it was measured
   with. */
.lg-cls .lgnav {
	position: sticky;
	/* The masthead is fixed; anything sticking to the top of the viewport has to
	   clear it. Same arithmetic as html{scroll-padding-top} -- the announcement
	   strip is not counted because it scrolls away and the bar does not. */
	inset-block-start: calc(var(--bar-h) + var(--s-4));
}

/* THE SECTION THE READER CHOSE, marked in the menu. :target is the only thing
   that knows which of the four is open -- all four are on this one page, so
   until a link is followed none of them is "the current document" the way a
   legal page is. Written against the section rather than the link because the
   fragment names the section; :has carries it back to the menu row, which is
   where the reader is looking. */
.lg-cls:has(#warrior:target)  .lgnav a[href="#warrior"],
.lg-cls:has(#assassin:target) .lgnav a[href="#assassin"],
.lg-cls:has(#sura:target)     .lgnav a[href="#sura"],
.lg-cls:has(#shaman:target)   .lgnav a[href="#shaman"] {
	color: var(--c-gold-hi);
	background: var(--c-gold-tint);
	border-inline-start: var(--bw-mark) solid var(--c-gold);
}

.cls-sec {
	/* The class's colour as a rail down the left. A section that is merely
	   headed by a name looks like the one before it; the rail is what makes
	   four long sections readable as four. */
	border-inline-start: var(--bw-mark) solid var(--c-class, var(--c-line));
	padding-inline-start: var(--s-5);
	margin-block-end: var(--s-7);
	/* The heading must clear the fixed masthead when a card's link lands here,
	   or the name the reader clicked is the one thing hidden behind it. */
	scroll-margin-block-start: calc(var(--bar-h) + var(--s-5));
}
.cls-sec:last-of-type { margin-block-end: var(--s-5); }

.cls-head { display: grid; grid-template-columns: var(--w-class-art) minmax(0, 1fr); gap: var(--s-5); align-items: start; }
.cls-art { border: var(--bw) solid var(--c-line); border-radius: var(--r); width: 100%; height: auto; }
.cls-intro h2 { font-size: var(--step-3); margin-block-end: var(--s-1); }
/* The one line the card carries, in the class's own colour: it is the same
   sentence, so it should look like the same sentence. */
.cls-tactic {
	font-family: var(--f-display);
	font-weight: var(--w-medium);
	font-size: var(--step--1);
	letter-spacing: var(--ls-wide);
	text-transform: uppercase;
	color: var(--c-class, var(--c-ink-faint));
	margin-block-end: var(--s-4);
}
.cls-note { font-size: var(--step--1); color: var(--c-ink-faint); margin-block-end: var(--s-4); }

.cls-paths { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); gap: var(--s-4); }
.cls-path { max-width: none; }
/* The path's name is the game's word for it, so it is set like the game's other
   words on this site: the box heading's micro-label, not a fourth heading rank. */
.cls-path h4 {
	font-family: var(--f-display);
	font-weight: var(--w-medium);
	font-size: var(--step--2);
	letter-spacing: var(--ls-wide);
	text-transform: uppercase;
	color: var(--c-ink-faint);
	margin: 0 0 var(--s-3);
	padding-block-end: var(--s-2);
	border-block-end: var(--bw) solid var(--c-hair);
}
/* A definition list, because that is what it is: a skill and what it does. The
   two master-tier names sit under the description in the faintest ink -- they
   are the same skill later, not a third fact. */
.cls-skills { margin: 0; display: grid; gap: var(--s-3); }
.cls-skills dt {
	font-family: var(--f-display);
	font-weight: var(--w-medium);
	font-size: var(--step-0);
	color: var(--c-ink);
}
.cls-skills dd { margin: 0; display: grid; gap: 2px; }
.cls-what { font-size: var(--step--1); color: var(--c-ink-dim); }
.cls-tier { font-family: var(--f-mono); font-size: var(--step--2); color: var(--c-ink-faint); }

.cls-cta { margin-block-start: var(--s-6); }

/* The painting stops being a column of its own before the text does. Below this
   width a 14rem picture leaves the introduction in a gutter. */
@media (max-width: 51.25rem) {
	.cls-head { grid-template-columns: minmax(0, 1fr); }
	.cls-art { max-width: var(--w-class-art); }
}

/* ---- SHOP ---------------------------------------------------------------- */

/* THE SHELF IS THE GAME'S INVENTORY, SEEN FROM THE WEB. Every icon here is a
   sprite the player will later find in a square in their bag, so the square is
   drawn around it rather than dropped: a grid of loose icons reads as a
   catalogue of pictures, a grid of slots reads as things you can own. That is
   the one borrowed idiom on the page and everything else is the site's
   ordinary vocabulary -- panel, hairline, gold for money. */

.shop-head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--s-4) var(--s-5);
}
.shop-title { min-width: 0; }
.shop-narrow { max-width: var(--w-conf); }
.shop-note { color: var(--c-ink-dim); }
.shop-back { margin-block-end: var(--s-4); font-size: var(--step--1); }
.shop-back a { color: var(--c-ink-dim); }
.shop-back a:hover { color: var(--c-gold); }

/* THE SLOT. Recessed rather than raised -- an inset well with a hairline -- so
   it reads as a socket the icon is sitting in. The icon is centred and NEVER
   scaled up past its own pixels: max-width/height only. A 32x32 sprite blown up
   to fill 4.5rem is a blurred smear, and image-rendering: pixelated is the
   answer only when the scale is a whole multiple, which it is not for every
   icon in the game. */
.slot {
	position: relative;
	overflow: hidden;
	display: grid;
	place-items: center;
	inline-size: var(--sz-slot);
	block-size: var(--sz-slot);
	background: var(--c-well);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r-sm);
	box-shadow: inset 0 1px 0 rgb(0 0 0 / .35);
}
/* ABSOLUTE, NOT PERCENTAGE SIZED -- measured, not assumed. With
   `max-block-size: 100%` the browser resolved the height as auto and a 32x64
   costume icon came out at twice the slot's height, hanging over the name and
   the row below it. Anchoring to the slot's own box with inset:0 makes the
   height definite; object-fit keeps the sprite's proportions inside it. */
.slot img {
	position: absolute;
	inset: 0;
	inline-size: 100%;
	block-size: 100%;
	object-fit: contain;
	image-rendering: pixelated;
}
.slot-lg { inline-size: var(--sz-slot-lg); block-size: var(--sz-slot-lg); }

/* ---- one product --------------------------------------------------------- */

.prod {
	display: grid;
	grid-template-columns: var(--sz-slot-lg) minmax(0, 1fr);
	gap: var(--s-5) var(--s-6);
	align-items: start;
}
/* THE TEXT COLUMN IS CAPPED AT THE MEASURE, and everything in it -- heading,
   description, the rule above and below the price -- is capped at the SAME
   place. Left to the grid the heading ran a thousand pixels wide while the
   price rule stopped at the measure underneath it, which reads as a rule that
   broke rather than as a column that ends. */
.prod-body { display: grid; gap: var(--s-3); min-width: 0; max-inline-size: var(--measure); }
.prod-body h1 { margin: 0; }
.prod-desc { color: var(--c-ink-dim); max-inline-size: var(--measure); margin: 0; }
.prod-price {
	display: flex;
	align-items: baseline;
	gap: var(--s-3);
	margin: 0;
	padding-block: var(--s-3);
	border-block: var(--bw) solid var(--c-hair);
}
.prod-price > span {
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-kicker);
	color: var(--c-ink-faint);
}
.prod-price strong {
	font-family: var(--f-display);
	font-size: var(--step-2);
	color: var(--c-gold);
	font-variant-numeric: tabular-nums;
}
.prod-price em { font-style: normal; font-size: var(--step--1); color: var(--c-gold-dim); }

/* The quantity and the button on one line, and the field only as wide as four
   digits: a number input stretched across the column invites a number nobody
   meant to type. */
.prod-buy { grid-auto-flow: column; justify-content: start; align-items: end; gap: var(--s-3); }
.prod-qty { inline-size: 6rem; }
.prod-bal { margin: 0; font-size: var(--step--1); color: var(--c-ink-dim); }
.prod-short { margin: 0; font-size: var(--step--1); color: var(--c-danger-ink); }
.prod-short a { margin-inline-start: var(--s-2); color: var(--c-gold); }
.prod-note { margin: 0; font-size: var(--step--1); color: var(--c-ink-faint); }

/* ---- confirm, and the code form ------------------------------------------ */

.conf { display: grid; gap: var(--s-4); }
.conf-lede { margin: 0; color: var(--c-ink-dim); }
.conf-what { display: flex; align-items: center; gap: var(--s-4); }
.conf-n { font-weight: var(--w-semibold); display: grid; gap: 2px; min-width: 0; }
.conf-q { font-style: normal; font-size: var(--step--1); color: var(--c-ink-dim); font-weight: var(--w-regular); }

/* THE ARITHMETIC. Three rows, the middle one gold, and the numbers right-aligned
   on a tabular figure so the three line up as a sum rather than as three
   separate facts. */
.conf-sum { border-block-start: var(--bw) solid var(--c-hair); padding-block-start: var(--s-4); }
.conf-sum dd { font-variant-numeric: tabular-nums; }
.conf-pay { color: var(--c-gold); font-weight: var(--w-semibold); }

.conf-go { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }
.conf-note { margin: 0; font-size: var(--step--1); color: var(--c-ink-faint); }

/* A code is copied character by character off a printed block, so it is set in
   the monospaced face and upper-cased as it is typed -- l and 1 have to look
   different here. */
.code-in { font-family: var(--f-mono); text-transform: uppercase; letter-spacing: var(--ls-wide); }

/* The product's picture stops being a column of its own before the text does,
   and the purse stops sharing a line with the title: side by side at 390 the
   heading and the balance each get half a phone and neither is readable. */
@media (max-width: 40rem) {
	.prod { grid-template-columns: minmax(0, 1fr); }
}

/* A SUBMIT BUTTON DRAWN AS THE LINK IT REPLACED. The "load EP" control has to
   be a POST -- it mints a one-time ticket, and minting is a write -- but inside
   a sentence ("Bakiyen yetmiyor. EP yükle") a button would break the line. So
   the markup is honest and the paint is not: everything a browser puts on a
   button is removed, and what is left is the anchor's own rule. */
.btn-plain {
	appearance: none;
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
	font: inherit;
	color: var(--c-gold);
	cursor: pointer;
	text-decoration: underline;
	text-underline-offset: 2px;
}
.btn-plain:hover { color: var(--c-gold-hi); }
.btn-plain:focus-visible { outline: 2px solid var(--c-gold); outline-offset: 2px; }
/* The form is a wrapper, not a block: it sits inside the sentence it belongs
   to rather than pushing the rest of it onto its own line. */
.prod-short .inline, .purse-do .inline { display: inline; }

/* ---- SHOP: THE COUNTER --------------------------------------------------- */

/* Earlier drawings: a sparse card grid, a stacked list, an asymmetric bento, a
   dense seven-across inventory. The first three made the item small inside a
   large empty container; the fourth had the right idea at the wrong scale --
   squares small enough to manage rather than to look at. This one gives each
   item a counter box big enough to hold the art, what it does, the price and
   the way in. */

/* THE BALANCE, IN THE MASTHEAD. It was a full-width strip under the page's
   heading first; a shopper looks for a balance top right, beside the account,
   the way every shop they have used puts it -- and there it is on every page
   rather than only inside the shop. Drawn like the beta and live chips it sits
   between, in gold because it is money. */
.ep-chip {
	appearance: none;
	background: none;
	cursor: pointer;
	font: inherit;
	display: inline-flex;
	align-items: baseline;
	gap: 3px;
	padding: var(--s-1) var(--s-3);
	border: var(--bw) solid var(--c-gold-edge);
	border-radius: var(--r);
	font-size: var(--step--1);
	color: var(--c-gold-dim);
	font-variant-numeric: tabular-nums;
	transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.ep-chip b { font-family: var(--f-display); font-weight: var(--w-semibold); color: var(--c-gold); }
.ep-chip:hover { background: var(--c-gold-wash); color: var(--c-gold); }

/* The shelves as a filter strip beside the heading -- the way the in-game
   window has them. Drawn as a rail down the left once: it cost fifteen rems of
   width. Drawn as four stacked sections once: eight products across four of
   them left four half-empty rows and a screen of space. */
.shop-top { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--s-3) var(--s-5); margin-block-end: var(--s-4); }
.shelf-strip { display: flex; flex-wrap: wrap; gap: var(--s-1); }
.shelf-strip a {
	padding: var(--s-2) var(--s-3);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	font-family: var(--f-display);
	font-size: var(--step--1);
	text-transform: uppercase;
	letter-spacing: var(--ls-tab);
	color: var(--c-ink-dim);
	transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.shelf-strip a:hover { color: var(--c-ink); border-color: var(--c-gold-dim); }
.shelf-strip a.on { color: var(--c-ink); border-color: var(--c-gold-edge); background: var(--c-panel); }
/* The link at the end of the strip is a way out of it, not another shelf, so
   it carries no box. */
.strip-end {
	align-self: center;
	margin-inline-start: var(--s-2);
	border: 0;
	padding-inline: 0;
	text-transform: none;
	letter-spacing: 0;
	font-family: var(--f-text);
}
.shelf-strip .inline { display: inline-flex; align-items: center; }

.stall {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(var(--w-box), 1fr));
	gap: var(--s-4);
}
.box {
	position: relative;
	display: grid;
	justify-items: center;
	gap: var(--s-2);
	height: 100%;
	padding: var(--s-5) var(--s-4) var(--s-4);
	text-align: center;
	color: inherit;
	background: linear-gradient(180deg, var(--c-panel), var(--c-ground-2));
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
	overflow: hidden;
	transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.box:hover { border-color: var(--c-gold-edge); }
.box:focus-visible { outline: 2px solid var(--c-gold); outline-offset: 2px; }

/* The site's own Greek key across the head of every box: the ornament that
   already marks the masthead's lower edge and the footer's upper one, at the
   one other place where something is presented rather than listed. No new
   file, no new request. */
.box-key {
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: var(--h-key);
	background: url("/assets/img/ornament.png") repeat-x center / auto 100%;
	opacity: .35;
}

/* THE FRAME IS THE SIGNATURE: an inventory square. A recessed well, a hairline,
   a black line inset a pixel inside it -- which is what makes a box read as
   forged rather than as a div -- and four corner ticks, drawn with borders
   rather than an image. */
.frame {
	position: relative;
	display: block;
	padding: var(--s-2);
	background: linear-gradient(180deg, var(--c-raise), var(--c-well));
	border: var(--bw) solid var(--c-line-hi);
	border-radius: var(--r-sm);
	box-shadow: inset 0 0 0 1px rgb(0 0 0 / .45), inset 0 2px 6px rgb(0 0 0 / .35);
}
.box:hover .frame { border-color: var(--c-gold-edge); }
.frame::before, .frame::after {
	content: "";
	position: absolute;
	inline-size: 11px;
	block-size: 11px;
	border-color: var(--c-gold-dim);
	opacity: .5;
	transition: opacity var(--t-fast) var(--ease);
}
.frame::before { inset-block-start: 4px; inset-inline-start: 4px; border-block-start: 1px solid; border-inline-start: 1px solid; }
.frame::after  { inset-block-end: 4px;  inset-inline-end: 4px;  border-block-end: 1px solid;  border-inline-end: 1px solid; }
.box:hover .frame::before, .box:hover .frame::after { opacity: 1; }
/* Inside a frame the slot is only a box of the right size: the well, the
   hairline and the shadow belong to the frame. */
.frame .slot { background: none; border: 0; box-shadow: none; border-radius: 0; }
.slot-xl { inline-size: var(--sz-slot-xl); block-size: var(--sz-slot-xl); }

/* How many the pack holds, in the corner of the square -- where the game puts a
   stack count and where a player already looks for it. */
.qty {
	position: absolute;
	inset-block-end: 4px;
	inset-inline-end: 6px;
	font-style: normal;
	font-family: var(--f-mono);
	font-size: var(--step--1);
	color: var(--c-ink);
	text-shadow: 0 1px 2px #000, 0 0 3px #000;
}
.flag {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	font-style: normal;
	font-size: var(--step--2);
	line-height: 1;
	padding: 3px 5px;
	background: var(--c-gold);
	color: var(--c-gold-ink);
	border-radius: var(--r-sm) 0 var(--r-sm) 0;
	text-transform: uppercase;
	letter-spacing: var(--ls-tab);
}

.box-name {
	font-family: var(--f-display);
	font-size: var(--step-1);
	line-height: var(--lh-tight);
	color: var(--c-ink);
	margin-block-start: var(--s-2);
}
.box-desc {
	font-size: var(--step--1);
	line-height: var(--lh-tight);
	color: var(--c-ink-dim);
	max-inline-size: 30ch;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}
/* The price and the way in share the box's floor under a hairline: above the
   line is what the thing IS, below it is what it costs and what happens next. */
.box-foot {
	inline-size: 100%;
	margin-block-start: auto;
	padding-block-start: var(--s-3);
	border-block-start: var(--bw) solid var(--c-hair);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--s-3);
}
.box-price {
	font-family: var(--f-display);
	font-size: var(--step-2);
	font-weight: var(--w-semibold);
	color: var(--c-gold);
	font-variant-numeric: tabular-nums;
}
/* Drawn as a button and deliberately not one: the whole box is the link, and a
   real button inside it would be a second target for the same journey. */
.box-go {
	font-family: var(--f-display);
	font-size: var(--step--1);
	text-transform: uppercase;
	letter-spacing: var(--ls-tab);
	color: var(--c-gold-ink);
	background: var(--c-gold);
	border-radius: var(--r);
	padding: var(--s-2) var(--s-4);
	transition: background var(--t-fast) var(--ease);
}
.box:hover .box-go { background: var(--c-gold-hi); }
.box-off .slot img { opacity: .5; }
.box-off .box-price { color: var(--c-ink-faint); }
.box-off .box-price em { color: var(--c-ink-faint); }
/* Out of reach: the way in stays -- the product page is where the reason and
   the top-up link are -- but it stops shouting. */
.box-off .box-go { background: none; color: var(--c-ink-dim); box-shadow: inset 0 0 0 1px var(--c-line-hi); }

/* ---- the order list ----------------------------------------------------- */

/* A SLIP, IN THE SHOP'S OWN VOCABULARY. The same framed square, the same
   display face, the same gold figure -- what you bought drawn like what you can
   buy -- with the state of the order as the one thing that differs. Two earlier
   drawings: the account page's table borrowed whole, then a run of hairlines
   too thin for the page's only content. */
.bill { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.slip {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	gap: var(--s-4);
	padding: var(--s-3) var(--s-4);
	background: var(--c-panel);
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r);
}
.frame-sm { padding: 3px; }
.frame-sm .slot { inline-size: 3rem; block-size: 3rem; }
.slip-text { display: grid; gap: 2px; min-width: 0; }
.slip-name {
	font-family: var(--f-display);
	font-size: var(--step-0);
	color: var(--c-ink);
	overflow-wrap: anywhere;
}
.slip-when { font-size: var(--step--1); color: var(--c-ink-faint); font-variant-numeric: tabular-nums; }
.slip-end { display: grid; justify-items: end; gap: var(--s-1); }
.slip-price {
	font-family: var(--f-display);
	font-size: var(--step-1);
	font-weight: var(--w-semibold);
	color: var(--c-gold);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}
.slip-price em { font-style: normal; font-size: var(--step--2); color: var(--c-gold-dim); margin-inline-start: 2px; }

/* An account that has bought nothing gets a sentence and a way to the shop --
   not an empty box, and not a table with no rows in it. */
.bill-empty {
	display: grid;
	justify-items: start;
	gap: var(--s-4);
	padding: var(--s-7) 0;
}
.bill-empty p { margin: 0; color: var(--c-ink-dim); }

/* THE STATE OF AN ORDER, AS A CHIP. Three tones, not six: a player scanning
   their purchases is looking for the one that went wrong. */
.chip {
	font-size: var(--step--2);
	white-space: nowrap;
	border: var(--bw) solid var(--c-line);
	border-radius: var(--r-sm);
	padding: 1px var(--s-2);
	color: var(--c-ink-dim);
}
.chip-ok   { color: var(--c-ok);         border-color: var(--c-ok-line); }
.chip-wait { color: var(--c-gold);       border-color: var(--c-gold-edge); }
.chip-bad  { color: var(--c-danger-ink); border-color: var(--c-danger-line); }
.chip-plain { color: var(--c-ink-dim); }

/* ---- EP yükle ------------------------------------------------------------ */

/* A split, not a centred card: the figure that is about to change on the left,
   the one field that changes it beside it. */
.topup {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
	gap: var(--s-6);
	align-items: start;
	padding-block-start: var(--s-3);
	border-block-start: var(--bw) solid var(--c-hair);
}
.topup-h {
	margin: 0;
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-kicker);
	color: var(--c-ink-faint);
}
.topup-n {
	margin: 0;
	font-family: var(--f-display);
	font-size: var(--step-5);
	font-weight: var(--w-bold);
	line-height: var(--lh-tight);
	color: var(--c-gold);
	font-variant-numeric: tabular-nums;
}
.topup-added { margin: 0; color: var(--c-ok); }
.topup-form { justify-items: start; }

@media (max-width: 40rem) {
	.prod { grid-template-columns: minmax(0, 1fr); }
	.topup { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
	.slip { grid-template-columns: auto minmax(0, 1fr); gap: var(--s-3); }
	.slip-end { grid-column: 2; justify-items: start; display: flex; align-items: center; gap: var(--s-2); }
}
/* How many the pack holds, beside the NAME rather than near the price: it is
   part of what the thing is, not of what it costs. */
.shelf-x { font-style: normal; color: var(--c-ink-faint); font-weight: var(--w-regular); }
.chip-new {
	font-style: normal;
	font-size: var(--step--2);
	text-transform: uppercase;
	letter-spacing: var(--ls-tab);
	color: var(--c-gold);
	border: var(--bw) solid var(--c-gold-edge);
	border-radius: var(--r-sm);
	padding: 1px var(--s-1);
	margin-inline-start: var(--s-2);
	vertical-align: middle;
}
/* The unit beside a price is smaller and dimmer than the figure, and upright:
   <em> is the right element (it is an aside to the number) and the wrong
   default look. */
.box-price em, .topup-n em, .ep-chip em {
	font-style: normal;
	font-size: var(--step--1);
	font-weight: var(--w-medium);
	color: var(--c-gold-dim);
	margin-inline-start: 2px;
}
