/* ============================================================
   STANDING WATCH — the viewport, and every way it can fail
   ------------------------------------------------------------
   STEP 2 OF 4. The dead states are built FIRST, before anything plays,
   because they are the states this feature will spend most of its life
   in. Channels end, parks swap cameras, streams go private. A watch
   wired today has a half-life, and on most sites that slowly makes a
   page look abandoned. Here it should look intended.

   Namespace is sw- throughout. It deliberately does not reuse cv- or
   wr- class names: the Chronovisor's decay is tuned for VIDEO it owns,
   this is tuned for a borrowed camera and a held still, and the two
   drifting into each other would be a bad afternoon later. The visual
   language is shared on purpose; the selectors are not.

   ------------------------------------------------------------
   THE STATES, AND WHY THEY ARE NOT ONE STATE

     is-idle      poster up, nothing loaded, nothing third-party running
     is-reaching  the viewer asked; we are finding the angle
     is-live      playing
     is-night     playing, and BLACK ON PURPOSE (see below)
     is-lost      we had this camera and no longer do
     is-hollow    we never had it — with two different reasons

   LOST AND HOLLOW MUST NOT LOOK ALIKE. Lost is something taken away:
   the last frame we held, coming apart. Hollow is something that was
   never there: no corruption, because there is nothing to corrupt —
   just a cold empty frame with registration marks and a coordinate.
   Collapsing them into one "unavailable" card would throw away the only
   interesting thing this feature has to say.

   ORBITAL NIGHT IS NOT A FAILURE. The ISS downlink (W-08) goes black
   for roughly half of every 90-minute orbit. We cannot read pixels out
   of a cross-origin iframe, so nothing here tries to DETECT night — the
   watch declares darkCycle in watch-data.js and the page says so in
   words. A decay treatment firing on that black frame would kill the
   best feed on the list twice an hour.

   WHY THE DEAD STATES ARE DECLARATIVE. You cannot reliably detect a
   dead cross-origin stream from the page. So is-lost and is-hollow are
   driven by `status` in watch-data.js, set by hand — which means none of
   this needs a network to be seen, tested or trusted.
   ============================================================ */

.sw {
  --sw-ground: #0a0610;
  --sw-panel:  #150b1f;
  --sw-ink:    #f1e8fb;
  --sw-muted:  #a08cba;
  --sw-dim:    #6f5e86;
  --sw-rule:   #2e1d42;
  --sw-violet: #c084fc;
  --sw-soft:   #e9d5ff;
  --sw-amber:  #fbbf24;
  --sw-cyan:   #67e8f9;

  --sw-disp: "Barlow Condensed", "Arial Narrow", system-ui, sans-serif;
  --sw-mono: "Share Tech Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* 0..1, the single number every corruption effect reads. One property
     means the picture comes apart as one event instead of four effects
     crossing their own thresholds — the lesson from the Chronovisor. */
  --sw-decay: 0;
}

/* ─── the frame ───────────────────────────────────────────────────── */
.sw-view {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #05030a;
  border: 1px solid var(--sw-rule);
  overflow: hidden;
  isolation: isolate;
}
.sw-view > img,
.sw-view > iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
.sw-view > img { object-fit: cover; }

/* Corner registration marks. Present in every state — they are the
   instrument, not the picture, so they stay when the picture does not. */
.sw-view::before {
  content: "";
  position: absolute;
  inset: 7px;
  z-index: 4;
  pointer-events: none;
  background:
    linear-gradient(var(--sw-violet), var(--sw-violet)) 0 0 / 11px 1px no-repeat,
    linear-gradient(var(--sw-violet), var(--sw-violet)) 0 0 / 1px 11px no-repeat,
    linear-gradient(var(--sw-violet), var(--sw-violet)) 100% 0 / 11px 1px no-repeat,
    linear-gradient(var(--sw-violet), var(--sw-violet)) 100% 0 / 1px 11px no-repeat,
    linear-gradient(var(--sw-violet), var(--sw-violet)) 0 100% / 11px 1px no-repeat,
    linear-gradient(var(--sw-violet), var(--sw-violet)) 0 100% / 1px 11px no-repeat,
    linear-gradient(var(--sw-violet), var(--sw-violet)) 100% 100% / 11px 1px no-repeat,
    linear-gradient(var(--sw-violet), var(--sw-violet)) 100% 100% / 1px 11px no-repeat;
  opacity: .34;
}

/* ─── shared overlay plate ────────────────────────────────────────── */
.sw-plate {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  text-align: center;
  padding: 1.1rem;
  pointer-events: none;
}
.sw-plate b {
  font-family: var(--sw-mono);
  font-size: .74rem;
  letter-spacing: .3em;
  text-transform: uppercase;
  font-weight: 400;
  line-height: 1.4;
}
.sw-plate span {
  font-family: var(--sw-disp);
  font-size: 1.02rem;
  letter-spacing: .01em;
  color: var(--sw-muted);
  max-width: 30ch;
  line-height: 1.35;
}
.sw-plate em {
  font-style: normal;
  font-family: var(--sw-mono);
  font-size: .6rem;
  letter-spacing: .16em;
  color: var(--sw-dim);
  font-variant-numeric: tabular-nums;
}

/* ══════════════════════════════════════════════════════════════════
   IS-LOST — we had this camera and no longer do
   ------------------------------------------------------------------
   The last frame we held, coming apart. NOT a black card with an error
   on it: the Chronovisor taught that an opaque panel over a stopped
   picture reads as a dialog box, and the fork whose whole character was
   instability ended up feeling merely broken. The picture stays, ruined.
   ══════════════════════════════════════════════════════════════════ */
.sw-view.is-lost { --sw-decay: 1; }

.sw-view.is-lost > img {
  filter:
    grayscale(calc(var(--sw-decay) * .55))
    contrast(calc(1 + var(--sw-decay) * .4))
    brightness(calc(1 - var(--sw-decay) * .25));
  transform: translateX(calc(var(--sw-decay) * var(--sw-judder, 0px)));
}

/* Chromatic split as inset shadows on a sibling layer rather than a
   drop-shadow on the image: a drop-shadow lands on the letterbox bars
   when object-fit leaves any, which looked wrong on portrait captures. */
.sw-fx {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
}
.sw-view.is-lost .sw-fx {
  opacity: 1;
  box-shadow:
    inset calc(var(--sw-decay) * 8px) 0 calc(var(--sw-decay) * 24px) rgba(255, 60, 90, calc(var(--sw-decay) * .42)),
    inset calc(var(--sw-decay) * -8px) 0 calc(var(--sw-decay) * 24px) rgba(60, 200, 255, calc(var(--sw-decay) * .38));
}

/* Tear bands — slices that slide out of register. This is the effect
   that reads as "coming apart" rather than "noisy": the frame stays
   legible but stops agreeing with itself. */
.sw-tear {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: screen;
  background: repeating-linear-gradient(
    180deg,
    transparent 0 7%,
    rgba(186, 230, 253, .10) 7% 8%,
    transparent 8% 19%,
    rgba(255, 120, 150, .09) 19% 20%,
    transparent 20% 37%,
    rgba(160, 255, 220, .08) 37% 38%,
    transparent 38% 100%);
}
.sw-view.is-lost .sw-tear {
  opacity: var(--sw-decay);
  animation: sw-tear 1.7s steps(6, end) infinite;
}
@keyframes sw-tear {
  0%   { background-position-y: 0;     transform: scaleY(1); }
  33%  { background-position-y: -22px; transform: scaleY(1.02); }
  66%  { background-position-y: 15px;  transform: scaleY(.99); }
  100% { background-position-y: 0;     transform: scaleY(1); }
}

.sw-view.is-lost > img { animation: sw-judder .24s steps(2, end) infinite; }
@keyframes sw-judder {
  0%   { --sw-judder: -3px; }
  50%  { --sw-judder: 4px; }
  100% { --sw-judder: -2px; }
}

/* A slow breath in the vignette so the held frame does not read as a
   freeze. The moment is still on screen; it is just no longer arriving. */
.sw-view.is-lost::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 26%, rgba(3, 6, 14, .72) 100%);
  animation: sw-breathe 3.4s ease-in-out infinite;
}
@keyframes sw-breathe {
  0%, 100% { opacity: .78; }
  50%      { opacity: 1; }
}

/* Rose, not alarm red. A camera going away is a loss, not a fault light —
   the Chronovisor's CARRIER LOST in #ef4444 was the single most
   equipment-like thing on that page and it was worth changing. */
.sw-view.is-lost .sw-plate {
  justify-content: flex-end;
  padding-bottom: 1.2rem;
}
.sw-view.is-lost .sw-plate b {
  color: #f5d0fe;
  text-shadow: 0 0 18px rgba(232, 121, 249, .7);
}
.sw-view.is-lost .sw-plate b,
.sw-view.is-lost .sw-plate span,
.sw-view.is-lost .sw-plate em {
  background: rgba(3, 6, 14, .62);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  padding: .14rem .7rem;
  border-radius: 4px;
}

/* ══════════════════════════════════════════════════════════════════
   IS-HOLLOW — we never had this one
   ------------------------------------------------------------------
   No decay, because there is nothing to decay. An empty frame, a faint
   survey grid and a coordinate: the instrument pointed at ground and
   finding nothing to look through. Cold, quiet, and deliberately more
   comfortable to look at than is-lost — absence is not damage.
   ══════════════════════════════════════════════════════════════════ */
.sw-view.is-hollow {
  background:
    radial-gradient(ellipse 80% 60% at 50% 45%, rgba(46, 29, 66, .55), transparent 70%),
    #05030a;
}
.sw-view.is-hollow .sw-grid {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(192, 132, 252, .07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(192, 132, 252, .07) 1px, transparent 1px);
  background-size: 38px 38px;
  mask-image: radial-gradient(ellipse at center, #000 18%, transparent 76%);
  -webkit-mask-image: radial-gradient(ellipse at center, #000 18%, transparent 76%);
}
.sw-view.is-hollow .sw-plate b { color: var(--sw-dim); }
.sw-view.is-hollow .sw-plate span { color: #7d6b96; }

/* CLOSED GROUND — cameras exist here and belong to someone who says no.
   Redaction bars, the same gesture as the Lee Lou eyes-only documents:
   the ground is not empty, it is blacked out. A different unhappiness
   from NO ANGLE and it should look like one. */
.sw-view.is-hollow[data-reason="closed-ground"] .sw-grid {
  background-image:
    repeating-linear-gradient(
      180deg,
      transparent 0 14%,
      rgba(0, 0, 0, .92) 14% 22%,
      transparent 22% 40%,
      rgba(0, 0, 0, .92) 40% 46%,
      transparent 46% 68%,
      rgba(0, 0, 0, .92) 68% 78%,
      transparent 78% 100%);
  background-size: auto;
  mask-image: none;
  -webkit-mask-image: none;
  opacity: .85;
}
.sw-view.is-hollow[data-reason="closed-ground"] .sw-plate b { color: #b98ad4; }

/* ══════════════════════════════════════════════════════════════════
   IS-NIGHT — black on purpose. NEVER decay this.
   ══════════════════════════════════════════════════════════════════ */
.sw-view.is-night { --sw-decay: 0; background: #02030a; }
.sw-view.is-night > img,
.sw-view.is-night .sw-tear,
.sw-view.is-night .sw-fx { animation: none !important; opacity: 0; }
.sw-view.is-night .sw-plate b { color: var(--sw-cyan); opacity: .8; }
.sw-view.is-night .sw-plate span { color: #6f8ba6; }
/* The one moving thing: a slow breath, so it reads as waiting rather
   than stopped. Nothing corrupts. */
.sw-view.is-night::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 50% at 50% 60%, rgba(34, 211, 238, .07), transparent 72%);
  animation: sw-breathe 6.5s ease-in-out infinite;
}

/* ══════════════════════════════════════════════════════════════════
   IS-REACHING — the viewer asked; we are finding the angle
   ══════════════════════════════════════════════════════════════════ */
.sw-view.is-reaching .sw-plate b { color: var(--sw-soft); }
.sw-view.is-reaching .sw-scan {
  position: absolute;
  left: 0; right: 0;
  top: 0;
  height: 34%;
  z-index: 3;
  pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(192, 132, 252, .16) 60%, transparent);
  animation: sw-sweep 1.5s ease-in-out infinite;
}
@keyframes sw-sweep {
  0%   { transform: translateY(-110%); }
  100% { transform: translateY(330%); }
}

/* ─── states that show no plate ───────────────────────────────────── */
.sw-view.is-idle .sw-plate,
.sw-view.is-live .sw-plate { display: none; }
.sw-view.is-idle .sw-grid,
.sw-view.is-live .sw-grid,
.sw-view.is-reaching .sw-grid { display: none; }
.sw-view:not(.is-reaching) .sw-scan { display: none; }
.sw-view:not(.is-hollow) .sw-grid { display: none; }

/* ─── the status line under a viewport ────────────────────────────── */
.sw-status {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  padding: .5rem .1rem 0;
  font-family: var(--sw-mono);
  font-size: .63rem;
  letter-spacing: .16em;
  color: var(--sw-dim);
}
.sw-dot {
  width: 7px; height: 7px; flex: 0 0 auto;
  border: 1px solid currentColor; border-radius: 50%;
}
.sw-status.is-live  { color: var(--sw-amber); }
.sw-status.is-live .sw-dot { background: currentColor; }
.sw-status.is-lost  { color: var(--sw-dim); }
.sw-status.is-lost .sw-dot { background: currentColor; opacity: .45; }
.sw-status.is-hollow { color: var(--sw-dim); }
.sw-status.is-night { color: var(--sw-cyan); }
.sw-status.is-night .sw-dot { background: currentColor; }
.sw-status .sw-src { margin-left: auto; opacity: .7; }

/* ─── reduced motion ──────────────────────────────────────────────
   Degradation stays as a STATE, because it carries meaning. It just
   stops moving. Same call as the Chronovisor. */
@media (prefers-reduced-motion: reduce) {
  .sw-view.is-lost > img,
  .sw-view.is-lost .sw-tear,
  .sw-view.is-lost::after,
  .sw-view.is-night::after,
  .sw-view.is-reaching .sw-scan {
    animation: none !important;
  }
  .sw-view.is-lost > img { transform: none; }
  .sw-view.is-reaching .sw-scan { opacity: .5; }
}

/* ============================================================
   STEP 3 — THE PAGE
   ------------------------------------------------------------
   Self-contained skin, like chronovisor.html: this page does not load
   styles.css, which means it does NOT inherit the global
   `* { box-sizing: border-box }` and must bring its own. Skipping that
   is how bunker-access and friends picked up a horizontal scroll on
   phones — width:100% plus padding silently overflows without it.

   It also means the page never inherits styles.css's near-white
   .site-header, so the trap fixed on 18 Sep cannot reach this page at
   all. Its chrome is its own.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
  /* CLIP, NOT HIDDEN, and on BOTH elements.
     agency-nav.js parks its closed drawer just off the right edge. Pages
     that load styles.css get its `overflow-x: hidden` (line 110) and never
     see it; a self-contained skin does not, so without this the page
     carries a 24px horizontal scroll at every width.
     `hidden` on body alone does not fix it — html stays `visible` and the
     viewport still scrolls — and putting `hidden` on html WOULD fix it at
     the cost of the sticky header, because an ancestor scroll container
     is what `position: sticky` sticks to. `clip` clips without creating
     that scroll container, so the bar keeps working. */
  overflow-x: hidden;
  overflow-x: clip;
}

.sw-body {
  background:
    radial-gradient(ellipse 70% 45% at 12% -4%, rgba(168, 85, 247, .16), transparent 58%),
    radial-gradient(ellipse 50% 32% at 92% 3%, rgba(34, 211, 238, .07), transparent 55%),
    var(--sw-ground, #0a0610);
  color: var(--sw-ink, #f1e8fb);
  font-family: Inter, system-ui, -apple-system, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

.sw-skip { position: absolute; left: -999px; }
.sw-skip:focus {
  left: .5rem; top: .5rem; z-index: 99;
  background: #000; color: #fff; padding: .55rem .8rem; min-height: 44px;
  display: inline-flex; align-items: center;
}

/* ─── chrome ──────────────────────────────────────────────────────── */
.sw-top {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  padding: .7rem 1rem;
  padding-top: calc(.7rem + env(safe-area-inset-top, 0px));
  background: rgba(14, 8, 22, .93);
  border-bottom: 1px solid rgba(192, 132, 252, .3);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.sw-brand {
  display: flex; align-items: center; gap: .6rem;
  text-decoration: none; color: inherit;
}
.sw-brand strong {
  display: block; font-family: var(--sw-mono); font-size: .8rem;
  letter-spacing: .18em; color: var(--sw-soft); font-weight: 400;
}
.sw-brand em {
  display: block; font-style: normal; font-family: var(--sw-mono);
  font-size: .56rem; letter-spacing: .14em; color: var(--sw-dim);
}
.sw-top-right { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; }
.sw-count {
  font-family: var(--sw-mono); font-size: .58rem; letter-spacing: .16em;
  color: var(--sw-dim); border: 1px solid var(--sw-rule);
  padding: .3rem .5rem; white-space: nowrap;
}

/* ─── page body ───────────────────────────────────────────────────── */
.sw-wrap { max-width: 78rem; margin: 0 auto; padding: 1.4rem 1rem 4rem; }

.sw-kicker {
  font-family: var(--sw-mono); font-size: .6rem; letter-spacing: .18em;
  color: var(--sw-violet); margin: 0 0 .3rem;
}
.sw-wrap h1 {
  font-family: var(--sw-disp); font-weight: 600;
  font-size: clamp(1.9rem, 6vw, 2.9rem); line-height: 1;
  letter-spacing: .01em; margin: 0 0 .5rem; color: #fff; text-wrap: balance;
}
.sw-lede { max-width: 56ch; color: var(--sw-muted); margin: 0 0 1.6rem; }
.sw-lede b { color: var(--sw-soft); font-weight: 500; }

/* ─── the stage ───────────────────────────────────────────────────── */
.sw-stage { margin-bottom: 2.2rem; }
.sw-stage-wrap { position: relative; }
/* light from behind the aperture rather than a backlight in front of it */
.sw-stage-wrap::before {
  content: "";
  position: absolute; inset: -9% -4%; z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(ellipse 55% 45% at 50% 45%, rgba(168, 85, 247, .26), transparent 66%),
    radial-gradient(ellipse 40% 30% at 50% 82%, rgba(34, 211, 238, .14), transparent 70%);
  filter: blur(26px);
}
.sw-stage .sw-view { border-radius: 14px; }
.sw-stage .sw-view::before { inset: 11px; }

.sw-stage-head {
  display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
  margin: 0 0 .5rem;
}
.sw-stage-head h2 {
  font-family: var(--sw-disp); font-weight: 600; font-size: 1.5rem;
  letter-spacing: .01em; margin: 0; color: #fff;
}
.sw-stage-head .sw-where {
  font-family: var(--sw-mono); font-size: .6rem; letter-spacing: .14em;
  color: var(--sw-dim); font-variant-numeric: tabular-nums;
}
.sw-stage-blurb { max-width: 62ch; color: var(--sw-muted); margin: .55rem 0 0; }

/* the one control on the viewport: open it */
.sw-open {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 7;
  appearance: none; cursor: pointer;
  min-height: 44px; padding: 0 1.15rem;
  font-family: var(--sw-mono); font-size: .66rem; letter-spacing: .16em;
  color: #1a0510; font-weight: 700;
  background: linear-gradient(180deg, #fde68a, var(--sw-amber));
  border: 1px solid #fff7ed; border-radius: 999px;
  box-shadow: 0 0 26px rgba(251, 191, 36, .45);
}
.sw-open:hover { filter: brightness(1.08); }
.sw-view:not(.is-idle) .sw-open { display: none; }

.sw-note {
  display: flex; gap: .5rem; align-items: flex-start;
  margin-top: .6rem; padding: .5rem .7rem;
  border-left: 2px solid var(--sw-cyan);
  background: rgba(34, 211, 238, .07);
  font-size: .86rem; color: #9fc4d4;
}
.sw-note b {
  font-family: var(--sw-mono); font-size: .56rem; letter-spacing: .14em;
  color: var(--sw-cyan); white-space: nowrap; padding-top: .18rem;
}

/* ─── the rail ────────────────────────────────────────────────────── */
.sw-rail-h {
  font-family: var(--sw-mono); font-size: .6rem; letter-spacing: .18em;
  color: var(--sw-violet); margin: 0 0 .7rem;
}
.sw-rail {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
  gap: .6rem;
}
.sw-pick {
  appearance: none; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: .2rem;
  min-height: 44px; padding: .65rem .75rem;
  background: var(--sw-panel); color: inherit;
  border: 1px solid var(--sw-rule);
  transition: border-color .12s, background .12s;
}
.sw-pick:hover { border-color: var(--sw-violet); }
.sw-pick[aria-pressed="true"] {
  border-color: var(--sw-amber);
  background: #1d1029;
  box-shadow: inset 3px 0 0 var(--sw-amber);
}
.sw-pick .nm {
  font-family: var(--sw-disp); font-size: 1.12rem; font-weight: 500;
  color: #fff; line-height: 1.15;
}
.sw-pick .wh {
  font-family: var(--sw-mono); font-size: .56rem; letter-spacing: .1em;
  color: var(--sw-dim);
}
.sw-pick .st {
  font-family: var(--sw-mono); font-size: .54rem; letter-spacing: .12em;
  display: flex; align-items: center; gap: .32rem; margin-top: .12rem;
}
.sw-pick .st i {
  width: 6px; height: 6px; border-radius: 50%;
  border: 1px solid currentColor; flex: 0 0 auto;
}
.sw-pick.s-live   .st { color: var(--sw-amber); }
.sw-pick.s-live   .st i { background: currentColor; }
.sw-pick.s-dark   .st { color: var(--sw-dim); }
.sw-pick.s-none   .st { color: #5b4d72; }
.sw-pick.s-none   { opacity: .72; }
.sw-pick.s-none:hover { opacity: 1; }

.sw-foot {
  margin-top: 2.4rem; padding-top: 1rem;
  border-top: 1px solid var(--sw-rule);
  color: var(--sw-dim); font-size: .84rem; max-width: 66ch;
}
.sw-foot a { color: var(--sw-muted); }

.sw-open:focus-visible,
.sw-pick:focus-visible,
.sw-skip:focus-visible {
  outline: 2px solid var(--sw-cyan); outline-offset: 2px;
}

@media (max-width: 620px) {
  .sw-wrap { padding: 1.1rem .85rem 3rem; }
  .sw-rail { grid-template-columns: 1fr 1fr; }
  .sw-stage .sw-view { border-radius: 10px; }
}
@media (max-width: 400px) {
  .sw-rail { grid-template-columns: 1fr; }
}
