/* ARBY product shell — the OpenDesign od/*.html preview chrome (.stage/.frame/.vp-body)
   fills a fixed 1440x900 preview; the Django product serves the same .app full-viewport.
   This file only adapts the shell; every component rule stays the od CSS untouched. */

html,
body {
  height: 100%;
}

/* The od frame is a fixed-size preview panel with a shadow; the product is the page itself. */
#frame.frame {
  width: 100%;
  height: 100dvh;
  box-shadow: none;
}

#frame.frame .vp-body {
  height: 100%;
}

/* Desktop parity: the od preview hides the bottom nav; the product shows it under 720px. */
.frame[data-bp="desktop"] .bottomnav {
  display: none;
}

.frame[data-bp="mobile"] .bottomnav {
  display: flex;
}

.frame[data-bp="mobile"] .layout {
  display: block;
}

.frame[data-bp="mobile"] .rail {
  display: none;
}

/* Server-rendered pagination (round one) — composed from od tokens only. */
.pager {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px 4px 6px;
}

.pager .chip[aria-pressed="true"] {
  border-color: color-mix(in oklab, var(--margin) 55%, var(--border));
  color: var(--fg);
}

.pager a.btn {
  text-decoration: none;
}

/* Filter rail needs the rail scroll to fit the viewport on desktop (the od prototype
   scrolled the whole stage; the product scrolls only .app-scroll). */
.layout {
  align-items: start;
}

.rail {
  position: sticky;
  top: 0;
  align-self: start;
}

/* The sort bar / quick chips are anchors in server mode; keep the od button silhouette. */
a.sortbtn,
.chiprow a.chip {
  text-decoration: none;
}

/* The "seen" onboarding redirect page. */
body[data-screen=""] .app-scroll > section {
  min-height: 60dvh;
  display: grid;
  place-content: center;
  gap: 10px;
  text-align: center;
}

/* The od classes set display on their elements, which beats the UA [hidden] rule. */
[hidden] {
  display: none !important;
}

/* The unified no-photo placeholder (2026-10-02): one asset (od/assets/placeholder.jpg) for
   every listing without stored image_urls. The od scrim (.deal-media::after) is untouched;
   this only softens the light no-photo artwork so it sits in the card's dark rhythm and reads
   as a placeholder at a glance. No layout change - the img keeps the same 100%/cover box as
   real photos, so the feed rhythm is uniform. */
.deal-photo--placeholder {
  filter: brightness(0.86) saturate(0.85);
}

/* Uniform card media (2026-10-02): every image - real photo or placeholder - fills the SAME
   16:9 frame. The od aspect-ratio rule alone loses to the flex base size (an in-flow img
   resolves the box from its intrinsic height, so cards drifted by photo ratio), so the img is
   pinned to the frame. The od scrim, src chip and margin badge are already positioned. */
.deal-media img {
  position: absolute;
  inset: 0;
}
