/* ==========================================================================
   Launchpad — the index. A blurred desktop, a search field, a grid of icons.
   Hovering an icon tints the whole surface with that version's wallpaper.
   ========================================================================== */

:root{
  --sans:-apple-system,BlinkMacSystemFont,"SF Pro Display","SF Pro Text","Inter",system-ui,"Helvetica Neue",Arial,sans-serif;
  --mono:var(--sans);   /* same family as the body text — see site.css */

  /* light appearance: Launchpad frosts the desktop pale */
  --scrim:rgba(244,244,248,.62);
  --ink:#16141f;
  --ink-2:rgba(22,20,31,.62);
  --ink-3:rgba(22,20,31,.42);
  --field:rgba(255,255,255,.58);
  --field-line:rgba(22,20,31,.14);
  --icon-ring:rgba(255,255,255,.55);
  --icon-shadow:0 10px 26px -8px rgba(14,10,32,.42);
  --dot:rgba(22,20,31,.24);
  --dot-on:rgba(22,20,31,.62);
  --blur:56px;
  --void:#e9e7ee;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --scrim:rgba(8,7,18,.6);
    --ink:#f6f4fc;
    --ink-2:rgba(246,244,252,.7);
    --ink-3:rgba(246,244,252,.45);
    --field:rgba(255,255,255,.13);
    --field-line:rgba(255,255,255,.2);
    --icon-ring:rgba(255,255,255,.2);
    --icon-shadow:0 12px 30px -8px rgba(0,0,0,.68);
    --dot:rgba(246,244,252,.28);
    --dot-on:rgba(246,244,252,.75);
    --void:#0a0818;
  }
}
:root[data-theme="dark"]{
  --scrim:rgba(8,7,18,.6);
  --ink:#f6f4fc;
  --ink-2:rgba(246,244,252,.7);
  --ink-3:rgba(246,244,252,.45);
  --field:rgba(255,255,255,.13);
  --field-line:rgba(255,255,255,.2);
  --icon-ring:rgba(255,255,255,.2);
  --icon-shadow:0 12px 30px -8px rgba(0,0,0,.68);
  --dot:rgba(246,244,252,.28);
  --dot-on:rgba(246,244,252,.75);
  --void:#0a0818;
}

*{box-sizing:border-box}
/* The page tone lives on <html> only. Do NOT also set a background on <body>:
   once <html> has one, body stops propagating to the canvas and paints its own
   opaque box instead, which would bury the backdrop below it. */
html{background:var(--void)}
body{
  margin:0;min-height:100vh;
  font-family:var(--sans);color:var(--ink);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{display:block;max-width:100%}
:focus-visible{outline:none}

/* ---------- the blurred desktop behind everything ---------- */
.desktop{position:fixed;inset:0;z-index:0;overflow:hidden;background:var(--void)}
/* Centred on the viewport and overscaled by 34%, so the blur's soft edge always
   falls well outside the screen. Never size this with insets plus width/height —
   that combination is over-constrained and browsers drop an offset, which leaves
   a strip of bare background down one side. */
.desktop img{
  position:absolute;
  top:50%;left:50%;
  width:100%;height:100%;
  object-fit:cover;object-position:center;
  transform:translate(-50%,-50%) scale(1.34);
  filter:blur(var(--blur)) saturate(165%);
  opacity:0;transition:opacity .7s cubic-bezier(.3,.7,.3,1);
}
.desktop img.on{opacity:1}
.desktop::after{content:"";position:absolute;inset:0;background:var(--scrim);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}

/* ---------- shell ---------- */
.pad{
  position:relative;z-index:1;
  min-height:100vh;
  min-height:100svh;
  display:flex;flex-direction:column;align-items:center;
  padding:clamp(26px,5vh,58px) max(16px,4vw) clamp(24px,4vh,44px);
  gap:clamp(20px,3.4vh,38px);
}

.top{display:flex;flex-direction:column;align-items:center;gap:16px;width:100%}
.wordmark{
  display:flex;align-items:center;gap:9px;
  font-size:.95rem;font-weight:600;letter-spacing:-.005em;color:var(--ink-2);
}
.search{
  position:relative;width:min(380px,82vw);
}
.search svg{
  position:absolute;left:11px;top:50%;translate:0 -50%;
  color:var(--ink-3);pointer-events:none;
}
.search input{
  width:100%;height:38px;border-radius:100px;
  padding:0 15px 0 36px;
  font:inherit;font-size:.95rem;color:var(--ink);
  background:var(--field);
  border:1px solid var(--field-line);
  backdrop-filter:blur(18px) saturate(170%);-webkit-backdrop-filter:blur(18px) saturate(170%);
  transition:border-color .2s,background .2s;
}
.search input::placeholder{color:var(--ink-3)}
.search input:focus{outline:none;border-color:var(--ink-3);background:var(--field)}

/* ---------- the grid of icons ---------- */
.deck{
  flex:1;width:100%;max-width:1280px;
  display:flex;align-items:center;justify-content:center;
}
.apps{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(128px,1fr));
  gap:clamp(22px,3vw,40px) clamp(10px,1.4vw,20px);
  width:100%;
  list-style:none;margin:0;padding:0;
}
/* Fixed-width tracks so a part-full row centres itself, the way Launchpad does. */
@media (min-width:620px){
  .apps{grid-template-columns:repeat(auto-fit,clamp(124px,11.4vw,162px));justify-content:center}
}

.app{display:flex}
.app a{
  display:flex;flex-direction:column;align-items:center;gap:clamp(9px,1vw,13px);
  text-decoration:none;color:inherit;width:100%;
  padding:8px 4px 10px;border-radius:16px;
  transition:transform .22s cubic-bezier(.3,.8,.3,1),background .22s;
}
.app a:hover,.app a:focus-visible{transform:translateY(-3px);background:rgba(127,127,160,.12)}
.app a:focus-visible{box-shadow:0 0 0 2.5px var(--ink-3)}
.app a:active{transform:translateY(-1px) scale(.97)}

.icon{
  width:clamp(72px,8.4vw,112px);aspect-ratio:1;
  border-radius:22.5%;overflow:hidden;position:relative;
  box-shadow:var(--icon-shadow);
  flex:0 0 auto;
}
.icon img{width:100%;height:100%;object-fit:cover}
.icon::after{
  content:"";position:absolute;inset:0;border-radius:inherit;
  box-shadow:inset 0 0 0 1px var(--icon-ring),inset 0 1px 1px rgba(255,255,255,.4);
}
.name{font-size:clamp(.86rem,1.05vw,1rem);font-weight:500;letter-spacing:-.008em;text-align:center;line-height:1.25}
.ver{font-family:var(--mono);font-weight:500;font-size:clamp(.66rem,.8vw,.76rem);letter-spacing:.08em;font-variant-numeric:tabular-nums;color:var(--ink-3);margin-top:-4px}

/* entrance — Launchpad's zoom-in, staggered */
.apps .app{animation:pop .42s cubic-bezier(.2,.9,.3,1) backwards}
@keyframes pop{from{opacity:0;transform:scale(.86)}to{opacity:1;transform:none}}

/* filtered out by search */
.app[hidden]{display:none!important}

.empty{
  grid-column:1/-1;text-align:center;color:var(--ink-3);
  font-size:.9rem;padding:40px 0;
}

/* ---------- bottom rail ---------- */
.rail{display:flex;flex-direction:column;align-items:center;gap:14px;width:100%}
.dots{display:flex;gap:7px}
.dots i{width:7px;height:7px;border-radius:50%;background:var(--dot);display:block}
.dots i.on{background:var(--dot-on)}
.note{font-size:.72rem;color:var(--ink-3);text-align:center;max-width:52ch;line-height:1.5}
.note a{color:var(--ink-2)}

.appear{
  position:fixed;z-index:3;top:clamp(16px,3vh,26px);right:max(16px,4vw);
  height:28px;padding:0 12px;border-radius:100px;
  display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  font:inherit;font-size:.74rem;color:var(--ink-2);
  background:var(--field);border:1px solid var(--field-line);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  transition:color .2s,border-color .2s;
}
.appear:hover{color:var(--ink)}
.appear .dot{width:9px;height:9px;border-radius:50%;background:linear-gradient(140deg,#e04aa4,#3a1fd0)}

@media (prefers-reduced-motion:reduce){
  .apps .app{animation:none}
  .desktop img{transition:none}
  .app a{transition:none}
}
