/* Made by Ricci — one stylesheet, no JS, no external requests. */

:root{
  --bg:#07090f;
  --panel:rgba(255,255,255,.028);
  --panel-hi:rgba(255,255,255,.055);
  --line:rgba(255,255,255,.10);
  --line-hi:rgba(255,255,255,.20);
  --ink:#e9edf7;
  --muted:#8b97af;
  --accent:#4de1ff;
  --accent-2:#a78bfa;
  --radius:18px;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}
/* Per-game accents, set with a class on <body>. */
body.t-muncher{--accent:#8dff43;--accent-2:#4de1ff}
body.t-koala{--accent:#b79cff;--accent-2:#6fd7e8}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}

body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font:16px/1.7 var(--sans);
  letter-spacing:.1px;
  overflow-x:hidden;
}
/* Faint grid. Fixed so it never scrolls away. */
body::after{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.5;
  background-image:
    linear-gradient(var(--line) 1px,transparent 1px),
    linear-gradient(90deg,var(--line) 1px,transparent 1px);
  background-size:4.5rem 4.5rem;
  -webkit-mask-image:radial-gradient(70% 55% at 50% 0%,#000,transparent 100%);
          mask-image:radial-gradient(70% 55% at 50% 0%,#000,transparent 100%);
  animation:grid-drift 26s linear infinite;
}
@keyframes grid-drift{from{background-position:0 0}to{background-position:0 4.5rem}}

/* ---------- animated background ----------
   Two slow-drifting aurora blobs and a field of rising pellets. Everything
   animates transform/opacity only, so it stays on the compositor and costs
   almost nothing. Colours come from the page accent, so each game gets its own. */
.fx{position:fixed;inset:0;z-index:-2;pointer-events:none;overflow:hidden}
/* Parallax groups. Each group carries only the scroll-driven transform, so the
   time-based drifts on its children stay untouched — no two animations fight
   over the same property. */
.plx{position:absolute;inset:0}
.fx i{position:absolute;display:block;border-radius:50%;will-change:transform}
.fx-a{width:48rem;height:38rem;left:-12rem;top:-14rem;
  background:radial-gradient(circle at 50% 50%,
    color-mix(in srgb,var(--accent) 22%,transparent), transparent 68%);
  animation:drift-a 46s linear infinite}
.fx-b{width:42rem;height:32rem;right:-14rem;top:-9rem;
  background:radial-gradient(circle at 50% 50%,
    color-mix(in srgb,var(--accent-2) 20%,transparent), transparent 68%);
  animation:drift-b 58s linear infinite}
@keyframes drift-a{
  0%,100%{transform:translate3d(0,0,0)        scale(1)}
  25%    {transform:translate3d(10rem,3rem,0) scale(1.12)}
  50%    {transform:translate3d(15rem,9rem,0) scale(1.24)}
  75%    {transform:translate3d(6rem,8rem,0)  scale(1.12)}}
@keyframes drift-b{
  0%,100%{transform:translate3d(0,0,0)          scale(1.15)}
  25%    {transform:translate3d(-8rem,5rem,0)   scale(1.02)}
  50%    {transform:translate3d(-14rem,11rem,0) scale(.9)}
  75%    {transform:translate3d(-6rem,6rem,0)   scale(1.02)}}

/* Third blob rising from the lower edge, and a slow light beam that sweeps
   diagonally across the whole page. */
.fx-c{width:36rem;height:28rem;left:32%;top:auto;bottom:-18rem;
  background:radial-gradient(circle at 50% 50%,
    color-mix(in srgb,var(--accent) 15%,transparent), transparent 68%);
  animation:drift-c 70s linear infinite}
@keyframes drift-c{
  0%,100%{transform:translate3d(-6rem,4rem,0) scale(.95)}
  25%    {transform:translate3d(0,-1rem,0)    scale(1.08)}
  50%    {transform:translate3d(7rem,-8rem,0) scale(1.2)}
  75%    {transform:translate3d(1rem,-2rem,0) scale(1.08)}}

.fx-beam{width:150%;height:150%;left:-25%;top:-25%;border-radius:0;
  background:linear-gradient(101deg,transparent 41%,
    color-mix(in srgb,var(--accent) 10%,transparent) 50%, transparent 59%);
  animation:beam 19s linear infinite}
@keyframes beam{
  0%  {opacity:0;transform:translate3d(-55%,0,0)}
  12% {opacity:1}
  88% {opacity:1}
  100%{opacity:0;transform:translate3d(55%,0,0)}}

/* Pellets. One tile is 50% of the element's height and the element is 200%
   tall, so translating by one tile loops seamlessly with no visible jump. */
.fx-dots{position:absolute;left:0;top:0;width:100%;height:200%;
  border-radius:0;opacity:.8;
  background-repeat:repeat;background-size:100% 50%;
  background-image:
    radial-gradient(3.5px 3.5px at 12% 9%,  var(--accent),   transparent 60%),
    radial-gradient(3px 3px     at 78% 15%, var(--accent-2), transparent 60%),
    radial-gradient(2px 2px     at 33% 24%, #fff,            transparent 60%),
    radial-gradient(3.5px 3.5px at 91% 33%, var(--accent),   transparent 60%),
    radial-gradient(3px 3px     at 55% 41%, var(--accent-2), transparent 60%),
    radial-gradient(2px 2px     at 8%  49%, #fff,            transparent 60%),
    radial-gradient(3.5px 3.5px at 68% 58%, var(--accent),   transparent 60%),
    radial-gradient(3px 3px     at 24% 66%, var(--accent-2), transparent 60%),
    radial-gradient(2px 2px     at 86% 74%, #fff,            transparent 60%),
    radial-gradient(3.5px 3.5px at 44% 83%, var(--accent),   transparent 60%),
    radial-gradient(3px 3px     at 71% 91%, var(--accent-2), transparent 60%),
    radial-gradient(2px 2px     at 17% 97%, #fff,            transparent 60%),
    radial-gradient(3px 3px     at 62% 5%,  var(--accent),   transparent 60%),
    radial-gradient(2px 2px     at 40% 30%, #fff,            transparent 60%),
    radial-gradient(3.5px 3.5px at 5%  62%, var(--accent-2), transparent 60%),
    radial-gradient(2px 2px     at 95% 52%, #fff,            transparent 60%),
    radial-gradient(3px 3px     at 30% 88%, var(--accent),   transparent 60%),
    radial-gradient(2px 2px     at 82% 79%, var(--accent-2), transparent 60%);
  animation:rise 34s linear infinite, twinkle 7s ease-in-out infinite}
@keyframes rise{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,-50%,0)}}
/* ---------- scroll-driven parallax ----------
   Near layers travel further than far ones as the page scrolls, which reads as
   depth. Scroll-driven animations need no JavaScript; browsers without support
   simply skip this block and keep the static layering. */
@keyframes plx{from{translate:0 0}to{translate:0 var(--plx,0)}}
@keyframes plx-grid{from{translate:0 0}to{translate:0 -2.5rem}}
@supports (animation-timeline:scroll()){
  .plx{
    animation-name:plx;
    animation-duration:auto;
    animation-timing-function:linear;
    animation-fill-mode:both;
    animation-timeline:scroll(root block);
  }
  .plx-far{--plx:-5rem}
  .plx-mid{--plx:-11rem}
  .plx-near{--plx:-20rem}
  /* the grid animates background-position on the time axis, so parallax uses
     the separate `translate` property and the two never collide */
  body::after{
    animation-name:grid-drift,plx-grid;
    animation-duration:26s,auto;
    animation-timing-function:linear,linear;
    animation-iteration-count:infinite,1;
    animation-fill-mode:none,both;
    animation-timeline:auto,scroll(root block);
  }
}
@keyframes twinkle{0%,100%{opacity:.85}50%{opacity:.45}}

/* Finer, quicker layer. Different speed to the layer above gives the field
   a sense of depth as it moves. */
.fx-dots2{position:absolute;left:0;top:0;width:100%;height:200%;
  border-radius:0;opacity:.5;
  background-repeat:repeat;background-size:100% 50%;
  background-image:
    radial-gradient(2px 2px at 21% 6%,  var(--accent-2), transparent 60%),
    radial-gradient(1.5px 1.5px at 66% 12%, #fff,        transparent 60%),
    radial-gradient(2px 2px at 47% 19%, var(--accent),   transparent 60%),
    radial-gradient(1.5px 1.5px at 88% 27%, var(--accent-2), transparent 60%),
    radial-gradient(2px 2px at 14% 35%, #fff,            transparent 60%),
    radial-gradient(1.5px 1.5px at 59% 44%, var(--accent), transparent 60%),
    radial-gradient(2px 2px at 35% 53%, var(--accent-2),  transparent 60%),
    radial-gradient(1.5px 1.5px at 76% 61%, #fff,        transparent 60%),
    radial-gradient(2px 2px at 6%  70%, var(--accent),    transparent 60%),
    radial-gradient(1.5px 1.5px at 52% 77%, var(--accent-2), transparent 60%),
    radial-gradient(2px 2px at 92% 86%, #fff,            transparent 60%),
    radial-gradient(1.5px 1.5px at 28% 94%, var(--accent), transparent 60%);
  animation:rise 21s linear infinite, twinkle 5s ease-in-out infinite reverse}

.wrap{max-width:70rem;margin:0 auto;padding:0 1.35rem}

/* ---------- header ---------- */
/* A single light trail that runs along the bottom hairline of the header,
   clipped to the bar. Constant velocity, and fully off both edges at the loop
   point so the wrap is invisible. */
.head-fx{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.head-fx i{position:absolute;display:block;bottom:0;left:-14rem;
  width:14rem;height:1px;border-radius:1px;opacity:.85;
  background:linear-gradient(to right,transparent,
    color-mix(in srgb,var(--accent) 85%,transparent) 62%,
    color-mix(in srgb,#fff 75%,transparent) 88%, transparent);
  animation:head-streak 13s linear infinite}
@keyframes head-streak{
  from{transform:translate3d(0,0,0)}
  to  {transform:translate3d(calc(100vw + 30rem),0,0)}}

.site-head{position:sticky;top:0;z-index:10;
  background:color-mix(in srgb,var(--bg) 82%,transparent);
  backdrop-filter:saturate(160%) blur(14px);
  -webkit-backdrop-filter:saturate(160%) blur(14px);
  border-bottom:1px solid var(--line)}
.site-head .wrap{position:relative;z-index:1;
  display:flex;align-items:center;justify-content:space-between;
  gap:1rem;min-height:4rem;flex-wrap:wrap}
.brand{display:inline-flex;align-items:baseline;gap:.5rem;
  text-decoration:none;color:#fff;font-weight:700;font-size:1.3rem;letter-spacing:-.3px;
  text-shadow:0 0 1.1rem color-mix(in srgb,#fff 26%,transparent);
  transition:text-shadow .3s}
.brand:hover{text-shadow:0 0 1.4rem color-mix(in srgb,#fff 40%,transparent)}
.brand .dot{width:.55rem;height:.55rem;border-radius:50%;background:var(--accent);
  box-shadow:0 0 .75rem var(--accent);align-self:center;
  animation:breathe 3.4s ease-in-out infinite}
@keyframes breathe{0%,100%{opacity:1;box-shadow:0 0 .75rem var(--accent)}
  50%{opacity:.55;box-shadow:0 0 .3rem var(--accent)}}
.brand span.thin{color:#fff;font-weight:500}
.site-head nav{display:flex;gap:1.25rem;font-size:.9rem;margin-left:auto}
.site-head nav a{color:var(--muted);text-decoration:none}
.site-head nav a:hover,.site-head nav a[aria-current]{color:var(--ink)}

/* ---------- type ---------- */
h1,h2,h3{line-height:1.15;letter-spacing:-.6px;margin:0}
h1{font-size:clamp(2.4rem,7vw,4.25rem);font-weight:800}
h2{font-size:clamp(1.35rem,3.2vw,1.8rem);font-weight:700;margin:0 0 .9rem}
h3{font-size:1.05rem;font-weight:650;margin:0 0 .35rem}
p{margin:0 0 1rem}
.lede{font-size:clamp(1.05rem,2.2vw,1.2rem);color:#c3cbdd}
.muted{color:var(--muted)}
a{color:var(--accent)}
.grad{background:linear-gradient(100deg,var(--accent),var(--accent-2) 45%,var(--accent) 90%);
  background-size:220% 100%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  animation:shimmer 9s ease-in-out infinite}
@keyframes shimmer{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}

/* Small mono label — the "futuristic" tell, used sparingly. */
.kicker{font:600 .72rem/1 var(--mono);letter-spacing:.18em;text-transform:uppercase;
  color:var(--accent);display:inline-block;margin-bottom:1rem}

.chip{display:inline-flex;align-items:center;gap:.45rem;
  font:600 .7rem/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  padding:.42rem .7rem;border:1px solid var(--line-hi);border-radius:999px;
  color:var(--muted);background:var(--panel)}
.chip.live{color:var(--accent);border-color:color-mix(in srgb,var(--accent) 45%,transparent);
  text-decoration:none;transition:border-color .2s,background .2s,transform .2s}
a.chip.live:hover{border-color:var(--accent);transform:translateY(-1px);
  background:color-mix(in srgb,var(--accent) 12%,transparent)}
/* Primary call to action: larger than an informational chip, with a leading icon. */
.chip.cta{font-size:.84rem;letter-spacing:.07em;padding:.78rem 1.25rem;gap:.6rem;
  background:color-mix(in srgb,var(--accent) 10%,transparent);
  box-shadow:0 .5rem 1.5rem -.6rem color-mix(in srgb,var(--accent) 55%,transparent)}
.chip.cta svg{width:1.15em;height:1.15em;flex:0 0 auto}
a.chip.cta:hover{background:color-mix(in srgb,var(--accent) 18%,transparent);
  box-shadow:0 .7rem 1.8rem -.6rem color-mix(in srgb,var(--accent) 70%,transparent)}
.chip .pulse{width:.4rem;height:.4rem;border-radius:50%;background:currentColor;
  box-shadow:0 0 .6rem currentColor;animation:breathe 2.6s ease-in-out infinite}

/* ---------- sections ---------- */
section{padding:3rem 0}
.hero{padding:4.25rem 0 1.5rem}
.hero .kicker,.hero h1,.hero .lede{animation:rise-in .8s cubic-bezier(.2,.7,.3,1)}
@keyframes rise-in{from{opacity:0;transform:translateY(1.1rem)}to{opacity:1;transform:none}}
.hero p{margin-top:1rem}
.sec-head{margin-bottom:1.4rem}

/* ---------- game cards ---------- */
.games{display:grid;gap:1.25rem;grid-template-columns:repeat(auto-fit,minmax(min(19rem,100%),1fr))}
.card{position:relative;display:flex;flex-direction:column;gap:1rem;
  padding:1.6rem;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--panel);text-decoration:none;color:inherit;overflow:hidden;
  transition:border-color .25s,transform .25s,background .25s}
.card::before{content:"";position:absolute;inset:0 0 auto;height:1px;
  background:linear-gradient(90deg,transparent,var(--card-accent,var(--accent)),transparent);
  background-size:40% 100%;background-repeat:no-repeat;
  opacity:.6;animation:sweep 6.5s linear infinite}
@keyframes sweep{from{background-position:-120% 0}to{background-position:260% 0}}
.card:hover{transform:translateY(-3px);border-color:var(--line-hi);background:var(--panel-hi);
  box-shadow:0 1rem 2.5rem -1rem color-mix(in srgb,var(--card-accent,var(--accent)) 45%,transparent)}
.card:hover::before{opacity:1}
.card .top{display:flex;align-items:center;gap:1rem}
.card img.icon{width:4.25rem;height:4.25rem;border-radius:1.15rem;display:block;
  border:1px solid var(--line);box-shadow:0 .6rem 1.6rem rgba(0,0,0,.5)}
.card h3{font-size:1.3rem;letter-spacing:-.4px;margin:0}
.card .by{font:600 .7rem/1.4 var(--mono);letter-spacing:.08em;text-transform:uppercase;
  color:var(--card-accent,var(--accent))}
.card p{color:var(--muted);margin:0;font-size:.95rem}
.card .go{margin-top:auto;font-weight:600;font-size:.9rem;color:var(--card-accent,var(--accent))}
.card .tag + .go{margin-top:.7rem}
/* Availability tag on a game card. Not a link: the whole card is already one. */
.card .tag{margin-top:auto;align-self:flex-start;
  font:600 .66rem/1 var(--mono);letter-spacing:.11em;text-transform:uppercase;
  padding:.38rem .62rem;border-radius:999px;
  color:var(--card-accent,var(--accent));
  border:1px solid color-mix(in srgb,var(--card-accent,var(--accent)) 42%,transparent);
  background:color-mix(in srgb,var(--card-accent,var(--accent)) 8%,transparent)}
.card.t-muncher{--card-accent:#8dff43}
.card.t-koala{--card-accent:#b79cff}

/* ---------- generic panels / lists ---------- */
.panel{border:1px solid var(--line);border-radius:var(--radius);
  background:var(--panel);padding:1.5rem}
.cols{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(min(14rem,100%),1fr))}
.cols .panel p{margin:0;color:var(--muted);font-size:.93rem}
.cols .panel .n{font:600 .72rem/1 var(--mono);color:var(--accent);
  letter-spacing:.14em;display:block;margin-bottom:.7rem}

/* ---------- screenshots ---------- */
.shots{display:grid;gap:1.15rem;grid-template-columns:repeat(auto-fit,minmax(min(24rem,100%),1fr))}
.shots figure{margin:0}
.shots img{width:100%;height:auto;display:block;border-radius:12px;
  border:1px solid var(--line);background:#0b0f18}
.shots figcaption{color:var(--muted);font-size:.85rem;margin-top:.55rem}

/* ---------- game page hero ---------- */
/* Game hero. A grid rather than a flex row so the icon can stay beside the
   name on a phone while the tagline and button drop to full width beneath.
   A flex row wrapped as one block and pushed the icon onto its own line. */
.game-hero{display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:1.5rem;row-gap:.5rem;align-items:center;padding:2.75rem 0 1.25rem}
.game-hero img{grid-column:1;grid-row:1 / span 3;align-self:center;
  width:6rem;height:6rem;border-radius:1.5rem;border:1px solid var(--line);
  box-shadow:0 1rem 2.5rem rgba(0,0,0,.55)}
.game-meta{grid-column:2;grid-row:1;min-width:0}
.game-meta .kicker{margin-bottom:.5rem}
.game-hero .tagline{grid-column:2;grid-row:2;margin:0}
.game-hero .chip{grid-column:2;grid-row:3;justify-self:start;margin-top:.5rem}
.game-hero h1{font-size:clamp(2rem,6vw,3rem)}
@media (max-width:34rem){
  .game-hero{column-gap:1rem;row-gap:.85rem}
  .game-hero img{grid-row:1;width:4.5rem;height:4.5rem;border-radius:1.15rem}
  .game-hero .tagline{grid-column:1 / -1;grid-row:2}
  .game-hero .chip{grid-column:1 / -1;grid-row:3;margin-top:0}
}
.back{display:inline-block;margin:1.75rem 0 0;font:600 .8rem/1 var(--mono);
  color:var(--muted);text-decoration:none;letter-spacing:.06em}
.back:hover{color:var(--ink)}

/* ---------- doc links ---------- */
.doclinks{display:grid;gap:.75rem;grid-template-columns:repeat(auto-fit,minmax(min(14rem,100%),1fr))}
.doclinks a{display:block;padding:1rem 1.15rem;border:1px solid var(--line);
  border-radius:14px;background:var(--panel);text-decoration:none;font-weight:600;
  color:var(--ink);transition:border-color .2s,background .2s}
.doclinks a:hover{border-color:var(--line-hi);background:var(--panel-hi)}
.doclinks a::after{content:" →";color:var(--accent)}

/* ---------- legal prose ---------- */
.prose{padding:2rem 0 3rem;max-width:64rem}
.prose h1{font-size:clamp(1.8rem,5vw,2.4rem);margin-bottom:.4rem}
.prose h2{font-size:1.1rem;margin:2.4rem 0 .6rem;color:var(--ink)}
.prose p,.prose li{color:var(--muted)}
.prose strong{color:var(--ink)}
.prose ul{padding-left:1.2rem}
.prose li{margin:.35rem 0}
.prose .date{font:600 .75rem/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--accent);margin:0 0 2rem}
.prose .summary{border:1px solid var(--line);border-left:2px solid var(--accent);
  border-radius:12px;background:var(--panel);padding:1.1rem 1.25rem;margin:0 0 2rem}
.prose .summary strong{color:var(--ink)}

/* ---------- footer ---------- */
.site-foot{border-top:1px solid var(--line);padding:2.5rem 0 3.5rem;
  color:var(--muted);font-size:.88rem}
.site-foot .wrap{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.site-foot a{color:var(--muted);text-decoration:none;margin-right:1.1rem}
.site-foot a:hover{color:var(--ink)}

@media (max-width:34rem){
  section{padding:2.5rem 0}
  .hero{padding:3rem 0 1.75rem}
  /* the larger wordmark would push the nav onto a second row on narrow
     screens, so both step down a little to keep the bar one line */
  .brand{font-size:1.1rem}
  .site-head nav{font-size:.82rem;gap:.85rem}
  .site-head .wrap{padding:0 1rem}
  .card{padding:1.3rem}
}
@media (prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important}
  html{scroll-behavior:auto}
  .hero .kicker,.hero h1,.hero .lede{opacity:1;transform:none}
  .grad{background-position:0 50%}
  .card::before{background-position:0 0;background-size:100% 100%}
  .fx-beam,.head-fx{display:none}
  .fx-dots,.fx-dots2{opacity:.6}
}

/* Utility classes replacing former inline style attributes, so the Content
   Security Policy can forbid inline styles outright. */
.pt0{padding-top:0}
.pt2{padding-top:2rem}
.tagline{margin:.6rem 0 1rem}
.mt125{margin-top:1.25rem}
.mt2{margin-top:2rem}
.mt25{margin-top:2.5rem}
.pad404{padding:6rem 1.35rem}

/* Contact address rendered as an image so it never appears as text in the
   HTML for scrapers to lift. Used as a mask rather than an <img> so a single
   asset inherits whatever colour surrounds it — muted in the footer, the page
   accent in body copy. Aspect ratio is 753/64 of the source PNG. */
.email-img{
  display:inline-block;
  height:1.08em;
  width:12.71em;
  max-width:100%;
  vertical-align:-.2em;
  background-color:currentColor;
  -webkit-mask:url(/assets/img/email.png?v=5a2ba6b0) no-repeat left center;
          mask:url(/assets/img/email.png?v=5a2ba6b0) no-repeat left center;
  -webkit-mask-size:contain;
          mask-size:contain;
}
/* On very narrow screens let it shrink rather than push the layout wide. */
@media (max-width:34rem){
  .email-img{height:.98em;width:11.53em}
}

/* "What they actually learned": a plain list rather than more panels, so it
   does not echo the three cards directly above it. Markers reuse the glowing
   dot motif from the wordmark and the drifting pellets. */
.skills{list-style:none;padding:0;margin:0;display:grid;gap:.95rem}
.skills li{position:relative;padding-left:1.6rem;max-width:58rem;
  color:#c3cbdd;font-size:clamp(1rem,2vw,1.1rem);line-height:1.65}
.skills li::before{content:"";position:absolute;left:.15rem;top:.62em;
  width:.45rem;height:.45rem;border-radius:50%;background:var(--accent);
  box-shadow:0 0 .55rem var(--accent)}

/* Character roster. Four across on desktop, two on a phone. Each figure gets a
   fixed image box so characters of slightly different proportions still sit on
   a common baseline. */
.roster{display:grid;gap:1rem;grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:52rem){.roster{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:34rem){.roster{grid-template-columns:repeat(2,minmax(0,1fr));gap:.7rem}}
.muncher{margin:0;padding:1rem .75rem .9rem;text-align:center;
  border:1px solid var(--line);border-radius:16px;background:var(--panel);
  transition:border-color .25s,background .25s,transform .25s}
.muncher:hover{border-color:var(--line-hi);background:var(--panel-hi);transform:translateY(-3px)}
.muncher img{display:block;width:100%;max-width:8.5rem;height:8.5rem;margin:0 auto .6rem;
  object-fit:contain;filter:drop-shadow(0 .5rem 1rem rgba(0,0,0,.45))}
.muncher figcaption{display:flex;flex-direction:column;gap:.25rem}
.muncher figcaption b{font-size:.98rem;font-weight:650;color:var(--ink)}
.muncher figcaption span{font:600 .62rem/1 var(--mono);letter-spacing:.11em;
  text-transform:uppercase;color:var(--accent);opacity:.85}
