/* IRONCADE MOTION FOUNDATION - motion.css
   ruleVersion: motion-1.0

   This file does not introduce a new design language. Every token below was
   measured out of styles.css as it already ships. The point is to give the
   values that are already in use a NAME, so that the next screen built uses
   the same number instead of a new one.

   Inventory that produced these tokens (styles.css @ build 86):
     .09s  x1   transform/filter on .addex           -> instant
     .12s  x27  the de-facto house duration          -> fast
     .15s  x2   background, pin dots                 -> fast
     .2s   x2                                        -> standard
     .22s  x1   @keyframes fade (screen enter)       -> standard
     .26s  x2   #pinGate opacity, pwaUp              -> emphasized
     .28s  x1   with cubic-bezier(.3,1.6,.5,1)       -> emphasized + arcade ease
     .35s .5s .7s  width on data bars                -> data

   NOTHING IN THIS FILE IS APPLIED AUTOMATICALLY except the token
   declarations themselves and the reduced-motion safety net. Classes are
   opt-in so that shipping this file cannot change how the live app looks.
*/

:root {
  /* ---- duration scale ---- */
  --motion-instant: 80ms;
  --motion-fast: 120ms;
  --motion-standard: 180ms;
  --motion-emphasized: 240ms;
  --motion-data: 300ms;

  /* ---- easing scale (three, and only three) ---- */
  /* Everyday movement. Symmetric, unremarkable, gets out of the way. */
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  /* Things arriving and settling: sheets, toasts, screens. Already the
     curve behind @keyframes pwaUp, so sheets keep the feel they have. */
  --ease-entrance: cubic-bezier(.22, 1, .36, 1);
  /* The arcade one. Slight overshoot. Reserved for confirmation of a
     completed action - never for routine movement. Already in use at
     styles.css:502 and on the tug-of-war bar. */
  --ease-arcade: cubic-bezier(.3, 1.6, .5, 1);
}

/* ------------------------------------------------------------------
   PRESSED STATE STANDARD

   The audit found 14 pressed rules using 6 different scale values:
   .92 .96 .97 .975 .98 .99. A control's size should not tell you which
   file it was written in. One value, one duration, applied by adding
   class="press" to the element.

   Scale .97 is the median of what already ships and reads as a press on
   a 44px target without looking like a bounce on a 72px one.

   Existing :active rules are deliberately NOT overridden here. They are
   migrated screen by screen in a later phase, so no surface changes
   appearance the moment this file loads.
   ------------------------------------------------------------------ */
.press {
  transition: transform var(--motion-instant) var(--ease-standard);
}
.press:active {
  transform: scale(.97);
}
/* Large targets (>= 64px) need less scale to read as pressed. */
.press.press-lg:active {
  transform: scale(.985);
}
/* Small chips need more. */
.press.press-sm:active {
  transform: scale(.94);
}

/* ------------------------------------------------------------------
   TEXT SELECTION GUARD  (iOS long-press callout on controls)

   The brief is explicit: do not apply user-select: none globally.
   There is a concrete reason in this codebase. styles.css:802 sets
   .wl-crew-id { user-select: all } - that is the CREW INVITE CODE.
   A global guard would make invite codes uncopyable and quietly break
   the way people join a crew.

   So: the guard is a list of chrome and control surfaces, and there is
   an explicit opt-out that outranks it.
   ------------------------------------------------------------------ */
.tabbar,
.tab,
.btn,
.gbtn,
.confirm,
.exp,
.snd,
.addex,
.set-keep,
.mail-btn,
.pwa-cta,
.rpk-opt,
.press,
.seg,
.chip,
.nav-label,
.scorecard-label,
.hdr-title {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Anything a person may legitimately want to copy wins over the guard.
   .wl-crew-id is listed by name because losing it is a real failure. */
.selectable,
.wl-crew-id,
input,
textarea,
[contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}
.wl-crew-id {
  -webkit-user-select: all;
  user-select: all;
}

/* ------------------------------------------------------------------
   REDUCED MOTION

   Before this file there was exactly ONE prefers-reduced-motion rule in
   the whole app (styles.css:678, covering .pwa-sheet-card and .pwa-cta).
   Everything else animated regardless of the setting.

   Reduced motion means reduced, not removed: state still changes, it
   just changes without travel. Opacity is kept because a thing appearing
   is information; transform and width travel are what cause trouble.
   ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-instant: 1ms;
    --motion-fast: 1ms;
    --motion-standard: 1ms;
    --motion-emphasized: 1ms;
    --motion-data: 1ms;
  }

  .press:active,
  .press.press-lg:active,
  .press.press-sm:active {
    transform: none;
  }

  /* Existing app animations, now actually covered. */
  .screen.on { animation: none; }
  #pinDots.shake { animation: none; }
  .blink { animation: none; opacity: 1; }

  /* Data bars still fill - they just arrive rather than travel. */
  .tug-bar,
  .pace-bar,
  .bar-fill {
    transition: none !important;
  }
}

/* ------------------------------------------------------------------
   PROGRAM TARGET CHIPS

   Three states, and the order matters: a chip is only ever one of them,
   so the classes are mutually exclusive by construction in day-category.js
   rather than by fighting specificity here.

   Teal is not a warning. It means "picked, and there is nothing to judge
   yet" - an empty day should not open covered in red.
   ------------------------------------------------------------------ */
.dc-chip {
  transition: background-color var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}
.dc-chip.picked {
  color: #00e5ff;
  border-color: rgba(0, 229, 255, .65);
  background: rgba(0, 229, 255, .12);
}
.dc-chip.met {
  color: #3fe08f;
  border-color: rgba(63, 224, 143, .7);
  background: rgba(63, 224, 143, .14);
}
.dc-chip.unmet {
  color: #ff5c6a;
  border-color: rgba(255, 92, 106, .7);
  background: rgba(255, 92, 106, .13);
}
@media (prefers-reduced-motion: reduce) {
  .dc-chip { transition: none; }
}

/* ============ NAV ACTIVE INDICATOR ============
   The tab bar gains one hairline that slides between tabs. The tabs
   themselves are untouched - same order, same labels, same colours. */
.tabs { --tab-i: 0; --tab-n: 6; }
.tabs::after {
  content: '';
  position: absolute;
  top: 0;
  height: 2px;
  width: calc(100% / var(--tab-n));
  left: 0;
  /* Moved with a transform, not with `left`. One tab's width IS 100% of this
     bar, so translateX(index * 100%) lands exactly on it - no second division
     to get wrong - and the browser can move it without a layout pass. */
  transform: translateX(calc(var(--tab-i) * 100%));
  background: linear-gradient(90deg, transparent, var(--p1), transparent);
  opacity: .9;
  pointer-events: none;
  transition: transform var(--motion-emphasized) var(--ease-entrance);
}
@media (prefers-reduced-motion: reduce) {
  .tabs::after { transition: none; }
}
