/* ------------------------------------------------------------------
   home.css — layout for the index page only. Shared tokens, ambient
   layer and fixed controls come from base.css.
   ------------------------------------------------------------------ */

/* ------------------------------------------------------------------
   ambient grid — a faint square lattice drifting diagonally, so the
   canvas is neither flatly empty nor visibly busy.

   One element, and the pattern moves rather than the layer. The obvious
   build is a transformed child inside this masked box, which is what the
   .ambient blobs in base.css do — but they are not masked, and that is
   the whole difference. A mask on the ancestor of a compositing-promoted
   child has to be resolved against that child every frame; the browser
   either re-composites the masked subtree continuously or gives up on
   promotion, and either way the result is a visible flicker.

   Animating background-position keeps the mask on a layer that never
   moves, which is the arrangement that was already working here before
   there was any motion at all. It repaints instead of compositing, but
   the repaint is two gradients inside `contain: paint` on a fixed,
   non-scrolling element — and it is off entirely on touch.

   It also removes the seam. A repeating background has no edge to run
   out of, so there is no overscan to size and no reset to hide.
   ------------------------------------------------------------------ */
.grain{
  --tile:104px;                /* also the column rhythm of the old rules */

  position:fixed;inset:0;pointer-events:none;z-index:0;
  contain:layout paint;

  background-image:
    linear-gradient(to right,  var(--rule-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--rule-line) 1px, transparent 1px);
  background-size:var(--tile) var(--tile);

  /* twice the ink of the old vertical-only rules, so a little fainter
     per line to land at the same overall weight */
  opacity:.45;

  mask-image:linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
  -webkit-mask-image:linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);

  /* linear, and never anything else: constant motion is the one case
     where easing is always wrong — it would speed up and slow down once
     per cycle for no reason the eye can attribute to anything.

     20s over one tile is ~5px/s. Slower than this and each hairline
     spends a third of a second crossing a single pixel, which reads as a
     slow pulse rather than as movement. */
  animation:grid-drift 20s linear infinite;
}

/* one tile in each axis. both background layers share a position and a
   size, so they land back on themselves together and the cycle is
   continuous rather than looped. */
@keyframes grid-drift{
  from{background-position:0 0}
  to  {background-position:calc(var(--tile) * -1) calc(var(--tile) * -1)}
}

/* motion sickness: keep the texture, drop the travel */
@media (prefers-reduced-motion:reduce){
  .grain{animation:none}
}

/* touch devices: drop the layer entirely. a masked full-viewport layer
   plus two animating blobs is the expensive part, and on a phone the
   grid is mostly hidden behind the cards anyway. */
@media (hover:none),(pointer:coarse),(max-width:760px){
  .grain{display:none}
}

.wrap{
  position:relative;
  z-index:1;
  max-width:1080px;
  margin:0 auto;
  padding:96px 32px 128px;
}
/* ---------- masthead ---------- */
.eyebrow{
  font-family:var(--mono);
  font-size:11px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
  margin:0 0 28px;
}
h1{
  font-family:var(--serif);
  font-weight:400;
  font-size:clamp(44px,7vw,76px);
  line-height:1.08;
  letter-spacing:-.03em;
  color:var(--ink);
  margin:0 0 20px;
}
.lede{
  max-width:52ch;
  color:var(--muted);
  font-size:17px;
  margin:0;
}
.rule{
  height:1px;
  background:var(--border);
  border:0;
  margin:64px 0 40px;
}

/* ---------- listing ---------- */
.meta-row{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:24px;
  font-family:var(--mono);
  font-size:11px;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--muted);
  margin-bottom:24px;
}

.grid{
  display:grid;
  grid-template-columns:repeat(6,1fr);
  gap:16px;
  list-style:none;
  margin:0;padding:0;
}
.cell{grid-column:span 3}
.cell:nth-child(6n+1){grid-column:span 4}
.cell:nth-child(6n+2){grid-column:span 2}
@media (max-width:760px){
  .cell,.cell:nth-child(6n+1),.cell:nth-child(6n+2){grid-column:span 6}
  .wrap{padding:64px 22px 96px}
}

.card{
  display:flex;
  flex-direction:column;
  height:100%;
  min-height:196px;
  padding:28px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:12px;
  text-decoration:none;
  color:inherit;
  box-shadow:0 0 0 rgba(0,0,0,0);
  transition:box-shadow 200ms var(--ease), transform 200ms var(--ease), border-color 200ms var(--ease);
}
.card:hover{
  box-shadow:var(--card-shadow);
  border-color:var(--border-strong);
  transform:translateY(-2px);
}
.card:active{transform:scale(.995)}
.card:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

.badge{
  align-self:flex-start;
  font-family:var(--mono);
  font-size:10px;
  letter-spacing:.09em;
  text-transform:uppercase;
  padding:4px 10px;
  border-radius:9999px;
  background:var(--pale-green);
  color:var(--pale-green-ink);
  margin-bottom:20px;
}
/* the badge says what the page is, not how recently it moved.
   plain = rendered from markdown by the shared reader; standalone = ships
   its own styles and scripts; unknown = the probe did not answer, so the
   card is shown without claiming to know. */
.badge.standalone{background:var(--pale-yellow);color:var(--pale-yellow-ink)}
.badge.unknown{background:var(--surface);color:var(--muted)}

.card h2{
  font-family:var(--serif);
  font-weight:400;
  font-size:26px;
  line-height:1.2;
  letter-spacing:-.02em;
  color:var(--ink);
  margin:0 0 8px;
}
.slug{
  font-family:var(--mono);
  font-size:12px;
  color:var(--muted);
  word-break:break-all;
  margin:0;
}
.foot{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  margin-top:auto;
  padding-top:24px;
}
.stamp{
  font-family:var(--mono);
  font-size:11px;
  letter-spacing:.06em;
  color:var(--muted);
}
.arrow{
  flex:none;
  color:var(--ink);
  transform:translateX(0);
  transition:transform 200ms var(--ease);
}
.card:hover .arrow{transform:translateX(4px)}

/* ---------- states ---------- */
.note{
  border:1px solid var(--border);
  border-radius:12px;
  background:var(--surface);
  padding:40px;
  color:var(--muted);
}
.note strong{
  display:block;
  font-family:var(--serif);
  font-weight:400;
  font-size:22px;
  letter-spacing:-.02em;
  color:var(--ink);
  margin-bottom:8px;
}
.note code{
  font-family:var(--mono);
  font-size:12px;
  background:var(--code-bg);
  border:1px solid var(--border);
  border-radius:4px;
  padding:1px 5px;
}



footer{
  margin-top:80px;
  padding-top:24px;
  border-top:1px solid var(--border);
  display:flex;
  justify-content:space-between;
  gap:16px;
  flex-wrap:wrap;
  font-family:var(--mono);
  font-size:11px;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--muted);
}

@media (prefers-reduced-motion:reduce){
  .card,.arrow{transition:none}
}
