/* R4 — the shared mechanics. Ten compositions, one idea underneath.
   ------------------------------------------------------------------
   THE BLANK-DESKTOP FIX

   The old viewer was a wide fixed box with the artefact contained inside
   it. A 0.68 phone screenshot in a 1.6 box is 42% picture and 58% empty
   room, and on a large screen that reads as a bug.

   Here the frame takes the ARTEFACT's ratio, so the picture fills its
   frame exactly — zero letterboxing, whatever the shape. What stays
   fixed is the BAND: its height, its position, and the controls above
   and below it never move. What adapts is how many artefacts stand in
   that band, which is chosen so the row fills the width exactly:

     4 phone screenshots, or 2 dashboards, or 3 ad screenshots.

   Same band, same buttons, same pager, always full.

   On a phone the same rule runs down instead of across.
   ------------------------------------------------------------------ */

/* No html/body rules live here. This file is loaded by the homepage as
   well as by the ten lab pages, and a `body{overflow:hidden}` in a shared
   mechanics file freezes whatever page happens to include it. The lab
   pages declare their own app-shell lock. */

:root{
  --r4-ease:cubic-bezier(.22,.68,.28,1);
  --r4-fast:.15s;
  --r4-slow:.3s;
  --r4-gap:14px;
}

/* ---- the type buttons -------------------------------------------------
   The one control every solution shares, because it is the one thing the
   visitor has to understand: these are the kinds of proof, pick one. */
.r4-types{display:flex;align-items:center;gap:7px;overflow-x:auto;
  overscroll-behavior-x:contain;scrollbar-width:none}
.r4-types::-webkit-scrollbar{width:0;height:0;display:none}
.r4-types button{flex:none;display:inline-flex;align-items:center;gap:8px;
  min-height:40px;padding:0 15px;border:1px solid var(--pf9-line2);
  background:var(--pf9-card);font-size:13.5px;color:var(--pf9-ink2);
  white-space:nowrap;transition:all var(--r4-fast)}
.r4-types button i{font-style:normal;font-family:var(--pf9-mono);font-size:10.5px;
  color:var(--pf9-ink3)}
.r4-types button[aria-pressed="true"],.r4-types button[aria-selected="true"]{
  background:var(--pf9-accent);border-color:var(--pf9-accent);color:#fff;
  font-weight:600}
.r4-types button[aria-pressed="true"] i,.r4-types button[aria-selected="true"] i{
  color:#B7D3CA}
@media (hover:hover) and (pointer:fine){
  .r4-types button:hover{border-color:var(--pf9-ink);color:var(--pf9-ink)}
  .r4-types button[aria-pressed="true"]:hover,
  .r4-types button[aria-selected="true"]:hover{color:#fff;
    background:var(--pf9-accent2);border-color:var(--pf9-accent2)}
}

/* ---- the band ---------------------------------------------------------
   Fixed height, decided by the layout. Nothing inside it may change it. */
.r4-band{position:relative;min-height:0;overflow:hidden;background:var(--pf9-mat)}

/* ---- a justified line of artefacts -------------------------------------
   flex-grow proportional to the artefact's ratio + aspect-ratio on the
   cell IS the justified-gallery algorithm, in two declarations: widths
   come out proportional to the shapes and every height resolves equal.
   JS only has to decide how many cells to put on the line. */
.r4-line{display:flex;align-items:center;justify-content:center;
  gap:var(--r4-gap);width:100%;height:100%;padding:var(--r4-pad,16px)}
.r4-line>.r4-cell{flex:var(--r) 1 0;aspect-ratio:var(--r);min-width:0;
  max-height:100%}
/* Down the screen instead of across, on a phone — but NOT justified.
   A tall band justified vertically squeezes two phone screenshots into
   215px each; one at the full width of the screen is the whole point of
   a phone. So: take the width, stack however many of them fit. */
.r4-line[data-axis="col"]{flex-direction:column}
.r4-line[data-axis="col"]>.r4-cell{flex:none;width:var(--colw,100%);height:auto;
  max-width:100%;max-height:none}

/* margin:0 is not decoration — .r4-cell is a <figure>, which every UA gives
   a 1em block margin. The lab's pages reset it in _pf9-core.css; a page that
   ports this file has no reason to, and 32px of phantom height per cell is
   exactly the kind of bug that only shows up somewhere else. */
.r4-cell{position:relative;display:block;margin:0;background:var(--pf9-card);
  border:1px solid var(--pf9-line2);overflow:hidden;
  box-shadow:0 2px 8px rgba(21,20,15,.07),0 12px 30px rgba(21,20,15,.08)}
/* the frame carries the artefact's own ratio, so the artefact fills it */
.r4-cell img{display:block;width:100%;height:100%;object-fit:cover;
  object-position:center top;-webkit-user-drag:none;
  opacity:0;transition:opacity var(--r4-fast) linear}
.r4-cell img.on{opacity:1}

/* ---- reading one of them ----------------------------------------------
   Same box, artefact at reading scale, panned inside. Never a modal. */
.r4-read{position:absolute;inset:0;z-index:6;display:flex;
  background:var(--pf9-mat)}
.r4-read[hidden]{display:none}
.r4-scroll{flex:1;min-width:0;min-height:0;overflow:auto;
  overscroll-behavior:contain;scrollbar-width:thin;
  scrollbar-color:#858C98 transparent}
.r4-scroll::-webkit-scrollbar{width:12px;height:12px}
.r4-scroll::-webkit-scrollbar-thumb{background:#858C98;
  border:3px solid transparent;background-clip:content-box;border-radius:999px}
.r4-scroll::-webkit-scrollbar-thumb:hover{background:#767E8B}
.r4-hold{min-width:100%;min-height:100%;width:max-content;
  display:flex;align-items:center;justify-content:center;padding:var(--r4-pad,16px)}
.r4-hold img{display:block;width:var(--r4-w,100%);height:auto;max-width:none;
  background:#fff;box-shadow:0 2px 6px rgba(21,20,15,.12),0 16px 40px rgba(21,20,15,.16)}

/* ---- small shared parts ------------------------------------------------ */
/* both of these chips sit ON an image. Opaque and unblurred as of 2026-09-09:
   a translucent chip over a blurred patch of the picture is exactly the hazy
   treatment being taken off the site, and a solid chip reads faster anyway. */
.r4-x{position:absolute;z-index:7;right:10px;top:10px;display:inline-flex;
  align-items:center;gap:7px;min-height:36px;padding:0 13px;
  background:#fff;border:1px solid var(--pf9-line2);
  font-size:12.5px;color:var(--pf9-ink2);
  box-shadow:0 2px 10px rgba(21,20,15,.12);transition:all var(--r4-fast)}
.r4-zoom{position:absolute;z-index:5;right:9px;bottom:9px;width:34px;height:34px;
  display:grid;place-items:center;background:#fff;
  border:1px solid var(--pf9-line2);color:var(--pf9-ink2);opacity:0;
  transition:opacity var(--r4-fast)}
.r4-cell:hover .r4-zoom,.r4-cell:focus-within .r4-zoom{opacity:1}
@media (hover:none){.r4-zoom{opacity:1}}
@media (hover:hover) and (pointer:fine){
  .r4-x:hover{border-color:var(--pf9-ink);color:var(--pf9-ink)}
  .r4-zoom:hover{border-color:var(--pf9-ink);color:var(--pf9-ink)}
  .r4-cell:hover{border-color:var(--pf9-ink)}
}

.r4-nobar{scrollbar-width:none;-ms-overflow-style:none}
.r4-nobar::-webkit-scrollbar{width:0;height:0;display:none}
.r4-sr{display:inline-block;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;padding:0;margin:0}

/* ---- the pager --------------------------------------------------------- */
.r4-pg{display:flex;align-items:center;gap:6px}
.r4-pg button{width:38px;height:38px;display:grid;place-items:center;
  border:1px solid var(--pf9-line2);background:var(--pf9-card);
  color:var(--pf9-ink2);transition:all var(--r4-fast)}
.r4-pg button[disabled]{opacity:.3;cursor:default}
.r4-pg .n{font-family:var(--pf9-mono);font-size:12px;color:var(--pf9-ink2);
  min-width:6.5ch;text-align:center}
@media (hover:hover) and (pointer:fine){
  .r4-pg button:hover:not([disabled]){border-color:var(--pf9-ink);color:var(--pf9-ink)}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
}

/* a last row that could not be filled keeps its natural height instead of
   stretching two artefacts across the whole width */
.r4-line[data-full="0"]{justify-content:flex-start}
.r4-line[data-full="0"]>.r4-cell{flex:none;height:var(--rowh);width:auto;max-width:100%}
