/* ==========================================================================
   Full-screen project viewer
   The device box is animated from the thumbnail's rectangle on the wall to its
   place in the viewer with transforms only (see js/viewer.js).
   A website fills the stage. An app, at 900px and wider, keeps its phone or
   tablet frame in the middle of the stage (.viewer.is-device).
   ========================================================================== */

.viewer {
  --bar-h: 48px;
  position: fixed; inset: 0; z-index: 60;
  pointer-events: none;
}
.viewer.is-open { pointer-events: auto; }
html.viewer-open { overflow: hidden; }

.viewer__bar {
  position: absolute; inset: 0 0 auto 0; z-index: 2;
  height: calc(var(--bar-h) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) 6px 0;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px;
  background: var(--bg); color: var(--fg);
  border-bottom: 1px solid var(--line-c);
  font-size: .8125rem; font-weight: 500;
  transform: translateY(-101%);
  transition: transform .5s var(--ease-out);
}
.viewer.is-open .viewer__bar { transform: none; }

.viewer__back, .viewer__new {
  display: inline-flex; align-items: center; gap: .5em;
  min-height: 40px; padding: 0 10px;
  background: none; border: 0; border-radius: 8px;
  color: inherit; font: inherit; text-decoration: none; white-space: nowrap;
}
.viewer__back { justify-self: start; }
.viewer__new { justify-self: end; }
.viewer__new-text { display: none; }
@media (hover: hover) {
  .viewer__back:hover, .viewer__new:hover { background: var(--line-c); }
}

.viewer__title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.viewer__name {
  font-family: var(--display); font-weight: var(--display-weight); font-stretch: var(--display-stretch);
  font-size: 1rem; line-height: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.viewer__title .tag { font-size: .5625rem; padding: .4em .65em; }
.tag__long { display: none; }

@media (min-width: 620px) {
  .viewer { --bar-h: 52px; }
  .viewer__bar { padding-inline: 12px; font-size: .875rem; }
  .viewer__new-text, .tag__long { display: inline; }
  .viewer__title { gap: 12px; }
  .viewer__name { font-size: 1.125rem; }
}

.viewer__stage { position: absolute; inset: calc(var(--bar-h) + env(safe-area-inset-top)) 0 0 0; }
.viewer__slot, .viewer__device, .viewer__frame { position: absolute; inset: 0; }
/* The box that travels. For a website it is the frame itself; for an app it also carries the bezel. */
.viewer__device {
  transform-origin: 0 0;
  will-change: transform;
  visibility: hidden;
}
.viewer.is-shown .viewer__device { visibility: visible; }
.viewer__frame { overflow: hidden; background: var(--p-bg, var(--bg)); }
.viewer__about, .viewer__try { display: none; }

.viewer__inner { position: absolute; inset: 0; transform-origin: 0 0; will-change: transform; }
.viewer__poster { width: 100%; height: auto; }

.viewer__site {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
  background: transparent;
  opacity: 0; transition: opacity .35s linear;
}
.viewer__site.is-ready { opacity: 1; }

.viewer__loading {
  position: absolute; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom));
  padding: 9px 16px; border-radius: 999px;
  background: var(--fg); color: var(--bg);
  font-size: .8125rem; font-weight: 600; white-space: nowrap;
  transform: translate(-50%, 16px); opacity: 0;
  transition: opacity .25s linear, transform .35s var(--ease-out);
  pointer-events: none;
}
.viewer.is-loading .viewer__loading { opacity: 1; transform: translate(-50%, 0); transition-delay: .25s; }
.viewer.is-loading .viewer__loading::after {
  content: ''; display: inline-block; width: 1.2em; text-align: left;
  animation: dots 1.2s steps(4, end) infinite;
}
@keyframes dots {
  0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75% { content: '...'; }
}

/* ---------- an app in its frame (900px and wider, set by js/viewer.js) ---------- */
/* The page behind is covered by the project's own background colour, which fades in. */
.viewer.is-device .viewer__stage::before, .viewer.is-column .viewer__stage::before {
  content: ''; position: absolute; inset: 0;
  background: var(--bg);
  opacity: 0; transition: opacity .45s linear;
}
.viewer.is-device.is-open .viewer__stage::before, .viewer.is-column.is-open .viewer__stage::before { opacity: 1; }

.viewer.is-device .viewer__stage {
  --col: clamp(220px, 22vw, 300px);
  --gap: clamp(28px, 4vw, 64px);
  display: grid; align-items: center; justify-content: center;
  grid-template-columns: var(--col) auto;
  /* The two text blocks sit together, level with the middle of the device. */
  grid-template-rows: minmax(0, 1fr) auto auto minmax(0, 1fr);
  grid-template-areas: '. device' 'about device' 'try device' '. device';
  column-gap: var(--gap);
  padding: clamp(14px, 3.4vh, 40px) clamp(24px, 3vw, 48px);
  container-type: size; /* lets the frame below size itself from the room the stage really has */
}
.viewer.is-device .viewer__slot { position: relative; inset: auto; grid-area: device; }
/* Sizes include the bezel (see "device frames" in sections.css): 414 x 868 and 1212 x 852. */
.viewer.is-device[data-device='phone'] .viewer__slot {
  --h: min(100cqh, 868px);
  height: var(--h); width: calc(var(--h) * 414 / 868);
}
.viewer.is-device[data-device='tablet'] .viewer__slot {
  --w: min(100cqw - var(--col) - var(--gap), 100cqh * 1212 / 852, 1212px);
  width: var(--w); height: calc(var(--w) * 852 / 1212);
}
.viewer.is-device .viewer__frame { position: relative; inset: auto; width: 100%; height: 100%; }
/* The app keeps the size it was built for and is scaled as a whole to fit the frame. */
.viewer.is-device .viewer__site {
  inset: 0 auto auto 0; max-width: none;
  width: var(--app-w); height: var(--app-h);
  transform: scale(var(--app-scale, 1)); transform-origin: 0 0;
}

.viewer.is-device .viewer__about, .viewer.is-device .viewer__try {
  display: block; position: relative; min-width: 0;
  opacity: 0; transform: translateY(14px);
  transition: opacity .3s linear, transform .3s var(--ease);
}
.viewer.is-device.is-open .viewer__about, .viewer.is-device.is-open .viewer__try {
  opacity: 1; transform: none;
  transition: opacity .45s linear .4s, transform .7s var(--ease-out) .4s;
}
.viewer.is-device.is-open .viewer__try { transition-delay: .5s; }
.viewer__about { grid-area: about; }
.viewer__try { grid-area: try; margin-top: 28px; }

.viewer__app-name {
  font-family: var(--display); font-weight: var(--display-weight); font-stretch: var(--display-stretch);
  font-size: clamp(2.25rem, 3.6vw, 3.5rem); line-height: 1.05; overflow-wrap: anywhere;
}
.viewer__app-text { margin-top: 14px; font-size: 1.0625rem; line-height: 1.45; text-wrap: pretty; }
/* Some actions quote an Arabic label from the app. Hanken Grotesk has no Arabic, so those words
   fall through to the app's own display font instead of a small system face. */
.viewer__try-list { font-family: 'Hanken Grotesk', var(--display); }
.viewer__try-title { font-size: .75rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.viewer__try-list { display: grid; gap: 12px; margin-top: 14px; counter-reset: step; }
.viewer__try-list li {
  display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 12px; align-items: start;
  font-size: 1rem; line-height: 1.4; text-wrap: pretty;
  counter-increment: step;
}
.viewer__try-list li::before {
  content: counter(step);
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: var(--on-accent);
  font-size: .8125rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
}
.viewer__try-note { margin-top: 18px; font-size: .875rem; color: var(--muted); }

/* A phone with room on both sides: the name on one, the list on the other, the phone in the middle. */
@media (min-width: 1100px) {
  .viewer.is-device[data-device='phone'] .viewer__stage {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: 'about device try';
  }
  .viewer.is-device[data-device='phone'] .viewer__about { justify-self: end; align-self: center; width: min(100%, 340px); }
  .viewer.is-device[data-device='phone'] .viewer__try { justify-self: start; align-self: center; width: min(100%, 340px); margin-top: 0; }
}
/* On a short window the closing note goes first, so the list itself always fits. */
@media (max-height: 720px) {
  .viewer__try-note { display: none; }
}

/* A phone app on a window that is wide but too short for the frame: a phone-wide column, edge to edge. */
.viewer.is-column .viewer__slot { inset: 0 auto 0 50%; width: 430px; margin-left: -215px; }

@media (prefers-reduced-motion: reduce) {
  .viewer.is-loading .viewer__loading::after { animation: none; content: '...'; }
  .viewer__site, .viewer__loading, .viewer__bar, .viewer__stage::before { transition: none !important; }
  .viewer.is-device .viewer__about, .viewer.is-device .viewer__try { transition: none !important; transform: none; }
}
