/* ============================================================================
   Pingo — the screen gallery. Owns .gal-* and nothing else.

   Eight Steel screens, one visible at a time. Six of them come from the LOCKED
   canvas design/Pingo Screens.dc.html and keep its artboard ids (1a Devices ·
   1b Speed test · 1c Wi-Fi check · 1d Tools · 1e Device detail · 1f Diagnose,
   which draws the symptom picker). Two were reconstructed from the app itself
   because the canvas never drew them: 1g the Diagnose RESULT, and 1h the Wi-Fi
   hardening check. The ids stay attached to the screens they name, so they do
   not read in sequence along the strip.

   The tab order is declared once, in inject-gallery.mjs, which generates the
   whole block in index.html. Do not hand-edit that block.

   WHY TABS RATHER THAN A SCROLL-THROUGH, and why only one animates:
     * In Pingo the motion IS the meaning. Each screen is captured at a named
       moment: mid-scan, mid-run, mid-diagnosis. Tools has nothing live on it and
       is almost perfectly still, and that contrast is what makes the other five
       read as genuinely alive, and 1g and 1h are still as well, because a
       finished verdict and a beacon already read are not live either. Eight
       screens animating at once would turn motion back into decoration.
     * Every screen carries backdrop-filter: blur(20px) on its cards. Eight of
       them compositing at once drops frames on a mid-range phone.
     * gallery.js adds .is-offstage to every inactive screen, which each screen's
       own CSS answers by stopping its animations on their HONEST FINAL FRAMES.
       That is the web's equivalent of the app's TickerMode + IndexedStack, where
       an offstage tab genuinely stops ticking (lib/app.dart:103-110).

   Reduced motion is NOT handled here: each screen's own stylesheet carries its
   final-frame block, gated on html:not(.motion-opt-in) so the site's existing
   "Play the motion" opt-in keeps working across the gallery too.
   ============================================================================ */

.gal {
  /* The canvas screens were authored by separate agents and settled on three
     names for the same knob. All three are set so every screen scales together;
     1g and 1h reuse --pgs-s rather than adding a fourth name.
     0.88 is the FLOOR: the screens are authored at 375x812 with 8-9px mono
     labels, and the handover's rule is "minimum size 9px for any mono unit or
     caption". Going smaller breaks legibility, so narrow viewports scroll the
     rail instead. */
  --gal-scale: 0.88;
  --pgst-scale: 0.88;
  --pgs-s: 0.88;
}

.gal-head { max-width: 62ch; margin-bottom: clamp(24px, 3.5vw, 36px); }
.gal-head .lbl { display: block; margin-bottom: 14px; }
.gal-head h2 + p { margin-top: 14px; }

/* ---- the tab strip ---- */
.gal-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}
.gal-tab {
  appearance: none;
  font-family: var(--font);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--mut2);
  background: var(--sur-cell);
  border: 1px solid var(--line);
  border-radius: var(--r-chip);
  padding: 9px 15px;
  cursor: pointer;
  transition: color 0.16s ease, background 0.16s ease, border-color 0.16s ease;
}
.gal-tab:hover { color: var(--ink); border-color: var(--line-strong); }
/* Selected state uses LIGHT, not a hue — there is no brand accent in Steel. */
.gal-tab[aria-selected='true'] {
  background: linear-gradient(150deg, #FFFFFF, #CFDBE9);
  border-color: transparent;
  color: var(--on-light);
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.45);
}
.gal-tab .gal-tab-id {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  opacity: 0.55;
  margin-right: 7px;
}

/* ---- panel + caption ---- */
.gal-body {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(24px, 4vw, 48px);
  align-items: start;
}
@media (max-width: 860px) { .gal-body { grid-template-columns: minmax(0, 1fr); } }

.gal-stage {
  /* The screens are fixed-size and cannot shrink, so below the breakpoint the
     rail scrolls rather than the type going under the 9px floor. */
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.gal-panel[hidden] { display: none; }

.gal-side { display: grid; gap: 14px; align-content: start; }
/* AND THE [hidden] RULE THAT GOES WITH IT. An author "display: grid" beats the
   user-agent sheet's [hidden] { display: none }, so without this line every side
   caption renders at once, under every other one, however carefully gallery.js
   sets the attribute. Same reason .gal-panel needs its own rule above. */
.gal-side[hidden] { display: none; }
.gal-moment {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: start;
  padding: 7px 13px;
  border-radius: var(--r-chip);
  border: 1px solid var(--line);
  background: var(--sur-cell);
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mut2);
}
.gal-side h3 { font-size: 1.125rem; }
.gal-side p { font-size: 0.9375rem; color: var(--mut); }
.gal-side .gal-still {
  font-size: 0.875rem;
  color: var(--faint2);
  border-left: 1px solid var(--line-strong);
  padding-left: 14px;
}
.gal-note {
  font-size: 0.8125rem;
  color: var(--faint2);
  margin-top: 22px;
  max-width: 70ch;
}
