/* Denzl — image_viewer.css
 *
 * One full-screen viewer for any image worth looking at closely. The first
 * caller is the try-on render: a card tile shows it at ~170px wide under
 * `object-fit: cover`, so the one thing a man asked to see — himself in the
 * garment — is both small and CROPPED. Opening it `contain` is most of the
 * fix; the zoom is the rest.
 *
 * Chrome is the house B&W (docs/brand/design-language.md): near-black ground,
 * white marks, no accent colour anywhere.
 */

.dz-viewer {
  position: fixed;
  inset: 0;
  z-index: 2147483000; /* above the Ask bubble and the app drawer */
  display: none;
  background: #0B0B0B;
  /* The pan mechanism. When the image is wider than this box the browser
     scrolls it natively — no drag handler, no momentum to reimplement, and it
     keeps working if the JS ever fails to bind. */
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.dz-viewer[open],
.dz-viewer.is-open {
  display: block;
}

/* Locks the page behind the viewer so a pan does not scroll the feed. */
body.dz-viewer-open {
  overflow: hidden;
}

.dz-viewer-stage {
  min-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.dz-viewer-img {
  display: block;
  max-width: 100%;
  max-height: 100vh;
  /* CONTAIN, not cover. The card crops; this is where the whole render is
     visible for the first time. */
  object-fit: contain;
  margin: auto;
  /* The stage is a flex container, so the image is a flex item and the default
     `flex-shrink: 1` silently pulls a 250%-wide image back down to the
     container width. The zoom class applied, the width never changed, and
     nothing looked broken from the DOM. */
  flex: 0 0 auto;
  user-select: none;
  -webkit-user-drag: none;
  /* Deliberately NOT transitioned. Animating the width meant the centring
     scroll ran against a box that was still 375px wide, so a zoom landed at
     the left edge — a crop of his shoulder — instead of the middle. An
     instant resize is also the honest gesture: a photo viewer should snap. */
}

/* Gear two. Width beyond the viewport is what makes the container scrollable,
   so panning comes free.
 *
 * The stage drops OUT of flex to do it. A flex item will not exceed its line
 * box however you size it — with `flex: 0 0 auto` and an inline
 * `width: 937px` the image still measured 375px, so this is layout refusing,
 * not a cascade fight to be won with more specificity. Block layout lets an
 * over-wide child overflow, which is exactly the behaviour the scroll
 * container needs. */
.dz-viewer.is-zoomed .dz-viewer-stage {
  display: block;
}

.dz-viewer.is-zoomed .dz-viewer-img {
  /* Width is set inline by the script: the useful ceiling is the image's own
     pixel count, which CSS cannot see. A flat 250% blew a 600px catalog photo
     up to 3,185px on a desktop viewport — five times its real resolution, so
     the "zoom" showed strictly less than the fitted view did, only bigger and
     softer. */
  max-width: none;
  max-height: none;
  cursor: zoom-out;
}

.dz-viewer:not(.is-zoomed) .dz-viewer-img {
  cursor: zoom-in;
}

/* Box, glyph and 44px target come from .dz-close / --light (app-shell.css);
   this rule only places it and gives it a plate. It used to be a round
   translucent disc carrying a 20px text × — the biggest close in the app,
   and the one Bharat picked out of the try-on viewer on 2026-09-05. The
   plate is DARK now, not white-on-white: a zoomed image fills the frame,
   so a 14% white disc vanished over any pale garment. */
.dz-viewer-close {
  position: fixed;
  top: max(12px, var(--dz-safe-top, 0px));
  right: max(12px, var(--dz-safe-right, 0px));
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(6px);
}

.dz-viewer-close:hover,
.dz-viewer-close:focus-visible {
  background: rgba(0, 0, 0, 0.66);
  outline: none;
}

/* The one line of copy. Says what the picture is and how to leave. */
.dz-viewer-hint {
  position: fixed;
  left: 0;
  right: 0;
  bottom: max(14px, var(--dz-safe-bottom, 0px));
  text-align: center;
  color: rgba(255, 255, 255, 0.62);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  pointer-events: none;
}

.dz-viewer.is-zoomed .dz-viewer-hint {
  opacity: 0;
}

/* ---------------------------------------------------------------------------
 * The affordance (2026-08-26)
 *
 * The viewer worked and read as absent. Tap-to-zoom was live on the try-on
 * render and on the PDP hero, and no surface said so — on a Discover tile the
 * only thing a tap had ever done was open the product, so nobody tried it, and
 * the product photo itself was never zoomable at all.
 *
 * A card cannot resolve this by making the picture tappable: the tap on a feed
 * card is spoken for — it goes to the product page, which is the card's whole
 * job. So the way to enlarge is an explicit control, small, monochrome, and in
 * the same chrome as save and dismiss (docs/brand/design-language.md).
 * ------------------------------------------------------------------------ */

/* A slot rather than a bare button: the control has to sit at the bottom-right
   of the PICTURE, and on three of the four surfaces the picture is smaller
   than the box that contains it. Each surface narrows the slot below; the
   button only ever knows its own corner. */
.dz-zoom-slot {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;  /* the slot covers the image; only the button takes taps */
}

.dz-zoom-btn {
  position: absolute;
  right: 8px;
  bottom: 8px;
  height: 30px;
  width: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid #E8E8E8;
  color: #1A1A1A;
  cursor: zoom-in;
  pointer-events: auto;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.dz-zoom-btn svg {
  width: 14px;
  height: 14px;
  display: block;
}

/* 30px matches the card's own save/dismiss density, which is the house look;
   this grows the TOUCH target to 44px without growing the mark.

   DEN-1879: the inset is measured from the PADDING box, and the button carries
   a 1px border — so `-7px` bought 28 + 14 = 42px, not 44, and the right and
   bottom probe points landed on the image behind. `-8px` is the arithmetic
   the comment always claimed. */
.dz-zoom-btn::after {
  content: "";
  position: absolute;
  inset: -8px;
}

.dz-zoom-btn:hover,
.dz-zoom-btn:focus-visible {
  background: #FFFFFF;
  border-color: #1A1A1A;
  outline: none;
}

/* Discover / Search tile. The control lives ABOVE the card's anchor — a
   <button> inside an <a> is invalid, and the existing save and dismiss
   controls already sit outside it for the same reason — so the slot has to
   re-state the media well's 3:4 box rather than inherit it. */
.feed-card > .dz-zoom-slot {
  inset: 0 0 auto 0;
  aspect-ratio: 3 / 4;
  z-index: 9;
}

/* PDP try-on render. `.result` is wider than the render on desktop: the image
   is capped at 320px and centred, so the slot mirrors that box exactly rather
   than the panel's. */
.pd-tryon .result > .dz-zoom-slot {
  inset: 0 0 auto 0;
  width: 100%;
  max-width: 320px;
  aspect-ratio: 3 / 4;
  margin: 0 auto;
}

/* Nothing to enlarge while it renders, and a rejected photo is shown dimmed
   under an X on purpose — offering to blow that up is offering the wrong
   thing. */
.pd-tryon .result.rendering > .dz-zoom-slot,
.pd-tryon .result.rejected > .dz-zoom-slot {
  display: none;
}

/* Desktop's half of the same message. A picture that opens on click should say
   so under the pointer; the button is what carries it on a phone, where there
   is no hover to say anything. */
img[data-zoomable] {
  cursor: zoom-in;
}

/* Dressing Room canvas. The look sits in a 2rem-radius frame under
   `overflow: hidden`, and a rounded overflow clip takes the HIT TEST with the
   paint: anything outside the arc is not merely unpainted, it is untappable.
   TOP-right, not bottom-right: the canvas's bottom corners are taken (thumbs
   right, the AI-preview tag left), and at bottom-right this button sat ON the
   thumbs — Bharat's phone, 2026-08-29. The top corners are empty on every
   state that renders a zoom.

   DEN-1879: 14px cleared the curve for the 30px MARK and not for the 44px
   TARGET around it. The target's corner sits 7px from each edge, and a point
   7px in from a 32px radius is 35px from the arc's centre — outside it, so
   the corner a thumb aims at was being clipped away. 20px puts that corner
   13px in, comfortably inside the arc, and moves the mark by six pixels. */
[data-look-canvas] .dz-zoom-btn {
  right: 20px;
  top: 20px;
  bottom: auto;
}

/* Your 100 hero. Same collision, same resolution — twice over now. The
   look-feedback thumbs take the picture's bottom-LEFT (since 2026-09-06: the
   bottom-right is the fixed Ask orb's corner and it covered the thumbs-down),
   and since 2026-09-03 the hero's collapse control takes the MODULE's
   top-right (it is the module's chrome, not the picture's). Zoom keeps the
   top-left, the corner it has always held. No rounded frame here, so the
   default 8px inset stands. */
.stylist-today-visual .dz-zoom-btn {
  left: 8px;
  right: auto;
  top: 8px;
  bottom: auto;
}
