/* Frontline UI layer — the finish every page shares: motion, focus, scrollbars
   and the label explanations. Loaded by every page beside its own <style>.

   Colours stay in each page's :root block (see PROJECT_CONVENTIONS.md); this
   file only reads them. Everything that moves is behind html.ui-motion, which
   frontline-ui.js sets only when the reader has not asked for reduced motion
   and the page is not being photographed by an automated browser. Nothing here
   hides content on its own: an element is only ever invisible while an
   animation that ends in it being visible is running. */

/* ---- scrollbars and selection -------------------------------------------- */

/* Thin, dark scrollbars inside panels (tapes, day rail, dropdowns). Windows draws
   a light grey bar by default, which is the brightest thing on a black page. */
* { scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .16) transparent; }
html { scrollbar-width: auto; scrollbar-color: #2A4068 #0A1628; }
::selection { background: rgba(61, 220, 151, .3); color: #fff; }

/* ---- focus --------------------------------------------------------------- */

/* A visible ring for keyboard focus only; a mouse click draws nothing. Inputs
   keep the border their page gives them on focus. */
:focus-visible { outline: 2px solid rgba(61, 220, 151, .6); outline-offset: 2px; }
input:focus-visible, textarea:focus-visible, select:focus-visible { outline: none; }

/* ---- interaction --------------------------------------------------------- */

/* Every control eases between its states instead of snapping. Only paint and
   transform properties: nothing here can move a layout. */
a, button, summary, label, [role="button"], [role="tab"], .chip, .btn, .fl-chip {
  transition: color .18s ease, background-color .18s ease, border-color .18s ease,
    box-shadow .18s ease, opacity .18s ease, transform .18s cubic-bezier(.2, .8, .2, 1);
}
/* A press you can feel: the control settles a pixel under the pointer. */
button:not(:disabled):active, .btn:active, a.fl-cta:active { transform: translateY(1px); }
button:disabled { cursor: not-allowed; }

/* ---- label explanations -------------------------------------------------- */

/* A label with a dotted underline explains itself on hover or focus. The text
   comes from its data-tip attribute; frontline-ui.js draws the bubble. */
[data-tip] {
  cursor: help;
  text-decoration: underline dotted rgba(255, 255, 255, .3);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
[data-tip]:is(button, a, [role="button"]) { cursor: pointer; }
.ui-tip {
  position: fixed;
  z-index: 1000;
  left: 0;
  top: 0;
  max-width: min(300px, calc(100vw - 16px));
  padding: 9px 12px;
  border-radius: 8px;
  background: #1A2E50;
  border: 1px solid rgba(255, 255, 255, .12);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .05) inset, 0 14px 34px -10px rgba(0, 0, 0, .85);
  color: #EEF2F8;
  font: 500 12px/1.55 'Plus Jakarta Sans', system-ui, sans-serif;
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .14s ease, transform .14s ease;
}
.ui-tip[data-below] { transform: translateY(-4px); }
.ui-tip.ui-on { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .ui-tip { transition: none; } }

/* ---- motion -------------------------------------------------------------- */

/* Keyframes give a start and no end, so each element animates back to however
   its own styles leave it — a debrief drawn at half opacity rises to half
   opacity, not to full and then a jump. `backwards` holds the start through
   the stagger delay and lets go completely once the animation ends. */
/* Movement uses the separate `translate` and `scale` properties rather than
   `transform`, so it composes with any transform an element already carries —
   a dropdown centred with translateX(-50%) stays centred while it pops. */
@keyframes ui-page { from { opacity: 0; } }
@keyframes ui-rise { from { opacity: 0; translate: 0 14px; } }
@keyframes ui-open { from { opacity: 0; translate: 0 8px; } }
@keyframes ui-pop { from { opacity: 0; translate: 0 -4px; scale: .98; } }
@keyframes ui-row { from { opacity: 0; translate: 0 5px; } }
@keyframes ui-settle { from { opacity: 0; translate: 0 .3em; filter: blur(6px); } }
@keyframes ui-flip { from { opacity: .2; translate: 0 .22em; } }
@keyframes ui-wipe {
  from { clip-path: polygon(-6% -12%, -6% -12%, -6% 112%, -6% 112%); }
  to { clip-path: polygon(-6% -12%, 106% -12%, 106% 112%, -6% 112%); }
}
@keyframes ui-ping {
  0% { box-shadow: 0 0 0 0 rgba(61, 220, 151, .55); }
  70%, 100% { box-shadow: 0 0 0 7px rgba(61, 220, 151, 0); }
}

html.ui-motion body { animation: ui-page .34s ease-out backwards; }
html.ui-motion .ui-rise { animation: ui-rise .64s cubic-bezier(.16, 1, .3, 1) backwards; animation-delay: var(--ui-d, 0ms); }
html.ui-motion .ui-open { animation: ui-open .34s cubic-bezier(.16, 1, .3, 1) backwards; }
html.ui-motion .ui-pop { animation: ui-pop .18s cubic-bezier(.2, .8, .2, 1) backwards; }
html.ui-motion .ui-row { animation: ui-row .46s cubic-bezier(.16, 1, .3, 1) backwards; animation-delay: var(--ui-d, 0ms); }
html.ui-motion .ui-settle { animation: ui-settle .6s cubic-bezier(.16, 1, .3, 1) backwards; animation-delay: var(--ui-d, 0ms); }
html.ui-motion .ui-flip { animation: ui-flip .3s cubic-bezier(.16, 1, .3, 1); }
html.ui-motion .ui-wipe { animation: ui-wipe 1.05s cubic-bezier(.65, 0, .35, 1) backwards; animation-delay: var(--ui-d, 0ms); }
/* Waits paused at its first frame until frontline-ui.js sees it scrolled to. */
@keyframes ui-reveal { from { opacity: 0; translate: 0 24px; } }
html.ui-motion .ui-await { animation: ui-reveal .8s cubic-bezier(.16, 1, .3, 1) backwards paused; animation-delay: var(--ui-d, 0ms); }
html.ui-motion .ui-await.ui-go { animation-play-state: running; }
@media print { html.ui-motion .ui-await { animation: none; } }
/* A picture still on its way: a soft light passes over the space it will fill.
   The finished picture paints over it, and frontline-ui.js drops the class on
   load so nothing keeps animating behind it. */
@keyframes ui-shimmer { from { background-position: 150% 0; } to { background-position: -50% 0; } }
html.ui-motion .ui-shimmer {
  background-image: linear-gradient(100deg, transparent 35%, rgba(255, 255, 255, .055) 50%, transparent 65%) !important;
  background-size: 200% 100% !important;
  background-repeat: no-repeat !important;
  animation: ui-shimmer 1.5s ease-in-out infinite;
}
/* The header's SOL dot breathes while the price feed is actually delivering. */
html.ui-motion.ui-sol-live .ui-sol-dot { animation: ui-ping 2.6s cubic-bezier(.4, 0, .2, 1) infinite; }
/* The collection progress bar (frontline-progress.js) slides to each new
   reading rather than jumping; without motion it simply jumps. */
html.ui-motion [data-progress-fill] { transition: width .9s cubic-bezier(.2, .7, .2, 1), background-color .3s ease; }
