/* motion-control.css — the CIC shell's motion drawer.
 *
 * Companion to motion-control.js, which injects this file relative to its own
 * module URL, so the same stylesheet serves `/cic/` and `/cic/overwatch/`
 * without a base-path guess.
 *
 * SCOPE. The drawer shell itself — .drawer, .drawer-right, .drawer-content,
 * .drawer-tab, the rail — is already styled by the shell's styles.css and is
 * NOT restated here. This file adds only what is specific to motion, so a
 * change to the shell's drawer look lands here for free and there is nothing
 * to keep in sync. Everything is expressed in the shell's own tokens
 * (--line, --ink, --muted, --accent, --surface-subtle, --field-surface,
 * --control-surface) rather than a forked palette, for the same reason.
 *
 * Ported from the JSLC Mainframe rules (`jslc/shell/public/styles.css`,
 * `.motion-*`), retokenised: the original used the --of-* office palette, which
 * belongs to that product.
 */

.motion-drawer { width: min(21rem, calc(100% - 2.6rem)); }

.motion-drawer-content { display: grid; align-content: start; gap: .7rem; }

.motion-actions { display: grid; grid-template-columns: 1fr 1fr; gap: .45rem; }
.motion-actions button {
  min-height: var(--ui-control-height, 2rem);
  border: 1px solid var(--line);
  background: var(--control-surface);
  color: var(--ink);
  font: inherit;
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
}
.motion-actions button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.motion-actions button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.motion-actions button:disabled { opacity: .45; cursor: not-allowed; }
.motion-actions .primary-button { border-color: var(--accent); background: var(--accent-subtle); color: var(--ink); }
.motion-actions .primary-button[aria-pressed="true"] { background: var(--accent); color: var(--field-surface); }

.motion-drawer #motion-status { margin: 0; color: var(--muted); font-size: .62rem; line-height: 1.4; }

/* ---- live tester ---- */
.motion-tester { display: grid; gap: .55rem; }
.motion-tester-heading,
.motion-slider > span { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.motion-tester-heading strong,
.motion-slider strong,
.motion-help strong {
  font-size: .66rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink);
}
.motion-tester-heading output { color: var(--accent); font-size: .66rem; font-weight: 800; font-variant-numeric: tabular-nums; }

/* ---- the shared two-axis pad (createPad) ----
   ONE component, two sizes. `.cic-pad` is the drawer's live tester; the
   `--sm` modifier is the same control shrunk for a surface's own toolbar --
   the Overwatch globe steers its spin with it. Sizing is the only difference,
   so the two can never drift apart in behaviour or in look. */
.cic-pad {
  position: relative;
  width: 100%;
  aspect-ratio: 1.7;
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--field-surface);
  /* A direct-manipulation surface: the browser must not claim the drag for
     panning, or the swipe path can never be demonstrated on a phone. */
  touch-action: none;
  cursor: grab;
}
.cic-pad:active { cursor: grabbing; }
.cic-pad:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* WIDTH *AND* HEIGHT, not width plus an aspect ratio.
   The pad's children are all absolutely positioned, so its in-flow content
   height is zero and its height came entirely from `aspect-ratio`. That is fine
   until it is a flex item: a stretched flex item takes its cross size from the
   line, the line takes its height from the content, and the content is this
   element -- circular, and engines break the cycle differently. Chromium
   resolves it to 83.2px; the owner's iPhone rendered the pad as a single
   horizontal line, which is this cycle collapsing to zero on the other engine
   and is what "my joystick is gone" looked like on his screen.
   An explicit height removes the cycle instead of betting on how it is broken.
   `aspect-ratio` is kept so the two stay in step if the width is ever changed,
   and `align-self` stops the parent stretching it in the first place. */
.cic-pad--sm {
  width: 5.2rem;
  height: 5.2rem;
  aspect-ratio: 1;
  align-self: center;
  border-radius: .25rem;
}
.cic-pad-axis { position: absolute; background: var(--line); }
.cic-pad-axis-h { top: 50%; right: .35rem; left: .35rem; height: 1px; }
.cic-pad-axis-v { top: .35rem; bottom: .35rem; left: 50%; width: 1px; }
/* A detent: where a meaningful value sits on a scale that is not linear. */
.cic-pad-tick {
  position: absolute; width: 1px; height: .42rem;
  margin-left: -.5px; transform: translateY(-50%);
  background: var(--accent); opacity: .75;
}
/* THE PUCK TRAVELS INSIDE THE PAD, NOT ONTO ITS EDGE.
   `paint()` publishes two 0..1 numbers, `--px` and `--py`, and the geometry is
   done here. It used to set `left`/`top` directly as percentages, which put the
   puck's CENTRE on the pad's border at full deflection -- and the pad is
   `overflow:hidden`, so half the puck was cut away. Measured at full travel:
   46-50% of the puck visible. With the pad's own border at .20 alpha that
   leaves a faint sliver and an axis line, which is exactly what "my joystick is
   gone" looked like on the owner's phone.
   Insetting the travel by half a puck is done in CSS rather than in JS because
   only the stylesheet knows how big the puck is -- `--sm` makes it smaller --
   so a size change can never again fall out of step with the travel. */
.cic-pad-puck {
  --s: 1.2rem;
  position: absolute;
  width: var(--s); height: var(--s);
  left: calc(var(--s) / 2 + (100% - var(--s)) * var(--px, .5));
  top:  calc(var(--s) / 2 + (100% - var(--s)) * var(--py, .5));
  border: 2px solid var(--field-surface);
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 .2rem .6rem rgb(0 0 0 / .38);
  transform: translate(-50%, -50%);
  transition: left 45ms linear, top 45ms linear;
}
.cic-pad--sm .cic-pad-puck { --s: .8rem; border-width: 1.5px; }

/* Aliases kept because the drawer's ids and direction labels are part of its
   published markup: `#motion-test-field` IS the pad element. */
.motion-label { position: absolute; color: var(--muted); font-size: .54rem; font-weight: 700; text-transform: uppercase; }
.motion-left { top: calc(50% + .35rem); left: .35rem; }
.motion-right { top: calc(50% + .35rem); right: .35rem; }
.motion-forward { top: .3rem; left: calc(50% + .35rem); }
.motion-back { bottom: .3rem; left: calc(50% + .35rem); }

.motion-meter-row {
  display: grid; grid-template-columns: 2rem 1fr 2.7rem; gap: .4rem;
  align-items: center; font-size: .62rem; font-variant-numeric: tabular-nums; color: var(--muted);
}
.motion-meter-row meter { width: 100%; }
.motion-meter-row output { text-align: right; color: var(--ink); }

/* ---- sensitivity ---- */
.motion-slider { display: grid; gap: .35rem; padding: .55rem; border: 1px solid var(--line); background: var(--surface-subtle); }
.motion-slider input { width: 100%; min-height: 1.9rem; margin: 0; accent-color: var(--accent); }
.motion-slider output { color: var(--accent); font-weight: 800; font-variant-numeric: tabular-nums; }
.motion-slider small { color: var(--muted); font-size: .58rem; line-height: 1.35; }

/* ---- which inputs do what on this surface ---- */
.motion-help ul { margin: .35rem 0 .2rem; padding-left: 1rem; color: var(--muted); font-size: .6rem; line-height: 1.45; }
.motion-help li { margin: .15rem 0; }
.motion-help b { color: var(--ink); font-weight: 700; }
.motion-help #motion-consumers { margin: .3rem 0 0; color: var(--muted); font-size: .58rem; }

/* The rail tab is a plain .drawer-tab; only its accent stripe is motion's, so a
   user can find it by edge colour without reading the rotated label. */
.motion-drawer-tab { border-bottom: 2px solid var(--accent); }

/* A reduced-motion user still gets the capability — the module halves the
   key-ramp gain rather than removing the control — but nothing here animates. */
@media (prefers-reduced-motion: reduce) {
  .cic-pad-puck { transition: none; }
}
