/* ==========================================================================
   PHOTOGRAPH INTEGRITY
   --------------------------------------------------------------------------
   These rules are binding. The photographs are the product, not illustration
   of it — their exact tonal content is what the customer receives in the mail.

   See plan/decisions/0002-photograph-integrity.md.

   NEVER apply to a catalog photograph, or to any ancestor of one:
     filter, backdrop-filter, opacity, mix-blend-mode, transform, box-shadow
     that overlaps, background showing through, overlay pseudo-element,
     border drawn inside the image box, object-fit: cover, or any crop.

   Selection, focus, hover, error and loading states render OUTSIDE the image.
   `outline-offset` is the workhorse: it draws clear of the photograph.

   A transform or opacity on a wrapper affects the image inside it, so the
   prohibition is inherited upward — not just on the <img> itself.
   ========================================================================== */

.photo {
  /* 4 x 6 portrait. Every photograph, every surface, no exceptions. */
  aspect-ratio: 2 / 3;
  display: block;
  position: relative;
  overflow: hidden;              /* only ever clips the mat, never the image */
  background: var(--mat);
  border-radius: 1px;
}

.photo__img {
  display: block;
  width: 100%;
  height: 100%;

  /* `contain` guarantees the whole frame is visible. `cover` is banned —
     it crops silently, which would sell a photograph the customer will not
     receive. If a source is ever slightly off-ratio it letterboxes against
     the mat and is caught by review, rather than being trimmed unseen. */
  object-fit: contain;

  /* Explicitly neutralise anything a global stylesheet might introduce. */
  filter: none;
  opacity: 1;
  mix-blend-mode: normal;
  box-shadow: none;
  border: 0;
  transform: none;
  transition: none;
}

/* Loading placeholder. Occupies the correct box, but must never be mistaken
   for merchandise — no photographic grey, no shimmer that reads as an image. */
.photo--pending {
  background:
    repeating-linear-gradient(
      45deg,
      var(--mat) 0 8px,
      var(--mat-alt) 8px 16px
    );
}

.photo--pending::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px dashed var(--rule-strong);
  border-radius: 1px;
}

/* A position whose photograph is no longer available. The gap is shown as a
   gap — never backfilled with a substitute the shopper did not choose. */
.photo--unavailable {
  background: var(--mat-alt);
  display: grid;
  place-items: center;
}

.photo--unavailable::after {
  content: "Unavailable";
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* ==========================================================================
   A composed word, as the photographs that spelled it
   ========================================================================== */

/*
  TWO SIZES AND NO THIRD.

  `--thumb` for a list of orders, `--natural` for one order's detail. Natural
  means the web derivative's own 320x480 and no larger: that is the biggest
  photograph this shop puts on the internet, and the ceiling is a decision
  rather than an accident. Decision 0021.

  `max-width` rather than `width` on the natural size, so a long word wraps
  and a narrow screen shrinks it — smaller than natural is fine, larger is
  never fine.
*/
.word {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  min-width: 0;
}

.word__letter { display: block; min-width: 0; }

/* Inherits every prohibition .photo__img carries — no filter, no crop, no
   shadow, nothing that alters what was photographed. Decision 0002. */
.word__img {
  display: block;
  height: auto;
  background: var(--mat);
  object-fit: contain;
  filter: none;
  opacity: 1;
  mix-blend-mode: normal;
  box-shadow: none;
  border: 0;
  transform: none;
}

.word--thumb { gap: 0.15rem; }
.word--thumb .word__img { width: 2rem; }

/*
  NATURAL IS A CEILING, NOT A WIDTH — and the word stays on one line.

  Two wrong turns worth recording, because both look reasonable in a
  stylesheet and neither survives a real word. A flat `width: 320px` overflowed
  the card and wrapped one letter per row. Then `flex: 0 1 320px` did the same,
  for a subtler reason: a wrapping flex line packs items at their basis and
  wraps the overflow, so nothing is ever asked to shrink — each letter got its
  own line and its full 320px.

  A grid row is the tool, and it is the same one the landing page already uses
  to spell HANGARANG across nine columns. Columns share the width equally and
  cap at natural size, so a three-letter word sits near 320px each and a
  twelve-letter one gets small — still a word, read left to right, rather than
  a column of unrelated pictures.
*/
.word--natural {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 320px);
  justify-content: start;
}
.word--natural .word__img { width: 100%; }

/* A photograph whose file could not be found. Named, never substituted. */
.word__missing {
  display: grid;
  place-items: center;
  width: 2rem;
  aspect-ratio: 2 / 3;
  background: var(--surface-alt);
  color: var(--ink-faint);
  font-size: 0.75rem;
}
.word--natural .word__missing { width: 5.5rem; font-size: 1.25rem; }
