/*
  Better Help — shared stage stylesheet. THE single source of visual truth
  for every topic animation. Topic files may define: their scene geometry and
  ONE @keyframes block per animated element, using ONLY the tokens and timing
  variables below. Everything else — colours, frame, glyphs, motion grid —
  lives here, so a design change edits one file for all topics.

  LINT RULES (scripts/check_help_stage.sh):
   - no colour literals outside this file (use var(--ink) / currentColor /
     color-mix(in srgb, var(--ink) N%, transparent))
   - animation durations/easings only via var(--loop-duration)/var(--loop-ease)
   - keyframe stops on the canonical grid below
   - glyphs referenced from glyphs.svg, never redrawn
*/

:root {
  --ink: #1d1d1f;
  --paper: #fafafa;
  --card: #ffffff;
  --accent: #0a84ff;
  --on-accent: #ffffff;

  /* Opacity ladder — derive every faded ink from these, never new literals. */
  --ink-soft:  color-mix(in srgb, var(--ink) 55%, transparent);
  --ink-mid:   color-mix(in srgb, var(--ink) 38%, transparent);
  --ink-faint: color-mix(in srgb, var(--ink) 18%, transparent);
  --ink-wash:  color-mix(in srgb, var(--ink) 8%,  transparent);

  --face:       color-mix(in srgb, var(--card) 92%, transparent);
  --face-shade: color-mix(in srgb, var(--ink) 4.5%, transparent);

  /*
    Canonical loop timing grid. Every topic's keyframes use these stops so
    all animations breathe together:
      0%   rest
      8%   fade lead-in begins (fades only)
      14%  input appears / motion begins
      52%  motion peak
      58%  fade lead-out begins (fades only)
      64%  hold at peak
      70%  fade-out complete (fades only)
      96%  returned to rest
      100% rest
  */
  --loop-duration: 6s;
  --loop-ease: cubic-bezier(0.45, 0, 0.25, 1);
}



* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { background: transparent; }

/* The stage is the ONLY thing a topic page shows — captions, steps, and the
   modality switcher are native SwiftUI. The webview is accessibility-hidden;
   the native container carries the localized label. */
.stage {
  position: relative;
  width: 340px;
  height: 250px;
  margin: 0 auto;
  background: var(--card);
  background-image: radial-gradient(var(--ink-faint) 1px, transparent 1px);
  background-size: 22px 22px;
  background-position: 11px 11px;
  border-radius: 20px;
  overflow: hidden;
  -webkit-user-select: none;
  user-select: none;
}

/* ---- shared gesture track ------------------------------------------------
   Topics place .track/.arc/.carrier; the carrier hosts the modality glyphs.
   stage-api.js toggles body classes m-touch / m-pencil / m-keyboard. */
.glyph { position: absolute; opacity: 0; transition: opacity 0.25s ease; }
body.m-touch    .glyph.touch,
body.m-pencil   .glyph.pencil,
body.m-keyboard .glyph.keyboard { opacity: 1; }

/* Modality-scoped SCENE elements (founder rule 2026-08-28): a glyph swap is
   only honest when the behaviour is identical across modalities. When a
   modality behaves differently — e.g. Pencil mode: the finger orbits WHILE
   the pencil draws — the topic stages distinct choreography and gates whole
   scene elements with these classes instead.

   Gated with VISIBILITY. Not opacity: these elements run their own opacity
   keyframes, and an animation on the element beats a gating opacity on the
   same element — that silently played touch-only beats in Pencil and
   Keyboard modality. And not display either: `display: block` clobbers the
   `display: flex` these scene elements use to centre their icon, which
   dropped the orbit-button and tool-chip glyphs into their top-left corner.
   visibility does neither — it cannot be overridden by our keyframes, and
   it leaves layout alone. */
.only-touch, .only-pencil, .only-keyboard { visibility: hidden; }
body.m-touch    .only-touch,
body.m-pencil   .only-pencil,
body.m-keyboard .only-keyboard { visibility: visible; }

.glyph svg { display: block; color: var(--ink); }

.glyph .dot {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--ink-wash);
  border: 1.5px solid var(--ink-mid);
}
.glyph.touch .dot + .dot { position: absolute; left: 30px; top: 0; }

.glyph.keyboard { display: flex; align-items: center; gap: 7px; }
.glyph .key {
  font: 600 13px/1 -apple-system, system-ui;
  color: var(--ink);
  background: var(--card);
  border: 1.5px solid var(--ink-faint);
  border-bottom-width: 3px;
  border-radius: 7px;
  padding: 6px 8px 5px;
  min-width: 27px;
  text-align: center;
}

/* Reduce Motion means STOP, not "slow down" — hold the 52% peak pose, which
   is the frame each loop is composed around, so the stage still reads. */
@media (prefers-reduced-motion: reduce) {
  .stage * {
    animation-play-state: paused !important;
    animation-delay: calc(var(--loop-duration) * -0.52) !important;
    transition: none !important;
  }
}

/* Website: the stage fills its frame (the page scales the frame to fit). */
html, body { overflow: hidden; }
