/* =========================================================================
   PLUMB - Interaction & motion layer
   -------------------------------------------------------------------------
   The brand is named for the plumb line: a weight on a string that swings,
   then settles to true vertical. That single idea drives the motion system.

   Three registers of motion:
     1. WORKING motion - fast, precise, no bounce. Buttons, rows, inputs.
        95% of the product. Uses --ease-out. Hover washes, press sinks 1px.
     2. SETTLE motion - the brand "finds true vertical": the mark on load,
        a value counting in and landing, the inspector sliding in. A damped
        pendulum that overshoots once and settles. Never decorative.
     3. INSTRUMENT motion - the drawing behaves like an instrument being
        read: numerals COUNT IN (never fade in), stamps SLAM DOWN, commit
        lines TYPE OUT, an analysis sweep crosses a plate. These are
        moments of record - used when the system asserts a fact.

   Import order: this file is pulled in by colors_and_type.css before the
   tokens are defined, so hard-code fallbacks where a var is load-bearing.
   ========================================================================= */

:root {
  /* ---------- MOTION CURVES --------------------------------------- */
  /* Working UI - ease-out-quint. Precise, no overshoot.                  */
  --ease-out:    cubic-bezier(0.22, 1, 0.36, 1);   /* @kind other */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);   /* @kind other */
  /* The plumb settle - a single, controlled overshoot. The signature.    */
  --ease-plumb:  cubic-bezier(0.34, 1.42, 0.5, 1); /* @kind other */
  /* A softer settle for larger travel (panels, drawers).                 */
  --ease-settle: cubic-bezier(0.16, 1.08, 0.3, 1); /* @kind other */
  /* The slam - a stamp hitting paper. Fast in, dead stop.                */
  --ease-slam:   cubic-bezier(0.2, 0.8, 0.3, 1);   /* @kind other */
  /* Radar / scan for AI work.                                            */
  --ease-radar:  cubic-bezier(0.4, 0, 0, 1);       /* @kind other */

  /* ---------- DURATIONS (all @kind other) ------------------------- */
  --dur-instant: 80ms;    /* @kind other */  /* page cross-fade            */
  --dur-fast:    120ms;   /* @kind other */  /* hover, press, focus        */
  --dur-base:    180ms;   /* @kind other */  /* default transition         */
  --dur-slow:    320ms;   /* @kind other */  /* drawer / panel travel      */
  --dur-slam:    320ms;   /* @kind other */  /* stamp landing              */
  --dur-count:   950ms;   /* @kind other */  /* numeral count-in (JS)      */
  --dur-swing:   1150ms;  /* @kind other */  /* full pendulum settle       */
  --dur-radar:   1600ms;  /* @kind other */  /* one analysis sweep         */

  /* ---------- INTERACTION DISPLACEMENTS --------------------------- */
  /* Tone moves first (paper wash), then tiny travel. Nothing scales.    */
  --press-drop:  1px;     /* how far a control sinks on :active          */
  --nudge:       2px;     /* chevron / arrow nudge on hover              */

  /* ---------- PLUMB GEOMETRY (shared by mark + accents) ----------- */
  --plumb-swing-max: 13deg;  /* @kind other */  /* starting amplitude of the settle */
}

/* =========================================================================
   KEYFRAMES
   ========================================================================= */

/* The pendulum settle - a damped swing to true vertical (0deg).
   Apply to a group whose transform-origin sits at the suspension point. */
@keyframes plumb-swing {
  0%   { transform: rotate(calc(-1 * var(--plumb-swing-max))); }
  22%  { transform: rotate(calc(0.62 * var(--plumb-swing-max))); }
  44%  { transform: rotate(calc(-0.32 * var(--plumb-swing-max))); }
  64%  { transform: rotate(calc(0.16 * var(--plumb-swing-max))); }
  82%  { transform: rotate(calc(-0.07 * var(--plumb-swing-max))); }
  100% { transform: rotate(0deg); }
}

/* The string drops and the bob falls into place - first paint. */
@keyframes plumb-drop {
  0%   { transform: translateY(-8px); opacity: 0; }
  60%  { opacity: 1; }
  100% { transform: translateY(0); opacity: 1; }
}

/* A value "finds level" - slides up a hair and settles. Translate-only
   (no opacity) so the value is never hidden if the animation is skipped. */
@keyframes plumb-settle-up {
  0%   { transform: translateY(7px); }
  100% { transform: translateY(0); }
}

/* The stamp - COMPLETE / VERIFIED marks slam onto the sheet. */
@keyframes plumb-slam {
  0%   { transform: scale(1.9); opacity: 0; }
  70%  { transform: scale(0.96); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* Radar sweep for AI analysis - a thin clay wash crossing a plate. */
@keyframes plumb-radar {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* Live pulse - the "analysis running" dot / the ● in a live badge. */
@keyframes plumb-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}

/* Right-side drawer / inspector slides in and settles. */
@keyframes plumb-drawer-in {
  0%   { transform: translateX(20px); opacity: 0; }
  100% { transform: translateX(0); opacity: 1; }
}

/* =========================================================================
   INTERACTION UTILITIES - opt-in classes
   ========================================================================= */

/* A control that sinks on press by tone + 1px. Never scales. */
.plumb-press {
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.plumb-press:active {
  transform: translateY(var(--press-drop));
}

/* A plate that sharpens on hover - the rule darkens, the corner ticks
   ink in. Paper does not float; do not add shadow or lift here. */
.plumb-sharpen {
  transition: border-color var(--dur-base) var(--ease-out),
              background var(--dur-base) var(--ease-out);
}
.plumb-sharpen:hover {
  border-color: var(--line-strong, #D2CDC0);
}

/* An icon / chevron that nudges in the read direction on parent hover. */
.plumb-nudge {
  transition: transform var(--dur-base) var(--ease-plumb);
}
:hover > .plumb-nudge,
.plumb-nudge:hover {
  transform: translateX(var(--nudge));
}

/* A link whose clay underline draws in from the left on hover. */
.plumb-underline {
  background-image: linear-gradient(var(--clay-500, #C4552F), var(--clay-500, #C4552F));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size var(--dur-base) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
  text-decoration: none;
}
.plumb-underline:hover { background-size: 100% 1px; }

/* The signature: plays the swing once on mount. transform-origin must be
   set by the element (its suspension point). */
.plumb-settle {
  animation: plumb-swing var(--dur-swing) var(--ease-settle) both;
}

/* Number / value that finds level on mount. Pair with a JS count-in:
   numerals should COUNT to their value (never fade in) - see README. */
.plumb-value {
  animation: plumb-settle-up var(--dur-slow) var(--ease-plumb) both;
}

/* A stamp that slams down. Re-trigger by re-adding the class. */
.plumb-slam {
  animation: plumb-slam var(--dur-slam) var(--ease-slam) both;
}

/* A plate that hosts a moving clay sweep while [data-analyzing] is set. */
.plumb-scan { position: relative; overflow: hidden; }
.plumb-scan[data-analyzing]::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(90deg,
    transparent 0%,
    color-mix(in oklab, var(--clay-500, #C4552F) 0%, transparent) 35%,
    color-mix(in oklab, var(--clay-500, #C4552F) 14%, transparent) 50%,
    color-mix(in oklab, var(--clay-500, #C4552F) 0%, transparent) 65%,
    transparent 100%);
  animation: plumb-radar var(--dur-radar) var(--ease-radar) infinite;
  pointer-events: none;
}

/* Respect reduced-motion - collapse all signature motion to its end state. */
@media (prefers-reduced-motion: reduce) {
  .plumb-settle, .plumb-value, .plumb-slam { animation: none; }
  .plumb-scan[data-analyzing]::after { animation: none; opacity: 0; }
  * { scroll-behavior: auto !important; }
}
