/* ============================================================
   PROJECTS — one ruled grid, drawn by the scroll
   The projects share one frame on the page ground, divided into cells by
   hairlines, with a small cross at every corner and crossing: the
   construction-line language of the hero's guides and the How I work icons.
   js/grid-draw.js draws it as the page scrolls: the vertical rules grow down
   with a pen held at 80% of the screen, each cross appears just before the
   pen reaches it, and each horizontal rule runs across once the pen has
   passed. A hovered cell takes the white surface fill.

   Cells pad their content by --cell-pad, the How I work gap is twice that,
   so the projects' inner edges line up with the How I work columns and the
   frame's outer edges with the page column.
   ============================================================ */


.cases-b{
  list-style:none;margin:0;padding:0;position:relative;
  display:grid;gap:1px;
}
@media (min-width:840px){
  .cases-b{grid-template-columns:1fr 1fr;}
}
.cases-b > li{display:flex;background:transparent;position:relative;z-index:0;}   /* the page's own fill: grey on the homepage band, white on case pages */
/* the hovered cell rises above its neighbours, so its selection's labels can
   sit over them */
.cases-b > li:has(:focus-visible){z-index:2;}
@media (hover:hover){.cases-b > li:hover{z-index:2;}}

/* ---------- the rules (placed and drawn by js/grid-draw.js) ----------
   Rules sit on the 1px gaps and just outside the outer cells. They pass
   under a hovered cell, whose selection box takes their place. */
.grid-draw{position:absolute;inset:0;pointer-events:none;z-index:1;}
.grid-draw i{position:absolute;display:block;}
.grid-draw .gd-v{width:1px;background:var(--rule);transform-origin:50% 0;}
.grid-draw .gd-h{height:1px;background:var(--rule);transform-origin:0 50%;
  transform:scaleX(0);transition:transform 1.4s cubic-bezier(.65,0,.35,1);}
.grid-draw .gd-h.is-on{transform:none;}
/* 13px with its 1px bars at 6px: placed at a rule's pixel (x, y), the bars
   land exactly on that rule's pixel column and row */
.grid-draw .gd-x{width:13px;height:13px;margin:-6px 0 0 -6px;opacity:.55;
  background:
    linear-gradient(var(--ink-2),var(--ink-2)) center/1px 100% no-repeat,
    linear-gradient(var(--ink-2),var(--ink-2)) center/100% 1px no-repeat;
  transform:scale(.3);opacity:0;transition:transform .28s cubic-bezier(.34,1.56,.64,1),opacity .2s ease;}
.grid-draw .gd-x.is-on{transform:none;opacity:.55;}

.card-b{
  flex:1;display:flex;flex-direction:column;
  padding:var(--cell-pad);
  text-decoration:none;color:inherit;
  transition:background-color .2s ease;
}
/* hover: the cell takes the surface fill (white in light); no lift, no shadow */
a.card-b:focus-visible{background:var(--paper);}
@media (hover:hover){a.card-b:hover{background:var(--paper);}}
/* dark: the surface fill is darker than the page ground there, so a hovered
   cell takes a lighter grey (--cell-hover, css/theme.css) to read as lifted, not sunk */
:root[data-theme="dark"] a.card-b:focus-visible{background:var(--cell-hover);}
@media (hover:hover){:root[data-theme="dark"] a.card-b:hover{background:var(--cell-hover);}}
.card-b:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;}

/* the screenshot: a hairline edge and soft corners */
.card-b .shot{padding:0;background:none;}
.card-b .shot img{
  width:100%;height:auto;display:block;
  aspect-ratio:16/10;object-fit:cover;object-position:center;
  border:1px solid var(--rule);border-radius:clamp(6px,0.6vw,10px);
}

/* a card whose preview has not been captured yet: the same box, filled with
   the card's field colour, so the grid keeps its rhythm until the image exists */
.card-b .shot-empty{
  aspect-ratio:16/10;background:var(--case-field);
  border:1px solid var(--rule);border-radius:clamp(6px,0.6vw,10px);
}

/* hover: the cell is selected the way the hero's inspector selects the
   photo and the role (css/inspect.css): a blue box on the cell's rules with
   square handles, and the company and years above it.
   js/project-select.js adds the parts. */
.shot-sel{position:absolute;inset:-1px;pointer-events:none;opacity:0;transition:opacity .2s ease;}
.cases-b > li:has(:focus-visible) .shot-sel{opacity:1;}
@media (hover:hover){.cases-b > li:hover .shot-sel{opacity:1;}}
.shot-sel .sb{position:absolute;inset:0;border:1px solid var(--sel);}
.shot-sel .sh{position:absolute;width:7px;height:7px;background:var(--paper);border:1px solid var(--sel);}
.shot-sel .sh.tl{left:-4px;top:-4px;} .shot-sel .sh.tr{right:-4px;top:-4px;}
.shot-sel .sh.bl{left:-4px;bottom:-4px;} .shot-sel .sh.br{right:-4px;bottom:-4px;}
.shot-sel .sn{
  position:absolute;font:500 10.5px/1 var(--mono);white-space:nowrap;letter-spacing:0;
  color:var(--sel-ink);background:var(--sel-text);padding:3px 5px;border-radius:3px;
}
.shot-sel .sn{left:0;bottom:calc(100% + 6px);}

.card-b .meta{padding:clamp(16px,1.6vw,22px) 0 0;}
.card-b .kicker{
  font-family:var(--body);font-weight:500;
  font-size:var(--t-sm-size);line-height:1.3;letter-spacing:0;color:var(--ink-2);margin:0;
}
.card-b h3{
  font-family:var(--body);font-weight:500;
  font-size:clamp(1.0625rem,0.95rem + 0.5vw,1.375rem);  /* 17 -> 22 */
  line-height:1.25;letter-spacing:-0.018em;color:var(--ink);
  margin:4px 0 0;text-wrap:balance;
}

@media (prefers-reduced-motion:reduce){
  .card-b,.shot-sel,.grid-draw .gd-x,.grid-draw .gd-h{transition:none;}
}

/* no visible section title: "Proof in production" is the link down to it at
   the end of How I work (css/practices.css) */

/* ============ MORE WORK (homepage) ============
   The roles without a case study, as cells in the same grid as the cases:
   no preview, the same hover fill and selection box. A little more vertical
   room than their text needs, so the rows do not read as a list.
   Details sit in .more, hidden in place and shown in the tooltip below. */
.card-b.is-text{padding-block:calc(var(--cell-pad) * 1.4);cursor:default;}
/* a case cell rises on hover so its selection box can cover the rules; a
   text cell has no box, so it stays under the rules and its fill never
   paints over the divider or the crosses */
.cases-b > li.is-text,
.cases-b > li.is-text:has(:focus-visible){z-index:0;}
@media (hover:hover){.cases-b > li.is-text:hover{z-index:0;}}
.card-b.is-text .meta{padding:0;}
.card-b.is-text h3{font-size:clamp(1rem,0.94rem + 0.3vw,1.1875rem);}
.card-b.is-text .line{
  font-family:var(--body);font-size:var(--t-sm-size);line-height:1.45;color:var(--ink-2);margin:6px 0 0;
}
.card-b.is-text:focus-visible{background:var(--paper);}
@media (hover:hover){.card-b.is-text:hover{background:var(--paper);}}
:root[data-theme="dark"] .card-b.is-text:focus-visible{background:var(--cell-hover);}
@media (hover:hover){:root[data-theme="dark"] .card-b.is-text:hover{background:var(--cell-hover);}}
.card-b .more{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* the tooltip: the selection label's blue fill and white text, following
   the pointer; on keyboard focus it sits under the cell instead */
.more-tip{
  position:fixed;left:0;top:0;z-index:60;pointer-events:none;
  max-width:min(320px, calc(100vw - 32px));margin:0;padding:8px 10px;list-style:none;
  font:500 11.5px/1.45 var(--mono);letter-spacing:0;
  color:var(--sel-ink);background:var(--sel-text);border-radius:3px;
  opacity:0;transition:opacity .12s ease;
}
.more-tip.is-on{opacity:1;}
.more-tip li + li{margin-top:5px;}
.more-tip li{padding-left:12px;position:relative;}
.more-tip li::before{content:"";position:absolute;left:0;top:.62em;width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.7;}
@media (hover:none){.more-tip{display:none;}}
