/* Photo placeholder */
.bx .photo {
  position: relative;
  background:
    linear-gradient(135deg, rgba(var(--bx-accent-rgb),0.08), rgba(var(--bx-teal-rgb),0.08)),
    repeating-linear-gradient(135deg,
      var(--bx-paper-2) 0 12px,
      var(--bx-paper-3) 12px 24px);
  color: var(--bx-ink-3);
  display: flex;
  align-items: end;
  justify-content: start;
  padding: 10px 12px;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-2xs);
  letter-spacing: 0;
  text-transform: uppercase;
  overflow: hidden;
}
.bx-dark .photo {
  background:
    linear-gradient(135deg, rgba(var(--bx-accent-rgb),0.18), rgba(var(--bx-teal-rgb),0.18)),
    repeating-linear-gradient(135deg,
      rgba(var(--bx-white-rgb),0.03) 0 12px,
      rgba(var(--bx-white-rgb),0.06) 12px 24px);
  color: rgba(var(--bx-white-rgb),0.6);
}
/* Restore the light placeholder for a .photo inside a .bx-light-surface
   island nested in a .bx-dark page (see cards.css for the same pattern). */
.bx-light-surface .photo {
  background:
    linear-gradient(135deg, rgba(var(--bx-accent-rgb),0.08), rgba(var(--bx-teal-rgb),0.08)),
    repeating-linear-gradient(135deg,
      var(--bx-paper-2) 0 12px,
      var(--bx-paper-3) 12px 24px);
  color: var(--bx-ink-3);
}
.bx .photo::before {
  content: '';
  position: absolute; inset: 8px;
  border: 1px dashed var(--bx-line-2);
  border-radius: var(--bx-r-sm);
  pointer-events: none;
}
.bx .photo > .photo-label {
  position: relative; z-index: 1;
  background: rgba(var(--bx-white-rgb),0.85);
  color: var(--bido-navy);
  padding: 3px 7px; border-radius: var(--bx-r-sm);
  font-weight: 600;
  /* The label is decorative — it sits over the photo placeholder gradient as
     a caption. .bido-card-link (the stretched anchor that turns a card into
     one big click target) shares z-index: 1 with this span and the span is
     later in DOM order, so without this guard the label intercepts clicks
     on the bottom of every photoless card on /plan, /vibes, etc. */
  pointer-events: none;
}
.bx-dark .photo > .photo-label { background: rgba(var(--bx-navy-rgb),0.65); color: rgba(var(--bx-white-rgb),0.85); }
.bx-light-surface .photo > .photo-label { background: rgba(var(--bx-white-rgb),0.85); color: var(--bido-navy); }
.bx .photo.photo-real {
  background: var(--bx-paper-2);
  padding: 0;
}
.bx .photo.photo-real::before { content: none; }
.bx .photo-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Ratio + radius modifiers. The photo helpers (`photo`, `listing_photo`,
   `attached_photo` in app/helpers/bido_helper.rb) used to inline these as
   `style="aspect-ratio: N; border-radius: Npx"` on every callsite, which
   violated the CSS guide rule against inline static layout. The four
   ratios + four radii below cover every consumer; anything outside this
   set still falls through to inline (kept as a back-compat shim). */
.bx .photo--ratio-4x3   { aspect-ratio: 4 / 3; }
.bx .photo--ratio-16x10 { aspect-ratio: 16 / 10; }
.bx .photo--ratio-1x1   { aspect-ratio: 1 / 1; }
.bx .photo--ratio-auto  { aspect-ratio: auto; }

.bx .photo--radius-none { border-radius: 0; }
.bx .photo--radius-sm   { border-radius: var(--bx-r-sm); }
.bx .photo--radius      { border-radius: var(--bx-r); }
.bx .photo--radius-lg   { border-radius: var(--bx-r-lg); }

/* Named size modifiers — the fixed thumbnail/cover sizes the app uses, so
   callsites don't inline static height/width (cart rows, booking covers,
   vendor table cells). */
.bx .photo--fill     { block-size: 100%; }
.bx .photo--thumb    { block-size: 60px; }
.bx .photo--thumb-sm { inline-size: 40px; block-size: 40px; }

