:root { --rank-background-color: #4b341d; --rank-background-image: none; --rank-frame-slice: 20%; }
/* Each place reads its own sizes and positions (--rank-<place>-…, set by applyRankAppearance from the
   editor's Rank tab): the emblem through --rank-emblem-current-*, the frame through --rank-frame-current-*. */
#gameScreen .menu-overlay:has(#rankMenu:not([hidden])) { position: absolute; inset: 0; z-index: 150; box-sizing: border-box; width: 100%; height: 100%; max-height: none; border-radius: 0; box-shadow: var(--z-frame); }
.rank-emblem, .podium-rank-badge, .team-result-rank-badge, #playerProfileRankSprite {
  transform: translate(calc(var(--rank-emblem-current-x, 0) * 1px), calc(var(--rank-emblem-current-y, 0) * 1px)) scale(var(--rank-emblem-current-scale, 1));
  transform-origin: center;
}
.rank-emblem { --rank-emblem-current-x: var(--rank-rank-emblem-x); --rank-emblem-current-y: var(--rank-rank-emblem-y); --rank-emblem-current-scale: var(--rank-rank-emblem-scale); }
.podium-rank-badge, .team-result-rank-badge { --rank-emblem-current-x: var(--rank-result-emblem-x); --rank-emblem-current-y: var(--rank-result-emblem-y); --rank-emblem-current-scale: var(--rank-result-emblem-scale); }
/* In the profile the size grows the emblem's own box (player-profile.css): the text moves aside instead of being covered. */
#playerProfileRankSprite { --rank-emblem-current-x: var(--rank-profile-emblem-x); --rank-emblem-current-y: var(--rank-profile-emblem-y); --rank-emblem-current-scale: 1; }
.player-name.has-rank-art { --rank-frame-current-x: var(--rank-hall-frame-x); --rank-frame-current-y: var(--rank-hall-frame-y); --rank-frame-current-scale: var(--rank-hall-frame-scale); --rank-frame-current-thickness: var(--rank-hall-frame-thickness); }
#playerProfilePhoto { --rank-frame-current-x: var(--rank-profile-frame-x); --rank-frame-current-y: var(--rank-profile-frame-y); --rank-frame-current-scale: var(--rank-profile-frame-scale); --rank-frame-current-thickness: var(--rank-profile-frame-thickness); }
.podium-player, .team-result-card { --rank-frame-current-x: var(--rank-result-frame-x); --rank-frame-current-y: var(--rank-result-frame-y); --rank-frame-current-scale: var(--rank-result-frame-scale); }
.player-name.has-rank-art,
.rank-mine-emblem, #playerProfilePhoto {
  background-color: var(--rank-background-color);
  background-image: var(--rank-background-image);
  background-position: center;
  background-size: cover;
  image-rendering: pixelated;
}
.player-name.has-rank-art .player-name-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.player-name.has-rank-art { border: 0; padding: calc(2 * var(--player-unit) + var(--rank-frame-current-thickness, 4) * 1px) calc(3 * var(--player-unit) + var(--rank-frame-current-thickness, 4) * 1px); }
.player-name.has-rank-art::after, #playerProfilePhoto::after {
  content: ''; position: absolute; inset: 0; z-index: 2; box-sizing: border-box;
  border: calc(var(--rank-frame-current-thickness, 4) * 1px) solid transparent;
  border-image-source: var(--rank-frame-source);
  border-image-slice: var(--rank-frame-slice); border-image-repeat: stretch;
  background: none; pointer-events: none;
  transform: translate(calc(var(--rank-frame-current-x, 0) * 1px), calc(var(--rank-frame-current-y, 0) * 1px)) scale(var(--rank-frame-current-scale, 1));
  transform-origin: center;
}
/* The league's background follows the frame (its size and position from the editor), from the middle
   of the frame's band inwards: it fills everything inside the frame and never shows outside it. */
.player-name.has-rank-art, #playerProfilePhoto { isolation: isolate; background: none; }
.player-name.has-rank-art::before, #playerProfilePhoto::before {
  content: ''; position: absolute; inset: calc(var(--rank-frame-current-thickness, 4) * .5px); z-index: -1; pointer-events: none;
  background-color: var(--rank-background-color); background-image: var(--rank-background-image);
  background-position: center; background-size: cover; image-rendering: pixelated;
  transform: translate(calc(var(--rank-frame-current-x, 0) * 1px), calc(var(--rank-frame-current-y, 0) * 1px)) scale(var(--rank-frame-current-scale, 1));
  transform-origin: center;
}
/* Rank > Profile controls frame/emblem stacking. Result layers are defined in 03-arena.css. */
#playerProfilePhoto { z-index: var(--rank-profile-frame-layer, 1); }
.player-profile-rank-icon { position: relative; z-index: var(--rank-profile-emblem-layer, 2); }
.team-result-mvp { z-index: var(--result-layer-mvp, 6); }
:is(.podium-player, .team-result-card) > .rank-portrait-frame {
  transform: translate(calc(var(--rank-frame-current-x, 0) * 1px), calc(var(--rank-frame-current-y, 0) * 1px)) scale(var(--rank-frame-current-scale, 1));
  transform-origin: center;
}
#playerProfilePhoto { border: 0; }
#playerProfilePhoto::after { background: none; border-image-source: var(--rank-frame-source); }
#gameScreen .menu-overlay:has(#rankMenu:not([hidden])) .menu-content { padding: clamp(10px, 2vw, 22px); overscroll-behavior: contain; }
.rank-lobby { box-sizing: border-box; min-height: calc(100% - 28px); }
.menu-content .rank-lobby > h3 { display: none; }
.rank-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; margin: 0 0 18px; }
.rank-tabs button { min-width: 0; }
.rank-tab-panel[hidden] { display: none; }
.rank-tab-panel { max-width: 980px; margin: 0 auto; }
.rank-section-kicker { display: block; color: var(--t-panel-text); font: 700 13px/1.2 var(--z-font-text, sans-serif); text-transform: uppercase; letter-spacing: .09em; }
.rank-queue-intro, .rank-general-intro { padding: 13px 16px; border-left: 5px solid var(--t-card-selected-border); background: var(--t-card-bg); color: var(--t-card-text); }
.rank-queue-intro .panel-help, .rank-general-intro .panel-help { margin: 5px 0 0; color: var(--t-card-muted); }
.rank-queue-intro .rank-section-kicker, .rank-general-intro .rank-section-kicker { color: var(--t-card-text); }
.menu-content .rank-section-heading { margin: 20px 0 10px; color: var(--t-panel-text); font: 700 18px var(--z-font-text, sans-serif); }
.rank-tab-panel .queue-modes { margin: 0 0 18px; }
.rank-tab-panel .queue-mode { min-height: 142px; }
.rank-tab-panel .queue-mode.is-selected { outline: 3px solid var(--t-card-selected-border); outline-offset: 2px; }
.rank-tab-panel .queue-searching { border-radius: 0; border-style: solid; background: var(--t-card-bg); }
.rank-mine-summary { display: grid; grid-template-columns: minmax(180px, .9fr) minmax(220px, 1.1fr) auto; align-items: stretch; gap: 0; margin: 0 0 18px; border: 3px solid var(--t-card-border); background: var(--t-card-bg); box-shadow: 4px 4px 0 var(--t-card-shadow); color: var(--t-card-text); }
.rank-mine-main { display: flex; align-items: center; gap: 14px; min-width: 0; padding: 18px; }
.rank-mine-emblem { display: grid; flex: 0 0 78px; place-items: center; width: 78px; height: 78px; border: 2px solid var(--t-card-border); background-color: var(--rank-background-color); background-image: var(--rank-background-image); background-position: center; background-size: cover; box-shadow: inset 0 0 0 3px var(--t-card-selected-border); }
.rank-mine-emblem .rank-emblem { width: 60px; height: 60px; }
.rank-mine-identity { min-width: 0; }
.rank-mine-identity > strong { display: block; margin: 3px 0; color: var(--t-card-text); font: 26px/1.1 var(--ui-title-font, 'Arcana', sans-serif); overflow-wrap: anywhere; }
.rank-mine-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; color: var(--t-card-text); font: 700 16px var(--z-font-text, sans-serif); }
.rank-mine-position { padding: 3px 7px; background: var(--t-panel-header-bg); color: var(--t-panel-header-color); }
.rank-mine-journey { display: flex; align-items: center; min-width: 0; padding: 18px; border-left: 2px solid var(--t-card-border); }
.rank-progress { width: 100%; min-width: 0; color: var(--t-card-text); }
.rank-progress-copy { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 7px; font: 15px/1.25 var(--z-font-text, sans-serif); }
.rank-progress-copy strong { white-space: nowrap; color: var(--z-green-light); font-size: 18px; }
.rank-progress-track { height: 14px; border: 2px solid var(--t-card-border); background: var(--t-panel-header-bg); box-shadow: inset 2px 2px 0 var(--t-card-shadow); }
.rank-progress-track > span { display: block; height: 100%; background: var(--z-green); box-shadow: inset 0 2px 0 var(--z-green-light); }
.rank-series { display: grid; gap: 8px; width: 100%; padding: 8px 10px; border: 2px solid var(--t-card-selected-border); background: var(--t-panel-header-bg); }
.rank-series-title { color: var(--t-panel-header-color); font-weight: 700; }
.rank-series-score { display: flex; flex-wrap: wrap; gap: 6px; }
.rank-series-score b { padding: 4px 7px; background: var(--t-card-bg); color: var(--t-card-text); font-size: 13px; }
.rank-max-league { color: var(--t-card-text); font-weight: 700; }
.rank-record { display: grid; grid-template-columns: repeat(3, minmax(64px, 1fr)); border-left: 2px solid var(--t-card-border); background: var(--t-panel-header-bg); }
.rank-record span { display: grid; align-content: center; justify-items: center; gap: 3px; padding: 10px; color: var(--t-card-text); font: 13px var(--z-font-text, sans-serif); text-align: center; }
.rank-record span + span { border-left: 1px solid var(--t-card-border); }
.rank-record strong { color: var(--t-card-text); font: 23px var(--ui-title-font, 'Arcana', sans-serif); }
.rank-record-percent { color: color-mix(in srgb, var(--t-card-text) 80%, transparent); font: 12px var(--z-font-text, sans-serif); font-style: normal; }
.rank-history, .rank-leaderboard { max-height: min(55vh, 620px); overflow: auto; border: 2px solid var(--t-card-border); background: var(--t-card-bg); }
.rank-history table, .rank-leaderboard table { color: var(--t-card-text); width: 100%; border-collapse: collapse; text-align: left; }
.rank-history th, .rank-history td, .rank-leaderboard th, .rank-leaderboard td { padding: 10px 12px; border-bottom: 1px solid var(--t-card-border); }
.rank-history th, .rank-leaderboard th { position: sticky; top: 0; z-index: 1; background: var(--t-panel-header-bg); color: var(--t-panel-header-color); font-weight: 700; }
.rank-history tbody tr:nth-child(even), .rank-leaderboard tbody tr:nth-child(even) { background: color-mix(in srgb, var(--t-card-bg) 78%, var(--t-panel-bg)); }
.rank-leaderboard tr.is-me, .rank-leaderboard tr.is-me:nth-child(even) { background: var(--t-tab-active-bg); box-shadow: inset 4px 0 var(--t-card-selected-border); }
.rank-leaderboard tr.is-me { color: var(--t-tab-active-color); }
.rank-leaderboard tr.is-me :is(.rank-rating, .rank-current-league, .rank-player-link) { color: inherit; }
.rank-leaderboard td:first-child { width: 56px; }
.rank-leaderboard td:nth-child(3) { width: 205px; }
.rank-leaderboard td:last-child { width: 112px; }
.rank-place { display: inline-grid; place-items: center; min-width: 28px; height: 28px; padding: 0 4px; border: 1px solid var(--t-card-border); background: var(--t-field-bg); color: var(--t-field-color); font-weight: 700; }
.rank-leaderboard tr:nth-child(1) .rank-place { background: var(--z-gold); }
.rank-leaderboard tr:nth-child(2) .rank-place { background: var(--z-stone-light); }
.rank-leaderboard tr:nth-child(3) .rank-place { background: var(--z-copper); }
.rank-rating { color: var(--t-card-text); font-size: 18px; }
.rank-current-league { display: block; margin-top: 2px; color: color-mix(in srgb, var(--t-card-text) 85%, transparent); font-size: 12px; font-weight: 700; }
.rank-you { display: inline-block; margin-left: 8px; padding: 2px 5px; background: var(--z-green); color: var(--z-light-text); font-size: 12px; font-weight: 700; }
.rank-progress-compact { max-width: 170px; margin-top: 4px; }
.rank-progress-compact .rank-progress-copy { display: grid; gap: 0; margin-bottom: 2px; font-size: 11px; }
.rank-progress-compact .rank-progress-copy span { white-space: nowrap; }
.rank-progress-compact .rank-progress-copy strong { font-size: 11px; text-align: right; }
.rank-progress-compact .rank-progress-track { height: 5px; border-width: 1px; }
.rank-result { display: inline-block; padding: 3px 6px; font-weight: 700; }
.rank-result-win { background: var(--z-green-dark); color: var(--z-green-light); }
.rank-result-loss { background: var(--z-red-dark); color: var(--z-red-light); }
.rank-result-pending, .rank-result-void { background: var(--t-panel-header-bg); color: var(--t-panel-header-color); }
.rank-points-change { color: var(--z-red-light); font-weight: 700; }
.rank-points-change.is-positive { color: var(--z-green-light); }
.rank-league-tabs { display: flex; gap: 6px; margin: 14px 0 12px; padding: 3px 0 9px; overflow-x: auto; }
.rank-league-tabs { scrollbar-color: var(--t-card-hover-border) var(--t-panel-bg); scrollbar-width: auto; }
.menu-content .rank-league-tabs button { display: flex; flex: 0 0 auto; align-items: center; gap: 7px; min-height: 48px; padding: 7px 10px; border: 2px solid var(--t-card-border); border-radius: 0; background: var(--t-tab-bg); color: var(--t-tab-color); font: 700 15px var(--z-font-text, sans-serif); text-shadow: none; cursor: pointer; }
.menu-content .rank-league-tabs button[aria-selected="true"] { background: var(--t-tab-active-bg); color: var(--t-tab-active-color); border-color: var(--t-card-selected-border); box-shadow: inset 0 -4px var(--t-card-selected-shadow); }
.rank-league-tabs .rank-emblem { width: 26px; height: 26px; }
.rank-league-tabs small { display: grid; place-items: center; min-width: 22px; padding: 2px 4px; background: var(--t-field-bg); color: var(--t-field-color); font-size: 12px; }
.rank-promotion-state { display: inline-block; padding: 4px 6px; background: var(--t-panel-header-bg); color: var(--t-panel-header-color); font-weight: 700; white-space: nowrap; }
.rank-mobile-series { display: none; }
.rank-no-series { color: color-mix(in srgb, var(--t-card-text) 80%, transparent); }
.rank-empty { margin: 0; padding: 24px; color: var(--t-card-text); text-align: center; }
.rank-tab-panel #rankLoadMore { display: block; margin: 14px auto 0; }
.rank-promotion-notice:not([hidden]) { position: fixed; z-index: 10002; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(400px, calc(100% - 28px)); box-sizing: border-box; padding: 18px; border: 4px solid var(--t-card-selected-border); background: var(--t-panel-bg); color: var(--t-panel-text); text-align: center; box-shadow: 0 0 0 999vmax #000b; }
/* On top of everything (popover="manual"): centered on the screen, without the browser's popover look. */
.rank-promotion-notice[popover] { right: auto; bottom: auto; height: auto; max-width: none; max-height: none; margin: 0; overflow: visible; }
.rank-elo-transition[popover] { width: auto; height: auto; max-width: none; max-height: none; margin: 0; border: 0; padding: 0; }
.rank-promotion-notice h3 { margin: 0 0 10px; color: var(--t-panel-text); }
.rank-promotion-notice p { margin: 0 0 14px; }
.rank-elo-transition:not([hidden]) { position: fixed; inset: 0; z-index: 10002; display: grid; place-items: center; overflow: hidden; pointer-events: none; background: radial-gradient(circle, #624b21dd 0%, #1b170ecf 55%, #0d0d0bcc 100%); color: #fff0b8; text-align: center; }
.rank-elo-transition-card { position: relative; display: grid; justify-items: center; align-content: center; width: min(92%, 540px); min-height: 280px; }
.rank-elo-transition-title { margin: 0 0 14px; color: #ffe398; font: clamp(20px, 3vw, 34px) var(--ui-title-font, sans-serif); text-transform: uppercase; text-shadow: 3px 3px #533919; }
.rank-elo-transition-art { position: relative; width: clamp(90px, 18vw, 150px); height: clamp(90px, 18vw, 150px); transform: translate(calc(var(--rank-transition-emblem-x, 0) * 1px), calc(var(--rank-transition-emblem-y, 0) * 1px)) scale(var(--rank-transition-emblem-scale, 1)); }
.rank-elo-transition-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
.rank-elo-old-name, .rank-elo-new-name { margin: 10px 0 0; font: clamp(22px, 3vw, 38px) var(--ui-title-font, sans-serif); }
.rank-elo-new-name, #rankEloNewBadge, .rank-elo-shard { position: absolute; opacity: 0; }
.rank-elo-new-name { bottom: 14px; }
.rank-elo-shards { position: absolute; inset: 0; pointer-events: none; }
/* Glow: the old emblem shrinks in a flash and the new one grows into place. */
.rank-elo-transition.is-playing #rankEloOldBadge, .rank-elo-transition.is-playing .rank-elo-old-name { animation: rank-elo-out var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing #rankEloNewBadge, .rank-elo-transition.is-playing .rank-elo-new-name { animation: rank-elo-in var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing .rank-elo-transition-card::after { content: ''; position: absolute; top: 44%; width: 10px; height: 10px; border-radius: 50%; pointer-events: none; animation: rank-elo-glow var(--rank-transition-duration) both; }
/* Rank > League transition selects the animation through data-animation. */
/* Break and rebuild: the emblem shakes, breaks into four pieces, then the new pieces assemble. */
.rank-elo-transition.is-playing[data-animation="shatter"] #rankEloOldBadge { animation: rank-shatter-old var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="shatter"] #rankEloNewBadge { animation: rank-shatter-new var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="shatter"] .rank-elo-shard.is-old { animation: rank-shard-out var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="shatter"] .rank-elo-shard.is-new { animation: rank-shard-in var(--rank-transition-duration) both; }
.rank-elo-shard.piece-1 { --dx: -1; --dy: -1; clip-path: polygon(0 0, 52% 0, 46% 48%, 0 54%); }
.rank-elo-shard.piece-2 { --dx: 1; --dy: -1; clip-path: polygon(52% 0, 100% 0, 100% 46%, 46% 48%); }
.rank-elo-shard.piece-3 { --dx: -1; --dy: 1; clip-path: polygon(0 54%, 46% 48%, 54% 100%, 0 100%); }
.rank-elo-shard.piece-4 { --dx: 1; --dy: 1; clip-path: polygon(46% 48%, 100% 46%, 100% 100%, 54% 100%); }
@keyframes rank-shatter-old { 0% { opacity: 1; transform: none; } 6%, 14%, 22%, 30% { transform: translate(-3px, 1px); } 10%, 18%, 26% { transform: translate(3px, -1px); } 34% { opacity: 1; transform: none; } 34.5%, 100% { opacity: 0; } }
@keyframes rank-shard-out { 0%, 34% { opacity: 0; transform: none; } 34.5% { opacity: 1; transform: none; }
  56%, 100% { opacity: 0; transform: translate(calc(var(--dx) * 70px), calc(var(--dy) * 60px + 40px)) rotate(calc(var(--dx) * 45deg)); } }
@keyframes rank-shard-in { 0%, 55% { opacity: 0; transform: translate(calc(var(--dx) * 90px), calc(var(--dy) * 90px)) rotate(calc(var(--dx) * -60deg)); }
  58% { opacity: 1; } 72% { opacity: 1; transform: none; } 72.5%, 100% { opacity: 0; transform: none; } }
@keyframes rank-shatter-new { 0%, 72% { opacity: 0; filter: none; } 72.5% { opacity: 1; filter: brightness(2.2); } 84%, 100% { opacity: 1; filter: none; } }
/* Spin: the emblem turns like a coin and reveals the new one on its reverse. */
.rank-elo-transition.is-playing[data-animation="flip"] #rankEloOldBadge { animation: rank-flip-out var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="flip"] #rankEloNewBadge { animation: rank-flip-in var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="flip"] .rank-elo-transition-card::after { display: none; }
@keyframes rank-flip-out { 0%, 30% { opacity: 1; transform: perspective(400px) rotateY(0); } 50% { opacity: 1; transform: perspective(400px) rotateY(90deg); } 50.5%, 100% { opacity: 0; } }
@keyframes rank-flip-in { 0%, 50% { opacity: 0; transform: perspective(400px) rotateY(-90deg); } 50.5% { opacity: 1; transform: perspective(400px) rotateY(-90deg); }
  62% { transform: perspective(400px) rotateY(18deg); } 68%, 100% { opacity: 1; transform: perspective(400px) rotateY(0); } }
/* Energy wave: the emblem pulses and bursts with two rings; the new emblem lands from the light. */
.rank-elo-transition.is-playing[data-animation="energy"] #rankEloOldBadge { animation: rank-energy-out var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="energy"] #rankEloNewBadge { animation: rank-energy-in var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="energy"] .rank-elo-transition-card::before,
.rank-elo-transition.is-playing[data-animation="energy"] .rank-elo-transition-card::after { content: ''; position: absolute; top: 44%; left: 50%; width: 40px; height: 40px; margin: -20px 0 0 -20px; border: 4px solid #8fe8ff; border-radius: 50%; box-shadow: 0 0 18px #6fd8ff, inset 0 0 12px #6fd8ff; background: none; pointer-events: none; animation: rank-energy-ring var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="energy"] .rank-elo-transition-card::before { animation-name: rank-energy-ring-late; }
@keyframes rank-energy-out { 0% { opacity: 1; transform: scale(1); filter: none; } 8%, 18%, 28%, 38% { transform: scale(1.08); } 13%, 23%, 33% { transform: scale(.97); }
  47% { opacity: 1; transform: scale(1.25); filter: brightness(3); } 51%, 100% { opacity: 0; transform: scale(1.25); } }
@keyframes rank-energy-in { 0%, 50% { opacity: 0; transform: scale(1.6); filter: brightness(3); } 62% { opacity: 1; transform: scale(.95); filter: brightness(1.6); } 70%, 100% { opacity: 1; transform: scale(1); filter: none; } }
@keyframes rank-energy-ring { 0%, 46% { opacity: 0; transform: scale(.2); } 50% { opacity: 1; transform: scale(1); } 74%, 100% { opacity: 0; transform: scale(9); } }
@keyframes rank-energy-ring-late { 0%, 52% { opacity: 0; transform: scale(.2); } 56% { opacity: 1; transform: scale(1); } 82%, 100% { opacity: 0; transform: scale(7); } }
/* Digital: the emblem glitches in slices and colors, and the new one glitches into place. */
.rank-elo-transition.is-playing[data-animation="glitch"] #rankEloOldBadge { animation: rank-glitch-out var(--rank-transition-duration) steps(1, end) both; }
.rank-elo-transition.is-playing[data-animation="glitch"] #rankEloNewBadge { animation: rank-glitch-in var(--rank-transition-duration) steps(1, end) both; }
.rank-elo-transition.is-playing[data-animation="glitch"] .rank-elo-transition-card::after { display: none; }
@keyframes rank-glitch-out { 0%, 30% { opacity: 1; transform: none; filter: none; clip-path: inset(0); }
  33% { transform: translate(-5px, 0); filter: hue-rotate(90deg); clip-path: inset(10% 0 55% 0); } 36% { transform: translate(4px, 0); filter: hue-rotate(-60deg); clip-path: inset(50% 0 10% 0); }
  39% { transform: translate(-2px, 2px); filter: none; clip-path: inset(0 0 70% 0); } 42% { transform: translate(6px, -1px); filter: saturate(3); clip-path: inset(30% 0 30% 0); }
  45% { opacity: 1; transform: none; filter: none; clip-path: inset(0); } 47% { opacity: 0; } 48% { opacity: 1; transform: translate(-8px, 0); } 50%, 100% { opacity: 0; } }
@keyframes rank-glitch-in { 0%, 50% { opacity: 0; } 51% { opacity: 1; transform: translate(7px, 0); filter: hue-rotate(120deg); clip-path: inset(0 0 60% 0); }
  54% { transform: translate(-5px, 0); filter: hue-rotate(-90deg); clip-path: inset(40% 0 0 0); } 57% { opacity: 0; }
  59% { opacity: 1; transform: translate(3px, 1px); filter: none; clip-path: inset(20% 0 20% 0); } 62%, 100% { opacity: 1; transform: none; filter: none; clip-path: inset(0); } }
/* Crystal: the emblem turns into white light and sparkles before the new emblem forms. */
.rank-elo-transition.is-playing[data-animation="crystal"] #rankEloOldBadge { animation: rank-crystal-out var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="crystal"] #rankEloNewBadge { animation: rank-crystal-in var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="crystal"] .rank-elo-transition-card::after { left: 50%; width: 6px; height: 6px; margin-left: -3px; border-radius: 0; background: #fff; animation: rank-crystal-sparkle var(--rank-transition-duration) both;
  box-shadow: -70px -40px #fff, 64px -58px #bdf4ff, -46px 52px #e8fbff, 78px 30px #fff, -90px 6px #bdf4ff, 20px -84px #fff, -18px 80px #bdf4ff, 96px -12px #e8fbff, -60px -78px #e8fbff, 50px 70px #fff; }
@keyframes rank-crystal-out { 0%, 30% { opacity: 1; transform: none; filter: none; } 48% { opacity: 1; transform: scale(1.1); filter: brightness(3) saturate(0); } 52%, 100% { opacity: 0; transform: scale(1.1); } }
@keyframes rank-crystal-in { 0%, 50% { opacity: 0; transform: scale(.6); filter: brightness(3) saturate(0); } 64% { opacity: 1; transform: scale(1.05); filter: brightness(1.8) saturate(.5); } 74%, 100% { opacity: 1; transform: none; filter: none; } }
@keyframes rank-crystal-sparkle { 0%, 38% { opacity: 0; transform: scale(.3) rotate(0); } 50% { opacity: 1; transform: scale(1); } 58% { opacity: .35; } 64% { opacity: 1; } 84%, 100% { opacity: 0; transform: scale(1.3) rotate(20deg); } }
/* Vibration: the card shakes harder, flashes, then the new emblem lands with a jolt. */
.rank-elo-transition.is-playing[data-animation="shake"] #rankEloOldBadge { animation: rank-shake-out var(--rank-transition-duration) linear both; }
.rank-elo-transition.is-playing[data-animation="shake"] #rankEloNewBadge { animation: rank-shake-in var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="shake"] .rank-elo-transition-card { animation: rank-shake-card var(--rank-transition-duration) linear both; }
@keyframes rank-shake-out { 0%, 8% { opacity: 1; transform: none; filter: none; }
  10% { transform: translate(-1px, 0); } 12% { transform: translate(1px, 0); } 14% { transform: translate(-1px, 1px); } 16% { transform: translate(1px, -1px); }
  18% { transform: translate(-2px, 1px) rotate(-1deg); } 20% { transform: translate(2px, -1px) rotate(1deg); } 22% { transform: translate(-2px, 0) rotate(-1deg); } 24% { transform: translate(2px, 1px) rotate(1deg); }
  26% { transform: translate(-3px, -1px) rotate(-2deg); } 28% { transform: translate(3px, 1px) rotate(2deg); } 30% { transform: translate(-3px, 1px) rotate(-2deg); } 32% { transform: translate(3px, -1px) rotate(2deg); }
  34% { transform: translate(-4px, 2px) rotate(-3deg) scale(1.03); filter: brightness(1.3); } 36% { transform: translate(4px, -2px) rotate(3deg) scale(1.03); }
  38% { transform: translate(-5px, 1px) rotate(-4deg) scale(1.05); } 40% { transform: translate(5px, -1px) rotate(4deg) scale(1.05); filter: brightness(1.7); }
  42% { transform: translate(-6px, 2px) rotate(-5deg) scale(1.08); } 44% { transform: translate(6px, -2px) rotate(5deg) scale(1.08); }
  46% { transform: translate(-7px, 1px) rotate(-6deg) scale(1.12); filter: brightness(2.4); } 48% { opacity: 1; transform: translate(7px, -1px) rotate(6deg) scale(1.15); filter: brightness(3); }
  49%, 100% { opacity: 0; transform: scale(1.3); filter: brightness(3); } }
@keyframes rank-shake-in { 0%, 49% { opacity: 0; transform: scale(1.35); filter: brightness(3); } 52% { opacity: 1; transform: scale(.9); filter: brightness(2); }
  55% { transform: translate(-4px, 0) scale(1.04); } 58% { transform: translate(3px, 0) scale(.98); filter: brightness(1.3); } 61% { transform: translate(-2px, 0); } 64% { transform: translate(1px, 0); }
  67%, 100% { opacity: 1; transform: none; filter: none; } }
@keyframes rank-shake-card { 0%, 30% { transform: none; } 32% { transform: translate(-1px, 0); } 34% { transform: translate(1px, 1px); } 36% { transform: translate(-2px, -1px); } 38% { transform: translate(2px, 1px); }
  40% { transform: translate(-2px, 1px); } 42% { transform: translate(3px, -1px); } 44% { transform: translate(-3px, 1px); } 46% { transform: translate(3px, -2px); } 48% { transform: translate(-4px, 2px); }
  50% { transform: translate(5px, -2px); } 52% { transform: translate(-4px, 1px); } 54% { transform: translate(3px, -1px); } 56% { transform: translate(-2px, 1px); } 58% { transform: translate(1px, 0); } 60%, 100% { transform: none; } }
/* Drop: the old emblem tips and falls; the new emblem drops from above and settles. */
.rank-elo-transition.is-playing[data-animation="fall"] #rankEloOldBadge { animation: rank-fall-out var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="fall"] #rankEloNewBadge { animation: rank-fall-in var(--rank-transition-duration) both; }
.rank-elo-transition.is-playing[data-animation="fall"] .rank-elo-transition-card::after { display: none; }
@keyframes rank-fall-out { 0%, 34% { opacity: 1; transform: none; } 42% { transform: translateY(-8px) rotate(-4deg); } 58%, 100% { opacity: 0; transform: translateY(110px) rotate(25deg); } }
@keyframes rank-fall-in { 0%, 55% { opacity: 0; transform: translateY(-90px); } 66% { opacity: 1; transform: translateY(6px); } 71% { transform: translateY(-4px); } 76%, 100% { opacity: 1; transform: none; } }
.rank-elo-transition.is-demotion { background: radial-gradient(circle, #414b61dc, #0e121ecc 70%); }
@keyframes rank-elo-out { 0%, 38% { opacity: 1; transform: scale(1); } 54%, 100% { opacity: 0; transform: scale(.7); } }
@keyframes rank-elo-in { 0%, 42% { opacity: 0; transform: scale(.65); } 62%, 100% { opacity: 1; transform: scale(1); } }
@keyframes rank-elo-glow { 0%, 35%, 78%, 100% { opacity: 0; box-shadow: 0 0 0 0 #fff8ca; } 53% { opacity: 1; box-shadow: 0 0 30px 55px #fff9d9, 0 0 110px 115px #efb83c; } }
/* The editor chooses the league-change animation for both the game and its preview.
   Keep the old emblem visible first, then transform it into the new one. */
.rank-emblem { width: 30px; height: 30px; vertical-align: middle; image-rendering: pixelated; }
.menu-content .rank-player-link { display: inline-flex; align-items: center; gap: 9px; padding: 0; border: 0; background: none; color: var(--t-card-text); box-shadow: none; text-shadow: none; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; font: 700 15px var(--z-font-text, sans-serif); overflow-wrap: anywhere; text-align: left; }
.rank-player-name { min-width: 0; }
.rank-player-thumb { display: grid; flex: 0 0 38px; place-items: center; width: 38px; height: 38px; overflow: hidden; border: 2px solid var(--t-card-border); background-color: var(--rank-background-color); background-image: var(--rank-background-image); background-position: center; background-size: cover; color: var(--t-card-text); box-shadow: inset 0 0 0 2px var(--t-card-selected-border); font-size: 23px; text-decoration: none; }
.rank-player-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; }
@media (max-width: 760px) {
  #gameScreen .menu-overlay:has(#rankMenu:not([hidden])) { position: fixed; inset: 0; width: 100%; height: 100dvh; border-width: 0; }
  .rank-mine-summary { grid-template-columns: 1fr; }
  .rank-mine-main { padding: 14px; }
  .rank-mine-journey { border-left: 0; border-top: 2px solid var(--t-card-border); padding: 12px 14px; }
  .rank-record { border-left: 0; border-top: 2px solid var(--t-card-border); }
  .rank-tabs button { padding: 9px 3px; font-size: 13px; white-space: normal; }
  .rank-history th, .rank-history td, .rank-leaderboard th, .rank-leaderboard td { padding: 7px 5px; font-size: 13px; }
  .rank-leaderboard td:nth-child(3) { width: 105px; }
  .rank-leaderboard td:last-child { width: 72px; }
  .rank-progress-compact .rank-progress-copy span { display: none; }
  .rank-leaderboard .rank-promotion-state { white-space: normal; }
  .rank-player-thumb { flex-basis: 30px; width: 30px; height: 30px; font-size: 18px; }
  .menu-content .rank-player-link { gap: 6px; }
}
@media (max-width: 480px) {
  .rank-tab-panel .queue-modes { grid-template-columns: 1fr; }
  .rank-tab-panel .queue-mode { min-height: 100px; }
  .rank-leaderboard th:last-child, .rank-leaderboard td:last-child { display: none; }
  .rank-mobile-series { display: block; width: fit-content; margin-top: 4px; padding: 2px 5px; background: var(--t-panel-header-bg); color: var(--t-panel-header-color); font-size: 11px; font-weight: 700; }
  .rank-leaderboard td:first-child { width: 34px; }
  .rank-leaderboard td:nth-child(3) { width: 84px; }
  .rank-progress-compact .rank-progress-copy { justify-content: end; }
  .rank-mine-emblem { flex-basis: 68px; width: 68px; height: 68px; }
  .rank-mine-emblem .rank-emblem { width: 54px; height: 54px; }
  .rank-history table, .rank-history tbody { display: block; width: 100%; }
  .rank-history thead { display: none; }
  .rank-history tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 10px; padding: 10px 12px; border-bottom: 1px solid var(--t-card-border); }
  .rank-history td { display: block; padding: 0; border: 0; }
  .rank-history td:nth-child(1) { grid-column: 1; grid-row: 1; color: var(--t-card-muted); font-size: 11px; }
  .rank-history td:nth-child(2) { grid-column: 1; grid-row: 2; font-weight: 700; overflow-wrap: anywhere; }
  .rank-history td:nth-child(3) { grid-column: 2; grid-row: 1; text-align: right; }
  .rank-history td:nth-child(4) { grid-column: 2; grid-row: 2; text-align: right; }
}
/* Result frames use nine slices: resizing the box preserves the corners. */
.podium { flex-wrap: wrap; gap: var(--result-row-gap, 14px) var(--result-card-gap, 10px); }
/* Zoom scales every layer and its layout footprint together; transform alone would overlap cards. */
.podium-player, .team-result-card { zoom: var(--result-card-scale, 1); flex-shrink: 0; }
.podium-player, .team-result-card { --rank-frame-current-thickness: var(--rank-result-frame-thickness, 4); }
:is(.podium-player, .team-result-card) > .rank-portrait-frame {
  grid-area: auto; grid-column: 1; grid-row: 2 / 4;
  inset: calc((1 - var(--rank-frame-current-scale, 1)) * 50%);
  width: auto; height: auto; box-sizing: border-box;
  border: max(1px, calc(var(--rank-frame-current-thickness, 4) * 1px)) solid transparent;
  border-image-source: var(--rank-frame-source);
  border-image-slice: var(--rank-frame-slice); border-image-repeat: stretch;
  transform: translate(calc(var(--rank-frame-current-x, 0) * 1px), calc(var(--rank-frame-current-y, 0) * 1px));
}
:is(.podium-player, .team-result-card) > .result-portrait-border { grid-area: auto; grid-column: 1; grid-row: 2 / 4; }
:is(.podium-player, .team-result-card):has(.rank-portrait-frame) .result-info-bg { border: 0; box-shadow: none; }
:is(.podium-player, .team-result-card):has(.rank-portrait-frame) .result-ranked-points {
  border: 0; padding: 4px 6px;
}
:is(.podium-player, .team-result-card) :is(.podium-info, .team-result-info) {
  padding: max(24px, var(--result-info-padding, 10px)) max(10px, calc(var(--rank-frame-current-thickness, 4) * 1px + 6px)) max(16px, calc(var(--rank-frame-current-thickness, 4) * 1px + 8px));
  row-gap: max(6px, var(--result-info-gap, 3px));
}
.team-result-card .team-result-mvp, .team-result-card:has(.result-ranked-points) .team-result-mvp {
  position: relative; grid-area: rank; top: auto; left: auto; transform: none;
  justify-self: center; align-self: end; margin-bottom: 0;
}
/* One continuous backing follows the exact frame box, including its editor offsets. */
.result-card-background {
  position: absolute; grid-column: 1; grid-row: 2 / 4;
  inset: calc((1 - var(--rank-frame-current-scale, 1)) * 50% + var(--rank-frame-current-thickness, 4) * .5px);
  transform: translate(calc(var(--rank-frame-current-x, 0) * 1px), calc(var(--rank-frame-current-y, 0) * 1px));
  z-index: -1; pointer-events: none;
  background: var(--ui-podium-card-background);
  image-rendering: pixelated;
}
.result-card-background.has-rank-background {
  background-color: var(--rank-background-color); background-image: var(--rank-background-image);
  background-position: center; background-size: 100% 100%; background-repeat: no-repeat;
}
body[data-result-rank-background="screen"] .result-card-background.has-rank-background { background: var(--ui-podium-card-background); }
:is(.podium-player, .team-result-card) > :is(.podium-rank-portrait, .team-result-square, .result-ranked-points),
:is(.podium-player, .team-result-card) :is(.podium-info, .team-result-info) > .result-info-bg { background: transparent !important; border: 0; box-shadow: none; }
:is(.podium-info, .team-result-info) { min-height: var(--result-info-min-height, 0px); }
/* These empty grid spacers define portrait height; they never paint a second backing. */
.podium-rank-portrait, .team-result-square { visibility: hidden; }

/* Teams and pre-match cards reserve the same name/stat slots, even when empty.
   Two name lines match the taller result card; content never sizes the frame. */
.team-result-info {
  --result-name-line: calc(var(--result-name-size, 14px) * 1.2);
  --result-stat-line: calc(var(--result-line-size, 14px) * 1.2);
  --result-info-fixed-height: max(var(--result-info-min-height, 0px),
    calc(max(24px, var(--result-info-padding, 10px)) +
      max(16px, var(--result-info-padding, 10px), calc(var(--rank-frame-current-thickness, 4) * 1px + 8px)) +
      var(--result-name-line) * 2 + var(--result-stat-line) * 3 + max(6px, var(--result-info-gap, 3px)) * 3));
  height: var(--result-info-fixed-height);
  min-height: var(--result-info-fixed-height);
  grid-template-rows: calc(var(--result-name-line) * 2) repeat(3, var(--result-stat-line));
}
.team-result-info b { width: 100%; line-height: var(--result-name-line); }
.team-result-info .result-player-name {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; max-height: calc(var(--result-name-line) * 2);
}
.team-result-info small {
  min-width: 0; max-width: 100%; line-height: var(--result-stat-line);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* The introduction has only the name: center it inside the unchanged information box. */
#winnerOverlay.is-intro .team-result-info {
  grid-template-rows: 1fr; padding-block: 0;
  align-content: stretch; justify-items: center; text-align: center;
}
#winnerOverlay.is-intro .team-result-info b { justify-content: center; align-items: center; }
#winnerOverlay.is-intro .team-result-info .result-player-name { text-align: center; }
/* The dock's Rank menu has two consultation tabs; portals retain the queue tab. */
.rank-tabs:has(#rankTabQueue[hidden]) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
