/**
 * data-img - the image treatment seam. The seam with no JavaScript.
 *
 * Contract: selected by data-img on the .media wrapper, or on any ancestor of
 * it. Markup:
 *   <figure class="media" data-img="tint">
 *     <img src="assets/img/plate-wide.svg" alt="...">
 *   </figure>
 * data-img may sit on the figure, on the slide <section>, or on an outer
 * <section> wrapping a vertical stack; the NEAREST one wins.
 *
 * Invariant: resolved by CUSTOM PROPERTY INHERITANCE, never by a descendant
 * selector. `[data-img="duotone"] img { ... }` looks equivalent and is not: an
 * outer section carrying one treatment and a slide inside it carrying another
 * both match the same <img>, and the winner is then decided by specificity and
 * source order - identical here, so the LAST-DECLARED treatment would win for
 * every slide in the stack regardless of which ancestor is nearer. Inherited
 * properties resolve by tree walk, so proximity wins.
 *
 * Invariant: composes from tier-3 roles only, so a preset switch re-themes
 * every treated image. `make check` sweeps this file.
 *
 * Invariant: .media carries `isolation: isolate`, so the wash blends against
 * the picture beneath it rather than against whatever the nearest ancestor
 * stacking context happens to be. Note the hazard that makes this fragile:
 * backdrop-filter, filter, transform, opacity and will-change EACH create a
 * stacking context, so a .media wrapper dropped inside any of them silently
 * changes what it blends against. css/layouts/bento.css unsets its tile blur
 * on .tile.media for exactly this reason.
 */

.media {
  isolation: isolate;
  position: relative;
  display: block;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
}

/* mask-mode/size/repeat sit on the base rule rather than under a cutout
   selector. They are inert while mask-image is `none`, which it is for every
   other treatment, and scoping them to the treatment does not work: data-img
   sits on the .media element itself, so `[data-img="cutout"] .media img` would
   demand a .media descendant of a .media element and match nothing. The mask
   would silently never apply and cutout would render as an ordinary tint. */
.media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--img-filter, none);
  mask-image: var(--img-mask, none);
  mask-mode: luminance;
  mask-size: cover;
  mask-repeat: no-repeat;
}

/* The wash layer. `none` for both defaults means an untreated image pays for
   an empty pseudo-element and nothing else - which is why .media img can be
   written once rather than once per treatment. */
.media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--img-wash, none);
  mix-blend-mode: var(--img-blend, normal);
}

/* Every treatment declares ALL THREE properties, and that is not redundancy:
   these are INHERITED custom properties, so a treatment that omits one
   inherits whatever a data-img further up the tree set - the nearest ancestor
   would win for two properties and an outer one for the third, which breaks
   the proximity contract this file's header describes. */

/* The default: an image that reads as brand-coloured. */
[data-img="tint"] {
  --img-filter: grayscale(1) contrast(1.05);
  --img-wash: var(--accent-key);
  --img-blend: color;
}

/* Shadows to one brand hue, highlights to another. --duotone-wash rather than
   a literal gradient here because mixing two brand ramps into one value is
   colour composition, which a component may not do - see css/brand/_engine.css. */
[data-img="duotone"] {
  --img-filter: grayscale(1) contrast(1.15);
  --img-wash: var(--duotone-wash);
  --img-blend: color;
}

/* For text over image: flatten the range so type stays legible on top. The
   veil is --img-veil, not --ground: --ground is opaque (it is var(--bg)), and
   an opaque wash at mix-blend-mode: normal COVERS the picture rather than
   veiling it - which renders as an empty rectangle the exact colour of the
   slide behind it. --img-veil is the same colour with the transparency the
   word "wash" implies. */
[data-img="wash"] {
  --img-filter: grayscale(1) contrast(0.55) brightness(1.15);
  --img-wash: var(--img-veil);
  --img-blend: normal;
}

/* Decorative art that must not compete with content. The whole treatment is
   the opacity in the filter; there is deliberately no wash on top of an image
   that is already 32% opaque. */
[data-img="ghost"] {
  --img-filter: grayscale(1) contrast(0.6) opacity(0.32);
  --img-wash: none;
  --img-blend: normal;
}

/* The image's own luminance as a mask, filled with the accent. The one
   treatment that cannot be expressed in inherited properties alone: a
   luminance mask needs the image's URL, and CSS cannot reach the src of a
   descendant <img>. The authoring form is an inline --img-src on the wrapper
   ALONGSIDE the ordinary src:
     <figure class="media" data-img="cutout"
             style="--img-src: url('assets/img/x.svg')">
       <img src="assets/img/x.svg" alt="...">
     </figure>
   The path is therefore written twice and NOTHING CHECKS THAT THE TWO AGREE -
   the parent framework had a check for exactly this and it did not survive the
   trim. A cutout masked by one image while displaying another renders as a
   plausible picture, so it fails silently. Keep the two on adjacent lines. */
[data-img="cutout"] {
  --img-filter: grayscale(1) contrast(1.4);
  --img-mask: var(--img-src, none);
  --img-wash: var(--accent-key);
  --img-blend: color;
}
