/* xp-viewer.css — EXPERIMENTAL single-mode surfaces (branch experimental/mobile-ux-v2).
   Owned by web/viewer.js. Nothing here may touch a shipped `.vw-*` rule: every selector is
   scoped under `html.xp`, which common.js's applyXpPref() puts on <html> only while the
   experimental flag is on, so this sheet is INERT on the shipped experience even though the
   viewer injects the <link> unconditionally once the flag has been seen.

   Two surfaces:
     · .xpv-lin — the LINEAGE panel (the post's variant family, GET /api/posts/:id/genealogy).
       It slides in from the right because that is the direction the edge swipe came from, and
       swiping it right sends it back the way it arrived.
     · .xpv-cfg — the gesture REMAP panel. ⚠ It is reached from a quiet line at the BOTTOM OF
       THE DETAIL SHEET, not from the top chrome (owner ruling 2026-07-28u: a niche remap
       panel must not carry the same weight as ✕ and ⤢). The panel is therefore anchored to
       the BOTTOM of the screen, near the control that opens it — a dialog that appears at the
       far end of the phone from your thumb is its own complaint.

   Mobile first: every interactive row is at least 44px tall, and every transition is dropped
   under prefers-reduced-motion (the viewer's own reduceMotion() takes the same branch in JS,
   so the two agree). */

/* The ⚙ that opens the remap panel. It now lives in the sheet, where .vw-sh-gear carries the
   44px box and the quiet type — this rule only sets the glyph's own size, so the label reads
   as a line of text with a mark in front of it rather than as a button. */
html.xp .xpv-gear::first-letter { font-size: 15px; }

/* ---- lineage panel ------------------------------------------------------ */
html.xp .xpv-lin {
  position: absolute; inset: 0; z-index: 7;
  display: flex; flex-direction: column;
  background: var(--panel, #14161a);
  transform: translate3d(100%, 0, 0);
  /* THE SLIDE — the archive's one curve, declared on :root in app.css. ⚠ THIS SHEET IS THE ONE
     THAT HAD TO BE CHECKED: it is a separate <link>, statically on index.html and injected by
     viewer.js's ensureXpCss() elsewhere, so an unresolvable var() here would not fall back to
     `ease`, it would invalidate the whole `transition` and the lineage panel would appear with
     no travel at all. All four pages that can reach it (index/post/queue/collective) link
     app.css first — verified, and re-verified per run by tools/viewer_e2e.sh §21. */
  transition: transform .22s var(--slide-ease);
  will-change: transform;
  overscroll-behavior: contain;
}
html.xp .xpv-lin.in { transform: translate3d(0, 0, 0); }
html.xp .xpv-lin-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: calc(env(safe-area-inset-top, 0px) + 6px) 10px 6px;
  border-bottom: 1px solid var(--hair, rgba(255,255,255,.12));
}
html.xp .xpv-lin-x {
  background: none; border: 0; color: var(--bright, #fff); font: inherit; font-size: 18px;
  min-width: 44px; min-height: 44px; display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
html.xp .xpv-lin-title {
  color: var(--ink, #c9ced6); font-size: 11px; letter-spacing: .14em; text-transform: lowercase;
}
html.xp .xpv-lin-body {
  flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; touch-action: pan-y;
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
}
html.xp .xpv-lin-hint {
  color: var(--dim, #8a919b); font-size: 11px; padding: 10px 14px;
}
html.xp .xpv-lin-row {
  display: flex; align-items: center; gap: 10px;
  min-height: 56px; padding: 6px 12px 6px 8px;
  color: var(--ink, #c9ced6); text-decoration: none; font-size: 12px;
  border-bottom: 1px solid var(--hair, rgba(255,255,255,.07));
}
html.xp .xpv-lin-row.focus { background: rgba(255,255,255,.06); color: var(--bright, #fff); }
html.xp .xpv-lin-th {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 3px; overflow: hidden;
  background: rgba(255,255,255,.06); display: block;
}
html.xp .xpv-lin-th img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* a MASKED family member (someone else's pending/hidden/locked) has no thumb by design —
   the shape of the family is intact, the content is not shown */
html.xp .xpv-lin-th.masked { background: repeating-linear-gradient(45deg,
  rgba(255,255,255,.05) 0 6px, rgba(255,255,255,.02) 6px 12px); }
html.xp .xpv-lin-txt { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.xp .xpv-lin-here {
  flex: 0 0 auto; font-size: 10px; letter-spacing: .1em;
  color: var(--accent, #7fd1c1); border: 1px solid currentColor; border-radius: 2px; padding: 2px 5px;
}

/* ---- gesture remap panel ------------------------------------------------ */
html.xp .xpv-cfg {
  position: absolute; z-index: 8;
  left: 10px; right: 10px; bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  max-height: 70vh; overflow-y: auto; touch-action: pan-y;
  background: var(--panel, #14161a); border: 1px solid var(--hair-hi, rgba(255,255,255,.18));
  border-radius: 4px; box-shadow: 0 16px 48px rgba(0,0,0,.6);
  padding: 4px 10px 10px;
}
html.xp .xpv-cfg-head { display: flex; align-items: center; justify-content: space-between; }
html.xp .xpv-cfg-title {
  color: var(--ink, #c9ced6); font-size: 11px; letter-spacing: .14em;
}
html.xp .xpv-cfg-x {
  background: none; border: 0; color: var(--bright, #fff); font: inherit;
  min-width: 44px; min-height: 44px; cursor: pointer;
}
html.xp .xpv-cfg-row {
  display: flex; align-items: center; gap: 10px; min-height: 44px;
  border-top: 1px solid var(--hair, rgba(255,255,255,.08));
}
html.xp .xpv-cfg-k { flex: 1 1 auto; color: var(--ink, #c9ced6); font-size: 12px; }
html.xp .xpv-cfg-v {
  flex: 0 0 auto; min-height: 44px; min-width: 132px;
  background: var(--bg, #0e1013); color: var(--bright, #fff);
  border: 1px solid var(--hair-hi, rgba(255,255,255,.18)); border-radius: 3px;
  font: inherit; font-size: 12px; padding: 4px 6px;
}
html.xp .xpv-cfg-reset {
  margin-top: 8px; width: 100%; min-height: 44px; cursor: pointer;
  background: none; border: 1px solid var(--hair-hi, rgba(255,255,255,.18)); border-radius: 3px;
  color: var(--dim, #8a919b); font: inherit; font-size: 11px; letter-spacing: .1em;
}

/* ---- the toast the silent actions need ----------------------------------
   ⚠ DELIBERATELY NOT SCOPED UNDER html.xp. This started gated like everything else in this
   sheet, and that made it INVISIBLE with the flag off — which is how the dead ⊕ on
   post/queue/collective went unnoticed: the code was calling flash("linking unavailable
   here") and nothing was ever drawn. A diagnostic you cannot see is worse than none, because
   it convinces the code's author the user was told. The toast is chrome for a CORE control,
   so it is styled unconditionally; the flag decides FEATURES, never whether an error is
   legible. */
.xpv-toast {
  position: absolute; z-index: 9; left: 50%; bottom: 22%;
  transform: translateX(-50%);
  max-width: 80vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: rgba(0,0,0,.82); color: var(--bright, #fff);
  border: 1px solid var(--hair-hi, rgba(255,255,255,.18)); border-radius: 3px;
  padding: 8px 12px; font-size: 12px; pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  html.xp .xpv-lin { transition: none; }
}
