/* Level system styling (LEVELING_PLAN.md §3): the XP bar and the portal level card. The name-plate crests
   (bottom) and the celebration overlay live here too. Theme-neutral: every color is a variable with a
   dark-portal default, so the paper/ink profile page can override the four --xp-* tokens. */
:root {
  --xp-track: #2c2c2c;
  --xp-fill: #f4c12a;
  --xp-text: #eee;
  --xp-muted: #999;
}

.xp-bar {
  color: var(--xp-text);
  font-size: 0.85em;
}
.xp-bar__track {
  display: block;
  flex: 1;
  height: 8px;
  border-radius: 4px;
  background: var(--xp-track);
  overflow: hidden;
}
.xp-bar__fill {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--xp-fill);
  transition: width 0.6s ease-out;
}
.xp-bar__level {
  font-weight: 700;
  white-space: nowrap;
}
.xp-bar__rank,
.xp-bar__foot {
  color: var(--xp-muted);
}
.xp-bar__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 4px;
}
.xp-bar__foot {
  margin-top: 4px;
  font-size: 0.9em;
}
.xp-bar__gain {
  font-weight: 700;
  color: var(--xp-fill);
}
.xp-bar--flash .xp-bar__track {
  animation: xpBarFlash 0.5s ease-out;
}
@keyframes xpBarFlash {
  0% {
    box-shadow: 0 0 0 0 var(--xp-fill);
  }
  100% {
    box-shadow: 0 0 0 10px transparent;
  }
}
@media (prefers-reduced-motion: reduce) {
  .xp-bar__fill {
    transition: none;
  }
  .xp-bar--flash .xp-bar__track {
    animation: none;
  }
}

/* Compact: one slim row in the portal drawer header. */
.xp-bar--compact {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  cursor: pointer;
}
.xp-bar--compact .xp-bar__track {
  height: 6px;
}
.xp-bar__tip {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 20;
  display: none;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  border: 1px solid var(--xp-track);
  border-radius: 8px;
  background: #1b1b1b;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  white-space: nowrap;
  pointer-events: none;
}
.xp-bar--compact:hover .xp-bar__tip {
  display: flex;
}
.xp-bar__tip-main {
  font-weight: 700;
  color: var(--xp-fill);
}
.xp-bar__tip-sub {
  font-size: 0.85em;
  color: var(--xp-muted);
}
/* A touch screen has no hover; the bar is a tap target into the level card there. */
@media (hover: none) and (pointer: coarse) {
  .xp-bar__tip {
    display: none !important;
  }
}

/* Rank colors: any element carrying xp-bar--<rank> exposes --rank-color. */
.xp-bar--rookie {
  --rank-color: #9aa0a6;
}
.xp-bar--regular {
  --rank-color: #5fbf6a;
}
.xp-bar--rider {
  --rank-color: #38b6e8;
}
.xp-bar--veteran {
  --rank-color: #5c8dff;
}
.xp-bar--ace {
  --rank-color: #a777ff;
}
.xp-bar--expert {
  --rank-color: #e0a800;
}
.xp-bar--elite {
  --rank-color: #ff8a2b;
}
.xp-bar--master {
  --rank-color: #f0524f;
}
.xp-bar--legend {
  --rank-color: #f0468f;
}
.xp-bar--mythic {
  --rank-color: #c58bff;
}

/* Level card (#sectionLevel): a hero panel, then a separate next-rank panel. Surfaces read the
   dashboard's --dash-* tokens (portal-shell.css, paper since PT3); rank-colored text goes through
   --rank-text, which the paper dashboard darkens toward ink so a pale rank stays readable. */
.level-card__heading {
  margin: 0 0 14px;
}
.level-hero,
.level-next {
  max-width: 460px;
  border: 1px solid var(--dash-border, #333);
  border-radius: 12px;
  background: var(--dash-surface, #1a1a1a);
}
.level-hero {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  border-color: var(--rank-color, #333);
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--rank-color, #333) 18%, var(--dash-surface, #1a1a1a)),
    var(--dash-surface, #1a1a1a) 70%
  );
}
.level-hero__badge {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: 3px solid var(--rank-color, #999);
  background: var(--dash-surface, #111);
  box-shadow: 0 0 14px color-mix(in srgb, var(--rank-color, #999) 45%, transparent);
}
.level-hero__lv {
  font-size: 0.6rem;
  letter-spacing: 2px;
  color: var(--xp-muted);
}
.level-hero__badge b {
  font-size: 1.6rem;
  line-height: 1;
  color: var(--rank-text, var(--rank-color, #eee));
}
.level-hero__body {
  flex: 1;
  min-width: 0;
}
.level-hero__rank {
  margin-bottom: 8px;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--rank-text, var(--rank-color, #eee));
}
.level-hero .xp-bar__head {
  display: none;
}
.level-hero .xp-bar__track {
  height: 10px;
}
.level-hero .xp-bar__fill {
  background: var(--rank-color, var(--xp-fill));
}
.level-next {
  margin-top: 14px;
  padding: 14px 16px;
  border-left: 4px solid var(--rank-color, #333);
}
.level-next__kicker {
  font-size: 0.72rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--xp-muted);
}
.level-next__name {
  margin: 4px 0 10px;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--rank-text, var(--rank-color, #eee));
}
.level-next__level {
  margin-left: 10px;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--xp-muted);
}
.level-next__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.level-next__chip {
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--rank-color, #666) 60%, transparent);
  background: color-mix(in srgb, var(--rank-color, #666) 14%, transparent);
  font-size: 0.8rem;
  color: var(--dash-text, #ddd);
}
.level-next__body {
  margin: 6px 0 0;
  color: var(--dash-text-soft, #ccc);
}
.level-card__note {
  max-width: 460px;
  margin-top: 14px;
  color: var(--xp-muted);
  font-size: 0.85em;
}

/* Cosmetic picker (level-cosmetic-picker.js): a tray of raised tiles plus a detail bar. Shared by the
   Bike Shop tab and the profile emblem overlay; the host sets the --look-* tokens to fit its theme.
   Three roles are kept visually distinct: a tile is a raised button, the selected tile is outlined in
   --look-select, the equipped tile is filled gold with a check. */
:root {
  --look-ink: #eee;
  --look-muted: #999;
  --look-tray: #1e1e1e;
  --look-surface: #2c2c2c;
  --look-edge: #555;
  --look-select: #fff;
  --look-on-select: #111;
  --look-accent: #f4c12a;
}
.look-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
  padding: 10px;
  /* Scrolls once the catalog outgrows a few rows, so the name and actions above stay in view. */
  max-height: min(44vh, 320px);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--look-edge) transparent;
  border: 2px solid var(--look-edge);
  border-radius: 10px;
  background: var(--look-tray);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.18);
}
.look-grid::-webkit-scrollbar {
  width: 8px;
}
.look-grid::-webkit-scrollbar-track {
  background: transparent;
}
.look-grid::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background: var(--look-edge);
}
.look-tile {
  position: relative;
  aspect-ratio: 1;
  min-width: 0;
  padding: 0;
  border: 2px solid var(--look-edge);
  border-radius: 8px;
  background: var(--look-surface);
  box-shadow: 0 2px 0 var(--look-edge);
  color: var(--look-ink);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
}
.look-tile.is-locked,
.look-tile.is-buyable {
  opacity: 0.45;
}
.look-tile.is-selected {
  border-color: var(--look-select);
  box-shadow: 0 0 0 2px var(--look-select);
}
.look-tile.is-equipped {
  background: color-mix(in oklab, var(--look-accent) 35%, var(--look-surface));
}
.look-tile.is-equipped::after {
  content: '¹3';
  position: absolute;
  top: -6px;
  right: -6px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--look-accent);
  color: #111;
  font-size: 0.6rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}
.look-tile:focus-visible,
.look-action:focus-visible {
  outline: 2px solid var(--look-select);
  outline-offset: 2px;
}
.look-detail {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
  color: var(--look-ink);
}
.look-detail__glyph {
  font-size: 1.8rem;
  line-height: 1;
}
.emblem-img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: contain;
  pointer-events: none;
}
.look-tile:has(.emblem-img) {
  padding: 4px;
}
.look-detail__glyph:has(> .emblem-img) {
  width: 2.25rem;
}
.look-detail__text {
  flex: 1;
  min-width: 0;
}
.look-detail__name {
  font-weight: 700;
}
.look-detail__status {
  font-size: 0.75rem;
  color: var(--look-muted);
}
.look-detail__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}
.look-action {
  padding: 6px 12px;
  border: 2px solid var(--look-muted);
  border-radius: 999px;
  background: transparent;
  color: var(--look-ink);
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
}
.look-action--equip,
.look-action--buy,
.look-action--shop {
  border-color: var(--look-select);
  background: var(--look-select);
  color: var(--look-on-select);
  font-weight: 700;
}
.look-action:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Name-plate crest (LEVELING_PLAN.md §4): a shaped plate around the name only. level_crest.js sets
   --crest-color / --crest-accent from the catalog and picks a form class, and each form is its own
   silhouette (pill, rounded double line, pointed corners, brackets, leaf, arrow-ended tag). The
   title owns the text, so the crest has its own inner padding and never touches color; any motion
   is a slow sheen on the border alone. */
.level-crest {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  box-sizing: border-box;
  vertical-align: middle;
  padding: 1px 9px;
  border: 1px solid var(--crest-color);
  border-radius: 4px;
  background: color-mix(in srgb, var(--crest-color) 10%, transparent);
  line-height: 1.35;
}
.level-crest__name {
  min-width: 0;
  padding: 0 2px;
}
.level-crest-stack {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  max-width: 100%;
}
.level-crest__lv--below {
  padding-left: 0;
  border-left: 0;
}
.level-crest__lv {
  flex: none;
  padding-left: 6px;
  border-left: 1px solid color-mix(in srgb, var(--crest-color) 55%, transparent);
  color: var(--crest-color);
  font-size: 0.72em;
  font-weight: 700;
  letter-spacing: 0.03em;
  white-space: nowrap;
}
/* No plate wrapper exists in the bare case (level_crest.js's no-crest branch) — there's no
   --crest-color custom property to inherit, so this gets its own neutral divider/text color
   instead of the plate-tinted one above. */
.level-crest__lv--bare {
  margin-left: 6px;
  padding-left: 6px;
  border-left: 1px solid color-mix(in srgb, currentColor 35%, transparent);
  color: color-mix(in srgb, currentColor 65%, transparent);
}
.level-crest--compact {
  gap: 0;
  padding: 0 4px;
}
.level-crest--compact::before,
.level-crest--compact::after {
  display: none;
}

/* Pill: fully rounded, one thin line. */
.level-crest--pill {
  padding: 1px 12px;
  border-radius: 999px;
}
.level-crest--compact.level-crest--pill {
  padding: 0 7px;
}

/* Double: a rounded plate with a double line. */
.level-crest--double,
.level-crest--ornate,
.level-crest--sheen,
.level-crest--mythic,
.level-crest--notch {
  border-width: 3px;
  border-style: double;
  padding: 0 8px;
}
.level-crest--double {
  border-radius: 9px;
}

/* Notch: pointed accent corners on two opposite corners of a square plate. */
.level-crest--notch::before,
.level-crest--notch::after {
  content: '';
  position: absolute;
  width: 7px;
  height: 7px;
  pointer-events: none;
}
.level-crest--notch::before {
  top: -4px;
  left: -4px;
  border-top: 2px solid var(--crest-accent);
  border-left: 2px solid var(--crest-accent);
}
.level-crest--notch::after {
  right: -4px;
  bottom: -4px;
  border-right: 2px solid var(--crest-accent);
  border-bottom: 2px solid var(--crest-accent);
}

/* Bracket: open square brackets either side of the name, accent caps at the corners. */
.level-crest--bracket {
  padding: 0 9px;
  border-width: 0 2px;
  border-radius: 2px;
  background:
    linear-gradient(var(--crest-accent), var(--crest-accent)) 0 0 / 6px 2px no-repeat,
    linear-gradient(var(--crest-accent), var(--crest-accent)) 100% 0 / 6px 2px no-repeat,
    linear-gradient(var(--crest-accent), var(--crest-accent)) 0 100% / 6px 2px no-repeat,
    linear-gradient(var(--crest-accent), var(--crest-accent)) 100% 100% / 6px 2px no-repeat,
    color-mix(in srgb, var(--crest-color) 10%, transparent);
}

/* Leaf: opposite corners rounded hard, the other two nearly square. */
.level-crest--leaf {
  padding: 0 11px;
  border-width: 2px;
  border-radius: 14px 2px 14px 2px;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crest-accent) 45%, transparent);
}

/* Tag: a banner with pointed ends. The arrows are rotated squares outlined on two sides, so the
   plate's top and bottom lines run straight into them. */
:is(.level-crest--tag, .level-crest--tag2) {
  margin: 0 0.5em;
  padding: 0 0.7em;
  border-width: 1px 0;
  border-radius: 0;
}
:is(.level-crest--tag, .level-crest--tag2)::before,
:is(.level-crest--tag, .level-crest--tag2)::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 1em;
  height: 1em;
  pointer-events: none;
}
:is(.level-crest--tag, .level-crest--tag2)::before {
  left: -0.5em;
  border-left: 1px solid var(--crest-color);
  border-bottom: 1px solid var(--crest-color);
  transform: translateY(-50%) rotate(45deg);
}
:is(.level-crest--tag, .level-crest--tag2)::after {
  right: -0.5em;
  border-top: 1px solid var(--crest-color);
  border-right: 1px solid var(--crest-color);
  transform: translateY(-50%) rotate(45deg);
}
.level-crest--compact:is(.level-crest--tag, .level-crest--tag2) {
  margin: 0;
  padding: 0 4px;
  border-width: 1px;
  border-radius: 3px;
}

/* Ticket: half-circle bites out of both sides, like a stub. */
.level-crest--ticket {
  padding: 1px 12px;
  border-radius: 4px;
  -webkit-mask:
    radial-gradient(circle 5px at 0 50%, #0000 96%, #000) left / 51% 100% no-repeat,
    radial-gradient(circle 5px at 100% 50%, #0000 96%, #000) right / 51% 100% no-repeat;
  mask:
    radial-gradient(circle 5px at 0 50%, #0000 96%, #000) left / 51% 100% no-repeat,
    radial-gradient(circle 5px at 100% 50%, #0000 96%, #000) right / 51% 100% no-repeat;
}

/* Stamp: a dotted, perforated border. */
.level-crest--stamp {
  padding: 1px 10px;
  border: 3px dotted var(--crest-color);
  border-radius: 2px;
  background: color-mix(in srgb, var(--crest-color) 16%, transparent);
}

/* Stitch: a solid plate with a dashed line stitched just inside it. */
.level-crest--stitch {
  padding: 1px 11px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--crest-color) 18%, transparent);
}
.level-crest--stitch::before {
  content: '';
  position: absolute;
  inset: 2px;
  border: 1px dashed var(--crest-accent);
  border-radius: 4px;
  pointer-events: none;
}

/* Corners: no box, just an L-shaped mark on each corner. */
.level-crest--corners {
  padding: 2px 11px;
  border: 0;
  border-radius: 0;
  background:
    linear-gradient(var(--crest-color), var(--crest-color)) 0 0 / 8px 2px no-repeat,
    linear-gradient(var(--crest-color), var(--crest-color)) 0 0 / 2px 8px no-repeat,
    linear-gradient(var(--crest-color), var(--crest-color)) 100% 0 / 8px 2px no-repeat,
    linear-gradient(var(--crest-color), var(--crest-color)) 100% 0 / 2px 8px no-repeat,
    linear-gradient(var(--crest-color), var(--crest-color)) 0 100% / 8px 2px no-repeat,
    linear-gradient(var(--crest-color), var(--crest-color)) 0 100% / 2px 8px no-repeat,
    linear-gradient(var(--crest-color), var(--crest-color)) 100% 100% / 8px 2px no-repeat,
    linear-gradient(var(--crest-color), var(--crest-color)) 100% 100% / 2px 8px no-repeat;
}

/* Pixel: a stepped, 8-bit outline (the border is four bars, so each corner is a notch). */
.level-crest--pixel {
  margin: 2px;
  padding: 1px 10px;
  border: 0;
  border-radius: 0;
  background: color-mix(in srgb, var(--crest-color) 20%, transparent);
  box-shadow:
    -2px 0 0 0 var(--crest-color),
    2px 0 0 0 var(--crest-color),
    0 -2px 0 0 var(--crest-color),
    0 2px 0 0 var(--crest-color);
}

/* Holo: a rounded plate whose border cycles through a rainbow (see the sheen ring below). */
.level-crest--holo {
  padding: 0 9px;
  border: 3px solid transparent;
  border-radius: 9px;
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--crest-color) 16%, transparent),
    color-mix(in srgb, var(--crest-accent) 12%, transparent)
  );
}

/* Tag, double: the same arrow-ended banner drawn with a double line. */
.level-crest--tag2 {
  border-width: 3px 0;
  border-style: double none;
}
.level-crest--tag2::before,
.level-crest--tag2::after {
  width: 0.95em;
  height: 0.95em;
}
.level-crest--tag2::before {
  border-left: 3px double var(--crest-color);
  border-bottom: 3px double var(--crest-color);
}
.level-crest--tag2::after {
  border-top: 3px double var(--crest-color);
  border-right: 3px double var(--crest-color);
}
.level-crest--compact.level-crest--tag2 {
  border-style: solid;
  border-width: 1px;
}

/* Ornate: a rounded plate with a soft fill, an inner ring and a faint glow. */
.level-crest--ornate,
.level-crest--sheen,
.level-crest--mythic {
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--crest-color) 22%, transparent),
    color-mix(in srgb, var(--crest-accent) 8%, transparent)
  );
  box-shadow: 0 0 8px color-mix(in srgb, var(--crest-color) 35%, transparent);
}
.level-crest--ornate {
  border-width: 2px;
  border-style: solid;
  border-radius: 12px;
  box-shadow:
    0 0 8px color-mix(in srgb, var(--crest-color) 35%, transparent),
    inset 0 0 0 2px color-mix(in srgb, var(--crest-accent) 40%, transparent);
}

/* Sheen (Aurora, Mythic): a light band drifting along the border only. */
.level-crest--sheen {
  padding: 0 12px;
  border-radius: 999px;
}
.level-crest--mythic {
  border-radius: 10px;
}
.level-crest--sheen::after,
.level-crest--mythic::after,
.level-crest--holo::after {
  content: '';
  position: absolute;
  inset: -3px;
  padding: 3px;
  border-radius: inherit;
  background: linear-gradient(
    110deg,
    var(--crest-color) 0%,
    var(--crest-accent) 50%,
    var(--crest-color) 100%
  );
  background-size: 250% 100%;
  animation: level-crest-sheen 5s linear infinite;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}
.level-crest--compact.level-crest--sheen,
.level-crest--compact.level-crest--ornate,
.level-crest--compact.level-crest--mythic,
.level-crest--compact.level-crest--double,
.level-crest--compact.level-crest--notch {
  border-width: 1px;
  border-style: solid;
  padding: 0 5px;
}
.level-crest--compact.level-crest--sheen {
  padding: 0 7px;
}
.level-crest--holo::after {
  background-image: linear-gradient(
    110deg,
    #ff5fa2,
    #ffd36e,
    #7dffb0,
    #5fd0ff,
    #b78cff,
    #ff5fa2
  );
}
.level-crest--compact.level-crest--holo {
  border: 1px solid var(--crest-color);
  padding: 0 6px;
}
.level-crest--compact.level-crest--sheen::after,
.level-crest--compact.level-crest--mythic::after,
.level-crest--compact.level-crest--holo::after {
  display: none;
}
@keyframes level-crest-sheen {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: -150% 0;
  }
}

/* Mythic: diamond end-caps on either side of the name. */
.level-crest--mythic .level-crest__name::before,
.level-crest--mythic .level-crest__name::after {
  content: '';
  display: inline-block;
  width: 5px;
  height: 5px;
  background: var(--crest-accent);
  transform: rotate(45deg);
}
.level-crest--mythic .level-crest__name::before {
  margin-right: 7px;
}
.level-crest--mythic .level-crest__name::after {
  margin-left: 7px;
}
.level-crest--compact.level-crest--mythic .level-crest__name::before,
.level-crest--compact.level-crest--mythic .level-crest__name::after {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .level-crest--sheen::after,
  .level-crest--mythic::after,
  .level-crest--holo::after {
    animation: none;
  }
}

/* Effect crests. Each is a dark "screen" with the name animated inside it: Marquee (a chasing-bulb
   sign, the name ticks in, holds and scrolls out), Board (a hexagon, the name flips like a split-flap
   display) and Slice (a sliced parallelogram with a scanline sweep and a glitch jitter). The hexagon
   and parallelogram draw their line as the plate's own fill with a dark ::before inset by 2px. */
.level-crest--marquee,
.level-crest--board,
.level-crest--slice {
  isolation: isolate;
}
.level-crest--marquee > .level-crest__name,
.level-crest--board > .level-crest__name,
.level-crest--slice > .level-crest__name,
.level-crest--marquee > .level-crest__lv,
.level-crest--board > .level-crest__lv,
.level-crest--slice > .level-crest__lv {
  position: relative;
  z-index: 1;
}

.level-crest--marquee {
  /* Horizontal-only clip for the ticker sweep (level-crest-ticker). `overflow`
     can't do this split: setting overflow-x to anything but `visible` forces
     the UA to compute overflow-y as `auto` instead of the `visible` it was
     given (CSS Overflow §3), which both re-clips the title's hover tooltip
     (.player-title-tip, position:absolute, dropping below the name) AND
     turns this box into a scroll container that grows a vertical scrollbar
     the moment that tooltip's height overflows it. clip-path has no such
     axis-coupling: an asymmetric inset() clips left/right flush with the
     plate edge (matching the old overflow-x) while leaving top/bottom open
     far enough that the tooltip renders uncropped underneath.
  */
  clip-path: inset(-9999px 0 -9999px 0);
  padding: 7px 14px;
  border: 2px solid var(--crest-color);
  border-radius: 3px;
  background: color-mix(in srgb, var(--crest-color) 20%, #16110a);
  box-shadow: 0 0 8px color-mix(in srgb, var(--crest-color) 45%, transparent);
}
.level-crest--marquee::before,
.level-crest--marquee::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 4px;
  background: radial-gradient(circle at 50% 50%, var(--crest-accent) 0 1.4px, transparent 2px) 0 0 / 8px 4px repeat-x;
  animation: level-crest-bulbs 0.8s steps(4) infinite;
  pointer-events: none;
}
.level-crest--marquee::before {
  top: 1px;
}
.level-crest--marquee::after {
  bottom: 1px;
  animation-direction: reverse;
}
.level-crest--marquee .level-crest__name {
  color: #fff3c4;
  animation: level-crest-ticker 6s ease-in-out infinite;
}
@keyframes level-crest-bulbs {
  to {
    background-position: 8px 0;
  }
}
@keyframes level-crest-ticker {
  0% {
    transform: translateX(calc(100% + 18px));
  }
  14%,
  72% {
    transform: translateX(0);
  }
  86%,
  100% {
    transform: translateX(calc(-100% - 18px));
  }
}

.level-crest--board,
.level-crest--slice {
  border: 0;
  background: var(--crest-color);
  padding: 4px 18px;
  border-radius: 0;
}
.level-crest--board {
  clip-path: polygon(9px 0, calc(100% - 9px) 0, 100% 50%, calc(100% - 9px) 100%, 9px 100%, 0 50%);
}
.level-crest--board::before {
  content: '';
  position: absolute;
  inset: 2px;
  z-index: 0;
  clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 8px 100%, 0 50%);
  background: color-mix(in srgb, var(--crest-color) 30%, #0e0716);
  pointer-events: none;
}
.level-crest--board .level-crest__name {
  display: inline-block;
  color: #efe5ff;
  background: linear-gradient(transparent calc(50% - 0.5px), rgba(0, 0, 0, 0.5) 0 calc(50% + 0.5px), transparent 0);
  animation: level-crest-flip 5s ease-in-out infinite;
}
@keyframes level-crest-flip {
  0%,
  62% {
    transform: perspective(180px) rotateX(0);
  }
  70% {
    transform: perspective(180px) rotateX(-90deg);
  }
  70.1% {
    transform: perspective(180px) rotateX(90deg);
  }
  78%,
  100% {
    transform: perspective(180px) rotateX(0);
  }
}

.level-crest--slice {
  padding: 4px 16px;
  clip-path: polygon(7px 0, 100% 0, calc(100% - 7px) 100%, 0 100%);
}
.level-crest--slice::before {
  content: '';
  position: absolute;
  inset: 2px;
  z-index: 0;
  clip-path: polygon(7px 0, 100% 0, calc(100% - 7px) 100%, 0 100%);
  background:
    linear-gradient(115deg, transparent 0 46%, var(--crest-accent) 46% 47.5%, transparent 47.5%) 0 0 / 100% 100% no-repeat,
    color-mix(in srgb, var(--crest-color) 24%, #14060a);
  animation: level-crest-slice 3.4s steps(1) infinite;
  pointer-events: none;
}
.level-crest--slice::after {
  content: '';
  position: absolute;
  inset: 2px;
  z-index: 2;
  background:
    linear-gradient(transparent 0 40%, rgba(255, 255, 255, 0.3) 50%, transparent 60%) 0 200% / 100% 300% no-repeat,
    repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.28) 0 1px, transparent 1px 3px);
  animation: level-crest-scan 2.6s linear infinite;
  pointer-events: none;
}
.level-crest--slice .level-crest__name {
  color: #ffe6e3;
  animation: level-crest-glitch 3.4s steps(1) infinite;
}
@keyframes level-crest-scan {
  from {
    background-position:
      0 200%,
      0 0;
  }
  to {
    background-position:
      0 -100%,
      0 0;
  }
}
@keyframes level-crest-slice {
  0%,
  88%,
  100% {
    background-position:
      0 0,
      0 0;
  }
  90% {
    background-position:
      -3px 0,
      0 0;
  }
  94% {
    background-position:
      3px 0,
      0 0;
  }
}
@keyframes level-crest-glitch {
  0%,
  88%,
  100% {
    transform: none;
    text-shadow: none;
  }
  90% {
    transform: translate(-2px, 0);
    text-shadow:
      2px 0 #ff3b4a,
      -2px 0 #3bd8ff;
  }
  92% {
    transform: translate(2px, 1px);
    text-shadow:
      -2px 0 #ff3b4a,
      2px 0 #3bd8ff;
  }
  95% {
    transform: none;
    text-shadow: none;
  }
}

/* Compact (cramped surfaces): a plain dark plate, no animation. */
.level-crest--compact.level-crest--marquee,
.level-crest--compact.level-crest--board,
.level-crest--compact.level-crest--slice {
  padding: 0 6px;
  clip-path: none;
  overflow: visible;
  border: 1px solid var(--crest-color);
  background: color-mix(in srgb, var(--crest-color) 24%, #100a12);
}
.level-crest--compact.level-crest--marquee .level-crest__name,
.level-crest--compact.level-crest--board .level-crest__name,
.level-crest--compact.level-crest--slice .level-crest__name {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .level-crest--marquee::before,
  .level-crest--marquee::after,
  .level-crest--marquee .level-crest__name,
  .level-crest--board .level-crest__name,
  .level-crest--slice::before,
  .level-crest--slice::after,
  .level-crest--slice .level-crest__name {
    animation: none;
  }
}

/* A labelled on/off switch (the crest "show my level" option), same look as the profile toggles. */
.look-toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}
.look-toggle input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.look-toggle__track {
  position: relative;
  flex: none;
  width: 38px;
  height: 22px;
  border: 2px solid color-mix(in oklab, var(--look-ink, #222) 35%, transparent);
  border-radius: 999px;
  background: color-mix(in oklab, var(--look-ink, #222) 12%, transparent);
  box-shadow: 1px 1px 0 color-mix(in oklab, var(--look-ink, #222) 20%, transparent);
  transition:
    background 0.2s,
    border-color 0.2s;
}
.look-toggle__track::after {
  content: '';
  position: absolute;
  left: 2px;
  top: 50%;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--look-muted, #666);
  transform: translateY(-50%);
  transition:
    transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1),
    background 0.2s;
}
.look-toggle input:checked + .look-toggle__track {
  border-color: #6aa61a;
  background: color-mix(in oklab, #8bc34a 25%, transparent);
}
.look-toggle input:checked + .look-toggle__track::after {
  background: #6aa61a;
  transform: translateY(-50%) translateX(16px);
}
.look-toggle input:focus-visible + .look-toggle__track {
  outline: 2px solid var(--look-select, #222);
  outline-offset: 2px;
}
.look-toggle:has(input:disabled) {
  cursor: not-allowed;
  opacity: 0.45;
}

/* A picker whose tiles are name plates rather than square glyphs: wide tiles, as many across as fit. */
.look-picker--plates .look-grid {
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  max-height: min(62vh, 480px);
}
.look-picker--plates .look-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  aspect-ratio: auto;
  min-height: 62px;
  padding: 10px 6px;
  font-size: 1rem;
}
/* An unowned plate stays readable; the caption underneath says what it takes. */
.look-picker--plates .look-tile.is-locked,
.look-picker--plates .look-tile.is-buyable {
  opacity: 0.8;
}
.look-picker--plates .look-tile.is-locked .look-tile__glyph,
.look-picker--plates .look-tile.is-buyable .look-tile__glyph {
  opacity: 0.55;
  filter: grayscale(0.5);
}
.look-picker--plates .look-tile__glyph {
  display: inline-flex;
  max-width: 100%;
  justify-content: center;
}
.look-tile__caption {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--look-muted);
}
.look-picker--plates .look-detail {
  margin-bottom: 10px;
}
/* The tile already shows the crest's name and the button says what it costs or needs, so the
   detail bar keeps just the action. */
.look-picker--plates .look-detail__text {
  display: none;
}
.look-picker--plates .look-detail__actions {
  width: 100%;
}
.look-picker--plates .look-detail__glyph {
  font-size: 1rem;
}
.look-card .look-picker--plates .look-grid {
  max-height: min(36vh, 260px);
}

/* Level-up celebration (celebration/level-celebration.js): a centered takeover on its own overlay,
   above the portal and the notice popups. The confetti canvas never takes input. */
.celebration-overlay {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 18px;
  background: rgba(8, 8, 12, 0.72);
  cursor: pointer;
  overscroll-behavior: contain;
  touch-action: none;
  animation: celebration-fade 0.25s ease-out;
}
.celebration__confetti {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.celebration__card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  max-width: min(90vw, 420px);
  padding: 28px 40px;
  text-align: center;
  color: var(--xp-text);
  animation: celebration-pop 0.45s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.celebration__card--milestone {
  padding: 36px 48px;
  border: 2px solid var(--rank-color);
  border-radius: 16px;
  background: color-mix(in srgb, var(--rank-color) 14%, #14141a);
  box-shadow: 0 0 60px color-mix(in srgb, var(--rank-color) 50%, transparent);
}
.celebration__kicker {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--xp-muted);
}
.celebration__level {
  font-size: clamp(5rem, 22vw, 9rem);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--rank-color);
  text-shadow: 0 0 32px color-mix(in srgb, var(--rank-color) 60%, transparent);
}
.celebration__card--milestone .celebration__level {
  font-size: clamp(6rem, 26vw, 11rem);
}
.celebration__bar {
  position: relative;
  width: min(72vw, 300px);
  height: 12px;
  margin: 6px 0 4px;
  border-radius: 6px;
  background: var(--xp-track);
  overflow: hidden;
}
.celebration__bar-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 6px;
  background: var(--rank-color);
}
.celebration__bar--shine {
  box-shadow: 0 0 18px var(--rank-color);
}
.celebration__bar--shine::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, 0.85) 50%, transparent 70%);
  transform: translateX(-100%);
  animation: celebration-shine 0.55s ease-out forwards;
}
.celebration__rank {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--rank-color);
}
.celebration__crest {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.celebration__crest-label {
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--xp-muted);
}
/* Level-10 "this was the tutorial" card — a separate, smaller card next to the normal Lv10
   milestone reveal (LEVELING_PLAN.md's tutorial-phase overhaul), not nested inside it. Fixed
   amber accent rather than `--rank-color`: level 10 is always the 'regular' (green) rank, so
   reusing that variable made this card read as just more of the same green main card instead of
   its own distinct callout. `.celebration-overlay`'s flex-wrap lays it beside the main card on a
   wide viewport and stacks it underneath on a narrow one. */
.celebration__tutorial-complete {
  align-self: center;
  width: min(74vw, 230px);
  padding: 16px 18px;
  border-radius: 14px;
  border: 1px solid rgba(244, 193, 42, 0.45);
  background: color-mix(in srgb, #f4c12a 14%, #14141a);
  box-shadow: 0 0 24px rgba(244, 193, 42, 0.18);
  animation: celebration-pop 0.45s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.celebration__tutorial-complete-title {
  font-size: 1.1rem;
  font-weight: 800;
  color: #f4c12a;
}
.celebration__tutorial-complete-copy {
  margin-top: 6px;
  font-size: 0.92rem;
  line-height: 1.4;
  color: var(--xp-muted);
}
/* Welcome-grant celebration (celebration/welcome-celebration.js) — deliberately NOT the level-up
   takeover's "dark box + thick rank-colored border + big glow" formula (that's its whole visual
   signature). This one reads as a gift ticket instead: a warm teal→ink gradient card, a circular
   icon badge, and a dashed divider ahead of the flavor line. */
.celebration__card--welcome {
  padding: 36px 40px 30px;
  border: 1px solid rgba(244, 193, 42, 0.3);
  border-radius: 22px;
  background: linear-gradient(165deg, #1f6a4f 0%, #15493a 55%, #0e2f27 100%);
  box-shadow:
    0 24px 60px rgba(0, 0, 0, 0.5),
    0 0 0 1px rgba(244, 193, 42, 0.12) inset;
}
.celebration__welcome-icon-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 84px;
  height: 84px;
  margin-bottom: 6px;
  border-radius: 50%;
  background: radial-gradient(
    circle at 35% 30%,
    color-mix(in srgb, #f4c12a 35%, transparent),
    color-mix(in srgb, #f4c12a 6%, transparent) 70%
  );
  box-shadow: 0 0 0 2px rgba(244, 193, 42, 0.4) inset;
}
.celebration__welcome-icon {
  width: 42px;
  height: 42px;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.45));
}
.celebration__card--welcome .celebration__kicker {
  color: #ffd65c;
}
.celebration__welcome-title {
  font-size: 1.2rem;
  font-weight: 800;
  color: #fff;
  max-width: 290px;
}
.celebration__welcome-rewards {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 8px;
}
.celebration__welcome-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 18px;
  border-radius: 999px;
  font-weight: 800;
  font-size: 1.1rem;
  color: #0e2f27;
  background: linear-gradient(180deg, #8de89a, #52ba63);
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.22);
}
.celebration__welcome-chip--dp {
  color: #2b1d04;
  background: linear-gradient(180deg, #ffe08a, #e8ab1c);
}
.celebration__welcome-chip-icon {
  width: 32px;
  height: 32px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
}
.celebration__welcome-flavor {
  margin-top: 16px;
  padding-top: 12px;
  max-width: 280px;
  border-top: 1px dashed rgba(244, 193, 42, 0.35);
  font-size: 0.78rem;
  font-style: italic;
  line-height: 1.35;
  color: #bcd9cd;
}
.celebration__hint {
  margin-top: 16px;
  font-size: 0.75rem;
  color: var(--xp-muted);
}
@keyframes celebration-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes celebration-shine {
  to {
    transform: translateX(100%);
  }
}
@keyframes celebration-pop {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .celebration-overlay,
  .celebration__card {
    animation: none;
  }
}

/* Phones (VIEW_REQUIREMENTS.md §4): gated on input capability so a narrowed desktop window can never
   match. The celebration card sheds padding and scrolls inside a short landscape viewport, and the
   picker trays size against the dynamic viewport so browser chrome cannot push the actions off-screen. */
@media (hover: none) and (pointer: coarse) {
  .celebration__card,
  .celebration__card--milestone {
    padding: 20px 20px;
    max-height: 100dvh;
    overflow-y: auto;
  }
  .look-grid {
    max-height: min(44dvh, 320px);
  }
  .look-picker--plates .look-grid {
    max-height: min(62dvh, 480px);
  }
  .look-card .look-picker--plates .look-grid {
    max-height: min(36dvh, 260px);
  }
}
@media (hover: none) and (pointer: coarse) and (max-height: 480px) {
  .celebration__level,
  .celebration__card--milestone .celebration__level {
    font-size: clamp(3rem, 16vh, 5rem);
  }
  .celebration__crest {
    margin-top: 6px;
  }
  .celebration__hint {
    margin-top: 8px;
  }
}
