/* ===========================================================================
   loading.css — the MAVEN RAGNAROK loading screen.

   Replaces the text readout ("Downloading the game engine · roBrowserLegacy —
   your browser caches this after the first load · Size not yet known · 2.6 MB
   so far") with a loading screen in the game's own language.

   CLASSIC RESKIN, 2026-09-03 (Ramil: "make the OLD classic loading screen of
   ragnarok then just add the LOADING of the game data there"). The parchment
   plate, gold Cinzel wordmark and rotating tips are gone. This is now the 2002
   client's screen: one of the GRF's own loading plates centred on black,
   letterboxed at its native aspect, with a thin squared blue progress bar at
   the bottom — the classic bar, carrying the game-data byte counts.
   ======================================================================== */

#mvl {
	position: fixed;
	inset: 0;
	z-index: 99999;
	display: grid;
	grid-template-rows: 1fr auto;
	overflow: hidden;
	/* Black, like the client letterboxing a 4:3 plate on a wide screen. */
	background: #000;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity .45s ease, visibility 0s linear .45s;
	/* Nothing in here is selectable or draggable — it is a curtain. */
	user-select: none;
	-webkit-user-select: none;
}

/* NOTE THE MISSING `pointer-events`. It is `none` on #mvl above and it is
   never turned back on, in any state. The first version set `auto` here, and
   when the hide logic failed the result was a full-screen sheet that ate every
   click and locked players out of the game. A loading screen is a picture; it
   has nothing to receive a tap FOR. Do not add pointer-events to this rule. */
#mvl[data-on='true'] {
	opacity: 1;
	visibility: visible;
	transition: opacity .28s ease, visibility 0s;
}

/* -- the plate ----------------------------------------------------------- */

#mvl .mvl__scene {
	position: absolute;
	inset: 0;
	overflow: hidden;
}

/* The classic plate. `contain`, never `cover`: the old client's art is 4:3 and
   the whole point is showing the picture as drawn, black bars and all. */
#mvl .mvl__plate {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	object-position: 50% 50%;
	display: block;
	opacity: 0;
	transition: opacity .35s ease;
}
#mvl .mvl__plate[data-in='true'] { opacity: 1; }

/* -- the foot: note, bar, readout ---------------------------------------- */

/* A low black fade so the readout stays legible when the plate's bottom edge
   is bright. On the letterbox bars it disappears into the black. */
#mvl .mvl__foot::before {
	content: '';
	position: absolute;
	left: 0; right: 0; bottom: 0;
	height: calc(100% + 40px);
	background: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, .5) 55%, rgba(0, 0, 0, .72));
	pointer-events: none;
	z-index: -1;
}

#mvl .mvl__foot {
	/* Row 2 explicitly. The brand block used to hold row 1 and push the foot
	   down; with it gone the foot would auto-place into the 1fr row and float
	   to the TOP of the screen. Pin it to the bottom `auto` row instead. */
	grid-row: 2;
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(5px, .9vh, 10px);
	padding: 0 clamp(18px, 6vw, 92px) clamp(14px, 3.6vh, 36px);
}

/* The one-line "first time only" note (paintAssets). Plain small print, not a
   styled pill — nothing on the classic screen is decorated. */
#mvl .mvl__tip {
	max-width: min(760px, 88%);
	min-height: 1.4em;
	font-family: "Barlow Semi Condensed", "Barlow Semi Condensed Fallback", "Roboto Condensed", sans-serif;
	font-size: clamp(10px, 1.2vw, 14px);
	line-height: 1.4;
	color: #cfd6e4;
	text-align: center;
	text-shadow: 0 1px 3px rgba(0, 0, 0, .9);
	opacity: 0;
	transition: opacity .5s ease;
}
#mvl .mvl__tip[data-in='true'] { opacity: .9; }

/* THE CLASSIC BAR. Squared corners, a steel hairline, a dark channel and a
   pale-blue fill — the shape every RO player has watched a thousand times.
   Centred at a fixed-ish width rather than running edge to edge. */
#mvl .mvl__bar {
	position: relative;
	width: min(620px, 84%);
	height: clamp(11px, 1.8vh, 15px);
	border-radius: 0;
	background: rgba(6, 9, 16, .85);
	box-shadow:
		0 0 0 1px #98a2b4,
		inset 0 0 0 1px #05070c,
		0 1px 8px rgba(0, 0, 0, .8);
	overflow: hidden;
}

#mvl .mvl__bar > i {
	display: block;
	height: 100%;
	width: 0%;
	border-radius: 0;
	background: linear-gradient(180deg, #d8eeff 0%, #8cc4f4 40%, #3d80cf 55%, #2b5fa8 100%);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65);
	transition: width .3s cubic-bezier(.3, .9, .4, 1);
}

/* The leading edge glows, so movement is legible even at 2% */
#mvl .mvl__bar > i::after {
	content: '';
	position: absolute;
	top: 0;
	bottom: 0;
	width: 26px;
	margin-left: -26px;
	left: var(--mvl-edge, 0%);
	background: linear-gradient(90deg, rgba(225, 240, 255, 0), rgba(235, 246, 255, .85));
	pointer-events: none;
}

/* Unknown total: the engine reports bytes with no content-length for a while.
   A striped crawl says "working" without inventing a percentage. */
/* Unknown total: a single travelling sweep, not barrier tape. The striped
   full-width fill read as a hazard sign across the bottom of the plate. */
#mvl .mvl__bar[data-mode='unmeasured'] > i {
	width: 34% !important;
	opacity: .95;
	animation: mvl-crawl 1.9s cubic-bezier(.55, 0, .45, 1) infinite;
}
#mvl .mvl__bar[data-mode='unmeasured'] > i::after { display: none; }
@keyframes mvl-crawl {
	0%   { transform: translateX(-105%); }
	100% { transform: translateX(305%); }
}

/* The readout shares the bar's width so the numbers hang off its ends, the
   way the classic client sets its "Loading..." line against the bar. */
#mvl .mvl__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	width: min(620px, 84%);
	font-family: "Barlow Semi Condensed", "Barlow Semi Condensed Fallback", "Roboto Condensed", sans-serif;
	font-size: clamp(10px, 1.2vw, 14px);
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: #dfe6f2;
	text-shadow: 0 1px 3px rgba(0, 0, 0, .9);
}
#mvl .mvl__pct {
	font-variant-numeric: tabular-nums;
	color: #eaf4ff;
	letter-spacing: .1em;
}

/* -- portrait phone: no room for the note above the bar ------------------ */
@media (orientation: portrait) and (max-width: 700px) {
	#mvl .mvl__tip { display: none; }
}
/* -- landscape phone: very little height, so trim the padding ----------- */
@media (orientation: landscape) and (max-height: 460px) {
	#mvl .mvl__foot { padding-bottom: clamp(8px, 3vh, 18px); }
	#mvl .mvl__tip { font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
	#mvl .mvl__bar[data-mode='unmeasured'] > i { animation: none; }
	#mvl .mvl__plate { transition: opacity .2s ease; }
}

/* ===========================================================================
   THE READOUT THIS REPLACES

   The page's own progress panel, in full:

     Downloading the game engine
     roBrowserLegacy — your browser caches this after the first load.
     186 KB so far · Size not yet known
     Preflight            ok    WebGL 2 · secure origin · 3/3 servers up.
     Game client          13.1 KB   Requesting client/bootstrap.js
     Map & sprite data    186 KB
     Entering Midgard     Login server, then character server, then map server.
     [ Download the client instead ]

   An engineer's panel, and Ramil asked for it gone. The nodes STAY — play.js
   writes to them continuously and loading.js reads them to drive its own bar,
   so deleting them would break the thing that replaced them. They are hidden.

   An earlier version scoped this to `html.mvl-live`, which is only set WHILE
   the curtain is up — so the whole wall reappeared the moment it hid. This is
   unconditional.

   TWO EXCEPTIONS, deliberately kept:
     · `#stage-alert` — the error panel. If the client cannot start, this is
       the only thing that says why. Hiding it would turn every failure into a
       blank screen.
     · the retry / download row, which is the way out of such a failure. It is
       hidden while things are going well and comes back with the alert.
   ======================================================================== */

#play-loader .play-loader__crest,
#play-loader .play-loader__title,
#play-loader .play-loader__sub,
#play-loader .play-meterblock,
#play-loader .play-phases,
#play-loader .rag-row {
	display: none !important;
}

/* With its contents gone the card is an EMPTY BOX THAT STILL COVERS THE FIELD.
   Measured: 854px tall, and `elementFromPoint` at the centre of the client
   returned `play-loader` — an invisible sheet over the game, which is the same
   defect as the lockout wearing different clothes. Caught in staging by the
   "clicks reach the client" assertion, which is why that assertion exists.

   `pointer-events: none` rather than `display: none`: play.js keeps writing to
   the nodes inside and loading.js keeps reading them, so the box must stay in
   the layout — it just must not be able to receive anything. */
#play-loader:not(:has(#stage-alert:not([hidden]))) {
	background: none !important;
	border: 0 !important;
	box-shadow: none !important;
	padding: 0 !important;
	min-height: 0 !important;
	backdrop-filter: none !important;
	pointer-events: none !important;
}

/* Something went wrong: give back the reason and the escape hatches — and the
   hit-testing they need to be usable. */
#play-loader:has(#stage-alert:not([hidden])) {
	pointer-events: auto !important;
}
#play-loader:has(#stage-alert:not([hidden])) .rag-row {
	display: flex !important;
}
#play-loader #stage-alert:not([hidden]),
#play-loader:has(#stage-alert:not([hidden])) .rag-row * {
	pointer-events: auto !important;
}


/* ===========================================================================
   THE PAGE ITSELF — "that page should just be a plain username and pasword
   and game client to be exact", per Ramil.

   Signing in already goes straight into the client; there is no separate PLAY
   step. So what stands between a player and the game is furniture: a masthead
   of site navigation above the login card, and a legal slab under the client
   deep enough to make the page scroll.

   BOTH ARE SUPPRESSED, NOT DELETED. This is a stylesheet — remove the block
   from index.html and the page is exactly as it was. Nothing here edits the
   markup, so nothing here can lose anything.

   TWO THINGS DELIBERATELY KEPT:
     · the register link inside the login card — it is the only route onto the
       server, and hiding it would strand every new player
     · the trademark line — this is a fan server, and "Ragnarok Online is a
       trademark of Gravity Co., Ltd ... not affiliated with, endorsed by, or
       sponsored by" is the sentence that says so. It is now one quiet line
       instead of a slab, but it is still there, and it should stay there.
   ======================================================================== */

/* The masthead goes on the LANDING only. In game it carries the account name
   and LEAVE THE GAME, which are the only way back out. `#play-stage` is
   `hidden` until the client is launched, which is the page's own signal. */
body:has(#play-stage[hidden]) .rag-masthead { display: none !important; }

/* The footer becomes a caption rather than a floor. */
.rag-footer {
	padding: 4px 12px !important;
	background: none !important;
	border: 0 !important;
	box-shadow: none !important;
}
.rag-footer__legal {
	display: block !important;
	padding: 0 !important;
	font-size: 9.5px !important;
	line-height: 1.5 !important;
	text-align: center !important;
	opacity: .5;
}
/* The age badge is a 32px graphic in a line of 9.5px small print, and it was
   the whole of the footer's remaining height. Its real class is
   `.rag-footer__pegi` — an earlier guess at `.rag-badge` matched nothing. */
.rag-footer__pegi,
.rag-footer__legal img,
.rag-footer__legal svg { display: none !important; }
.rag-footer, .rag-footer__legal { min-height: 0 !important; }

/* NO `display:flex` HERE. An earlier version made .rag-main a flex container
   to centre the login card; it collapsed the full-bleed hero to 37% of the
   width and left two thirds of the page blank. The card was already placed
   correctly — removing the masthead did not move it — so this only asks the
   section to fill the height the masthead used to occupy. */
/* The height has to go on the element that CARRIES THE BACKGROUND, which is
   `main.rag-section`, not the `.rag-main` wrapper around it — with it on the
   wrapper the art stopped short and a grey band showed underneath it.
   66px is the measured height of the trimmed footer, so art + footer is exactly
   one screen and nothing scrolls. */
body:has(#play-stage[hidden]) .rag-main,
body:has(#play-stage[hidden]) main.rag-section {
	min-height: calc(100vh - 66px);
}

/* ===========================================================================
   THE LOGIN BACKGROUND — Ramil's own key art (mavenroasset/bg.webp).

   theme-sync.css dresses the gate with `/bg/bg01.webp` under a heavy white
   veil (0.72 → 0.9 alpha), which is right for a soft anime plate and wrong for
   this one: the veil would wash out the very thing that makes it worth using.
   The scrim here is a tenth of that, and only enough to keep the page's own
   small print readable at the edges.

   No scrim is needed behind the login card itself — the card is an opaque
   parchment panel with its own border, so it reads over anything.

   Served from /loading/ rather than /bg/ so the whole change (art, sheet,
   script) remains one deployable with one rollback. bg01.webp is untouched.
   ======================================================================== */

body:has(#play-stage[hidden]) main.rag-section,
body:has(#play-stage[hidden]) .rag-section--tight {
	background:
		linear-gradient(180deg,
			rgba(255, 253, 248, .06) 0%,
			rgba(255, 253, 248, .10) 62%,
			rgba(253, 250, 242, .30) 100%),
		url('/loading/login.webp') center center / cover no-repeat,
		/* the sky in the art, so there is no white flash before it decodes */
		#8fc4e8 !important;
	background-attachment: scroll !important;
}

/* Portrait crops a 1.79 plate hard. Bias left-of-centre so the wordmark
   survives the crop rather than the empty sky between the two halves. */
@media (orientation: portrait) {
	body:has(#play-stage[hidden]) main.rag-section,
	body:has(#play-stage[hidden]) .rag-section--tight {
		background-position: 38% center, 38% center !important;
	}
}

/* ── the login card is CENTRED, on every width ────────────────────────────
   Ramil, 2026-08-30: "on Desktop UI put the Login input on the Middle again."

   This block used to send it to the right:

       justify-self: end; margin-right: clamp(16px, 5vw, 110px);

   The reason recorded at the time was that a centred card sits across the
   RAGNARÖK wordmark, which is the one thing on the plate that has to stay
   legible. That is still true and it is the cost of this change — the card now
   overlaps the lower half of the wordmark on a wide screen. Asked for
   explicitly, so it is a decision, not a regression; the note is here so the
   next person does not "fix" it back.

   `justify-self: center` rather than deleting the block. `main.rag-section` is
   `display: grid` (measured), and the card is a grid ITEM with a fixed
   `width: min(460px, 100%)` from theme-sync.css — so the axis is controlled by
   justify-self, and an explicit `center` is a smaller, more legible statement
   than relying on which auto-margin rule happens to survive the cascade once
   this override is gone. */
html:not(.mvm-shell) body:has(#play-stage[hidden]) main.rag-section > .rag-wrap {
	justify-self: center;
	margin-right: auto;
	margin-left: auto;
}

/* MOBILE KEEPS IT CENTRED, per Ramil.
   `min-width: 720px` alone was not enough: a phone in landscape is 852 or 915
   CSS px wide, so it matched the desktop branch and the card went to the right
   edge. `html.mvm-shell` is set by the mobile gate itself — coarse pointer AND
   a short edge under 900px — so it is the honest test for "this is a phone",
   which a width query is not. */
html.mvm-shell body:has(#play-stage[hidden]) main.rag-section > .rag-wrap {
	justify-self: center !important;
	margin-left: auto !important;
	margin-right: auto !important;
}

/* The footer carries a 96px top margin from the site layout — a gap that made
   sense under a page of content and is just dead scroll under a login card.
   Measured: it WAS the entire overflow on desktop (96px of 96px). */
body:has(#play-stage[hidden]) .rag-footer {
	margin-top: 0 !important;
}

/* A short landscape phone cannot fit the card plus the section's normal
   padding — measured 475px of section on a 393px screen. Give the padding
   back rather than make someone scroll to reach the password field. */
@media (max-height: 560px) {
	body:has(#play-stage[hidden]) main.rag-section {
		padding-top: clamp(6px, 2vh, 20px) !important;
		padding-bottom: clamp(6px, 2vh, 20px) !important;
		min-height: calc(100vh - 66px) !important;
	}
}

/* On a narrow screen the trademark sentence wraps to four or five lines and
   the footer becomes taller than the login card — 135px on a 393px-wide
   phone. It is small print; let it be small. */
@media (max-width: 900px) {
	.rag-footer { padding: 2px 10px !important; }
	.rag-footer__legal { font-size: 8px !important; line-height: 1.4 !important; }
}

/* ── the asset phase ───────────────────────────────────────────────────────
   Ramil, 2026-08-29: "make the Download Game data FORCE ... after login it
   will force a Loading remove the other loading before the Character selection
   replace with game data Loading."

   THIS IS THE ONLY RULE IN THE FILE THAT LETS THE CURTAIN TAKE A TAP, and the
   header of loading.js explains at length why that used to be forbidden. It is
   scoped to one attribute that JS sets only while the 71.7 MB pack is still
   incomplete, and which THREE independent releases remove — a 25 s stall
   watchdog, a bare 10-minute setTimeout armed outside every loop and promise
   chain, and a catch around the whole branch. Anything that leaves this
   attribute set with the download finished IS the bug.
   ---------------------------------------------------------------------- */
#mvl[data-assets='true'] {
	pointer-events: auto;
}

/* A download is a wait with a known end, so the readout earns more room than
   the engine's "size not yet known" ever did. */
#mvl[data-assets='true'] .mvl__stat {
	font-variant-numeric: tabular-nums;
	letter-spacing: .01em;
}
