/* ==========================================================================
   Grids — the layout side of tools/grid.json.

   A photograph declares WHICH GRID it sits in and nothing else: no width, no
   srcset, no sizes. core/media.js turns the grid into the `sizes` attribute
   through the generated table in core/grid.js, and tools/build-images.py used
   the same table to decide which widths to encode. Three things, one fact.

   Most of NAMI's widths are already stated by the section that owns them —
   .svc--facials is span 5 of 12 in services.css, .gallery__item--tall is
   clamp(15rem, 22vw, 22rem) in gallery.css — so this file does not restate
   them. A g- class is the NAME of that width, and the pairing is asserted in
   tools/grid.json where both halves are written down together. What lives here
   is only what every grid shares.
   ========================================================================== */

/* A mounted photograph fills the box it was given and is cropped, never
   letterboxed. Section stylesheets say this for their own figures too; stating
   it once here means a new slot dropped into a new box behaves before anyone
   has written a rule for it. */
[data-img] > picture { display: block; width: 100%; height: 100%; }
[data-img] > picture > img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------
   The reservation, and where it must not apply.

   core/media.js reserves a figure's box from the slot's aspect ratio BEFORE
   fetching anything, so the document reaches its true height first and no
   photograph is requested merely because an empty skeleton made every section
   look near the viewport. It does that with an inline min-height, which it
   clears the moment the picture is built.

   Every box below already reserves its own height — an aspect-ratio, or
   inset: 0 against a parent that has one. For those the reservation is at best
   redundant, and where the crop's ratio differs from the tile's it is wrong:
   the lashes tile is 4/3 and its crop is square, so the reservation would
   stretch the tile until the photograph arrived and then snap it back. The box
   was never unreserved, so the inline value is refused.

   !important is the mechanism because the value it overrides is inline. It is
   scoped to boxes whose own stylesheet gives them a height, and nothing else.
   -------------------------------------------------------------------------- */
.svc,
.gallery__item,
.ritual__media,
.booking__bg,
.story__main,
.story__inset,
.contact__media .frame { min-height: 0 !important; }

/* --------------------------------------------------------------------------
   The grids themselves.

   g-hero / g-hero-tall   the opening frame and its phone recomposition
   g-ritual               one of the three ritual panels
   g-story / g-inset      the story photograph and the square that overlaps it
   g-svc-*                the six services bento tiles, one grid per span set
   g-tall / g-wide / g-small   the three shapes in the drag gallery
   g-bleed                the palm-shadow band behind the booking call to action
   g-contact              the treatment-room photograph in the contact column
   g-share                not a layout: the social card

   They carry no rules of their own. That is deliberate: a class here that also
   set a width would be a second place for a width to live, and the whole point
   of tools/grid.json is that there is one.
   -------------------------------------------------------------------------- */
