/* The site's own fonts (tools/subset_fonts.py; SIL Open Font License, fonts/OFL-*.txt), split by
   script: a browser downloads only the pieces a page's text needs. */
/* fonts: begin (written by tools/subset_fonts.py) */
@font-face{font-family:"Inter";src:url(../fonts/inter-latin.woff2) format("woff2");font-weight:400 800;font-display:swap;unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-2199, U+2212, U+2215, U+2605, U+2713, U+FEFF, U+FFFD}
@font-face{font-family:"Inter";src:url(../fonts/inter-latin-ext.woff2) format("woff2");font-weight:400 800;font-display:swap;unicode-range:U+0100-024F, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:"Inter";src:url(../fonts/inter-vietnamese.woff2) format("woff2");font-weight:400 800;font-display:swap;unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB}
@font-face{font-family:"Inter";src:url(../fonts/inter-cyrillic.woff2) format("woff2");font-weight:400 800;font-display:swap;unicode-range:U+0400-052F, U+1C80-1C8A, U+20B4, U+2116, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F}
@font-face{font-family:"Inter";src:url(../fonts/inter-greek.woff2) format("woff2");font-weight:400 800;font-display:swap;unicode-range:U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF, U+1F00-1FFF}
@font-face{font-family:"JetBrains Mono";src:url(../fonts/jetbrains-mono-latin.woff2) format("woff2");font-weight:500 700;font-display:swap;unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-2199, U+2212, U+2215, U+2605, U+2713, U+FEFF, U+FFFD}
@font-face{font-family:"JetBrains Mono";src:url(../fonts/jetbrains-mono-latin-ext.woff2) format("woff2");font-weight:500 700;font-display:swap;unicode-range:U+0100-024F, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:"JetBrains Mono";src:url(../fonts/jetbrains-mono-vietnamese.woff2) format("woff2");font-weight:500 700;font-display:swap;unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB}
@font-face{font-family:"JetBrains Mono";src:url(../fonts/jetbrains-mono-cyrillic.woff2) format("woff2");font-weight:500 700;font-display:swap;unicode-range:U+0400-052F, U+1C80-1C8A, U+20B4, U+2116, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F}
@font-face{font-family:"JetBrains Mono";src:url(../fonts/jetbrains-mono-greek.woff2) format("woff2");font-weight:500 700;font-display:swap;unicode-range:U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF, U+1F00-1FFF}
@font-face{font-family:"Lilita One";src:url(../fonts/lilita-one-latin.woff2) format("woff2");font-weight:400;font-display:swap;unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-2199, U+2212, U+2215, U+2605, U+2713, U+FEFF, U+FFFD}
@font-face{font-family:"Lilita One";src:url(../fonts/lilita-one-latin-ext.woff2) format("woff2");font-weight:400;font-display:swap;unicode-range:U+0100-024F, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
/* fonts: end */
:root{
  --bg:#0f0a26; --bg2:#160f36; --panel:#1d1446; --panel2:#251a58; --line:#3a2b80;
  --text:#f1ecff; --muted:#a99fd6; --faint:#9186c4;
  --violet:#7b4dff; --violet2:#9a74ff; --lav:#e7defe;
  --gold:#ffb627; --orange:#ff7a2f; --red:#ff4d6d; --green:#46d37e; --teal:#3cc7c0;
  --radius:14px; --shadow:0 10px 30px rgba(0,0,0,.35);
  --edge:#7563c4;  /* borders that mark a control: 3.5:1 on the panels (WCAG non-text contrast) */
  color-scheme:dark;
}
*{box-sizing:border-box}
html,body{margin:0}
body{background:radial-gradient(1200px 600px at 50% -200px,#2a1a6e 0%,transparent 70%),var(--bg);color:var(--text);
  font:15px/1.5 Inter,system-ui,sans-serif;min-height:100vh;overflow-x:hidden}
a{color:inherit;text-decoration:none}
a.link{color:var(--violet2);text-decoration:underline;text-underline-offset:2px}
button{font:inherit;color:inherit;cursor:pointer}
.wrap{max-width:1180px;margin:0 auto;padding:0 20px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip{position:absolute;left:12px;top:-80px;z-index:100;background:var(--gold);color:#2a1700;font-weight:800;padding:8px 14px;border-radius:10px}
.skip:focus{top:12px}
main:focus{outline:none}
/* nav */
.banner{background:repeating-linear-gradient(45deg,#2b1d70,#2b1d70 10px,#24185f 10px,#24185f 20px);color:var(--lav);text-align:center;font-size:12.5px;padding:6px 10px}
.nav{position:sticky;top:0;z-index:10;background:rgba(15,10,38,.86);backdrop-filter:blur(10px);border-bottom:1px solid #2a1f63}
.nav .wrap{display:flex;align-items:center;gap:18px;height:64px}
/* The brand: the logo's "P" as an icon and the name in the site's heading font, legible at the bar's
   size, where the whole logo, two lines and its floating blocks, was too small to read. Below 1041px
   the name gives the links its room (it stays for screen readers: it names the link). */
.nav .brand{position:relative;flex:none}
.nav .brand .mark{display:flex;align-items:center;gap:10px}
.nav .brand img{display:block}
.nav .brand .mark img{width:36px;height:36px}
.nav .brand .name{font:400 22px/1 "Lilita One",sans-serif;letter-spacing:.4px;white-space:nowrap;text-shadow:0 2px 0 var(--line)}
.nav .brand .name span{color:var(--gold)}
.nav .brand .badge{display:none}
@media (max-width:1040px){.nav .brand .name{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}}
/* the focus ring round what shows: the link's own box is the icon and name, transparent while the logo hangs */
.nav .brand:focus-visible{outline:none}
.nav .brand:focus-visible .mark,.nav .brand:focus-visible .badge{outline:2px solid var(--violet2);outline-offset:2px;border-radius:8px}
/* Where the name shows, the top of a page (not home's) has the whole logo hanging from the bar instead:
   over the first 64px of scrolling (all of it, on a page that scrolls less) it tucks away by 5/8 of the
   way and the icon and name come in over the second half (barely overlapping, where the two would show
   through each other). One range for both: a page that stops being scrollable (a search with no results)
   leaves Chrome keeping or dropping the two together, never the logo gone and the name not in. Only where
   the browser drives animations by scrolling, ranges and all (without them the swap would spread over the
   whole page): elsewhere the icon and name stay. The logo is the starting point, so a page too short to
   scroll from the start (whose timeline never starts) keeps it. */
@media (min-width:1041px){@supports (animation-timeline:scroll()) and (animation-range:0 min(64px,100%)){
  .nav .brand .badge{display:block;position:absolute;left:0;top:-8px;transform-origin:0 0;
    animation:pgg-tuck linear both;animation-timeline:scroll(root);animation-range:0 min(64px,100%)}
  .nav .brand:has(.badge) .mark{opacity:0;animation:pgg-show linear both;animation-timeline:scroll(root);animation-range:0 min(64px,100%)}
}}
@media (min-width:1041px) and (prefers-reduced-motion:no-preference){.nav .brand .badge{animation-name:pgg-tuck-up}}
@keyframes pgg-tuck{62.5%,to{opacity:0;visibility:hidden}}  /* (hidden: it no longer takes clicks over the page) */
@keyframes pgg-tuck-up{62.5%,to{opacity:0;visibility:hidden;translate:0 -8px;scale:.85}}
@keyframes pgg-show{0%,50%{opacity:0}to{opacity:1}}
/* Scrolls sideways rather than cutting a link off, should the links ever not fit (#35). */
.nav nav{display:flex;gap:4px;margin:-4px 0 -4px 4px;padding:4px;min-width:0;overflow-x:auto;scrollbar-width:none}
/* (the padding is room for focus rings, which the scrolling box would otherwise cut off) */
.nav nav::-webkit-scrollbar{display:none}
.nav nav .short{display:none}
.nav nav a{padding:8px 12px;border-radius:10px;color:var(--muted);font-weight:600;white-space:nowrap}
.nav nav a.on,.nav nav a:hover{color:var(--text);background:var(--panel)}
.nav .spacer{flex:1}
.hero-ip code{font-family:"JetBrains Mono",monospace;font-weight:700;color:var(--gold)}
.ip{display:flex;align-items:center;gap:8px;background:var(--panel);border:1px solid var(--line);border-radius:999px;padding:6px 6px 6px 14px;font-weight:600;white-space:nowrap}
[hidden]{display:none!important}  /* .btn's display would otherwise beat the browser's [hidden] */
/* Copy buttons and the difficulty toggles only work with JavaScript, which marks the page (html.js):
   without it they are invisible (not removed, so nothing moves when they appear). */
html:not(.js) [data-copy],html:not(.js) .filters .diffs,html:not(.js) #random,html:not(.js) #isme,html:not(.js) #pbsort{visibility:hidden}
.btn{border:0;border-radius:999px;padding:7px 14px;background:var(--violet);font-weight:700;box-shadow:0 3px 0 #4b2bb3;display:inline-block;color:#fff}
.btn:hover{background:#6a3df0}  /* darker, not lighter: white text stays above 4.5:1 */
.btn.gold{background:var(--gold);color:#2a1700;box-shadow:0 3px 0 #b97700}
.btn.ghost{background:transparent;border:1px solid var(--line);box-shadow:none;color:var(--text)}
/* hero: room above the logo for the runner's highest jumps, hat and all (static/js/logo.js, TOP) */
.hero{text-align:center;padding:66px 0 18px}
.hero .stage{position:relative;width:min(620px,92%);margin:0 auto}
.hero .logo{display:block;position:relative;filter:drop-shadow(0 18px 40px rgba(123,77,255,.35))}
.hero .logo img{display:block;width:100%;height:auto}
/* the logo's runner and blocks, over it; the runner stands above its top edge on the high blocks */
.hero .run{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
/* The run (static/js/logo.js) goes on, so a button stops it (WCAG 2.2.2), in the logo's empty bottom
   right corner: stopped, the logo is as it's drawn. Without JavaScript or with reduced motion there's
   no button: the run doesn't play there. */
.hero .still{display:none;position:absolute;right:0;bottom:4%;width:32px;height:32px;padding:8px;border:1px solid var(--line);border-radius:50%;background:rgba(15,10,38,.6);color:var(--lav);cursor:pointer}
.hero .still svg{display:block;width:100%;height:100%;fill:currentColor}
.hero .still:hover{color:#fff;border-color:var(--violet2)}
.hero .still .i-go,.hero .still.stopped .i-stop{display:none}
.hero .still.stopped .i-go{display:inline}
@media (prefers-reduced-motion:no-preference){.js .hero .still{display:block}}
.hero p{color:var(--muted);font-size:18px;margin:6px auto 22px;max-width:620px}
.hero p code{white-space:nowrap} /* (/fp start whole, #413) */
.hero .cta{display:flex;flex-direction:column;align-items:center;gap:16px}
.hero .hero-ip{font-size:20px;padding:8px 8px 8px 22px;gap:14px;max-width:100%}
.hero .hero-ip code{font-size:20px;min-width:0;overflow:hidden;text-overflow:ellipsis}  /* (a long address at 320 px) */
.hero .hero-ip .btn{padding:10px 22px;font-size:17px}
/* the next steps, as links under the address: each a finger's height (WCAG 2.5.8) */
.hero .next{display:flex;flex-wrap:wrap;justify-content:center;gap:2px 22px}
.hero .next a{color:var(--violet2);font-weight:600;padding:6px 2px}
.hero .next a:hover{color:var(--lav);text-decoration:underline;text-underline-offset:3px}
.hero .next a::after{content:" →";content:" →"/""}  /* (the first for browsers without alt text) */
.hero .next a[target]::after{content:" ↗";content:" ↗"/""}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:34px 0 8px}
.stat{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:16px 18px;min-width:0}
.stat b{display:block;font-family:"Lilita One",sans-serif;font-weight:400;font-size:30px;letter-spacing:.5px}
.stat span{color:var(--muted);font-size:13px}
/* (#433) The band of phantoms, right above the Map of the Day: the loop over the open space and the line,
   its edges faded into the page (wider than the page's column, up to 1600 px, so it has no sides), a little
   darker at its foot, where the line sits. A grid, so the loop's box is that of its rows (an absolutely
   placed child of a grid sits in its grid area), reaching 24 px past them above and below, faded out there.
   The poster shows until the video plays, which then fades in over it (static/js/phantoms.js). */
.phantoms{position:relative;isolation:isolate;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:clamp(170px,24vw,280px) auto;margin:34px 0 24px}  /* (24 below: the loop's faded foot clears whatever follows) */
/* (100vw counts a classic scrollbar too, so the loop can pass the window's edge by its width: the body's
   overflow-x:hidden clips it, faded out there anyway) */
.phantoms .reel{position:absolute;grid-row:1/3;grid-column:1;top:-24px;bottom:-24px;left:50%;width:min(100vw,1600px);transform:translateX(-50%);z-index:-1;overflow:hidden;pointer-events:none;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 14%,#000 86%,transparent),linear-gradient(180deg,transparent,#000 22%,#000 70%,transparent);
  -webkit-mask-composite:source-in;
  mask-image:linear-gradient(90deg,transparent,#000 14%,#000 86%,transparent),linear-gradient(180deg,transparent,#000 22%,#000 70%,transparent);
  mask-composite:intersect}
.phantoms .reel img,.phantoms .reel video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.phantoms .reel video{opacity:0;transition:opacity .8s}
.phantoms.playing .reel video{opacity:1}
/* (the footage tinted towards the page's violet, and darker at its foot: an overlay rather than a filter
   on the video) */
.phantoms .reel::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(42,26,110,.42),rgba(30,18,84,.34) 55%,rgba(15,10,38,.8))}
/* (the line on a dark pill of its own: over the brightest frame its text keeps 4.5:1) */
.phantoms .onmap{grid-row:2;grid-column:1;align-self:end;justify-self:start;max-width:calc(100% - 44px);margin:0 0 8px;padding:2px 10px;border-radius:999px;background:rgba(15,10,38,.78);font-size:13px;color:var(--lav);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.phantoms .onmap a{color:#fff;font-weight:600}
.phantoms .onmap a:focus-visible{outline-offset:-2px}  /* (inside the pill, which clips what passes its edge) */
/* (hidden, not taken out: its row keeps its height whether it shows or not, so nothing moves) */
.phantoms .reel-stop{visibility:hidden;grid-row:2;grid-column:1;justify-self:end;align-self:end;margin-bottom:6px;width:32px;height:32px;padding:8px;border:1px solid var(--edge);border-radius:50%;background:rgba(15,10,38,.6);color:var(--lav);cursor:pointer}
.phantoms .reel-stop svg{display:block;width:100%;height:100%;fill:currentColor}
.phantoms .reel-stop:hover{color:#fff;border-color:var(--violet2)}
.phantoms .reel-stop .i-go,.phantoms.stopped .reel-stop .i-stop{display:none}
.phantoms.stopped .reel-stop .i-go{display:inline}
@media (prefers-reduced-motion:no-preference){.js .phantoms .reel-stop{visibility:visible}}
.phantoms.broken .reel-stop{visibility:hidden}
h1,h2,h3{overflow-wrap:anywhere}
h2,h1.page{font-family:"Lilita One",sans-serif;font-weight:400;font-size:28px;letter-spacing:.4px;margin:42px 0 14px;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
h1.page{font-size:32px;margin-top:30px}
h2 small,h1.page small{font:500 13px Inter,sans-serif;color:var(--faint)}
.hero h1{margin:0;font-size:inherit}
.prestige{font-weight:800}
h2 .more{margin-left:auto;font:600 14px Inter,sans-serif;color:var(--violet2)}
.sechead{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 12px;margin:42px 0 14px}
.sechead h2{margin:0}
.sechead p{margin:0;font:500 13px Inter,sans-serif;color:var(--faint)}
.sechead .more{margin-left:auto;font:600 14px Inter,sans-serif;color:var(--violet2)}
/* Trending, top rated, newest and most played (templates/home.html): the names in a row over one list
   at a time, where the browser has :has(); elsewhere every list under its own heading. */
.listpick{display:none}
@supports selector(:has(*)){
  .listpick{display:flex;flex-wrap:wrap;gap:4px 26px;margin:42px 0 0;padding:2px 2px 0}
  .listpick label{font:400 28px/1.3 "Lilita One",sans-serif;letter-spacing:.4px;color:var(--faint);cursor:pointer;white-space:nowrap;
    padding-bottom:6px;border-bottom:3px solid transparent}
  .listpick label:hover{color:var(--lav)}
  .listpick input:checked+label{color:var(--text);border-bottom-color:var(--gold)}
  .listpick input:focus-visible+label{outline:2px solid var(--violet2);outline-offset:2px;border-radius:4px}
  .lists .list{display:none}
  .lists .list .sechead{margin-top:10px}
  .lists .list .sechead h2{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .lists:has(#ml-trending:checked) #list-trending,.lists:has(#ml-top:checked) #list-top,
  .lists:has(#ml-newest:checked) #list-newest,.lists:has(#ml-played:checked) #list-played{display:block}
}
h3.sub{font-family:"Lilita One",sans-serif;font-weight:400;font-size:20px;margin:22px 0 12px}
.h1note{font-size:.72em;color:var(--lav)}
/* map of the day */
.motd{display:grid;grid-template-columns:1.1fr 1fr;background:linear-gradient(135deg,#2a1b6b,#1b1248);border:1px solid #4a36a8;border-radius:20px;overflow:hidden;box-shadow:var(--shadow)}
.motd>*{min-width:0}
.motd .art{position:relative;min-height:300px;background:radial-gradient(circle at 50% 60%,#3b28a0,#140d38);display:grid;place-items:center}
.motd .art svg{width:190px;height:190px}
.ribbon{position:absolute;top:16px;left:16px;background:var(--gold);color:#2a1700;font:800 12px Inter,sans-serif;letter-spacing:1px;padding:6px 10px;border-radius:8px;text-transform:uppercase}
.motd .body{padding:26px 28px}
.motd h3{font-family:"Lilita One",sans-serif;font-weight:400;font-size:34px;margin:0 0 4px;line-height:1.1}
.by{color:var(--muted)} .by b{color:var(--lav)} .by a:hover b{text-decoration:underline}
.meta{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0}
.chip{display:inline-flex;align-items:center;gap:6px;background:var(--panel2);border:1px solid var(--line);border-radius:999px;padding:4px 10px;font-size:13px;color:var(--lav);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
a.chip:hover{border-color:var(--violet)}
.diff{font-weight:700;border:0}
/* players' vote, not the builder's pick (or shown harder by its finish rate): the same chip, "voted" (or
   "by finish rate") said more quietly */
.diff{display:inline-block}  /* (one run of text: no flex gap before "voted") */
.diff small{font-size:inherit;font-weight:500}  /* (by weight, not opacity: the chip's colours hold 4.5:1, #269) */
.d-BEGINNER{background:#0f4458;color:#7fdcf8}
.d-EASY{background:#174a2c;color:#86f0b0}
.d-NORMAL{background:#4d3a0b;color:#f2cf73}
.d-HARD{background:#5a1b19;color:#ff9a95}
.d-HARDCORE{background:#3a2366;color:#c7a8ff}
.rating{display:inline-flex;align-items:center;gap:6px;font-weight:700}
.rating .bar{width:70px;height:8px;border-radius:9px;background:#2d2366;overflow:hidden}
.rating .bar i{display:block;height:100%;background:linear-gradient(90deg,var(--orange),var(--gold))}
.card .rating .bar{width:52px}
.rating small{color:var(--faint);font-weight:500}
.rating.none{color:var(--faint);font-weight:500}
.cmd{display:flex;align-items:center;gap:8px;background:#120c2f;border:1px dashed #4a36a8;border-radius:12px;padding:8px 8px 8px 12px;margin-top:14px;min-width:0}
.cmd code{flex:1;min-width:0;font-family:"JetBrains Mono",monospace;font-size:13px;color:var(--gold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.podium{margin-top:16px;display:grid;gap:6px}
.podium div{display:flex;align-items:center;gap:10px;font-size:14px;min-width:0}
.podium .who{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.medal{width:24px;height:24px;border-radius:50%;display:inline-grid;place-items:center;font:800 12px Inter,sans-serif;color:#1b1030;flex:none}
.m1{background:linear-gradient(#ffe08a,#ffb627)}.m2{background:linear-gradient(#f2f2ff,#b9b6d6)}.m3{background:linear-gradient(#f3b98d,#c9773e)}.mx{background:#2d2366;color:var(--muted)}
.medal.wide{width:auto;min-width:24px;padding:0 7px;border-radius:12px}
.time{font-family:"JetBrains Mono",monospace;font-weight:700;margin-left:auto;white-space:nowrap}
/* cards */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:16px}
.card{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;transition:transform .28s cubic-bezier(.34,1.7,.6,1),border-color .12s;display:flex;flex-direction:column;min-width:0}
.card:hover,.card:focus-within{transform:translateY(-3px);border-color:var(--violet)}
/* The map's name is the card's link and covers the card; the builder's name is a link above it. */
.card .name::after{content:"";position:absolute;inset:0;z-index:1}
.card .name:focus-visible{outline:none}
.card:has(.name:focus-visible){outline:2px solid var(--violet2);outline-offset:2px}
.card .by a{position:relative;z-index:2}
/* The difficulty chip is a link of its own to the difficulty's page (#260), above the card's link as the
   builder's name is; a voted one's explanation, or a finish rate's, shows on hover. */
.card .thumb .d a{position:relative;z-index:2}
.card .thumb .d .voted,.card .thumb .d .rate{cursor:help}
.more-built{margin-top:12px}
.more-built summary{list-style:none;cursor:pointer;margin:0 auto 12px;display:table}
.more-built summary::-webkit-details-marker{display:none}
.more-built[open] summary{display:none}
/* Featured maps (its builder paid for it, or staff featured it): listed first and coloured, as in the game. */
.card.featured{border-color:var(--gold)}
.ft{display:inline-flex;align-items:center;background:var(--gold);color:#2a1700;font:800 12px Inter,sans-serif;padding:4px 9px;border-radius:999px;white-space:nowrap}
.card .thumb .ft{position:absolute;left:10px;bottom:8px;padding:3px 8px;font-size:11px}
.grid.stale{opacity:.45;transition:opacity .2s}  /* cards that don't match the filter yet (#37) */
.card .thumb{height:120px;display:grid;place-items:center;position:relative;background:radial-gradient(circle at 50% 70%,#33248a,#1a1245)}
.card .thumb .d{position:absolute;top:10px;left:10px}
.card .thumb img.pic{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:6px 8px}
/* (scale-down: at most the size its srcset's `sizes` says, 480 px wide on a wide screen: the picture's
   own pixels, not a 1x screen fetching the 960 to show it at 512; parkourgg/pieces.py SLOT_SIZES, #267) */
.viewer img.pic{width:100%;height:100%;object-fit:scale-down;padding:28px 20px 70px;position:absolute;inset:0}
.motd .art img.pic{width:100%;height:100%;object-fit:scale-down;padding:44px 20px 20px;position:absolute;inset:0}
.mini img.pic{width:64px;height:40px;object-fit:contain;flex:none}
.viewer iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.viewer .view3d{position:absolute;left:50%;bottom:44px;transform:translateX(-50%);font-size:16px;padding:10px 20px;white-space:nowrap}
.viewer .view3d small{font-weight:500;margin-left:6px}  /* (no opacity: white on violet is 4.8:1, #269) */
/* A video (#263, templates/_video.html): 16:9 before and after the press, the poster filling it */
.video{margin:0;max-width:880px}
.video .frame{position:relative;aspect-ratio:16/9;border-radius:18px;overflow:hidden;border:1px solid #4a36a8;background:radial-gradient(circle at 50% 65%,#3a2a9a,#120c32)}
.video .poster{position:absolute;inset:0;display:grid;place-items:center}
.video .poster img,.video video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.video iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.video .play{position:relative;width:68px;height:48px;filter:drop-shadow(0 2px 6px rgba(0,0,0,.5))}
.video .play svg{width:100%;height:100%;display:block;fill:#e6223a}
.video .play .tri{fill:#fff}
/* (each on its own: a browser without :focus-visible, Safari before 15.4, drops a list it's in, :hover too) */
.video .poster:hover .play svg{fill:#ff3550}
.video .poster:focus-visible .play svg{fill:#ff3550}
.video .poster:focus-visible{outline:3px solid var(--violet2);outline-offset:-3px;border-radius:18px}
.video figcaption{margin-top:10px;font-size:14px;color:var(--muted)}
.video figcaption b{color:var(--text);margin-right:4px}

.card .info{padding:12px 14px 14px;display:flex;flex-direction:column;gap:6px;flex:1;min-width:0}
.card .name{font-weight:700;line-height:1.25;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow-wrap:anywhere}
.card .by{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card .row{display:flex;justify-content:space-between;align-items:center;gap:8px;color:var(--muted);font-size:13px;margin-top:auto}
.card .row{flex-wrap:wrap;row-gap:2px}  /* a narrow card puts the count under the rating */
.card .row>span:last-child{white-space:nowrap}
.strip{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
/* (#410) a kind's picks: 4 in a row, 2 when narrower, and 2 of each on a phone, so its list isn't pushed far down */
.picks .strip{grid-template-columns:repeat(2,minmax(0,1fr))}
@media (min-width:1000px){.picks .strip{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width:600px){.picks .strip{grid-template-columns:minmax(0,1fr)}.picks .strip .mini:nth-child(n+3){display:none}}
.mini{display:flex;align-items:center;gap:12px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:10px 12px;min-width:0}
.mini:hover{border-color:var(--violet)}
.mini .t{min-width:0}
.mini .t b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mini .t span{color:var(--faint);font-size:12.5px}
/* map page */
.crumbs{color:var(--faint);margin:26px 0 8px;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.crumbs a{color:var(--violet2)}
.maphead h1{font-family:"Lilita One",sans-serif;font-weight:400;font-size:44px;line-height:1.05;margin:0}
.desc{color:var(--lav);margin:0 0 4px;max-width:760px;overflow-wrap:anywhere}
.mapgrid{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);gap:20px;margin-top:20px}.mapgrid>*{min-width:0}
.side{display:grid;gap:16px;align-content:start}
.viewer{position:relative;border-radius:18px;overflow:hidden;border:1px solid #4a36a8;background:radial-gradient(circle at 50% 65%,#3a2a9a,#120c32);min-height:420px;display:grid;place-items:center}
.viewer svg{width:220px;height:220px}
.viewer .tag{position:absolute;left:14px;top:14px;display:flex;gap:8px;z-index:1}
.viewer .hint{position:absolute;bottom:12px;left:12px;right:12px;text-align:center;color:var(--muted);font-size:13px}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:18px;min-width:0}
.panel h2{margin:0 0 10px;font-family:"Lilita One",sans-serif;font-weight:400;font-size:22px;display:block;letter-spacing:0}
.kv{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.kv div{background:var(--panel2);border-radius:10px;padding:10px 12px;min-width:0}
.kv b{display:block;font-size:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kv span{color:var(--muted);font-size:12px}
.facts{display:grid;gap:8px;margin:0;font-size:14px}
.facts>div{display:flex;justify-content:space-between;gap:12px;border-bottom:1px solid #2a2064;padding-bottom:8px}
.facts>div:last-child{border:0;padding:0}
.facts>div.stack{display:block}
.facts dt{color:var(--muted)} .facts dd{margin:0;text-align:right;min-width:0;overflow-wrap:anywhere}
.facts dd .pl{justify-content:flex-end}.facts .when{display:block;color:var(--faint);font-size:13px}
.votes{display:grid;gap:6px;margin-top:4px}
.votes>div{display:grid;grid-template-columns:84px 1fr 44px;align-items:center;gap:8px;font-size:13px;background:none}
.facts dd .votes{margin-top:8px}
.votes .bar{height:8px;border-radius:9px;background:#2d2366;overflow:hidden}
.votes .bar i{display:block;height:100%;background:currentColor}
.votes span:last-child{text-align:right;color:var(--muted)}
/* tables */
table{width:100%;border-collapse:collapse;table-layout:auto}
td,th{padding:9px 10px;text-align:left;border-bottom:1px solid #2a2064;font-size:14px}
th{color:var(--faint);font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.6px;white-space:nowrap}
td.num,th.num{text-align:right;white-space:nowrap}
th abbr{text-decoration:none}
tr:hover td{background:#211858}
td.who{max-width:0;width:100%}
.pl{display:flex;align-items:center;gap:8px;min-width:0}
.pl span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.pl svg{flex:none}
a.pl:hover span{text-decoration:underline}
.head{width:24px;height:24px;border-radius:5px;flex:none;image-rendering:pixelated;background:#2d2366;display:inline-grid;place-items:center;font:800 12px Inter,sans-serif;color:var(--muted);overflow:hidden}
.head.big{width:72px;height:72px;border-radius:12px;font-size:30px}
.tablewrap{overflow-x:auto}
/* browse */
.filters{display:flex;flex-wrap:wrap;gap:10px;align-items:center;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:12px;margin-bottom:16px}
.filters input,.filters select,.search input{background:#120c2f;border:1px solid var(--edge);border-radius:10px;padding:9px 12px;color:var(--text);font:inherit;min-width:0}
.filters input{flex:1 1 220px}
.filters .diffs{display:flex;flex-wrap:wrap;gap:6px}
.filters .glabel{align-self:center;font-size:13px;color:var(--muted);margin-right:2px}
/* what a group's label means, in words beside its toggles (#368: a title would reach only a mouse) */
.filters .gnote{align-self:center;font-size:13px;color:var(--muted)}
.tog small{font-size:11.5px;opacity:.8;margin-left:2px}
.tog{border:1px solid var(--edge);background:transparent;border-radius:999px;padding:6px 12px;font-size:13px;color:var(--muted)}
.tog.on,a.tog.on{background:var(--violet);border-color:var(--violet);color:#fff}
a.tog{display:inline-block}
.tabs{display:flex;gap:6px;margin-bottom:14px;flex-wrap:wrap}
.count{color:var(--faint);font-size:13px;margin:-6px 0 12px}
/* (#410) under picks over the list: clear of their last cards, which the pull-up would put it under */
.picks ~ .count{margin-top:12px}
.more-wrap{text-align:center;margin:22px 0 0}
/* the map leaderboard's All time / This month / This week / Today (#196) */
.lbtabs{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
#lbperiod .note:empty{display:none}
.note{color:var(--faint);font-size:13px;margin-top:10px}
.search{display:flex;gap:8px;margin:0 0 16px;max-width:460px}
.search input{flex:1}
.pager{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;margin:24px 0 0}
.pager a,.pager span{min-width:38px;padding:7px 11px;border-radius:10px;border:1px solid var(--edge);text-align:center;font-weight:600;color:var(--lav)}
.pager a:hover{border-color:var(--violet2);background:var(--panel)}
.pager .on{background:var(--violet);border-color:var(--violet);color:#fff}
.pager .gap{border-color:transparent;color:var(--faint);min-width:0;padding:7px 2px}
/* join (#194) */
.lead{color:var(--lav);max-width:760px;margin:0 0 20px}
.join{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:20px}
.join .for{color:var(--faint);font-size:13px;margin:-6px 0 4px}
.cmd .lbl{flex:none;min-width:62px;color:var(--muted);font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}
.join .cmd+.cmd{margin-top:8px}
.join .cmd code{white-space:normal;overflow-wrap:anywhere}  /* the whole address, even at 320px */
.steps{margin:16px 0 0;padding-left:22px;display:grid;gap:8px}
.steps li::marker{color:var(--gold);font-weight:700}
.steps code,.guide code{font-family:"JetBrains Mono",monospace;font-size:13px;color:var(--gold)}
.join-next{margin-top:20px}.join-next .steps{margin-top:0}
.faq h3{font-size:15px;margin:14px 0 2px}.faq h3:first-of-type{margin-top:0}.faq p{margin:0;color:var(--lav)}
/* The kinds of map people search for by name (#223): links to their pages, and a kind's own page */
.types{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 16px}
.types .chip small{color:var(--faint);font-size:12px}
.topic .lead{margin-bottom:12px}
.play-these .btn{margin-left:4px;vertical-align:middle}
.topic-records,.topic-faq,.more-types{margin-top:24px}
.more-types h2{margin:0 0 12px}
.topic-records td.mapc{max-width:0;width:55%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.topic-records td.who{width:45%}
.toc{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 20px}
.toc a{border:1px solid var(--edge);border-radius:999px;padding:6px 12px;font-size:13px;color:var(--lav)}
.toc a:hover{border-color:var(--violet2);background:var(--panel)}
/* a jump link's heading clears the sticky nav */
.guide{margin-top:20px}.guide>h2{scroll-margin-top:100px}.guide p{margin:0 0 10px;max-width:820px}.guide p:last-child{margin-bottom:0}
.guide .steps{margin:0 0 10px}.guide .steps:last-child{margin-bottom:0}
/* the server's artwork beside a page's heading (#217), and the minigames (#215) */
.intro{display:flex;align-items:flex-end;justify-content:space-between;gap:20px}
.intro .lead{margin-bottom:12px}
.art-pic{display:block;flex:none;width:auto;height:180px}
.intro .art-pic{margin:20px 0 4px}
.game-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:0 0 10px}
.game-head h2{margin:0;scroll-margin-top:100px}
.game-head .chip{white-space:normal}  /* (a long one wraps at 320px rather than being cut off) */
.chip.soon{background:none;border-color:var(--gold);color:var(--gold);font-weight:600}
.game .cmd{max-width:520px}
.game .cmd code{white-space:normal;overflow-wrap:anywhere}  /* the whole command, even at 320px */
.with-art{display:flex;align-items:flex-end;justify-content:space-between;gap:20px}
.with-art .art-pic{height:150px}
.play-together{display:flex;align-items:center;gap:20px;margin-top:20px}
.play-together .art-pic{height:132px;margin:-8px 0 -18px}
.play-together h2{margin:0 0 6px}
.play-together p{margin:0 0 12px;color:var(--lav)}
.play-together .meta{display:flex;flex-wrap:wrap;gap:6px}
.play-together .chip:hover{border-color:var(--violet2);color:var(--text)}
/* The server, live (#288): the players online (home, /join/ and /bedrock/ only), and the day's Elimination events */
.online{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px;color:var(--muted);font-size:15px;margin:0 0 14px}
.online b{color:var(--text)}
.online .dot{flex:none;width:9px;height:9px;border-radius:50%;background:#3ddc84;box-shadow:0 0 0 3px rgba(61,220,132,.2)}
.hero p.online{justify-content:center;font-size:15px;margin:16px auto 0}
.events b{color:var(--text)}
.play-together p.events{color:var(--muted)}
/* Sharing (#274) and the one-tap Bedrock link (#287) */
.actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.add-row{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.by .share-own{margin-left:10px;padding:3px 12px;font-size:13px;vertical-align:middle}
td.time button.share-race{display:block;margin:2px 0 0 auto;padding:0;border:0;background:none;cursor:pointer;font:600 12px Inter,system-ui,sans-serif;color:var(--violet2);text-decoration:underline;text-underline-offset:2px}
td.time button.share-race:hover{color:var(--lav)}
#lb tr.raced td{background:rgba(123,77,255,.14)}
.view3d.raced{outline:2px solid var(--gold);outline-offset:2px}
@media (max-width:620px){
  .intro .art-pic,.with-art .art-pic{display:none}
  .play-together .art-pic{height:96px;margin:0}
}
@media (max-width:420px){.play-together .art-pic{display:none}}
/* "What you can do" (#290): six tiles, each picture in a box of fixed height, so nothing moves as they load */
.tiles{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:12px}  /* 6, 3 + 3 or 2 x 3: never 4 + 2 */
.tile{display:flex;flex-direction:column;gap:4px;height:100%;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:12px 14px 14px}
.tile:hover{border-color:var(--violet2)}
.tile:focus-visible{border-color:var(--violet2)}
.tile .pic{display:flex;align-items:flex-end;justify-content:center;height:96px;margin-bottom:6px;overflow:hidden}
.tile .pic img{height:96px;width:auto;max-width:100%;object-fit:contain}
.tile .pic svg{height:56px;width:auto;max-width:100%;margin-bottom:12px}
.tile b{font:400 21px "Lilita One",sans-serif;letter-spacing:.3px;color:var(--text)}
.tile .line{color:var(--lav);font-size:14px}
@media (max-width:1060px){.tiles{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:560px){.tiles{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:420px){.tiles{gap:8px}.tile{padding:10px}.tile .pic,.tile .pic img{height:72px}.tile .pic svg{height:44px;margin-bottom:8px}}
/* The cosmetics page (#290): a name, what it is and how to get it, by an icon of its kind */
.cosm-grid{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:8px}
.cosm{display:flex;gap:10px;align-items:flex-start;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:10px 12px;min-width:0}
.cosm>div{display:flex;flex-direction:column;min-width:0}
.cosm b{color:var(--text);overflow-wrap:anywhere}
.cosm .desc{color:var(--lav);font-size:13px;overflow-wrap:anywhere}
.cosm .how{color:var(--muted);font-size:13px;font-weight:600}
.cosm .how.sold{color:var(--gold)}
.cicon{flex:none;width:28px;height:28px;margin-top:2px;fill:currentColor}
/* its picture (or, without one, its icon) on a lit backdrop, so dark cosmetics show on the dark card */
.cosm .pic{flex:none;display:grid;place-items:center;width:96px;height:96px;border-radius:10px;background:radial-gradient(circle at 50% 42%,#4b3c9e 0,#2c2068 62%,var(--panel2) 100%)}
.cosm .pic img{display:block;width:96px;height:96px}
.cosm .pic .cicon{width:40px;height:40px;margin:0}
.cicon.hat{color:#c9b8ff}.cicon.plushie{color:#ffb08a}.cicon.backpack{color:#6fd6a0}.cicon.balloon{color:#ff8fa8}
.abilities{list-style:none;margin:0 0 10px;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:6px 18px}
.abilities b{color:var(--gold)}
.ranks{list-style:none;display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 14px;padding:0}
.ranks li{background:var(--panel2);border-radius:999px;padding:4px 11px;font-size:13px;font-weight:600}
/* player */
.phead{display:flex;align-items:center;gap:18px;margin:30px 0 6px;flex-wrap:wrap}
.phead h1{font-family:"Lilita One",sans-serif;font-weight:400;font-size:40px;margin:0;line-height:1.1;overflow-wrap:anywhere}
.phead .tags{display:flex;gap:8px;flex-wrap:wrap;margin-top:6px}
.pstats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:20px 0 4px}
.choose{display:grid;gap:8px;max-width:460px}
/* The browser-drawn player page fills in after two downloads: its space is kept from the start, so
   the footer never jumps (#32: a 0.73 layout shift on phones). */
#player.drawn{min-height:100vh}
.empty{color:var(--muted);padding:30px 0}
footer.wrap{margin:60px auto 30px;color:var(--faint);font-size:13px;text-align:center}
/* the config's community links (#195): a row that wraps on phones, each link about 24px tall (WCAG
   2.5.8's minimum target size) */
footer .community{display:flex;flex-wrap:wrap;justify-content:center;gap:0 14px;margin-bottom:8px}
footer .community a{color:var(--muted);font-weight:600;padding:4px 2px;text-decoration:underline;text-underline-offset:2px}
footer .community a:hover{color:var(--text)}
footer a.link{display:inline-block;padding:4px 2px;margin-top:2px}  /* (a finger's height too) */
/* the privacy page (#193): text at a reading width; a long address wraps rather than scroll sideways */
.prose{max-width:760px;overflow-wrap:anywhere}
.prose h2{font-size:22px;margin:30px 0 8px}
.prose p,.prose li{color:var(--muted)}
.prose ul{padding-left:22px;margin:8px 0}
.prose li{margin:5px 0}
.toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(80px);background:var(--gold);color:#2a1700;font-weight:800;padding:10px 16px;border-radius:12px;transition:transform .32s cubic-bezier(.34,1.56,.64,1),opacity .2s,visibility .2s;z-index:50;max-width:calc(100% - 32px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:0;visibility:hidden}
.toast.on{transform:translateX(-50%) translateY(0);opacity:1;visibility:visible}
.toast.long{white-space:normal;overflow-wrap:anywhere}  /* a message to act on wraps rather than cut off (#143) */
/* the four list names in one row down to the phone sizes below (#218) */
@media (max-width:620px){.listpick{gap:4px 18px}.listpick label{font-size:22px}}
/* Six links with Games (#215): below 961px the icon alone is the home link, and on phones Games goes
   too (the home page's Play together panel and every footer link it), so Players, which becomes a
   visitor's own "You" (common.js, #144), stays. */
@media (max-width:960px){.nav nav a[href="/"]{display:none}}
@media (max-width:420px){.nav nav a[href="/games/"]{display:none}}
@media (max-width:860px){
  .motd,.mapgrid,.join{grid-template-columns:minmax(0,1fr)}
  .stats,.pstats{grid-template-columns:repeat(2,1fr)}
  .nav .ip{display:none}
  .nav nav a{padding:8px 10px}  /* five links fit from 561px up (#35) */
  .maphead h1{font-size:34px}
  .viewer{min-height:300px}
}
/* a phone: a taller 3D view, so its chips, splits and buttons leave the map room (#232); never under
   the 300px above, and only where there is a model to view */
@media (max-width:560px){.viewer[data-src]{min-height:clamp(300px,64vh,440px)}}
td.place .of{color:var(--faint)}
@media (max-width:560px){
  td.lvl{white-space:normal;font-size:13px;min-width:4.5em}
  td.place .of{display:block;font-size:12px}
  .wrap{padding:0 16px}
  .nav .wrap{gap:10px}
  .nav nav{margin-left:-4px;gap:0}
  .nav nav a{padding:6px 7px;font-size:14px}
  .nav .brand .mark img{width:32px;height:32px}
  .stat{padding:12px 14px}.stat b{font-size:24px}
  .motd .body{padding:18px}
  .motd .art{min-height:220px}.motd .art svg{width:150px;height:150px}
  .grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px}
  .card .thumb{height:96px}.card .thumb svg{width:60px;height:60px}
  .card .info{padding:10px 10px 12px}
  .card .row{flex-direction:column;align-items:flex-start;gap:2px}
  .rating .bar{width:44px}
  h2{font-size:24px;margin-top:32px}
  .listpick{margin-top:32px;gap:2px 14px}.listpick label{font-size:17px;padding-bottom:4px}
  .hero .hero-ip,.hero .hero-ip code{font-size:17px}.hero .hero-ip .btn{padding:8px 18px;font-size:16px}
  .sechead{margin-top:32px}
  td,th{padding:8px 5px}
  .phead h1{font-size:30px}
}
/* Phones (#35, #36): "Home" gives its room to the other links up to 960px (#215), since the icon is the way home
   and from 451px the links are wider again (#194; with Games, 441-445px was too narrow for
   "Leaderboards", #215); "Leaderboards" says "Boards" (its full name stays
   for screen readers); names in tables keep to one line, cut with an ellipsis (the full name is the
   title), and give up their head picture and some padding for room. */
@media (max-width:450px){
  .nav nav .long{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .nav nav .short{display:inline}
  .panel{padding:12px}
  td .pl .head{display:none}
  td.who .pl{gap:0}
  th{font-size:10.5px;letter-spacing:.2px}
  td,th{padding:8px 4px}
}
@media (max-width:380px){.nav nav a{padding:6px 5px;font-size:13px}}
/* a personal best whose run can be raced against the record in the 3D view (#71) */
td.time a.race{display:block;margin-top:2px;font:600 12px Inter,system-ui,sans-serif;color:var(--violet2);text-decoration:underline;text-underline-offset:2px}
td.time a.race:hover{color:var(--lav)}
/* Reduced motion (#153, as the 3D view does, #64): cards don't lift, the toast doesn't slide. */
@media (prefers-reduced-motion:reduce){.card,.toast,.grid.stale{transition:none}.card:hover,.card:focus-within{transform:none}}
/* A personal best's gap to the record (#147), and a leaderboard's own rows (#144, #146) */
td.time .gap{display:block;font:600 12px Inter,system-ui,sans-serif;color:var(--faint)}
td.time .gap.rec{color:var(--gold)}
/* ... and every map leaderboard row's gap to its board's first (#339): under the time, so the names keep their
   room; after it only from 701 to 860 px, where the board has the page's whole width (in the side column, from
   861 px, an inline gap cut the widest names even at the column's widest, 1201 px and up: #372). Under the
   time it may reach into the cell's left padding: a gap has no more digits than its time and is set smaller,
   but should one still be the wider (in another font), it never widens the column (#372) */
.lbrows td.time .gap{margin-left:-10px}
@media (min-width:701px) and (max-width:860px){.lbrows td.time .gap{display:inline;margin-left:8px}}
@media (max-width:560px){.lbrows td.time .gap{margin-left:-5px}}
@media (max-width:450px){.lbrows td.time .gap{margin-left:-4px}}
/* (on the visitor's own row and the row raced in 3D, whose tint takes --faint under 4.5:1: #361 review) */
.lbrows tr.me td.time .gap,#lb tr.raced td.time .gap{color:var(--muted)}
/* A player's share of the maps and their 2nd and 3rd places (#338), on a line of their own in the stat (the
   share's words short enough for one line in a 320 px phone's stat: player.js counts()) */
.stat .sub{display:block;font-size:inherit}
/* ... and their maps finished per difficulty (#338): "of N" and the bars come with data/versions.json
   (player.js), in the room kept for them; without scripts, no bars that would say none */
.bydiff .hardest{margin:0 0 12px;display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px}
.bydiff .votes>div{grid-template-columns:84px minmax(0,1fr) 9.5em}
.bydiff .votes span:last-child{white-space:nowrap}
.bydiff .votes a{text-decoration:underline;text-underline-offset:2px}
/* (the bars only once player.js has the counts, "counted": until then, without scripts, or when data/versions.json
   doesn't come, an empty or full bar would say none or every one) */
.bydiff .bar{visibility:hidden}
.bydiff .bar i{width:0}
.bydiff.counted .bar{visibility:visible}
tr.me td{background:rgba(123,77,255,.16)}
.note.mybest b{color:var(--gold)}
.pbsort{margin-left:auto;background:#120c2f;border:1px solid var(--edge);border-radius:10px;padding:6px 10px;color:var(--text);font:inherit;font-size:13px}
/* A player's places on the boards (#145), and "This is me" (#144) */
/* One chip tall at any width, so the room the page keeps for it is the room it takes (#270): the row
   scrolls sideways where the chips don't fit (a phone), its end faded. (The padding is room for focus
   rings, which the scrolling box would otherwise cut off.) */
.places{display:flex;flex-wrap:nowrap;gap:8px;margin:8px -4px 0;padding:4px;overflow-x:auto;scrollbar-width:none;overscroll-behavior-x:contain}
.places::-webkit-scrollbar{display:none}
.places .chip{flex:none;max-width:none}
.places .held{visibility:hidden}
/* its end faded at every width (#305 review: from 561 to about 1030 px five chips don't fit either); the
   padding keeps a row that fits clear of the fade, and the last chip once scrolled to */
.places{padding-right:28px;scroll-padding-inline-end:28px;-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent)}
/* With a mouse, a thin scrollbar to drag (shift+wheel, trackpads and Tab turn it too), its room always
   kept so the row is the same height whether its chips fit or not (the room the page keeps, #270): 6 px,
   a violet thumb only when there is something to scroll. Chromium and Safari draw it from the
   ::-webkit-scrollbar rules, which Chromium ignores once scrollbar-width or -color is set (other than
   auto: the base's none is undone here); Firefox, without them, takes its thin one. Touch screens
   swipe the row. */
@media (hover:hover) and (pointer:fine){
  .places{overflow-x:scroll;scrollbar-width:auto}
  .places::-webkit-scrollbar{display:block;height:6px}
  .places::-webkit-scrollbar-track,.places::-webkit-scrollbar-corner{background:transparent}
  .places::-webkit-scrollbar-button{display:none}
  .places::-webkit-scrollbar-thumb{background:var(--violet);border-radius:3px}
  @supports not selector(::-webkit-scrollbar){.places{scrollbar-width:thin;scrollbar-color:var(--violet) transparent}}
}
.places .chip b{color:var(--gold)}
.places .chip small{color:var(--faint);font-size:12px}
/* A player's tier on the skill ladder and what the next one needs (#337); the ladder page's tiers */
.ladder{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;margin:14px 0 0;padding:12px 16px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);font-size:13px;color:var(--muted)}
.ladder .rung,.rungs .rung,td .chip.rung{font-weight:700}
.ladder .next b{font-weight:700}
.ladder .gates{display:flex;flex-wrap:wrap;gap:4px 14px;margin:0;padding:0;list-style:none;color:var(--text)}
.ladder .gates li::before{content:"•";margin-right:6px;color:var(--gold)}
.ladder .gates li.ok{color:var(--muted)}
.ladder .gates li.ok::before{content:"✓";color:var(--green)}
/* ... and on narrow screens they keep to the panel (#364 review): the board's cells in short forms (.rs for .rl:
   its skill without the difficulty's name, its place without "top"; the headings say what they are) and smaller
   tier chips up to 700px, its tier under the name (its own column and the maps, which the tier says enough of,
   gone) up to 560px; the tiers table's cells in short forms ("Hard+") and its tiers without the chip up to 450px */
.ladderboard .lsub,.ladderboard .rs,.rungs .rs{display:none}
.rungs td,.rungs th{white-space:normal}  /* (its headings and "20 at Hardcore" wrap where the panel is narrow) */
@media (max-width:700px){
  .ladderboard .chip.rung,.rungs .chip.rung{font-size:11px;padding:1px 7px}
  .ladderboard .rl{display:none}
  .ladderboard .rs{display:inline}  /* (the skill's difficulty, then, for screen readers only) */
}
@media (max-width:560px){
  .ladderboard .lrank,.ladderboard .lmaps{display:none}
  .ladderboard .lsub{display:inline-flex;margin-top:3px}
}
@media (max-width:450px){
  .rungs .rl{display:none}
  .rungs .rs{display:inline}
  .rungs td{font-size:13px}.rungs th{letter-spacing:0}.rungs td,.rungs th{padding:8px 2px}
  .rungs .chip.rung{background:none;border:0;padding:0}  /* (its name in its colour) */
}
.phead .isme{margin-left:auto;min-width:7em}  /* "Not me" as wide as "This is me" (104 px), which the page draws first (#270) */
.card .thumb .done{position:absolute;right:8px;bottom:8px;background:var(--green);color:#06210f;font-weight:800;border-radius:999px;padding:1px 8px;font-size:12px}
.you-strip{margin:18px 0 0}
/* a new record: who and the time (the time goes under a long name, never cut off; a name too long for
   the card ends in an ellipsis, whole in its title), then by how much it beat the one before and when,
   wrapping rather than cut off on a narrow card */
.records .t>span{display:block}
.records .t .who{display:flex;flex-wrap:wrap;white-space:nowrap}
.records .who .nm{display:flex;min-width:0;margin-right:4px}  /* (the dot stays with the name) */
.records .who bdi{min-width:0;overflow:hidden;text-overflow:ellipsis;margin-right:4px}
.records .who .ms{flex:none}
.records time{white-space:nowrap}
.records .t .gain{display:inline-block;white-space:nowrap;margin-right:4px;padding:0 7px;border-radius:999px;background:rgba(70,211,126,.14);
  color:var(--green);font:700 11.5px/1.6 "JetBrains Mono",monospace}
#random{white-space:nowrap}
/* Name suggestions in a player search (#149) */
.suggest{position:absolute;left:0;right:0;top:100%;z-index:20;margin:4px 0 0;padding:4px;list-style:none;background:var(--panel2);border:1px solid var(--edge);border-radius:10px;box-shadow:var(--shadow);max-width:460px}
.suggest li a{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:8px}
.suggest li[aria-selected="true"] a,.suggest li a:hover{background:var(--violet)}
.suggest .head{width:24px;height:24px;font-size:12px}
/* Motion (#185): parkour moves, small, and played once, but for the logo's run, which goes on with two
   ghosts and a button to stop it (above; static/js/logo.js). The logo lands and its runner runs over
   its blocks, the 404 page's runner misses a jump (tools/make_course.py, below), cards and lists land as they scroll in,
   and a map's picture hops on its card. Only without reduced motion, and the scroll-in only where the
   browser drives animations by scrolling (elsewhere they simply show). Only transforms and opacity
   move, so nothing shifts the layout (#32). */
.fall{display:block;width:min(480px,100%);height:auto;margin:28px 0 0}
@media (prefers-reduced-motion:no-preference){
  .hero .logo{animation:pgg-land .7s cubic-bezier(.3,.7,.4,1) both;transform-origin:50% 100%}
  .card:hover .thumb .pic,.card:hover .thumb>svg,.mini:hover .pic,.mini:hover>svg,.nav .brand:hover .mark img{animation:pgg-hop .45s cubic-bezier(.3,.7,.4,1);transform-origin:50% 100%}
  @supports (animation-timeline:view()) and (animation-range:entry 0% entry 70%){  /* (without ranges a card would slide in all the way across the screen) */
    /* not .panel or .motd: a leaderboard's, or the Map of the Day on a landscape phone, is taller
       than the screen and would stay half slid in */
    .grid .card,.strip .mini,.stat{animation:pgg-in linear;animation-timeline:view();animation-range:entry 0% entry 70%}
  }
}
@keyframes pgg-land{0%{translate:0 -22px;scale:.98 1.03}45%{translate:0 0;scale:1.03 .95}70%{scale:.99 1.01}100%{translate:0 0;scale:1 1}}
@keyframes pgg-hop{0%{translate:0 0}40%{translate:0 -8px;scale:.96 1.05}70%{translate:0 0;scale:1.05 .94}100%{translate:0 0;scale:1 1}}
/* (moves only, no fade: a card halfway in would show its text below 4.5:1, #269) */
@keyframes pgg-in{0%{translate:0 28px;scale:.97}100%{translate:0 0;scale:1}}
/* course: begin (written by tools/make_course.py) */
@media (prefers-reduced-motion:no-preference){
@keyframes pgg-f-x{0%{transform:translate(164px,0);opacity:1}20%{transform:translate(164px,0);opacity:1}64%{transform:translate(464px,0);opacity:1;animation-timing-function:step-end}64.4%{transform:translate(164px,0);opacity:0}84%{transform:translate(164px,0);opacity:0;animation-timing-function:ease-out}100%{transform:translate(164px,0);opacity:1}}@keyframes pgg-f-y{0%{transform:translate(0,181px)}20%{transform:translate(0,181px);animation-timing-function:cubic-bezier(.33,.66,.66,1)}34%{transform:translate(0,131px);animation-timing-function:cubic-bezier(.33,0,.66,.33)}64%{transform:translate(0,430px);animation-timing-function:step-end}64.4%{transform:translate(0,181px)}100%{transform:translate(0,181px)}}@keyframes pgg-f-s{0%{transform:none}15.2%{transform:none;animation-timing-function:ease-out}20%{transform:scale(1.14,0.84);animation-timing-function:ease-out}24%{transform:scale(0.9,1.12);animation-timing-function:ease-out}32%{transform:none}100%{transform:none}}.fall .f-x{animation:pgg-f-x 2.5s linear both}.fall .f-y{animation:pgg-f-y 2.5s both}.fall .f-s{animation:pgg-f-s 2.5s both}
}
/* course: end */
/* the admin pages (#211, templates/admin.html, static/js/admin.js) */
.admin .tabs{margin-top:-4px}
.admin-msg{color:var(--muted)}
.admin-tiles{grid-template-columns:repeat(auto-fill,minmax(210px,1fr));margin:18px 0}
.admin-tiles .stat b{font-size:22px;line-height:1.25;margin:4px 0 2px;overflow-wrap:anywhere}
.admin-tiles .stat .lbl{display:block;color:var(--faint);font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.6px}
.admin-tiles code,.admin dd code{font:500 12px "JetBrains Mono",monospace;color:var(--lav);overflow-wrap:anywhere}
.admin .panel{margin:0 0 16px}
.admin .panel h3{margin:16px 0 6px;font-size:13px;color:var(--faint);font-weight:600;text-transform:uppercase;letter-spacing:.6px}
.admin-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr));gap:16px;align-items:start}
.admin-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,480px),1fr));gap:16px;align-items:start}
.admin-stack{display:grid;gap:16px}
.admin-stack .panel{margin:0}
.state{display:inline-flex;align-items:center;gap:2px;font-weight:700;font-size:12.5px;padding:1px 8px;border-radius:999px;border:1px solid currentColor;white-space:nowrap}
.state.ok{color:var(--green)}.state.warn{color:var(--gold)}.state.bad{color:var(--red)}.state.none{color:var(--faint)}
.kv{display:grid;grid-template-columns:fit-content(45%) minmax(0,1fr);gap:6px 14px;margin:0;font-size:14px}
.kv dt{color:var(--muted);overflow-wrap:anywhere}
.kv .state{white-space:normal}.kv dd{margin:0;min-width:0;overflow-wrap:anywhere}
.admin .note{color:var(--lav);font-size:13px;overflow-wrap:anywhere}
.admin .faint{color:var(--faint)}
.log{margin:0;max-height:260px;overflow:auto;background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:10px;
  font:500 12px/1.5 "JetBrains Mono",monospace;color:var(--lav);white-space:pre-wrap;overflow-wrap:anywhere}
.admin-foot{color:var(--faint);font-size:13px;margin:6px 0 30px}
.admin-sub{margin:28px 0 0;font-size:18px}
.admin-count{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;margin:10px 0 14px;font-size:14px;color:var(--muted)}
.admin-warn{margin:16px 0 0;display:grid;gap:6px}
.admin-warn p{margin:0}
.admin .tablewrap:focus-visible{outline:2px solid var(--violet2);outline-offset:2px}
.admin table.top td.lbl{min-width:14em;width:100%}
.admin table.top td.states{min-width:16em;font-size:13px;color:var(--muted)}
.admin table.top td.lbl>span:first-child{display:block;overflow-wrap:anywhere}
.admin table.top small{display:block;margin-top:2px;color:var(--faint);font-size:12px}
.admin table.top code{font:500 12.5px "JetBrains Mono",monospace}
.hbar{display:block;height:6px;margin-top:5px;background:transparent}
.hbar i{display:block;height:100%;min-width:2px;background:#9a74ff;border-radius:0 4px 4px 0}
.chart .legend{display:flex;gap:16px;font-size:13px;color:var(--muted);margin:0 0 6px}
.chart .legend .key{display:inline-block;width:14px;height:2px;border-radius:1px;vertical-align:middle;margin-right:6px}
.chart .plot{position:relative;outline:none;border-radius:8px;touch-action:pan-y}
.chart .plot:focus-visible{box-shadow:0 0 0 2px var(--violet2)}
.chart svg{display:block;max-width:100%;height:auto}
.chart .grid{stroke:#2a2064;stroke-width:1}
.chart .axis{fill:var(--faint);font:500 11px Inter,system-ui,sans-serif}
.chart .cross{stroke:var(--muted);stroke-width:1}
.chart .dot{stroke:var(--panel);stroke-width:2}
.chart .tip{position:absolute;top:8px;min-width:130px;background:var(--panel2);border:1px solid var(--edge);border-radius:10px;padding:8px 10px;
  font-size:13px;color:var(--muted);pointer-events:none;box-shadow:var(--shadow)}
.chart .tip .when{color:var(--text);font-weight:600;margin-bottom:2px}
.chart .tip b{color:var(--text);margin-left:6px}
.chart .tip .line{display:inline-block;width:12px;height:2px;vertical-align:middle}
.chart details.daily{margin-top:10px;font-size:14px}
.chart details.daily summary{cursor:pointer;color:var(--violet2)}
/* the game's own data (#291, #292): a map's falls, a playlist's maps in order, challenges, videos */
ol.falls{margin:4px 0 0;padding-left:20px}
ol.falls li{margin:2px 0}
ol.grid.playlist{list-style:none;padding:0;margin:0}
.challenges{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px}
.challenges h3{margin:0 0 6px}
.challenges h3 small{color:var(--faint);font-weight:400;font-size:13px}
.start-here{margin-top:24px}
.start-here .strip{margin-top:12px}
ul.featured-in{padding-left:20px}
ul.featured-in li{margin:4px 0}
.chip.tier{font-size:11px;padding:1px 7px;vertical-align:1px}
.feed td.who{width:30%}
.feed td.m{max-width:0;width:30%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:560px){.feed .when{display:none}.feed td,.feed th{padding:9px 5px}}
/* the record and hardest-maps lists (#412): the long header wraps; below 761 px the difficulty, the all-time count
   and the record beaten give way, so the map's name keeps its room; on phones its builder too */
.feed td.m .by{color:var(--muted)}
.feed th.fb{white-space:normal}
@media (max-width:760px){.feed .d,.feed .fb,.feed .beat{display:none}}
@media (max-width:560px){.feed td.m .by{display:none}}
/* the longest-standing records: on phones the place gives way to the day, which is the point of the list */
@media (max-width:560px){.longest-list .rk{display:none}}
@media (max-width:450px){.chip.tier{display:none}}
/* "About this map" (#262) */
.about{margin-top:24px}
.about h2{margin-top:0}
.about p{max-width:72ch}
.about .facts{margin-top:12px}
