/* ══════════════════════════════════════════════════════════════
   motion.css — animation layer for IPE
   Loads AFTER styles.css. Colour lives in styles.css, size in the
   component files, timing lives here. Nothing below hardcodes a hue.

   Motion is ON by default. Under the OS "reduce motion" setting we
   keep short opacity fades and drop movement, rather than killing
   everything — a dead screen reads as broken.
   ══════════════════════════════════════════════════════════════ */

:root {
  --t-fast: 120ms;
  --t: 220ms;
  --t-slow: 400ms;
  --t-page: 560ms;

  --ez: cubic-bezier(0.2, 0, 0, 1);
  --ez-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ez-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
}

/* ── keyframes ─────────────────────────────────────────────── */
@keyframes ipe-rise    { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes ipe-fade    { from { opacity: 0; } to { opacity: 1; } }
@keyframes ipe-slide   { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: none; } }
@keyframes ipe-grow    { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes ipe-pop     { 0% { opacity: 0; transform: scale(0.85); } 60% { transform: scale(1.04); } 100% { opacity: 1; transform: scale(1); } }
@keyframes ipe-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@keyframes ipe-spin    { to { transform: rotate(360deg); } }
@keyframes ipe-flash   { 0%, 100% { background: transparent; } 25% { background: var(--accent-soft); } }

/* ── page + panel entrances ────────────────────────────────── */
.tab-panel {
  animation: ipe-rise var(--t-page) var(--ez-out) both;
}

/* stat cards land in sequence, left to right */
.rpa-stats > .rpa-stat {
  animation: ipe-rise var(--t-page) var(--ez-out) both;
}
.rpa-stats > .rpa-stat:nth-child(1) { animation-delay: 0ms; }
.rpa-stats > .rpa-stat:nth-child(2) { animation-delay: 60ms; }
.rpa-stats > .rpa-stat:nth-child(3) { animation-delay: 120ms; }
.rpa-stats > .rpa-stat:nth-child(4) { animation-delay: 180ms; }
.rpa-stats > .rpa-stat:nth-child(5) { animation-delay: 240ms; }
.rpa-stats > .rpa-stat:nth-child(6) { animation-delay: 300ms; }

/* generic stagger utility — add .ipe-stagger to any parent */
.ipe-stagger > * { animation: ipe-rise var(--t-slow) var(--ez-out) both; }
.ipe-stagger > *:nth-child(1) { animation-delay: 0ms; }
.ipe-stagger > *:nth-child(2) { animation-delay: 55ms; }
.ipe-stagger > *:nth-child(3) { animation-delay: 110ms; }
.ipe-stagger > *:nth-child(4) { animation-delay: 165ms; }
.ipe-stagger > *:nth-child(5) { animation-delay: 220ms; }
.ipe-stagger > *:nth-child(6) { animation-delay: 275ms; }
.ipe-stagger > *:nth-child(7) { animation-delay: 330ms; }
.ipe-stagger > *:nth-child(8) { animation-delay: 385ms; }

/* ── buttons ───────────────────────────────────────────────── */
.btn-primary,
.btn-ghost,
.btn-rpa,
.btn-save,
.view-btn,
.shp-btn {
  transition:
    background var(--t) var(--ez),
    border-color var(--t) var(--ez),
    color var(--t) var(--ez),
    box-shadow var(--t) var(--ez),
    transform var(--t-fast) var(--ez);
}
.btn-primary:hover,
.btn-rpa:hover,
.btn-save:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-lg);
}
.btn-primary:active,
.btn-ghost:active,
.btn-rpa:active,
.btn-save:active,
.view-btn:active,
.shp-btn:active {
  transform: translateY(0) scale(0.975);
}
.btn-primary:focus-visible,
.btn-ghost:focus-visible,
.btn-rpa:focus-visible,
.btn-save:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* busy state — set aria-busy="true" and drop in <span class="ipe-spin"></span> */
[aria-busy="true"] { pointer-events: none; }
.ipe-spin {
  display: inline-block;
  width: 13px;
  height: 13px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ipe-spin 0.7s linear infinite;
  vertical-align: -1px;
}

/* ── tabs ──────────────────────────────────────────────────── */
.tab-btn {
  transition: background var(--t) var(--ez), color var(--t) var(--ez), transform var(--t) var(--ez);
}
.tab-btn:hover { transform: translateX(2px); }
.tab-btn .tab-label { transition: color var(--t-fast) var(--ez); }

/* ── inputs ────────────────────────────────────────────────── */
.rpa-input,
.db-search,
.db-select,
.rs-loc-input,
input[type="text"],
input[type="number"],
input[type="date"],
select,
textarea {
  transition:
    border-color var(--t-fast) var(--ez),
    box-shadow var(--t-fast) var(--ez),
    background var(--t) var(--ez);
}

/* range slider — the margin control */
input[type="range"] { transition: background var(--t) var(--ez); }
input[type="range"]::-webkit-slider-thumb {
  transition: transform var(--t-fast) var(--ez-spring), box-shadow var(--t-fast) var(--ez);
}
input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.15); }
input[type="range"]:active::-webkit-slider-thumb {
  transform: scale(1.3);
  box-shadow: 0 0 0 7px var(--accent-soft);
}

/* ── tables ────────────────────────────────────────────────── */
.rules-table tbody tr,
.table-container tbody tr {
  position: relative;
  transition: background var(--t-fast) var(--ez);
}
.rules-table tbody tr td:first-child::before,
.table-container tbody tr td:first-child::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: center;
  transition: transform var(--t) var(--ez-spring);
}
.rules-table tbody tr:hover td:first-child::before,
.table-container tbody tr:hover td:first-child::before {
  transform: scaleY(1);
}

/* ── cards / stats ─────────────────────────────────────────── */
.rpa-stat { transition: var(--transition); }

/* ── modals and dialogs ────────────────────────────────────── */
.modal-overlay { animation: ipe-fade var(--t) var(--ez) both; }
.modal-box { animation: ipe-rise var(--t-slow) var(--ez-spring) both; }

/* ── chips / badges appearing ──────────────────────────────── */
.ipe-pop { animation: ipe-pop var(--t-slow) var(--ez-spring) both; }

/* ── breakdown rows: reveal in calculation order ───────────── */
.ipe-ladder > .ipe-rung {
  animation: ipe-slide var(--t-slow) var(--ez-out) both;
}
.ipe-ladder > .ipe-rung:nth-child(1) { animation-delay: 60ms; }
.ipe-ladder > .ipe-rung:nth-child(2) { animation-delay: 140ms; }
.ipe-ladder > .ipe-rung:nth-child(3) { animation-delay: 220ms; }
.ipe-ladder > .ipe-rung:nth-child(4) { animation-delay: 300ms; }
.ipe-ladder > .ipe-rung:nth-child(5) { animation-delay: 380ms; }
.ipe-ladder > .ipe-rung:nth-child(6) { animation-delay: 460ms; }

/* highlight a row that just recalculated */
.ipe-lit { animation: ipe-flash 700ms var(--ez) 1; }

/* ── loading skeletons ─────────────────────────────────────── */
.ipe-sk {
  border-radius: 6px;
  background: linear-gradient(90deg, var(--surface-2) 0%, var(--surface-1) 50%, var(--surface-2) 100%);
  background-size: 200% 100%;
  animation: ipe-shimmer 1.3s linear infinite;
}
.ipe-sk-line { height: 13px; margin-bottom: 8px; }
.ipe-sk-title { height: 34px; width: 55%; margin-bottom: 14px; }

.ipe-loading .ipe-live { display: none; }
.ipe-loading .ipe-ghost { display: block; }
.ipe-ghost { display: none; }

/* ── theme switch ──────────────────────────────────────────── */
body,
.rpa-stat,
.modal-box,
.table-container,
.tab-panel {
  transition:
    background var(--t-slow) var(--ez),
    color var(--t-slow) var(--ez),
    border-color var(--t-slow) var(--ez);
}


/* ── Rate Search results (injected by dat-config.js) ───────── */
/* These are built with inline styles and no reusable classes,
   so the reveal is hung on the container instead. */
.ipe-reveal { animation: ipe-rise var(--t-page) var(--ez-out) both; }

.ipe-reveal > div > div,
.ipe-reveal > div > section { animation: ipe-rise var(--t-slow) var(--ez-out) both; }
.ipe-reveal > div > div:nth-child(1) { animation-delay: 40ms; }
.ipe-reveal > div > div:nth-child(2) { animation-delay: 120ms; }
.ipe-reveal > div > div:nth-child(3) { animation-delay: 200ms; }

/* breakdown rows land in calculation order */
.ipe-ladder > * { animation: ipe-slide var(--t-slow) var(--ez-out) both; }
.ipe-ladder > *:nth-child(1) { animation-delay: 40ms; }
.ipe-ladder > *:nth-child(2) { animation-delay: 100ms; }
.ipe-ladder > *:nth-child(3) { animation-delay: 160ms; }
.ipe-ladder > *:nth-child(4) { animation-delay: 220ms; }
.ipe-ladder > *:nth-child(5) { animation-delay: 280ms; }
.ipe-ladder > *:nth-child(6) { animation-delay: 340ms; }

/* the margin slider's own thumb and the trend canvas fading in */
#sug-trend-canvas { animation: ipe-fade var(--t-slow) var(--ez) both; }


/* ══════════════════════════════════════════════════════════════
   Added with the Hub Group brand pass. Everything below hangs off
   a class that actually exists in the rendered markup — the last
   round hung on .rpa-stat and .tab-panel, which Rate Search never
   emits, so none of it was visible on the default screen.
   ══════════════════════════════════════════════════════════════ */

/* ── table rows arrive in order ────────────────────────────── */
.rules-table tbody tr,
.lm-table tbody tr {
  animation: ipe-rise var(--t) var(--ez-out) both;
}
.rules-table tbody tr:nth-child(1)  { animation-delay: 0ms; }
.rules-table tbody tr:nth-child(2)  { animation-delay: 25ms; }
.rules-table tbody tr:nth-child(3)  { animation-delay: 50ms; }
.rules-table tbody tr:nth-child(4)  { animation-delay: 75ms; }
.rules-table tbody tr:nth-child(5)  { animation-delay: 100ms; }
.rules-table tbody tr:nth-child(6)  { animation-delay: 125ms; }
.rules-table tbody tr:nth-child(7)  { animation-delay: 150ms; }
.rules-table tbody tr:nth-child(8)  { animation-delay: 175ms; }
.rules-table tbody tr:nth-child(n+9) { animation-delay: 200ms; }

/* ── sidebar navigation ────────────────────────────────────── */
.nav-item,
.sidebar-nav a,
.tab-btn {
  transition:
    background var(--t-fast) var(--ez),
    color var(--t-fast) var(--ez),
    border-color var(--t-fast) var(--ez),
    transform var(--t-fast) var(--ez-out);
}
.nav-item:hover,
.sidebar-nav a:hover { transform: translateX(2px); }

/* ── the quote figure ───────────────────────────────────────────
   Deliberately a scale-in, not a count-up. A number that ticks
   toward its value cannot be read until it stops, and on this screen
   the number is the entire point.
   ─────────────────────────────────────────────────────────── */
#sug-summary-price-val { animation-delay: 420ms; }

/* ── rung rail draws downward behind the pips ──────────────── */
.ipe-ladder > .ipe-rung > span:first-child {
  transform-origin: top;
  animation: ipe-grow var(--t-slow) var(--ez-out) both;
}

/* ── focus rings ───────────────────────────────────────────── */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  transition: outline-offset var(--t-fast) var(--ez);
}
/* ══════════════════════════════════════════════════════════════
   Reduced motion. Movement and looping effects go; short fades
   stay so the interface still acknowledges what happened.
   ══════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  /* Movement is what triggers vestibular discomfort, not duration.
     So: shorten the travel distance and stop anything that loops.
     Entrances stay visible rather than collapsing to nothing, which
     is what made the interface look frozen. */

  @keyframes ipe-rise  { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: none; } }
  @keyframes ipe-slide { from { opacity: 0; transform: none; } to { opacity: 1; transform: none; } }
  @keyframes ipe-pop   { from { opacity: 0; } to { opacity: 1; } }

  .btn-primary:hover,
  .btn-rpa:hover,
  .btn-save:hover,
  .tab-btn:hover { transform: none; }

  input[type="range"]:hover::-webkit-slider-thumb,
  input[type="range"]:active::-webkit-slider-thumb { transform: none; }

  .ipe-sk { animation: none; background: var(--surface-2); }
  .ipe-lit { animation: none; background: var(--accent-soft); }
  .ipe-spin { animation-duration: 1.6s; }

  .nav-item:hover,
  .sidebar-nav a:hover { transform: none; }
  .ipe-ladder > .ipe-rung > span:first-child { animation: none; }
}