/* ===========================================================================
   jp-icons.css — the animated travel icon family
   ===========================================================================
   ONE FAMILY, ONE GRAMMAR. Every icon is a 24x24 stroke drawing at
   stroke-width 1.6 with round caps and joins, inheriting `currentColor` — which
   is what makes light and dark mode automatic rather than two sets of assets.

   WHY SELF-HOSTED SVG AND NOT LORDICON / LOTTIE
   Lordicon, LottieFiles and IconScout are licensed, account-based libraries;
   their assets cannot be vendored here without a licence, and lottie-web costs
   ~250KB before a single icon renders. This whole family is a few KB, makes no
   external request, and needs no account. jp-icons.js keeps the markup behind
   one function so switching to <lord-icon> later is a change in that file only.

   THE MOTION IS ROLE-BASED, NOT PER-ICON. A part is tagged with what it should
   do — glide, rock, pop, draw, shift, spin — and the keyframes live here once.
   That is what keeps eight icons feeling like one set instead of eight
   animations that happen to share a stroke width.

   Every animation is transform/opacity only (compositor-friendly), runs once
   per trigger, and lasts 600-900ms on an ease-out curve. Nothing loops, nothing
   bounces, nothing squashes.
   =========================================================================== */

.jpi {
  display: inline-block;
  width: 1.25em;
  height: 1.25em;
  flex: none;
  line-height: 0;
  color: inherit;
}
.jpi svg {
  display: block;
  width: 100%;
  height: 100%;
  /* Parts translate a couple of px past the box mid-animation; without this
     they are clipped and the motion reads as a stutter. */
  overflow: visible;
}
.jpi svg [fill="none"] { fill: none; }

/* Sizes, relative. Set on the host so the icon scales with its context. */
.jpi-sm { width: 1em;    height: 1em; }
.jpi-lg { width: 1.75em; height: 1.75em; }
.jpi-xl { width: 2.5em;  height: 2.5em; }

/* --------------------------------------------------------------------------
   THE SIZE SCALE — six steps, named for the job rather than the number.

   The em sizes above scale an icon with whatever font-size it inherited, which
   is right inside a paragraph and wrong everywhere else: an icon in a 13px
   filter chip and an icon in a 15px field came out 2px apart for no reason
   anyone chose. These are absolute, and they are named for where they are used
   so a call site cannot pick "18px" without saying which 18px it means.

   Optical size, not box size. A chevron at 18px reads smaller than a bell at
   18px because it inks less of its 24-grid; the steps are close enough
   together that the difference never crosses a step.
   -------------------------------------------------------------------------- */
.jpi-nav    { width: 22px; height: 22px; }  /* primary product navigation      */
.jpi-field  { width: 19px; height: 19px; }  /* inside a search or form control */
.jpi-btn    { width: 18px; height: 18px; }  /* inside a button, beside a label */
.jpi-card   { width: 19px; height: 19px; }  /* flight and hotel result cards   */
.jpi-filter { width: 18px; height: 18px; }  /* filter and sort controls        */
.jpi-meta   { width: 16px; height: 16px; }  /* small metadata, inline with 12-13px text */

/* --------------------------------------------------------------------------
   SPACING — the gap between an icon and the word it belongs to.

   Put `jpi-row` on the element that holds both. It is a flex row with the 7px
   from the spec (the 6-8px band, middle of it) and a baseline that lines the
   drawing up with lowercase text rather than with the line box, which is what
   stops an icon sitting a pixel high next to its own label.

   `jpi-in-field` is the other case: an icon sitting INSIDE an input rather
   than beside it, where the spec asks for 10-14px of clearance from the edge.
   -------------------------------------------------------------------------- */
.jpi-row { display: inline-flex; align-items: center; gap: 7px; }
.jpi-row--tight { gap: 6px; }
.jpi-row--loose { gap: 8px; }

.jpi-in-field { position: relative; }
.jpi-in-field > .jpi {
  position: absolute; top: 50%; left: 12px; transform: translateY(-50%);
  pointer-events: none;
}
/* The control has to be told to get out of the icon's way; 12px of inset plus
   a 19px icon plus 9px of air is the 40px this reserves. */
.jpi-in-field > input,
.jpi-in-field > select { padding-left: 40px; }

/* An icon-only control still needs a hit area. 24px of drawing inside a 40px
   target is the smallest the WCAG 2.2 target-size rule accepts without
   spacing exemptions, and it costs nothing here because these sit in a row
   that is already that tall. */
.jpi-tap {
  display: inline-grid; place-items: center;
  min-width: 40px; min-height: 40px;
}

/* --------------------------------------------------------------------------
   Keyframes — the shared grammar
   -------------------------------------------------------------------------- */
@keyframes jpiGlide { 0% { transform: translate(0,0); } 45% { transform: translate(1.6px,-1.6px); } 100% { transform: translate(0,0); } }
@keyframes jpiRock  { 0%,100% { transform: rotate(0deg); } 30% { transform: rotate(-3.5deg); } 65% { transform: rotate(2deg); } }
@keyframes jpiPop   { 0% { transform: scale(.55); opacity: 0; } 60% { transform: scale(1.06); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes jpiShift { 0% { transform: translateX(0); } 50% { transform: translateX(1.8px); } 100% { transform: translateX(0); } }
@keyframes jpiSpin  { 0% { transform: rotate(0deg); } 100% { transform: rotate(32deg); } }
@keyframes jpiDraw  { 0% { stroke-dashoffset: var(--jpi-len, 24); } 100% { stroke-dashoffset: 0; } }
@keyframes jpiLift  { 0% { transform: translateY(0); } 45% { transform: translateY(-1.6px); } 100% { transform: translateY(0); } }
@keyframes jpiFadeUp{ 0% { transform: translateY(2px); opacity: .25; } 100% { transform: translateY(0); opacity: 1; } }

/* --------------------------------------------------------------------------
   Triggers

   Two, and only two: the icon has entered the viewport (once), or the pointer
   is over the icon or whatever host opted in with data-jpi-hover. Listing the
   selectors together means every part keeps identical timing on both.
   -------------------------------------------------------------------------- */
.jpi--play [data-jpi="glide"],  .jpi:hover [data-jpi="glide"],  [data-jpi-hover]:hover .jpi [data-jpi="glide"]  { animation: jpiGlide  .85s cubic-bezier(.22,1,.36,1); }
.jpi--play [data-jpi="rock"],   .jpi:hover [data-jpi="rock"],   [data-jpi-hover]:hover .jpi [data-jpi="rock"]   { animation: jpiRock   .9s  cubic-bezier(.22,1,.36,1); }
.jpi--play [data-jpi="pop"],    .jpi:hover [data-jpi="pop"],    [data-jpi-hover]:hover .jpi [data-jpi="pop"]    { animation: jpiPop    .7s  cubic-bezier(.22,1,.36,1); }
.jpi--play [data-jpi="shift"],  .jpi:hover [data-jpi="shift"],  [data-jpi-hover]:hover .jpi [data-jpi="shift"]  { animation: jpiShift  .9s  cubic-bezier(.22,1,.36,1); }
.jpi--play [data-jpi="spin"],   .jpi:hover [data-jpi="spin"],   [data-jpi-hover]:hover .jpi [data-jpi="spin"]   { animation: jpiSpin   .8s  cubic-bezier(.22,1,.36,1) alternate 2; }
.jpi--play [data-jpi="lift"],   .jpi:hover [data-jpi="lift"],   [data-jpi-hover]:hover .jpi [data-jpi="lift"]   { animation: jpiLift   .8s  cubic-bezier(.22,1,.36,1); }
.jpi--play [data-jpi="draw"],   .jpi:hover [data-jpi="draw"],   [data-jpi-hover]:hover .jpi [data-jpi="draw"]   { animation: jpiDraw   .7s  cubic-bezier(.22,1,.36,1) forwards; }

/* Sequenced parts (hotel windows lighting up, ticket perforation). The stagger
   is what stops three identical bars reading as one flicker. */
.jpi--play [data-jpi="seq"],    .jpi:hover [data-jpi="seq"],    [data-jpi-hover]:hover .jpi [data-jpi="seq"]    { animation: jpiFadeUp .5s cubic-bezier(.22,1,.36,1) both; }
[data-jpi="seq"]:nth-of-type(1) { animation-delay: .00s; }
[data-jpi="seq"]:nth-of-type(2) { animation-delay: .08s; }
[data-jpi="seq"]:nth-of-type(3) { animation-delay: .16s; }

/* A drawn stroke must start hidden, or it is visible before it draws. */
[data-jpi="draw"] { stroke-dasharray: var(--jpi-len, 24); stroke-dashoffset: var(--jpi-len, 24); }
/* ...but only while the animation can actually run. With motion reduced, or
   before scripting hydrates it, the finished state is the honest one. */
.jpi--static [data-jpi="draw"] { stroke-dashoffset: 0; }

/* --------------------------------------------------------------------------
   Rating star — solid, not stroked, because a 12px outlined star is mush.
   -------------------------------------------------------------------------- */
.jpi-star svg path { fill: currentColor; stroke: none; }
.jpi-stars { display: inline-flex; align-items: center; gap: 1px; line-height: 0; }
.jpi-stars .jpi { width: 1em; height: 1em; }
.jpi-stars .jpi-off { opacity: .28; }

/* --------------------------------------------------------------------------
   Host adjustments

   A handful of places size their icon from an inherited font-size that was
   chosen for an emoji, not a 24-grid drawing. These live here rather than in
   main.css so the V1 landing page's stylesheet stays untouched.
   -------------------------------------------------------------------------- */
/* 42px round button — an em-sized icon landed at 13px and looked lost in it. */
.swap-btn .jpi { width: 18px; height: 18px; }

/* The payment screen. Two sizes: a mark inline with "secure payment" text, and
   the outcome mark on the success and failure screens, which is a statement
   rather than a label and is sized like one. */
.jpay-ic-sm { width: 16px; height: 16px; }
.jpay-ic-lg { width: 30px; height: 30px; }

/* The results empty/failure state. Big, because it IS the screen at that
   moment -- there is nothing else on it. */
.tx-state-art { width: 38px; height: 38px; }
/* The rating rows inherit their gold from .pkg-stars .stars / .tx-stars, and
   letter-spacing meant for text glyphs would push the SVGs apart. */
.pkg-stars .stars { letter-spacing: normal; display: inline-flex; }
/* The review picker keeps its data-star spans; only the glyph inside changed. */
[data-star] { line-height: 0; }

/* --------------------------------------------------------------------------
   Accessibility

   Motion is decoration here — every icon sits beside its own text label — so
   reduced-motion removes it entirely rather than substituting a gentler
   version.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .jpi *,
  .jpi--play *,
  .jpi:hover * { animation: none !important; }
  [data-jpi="draw"] { stroke-dashoffset: 0; }
}
