/* Motion & easing — duration scale, easing curves, and rules of thumb.
   Belongs on the Brand page. Static-keyframe demos so we don't pull in
   any animation libraries; everything is plain CSS + inline styles. */

const MOTION_DURATIONS = [
  {
    name: '--motion-fast',
    ms: 120,
    use: 'Micro-interactions — hover, focus ring, button press, ripple.',
  },
  {
    name: '--motion-normal',
    ms: 200,
    use: 'Default for state changes — open/close panels, switch tabs, toggle.',
  },
  {
    name: '--motion-slow',
    ms: 320,
    use: 'Substantive transitions — modal open, page route, drawer slide.',
  },
  {
    name: '--motion-graceful',
    ms: 480,
    use: 'Content reveal, list-stagger root, hero-section choreography.',
  },
];

const MOTION_EASINGS = [
  {
    name: '--ease-out',
    bezier: 'cubic-bezier(0.0, 0.0, 0.2, 1)',
    use: 'Default for "entering" elements — panels opening, content revealing.',
  },
  {
    name: '--ease-in',
    bezier: 'cubic-bezier(0.4, 0.0, 1, 1)',
    use: 'For "exiting" elements — panels closing, content dismissal.',
  },
  {
    name: '--ease-in-out',
    bezier: 'cubic-bezier(0.4, 0.0, 0.2, 1)',
    use: 'For elements travelling across the screen — sliders, sortable rows.',
  },
  {
    name: '--ease-out-expressive',
    bezier: 'cubic-bezier(0.16, 1, 0.3, 1)',
    use: 'Celebratory reveals — success states, confetti. Use sparingly.',
  },
];

const MOTION_RULES = [
  'Default any new transition to 200ms ease-out.',
  'Never animate more than two properties simultaneously.',
  'Respect prefers-reduced-motion (compress all durations to 0 or sub-50ms).',
  'Don\'t animate properties that cause layout (margin, top, width); prefer transform and opacity.',
  'Match the animation polarity: opening → ease-out, closing → ease-in.',
  'List entry/exit can use a 30-50ms stagger between siblings.',
];

/* Inline keyframes — defined once, reused by every duration row demo.
   Each row picks a different animation-duration so the same keyframe
   trace runs at fast/normal/slow/graceful tempo. */
const MOTION_KEYFRAMES = `
@keyframes nx-motion-slide {
  0%   { transform: translateX(0); }
  50%  { transform: translateX(72px); }
  100% { transform: translateX(0); }
}
@keyframes nx-motion-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.9); }
  50%      { opacity: 1;    transform: scale(1.0); }
}
.nx-motion-square {
  width: 18px; height: 18px;
  border-radius: 4px;
  background: var(--brand-600);
  animation-name: nx-motion-slide;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
.nx-motion-track {
  position: relative;
  height: 28px;
  width: 100%;
  max-width: 132px;
  display: flex; align-items: center;
  padding: 5px 8px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-tertiary);
  border-radius: 8px;
  overflow: hidden;
}
.nx-easing-curve {
  width: 56px; height: 56px;
  display: block;
}
.nx-easing-row:hover .nx-easing-curve path { stroke: var(--brand-500); }
`;

function MotionStyleTag() {
  return <style dangerouslySetInnerHTML={{ __html: MOTION_KEYFRAMES }} />;
}

/* Render the cubic-bezier as a tiny SVG curve so the easing visually
   matches its name. Inputs are the four control values. */
function EasingCurve({ p1x, p1y, p2x, p2y }) {
  const W = 56, H = 56, pad = 6;
  const map = (x, y) => [pad + x * (W - pad * 2), H - pad - y * (H - pad * 2)];
  const [x1, y1] = map(p1x, p1y);
  const [x2, y2] = map(p2x, p2y);
  const [sx, sy] = map(0, 0);
  const [ex, ey] = map(1, 1);
  return (
    <svg className="nx-easing-curve" viewBox={`0 0 ${W} ${H}`} aria-hidden="true">
      <line x1={pad} y1={H - pad} x2={W - pad} y2={H - pad} stroke="var(--border-tertiary)" strokeWidth="1" />
      <line x1={pad} y1={pad} x2={pad} y2={H - pad} stroke="var(--border-tertiary)" strokeWidth="1" />
      <path
        d={`M ${sx} ${sy} C ${x1} ${y1}, ${x2} ${y2}, ${ex} ${ey}`}
        fill="none" stroke="var(--brand-600)" strokeWidth="1.5" strokeLinecap="round"
      />
    </svg>
  );
}

function parseBezier(str) {
  const m = str.match(/cubic-bezier\(([^)]+)\)/);
  if (!m) return [0, 0, 1, 1];
  return m[1].split(',').map(s => parseFloat(s.trim()));
}

function DurationRow({ token, ms, use }) {
  return (
    <div
      onClick={() => copy(`${ms}ms`)}
      style={{
        display: 'grid',
        gridTemplateColumns: '180px 64px 1fr 152px',
        alignItems: 'center',
        gap: 16,
        padding: '14px 16px',
        borderRadius: 12,
        cursor: 'pointer',
        transition: 'background .15s',
      }}
      onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-secondary)'}
      onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
    >
      <code style={{
        fontSize: 12, fontFamily: 'var(--font-mono)', fontWeight: 600,
        color: 'var(--text-primary)',
      }}>{token}</code>
      <div style={{ fontSize: 13, color: 'var(--text-secondary)', fontFamily: 'var(--font-mono)' }}>
        {ms}ms
      </div>
      <div style={{ fontSize: 13, color: 'var(--text-tertiary)', lineHeight: 1.5 }}>{use}</div>
      <div className="nx-motion-track">
        <div
          className="nx-motion-square"
          style={{
            animationDuration: `${ms}ms`,
            animationTimingFunction: 'cubic-bezier(0.4, 0.0, 0.2, 1)',
          }}
        />
      </div>
    </div>
  );
}

function EasingRow({ token, bezier, use }) {
  const [p1x, p1y, p2x, p2y] = parseBezier(bezier);
  return (
    <div
      className="nx-easing-row"
      onClick={() => copy(bezier)}
      style={{
        display: 'grid',
        gridTemplateColumns: '72px 220px 1fr auto',
        alignItems: 'center',
        gap: 16,
        padding: '14px 16px',
        borderRadius: 12,
        cursor: 'pointer',
        transition: 'background .15s',
      }}
      onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-secondary)'}
      onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
    >
      <EasingCurve p1x={p1x} p1y={p1y} p2x={p2x} p2y={p2y} />
      <code style={{
        fontSize: 12, fontFamily: 'var(--font-mono)', fontWeight: 600,
        color: 'var(--text-primary)',
      }}>{token}</code>
      <div style={{ fontSize: 13, color: 'var(--text-tertiary)', lineHeight: 1.5 }}>{use}</div>
      <code style={{
        fontSize: 11, fontFamily: 'var(--font-mono)',
        color: 'var(--text-quaternary)', whiteSpace: 'nowrap',
      }}>{bezier}</code>
    </div>
  );
}

function S_Motion() {
  return (
    <Section
      id="motion"
      eyebrow="12 · Motion"
      title="Motion & easing"
      intro="Motion communicates causality. Keep it brief, predictable, and quiet — animation should never compete with content."
    >
      <MotionStyleTag />

      <Block title="Duration scale" note="Click any row to copy the millisecond value.">
        <Card pad={8}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
            {MOTION_DURATIONS.map(d => (
              <DurationRow key={d.name} token={d.name} ms={d.ms} use={d.use} />
            ))}
          </div>
        </Card>
      </Block>

      <Block title="Easing curves" note="Click a row to copy the cubic-bezier string.">
        <Card pad={8}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
            {MOTION_EASINGS.map(e => (
              <EasingRow key={e.name} token={e.name} bezier={e.bezier} use={e.use} />
            ))}
          </div>
        </Card>
      </Block>

      <Block title="Rules of thumb" note="When in doubt, snap a 200ms ease-out and move on.">
        <Card pad={28}>
          <ul style={{
            margin: 0, padding: 0, listStyle: 'none',
            display: 'flex', flexDirection: 'column', gap: 12,
          }}>
            {MOTION_RULES.map((r, i) => (
              <li
                key={i}
                style={{
                  display: 'grid',
                  gridTemplateColumns: '24px 1fr',
                  alignItems: 'baseline',
                  gap: 8,
                  fontSize: 14,
                  lineHeight: 1.55,
                  color: 'var(--text-secondary)',
                }}
              >
                <span style={{
                  fontFamily: 'var(--font-mono)',
                  fontSize: 11,
                  color: 'var(--text-quaternary)',
                }}>{String(i + 1).padStart(2, '0')}</span>
                <span>{r}</span>
              </li>
            ))}
          </ul>
        </Card>
      </Block>

      <Block title="Reduced motion">
        <Card pad={20} variant="inset">
          <div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.6, marginBottom: 12 }}>
            Wrap any non-essential transition in a media-query guard. The system tokens above are the
            "full motion" defaults; when the user has reduced motion enabled, collapse them.
          </div>
          <Code block>{`@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 0ms;
    --motion-normal: 0ms;
    --motion-slow: 0ms;
    --motion-graceful: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}`}</Code>
        </Card>
      </Block>
    </Section>
  );
}

window.S_Motion = S_Motion;
