/* ═══════════════════════════════════════════════════════════
   ShadowDemonHD · widget skin
   Every block is built like the stream widgets and pepeland.net:
   zinc-950 cards, a 1px white/10 ring, teal accents, Manrope.
   The drawn glass cube is the one illustrated object on the page.
   ═══════════════════════════════════════════════════════════ */

@font-face{
  font-family:"Unbounded";
  src:url("fonts/Unbounded-cyrillic.woff2") format("woff2");
  unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
  font-weight:400 800; font-display:swap;
}
@font-face{
  font-family:"Unbounded";
  src:url("fonts/Unbounded-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+2000-206F, U+2122, U+2212;
  font-weight:400 800; font-display:swap;
}

:root{
  /* reference sheet swatches */
  --cyan:#77F4FF;  --magenta:#C63ED3;
  --indigo:#392C6A; --lavender:#7B6ABF; --skin:#FDEBD3;
  --navy:#343471;  --deep:#20165F;
  --ink:#191723;   --ink-2:#242537; --slate:#364051;
  --gold:#BDA33F;  --gold-lt:#E2DC84;
  --dusk:#5C5A8F;  --peri:#7271BC;

  --page:#0D0A18;
  --paper:#EDE6F7;
  --display:"Unbounded", system-ui, sans-serif;
  --wrap:min(1080px, 100% - 48px);

  /* the side face every drawn object stands on */
  --side:var(--indigo);
  --ease-out:cubic-bezier(.16,1,.3,1);
  --spring:cubic-bezier(.34,1.56,.64,1);
}

@font-face{ font-family:"Manrope"; src:url("fonts/Manrope-cyrillic.woff2") format("woff2");
  unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; font-weight:200 800; font-display:swap; }
@font-face{ font-family:"Manrope"; src:url("fonts/Manrope-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+2000-206F, U+2122, U+2212; font-weight:200 800; font-display:swap; }

body{ background:var(--page); color:var(--paper); font-family:var(--text-font); }
:root{
  --text-font:"Manrope", system-ui, sans-serif;
  --teal:#00D5BE; --on-teal:#27272A;
  --w-bg:rgba(9,9,11,.84); --w-ring:rgba(255,255,255,.1); --w-soft:rgba(255,255,255,.04);
  --w-mute:#A1A1AA;
}
:root[data-theme="light"]{ --page:#E9E4F4; --paper:#191723; }

.sr-only{
  position:absolute !important; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; margin:-1px;
}

.top{ padding-left:max(20px, calc((100% - var(--wrap)) / 2)); }
.icon-btn{ border-radius:12px; background:var(--w-bg); box-shadow:inset 0 0 0 1px var(--w-ring); color:#fff; }

/* ───────── type ───────── */
.h2{
  font-family:var(--text-font); font-weight:800;
  font-size:clamp(1.6rem, 3.4vw, 2.3rem); line-height:1.1; letter-spacing:-.025em;
  color:#fff; margin:0;
}
.section-head{ display:block; text-align:left; justify-items:start; margin-bottom:22px; }
.section{ padding:clamp(56px, 9vh, 104px) 0 0; }

/* ───────── the widget card ───────── */
.plate{
  position:relative; overflow:hidden;
  border:1px solid var(--w-ring); border-radius:16px;
  background:var(--w-bg);
  box-shadow:0 24px 60px rgba(0,0,0,.4);
}
/* teal bar on the left edge, the widgets' "this one is active" mark */
.cast a::before, .ref-link::before{
  content:""; position:absolute; left:0; top:50%; width:3px; height:0;
  border-radius:0 3px 3px 0; background:var(--teal); translate:0 -50%;
  transition:height .4s var(--spring);
}
.cast a:hover::before, .cast a.is-hot::before, .cast a:focus-visible::before,
.ref-link:hover::before, .ref-link:focus-visible::before{ height:58%; }

/* ───────── hero ───────── */
.opening{ padding-top:clamp(18px, 4vh, 36px); }
.opening{ position:relative; }
.opening .art-bleed{ position:relative; margin:0; transform-origin:50% 100%; animation:plate-in 1.1s var(--ease-out) both .1s; }
/* the art has no frame: its edges dissolve into the page, and swirls.js keeps its line-drawn vortices going around it */
.opening .art-bleed img{
  width:100%; height:auto; display:block;
  -webkit-mask:linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent), linear-gradient(transparent, #000 12%, #000 88%, transparent);
  -webkit-mask-composite:source-in;
  mask:linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent), linear-gradient(transparent, #000 12%, #000 88%, transparent);
  mask-composite:intersect;
}
.art-swirls{
  /* starts at the art's own top, so nothing is drawn over the black hole above it */
  position:absolute; z-index:-1; left:50%; top:0; width:100vw; height:calc(100% + 14vh); translate:-50% 0;
  pointer-events:none; overflow:hidden; opacity:0; transition:opacity 1.6s ease .3s;
  -webkit-mask:linear-gradient(transparent, #000 10%, #000 80%, transparent);
  mask:linear-gradient(transparent, #000 10%, #000 80%, transparent);
}
@media (max-width:760px){
  .opening .art-bleed img{
    -webkit-mask:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent), linear-gradient(transparent, #000 9%, #000 91%, transparent);
    -webkit-mask-composite:source-in;
    mask:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent), linear-gradient(transparent, #000 9%, #000 91%, transparent);
    mask-composite:intersect;
  }
}
.art-swirls.on{ opacity:1; }
/* who is in the art and who drew it: just outside the art, under its bottom-right corner, with
   the artist centred under the names. It is still part of the figure, so it rides the art's
   own entrance and never drifts from it */
.art-credit{
  position:absolute; right:0; top:calc(100% + 18px); z-index:1; display:grid; justify-items:center; gap:4px;
  font-weight:700; font-size:.9rem; line-height:1.25; color:#D9DCFF; text-align:center;
  text-shadow:0 0 10px rgba(142,149,255,.55), 0 1px 3px rgba(0,0,0,.9);
}
.art-credit a{ color:#fff; text-decoration:none; transition:color .2s ease, text-shadow .2s ease; }
.art-credit a:hover, .art-credit a:focus-visible{ color:#B9BEF5; text-shadow:0 0 12px rgba(185,190,245,.9); }
.art-credit-by{ font-weight:600; font-size:.8rem; color:#A9AEE0; }
@media (max-width:760px){ .art-credit{ top:calc(100% + 10px); font-size:.78rem; } .art-credit-by{ font-size:.72rem; } }

.art-swirls path{ fill:none; stroke:#B9BEF5; stroke-linecap:round; }
.art-swirls .halos path{ stroke:#8E95FF; stroke-width:5; stroke-opacity:.13; }
.art-swirls .cores circle{ fill:url(#swirl-core); }
@keyframes plate-in{ from{ opacity:0; transform:translateY(28px) scale(.975); } }
.status{
  display:inline-flex; align-items:center; gap:10px; margin:18px 0 0;
  padding:9px 16px 9px 13px; border-radius:999px;
  background:var(--w-bg); box-shadow:inset 0 0 0 1px var(--w-ring);
  font-weight:700; font-size:.92rem; color:#fff;
}
.status .dot{ width:9px; height:9px; border:0; }

/* ───────── channels: list on the left, the cube on the right ───────── */
.channels{
  display:grid; gap:clamp(20px, 4vw, 48px);
  grid-template-columns:minmax(0, .9fr) minmax(0, 1.1fr);
  align-items:center;
}
@media (max-width:760px){ .channels{ grid-template-columns:1fr; } }

.cast{ display:grid; gap:10px; }
.cast a{
  position:relative; overflow:hidden;
  display:grid; grid-template-columns:auto 1fr; align-items:center; gap:14px;
  padding:12px 16px 12px 14px; border-radius:14px;
  background:var(--w-bg); box-shadow:inset 0 0 0 1px var(--w-ring);
  transition:transform .35s var(--spring), background-color .25s ease;
}
.cast a:hover, .cast a.is-hot, .cast a:focus-visible{ transform:translateX(4px); background:rgba(24,24,27,.92); }
.cast a:active{ transform:translateX(2px) scale(.99); transition-duration:.1s; }
.cast .glyph{
  position:relative; width:42px; height:42px; display:grid; place-items:center;
  border-radius:10px; box-shadow:inset 0 0 0 1px var(--w-ring);
}
.cast .glyph svg{ width:22px; height:22px; color:#fff; }
.cast .tw .glyph{ background:#9146FF; }
.cast .tg .glyph{ background:#2AABEE; }
.cast .da .glyph{ background:#F5A623; }
.cast .ds .glyph{ background:#5865F2; }
/* PepeLand's own app icon (the one in the widget) is already a tile: it fills the box */
.cast .ppl .glyph{ box-shadow:none; }
.cast .ppl .glyph svg{ width:42px; height:42px; }
.cast .txt{ display:grid; min-width:0; }
.cast .name{ font-weight:700; font-size:1rem; color:#fff; }

/* the cube stage */
.cube-scene{
  position:relative;
  aspect-ratio:1/1.02;
  display:grid; place-items:center;
  isolation:isolate;
}
.cube-scene::before{              /* light pool the cube hangs in */
  content:""; position:absolute; inset:6% 4% 14%;
  background:radial-gradient(closest-side, rgba(114,113,188,.30), transparent 72%);
  filter:blur(8px); z-index:-1;
}
.cube-shadow{
  position:absolute; left:50%; bottom:7%;
  width:54%; height:9%;
  translate:-50% 0;
  background:radial-gradient(closest-side, rgba(0,0,0,.72), transparent);
  z-index:-1;
}
.cube-rig{ width:100%; will-change:transform; }
/* the whole cube floats as one layer the GPU moves; nothing inside the SVG animates on
   its own, since that would repaint all of it every frame */
.cube-float{ animation:levitate 6.8s ease-in-out infinite; will-change:transform; }
.cube-svg{ width:100%; height:auto; display:block; overflow:visible; }

@keyframes levitate{ 0%,100%{ transform:translateY(-12px); } 50%{ transform:translateY(8px); } }

/* cubelet rig: drop in on load, lift on hover */
.cube-svg .cell .drop{ animation:cell-drop .9s var(--spring) both; animation-delay:calc(.3s + var(--i) * .045s); }
@keyframes cell-drop{ from{ transform:translateY(-130px); opacity:0; } 60%{ opacity:1; } }

.cube-svg .item{ transform-box:fill-box; transform-origin:50% 100%; transition:scale .5s var(--spring); }
.cube-svg .cell.is-full:hover .item,
.cube-svg .cell.is-full:focus-visible .item,
.cube-svg .cell.is-hot .item{ scale:1.12; }

.cube-svg .cell .lift{ transition:transform .55s var(--spring); }
.cube-svg .cell.is-full{ cursor:pointer; outline:none; }
.cube-svg .cell.is-full:hover .lift,
.cube-svg .cell.is-full:focus-visible .lift,
.cube-svg .cell.is-hot .lift{ transform:translateY(-16px); }
.cube-svg .glass-t, .cube-svg .spec, .cube-svg .glow{ transition:fill-opacity .35s ease, opacity .35s ease; }
.cube-svg .cell.is-full:hover .glass-t,
.cube-svg .cell.is-hot .glass-t{ fill-opacity:.22; }
.cube-svg .cell.is-full:hover .glow,
.cube-svg .cell.is-hot .glow{ opacity:1.6; }
.cube-svg .glow{ opacity:.85; }
.cube-svg .cell.is-full:focus-visible .glass-t{ stroke:var(--cyan); }

@media (prefers-reduced-motion: reduce){
  .cube-float, .cube-svg .cell .drop, .opening .art-bleed{ animation:none; }
}

/* ───────── arts ───────── */

.credit{ font-style:normal; color:var(--w-mute); }

/* ───────── PepeLand ───────── */
@keyframes hop{
  0%, 70%, 100%{ transform:translateY(0) scale(1,1); }
  74%{ transform:translateY(0) scale(1.14,.82); }
  82%{ transform:translateY(-9px) scale(.9,1.12); }
  90%{ transform:translateY(0) scale(1.1,.88); }
  95%{ transform:translateY(0) scale(.97,1.03); }
}
/* ───────── buttons ───────── */
.btn-drawn, .pw-btn{
  display:flex; align-items:center; justify-content:center; gap:10px;
  padding:13px 18px; border-radius:8px;
  font-family:var(--text-font); font-weight:700; font-size:.95rem; text-decoration:none;
  background:var(--teal); color:var(--on-teal);
  transition:filter .2s ease, transform .35s var(--spring);
}
.btn-drawn:hover, .pw-btn:hover{ filter:brightness(1.08); transform:translateY(-2px); }
.btn-drawn:active, .pw-btn:active{ transform:translateY(1px); transition-duration:.08s; }
.btn-drawn:focus-visible, .pw-btn:focus-visible{ outline:2px solid #fff; outline-offset:3px; }

/* ───────── artists ───────── */
.ref-link{
  display:grid; grid-template-columns:auto 1fr; gap:16px; align-items:center;
  padding:14px 16px 14px 14px;
  transition:transform .35s var(--spring), background-color .25s ease;
}
.ref-link:hover{ transform:translateX(4px); background:rgba(24,24,27,.92); }
.ref-link img{ width:96px; height:72px; object-fit:cover; border-radius:10px; box-shadow:0 0 0 1px var(--w-ring); }
.ref-link .name{ font-weight:700; color:#fff; }
.ref-link .sub{ color:var(--w-mute); font-size:.9rem; margin-top:4px; }
/* the other tabs: the same plates, each with a small picture of what's inside */
.tab-links{ display:grid; gap:12px; grid-template-columns:repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.thumb{
  position:relative; width:96px; height:72px; border-radius:10px; overflow:hidden; display:grid; place-items:center;
  background:#18181B; box-shadow:0 0 0 1px var(--w-ring);
}
/* an emoji on a square tinted to match it, as goood.pw marks its sections */
.thumb.emo{ background:rgba(var(--t), .14); box-shadow:inset 0 0 0 1px rgba(var(--t), .22); }
.ref-link .thumb.emo img{ width:46px; height:46px; object-fit:contain; border-radius:0; box-shadow:none; }

/* ───────── arts on a curved wall (assets/gallery.js) ─────────
   The stage bleeds to the screen edges and fades out there; panels stand on a cylinder
   around you, the front one lit, the others dimmed as they turn away. */
.curve{ position:relative; outline:none; }
.curve:focus-visible .panel.is-front{ box-shadow:0 0 0 2px var(--teal), 0 30px 80px rgba(0,0,0,.55); }
.curve-stage{
  position:relative; height:clamp(240px, 38vw, 470px);
  width:100vw; margin-left:calc(50% - 50vw); overflow:hidden;
  perspective:1100px; perspective-origin:50% 50%;
  touch-action:pan-y; cursor:grab; user-select:none; -webkit-user-select:none;
  -webkit-mask:linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
  mask:linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}
.curve-stage.dragging{ cursor:grabbing; }
.panel{
  position:absolute; left:50%; top:50%; margin:0;
  width:min(62vw, 640px); aspect-ratio:16 / 10;
  translate:-50% -50%; will-change:transform, opacity;
  border-radius:14px; overflow:hidden; background:var(--bg, #0B0D1C);
  box-shadow:0 0 0 1px rgba(255,255,255,.1), 0 30px 80px rgba(0,0,0,.55);
}
.panel img{ width:100%; height:100%; object-fit:cover; object-position:50% 30%; display:block; pointer-events:none; }
.panel.fit img{ object-fit:contain; }   /* arts on a light ground: the whole art, on its own edge colour (--bg) */
/* tall and square arts stand as posters: same height as the others, their own width */
.panel.poster{ width:auto; height:min(38.75vw, 400px); aspect-ratio:var(--ar); }
.panel.poster img{ object-fit:cover; object-position:50% 50%; }
.panel-shade{   /* gallery.js fades it in as the panel turns away */
  position:absolute; inset:0; pointer-events:none; opacity:0;
  background:linear-gradient(180deg, rgba(4,5,13,.25), rgba(4,5,13,.75));
}
.panel.is-front{ cursor:zoom-in; }
.curve-foot{ display:flex; align-items:center; justify-content:center; gap:14px; margin-top:18px; }
.curve-btn{
  width:40px; height:40px; display:grid; place-items:center; border:0; border-radius:12px; cursor:pointer;
  background:var(--w-bg); box-shadow:inset 0 0 0 1px var(--w-ring); color:#fff;
  transition:background-color .2s ease, transform .1s ease-out;
}
.curve-btn:hover{ background:#27272A; }
.curve-btn:active{ transform:scale(.92); }
.curve-count{ margin:0; min-width:74px; text-align:center; font:700 .95rem/1 var(--text-font); color:var(--w-mute); font-variant-numeric:tabular-nums; }
.curve-count b{ color:#fff; }
.curve .credit{ text-align:center; margin:12px 0 0; }
/* the artist's profile card under the carousel: avatar, name with a check, live Telegram subscribers */
/* the strip of artist cards: the current one in the middle, the others peek in at the sides */
.artists{ display:flex; align-items:center; justify-content:center; gap:10px; margin-top:16px; }
.artists-view{
  flex:0 1 640px; min-width:0; overflow:hidden; padding:4px 0; touch-action:pan-y;
  -webkit-mask:linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
  mask:linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
}
.artists-track{ display:flex; gap:14px; width:max-content; transition:transform .45s cubic-bezier(.2,.8,.2,1); }
.artists .artist{ margin:0; flex:none; transition:opacity .3s ease, transform .3s ease; }
.artists .artist:not(.is-current){ opacity:.35; transform:scale(.92); cursor:pointer; }
.artists-track.jump, .artists-track.jump .artist{ transition:none; }   /* gallery.js: the unseen jump back from a copy */
.curve-btn[hidden]{ display:none; }
.artists-dots{ display:flex; justify-content:center; gap:8px; margin-top:10px; }
.artists-dot{ width:8px; height:8px; padding:0; border:0; border-radius:50%; cursor:pointer; background:rgba(255,255,255,.28); transition:background-color .2s ease, width .25s ease; }
.artists-dot[aria-current="true"]{ width:22px; border-radius:4px; background:var(--teal); }
@media (max-width:560px){ .artists .curve-btn{ display:none; } .artists-view{ flex-basis:100%; } }   /* phones: swipe the strip or tap a side card */
.curve-stage.swap .panel{ animation:art-swap .35s ease; }
@keyframes art-swap{ from{ filter:brightness(.3); } }
.artist{
  display:flex; align-items:center; gap:14px; width:fit-content; max-width:100%; margin:16px auto 0;
  padding:10px 12px 10px 10px; border-radius:16px; background:var(--w-bg); box-shadow:inset 0 0 0 1px var(--w-ring);
}
.artist[hidden]{ display:none; }
.artist-av{
  flex:none; width:56px; height:56px; border-radius:50%; overflow:hidden; display:grid; place-items:center;
  background:linear-gradient(135deg, #7B6ABF, #C63ED3); box-shadow:0 0 0 2px #4FAEF0, 0 0 14px rgba(79,174,240,.45);
}
.artist-av img{ width:100%; height:100%; object-fit:cover; display:block; }
.artist-av.no-img img{ display:none; }
.artist-av.no-img::before{ content:attr(data-initial); color:#fff; font:800 1.4rem/1 var(--text-font); }
.artist-id{ display:grid; gap:3px; min-width:0; }
.artist-label{ font-weight:800; font-size:.66rem; letter-spacing:.12em; text-transform:uppercase; color:var(--teal); }
.artist-nick{ display:flex; align-items:center; gap:5px; color:#fff; text-decoration:none; font-size:1.02rem; font-weight:800; }
.artist-nick:hover b, .artist-nick:focus-visible b{ text-shadow:0 0 12px rgba(185,190,245,.9); }
.artist-ok{ flex:none; width:17px; height:17px; fill:#4FAEF0; filter:drop-shadow(0 1px 3px rgba(0,0,0,.6)); }
.artist-subs{ font-size:.8rem; color:var(--w-mute); font-variant-numeric:tabular-nums; white-space:nowrap; }
.artist-subs b{ color:#fff; font-weight:700; }
.artist-links{ display:flex; gap:8px; margin-left:6px; }
.artist-links a{
  width:36px; height:36px; display:grid; place-items:center; border-radius:11px; color:#fff;
  background:rgba(255,255,255,.06); box-shadow:inset 0 0 0 1px var(--w-ring);
  transition:background-color .2s ease, transform .1s ease-out;
}
.artist-links a:hover{ background:#27272A; }
.artist-links a:active{ transform:scale(.92); }
@media (max-width:420px){ .artist{ gap:10px; } .artist-av{ width:46px; height:46px; } .artist-links{ margin-left:0; flex-direction:column; gap:6px; } .artist-links a{ width:32px; height:32px; } }

/* ───────── tab pages: extensions, commands, games ───────── */
.cmds, .exts{ padding-top:clamp(20px, 4vh, 40px); }
.cmds + .cmds, .exts + .exts{ padding-top:clamp(36px, 6vh, 64px); }
.cmds-h{ font-size:clamp(1.15rem, 2.2vw, 1.4rem); margin:0 0 14px; }

/* commands, explained the goood.pw way: the command, then the exchange in chat */
.cmd-list{ display:grid; gap:14px; }
.cmd{
  display:grid; gap:12px; padding:16px 18px; border-radius:14px; scroll-margin-top:90px;
  background:rgba(24,24,27,.86); box-shadow:inset 0 0 0 1px var(--w-ring);
}
.cmd:target{ box-shadow:inset 0 0 0 1px var(--teal); }
.cmd-head{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.cmd-name{ margin:0; font:800 1.05rem/1.2 var(--text-font); color:#fff; }
.cmd-title{ font:500 1.05rem/1.2 var(--text-font); color:#D4D4D8; }
.cmd-tag{ align-self:center; padding:4px 8px; border-radius:999px; font:700 .7rem/1 var(--text-font); background:rgba(0,213,190,.12); color:var(--teal); }
.cmd-bot{ margin-left:auto; font:500 .9rem/1.2 var(--text-font); color:#A1A1AA; }
/* Twitch's own chat, as it draws it: Inter 13/20, #18181B, 18px badges, 28px emotes,
   the reply line above the answer, links in Twitch purple */
@font-face{ font-family:"Inter"; src:url("fonts/Inter-cyrillic.woff2") format("woff2");
  unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; font-weight:400 700; font-display:swap; }
@font-face{ font-family:"Inter"; src:url("fonts/Inter-latin.woff2") format("woff2");
  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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  font-weight:400 700; font-display:swap; }
.tw-chat{
  padding:5px 0; border-radius:6px; background:#18181B; box-shadow:inset 0 0 0 1px #2F2F35;
  font:400 13px/20px Inter, Roobert, "Helvetica Neue", Helvetica, Arial, sans-serif; color:#EFEFF1;
  -webkit-font-smoothing:antialiased;
}
.tw-msg{ padding:5px 20px; overflow-wrap:anywhere; }
.tw-msg:hover{ background:rgba(83,83,95,.24); }
.tw-msg .tb{ display:inline-block; width:18px; height:18px; margin:-1px 3px 1px 0; vertical-align:middle; }
.tw-msg .who{ font-weight:700; }
.tw-msg .emote{ display:inline-block; height:28px; width:auto; margin:-5px 0; vertical-align:middle; }
.tw-msg a{ color:#BF94FF; }
.tw-msg a:hover{ text-decoration:underline; }
.tw-msg .ph{ color:#ADADB8; }
.tw-reply{ display:flex; align-items:center; gap:4px; margin-bottom:2px; font-size:12px; line-height:16px; color:#ADADB8; }
.tw-reply span{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rp-ic{ width:16px; height:16px; flex:none; }
.var{ display:inline-block; padding:1px 7px; border-radius:6px; background:rgba(119,244,255,.12); color:#77F4FF; font-weight:700; font-size:.85em; }

/* extensions */
.exts-lead{ margin:0 0 22px; font-size:1.02rem; line-height:1.55; color:#D4D4D8; max-width:60ch; }
.ext-list{ display:grid; gap:12px; }
.ext{
  display:grid; grid-template-columns:56px minmax(0, 1fr); gap:16px; padding:16px; border-radius:16px;
  background:var(--w-bg); box-shadow:inset 0 0 0 1px var(--w-ring);
}
.ext-logo{
  width:56px; height:56px; padding:9px; box-sizing:border-box; border-radius:14px; object-fit:contain;
  background:#18181B; box-shadow:inset 0 0 0 1px var(--w-ring);
}
.ext-body{ display:grid; gap:8px; }
.ext-name{ margin:0; font:800 1.1rem/1.2 var(--text-font); }
.ext-name a{ color:#fff; }
.ext-name a:hover{ color:var(--teal); }
.ext-desc{ margin:0; color:#D4D4D8; font-size:.93rem; line-height:1.55; max-width:70ch; }
.ext-get{ display:flex; flex-wrap:wrap; gap:8px; margin-top:4px; }
.ext-get a{
  padding:8px 12px; border-radius:10px; font:700 .82rem/1.2 var(--text-font); color:#fff;
  background:rgba(255,255,255,.05); box-shadow:inset 0 0 0 1px var(--w-ring); transition:background-color .15s ease;
}
.ext-get a:hover, .ext-get a:focus-visible{ background:#27272A; }

/* games: covers like a game library, best rated first; the bar's colour runs from
   teal at 10 toward violet as the score drops */
.games-sec{ padding-top:clamp(12px, 2vh, 24px); }
.games{ list-style:none; margin:0; padding:0; display:grid; gap:24px 18px; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); }
.game{ display:grid; gap:10px; align-content:start; }
.game img{
  width:100%; height:auto; aspect-ratio:2 / 3; object-fit:cover; display:block; border-radius:12px;
  box-shadow:0 0 0 1px rgba(255,255,255,.1), 0 18px 40px rgba(0,0,0,.45);
  transition:transform .35s var(--spring), box-shadow .35s ease;
}
.game:hover img{ transform:translateY(-6px) scale(1.02); box-shadow:0 0 0 1px rgba(119,244,255,.5), 0 26px 50px rgba(0,0,0,.55), 0 0 32px rgba(0,213,190,.22); }
.game-name{ margin:0; font:800 .98rem/1.25 var(--text-font); color:#fff; }
.game-score{ margin:0; display:flex; align-items:center; gap:10px; font:700 .85rem/1 var(--text-font); color:var(--w-mute); }
.game-score b{ color:#fff; font-size:1.05rem; }
.game-bar{
  --hue:calc(172 + (10 - var(--score)) * 22);
  flex:1; height:6px; position:relative; background:rgba(255,255,255,.12);
  -webkit-mask:repeating-linear-gradient(90deg, #000 0 calc(10% - 2px), transparent calc(10% - 2px) 10%);
  mask:repeating-linear-gradient(90deg, #000 0 calc(10% - 2px), transparent calc(10% - 2px) 10%);
}
.game-bar::before{ content:""; position:absolute; inset:0 auto 0 0; width:calc(var(--score) * 10%); background:hsl(var(--hue) 85% 58%); }
@media (prefers-reduced-motion: reduce){ .game img{ transition:none; } .game:hover img{ transform:none; } }

/* footer laid out like pepeland.net's: a full-width band, brand and status on top,
   the site's pages on the left, channels with their icons on the right, small print */
.foot{
  width:auto; display:block; position:relative; z-index:1;
  margin-top:clamp(72px, 12vh, 140px); padding:24px 0 28px;
  border-top:1px solid rgba(255,255,255,.08); background:rgba(9,9,11,.78); color:#E4E4E7;
}
.foot-in{ width:var(--wrap); margin:0 auto; display:grid; gap:12px; }
.foot-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; }
.foot-brand{ display:flex; align-items:center; gap:12px; font-size:.9rem; color:#fff; }
.foot-brand img{ width:28px; height:28px; display:block; }
.foot .status{ margin:0; padding:6px 12px 6px 10px; font-size:.8rem; }
.foot-links{ align-items:flex-start; margin:0 -8px; }
.foot-pages, .foot-social{ display:flex; flex-wrap:wrap; }
.foot-pages a, .foot-social a{
  padding:8px; border-radius:8px; font-size:.875rem; color:#E4E4E7;
  transition:background-color .15s ease;
}
.foot-social a{ display:flex; align-items:center; gap:6px; font-weight:600; }
.foot-social svg{ flex:none; }
.foot-pages a:hover, .foot-social a:hover, .foot-pages a:focus-visible, .foot-social a:focus-visible{ background:#27272A; color:#fff; }
.foot-small{ margin:6px 0 0; font-size:.75rem; color:#A1A1AA; }
@media (max-width:760px){ .foot-links{ flex-direction:column; } .foot-social{ order:-1; } }

/* retire the old generic motion and chrome from app.css on this page */

[data-tilt]{ transform:none !important; }
[data-tilt]::after{ display:none !important; }

/* backdrop: one painted space sky behind the whole page */

@keyframes badge-bob{ 0%, 60%, 100%{ transform:translateY(0); } 70%{ transform:translateY(-4px); } 80%{ transform:translateY(0); } }
.lb-cap:empty{ display:none; }

/* light theme: widgets stay dark like on stream, only the page-level type flips */
:root[data-theme="light"] .h2{ color:#191723; }
:root[data-theme="light"] .credit, :root[data-theme="light"] .foot{ color:rgba(25,23,35,.6); }

/* ───────── ray field, from pepeland.net: a colour ramp drifting through their wave mask ───────── */
.rays{ position:absolute; inset:0; z-index:1; overflow:hidden; opacity:.82; container-type:size; pointer-events:none; }
.ray-mask{
  position:absolute; inset:0; background:var(--ray);
  -webkit-mask:url("ray-wave.webp") 0 50% / 533.333cqh 200cqh repeat-x;
          mask:url("ray-wave.webp") 0 50% / 533.333cqh 200cqh repeat-x;
  animation:ray-drift 9s linear infinite; animation-delay:var(--ray-delay, 0s);
}
@keyframes ray-drift{ to{ -webkit-mask-position:-533.333cqh 50%; mask-position:-533.333cqh 50%; } }
/* on the badges the ray colour is flat, so the masked layer itself can slide (one tile wider,
   moved by the GPU) instead of repainting the mask every frame; it looks the same */
.pw-btile .ray-mask{ right:auto; width:calc(100% + 533.333cqh); animation-name:ray-slide; will-change:transform; }
@keyframes ray-slide{ to{ transform:translateX(-533.333cqh); } }

/* endless loops pause while their block is off screen (app.js marks it .idle) */
.idle :is(.dot, .cube, .cube-shadow, .cube-float, .ray-mask, .pw-parade, .pw-step, .pw-bicon,
  .px-chest-a *, .px-chest-b *, .pp-x, .pp-y, .pp-flip, .diamond, .spark i, .cubo-crown img, .ring, .fr-track),
.idle .scroll-cue::after{ animation-play-state:paused !important; }

/* ───────── PepeLand card ───────── */
.pw{
  position:relative; isolation:isolate; overflow:hidden;
  display:grid; gap:14px; padding:18px 20px 20px;
  border-radius:16px; background:rgba(9,9,11,.9);
  box-shadow:inset 0 0 0 1px var(--w-ring), 0 24px 60px rgba(0,0,0,.45);
  color:#fff;
}
/* white pepes walking from the top left corner to the bottom right */
.pw-parade{
  position:absolute; z-index:-1; inset:-160px 0 0 -160px; pointer-events:none;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160' shape-rendering='crispEdges'%3E%3Cg fill='%23fff'%3E%3Cpath transform='translate(14 18) scale(.1)' d='M0 288H336v-48h48v-96h48V48h-48V0h-96v48h-48V0H144v48H96v48H48v96H0ZM0 288H336v48H0Z'/%3E%3Cpath transform='translate(94 98) scale(.1)' d='M0 288H336v-48h48v-96h48V48h-48V0h-96v48h-48V0H144v48H96v48H48v96H0ZM0 288H336v48H0Z'/%3E%3C/g%3E%3C/svg%3E") 0 0 / 160px 160px;
  opacity:.05;
  animation:parade 16s linear infinite;
}
@keyframes parade{ to{ transform:translate(160px, 160px); } }

.pw-top{ display:flex; align-items:center; justify-content:space-between; gap:12px; }
.pw-kicker{ display:flex; align-items:center; gap:10px; font-weight:700; font-size:.98rem; }

.pw-hero{ position:relative; }
.pw-hero::before{ content:""; position:absolute; left:-20px; top:22%; width:3px; height:56%; border-radius:0 3px 3px 0; background:var(--teal); }
.pw-paint{
  position:relative; isolation:isolate; overflow:hidden;
  display:grid; place-items:center; min-height:clamp(96px, 16vw, 124px); padding:16px;
  border-radius:12px; background:var(--bg);
  box-shadow:inset 0 0 0 1px var(--w-ring);
}
.pw-paint::after{ content:""; position:absolute; inset:4px; border-radius:9px; box-shadow:inset 0 0 0 2px rgba(255,255,255,.18); pointer-events:none; z-index:3; }
.pw-nickline{ position:relative; z-index:2; display:flex; align-items:center; gap:.45em; font-family:"Minecraft", monospace; font-size:clamp(1.15rem, 3.2vw, 1.8rem); line-height:1.1; }
.pw-badges{ display:flex; gap:.12em; }
.pw-pb{ width:1.05em; height:1.05em; }
.pw-nick{ white-space:nowrap; text-shadow:.08em .08em 0 rgba(0,0,0,.35); }

.pw-panel{ margin:0; padding:14px 16px; border-radius:12px; background:var(--w-soft); box-shadow:inset 0 0 0 1px var(--w-ring); display:grid; gap:10px; align-content:start; }
.pw-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; }
.pw-label{ margin:0; font-weight:800; font-size:.72rem; letter-spacing:.12em; text-transform:uppercase; color:var(--teal); }
.pw-count{ font-weight:700; font-size:.85rem; }
.pw-meta{ margin:0; font-size:.84rem; color:var(--w-mute); }

/* season tracker: five phases on a line, like on pepeland.net */
.pw-steps{
  position:relative; list-style:none; margin:4px 0 2px; padding:0;
  display:grid; grid-template-columns:repeat(5, 1fr); justify-items:center;
}
.pw-steps::before, .pw-steps::after{ content:""; position:absolute; left:0; top:50%; height:2px; translate:0 -50%; border-radius:2px; }
.pw-steps::before{ right:0; background:rgba(255,255,255,.14); }
.pw-steps::after{
  width:calc((var(--step) * 2 - 1) * 10%);
  background:linear-gradient(to right, transparent, var(--now, #EF4444));
  transition:width .8s var(--ease-out);
}
.pw-tracker:has(.pw-step:nth-child(1).is-now){ --now:#EF4444; }
.pw-tracker:has(.pw-step:nth-child(2).is-now){ --now:#F97316; }
.pw-tracker:has(.pw-step:nth-child(3).is-now){ --now:#EAB308; }
.pw-tracker:has(.pw-step:nth-child(4).is-now){ --now:#22C55E; }
.pw-tracker:has(.pw-step:nth-child(5).is-now){ --now:#00D5BE; }
.pw-step{
  position:relative; z-index:1; width:20px; height:20px; border-radius:50%;
  background:#27272A; box-shadow:inset 0 0 0 2px rgba(255,255,255,.1);
}
.pw-step.is-done{ background:var(--c); box-shadow:none; opacity:.55; }
.pw-step.is-now{ background:var(--c); box-shadow:0 0 0 4px color-mix(in srgb, var(--c) 30%, transparent); animation:step-pulse 2.4s ease-out infinite; }
@keyframes step-pulse{
  0%{ box-shadow:0 0 0 4px color-mix(in srgb, var(--c) 35%, transparent), 0 0 0 4px color-mix(in srgb, var(--c) 40%, transparent); }
  100%{ box-shadow:0 0 0 4px color-mix(in srgb, var(--c) 35%, transparent), 0 0 0 14px transparent; }
}
.pw-phase{ margin:2px 0 0; font-weight:800; font-size:1.3rem; letter-spacing:-.02em; }
.pw-desc{ margin:0; font-size:.9rem; line-height:1.55; color:#D4D4D8; max-width:68ch; }

/* badges: the same rectangular tiles as the appearance page */
.pw-badge-grid{ list-style:none; margin:0; padding:0; display:grid; grid-template-columns:repeat(4, minmax(0, 1fr)); gap:12px; }
.pw-badge{ display:grid; gap:8px; min-width:0; }
.pw-btile{
  position:relative; isolation:isolate; overflow:hidden;
  display:grid; place-items:center; aspect-ratio:1.44; border-radius:14px;
  background:var(--bg); box-shadow:inset 0 0 0 1px var(--w-ring);
  transition:transform .4s var(--spring);
}
.pw-btile::after{ content:""; position:absolute; inset:4px; border-radius:10px; box-shadow:inset 0 0 0 2px rgba(255,255,255,.14); z-index:3; pointer-events:none; }
.pw-bicon{ position:relative; z-index:2; width:52%; height:auto; transition:transform .45s var(--spring); }
.pw-badge:nth-child(1) .pw-bicon{ animation:badge-bob 3.6s var(--ease-out) infinite; }
.pw-badge:nth-child(2) .pw-bicon{ animation:badge-bob 3.6s var(--ease-out) infinite .25s; }
.pw-badge:nth-child(3) .pw-bicon{ animation:badge-bob 3.6s var(--ease-out) infinite .5s; }
.pw-badge:nth-child(4) .pw-bicon{ animation:badge-bob 3.6s var(--ease-out) infinite .75s; }
.pw-badge:hover .pw-btile{ transform:translateY(-3px); }
.pw-badge:hover .pw-bicon{ transform:scale(1.12); }
.pw-badge:hover .ray-mask, .pw-paint:hover .ray-mask{ animation-duration:4s; }
.pw-badge-name{ font-weight:600; font-size:.84rem; line-height:1.25; }

.pw-stats{ display:grid; gap:14px; }
.pw-big{ display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; }
.pw-big .unit{ display:flex; align-items:baseline; gap:5px; }
.pw .pw-big b{ font-weight:800; font-size:clamp(1.8rem, 4.4vw, 2.4rem); line-height:1; font-variant-numeric:tabular-nums; }
.pw-big .unit span{ font-size:.85rem; color:var(--w-mute); }

@media (max-width:640px){
  .pw{ padding:16px; }
  .pw-hero::before{ left:-16px; }
  .pw-badge-grid{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce){
  .pw-parade, .pw-bicon, .ray-mask, .pw-step.is-now{ animation:none !important; }
}

/* ───────── header: the static PepeLand logo ───────── */
.pw-logo{ width:34px; height:34px; flex:none; display:block; }

/* ───────── chest run, pixel art (sprites from tools/build_sprites.py, drawn 2x) ─────────
   Pepe opens the chest, takes out a diamond, carries it over his head to the ender chest
   and puts it in. The scene runs from the title to the card's edge. One 10s loop. */
.pw-top{ gap:18px; align-items:flex-end; }
.pw-top .pw-kicker{ align-self:center; }
.pw-scene{ position:relative; flex:1; min-width:0; height:66px; container-type:inline-size; }
.pw-scene img{ image-rendering:pixelated; }
.px-chest{ position:absolute; bottom:0; width:50px; height:66px; }
.px-chest img{ position:absolute; inset:0; width:100%; height:100%; }
.px-chest-a{ left:0; transform:scaleX(-1); }   /* mirrored so its latch faces pepe */
.px-chest-b{ right:0; }
.px-chest .open{ opacity:0; }
.px-chest-a .open{ animation:open-a 10s infinite steps(1, end); }
.px-chest-a .shut{ animation:shut-a 10s infinite steps(1, end); }
.px-chest-b .open{ animation:open-b 10s infinite steps(1, end); }
.px-chest-b .shut{ animation:shut-b 10s infinite steps(1, end); }
@keyframes open-a{ 0%{ opacity:0; } 5%{ opacity:1; } 15%{ opacity:0; } }
@keyframes shut-a{ 0%{ opacity:1; } 5%{ opacity:0; } 15%{ opacity:1; } }
@keyframes open-b{ 0%{ opacity:0; } 54%{ opacity:1; } 64%{ opacity:0; } }
@keyframes shut-b{ 0%{ opacity:1; } 54%{ opacity:0; } 64%{ opacity:1; } }
/* light spilling out of the open chest */
.px-glow{ position:absolute; left:14px; right:14px; top:26px; height:14px; border-radius:50%; opacity:0; filter:blur(5px); mix-blend-mode:screen; }
.px-chest-a .px-glow{ background:#FFD27A; animation:glow-a 10s infinite; }
.px-chest-b .px-glow{ background:#B45CFF; animation:glow-b 10s infinite; }
@keyframes glow-a{ 0%, 5%{ opacity:0; } 7%, 13%{ opacity:.85; } 15%, 100%{ opacity:0; } }
@keyframes glow-b{ 0%, 54%{ opacity:0; } 56%, 62%{ opacity:.85; } 64%, 100%{ opacity:0; } }

.pp-x{ position:absolute; left:0; bottom:2px; width:30px; animation:pp-x 10s linear infinite; }
@keyframes pp-x{ 0%{ transform:translateX(54px); } 18%{ transform:translateX(54px); } 50%{ transform:translateX(calc(100cqw - 84px)); } 70%{ transform:translateX(calc(100cqw - 84px)); } 96%{ transform:translateX(54px); } 100%{ transform:translateX(54px); } }
.pp-y{ position:relative; display:block; animation:pp-y 10s infinite ease-in-out; }
@keyframes pp-y{ 0.00%{ transform:translateY(0px); } 1.50%{ transform:translateY(0px); } 2.50%{ transform:translateY(-3px); } 3.50%{ transform:translateY(0px); } 18.00%{ transform:translateY(0px); } 20.00%{ transform:translateY(-6px); } 22.00%{ transform:translateY(0px); } 22.00%{ transform:translateY(0px); } 24.00%{ transform:translateY(-6px); } 26.00%{ transform:translateY(0px); } 26.00%{ transform:translateY(0px); } 28.00%{ transform:translateY(-6px); } 30.00%{ transform:translateY(0px); } 30.00%{ transform:translateY(0px); } 32.00%{ transform:translateY(-6px); } 34.00%{ transform:translateY(0px); } 34.00%{ transform:translateY(0px); } 36.00%{ transform:translateY(-6px); } 38.00%{ transform:translateY(0px); } 38.00%{ transform:translateY(0px); } 40.00%{ transform:translateY(-6px); } 42.00%{ transform:translateY(0px); } 42.00%{ transform:translateY(0px); } 44.00%{ transform:translateY(-6px); } 46.00%{ transform:translateY(0px); } 46.00%{ transform:translateY(0px); } 48.00%{ transform:translateY(-6px); } 50.00%{ transform:translateY(0px); } 50.50%{ transform:translateY(0px); } 51.50%{ transform:translateY(-3px); } 52.50%{ transform:translateY(0px); } 70.00%{ transform:translateY(0px); } 71.86%{ transform:translateY(-6px); } 73.71%{ transform:translateY(0px); } 73.71%{ transform:translateY(0px); } 75.57%{ transform:translateY(-6px); } 77.43%{ transform:translateY(0px); } 77.43%{ transform:translateY(0px); } 79.29%{ transform:translateY(-6px); } 81.14%{ transform:translateY(0px); } 81.14%{ transform:translateY(0px); } 83.00%{ transform:translateY(-6px); } 84.86%{ transform:translateY(0px); } 84.86%{ transform:translateY(0px); } 86.71%{ transform:translateY(-6px); } 88.57%{ transform:translateY(0px); } 88.57%{ transform:translateY(0px); } 90.43%{ transform:translateY(-6px); } 92.29%{ transform:translateY(0px); } 92.29%{ transform:translateY(0px); } 94.14%{ transform:translateY(-6px); } 96.00%{ transform:translateY(0px); } 100.00%{ transform:translateY(0px); } }
.pp-flip{ display:block; width:30px; height:auto; animation:pp-flip 10s infinite steps(1, end); }
@keyframes pp-flip{ 0%{ transform:scaleX(-1); } 17%{ transform:scaleX(1); } 68%{ transform:scaleX(-1); } }
.pp-shadow{ position:absolute; left:5px; right:5px; bottom:-2px; height:3px; background:#000; opacity:.3; border-radius:50%; }

/* the diamond rides in pepe's hop group, so it bobs with him while carried */
.diamond{ position:absolute; left:7px; bottom:25px; width:16px; height:16px; opacity:0; animation:carry 10s infinite; }
@keyframes carry{
  0%, 6%{ opacity:0; transform:translate(-44px, 4px); }
  8%{ opacity:1; transform:translate(-44px, -12px); }
  14%, 53%{ opacity:1; transform:translate(0, 0); }
  57%{ opacity:1; transform:translate(44px, -12px); }
  59%, 100%{ opacity:0; transform:translate(44px, 4px); }
}
.spark{ position:absolute; right:14px; bottom:30px; width:22px; height:16px; pointer-events:none; }
.spark i{ position:absolute; bottom:0; width:3px; height:3px; background:#C77DFF; opacity:0; animation:spark 10s infinite; }
.spark i:nth-child(1){ left:2px; } .spark i:nth-child(2){ left:10px; animation-delay:.2s; } .spark i:nth-child(3){ left:18px; animation-delay:.4s; }
@keyframes spark{ 0%, 57%{ opacity:0; transform:translate(0, 0); } 59%{ opacity:1; } 68%{ opacity:0; transform:translate(3px, -18px); } 100%{ opacity:0; } }

@media (prefers-reduced-motion: reduce){
  .pp-x, .pp-y, .pp-flip, .px-chest img, .px-glow, .diamond, .spark i{ animation:none !important; }
}

/* ───────── Cuboserver: where I worked before, in the same widget card ─────────
   Their pixel crown and wordmark from cuboserver.net, their yellow as the accent. */
.cubo-section{ padding-top:18px; }
.pw.cubo{
  --cubo:#FEBF02;
  display:flex; align-items:center; gap:18px; padding:16px 20px 16px 16px;
  text-decoration:none; color:#fff;
  transition:transform .35s var(--spring), background-color .25s ease;
}
.pw.cubo::before{
  content:""; position:absolute; left:0; top:50%; width:3px; height:0; translate:0 -50%;
  border-radius:0 3px 3px 0; background:var(--cubo); transition:height .4s var(--spring);
}
.pw.cubo:hover, .pw.cubo:focus-visible{ transform:translateX(4px); background:rgba(24,24,27,.94); }
.pw.cubo:hover::before, .pw.cubo:focus-visible::before{ height:58%; }
.pw.cubo:focus-visible{ outline:2px solid var(--cubo); outline-offset:3px; }
.cubo-crown{
  flex:none; width:64px; height:64px; display:grid; place-items:center;
  border-radius:12px; background:radial-gradient(closest-side, rgba(254,191,2,.22), transparent), #141416;
  box-shadow:inset 0 0 0 1px var(--w-ring);
}
.cubo-crown img{ width:44px; height:44px; image-rendering:pixelated; animation:crown-bob 3.8s var(--ease-out) infinite; }
@keyframes crown-bob{ 0%, 70%, 100%{ transform:translateY(0); } 78%{ transform:translateY(-5px) rotate(-4deg); } 86%{ transform:translateY(0) rotate(2deg); } 92%{ transform:rotate(0); } }
.cubo-txt{ display:grid; gap:4px; min-width:0; flex:1; }
.cubo-name{ font-weight:800; font-size:1.3rem; letter-spacing:-.01em; color:#fff; }
.cubo-role{ font-weight:700; font-size:1.02rem; color:#fff; }
.cubo-tag{
  flex:none; padding:6px 12px; border-radius:999px;
  background:rgba(254,191,2,.14); color:var(--cubo); font-weight:700; font-size:.82rem;
  box-shadow:inset 0 0 0 1px rgba(254,191,2,.3);
}
@media (max-width:520px){ .pw.cubo{ gap:12px; align-items:flex-start; } .cubo-crown{ width:52px; height:52px; } .cubo-crown img{ width:36px; height:36px; } .cubo-tag{ padding:4px 9px; font-size:.74rem; } .cubo-name{ font-size:1.1rem; } .cubo-role{ font-size:.92rem; } }
@media (prefers-reduced-motion: reduce){ .cubo-crown img{ animation:none; } }
/* GitHub: the same card under Cuboserver, in GitHub's own greys */
.pw.cubo + .pw.cubo{ margin-top:12px; }
.pw.cubo.gh{ --cubo:#fff; }
.gh .cubo-crown{ color:#fff; background:radial-gradient(closest-side, rgba(255,255,255,.24), transparent), #141416; }
.gh .cubo-crown svg{ filter:drop-shadow(0 0 6px rgba(255,255,255,.45)); }
.gh .cubo-tag{ background:rgba(255,255,255,.1); box-shadow:inset 0 0 0 1px rgba(255,255,255,.3); }
@media (max-width:520px){ .gh .cubo-crown svg{ width:32px; height:32px; } }

/* ───────── the cosmos backdrop, in the spirit of the Mornye banner ─────────
   Deep blue-black space, a periwinkle haze from the left, slow orbit rings like an
   astrolabe, a black hole, electric-blue glitch blocks.
   Stars, glints and shooting stars are drawn by assets/cosmos.js. */
body{ background:#04050D; }
.cosmos{
  position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden;
  background:radial-gradient(120% 90% at 55% 40%, #0B1030 0%, #060817 55%, #03040B 100%);
}
.cosmos-stars{ position:absolute; left:0; top:0; width:100%; height:200%; will-change:transform; }   /* two screens: cosmos.js slides it with the scroll */
/* the stars are drawn once; two of the three layers breathe, which reads as twinkling */
.cosmos-stars.twinkle{ animation:twinkle 3.4s ease-in-out infinite alternate; }
.cosmos-stars.twinkle.b{ animation-duration:4.6s; animation-delay:-2.1s; }
@keyframes twinkle{ from{ opacity:.25; } to{ opacity:1; } }
.sparkle{
  position:absolute; width:calc(36px * var(--s, 1)); height:calc(36px * var(--s, 1)); translate:-50% -50%;
  background:
    linear-gradient(90deg, transparent, #fff 50%, transparent) center / 100% 1.6px no-repeat,
    linear-gradient(transparent, #fff 50%, transparent) center / 1.6px 100% no-repeat,
    radial-gradient(circle, #fff 0 1.4px, rgba(210,222,255,.35) 2.5px, transparent 6px);
  opacity:0; animation:sparkle 7s ease-in-out infinite;
}
@keyframes sparkle{ 0%, 70%, 100%{ opacity:0; transform:scale(.5); } 82%{ opacity:1; transform:scale(1); } }
.shooting{
  position:absolute; left:78%; top:8%; width:150px; height:1.6px; rotate:-29deg; transform-origin:0 50%;
  background:linear-gradient(90deg, #fff, rgba(160,190,255,0)); opacity:0;
  animation:shoot 11s ease-in 3s infinite;
}
@keyframes shoot{
  0%{ opacity:0; translate:0 0; } 1%{ opacity:1; }
  9%{ opacity:0; translate:-620px 344px; } 100%{ opacity:0; translate:-620px 344px; }
}
@media (prefers-reduced-motion: reduce){ .cosmos-stars.twinkle, .sparkle, .shooting{ animation:none; } .shooting{ display:none; } }
.cosmos-haze{
  position:absolute; inset:0;
  background:
    radial-gradient(55% 75% at -8% 28%, rgba(176,192,255,.26), transparent 62%),
    radial-gradient(38% 50% at 108% 82%, rgba(36,76,255,.22), transparent 70%),
    radial-gradient(30% 30% at 72% 8%, rgba(126,96,255,.13), transparent 70%);
}
/* the dial and the hole share a stage that scrolls with the page: it sits in the first
   screen of the home page and above the footer (cosmos.js moves it between the two) */
.hole-stage{
  position:absolute; left:50%; top:0; width:100vw; height:100%; translate:-50% 0;
  z-index:-1; pointer-events:none;             }
.hero-bh{ --cy:42%; }
/* at the foot of every page the hole peeks up from the bottom edge, half of it, behind the
   content and the footer; the slot is pinned to the end of the page and clips the rest */
body{ position:relative; min-height:100vh; min-height:100svh; }   /* short pages too: the hole sits at the screen's bottom */
.hole-slot{
  position:absolute; left:0; right:0; bottom:0; height:80vh; overflow:hidden;
  z-index:1; pointer-events:none; --cy:100%;
}
.orrery{
  position:absolute; left:50%; top:var(--cy); width:min(140vmin, 1300px); aspect-ratio:1;
  translate:-50% -50%; overflow:visible; opacity:.85;
}
.hole-slot .orrery{ opacity:.6; }
/* the dial sweeps itself in on load like a radar hand: a conic mask opens each ring; the
   mask is there only for that (cosmos.js takes .sweeping off after), so the turning rings
   don't carry a mask for the rest of the visit */
@property --sweep{ syntax:'<angle>'; inherits:false; initial-value:360deg; }
.orrery.sweeping .ring{
  -webkit-mask:conic-gradient(#000 var(--sweep), transparent 0);
  mask:conic-gradient(#000 var(--sweep), transparent 0);
}
@keyframes sweep-in{ from{ --sweep:0deg; } }
.orrery .line{ fill:none; stroke:#E4EAFF; stroke-width:1.2; vector-effect:non-scaling-stroke; opacity:.75; }
/* neon: two wider, fainter blue copies under every line (added by cosmos.js) */
.orrery .halo{ stroke:#7C96FF; stroke-width:4; opacity:.32; }
.orrery .halo-wide{ stroke:#4A64FF; stroke-width:12; opacity:.12; }
.orrery .dash{ stroke-dasharray:2 10; }
.orrery .dash.halo, .orrery .dash.halo-wide{ stroke-dasharray:none; opacity:.05; }
.orrery .thick{ stroke:url(#arcGlow); stroke-width:3.2; opacity:1; }
.orrery .thick.halo{ stroke:#6F8CFF; stroke-width:8; opacity:.28; }
.orrery .thick.halo-wide{ stroke:#3350FF; stroke-width:20; opacity:.12; }
.orrery .faint{ opacity:.18; }
.orrery .faint.halo{ opacity:.06; } .orrery .faint.halo-wide{ opacity:0; }
.orrery .node{ fill:rgba(8,12,40,.85); stroke:#F2F5FF; stroke-width:2; vector-effect:non-scaling-stroke; }
.orrery .dot{ fill:#FFFFFF; }
.orrery .node-halo{ fill:url(#nodeGlow); }
.orrery .tick{ stroke:#C9D4FF; stroke-width:1; vector-effect:non-scaling-stroke; opacity:.6; }
.orrery .deg{ fill:#D5DEFF; font:600 13px/1 var(--text-font); text-anchor:middle; dominant-baseline:middle; letter-spacing:.12em; opacity:.7; }
.orrery .ring{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; will-change:transform; }
.ring-1{ animation:sweep-in 2.4s var(--ease-out) .15s backwards, orbit 260s linear infinite; }
.ring-2{ animation:sweep-in 2.4s var(--ease-out) .35s backwards, orbit 150s linear infinite reverse; }
.ring-3{ animation:sweep-in 2.4s var(--ease-out) .55s backwards, orbit 96s linear infinite; }
.ring-4{ animation:sweep-in 2.4s var(--ease-out) backwards, orbit 420s linear infinite reverse; }
@keyframes orbit{ to{ transform:rotate(360deg); } }

/* the black hole is ray traced by cosmos.js, which also sizes and moves this canvas; it
   fades in only once its first frame has checked out */
.blackhole{ position:absolute; left:50%; top:var(--cy); translate:-50% -50%; rotate:-3deg; opacity:0; transition:opacity 1.4s ease .1s; }
.blackhole.ready{ opacity:1; }
/* where the live hole won't run (weak graphics, no WebGL2), a still frame of it stands in;
   lazy, so a page with the live hole never downloads it */
.hole-still{ display:none; position:absolute; left:50%; top:var(--cy); width:115.4vmin; aspect-ratio:5 / 3; translate:-50% -50%; rotate:-3deg; }
.hole-stage.still .hole-still{ display:block; }
@media (max-width:760px){ .hole-still{ width:173vw; } }

/* ───────── lite: weak graphics (built-in Intel, software rendering, phones) ─────────
   cosmos.js sets html.lite; the dial, the cube and the PepeLand card keep moving (the GPU
   moves them as whole layers, or they're small), the full-screen extras stop */
.lite .cosmos-stars.twinkle, .lite .pw-step.is-now, .lite .glitch i, .lite .scroll-cue::after{ animation:none !important; }
.lite .sparkle, .lite .shooting{ display:none; }

/* glitch bursts: torn blocks, scrambled glyph lines */
.glitch-field i{ position:absolute; opacity:0; box-shadow:0 0 16px rgba(40,90,255,.55); mix-blend-mode:screen; }
.glyphs{
  position:absolute; white-space:pre; font:500 15px/1 ui-monospace, monospace; letter-spacing:.18em;
  color:#5CE1FF; opacity:.32; text-shadow:0 0 8px rgba(92,225,255,.6);
}
.glyphs.hot{ opacity:.85; color:#8CEBFF; transform:translateX(6px); }
.g1{ left:4vw; top:72vh; } .g2{ right:6vw; top:9vh; font-size:13px; } .g3{ right:10vw; bottom:12vh; font-size:12px; opacity:.24; }
@media (max-width:760px){ .glyphs{ display:none; } }

/* a heading tears: two colour-shifted copies slide apart in slices */
.h2{ position:relative; }
.h2.tear::before, .h2.tear::after, .hero-title.tear::before, .hero-title.tear::after{
  content:attr(data-text); position:absolute; inset:0; pointer-events:none; opacity:1;
  animation:tear .36s steps(4) both;
}
.h2.tear::before, .hero-title.tear::before{ color:#FF2A6D; clip-path:inset(12% 0 55% 0); transform:translateX(-6px); mix-blend-mode:screen; }
.h2.tear::after, .hero-title.tear::after{ color:#28DCFF; clip-path:inset(58% 0 8% 0); transform:translateX(7px); mix-blend-mode:screen; }
@keyframes tear{
  25%{ clip-path:inset(40% 0 30% 0); } 50%{ clip-path:inset(5% 0 75% 0); } 75%{ clip-path:inset(70% 0 4% 0); }
}

.glitch{ position:absolute; right:14vw; top:18vh; width:280px; height:130px; }
.glitch i{ position:absolute; height:10px; background:#1E4BFF; box-shadow:0 0 14px rgba(40,90,255,.6); opacity:0; animation:glitch 6s steps(1) infinite; }
.glitch i:nth-child(1){ left:0; top:0; width:120px; }
.glitch i:nth-child(2){ left:130px; top:0; width:40px; height:22px; animation-delay:.1s; }
.glitch i:nth-child(3){ left:40px; top:32px; width:190px; animation-delay:.2s; }
.glitch i:nth-child(4){ left:200px; top:48px; width:70px; height:16px; animation-delay:2.6s; }
.glitch i:nth-child(5){ left:10px; top:76px; width:60px; animation-delay:2.7s; }
.glitch i:nth-child(6){ left:90px; top:100px; width:150px; height:6px; animation-delay:2.8s; }
@keyframes glitch{
  0%, 100%{ opacity:0; transform:none; }
  3%{ opacity:.9; } 5%{ transform:translateX(16px); } 7%{ opacity:.45; transform:translateX(-6px); } 9%{ opacity:0; }
  48%{ opacity:.75; transform:translateX(-10px); } 50%{ opacity:0; }
}
@media (max-width:760px){
  .orrery{ width:150vmin; opacity:.45; }
  .hero-bh{ --cy:36%; }
  .glitch{ right:4vw; top:10vh; transform:scale(.7); transform-origin:right top; }
}
@media (prefers-reduced-motion: reduce){
  .orrery .ring, .blackhole, .glitch i{ animation:none !important; }
  .glitch-field, .glyphs{ display:none; }
}

/* ───────── first screen: the black hole and the name ─────────
   The name assembles out of torn slices on load, the way ALCHE's logo does. */
.hero-bh{
  position:relative; min-height:calc(100svh - 65px);
  display:grid; justify-items:center; align-content:end; gap:22px;
  padding-bottom:clamp(110px, 17vh, 180px); text-align:center;
}
.hero-title{
  position:relative; margin:0; color:#fff;
  font-family:var(--display); font-weight:700; line-height:1; letter-spacing:-.035em;
  font-size:clamp(2rem, 6.4vw, 6.2rem);
  text-shadow:0 0 48px rgba(104,124,255,.5);
  animation:title-in 1.4s steps(1) both .25s;
}
.hero-title::before, .hero-title::after{
  content:attr(data-text); position:absolute; inset:0; pointer-events:none;
  mix-blend-mode:screen; opacity:0; animation:split 1.4s steps(1) both .25s;
}
.hero-title::before{ color:#E040F0; }
.hero-title::after{ color:#77F4FF; animation-name:split-b; }
@keyframes title-in{
  0%{ opacity:0; }
  6%{ opacity:1; clip-path:inset(44% 0 40% 0); transform:translateX(-14px); }
  14%{ clip-path:inset(8% 0 72% 0); transform:translateX(9px); }
  22%{ clip-path:inset(62% 0 12% 0); transform:translateX(-5px); }
  32%{ clip-path:inset(0 0 46% 0); transform:translateX(3px); }
  44%{ clip-path:inset(28% 0 0 0); transform:none; }
  56%, 100%{ clip-path:inset(-60% -12%); transform:none; opacity:1; }   }
@keyframes split{
  0%{ opacity:0; } 8%{ opacity:1; clip-path:inset(20% 0 55% 0); transform:translateX(-10px); }
  20%{ clip-path:inset(60% 0 8% 0); transform:translateX(-5px); } 34%{ clip-path:inset(4% 0 80% 0); transform:translateX(-3px); }
  48%, 100%{ opacity:0; transform:none; }
}
@keyframes split-b{
  0%{ opacity:0; } 10%{ opacity:1; clip-path:inset(58% 0 14% 0); transform:translateX(11px); }
  24%{ clip-path:inset(10% 0 62% 0); transform:translateX(6px); } 38%{ clip-path:inset(40% 0 38% 0); transform:translateX(3px); }
  50%, 100%{ opacity:0; transform:none; }
}
.hero-bh .status{ margin:0; }
/* a thin line with a spark running down: there is more below */
.scroll-cue{
  position:absolute; left:50%; bottom:clamp(24px, 5vh, 44px); width:1px; height:56px; overflow:hidden;
  background:linear-gradient(rgba(228,234,255,0), rgba(228,234,255,.45));
}
.scroll-cue::after{
  content:""; position:absolute; left:-2px; top:0; width:5px; height:5px; border-radius:50%;
  background:#fff; box-shadow:0 0 10px #8FA6FF; animation:cue 2.2s var(--ease-out) infinite;
}
@keyframes cue{ from{ transform:translateY(-6px); opacity:0; } 30%{ opacity:1; } to{ transform:translateY(56px); opacity:0; } }
@media (prefers-reduced-motion: reduce){
  .hero-title, .hero-title::before, .hero-title::after, .scroll-cue::after{ animation:none; }
}
/* over the first screen the bar goes clear, so the scene runs up to the top edge */
.top{ transition:background-color .35s ease, border-color .35s ease; }
.at-top .top{ background:transparent; border-bottom-color:transparent; }

/* the header floats over an animated backdrop; a live backdrop blur would re-run every frame */
.top{ backdrop-filter:none; -webkit-backdrop-filter:none; background:rgba(5,6,16,.88); }

/* ───────── entrance: everything eases in instead of popping up ─────────
   Only opacity, translate and scale move, which the GPU does without repainting.
   The first screen plays once on load; blocks further down wait for reveal.js
   (home page only) to slide them up as they first scroll into view. */
/* the black hole grows out of the dark while it fades in (cosmos.js adds .ready on its first good frame) */
.blackhole{ scale:.8; transition:opacity 1.4s ease .1s, scale 2.8s var(--ease-out) .1s; }
.blackhole.ready{ scale:1; }
.hole-stage.still .hole-still{ animation:hole-in 2.2s var(--ease-out) both .1s; }
@keyframes hole-in{ from{ opacity:0; scale:.82; } }
body:has(.hero-bh) .top{ animation:drop-in .8s var(--ease-out) both .15s; }
.hero-bh .status{ animation:rise-in .9s var(--ease-out) both 1.1s; }
.hero-bh .scroll-cue{ animation:fade-in 1.2s ease both 1.8s; }
@keyframes drop-in{ from{ opacity:0; translate:0 -100%; } }
@keyframes rise-in{ from{ opacity:0; translate:0 18px; } }
@keyframes fade-in{ from{ opacity:0; } }
.rv{
  opacity:0; translate:0 40px; scale:.97; animation:none !important;
  transition:opacity .8s ease var(--rv-d, 0s), translate 1s var(--ease-out) var(--rv-d, 0s), scale 1s var(--ease-out) var(--rv-d, 0s) !important;
}
.rv.in{ opacity:1; translate:none; scale:none; }
/* weak graphics: a shorter slide, no scaling */
.lite .rv{ translate:0 20px; scale:none; }
@media (prefers-reduced-motion: reduce){
  .blackhole{ scale:none; transition:opacity .4s ease; }
  .hole-stage.still .hole-still, body:has(.hero-bh) .top, .hero-bh .status, .hero-bh .scroll-cue{ animation:none; }
}
