/* Knight theme: midnight sky, cornflower fields, moonlit steel, prismatic sheen. */
:root {
  color-scheme: dark; /* native checkboxes, selects and their lists in the dark scheme */
  --bg: #050814;
  --panel-2: rgba(28, 40, 80, 0.55);
  --line: rgba(150, 170, 225, 0.15);
  --line-2: rgba(200, 212, 245, 0.3);
  --text: #e9edf7;
  --muted: #8f9abb;
  --accent: #6d95ff;
  --accent-2: #3d63e0;
  --gold: #e6c47e;
  --neg: #ff9393;
  --warn: #f2c66d;
  --radius: 14px;
  --steel: linear-gradient(180deg, #ffffff 0%, #d3dbec 42%, #8d97b1 100%);
  --display: "Cinzel", "Trajan Pro", Georgia, serif;
  --body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* One type scale: eyebrows, meta, secondary UI, body, small headings, entity titles, page titles, value amounts. */
  --fs-1: 11px; --fs-2: 12px; --fs-3: 13px; --fs-4: 15px; --fs-5: 20px; --fs-6: 24px;
  --fs-7: clamp(28px, 4vw + 12px, 40px); --fs-8: clamp(30px, 3vw + 16px, 44px); --fs-8-long: clamp(26px, 2.6vw + 14px, 38px);
  /* Fields and controls: one height, one radius, one background. */
  --h-ctl: 40px; --h-ctl-lg: 48px; --r-2: 10px; --field-bg: rgba(10, 16, 36, 0.9);
}
body[data-tab="discord"] { --accent: #a58bff; --accent-2: #7357ee; }

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; }
body {
  background: var(--bg); color: var(--text);
  font: var(--fs-4)/1.45 var(--body); font-variant-numeric: tabular-nums;
  min-height: 100vh; display: flex; flex-direction: column;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
/* Outlines follow each element's own corners; only bare links get rounded ones. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
a:focus-visible { border-radius: 6px; }
h1, h2, h3, h4 { margin: 0; }
h1, h2, h3 { font-family: var(--display); font-weight: 700; letter-spacing: 0.02em; }
h3 { font-size: var(--fs-4); margin-bottom: 12px; }
.muted { color: var(--muted); }
.small { font-size: var(--fs-2); }
.num { text-align: right; white-space: nowrap; }
.mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: var(--fs-2); word-break: break-all; }
.steel { background: var(--steel); -webkit-background-clip: text; background-clip: text; color: transparent; }
.sr { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ---------- backdrop art and falling petals ---------- */

/* The rose in the knight's hand sits exactly on the horizontal center line. The art is anchored at the rose
   (translateX by the rose's x as a share of the image width) and sized so the narrower side of the rose still
   reaches the screen edge: width >= 50vw / that share. Wide screens use the outpainted valley (rose at 43.78%),
   tall ones the original portrait (rose at 62.84%). It is shifted down so the rose lands under the search and
   tier chips, and fades in from the dark page above. Dimming is one overlay, not a filter, so the fixed layer
   never repaints while scrolling. Both fixed layers take the large viewport height (lvh), so a phone's address
   bar sliding away mid-scroll doesn't resize and re-raster them. */
.backdrop, .petals { position: fixed; top: 0; left: 0; right: 0; height: 100vh; height: 100lvh; pointer-events: none; overflow: hidden; contain: strict; }
.backdrop { z-index: -2; background: var(--bg); }
.backdrop .art {
  position: absolute; top: 12vh; left: 50%; width: max(115vw, 178vh); aspect-ratio: 1672 / 941; transform: translateX(-43.78%);
  background: url("/img/knight-valley.jpg") center / 100% 100% no-repeat;
  /* Where the light breaks through the clouds (share of the art), how far its rays reach and how wide they start. */
  --lx: 48.4%; --ly: 8.5%; --ray: 52%; --ray-w: 3.4%; --bloom: 30%; --motes-w: 30%;
}
@media (orientation: portrait) {
  .backdrop .art {
    top: 6vh; width: max(135vw, 57vh); aspect-ratio: 736 / 1307; transform: translateX(-62.84%); background-image: url("/img/knight-rose.jpg");
    --lx: 66.6%; --ly: 8.8%; --ray: 42%; --ray-w: 7.5%; --bloom: 72%; --motes-w: 70%;
  }
}
/* The art is dimmed from inside, beneath its light layers, so the light glows at full strength over the dimmed
   painting instead of being dimmed with it. It fades in from the dark page above through an overlay rather than a
   mask: a mask over the animated light would redraw the whole art every frame. */
.backdrop .art::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(5, 8, 20, 0.5) 0%, rgba(5, 8, 20, 0.6) 45%, rgba(5, 8, 20, 0.9) 85%);
}
.backdrop .art::after { content: ""; position: absolute; inset: 0 0 auto; height: 90px; background: linear-gradient(180deg, var(--bg), transparent); }

/* Light from the sky: a soft bloom that breathes and a fan of rays that drifts and shimmers. Two layers, animating
   only opacity and transform, so the compositor runs them without repainting. They rest while results are shown
   (the backdrop is dimmed there anyway). */
.art .bloom, .art .rays { position: absolute; pointer-events: none; }
.art .bloom {
  left: var(--lx); top: var(--ly); width: var(--bloom); aspect-ratio: 1; translate: -50% -42%;
  background: radial-gradient(closest-side, rgba(226, 236, 255, 0.34), rgba(140, 170, 255, 0.14) 45%, transparent);
  animation: bloom 8s ease-in-out infinite alternate;
}
.art .rays {
  left: calc(var(--lx) - var(--ray-w) / 2); top: var(--ly); width: var(--ray-w); height: var(--ray); transform-origin: 50% 0;
  animation: rays-drift 23s ease-in-out infinite alternate, rays-shimmer 9.5s ease-in-out infinite;
}
/* Each beam turns about the light source; positive angles fall toward the knight on the left. */
.art .rays b {
  position: absolute; inset: 0; transform-origin: 50% 0; transform: rotate(var(--a)) scaleX(var(--w));
  background: radial-gradient(50% 100% at 50% 0, rgba(205, 222, 255, 0.24), rgba(150, 180, 255, 0.07) 55%, transparent);
}
@keyframes bloom { from { opacity: 0.55; transform: scale(0.93); } to { opacity: 1; transform: scale(1.06); } }
@keyframes rays-drift { from { transform: rotate(-1.6deg); } to { transform: rotate(1.6deg); } }
@keyframes rays-shimmer { 0%, 100% { opacity: 0.65; } 30% { opacity: 1; } 55% { opacity: 0.75; } 80% { opacity: 0.95; } }
/* Motes of dust catching the light: a few specks inside the cone of rays that drift down and glint. */
.art .motes { position: absolute; pointer-events: none; left: var(--lx); top: var(--ly); width: var(--motes-w); height: var(--ray); translate: -50% 0; }
.art .motes b {
  position: absolute; left: calc(50% + var(--x)); top: var(--y); width: 3px; height: 3px; border-radius: 50%;
  background: #e4ecff; box-shadow: 0 0 6px 2px rgba(160, 188, 255, 0.55); opacity: 0;
  animation: mote var(--d) ease-in-out var(--t) infinite;
}
@keyframes mote {
  0% { opacity: 0; transform: translate3d(0, 0, 0) scale(0.6); }
  35% { opacity: 0.95; }
  60% { opacity: 0.5; transform: translate3d(calc(var(--dx) * 0.6), 18px, 0) scale(1); }
  80% { opacity: 0.85; }
  100% { opacity: 0; transform: translate3d(var(--dx), 30px, 0) scale(0.7); }
}
body:not(.landing) .art .bloom, body:not(.landing) .art .rays, body:not(.landing) .art .motes b { animation-play-state: paused; }

/* A vignette deepens the gloom toward the edges of the landing page; results pages dim the whole backdrop. */
.backdrop::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(125% 95% at 50% 36%, transparent 55%, rgba(2, 4, 12, 0.55));
  transition: background 0.6s;
}
body:not(.landing) .backdrop::after { background: rgba(5, 8, 20, 0.86); }

.petals { z-index: -1; }
/* The span falls and the <i> inside it spins, as two animations, so app.js can pause a pushed petal's fall while it
   keeps turning; the wind adds to them through the separate translate and rotate properties. */
.petals span { position: absolute; top: -6vh; left: var(--x); will-change: transform; animation: fall var(--d) linear var(--t) infinite; }
.petals i {
  display: block; will-change: transform;
  width: calc(15px * var(--s)); height: calc(9px * var(--s)); border-radius: 85% 0 85% 0;
  background: linear-gradient(135deg, #b4caff, #3a5ef0 55%, #1b2a9c);
  box-shadow: 0 0 12px rgba(90, 130, 255, 0.85); opacity: 0.85;
  animation: spin var(--d) linear var(--t) infinite;
}
@keyframes fall {
  50% { transform: translate3d(-40px, 55vh, 0); }
  100% { transform: translate3d(25px, 112vh, 0); }
}
@keyframes spin {
  50% { transform: rotate(200deg); }
  100% { transform: rotate(430deg); }
}

/* ---------- header ---------- */

.top {
  display: flex; align-items: center; gap: 24px;
  padding: 14px 24px; border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(5, 8, 20, 0.9), rgba(5, 8, 20, 0.45));
}
.brand { display: flex; align-items: center; gap: 10px; color: var(--text); font: 700 var(--fs-5)/1 var(--display); letter-spacing: 0.04em; }
.brand .helm { width: 42px; height: 42px; object-fit: contain; filter: drop-shadow(0 0 1.5px rgba(205, 218, 255, 0.75)) drop-shadow(0 2px 8px rgba(109, 149, 255, 0.45)); }
.brand b { color: var(--accent); font-weight: 700; }
.brand:hover { text-decoration: none; }
.tabs { display: flex; gap: 4px; }
/* How many are in the hangout (app.js): a small gold number on its tab that flickers faintly, like a lantern.
   Switch off: delete the "hangout count" block in app.js. */
.tab-count {
  display: inline-block; min-width: 1ch; margin-left: 6px; font: 700 var(--fs-1)/1 var(--display); letter-spacing: 0; color: var(--gold);
  text-shadow: 0 0 8px rgba(230, 196, 126, 0.55); animation: lantern 5.3s ease-in-out infinite;
}
@keyframes lantern { 0%, 100% { opacity: 1; } 18% { opacity: 0.78; } 24% { opacity: 0.95; } 61% { opacity: 0.84; } 70% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .tab-count { animation: none; } }
/* Still in the hangout while looking at another page (hangout.js): a small blue light in its tab's corner, taking
   no room from the row, gold once someone has said something since. */
.tabs a.away { position: relative; }
.tabs a.away::before {
  content: ''; position: absolute; top: 4px; left: 3px; width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 6px rgba(109, 149, 255, 0.8);
}
.tabs a.away.news::before { background: var(--gold); box-shadow: 0 0 8px rgba(230, 196, 126, 0.85); }
.tabs a { color: var(--muted); padding: 6px 12px; border-radius: 8px; font-size: var(--fs-3); letter-spacing: 0.08em; text-transform: uppercase; }
.tabs a:hover { color: var(--text); text-decoration: none; background: var(--panel-2); }
.tabs a.on { color: var(--text); background: var(--panel-2); box-shadow: inset 0 -2px 0 var(--accent); }
/* Discord server button at the right end of the header: the mark in muted steel, lit like a tab on hover.
   Switch off: delete the link in index.html. */
.hd-discord {
  flex: none; display: grid; place-items: center; width: 38px; height: 38px; margin-left: auto; border-radius: 8px;
  color: var(--muted); transition: color 0.2s, background-color 0.2s;
}
.hd-discord:hover { color: #c9d3f2; background: var(--panel-2); text-decoration: none; }
.hd-discord:focus-visible { border-radius: 8px; }

main { width: 100%; max-width: 1160px; margin: 0 auto; padding: 24px 24px 140px; flex: 1; }
footer { color: var(--muted); font-size: var(--fs-2); text-align: center; padding: 20px; border-top: 1px solid var(--line); background: rgba(5, 8, 20, 0.6); }

/* ---------- hero, search, buttons ---------- */

.hero { text-align: center; margin: 5vh auto 8px; max-width: 640px; }
.hero h1 {
  font: 700 clamp(36px, 7vw, 64px)/1.05 var(--display); letter-spacing: 0.03em; margin: 0 0 10px;
  filter: drop-shadow(0 2px 14px rgba(5, 8, 20, 0.9));
}
.hero p { color: #c8d2ec; margin: 0 0 22px; text-shadow: 0 1px 10px rgba(5, 8, 20, 0.95); }
/* Moonlight on steel: now and then a narrow streak of cool light slides across the title, like moonlight running
   along a blade turned in the hand, then the steel rests again. Darker flanks around the streak are what make it
   read as polished metal rather than a glow. Only the streak's position moves.
   Switch off: remove the "sheen" class from the title in index.html. */
.hero h1.sheen {
  background-image:
    linear-gradient(105deg, transparent 43%, rgba(20, 30, 64, 0.35) 46.5%, rgba(214, 228, 255, 0.9) 49.2%, #fff 50%, rgba(214, 228, 255, 0.9) 50.8%, rgba(20, 30, 64, 0.35) 53.5%, transparent 57%),
    var(--steel);
  background-size: 320% 100%, 100% 100%;
  background-repeat: no-repeat;
  background-position: 100% 0, 0 0;
  animation: moonlight 11s cubic-bezier(0.5, 0, 0.35, 1) -4s infinite;
}
@keyframes moonlight {
  0%, 70% { background-position: 100% 0, 0 0; }
  92%, 100% { background-position: 0% 0, 0 0; }
}
@media (prefers-reduced-motion: reduce) { .hero h1.sheen { animation: none; } }
.ladder { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-top: 26px; }
/* A legend, not buttons: flat, no border. */
.ladder .rank { background: rgba(8, 12, 28, 0.85); border-color: transparent; cursor: default; }
.explore { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 20px; margin-top: 16px; font-size: var(--fs-3); text-shadow: 0 1px 10px rgba(5, 8, 20, 0.95); }

.search { display: flex; gap: 8px; max-width: 640px; margin: 8px auto 24px; }
/* Every text field and select: one height, one radius, one background, one focus ring; the selects share a chevron. */
:where(.search input, .search select, .adjust select, .adjust input[type="number"], .values .sec-head input, .own-edit textarea, .own-edit input[type="text"], .own-edit select, .acct-form input[name="q"], .hg-say input, .hg-pick select) {
  font: inherit; font-size: var(--fs-4); color: var(--text); background-color: var(--field-bg);
  border: 1px solid var(--line-2); border-radius: var(--r-2); padding: 0 12px; min-height: var(--h-ctl); outline: none;
}
:where(.search input, .search select, .adjust select, .adjust input[type="number"], .values .sec-head input, .own-edit textarea, .own-edit input[type="text"], .own-edit select, .acct-form input[name="q"], .hg-say input, .hg-pick select):focus-visible { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
:where(.adjust select, .own-edit select, .hg-pick select) { appearance: none; padding-right: 34px; background: var(--field-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%238f9abb' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 12px center / 12px; cursor: pointer; }
.search input {
  flex: 1; min-width: 0; padding: 0 14px; font-size: 16px; min-height: var(--h-ctl-lg);
}
.search input::placeholder { color: var(--muted); }
/* The platform picker, styled like the search box beside it. */
.search select {
  flex: none; padding: 12px 34px 12px 14px; min-height: var(--h-ctl-lg); cursor: pointer; appearance: none;
  background: var(--field-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%238f9abb' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 12px center / 12px;
}
.search select:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
.search select option { background: #0c1228; }
/* Where the browser lets a page style the list itself (Chrome and Edge 135+), it matches the recent-lookups list;
   elsewhere the native list stays. */
@supports (appearance: base-select) {
  .search select, .search select::picker(select) { appearance: base-select; }
  .search select::picker-icon { display: none; }
  /* Below the box whenever it fits (Chrome's default picks the roomier side), above only when it doesn't. */
  .search select::picker(select) {
    position-try-order: normal; margin: 6px 0;
    padding: 6px; color: var(--text); border: 1px solid var(--line-2); border-radius: 10px;
    background: rgba(12, 18, 40, 0.98); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
  }
  .search select option { padding: 8px 12px; border-radius: 7px; font-size: var(--fs-3); background: none; cursor: pointer; }
  .search select option::checkmark { display: none; }
  .search select option:hover, .search select option:focus-visible { background: var(--panel-2); outline: none; }
  .search select option:checked { color: var(--accent); font-weight: 600; }
}
.q-wrap { position: relative; flex: 1; min-width: 0; display: flex; }
/* Recent lookups under the empty, focused search box; they float over the page instead of pushing it down. */
.recent {
  position: absolute; z-index: 5; top: calc(100% + 6px); left: 0; right: 0; margin: 0; padding: 6px; list-style: none;
  background: rgba(12, 18, 40, 0.98); border: 1px solid var(--line-2); border-radius: 10px; box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
}
.recent li { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 7px; cursor: pointer; font-size: var(--fs-4); }
.recent li[aria-selected="true"], .recent li:hover { background: var(--panel-2); }
.recent img { width: 20px; height: 20px; border-radius: 4px; }
.recent .rank { margin-left: auto; padding: 3px 7px; }
.recent .clear { justify-content: center; color: var(--muted); font-size: var(--fs-2); }
.search button { min-height: var(--h-ctl-lg); }
button {
  position: relative; overflow: hidden;
  font: inherit; cursor: pointer; border: 0; border-radius: 10px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 55%, #fff), var(--accent) 48%, var(--accent-2));
  color: #050814; font-weight: 700; letter-spacing: 0.02em; padding: 10px 18px;
  box-shadow: 0 4px 18px color-mix(in srgb, var(--accent) 35%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
/* Prismatic glint sweeping across steel, like light on polished armor. */
button::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(110deg, transparent 32%, rgba(255, 255, 255, 0.5) 44%, rgba(255, 214, 120, 0.35) 49%, rgba(126, 240, 197, 0.3) 54%, rgba(195, 139, 255, 0.25) 58%, transparent 68%);
  transform: translateX(-130%); transition: transform 0.7s ease;
}
button:hover::after { transform: translateX(130%); }

.status { text-align: center; color: var(--muted); margin-bottom: 16px; }
.status:empty { margin: 0; }
.status.err { color: var(--neg); }
/* Pages settle in instead of snapping: whatever the router puts in the view (a page, or a result replacing its
   loading placeholder), and the landing title, fade up a few pixels. It runs once per insertion, and nothing is
   left applied afterwards (fill backwards), so sticky and fixed parts inside behave as before.
   Switch off: delete this block. */
.hero, #view > * { animation: settle 0.28s ease-out backwards; }
@keyframes settle { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) { .hero, #view > * { animation: none; } }

/* ---------- cards ---------- */

.grid { display: grid; grid-template-columns: 320px 1fr; gap: 16px; align-items: start; }
.col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.col.pin { position: sticky; top: 16px; }
.card {
  background:
    linear-gradient(180deg, rgba(20, 30, 62, 0.94), rgba(10, 16, 36, 0.96)) padding-box,
    linear-gradient(160deg, rgba(225, 233, 255, 0.38), rgba(109, 149, 255, 0.14) 38%, rgba(255, 255, 255, 0.04) 68%, rgba(165, 139, 255, 0.22)) border-box;
  border: 1px solid transparent; border-radius: var(--radius); padding: 18px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.38), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* Loading placeholders, shaped like the cards they stand in for. The sheen moves by transform, so it animates
   without repainting. */
.sk {
  display: block; position: relative; overflow: hidden; height: 14px; margin: 12px auto; border-radius: 6px;
  background: rgba(150, 170, 225, 0.08);
}
.sk::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(150, 170, 225, 0.1), transparent);
  transform: translateX(-100%); animation: shimmer 1.4s linear infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }
.sk-head { display: flex; align-items: center; gap: 18px; }
.sk-head .sk { margin: 6px 0; }

.profile { text-align: center; }
.profile canvas, .profile .fallback { display: block; margin: 0 auto 8px; max-width: 100%; }
/* A fixed glow behind the live skin; a drop-shadow filter would be recomputed on every WebGL frame. */
.profile canvas { background: radial-gradient(42% 46% at 50% 56%, rgba(80, 120, 255, 0.2), transparent 72%); }
.profile .fallback { filter: drop-shadow(0 14px 28px rgba(80, 120, 255, 0.28)); }
/* Usernames are case-sensitive identifiers; Cinzel has no lowercase, so they use the body font. */
.profile h1, .dc-body h1 { font-family: var(--body); letter-spacing: 0; }
.profile h1 { font-size: var(--fs-6); margin-bottom: 2px; }
h3 .muted { font: 400 var(--fs-2)/1.4 var(--body); letter-spacing: 0; }
.facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; margin: 14px 0 0; text-align: left; font-size: var(--fs-3); }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; text-align: right; }
.facts dd.owners-trend { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.owners-trend svg { color: var(--accent); flex: none; }
.links { display: flex; justify-content: center; gap: 14px; margin-top: 14px; font-size: var(--fs-3); }

.adjust label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-3); color: var(--muted); margin-bottom: 10px; }
.adjust label.check { flex-direction: row; align-items: center; gap: 8px; color: var(--text); }
.adjust input[type="checkbox"] { accent-color: var(--accent); width: 16px; height: 16px; }
.adjust .sep { margin: 14px 0 8px; border-top: 1px solid var(--line); padding-top: 12px; }

.pill { display: inline-block; font-size: var(--fs-1); padding: 2px 8px; border-radius: 99px; background: var(--panel-2); color: var(--muted); vertical-align: middle; }
.pill.warn { color: var(--warn); background: rgba(242, 198, 109, 0.12); }

/* Value tier colors: D → SS, set by the midpoint value. */
.r0 { --c: #a89b8a; }
.r1 { --c: #b8c2d6; }
.r2 { --c: #e3e9f7; }
.r3 { --c: #7fa4ff; }
.r4 { --c: #b89aff; }
.r5 { --c: #f0cf86; }
.rank {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  font: 700 var(--fs-1)/1 var(--display); letter-spacing: 0.12em; text-transform: uppercase;
  padding: 6px 10px 6px 8px; border-radius: 8px; color: var(--c); background: color-mix(in srgb, var(--c) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--c) 40%, transparent);
}
.rank svg { width: 14px; height: 16px; }
.rank.r5 { box-shadow: 0 0 18px rgba(240, 207, 134, 0.35); }

/* ---------- estimate card ---------- */

.rc-head { display: flex; align-items: center; gap: 18px; }
/* One eyebrow for every small label over or beside a value. */
.label, .held h4, .method-h, .vt .sub th, .jump span, .acct-who small, .adjust .sep, .free-name .label {
  font: 600 var(--fs-1)/1.4 var(--body); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
}
.v-range { font: 700 var(--fs-8)/1.1 var(--display); letter-spacing: 0.01em; margin: 2px 0 4px; }
.v-range.long { font-size: var(--fs-8-long); }
.v-sub { color: var(--muted); display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; font-size: var(--fs-4); }
.v-sub b { color: var(--text); }

/* Tier crest: a shield in the tier color with its letter. */
.crest { position: relative; flex: none; width: 64px; height: 72px; color: var(--c); }
.crest svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.crest path { fill: color-mix(in srgb, var(--c) 14%, transparent); stroke: var(--c); stroke-width: 2; }
.crest span {
  position: absolute; inset: 0 0 6px; display: grid; place-items: center;
  font: 700 30px/1 var(--display); text-shadow: 0 0 16px color-mix(in srgb, var(--c) 55%, transparent);
}
.crest span.two { font-size: 22px; letter-spacing: -0.02em; }
.crest.r5 { filter: drop-shadow(0 0 14px rgba(240, 207, 134, 0.35)); }

.cert { display: inline-flex; align-items: center; gap: 3px; }
.cert i { width: 7px; height: 7px; border-radius: 2px; background: var(--line-2); }
.cert i.on { background: var(--accent); }
.cert i:last-of-type { margin-right: 5px; }
/* The confidence label and the footer lead to "How estimates work" without looking like calls to action. */
.free-name { max-width: 420px; margin: 0 auto; text-align: center; display: grid; gap: 4px; }
.free-name .fn-name { font-size: var(--fs-6); font-weight: 700; overflow-wrap: anywhere; }
.free-name .fn-range { font-size: var(--fs-5); font-weight: 600; margin-bottom: 4px; }
.free-name p { margin: 8px 0 0; }
footer .legal { display: block; margin-top: 6px; opacity: 0.8; }
.privacy { max-width: 760px; margin: 0 auto; display: grid; gap: 16px; }
.privacy .values-head { margin-bottom: 2px; }
.privacy .legal { text-align: center; margin: 0; }
.cert a, footer a { color: inherit; }
/* Small text links still get a 24px tap height. */
.cert a, .crumbs a { display: inline-block; padding: 3px 0; }
.cert a:hover, footer a:hover { color: var(--text); text-decoration: underline dotted; text-underline-offset: 3px; }

/* What the value is made of. Group colors are shared by the bar and the rows. */
.made { margin: 18px 0 4px; }
.made-bar { display: flex; gap: 2px; height: 10px; border-radius: 99px; overflow: hidden; background: rgba(10, 16, 36, 0.9); }
.made-bar i { display: block; flex-basis: 0; min-width: 4px; }
.parts { list-style: none; margin: 12px 0 0; padding: 0; }
.parts li { display: grid; grid-template-columns: 10px 1fr auto; gap: 10px; align-items: baseline; padding: 8px 0; border-top: 1px solid var(--line); font-size: var(--fs-4); }
/* Swatches sit on the first line, not the middle of a reason that wraps. */
.parts li > i { width: 10px; height: 10px; border-radius: 3px; align-self: start; margin-top: 5px; }
.parts .muted { font-size: var(--fs-3); margin-left: 4px; }
.parts .num { font-weight: 600; }
.parts .pending > i, .parts .quiet > i { opacity: 0.35; }
.parts .quiet b, .parts .quiet .num { color: var(--muted); font-weight: 500; }
.parts .pending .num { align-self: center; }
.parts .sk { width: 72px; height: 12px; margin: 0; }
.g-account { background: #5f6b8c; }
.g-name, .g-handle { background: #6d95ff; }
.g-capes { background: #8be3b5; }
.g-collection { background: #3fb6a8; }
.g-hypixel { background: #f2c66d; }
.g-age { background: #a58bff; }
.g-badges { background: #f0cf86; }
.g-cosmetics { background: #ff8fc7; }
.g-nitro { background: #ff73fa; }
/* Hatched where the part rests on rarity estimates instead of market asks. */
.est { background-image: repeating-linear-gradient(135deg, rgba(5, 8, 20, 0.55) 0 3px, transparent 3px 6px); }

.est-note { color: var(--muted); font-size: var(--fs-3); margin: 12px 0 0; }
.est-note b { color: var(--text); font-weight: 600; }
.est-key { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 8px; vertical-align: -1px; background-color: var(--muted); }
.held { margin-top: 14px; }
.held h4 { margin-bottom: 6px; }
.held ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: var(--fs-3); }
.held li.warn b { color: var(--warn); }

.sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.sec-head h3 { margin: 0; }
.armory { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }

/* ---------- capes ---------- */

.capes { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 8px; }
.cape {
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: 10px; box-shadow: none;
  padding: 10px 8px; font-weight: 400; display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center;
}
button.cape:hover { border-color: var(--line-2); }
.cape.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 6px 20px color-mix(in srgb, var(--accent) 25%, transparent); }
.cape.removed { opacity: 0.4; }
.cape .tex {
  width: 40px; height: 64px; margin-bottom: 6px; flex: none;
  background-size: 640% 200%; background-position: 1.852% 6.25%; background-repeat: no-repeat;
  background-color: rgba(150, 170, 225, 0.07); /* stands in while the texture loads */
  image-rendering: pixelated; border-radius: 2px;
}
.cape .tex.of { background-size: 460% 137.5%; background-position: 2.78% 16.67%; }
.cape .cn { font-size: var(--fs-3); line-height: 1.2; }
/* Prices line up along the bottom of a row even when a name takes two lines. */
.cape .cv { color: var(--accent); font-weight: 600; margin-top: auto; padding-top: 2px; }
.cape .eq { font-size: var(--fs-1); color: var(--accent); }
a.cape.static { color: var(--text); }
a.cape.static:hover { text-decoration: none; border-color: var(--line-2); }

/* ---------- cape pages ---------- */

.crumbs { display: flex; gap: 8px; max-width: 820px; margin: 0 auto 12px; font-size: var(--fs-3); color: var(--muted); }
.cape-page { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 28px; align-items: center; max-width: 820px; margin: 0 auto; }
.cape-art { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.cape-art canvas { display: block; max-width: 100%; }
/* The flat texture's front panel, 8 px per pixel. */
.cape-art .tex {
  width: 80px; height: 128px; border-radius: 3px; image-rendering: pixelated;
  background-size: 640% 200%; background-position: 1.852% 6.25%; background-repeat: no-repeat;
}
.cape-info h1 { font-size: var(--fs-6); margin: 4px 0 8px; }
.cape-info .facts { margin-top: 18px; max-width: 380px; }
@media (max-width: 640px) {
  .cape-page { grid-template-columns: minmax(0, 1fr); gap: 16px; text-align: center; }
  .cape-info .v-sub { justify-content: center; }
  .cape-info .facts { margin: 18px auto 0; }
}

/* ---------- Discord ---------- */

.dc { padding: 0; overflow: hidden; }
.dc-banner { height: 96px; background-size: cover; background-position: center; }
.dc-av { position: relative; width: 92px; height: 92px; margin: -46px 0 0 16px; }
.dc-av img:first-child { width: 92px; height: 92px; border-radius: 50%; border: 6px solid #0f1733; background: #0f1733; }
.dc-av .deco { position: absolute; inset: -4px; width: 100px; height: 100px; pointer-events: none; }
.dc-body { padding: 8px 18px 18px; }
.dc-body h1 { font-size: var(--fs-6); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.gtag { display: inline-flex; align-items: center; gap: 4px; font: 600 var(--fs-2)/1.4 var(--body); letter-spacing: 0; background: var(--panel-2); border-radius: 6px; padding: 2px 6px; }
.gtag img { width: 14px; height: 14px; }
.badges { display: inline-flex; max-width: 100%; flex-wrap: wrap; gap: 4px; margin: 10px 0 4px; padding: 6px; background: var(--panel-2); border-radius: 8px; min-height: 34px; align-items: center; }
.badges img { width: 22px; height: 22px; }
.badges img.declared { opacity: 0.75; outline: 1px dashed var(--muted); outline-offset: 1px; border-radius: 4px; }
.np-row {
  position: relative; height: 52px; margin: 10px 0 4px; padding: 0 10px; border-radius: 8px; overflow: hidden;
  display: flex; align-items: center; gap: 10px; background: var(--panel-2);
}
.np-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: right center; }
.np-tint { position: absolute; inset: 0; }
.np-av { position: relative; z-index: 1; width: 34px; height: 34px; flex: none; }
.np-av img:first-child { width: 34px; height: 34px; border-radius: 50%; }
.np-av .deco { position: absolute; inset: -4px; width: 42px; height: 42px; }
.np-name { position: relative; z-index: 1; font-weight: 600; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); display: flex; align-items: center; gap: 6px; }
.coll { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; margin: 6px 0 12px; }
.coll-item { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 10px 4px 8px; border-radius: 10px; background: var(--panel-2); font-size: var(--fs-1); text-align: center; border: 1px solid transparent; }
.dc-av.mini { width: 48px; height: 48px; margin: 0 0 6px; }
.dc-av.mini img:first-child { width: 48px; height: 48px; border: 0; }
.dc-av.mini .deco { inset: -6px; width: 60px; height: 60px; }
.plates { display: grid; gap: 6px; margin: 6px 0 12px; }
.coll-plate { display: flex; align-items: center; gap: 10px; padding: 6px; border-radius: 10px; background: var(--panel-2); border: 1px solid transparent; font-size: var(--fs-3); }
.coll-plate img { width: 96px; height: 32px; object-fit: cover; object-position: right center; border-radius: 6px; flex: none; }

/* ---------- Values tab ---------- */

.values-head { text-align: center; max-width: 640px; margin: 2vh auto 18px; }
.values-head h1 { font-size: var(--fs-7); line-height: 1.1; margin-bottom: 8px; }
.values-head p { margin: 0; }
/* Section links, pinned to the top while the long guide scrolls. Solid backing, no blur, so it stays cheap. */
.jump {
  position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 2px;
  margin: 0 -24px 16px; padding: 8px 24px; overflow-x: auto; scrollbar-width: none;
  background: rgba(5, 8, 20, 0.97); border-bottom: 1px solid var(--line);
}
.jump::-webkit-scrollbar { display: none; }
/* Auto margins center the links but, unlike justify-content, give way when they overflow on narrow screens. */
.jump::before, .jump::after { content: ""; margin: auto; }
.jump span { margin: 0 6px 0 14px; white-space: nowrap; }
.jump span:first-child { margin-left: 0; }
.jump a { color: var(--text); font-size: var(--fs-3); padding: 6px 10px; border-radius: 8px; white-space: nowrap; }
.jump a:hover { background: var(--panel-2); text-decoration: none; }
.values section { scroll-margin-top: 64px; }
.values section:focus { outline: none; }
.values .sec-head { flex-wrap: wrap; }
.values .sec-head input {
  margin-left: auto; width: 180px; max-width: 100%;
}
.values .sec-head input::placeholder { color: var(--muted); }
.values .sec-head input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
/* minmax(0, …) lets wide tables scroll inside their card instead of stretching the column past the screen. */
.values-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 16px; align-items: start; }
#v-method { margin-top: 16px; }
.method { margin: 0; padding-left: 18px; display: grid; gap: 6px; font-size: var(--fs-4); line-height: 1.5; }
.method code { font: 13px ui-monospace, "Cascadia Mono", Consolas, monospace; }
.method-h { margin: 16px 0 6px; }
.updates { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: var(--fs-3); }
.updates time { display: inline-block; min-width: 58px; color: var(--muted); }
.stack { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
/* Off-screen sections skip layout and paint until scrolled near. Only the height is a placeholder: a placeholder
   width would count toward the column's minimum and push the page wider than a phone. */
.values .card { content-visibility: auto; contain-intrinsic-height: auto 480px; }
.values.laid-out .card { content-visibility: visible; }
.vt { width: 100%; border-collapse: collapse; font-size: var(--fs-3); }
.vt td, .vt th { padding: 7px 0; border-top: 1px solid var(--line); vertical-align: middle; }
.vt td + td, .vt th + th { padding-left: 12px; }
.vt th { font-size: var(--fs-2); font-weight: 600; color: var(--muted); text-align: left; border-top: 0; }
.vt th.num { text-align: right; }
.vt .sub th { padding: 16px 0 6px; }
.vt .sub:first-child th { padding-top: 0; }
.vt img { width: 18px; height: 18px; vertical-align: -4px; margin-right: 4px; }
.vt .muted { font-size: var(--fs-2); }
.scroll-x { overflow-x: auto; }
.values .card > p { margin: 10px 0 0; }

@media (max-width: 860px) {
  .grid { grid-template-columns: 1fr; }
  /* Answer first on narrow screens: estimate, then who it is, then the details. */
  .grid > .col { display: contents; }
  .value { order: 1; }
  .profile, .dc { order: 2; }
  .collection-card { order: 3; }
  .adjust { order: 4; }
  .values-grid { grid-template-columns: minmax(0, 1fr); }
  .tabs a { padding: 6px 9px; letter-spacing: 0.05em; }
}
/* The header's right end (Discord button, then Sign in or your account) on narrower screens. It stays on the
   brand's row: a long account name gives way first, then below 800px both are icons (the label stays for screen
   readers), and on phones they grow to thumb size. Prefixed with .top to outrank menu.css, which loads later. */
.top .acct { flex: 0 1 auto; min-width: 0; }
.top .acct .acct-btn { max-width: 100%; }
.top .acct .acct-label { min-width: 0; }
@media (max-width: 860px) { .top { gap: 16px; } }
@media (max-width: 800px) {
  .top .acct .acct-btn { width: 38px; padding: 0; justify-content: center; }
  .top .acct .acct-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .top .acct .acct-chev { display: none; }
}
@media (max-width: 760px) {
  .top .hd-discord, .top .acct .acct-btn { width: 42px; height: 42px; }
  .top .acct .acct-btn .acct-av { width: 30px; height: 30px; }
  .top .acct .acct-pop { width: min(272px, calc(100vw - 32px)); }
}
/* The smallest phones: a slightly smaller brand and buttons keep the icons on its row. */
@media (max-width: 359px) {
  .brand { gap: 6px; font-size: var(--fs-5); }
  .brand .helm { width: 34px; height: 34px; }
  .top .hd-discord, .top .acct .acct-btn { width: 38px; height: 38px; }
  .top .hd-discord + .acct { margin-left: 0; }
}
/* Four tabs and the header's buttons don't fit beside the brand here: the tabs get their own full-width row. */
@media (max-width: 760px) {
  .top { padding: 12px 16px 6px; gap: 6px 12px; flex-wrap: wrap; }
  .tabs { order: 1; width: 100%; justify-content: space-between; }
  .tabs a { padding: 12px 6px; font-size: var(--fs-2); letter-spacing: 0.04em; }
}
@media (max-width: 520px) {
  .search { gap: 6px; }
  .search select { padding: 12px 26px 12px 10px; font-size: var(--fs-4); background-position: right 9px center; }
  .search button { padding: 10px 14px; }
  .adjust input[type="checkbox"] { width: 20px; height: 20px; }
  .adjust label.check { min-height: 40px; }
  .links { gap: 4px; margin-top: 6px; }
  .links a { padding: 12px 8px; }
  main { padding: 16px 16px 120px; }
  .rc-head { gap: 14px; }
  .crest { width: 52px; height: 58px; }
  .crest span { font-size: 24px; }
  .parts .muted { display: block; margin: 2px 0 0; }
  /* Three tiles a row instead of two keeps the Armory and the guide a third shorter. */
  .capes { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 6px; }
  .cape { padding: 8px 4px; }
  .cape .cn { font-size: var(--fs-2); }
  .cape .small { font-size: var(--fs-1); }
  .jump { margin: 0 -16px 12px; padding: 6px 12px; }
  .values .sec-head input { width: 100%; margin: 4px 0 0; padding: 10px; font-size: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .petals { display: none; }
  .art .bloom, .art .rays { animation: none; }
  .art .motes { display: none; }
  button::after { transition: none; }
  .sk::after { animation: none; }
}

.cape-how { margin: 12px 0 0; max-width: 46ch; color: var(--muted); line-height: 1.5; }

/* Phones: the answer first on a cape page (the flat texture repeats the turning model), tap targets of 40 px, and
   16 px inputs (iOS zooms into anything smaller). */
@media (max-width: 640px) { .cape-info { order: -1; } .cape-art .tex { display: none; } }
@media (max-width: 520px) {
  input, select, textarea { font-size: 16px; }
  .jump a, .seg a { padding: 11px 12px; }
  .jump span { display: none; }
  .own > button.link { min-height: 40px; }
  .cert a, .crumbs a { display: inline-block; padding: 10px 0; margin: -7px 0; }
  footer .legal a { display: inline-block; padding: 12px 4px; margin: -12px 0; }
}

/* The ranked capes page: one row a cape, fewest owners first. */
.cape-rank { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.cape-rank li { display: grid; grid-template-columns: 2.4em 20px minmax(0, 1fr) auto; gap: 4px 12px; align-items: center; padding: 8px 6px; border-radius: 10px; }
.cape-rank li:hover { background: rgba(150, 170, 225, 0.06); }
.cape-rank .n { color: var(--muted); font-variant-numeric: tabular-nums; text-align: right; }
.cape-rank .tex { width: 20px; height: 32px; background-size: 640% 200%; background-position: 1.852% 6.25%; background-repeat: no-repeat; background-color: rgba(150, 170, 225, 0.07); image-rendering: pixelated; border-radius: 2px; }
.cape-rank a { font-weight: 600; min-width: 0; }
.cape-rank .sub { display: block; font-size: var(--fs-2); font-weight: 400; color: var(--muted); }
.cape-rank .v { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.badge-rank li { grid-template-columns: 2.4em 22px minmax(0, 1fr) auto; }
.badge-rank .t { font-weight: 600; min-width: 0; }
.badge-page { display: flex; gap: 20px; align-items: flex-start; max-width: 820px; margin: 0 auto; }
.badge-page .badge-big { width: 64px; height: 64px; flex: none; image-rendering: auto; }
.badge-page h1 { font-size: var(--fs-6); margin: 4px 0 8px; }
.badge-page p { max-width: 60ch; }
.name-page { max-width: 720px; margin: 0 auto; }
.name-page h1 { font-size: var(--fs-6); margin: 4px 0 8px; }
.name-page p { max-width: 60ch; }
.name-page .vt { margin-top: 12px; }
@media (max-width: 520px) { .cape-rank li { grid-template-columns: 2em 20px minmax(0, 1fr); } .cape-rank .v { grid-column: 3; text-align: left; } }
