/* grid.css — HOW A GRID MEASURES ITSELF, in one place (2026-09-19; the owner, of the templates page's cards: "still a
 * disparity between the templates page cards and what I'm seeing in the bench tool" → "a").
 * The gallery's page and the miniature of it on the templates page BOTH read these rules, so a card cannot draw a
 * different grid from the page it stands for. Everything else about a cell — its ground, its line, its shadow, the
 * placement, the mats — stays in loupe.css (the page) and cards.css (the miniature), where each belongs.
 * ⚠ `--page-width` is how wide the page is: the window (100vw) on a real page, and the fixed 1200px page a card draws.
 * ⚠ ITS OWN CLASS, never `#grid`: the templates page has an id of that name for its row of cards, and the shared
 * file would have laid a gallery's grid over it (found 2026-09-19). The engine puts `loupe-grid` on the page's
 * own grid (loupe.js), so a page and a card answer to one rule. Linked after loupe.css so these win where both speak. */
.loupe-grid {
  display: grid;
  /* ⚠ `safe` — a grid taller than its box must still be reachable from its first row (loupe.css says why) */
  align-content: safe center;
  justify-content: safe center;
  grid-template-columns: repeat(var(--grid-columns, auto-fit), var(--cell-size, 154px));
  gap: var(--cell-gap, 18px);
}
.fam-grid .loupe-grid {
  /* ⚠⚠ A CELL NEVER OUTGROWS THE PAGE. --cell-size is a fixed length; --cell is what is actually drawn — the
     template's own size, or the width there is divided by the columns, whichever is smaller. */
  --cell: min(var(--cell-size, 154px),
              calc((var(--page-width, 100vw) - 2 * var(--credit-inset-x, 5vw) - (var(--grid-columns, 1) - 1) * var(--cell-gap, 18px)) / var(--grid-columns, 1)));
  grid-template-columns: repeat(var(--grid-columns, auto-fit), var(--cell));
  /* ⚠⚠ A CELL'S HEIGHT IS ITS OWN (2026-10-10, `flush`): the width times the frame's shape, height ÷ width — 1 on every
     grid but one, so a square cell is still exactly what it was. Every height below reads this, never `--cell`, so a
     tall or wide frame reaches the lead, a work given more rows, and the picture over a label alike. */
  --cell-h: calc(var(--cell) * var(--cell-ratio, 1));
  /* ⚠⚠ EVERY GAP IS FILLED (2026-09-22, the owner, after a work made two columns wide in the last column dropped a row and
     left a hole above it: "fill every gap, go ahead"). `dense` lets the browser pull the next work that fits up into any
     hole a span opens, so a wall never shows a blank; the record's order is untouched, only the drawing departs from it
     at that one spot — the work pulled up keeps its own number. Without it the grid is sparse and the hole stays. */
  grid-auto-flow: row dense;
}
/* ⚠⚠ THE CELL'S OWN SIZE, at class weight ON PURPOSE. A template that pins its cells — `deckle`, whose cells take their
   work's height — must win here, and used to win or lose by which file was linked last (presets.css → the deckle note).
   At class weight the pin always wins, in a gallery and in the card alike, and a work given more of the row (below) is
   written at id weight so it wins over both. */
.fam-grid .loupe-grid > .cell { width: var(--cell); height: var(--cell-h); }
/* ⚠ …unless the template carries its label under each work (`lb-under`, 2026-09-19): the cell is then the pair —
   the picture at the cell's size, the card beneath it — so its HEIGHT comes from its contents. The width is still
   the column's, and `align-content` keeps the rows together. loupe.css → THE LABEL UNDER EACH WORK has the rest. */
.fam-grid.lb-under .loupe-grid > .cell { height: auto; align-self: start; }
/* ⚠⚠ EVERY ROW THE SAME (the owner, 2026-09-19: even rows are "a requirement for this"). `--row-h` is measured —
   loupe.js → sizeRows on a page, themes.html on a card — because CSS cannot ask for the tallest of all the rows,
   and how far a record wraps depends on the face it is set in. Unmeasured it falls back to `auto`, which is the
   stepped wall, so a page that never runs the measurement still draws, just unevenly. */
.fam-grid.lb-under .loupe-grid { grid-auto-rows: var(--row-h, auto); }
/* the lead — one work larger, with the rest filling in around it */
.fam-grid.grid-hero .loupe-grid > .cell:first-child {
  grid-column: span 2;
  grid-row: span 2;
  width:  calc(var(--cell) * 2 + var(--cell-gap, 18px));
}
/* ⚠⚠ …TWO ROWS TALL UNLESS IT SAYS HOW MANY (2026-10-10, the owner, of case's lead: "set it to any size the other photos
   can take"). The height sat in the rule above, so a lead given *rows: one* spanned one row and stood two rows tall — 152 ×
   318 on case, its row grown to 318 and an empty band beside it, on all five templates with a lead. A lead that says its
   rows is sized as any work that says them (below): one is whatever the template makes a cell (ONE ROW IS THE TEMPLATE'S
   OWN ROW), two to four are their rows. `:where()` adds nothing to the weight, so for a lead that says nothing this is
   exactly the rule it was. */
.fam-grid.grid-hero .loupe-grid > .cell:first-child:not(:where([data-tall])) {
  height: calc(var(--cell-h) * 2 + var(--cell-gap, 18px));
}
/* ⚠⚠ A WORK GIVEN MORE OF THE ROW (2026-09-19): `--wide` columns across and `--tall` rows down, the gaps counted in,
   so the cell lands on the grid's own lines and the works after it flow around, as a grid does. */
.fam-grid :is(#grid, .loupe-grid) > .cell[data-wide] {
  grid-column: span var(--wide, 1);
  width: calc(var(--cell) * var(--wide, 1) + var(--cell-gap, 18px) * (var(--wide, 1) - 1));
}
.fam-grid :is(#grid, .loupe-grid) > .cell[data-tall] {
  grid-row: span var(--tall, 1);
}
/* ⚠⚠ ONE ROW IS THE TEMPLATE'S OWN ROW (2026-09-24, the owner, placing cuttings on `deckle`: a whole, upright silhouette set to
   *rows: one* spilled below its cell, under the work beneath it). The height here is for a work given MORE rows; written for
   every [data-tall] it also pinned an explicit one (0103 keeps one as one) to a fixed one-cell height, at id weight — over
   `deckle`'s own rule that a cell takes its work's height — so a picture 291px tall stood in a cell of 152. From two rows up
   the cell is its rows; at one it is whatever the template makes a cell. */
.fam-grid :is(#grid, .loupe-grid) > .cell[data-tall]:not([data-tall="1"]) {
  height: calc(var(--cell-h) * var(--tall, 1) + var(--cell-gap, 18px) * (var(--tall, 1) - 1));
}
/* ⚠ THE WHOLE ROW (0103; the owner, 2026-09-24, of a wide stack of gold figures: "it may have to sit by itself on a whole
   row"). Every column the grid has at this window's width — not a number, since that changes with the window — and the
   cell as wide as those columns and their gaps. Its height is still its rows'. */
.fam-grid :is(#grid, .loupe-grid) > .cell[data-wide="row"] { grid-column: 1 / -1; width: auto; justify-self: stretch; }
