
:root{
  /* The site commits to dark: screenshots are the content and a bright ground
     competes with them. Declaring color-scheme makes that a decision rather than
     an omission -- without it the <select> and the scrollbars still render in the
     OS light theme against this palette. */
  color-scheme: dark;
  --bg:#0d0f13; --surface:#15181e; --surface-2:#1d212a; --border:#282d38;
  --border-2:#3a4150; --text:#e6e9ef; --text-2:#b8bfcc; --muted:#8b94a4;
  --accent:#5b8cff; --accent-dim:#16233f;
  /* The one destructive-looking control on the page. Pulled toward the logo's
     red but lifted off it, because #ee1b24 itself reads at 4.08:1 on a card. */
  --danger:#ff6b5a; --danger-dim:#2d1612;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0; background:var(--bg); color:var(--text);
  font-family:Archivo,"Helvetica Neue",Arial,sans-serif; font-size:16px; line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--accent); text-underline-offset:2px}
a:focus-visible,button:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:3px}
img{max-width:100%; height:auto; display:block}
/* The one place !important earns its keep. `hidden` is a plain attribute and the
   UA rule behind it is just [hidden]{display:none}, so any class on the same
   element that sets display beats it on source order and the element stays on
   screen with its attribute dutifully set. That is what kept the timeline legend
   visible -- and stale -- after a search narrowed to a single contributor. */
[hidden]{display:none !important}

.top{
  display:flex; align-items:center; justify-content:space-between; gap:20px;
  padding:16px 28px; border-bottom:1px solid var(--border);
  position:sticky; top:0; background:rgba(13,15,19,.92); backdrop-filter:blur(8px); z-index:20;
}
.brand{display:block; text-decoration:none; line-height:0}
/* The logo's blue sits at 2.2:1 on this ground, under the readable threshold.
   A faint light halo lifts it without altering the artwork itself. */
.brand img{height:40px; width:auto; filter:drop-shadow(0 0 1.5px rgba(255,255,255,.45))}
.top nav{display:flex; gap:20px; font-size:.92rem; flex:none}

/* ---- search ---- */
.search{position:relative; flex:1 1 420px; max-width:480px; min-width:150px}
.search input{
  width:100%; background:var(--surface); color:var(--text); font:inherit; font-size:.92rem;
  border:1px solid var(--border); border-radius:6px; padding:8px 30px 8px 12px;
}
.search input::placeholder{color:var(--muted)}
.search input:focus{outline:none; border-color:var(--accent); background:var(--surface-2)}
.search input::-webkit-search-cancel-button{display:none}
#qclear{
  position:absolute; right:6px; top:50%; transform:translateY(-50%); background:none;
  border:0; color:var(--muted); font-size:19px; line-height:1; cursor:pointer; padding:0 5px;
}
#qclear:hover{color:var(--text)}
.sugg{
  position:absolute; left:0; right:0; top:calc(100% + 6px); background:var(--surface);
  border:1px solid var(--border-2); border-radius:6px; z-index:40;
  box-shadow:0 10px 34px rgba(0,0,0,.5);
  max-height:min(60vh,420px); overflow-y:auto; overscroll-behavior:contain;
}
/* Sticky: the panel scrolls through every match now, and a group heading that
   scrolls away leaves you reading a list of unlabelled values. */
.sugg b{
  display:block; padding:5px 12px; background:var(--surface-2); color:var(--muted);
  font-family:"JetBrains Mono",monospace; font-size:10px; letter-spacing:.11em;
  text-transform:uppercase; font-weight:500;
  position:sticky; top:0; z-index:1;
}
.sugg button{
  display:flex; width:100%; gap:10px; align-items:baseline; justify-content:space-between;
  background:none; border:0; color:var(--text-2); font:inherit; font-size:.88rem;
  padding:7px 12px; text-align:left; cursor:pointer;
}
.sugg button:hover,.sugg button[aria-selected="true"]{background:var(--accent-dim); color:var(--text)}
.sugg button i{font-style:normal; color:var(--muted); font-family:"JetBrains Mono",monospace; font-size:11px}
.sugg .none{padding:9px 12px; color:var(--muted); font-size:.86rem}

.toolbar{display:flex; gap:14px 20px; align-items:center; justify-content:space-between;
  flex-wrap:wrap; margin:0 0 16px}
.toolbar .controls{display:flex; gap:14px 18px; align-items:center; flex-wrap:wrap}
.chips{display:flex; flex-wrap:wrap; gap:7px; align-items:center; min-height:1px}
.pagesize{display:flex; align-items:center; gap:8px; color:var(--muted);
  font-family:"JetBrains Mono",monospace; font-size:12px; white-space:nowrap}
.pagesize select{
  background:var(--surface); color:var(--text); border:1px solid var(--border);
  border-radius:5px; padding:5px 8px; font:inherit; font-size:12px; cursor:pointer;
}
.pagesize select:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
.more{display:flex; justify-content:center; padding:4px 0 70px}
#loadmore{
  background:var(--surface); border:1px solid var(--border-2); color:var(--text);
  font:inherit; font-size:14px; padding:11px 26px; border-radius:6px; cursor:pointer;
}
#loadmore:hover{border-color:var(--accent); color:var(--accent); background:var(--accent-dim)}
.chip{
  display:inline-flex; gap:7px; align-items:center; background:var(--accent-dim);
  color:var(--accent); border-radius:13px; padding:3px 6px 3px 11px;
  font-family:"JetBrains Mono",monospace; font-size:12px;
}
.chip button{background:none; border:0; color:inherit; cursor:pointer; font-size:14px; line-height:1; padding:0 3px}
.chip button:hover{color:var(--text)}
.chips .count{color:var(--muted); font-size:12.5px; font-family:"JetBrains Mono",monospace}
.top nav a{color:var(--text-2); text-decoration:none}
.top nav a:hover{color:var(--accent)}

.wrap{max-width:1500px; margin:0 auto; padding:0 28px}
.prose{max-width:66ch}
h1{font-size:clamp(1.9rem,4vw,2.9rem); line-height:1.05; letter-spacing:-.025em; margin:0 0 14px; text-wrap:balance}
h2{font-size:1.3rem; letter-spacing:-.015em; margin:36px 0 10px; text-wrap:balance}
h3{font-size:1rem; margin:28px 0 8px}
p{margin:0 0 1em}
.intro{padding:46px 0 26px}
.intro p{color:var(--text-2); max-width:58ch; font-size:1.08rem}
.pilot{
  display:inline-block; font-family:"JetBrains Mono",monospace; font-size:11px;
  letter-spacing:.1em; text-transform:uppercase; color:var(--accent);
  background:var(--accent-dim); border-radius:3px; padding:4px 10px; margin-bottom:16px;
}

/* ---- timeline ---- */
.tl{background:var(--surface); border:1px solid var(--border); border-radius:6px; padding:18px 20px 12px; margin:0 0 26px}
.tlhead{display:flex; justify-content:space-between; align-items:baseline; gap:16px; margin-bottom:12px; flex-wrap:wrap}
.tlhead h2{margin:0; font-size:.95rem; font-weight:600}
.tlstat{font-family:"JetBrains Mono",monospace; font-size:12px; color:var(--muted); font-variant-numeric:tabular-nums}
/* 180 monthly bars at 3px plus 2px gaps need ~900px. On a phone that overflowed
   the card and scrolled the whole page sideways, so the bars thin out instead;
   overflow-x is a safety net for when the archive outgrows even that. */
.tlbars{display:flex; align-items:flex-end; gap:2px; height:84px; cursor:crosshair;
  user-select:none; touch-action:pan-y; overflow-x:auto; overscroll-behavior-x:contain}
.tlb{flex:1 1 0; min-width:3px; background:var(--border-2); border-radius:2px 2px 0 0;
  min-height:3px; transition:opacity .12s, background .12s}
.tlb.has{background:var(--accent)}
/* The keyboard cursor. It rides the bar itself rather than a full-height
   column, so an empty month still shows a 4px marker where the walk is. */
.tlb{position:relative}
.tlb.cur::after{content:""; position:absolute; inset:0; border-radius:2px;
  outline:1.5px solid var(--text); outline-offset:1px; pointer-events:none}
.tlbars:focus{outline:none}
.tlbars:focus-visible{outline:2px solid var(--accent); outline-offset:4px; border-radius:3px}
/* Dimming is its own class rather than riding on .has, so a selection reads the
   same whether the bar is one colour or a stack of contributor bands. */
.tlb.dim{opacity:.22}
.tlb.empty{background:var(--border); min-height:2px}
.tlb.split{display:flex; flex-direction:column-reverse; overflow:hidden; background:var(--border)}
/* The segments must not swallow pointer events, or dragging a range over a
   stacked bar never finds the bar underneath it. */
.tlb.split i{display:block; width:100%; pointer-events:none}
.tlhint{color:var(--muted); font-family:"JetBrains Mono",monospace; font-size:11px}
.tllegend{display:flex; flex-wrap:wrap; gap:5px 16px; margin:10px 0 0;
  font-family:"JetBrains Mono",monospace; font-size:11px; color:var(--text-2)}
.tllegend span,.tllegend a{display:flex; align-items:center; gap:6px}
.tllegend a{color:var(--text-2); text-decoration:none}
.tllegend a:hover{color:var(--accent)}
.tllegend b{width:9px; height:9px; border-radius:2px; flex:none}
.tlmore{display:none; background:none; border:0; color:var(--accent); font:inherit;
  font-family:"JetBrains Mono",monospace; font-size:11px; padding:6px 0 0; cursor:pointer}
/* One cell per month, mirroring the bars above it. */
.tlyears{display:flex; gap:2px; margin-top:7px; height:15px;
  font-family:"JetBrains Mono",monospace; font-size:10.5px; color:var(--muted);
  font-variant-numeric:tabular-nums}
.ty{flex:1 1 0; min-width:3px; position:relative}
.ty i{position:absolute; top:0; left:-1px; font-style:normal; white-space:nowrap}
/* The year line is drawn from the ruler cell rather than from the January bar.
   A stacked bar sets overflow:hidden to clip its colour bands to its rounded
   top, and that clipped the line away too -- so it vanished in exactly the busy
   stretches where knowing the year matters most, which read as the lines
   disappearing whenever the bars got dense. The ruler clips nothing, and from
   there the line rules over the bars instead of hiding in the gap between them.
   84px is the height of .tlbars and 7px its distance from this row. */
.ty.jan::after{content:""; position:absolute; left:-2px; bottom:calc(100% + 7px);
  width:2px; height:84px; background:rgba(230,233,239,.16); pointer-events:none}
/* The same boundary again as a tick on the rule itself. */
.ty.jan::before{content:""; position:absolute; left:-2px; top:0; width:2px;
  height:4px; background:var(--border-2)}
.tlclear{background:none; border:1px solid var(--danger); color:var(--danger); font:inherit; font-size:12px;
  padding:3px 10px; border-radius:4px; cursor:pointer}
.tlclear:hover{background:var(--danger-dim); border-color:var(--danger); color:#ff8a7a}

/* ---- grid ---- */
/* A full-width flex item, so it breaks the justified row cleanly, and sticky
   under the site header so you always know which month you are looking at
   however far down you have scrolled. */
.gridhead{
  flex:1 0 100%; position:sticky; top:73px; z-index:6; margin:20px 0 0; padding:7px 2px 9px;
  background:linear-gradient(var(--bg) 62%, rgba(13,15,19,0));
  font-family:"JetBrains Mono",monospace; font-size:11.5px; letter-spacing:.11em;
  text-transform:uppercase; color:var(--muted);
}
.gridhead:first-child{margin-top:0}

.actions{display:flex; flex-wrap:wrap; gap:10px; align-items:center}
.dl.ghost{background:none; border:1px solid var(--border-2); color:var(--text-2);
  font:inherit; font-size:14px; cursor:pointer}
.dl.ghost:hover{border-color:var(--accent); color:var(--accent); background:var(--accent-dim)}
.dl.ghost.done{border-color:var(--go); color:var(--go); background:var(--go-dim)}
/* Justified rows, not a fixed grid. 93% of the archive is not 16:9 -- windowed
   Minecraft loses height to the title bar, giving ratios from 1.60 to 1.94 --
   so a 16:9 box with object-fit:cover was shaving the left and right edges off
   almost every screenshot, which is where the F3 column and chat live.

   Each cell carries its own --ar. flex-basis scales with it so wider images
   claim more of the row, and aspect-ratio derives the height, so everything in
   a row lands on the same height with nothing cropped. The ::after filler stops
   a short final row from stretching to full width. */
.grid{display:flex; flex-wrap:wrap; gap:10px; align-content:flex-start}
.grid::after{content:""; flex-grow:1e6}
/* The same filler, once per month group, closing each group's last row. Without
   one, a sparse month stretches its images across the full width. */
.gridfill{flex:1e6 0 0; height:0; min-width:0}
.cell{position:relative; display:block; background:var(--surface); border-radius:5px;
  overflow:hidden; border:1px solid var(--border); text-decoration:none;
  flex:var(--ar) 1 calc(var(--ar) * 155px); aspect-ratio:var(--ar); min-width:150px}
.cell img{
  width:100%; height:100%; object-fit:cover; background:var(--surface-2);
  color:transparent; font-size:0; transition:transform .35s ease, opacity .3s;
}
/* The cell now matches the image's own ratio, so cover crops nothing; it is kept
   only to absorb sub-pixel rounding in the aspect-ratio arithmetic. */
.shot img{width:100%; height:auto}
.cell:hover img{transform:scale(1.035)}
.cell figcaption{
  position:absolute; left:0; right:0; bottom:0; padding:16px 10px 7px;
  background:linear-gradient(transparent,rgba(6,8,11,.88));
  font-family:"JetBrains Mono",monospace; font-size:11px; color:#d7dce6;
  opacity:0; transition:opacity .18s;
}
.cell:hover figcaption,.cell:focus-visible figcaption{opacity:1}
.empty-note{color:var(--muted); padding:40px 0}

/* ---- detail ---- */
/* The screenshot is what the page is for, so it gets the width. Metadata sits
   below it rather than beside it: a 300px sidebar was costing the image a third
   of the viewport on every view. */
.detail{padding:16px 0 70px}
.detailbar{display:flex; justify-content:space-between; align-items:center; gap:10px 18px;
  margin:0 0 12px; flex-wrap:wrap}
.detailbar .pos{flex:1; color:var(--muted); font-family:"JetBrains Mono",monospace;
  font-size:11.5px; letter-spacing:.04em}
/* fit-content so the frame hugs the screenshot. A fixed-width card left a
   854px original floating in half a metre of empty surface. */
.shot{margin:0 auto; background:var(--surface); border:1px solid var(--border);
  border-radius:6px; overflow:hidden; display:flex; justify-content:center;
  align-items:center; width:fit-content; max-width:100%}
.shot img{width:auto; max-width:100%; height:auto; max-height:calc(100vh - 215px)}
.detail h1{font-size:1.35rem; letter-spacing:-.01em; margin:22px 0 14px}
dl.meta{display:grid; grid-template-columns:repeat(auto-fit,minmax(185px,1fr));
  gap:15px 24px; margin:0 0 22px; font-family:"JetBrains Mono",monospace; font-size:12.5px}
dl.meta > div{min-width:0}
dl.meta dt{color:var(--muted); margin-bottom:3px}
dl.meta dd{margin:0; color:var(--text-2); word-break:break-word}
.back{display:inline-block; color:var(--muted); text-decoration:none;
  font-family:"JetBrains Mono",monospace; font-size:12px; letter-spacing:.04em}
.back:hover{color:var(--accent)}
.nav2{display:flex; gap:8px}
.nav2 a,.nav2 span{padding:7px 16px; border:1px solid var(--border-2); border-radius:5px;
  font-size:13px; text-decoration:none; color:var(--text-2)}
.nav2 a:hover{border-color:var(--accent); color:var(--accent)}
.nav2 span{opacity:.3}
.dl{display:inline-block; padding:9px 15px; border:1px solid var(--accent); color:var(--accent);
  border-radius:5px; text-decoration:none; font-size:13.5px}
.dl:hover{background:var(--accent-dim)}

/* ---- statistics ---- */
.card{background:var(--surface); border:1px solid var(--border); border-radius:6px;
  padding:22px 24px 18px; margin:0 0 22px}
.card > h2{margin:0 0 4px; font-size:1.05rem}
.card > p.note{margin:0 0 18px; color:var(--muted); font-size:13.5px; max-width:68ch}
.stack-wrap{overflow-x:auto}
.stackbars{display:flex; align-items:flex-end; gap:2px; height:190px; min-width:640px}
.sb{flex:1 1 0; min-width:3px; display:flex; flex-direction:column-reverse; border-radius:2px 2px 0 0;
  overflow:hidden; background:var(--border); min-height:2px}
.sb i{display:block; width:100%}
.axis{display:flex; justify-content:space-between; margin-top:9px; padding-top:8px;
  border-top:1px solid var(--border); font-family:"JetBrains Mono",monospace;
  font-size:11px; color:var(--muted); min-width:640px}
.legend{display:flex; flex-wrap:wrap; gap:6px 18px; margin:18px 0 0;
  font-family:"JetBrains Mono",monospace; font-size:12px}
.legend span{display:flex; align-items:center; gap:7px; color:var(--text-2)}
.legend b{width:11px; height:11px; border-radius:2px; flex:none}
.legend i{color:var(--muted); font-style:normal}
.two{display:grid; grid-template-columns:minmax(0,320px) minmax(0,1fr); gap:30px; align-items:center}
.pie-rows{display:grid; gap:7px; font-family:"JetBrains Mono",monospace; font-size:12.5px}
.pie-row{display:grid; grid-template-columns:11px 1fr auto auto; gap:11px; align-items:center}
.pie-row b{width:11px; height:11px; border-radius:2px}
.pie-row u{text-decoration:none; color:var(--text-2)}
.pie-row em{font-style:normal; color:var(--muted); font-variant-numeric:tabular-nums}
.pie-row s{text-decoration:none; color:var(--text); font-variant-numeric:tabular-nums}
.span-wrap{overflow-x:auto}
.spans{display:grid; gap:9px; min-width:700px}
.span-row{display:grid; grid-template-columns:130px 1fr; gap:14px; align-items:center;
  font-family:"JetBrains Mono",monospace; font-size:12px}
.span-track{position:relative; height:15px; background:var(--surface-2); border-radius:3px}
.span-bar{position:absolute; top:0; bottom:0; border-radius:3px; opacity:.9}
/* Year rule. The axis named only the first and last month, which left every
   bar's actual years to be guessed off its pixel position. */
.span-track i{position:absolute; top:0; bottom:0; width:1px; background:var(--border);
  pointer-events:none}
./* The rule heads the chart: you read the years first, then the bars under them.
   So the labels sit above their own line and the ticks hang off its underside,
   pointing down into the tracks they measure. */
.span-row.span-rule{min-width:700px; margin-bottom:7px; align-items:end}
.span-ticks{position:relative; height:17px; border-bottom:1px solid var(--border);
  font-family:"JetBrains Mono",monospace; font-size:10.5px; color:var(--muted);
  font-variant-numeric:tabular-nums}
.span-ticks i{position:absolute; top:0; transform:translateX(-50%); font-style:normal}
/* A label whose band sits against an edge anchors to that edge rather than
   centring half of itself outside the chart, which gave the card a stray 10px
   of horizontal scroll. */
.span-ticks i.lead{transform:none}
.span-ticks i.trail{transform:translateX(-100%)}
.span-ticks u{position:absolute; bottom:0; width:1px; height:4px; background:var(--border-2);
  text-decoration:none}
.yearbars{display:flex; align-items:stretch; gap:6px; height:130px}
/* stretch, not flex-end: each column needs a definite height for its bar's
   percentage height to resolve against, or the bar collapses to nothing. */
.yearbars > div{flex:1; display:flex; flex-direction:column; justify-content:flex-end; gap:6px}
.yearbars u{display:block; background:var(--accent); border-radius:2px 2px 0 0; text-decoration:none}
.yearlabels{display:flex; gap:6px; margin-top:8px; font-family:"JetBrains Mono",monospace;
  font-size:11px; color:var(--muted)}
.yearlabels > div{flex:1; text-align:center}
.yearlabels s{display:block; text-decoration:none; color:var(--text-2);
  font-variant-numeric:tabular-nums}
.caption{margin:-2px 0 14px; color:var(--text-2); max-width:70ch}
.tagrow{display:flex; flex-wrap:wrap; gap:7px; margin:0 0 20px}
.tag{display:inline-flex; align-items:center; background:var(--surface-2);
  border:1px solid var(--border); color:var(--text-2); text-decoration:none;
  border-radius:13px; padding:3px 11px; font-family:"JetBrains Mono",monospace; font-size:12px}
.tag:hover{border-color:var(--accent); color:var(--accent); background:var(--accent-dim)}
/* A collection is a curated set rather than a label, so it reads as one. */
.tag.coll{border-style:dashed}

/* ---- contributor x year heatmap ---- */
.heat-wrap{overflow-x:auto}
.heat{display:grid; grid-template-columns:132px repeat(var(--yrs,16),minmax(42px,1fr));
  gap:2px; min-width:760px; font-family:"JetBrains Mono",monospace;
  font-variant-numeric:tabular-nums}
.heat b{font-size:10.5px; font-weight:500; color:var(--muted); text-align:center;
  padding-bottom:3px}
.heat u{display:flex; align-items:center; text-decoration:none; font-size:11.5px;
  color:var(--text-2); padding-right:8px; white-space:nowrap}
.heat i{display:flex; align-items:center; justify-content:center; height:25px;
  border-radius:3px; font-style:normal; font-size:10.5px}
/* A year nobody shot still gets a cell: the absence is the information. */
.heat i.zero{background:var(--surface-2)}

.facts{display:grid; grid-template-columns:repeat(auto-fit,minmax(168px,1fr)); gap:1px;
  background:var(--border); border:1px solid var(--border); border-radius:6px; overflow:hidden}
.fact{background:var(--surface); padding:15px 18px}
.fact b{display:block; font-size:1.45rem; font-weight:700; letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.fact span{display:block; margin-top:4px; color:var(--muted);
  font-family:"JetBrains Mono",monospace; font-size:10px; letter-spacing:.1em; text-transform:uppercase}
.chip-or{color:var(--muted); font-family:"JetBrains Mono",monospace; font-size:11px; padding:0 1px}
.linkish{background:none; border:0; color:var(--accent); font:inherit; cursor:pointer;
  text-decoration:underline; text-underline-offset:2px; padding:0}
@media (max-width:760px){ .two{grid-template-columns:1fr} }

.foot{border-top:1px solid var(--border); padding:30px 28px 50px; color:var(--muted); font-size:13.5px}
.foot p{max-width:70ch; margin:0 0 .6em}
@media (max-width:860px){
  .wrap{padding:0 16px}
  .top{padding:12px 16px; flex-wrap:wrap}
  .search{order:3; flex-basis:100%; max-width:none}
}
@media (max-width:700px){
  .tlbars{gap:1px}
  .tlb{min-width:1px}
  .tlyears{gap:1px}
  .ty{min-width:1px}
  .ty.jan::before,.ty.jan::after{left:-1px; width:1px}
  .ty i.alt{display:none}
  .tlhint{display:none}
  /* Six rows of contributor names pushed the first screenshot off the screen.
     Two rows, and the rest on demand. */
  .tllegend{max-height:3.4em; overflow:hidden; position:relative}
  .tllegend.open{max-height:none}
  .tlmore{display:block}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important; animation:none!important}}
