/* vanta-tiles.css — PRODUCT-TILE IMAGE FRAMING (catalogue grid).
 *
 * ── WHY THIS FILE EXISTS ──────────────────────────────────────────────────
 * Every catalogue tile was cutting the flip-off cap off the top of the vial and
 * the foot off the bottom, on every SKU. It reads worst on NAD+, because that
 * one is amber glass under a bright silver cap, so the flat-topped cap is the
 * first thing the eye lands on.
 *
 * It is not a masking defect in the artwork. `vial.mjs` keys a genuine alpha
 * cut-out off the frozen base's white ground and it is clean — measured over a
 * hostile magenta ground, no halo, no hard fringe — and all eleven masters share
 * one bounding box to the pixel (x 325-1427, y 192-1833 on a 2000² canvas).
 * The crop is CSS, and the arithmetic is exact:
 *
 *   · the tile media box is 4:3            (--sf-thumb-aspect, theme.css)
 *   · this client's layout resolves        --sf-thumb-fit: cover  (theme.css:917)
 *   · every product render is 1:1          (vial.mjs emits a square canvas)
 *
 * `cover` scales a square to fill a 4:3 box by WIDTH, so the top and bottom
 * eighth of the frame are thrown away — and that is precisely where the cap and
 * the base sit. Measured on the shipped build at a 330px tile: content box
 * 274 × 191.5, image drawn 274 × 274, 41.25px discarded top and bottom, which
 * eats 15px of a 46px cap (a third of it) and 18px of the base. The hover zoom
 * then took a second bite — scale(1.44) about the centre, with nothing left to
 * give.
 *
 * ── THE FIX ───────────────────────────────────────────────────────────────
 * `contain`, so the whole render is inside the box by construction and the tile
 * can never crop a vial again no matter what a later stage does to the tile
 * width, the grid or the aspect token.
 *
 * The padding is what keeps that from shrinking the vial: it is stated in
 * PERCENT, which resolves against the box WIDTH on all four sides, so the
 * composition is scale-invariant — identical at the 330px desktop tile, the
 * ~170px mobile tile, and a stretched row where the media box is taller than
 * 4:3. Top is deliberately lighter than bottom: it lifts the vial off the
 * "For Research Use Only" scrim pinned to the bottom of the media box
 * (products.html, `#product-grid .sf-card-media::after`) so the foot sits at the
 * scrim's transparent edge rather than inside it.
 *
 * At a 330px tile that lands the vial 181px tall — against 191.5px of VISIBLE
 * vial before, out of the 225px it should have been. Same visual weight, whole
 * object.
 *
 * ── THE HOVER ZOOM HAS A CEILING, AND IT IS ARITHMETIC ────────────────────
 * The vial is 73% of the media box's height at rest, so a zoom past ~1.37 can
 * NOT show all of it — the object is simply taller than the box at that point.
 * 1.22 is the working figure: it leaves 7px of headroom above the cap and 21px
 * under the foot at the top of the animation. If someone raises it, raise the
 * media box first (`--sf-thumb-aspect: 1`) or the crop comes straight back.
 *
 * The Research Case tile is EXEMPT and stays on `cover` + scale(2.2). That tile
 * is a flat product case, not a vial: it has no silhouette to protect and its
 * whole treatment is "fill the box with minimal backdrop" (the rule and its
 * reasoning are in products.html). Excluding it by attribute rather than by
 * SKU means a second case never has to be remembered.
 *
 * ── SPECIFICITY, STATED BECAUSE IT IS LOAD-BEARING ────────────────────────
 * The rules being replaced live in products.html's own inline <style>, which is
 * later in the document than any <link> in <head>, so source order cannot win
 * this. Every selector here is ID-anchored on #product-grid (1,2,1) against
 * their (0,2,1) and (1,1,1), and the hover rule restates `!important` because
 * the rule it supersedes carries one.
 *
 * ── WHERE IT COMES FROM ───────────────────────────────────────────────────
 * A top-level `frontend/*.css` is already a first-class build input: build.mjs
 * copies it into the output and links it into every template-emitted page right
 * after /theme.css (linkClientStylesheets, ~1584 / clientCss, ~1802). So this
 * survives a rebuild with nothing to opt in and no post-build layer to run.
 */

/* Whole render, never cropped. */
#product-grid .sf-card-media img {
  object-fit: contain;
  /* top · sides · bottom — percent of the box WIDTH, so this holds at any tile size. */
  padding: 2.2% 8.5% 6.4%;
}

/* Hover / keyboard focus: the largest zoom that still shows the whole vial. */
#product-grid article:hover .sf-card-media img,
#product-grid article:focus-within .sf-card-media img {
  transform: scale(1.22) !important;
}

/* The Research Case keeps its own treatment. */
#product-grid article[data-category="accessories"] .sf-card-media img {
  object-fit: cover;
  padding: 28px;
}
#product-grid article[data-category="accessories"]:hover .sf-card-media img,
#product-grid article[data-category="accessories"]:focus-within .sf-card-media img {
  transform: scale(2.2) !important;
}
