/* Skeleton loaders for the journal.
   =================================
   Every screen that fetches its content shows the shape of that content while
   it loads, in the place it will appear, so the page fills in rather than
   jumping under the person reading it.

   The palette is the app's own -- warm parchment tones, not the grey of a
   generic loading graphic -- because these appear inside a page somebody opens
   to sit quietly with. The console has its own set in admin.css; same API,
   deliberately different colour, since nothing in the admin tool should be
   mistaken for this. Keep this file in step with skeletons.js.

   Every skeleton is aria-hidden and its container carries aria-busy, so a
   screen reader hears "busy" instead of reading out a dozen empty boxes. */

.skeleton {
    background: linear-gradient(90deg, #f0e8de 25%, #e6dacd 50%, #f0e8de 75%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
    border-radius: 8px;
    height: 1.1rem;
}

@keyframes skeleton-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* A moving gradient is exactly the sort of motion that makes some people
   unwell, and the shape reads perfectly well standing still. */
@media (prefers-reduced-motion: reduce) {
    .skeleton {
        animation: none;
        background: #ece3d8;
    }
}

/* Lines of text. The widths are uneven on purpose: a stack of identical bars
   reads as a loading graphic, where ragged ones read as words about to
   arrive. */
.skeleton-line { height: 1.1rem; margin: 0.55rem 0; }
.skeleton-line.w-30 { width: 30%; }
.skeleton-line.w-45 { width: 45%; }
.skeleton-line.w-60 { width: 60%; }
.skeleton-line.w-75 { width: 75%; }
.skeleton-line.w-90 { width: 90%; }
.skeleton-line.w-100 { width: 100%; }

/* A heading, and the small meta line under one. */
.skeleton-title { height: 1.6rem; width: 55%; margin: 0.4rem 0 0.9rem; }
.skeleton-meta { height: 0.8rem; width: 35%; margin: 0.3rem 0; }

/* A whole card: an entry in the history timeline, a reflection, a prompt. */
.skeleton-card {
    height: 116px;
    width: 100%;
    margin-bottom: 1rem;
    border-radius: 14px;
}

/* The prompt panel on the journal page, which is the first thing somebody
   reads and the thing most worth holding a space for. */
.skeleton-prompt { height: 84px; width: 100%; border-radius: 12px; }

/* A track row in the soaking library, and the artwork beside it. */
.skeleton-row-item { height: 52px; width: 100%; margin-bottom: 0.6rem; border-radius: 10px; }
.skeleton-thumb { height: 56px; width: 56px; border-radius: 10px; }

/* A pill: a category chip, a status badge. */
.skeleton-pill { height: 30px; width: 96px; border-radius: 999px; display: inline-block; margin: 0 0.4rem 0.4rem 0; }

/* A form field whose value arrives by fetch. */
.skeleton-input { height: 44px; width: 100%; border-radius: 10px; }
.skeleton-text { display: inline-block; height: 1em; vertical-align: middle; }
.skeleton-ghost {
    color: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
    background: linear-gradient(90deg, #f0e8de 25%, #e6dacd 50%, #f0e8de 75%) !important;
    background-size: 200% 100% !important;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
    pointer-events: none;
    user-select: none;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}
span.skeleton-ghost, p.skeleton-ghost { border-radius: 6px; }
.skeleton-toggle { display: block; height: calc(1.2rem + 30px); width: 296px; max-width: 100%; border-radius: 24px; margin: 0 auto 1.5rem; }
.skeleton-textarea { height: 120px; width: 100%; border-radius: 10px; }


/* --- The hummingbird: waiting for something to be written -----------------
   Adapted from "Hummingbird loading icon" by marginalhours on CodePen
   (https://codepen.io/marginalhours/pen/NyNYEd), under CodePen's default MIT
   terms. Six wing paths pulse in sequence while the whole bird rises and
   settles, which reads as something alive and working rather than a machine
   turning over.

   This is the app's one loading icon, and it means "something is being
   written for you": a friend-voice response, a prompt, a reflection. It is
   not the same device as a skeleton, and the difference matters. A skeleton
   says "your data is on its way and here is the shape of it"; the bird says
   "there is nothing to show yet because it does not exist yet -- it is being
   made". Use a skeleton for a fetch, the bird for a generation.

   70x70 and centred in whatever holds it, everywhere it appears.
   Journal palette: the app's own brown, inherited by currentColor. */

.lj-loader {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 70px;
  color: var(--walnut);
}

/* The hummingbird in flight: the original loading icon's wings -- six fanned
   positions whose opacities cycle so the wing beats with soft trails -- at a
   600ms beat; the body hovering and flicking its tail every 2.3s; and, from
   the script, a turn to face the other way every 3-8s followed by a short
   glide that way. Adapted from "Hummingbird loading icon" by marginalhours on
   CodePen (https://codepen.io/marginalhours/pen/NyNYEd). */
.lj-bird-flight {
  display: inline-block;
  perspective: 400px;
  line-height: 0;
}

.lj-bird-drift {
  display: block;
  transform-style: preserve-3d;
  transition: transform 1.3s cubic-bezier(0.22, 1, 0.36, 1) 0.4s;
}

.lj-bird-turn {
  display: block;
  transform-style: preserve-3d;
  transition: transform 0.55s cubic-bezier(0.4, 0, 0.2, 1);
}

.lj-bird {
  display: block;
  width: 70px;
  height: 70px;
  overflow: visible;
  animation: lj-bird-hover 2.4s ease-in-out infinite;
}

.lj-bird .lj-body {
  fill: currentColor;
  transform-box: fill-box;
  transform-origin: 92% 6%;
  animation: lj-bird-twitch 2.3s ease-in-out infinite;
}

/* fill-opacity and the animated opacity multiply, which is how the original
   gets its soft trailing wings. */
.lj-bird .lj-wing {
  fill: currentColor;
  fill-opacity: 0.7;
  animation-duration: 0.6s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

.lj-bird .lj-wing:nth-child(1) { animation-name: lj-bird-wing-1; }
.lj-bird .lj-wing:nth-child(2) { animation-name: lj-bird-wing-2; }
.lj-bird .lj-wing:nth-child(3) { animation-name: lj-bird-wing-3; }
.lj-bird .lj-wing:nth-child(4) { animation-name: lj-bird-wing-4; }
.lj-bird .lj-wing:nth-child(5) { animation-name: lj-bird-wing-5; }
.lj-bird .lj-wing:nth-child(6) { animation-name: lj-bird-wing-6; }

/* The same bird standing in as the brand mark on the sign-in screen, where it
   is not loading anything -- so no status role, and a size of its own. */
.lj-bird-mark {
  display: flex;
  justify-content: center;
  color: var(--walnut);
  line-height: 0;
}

.lj-bird-mark .lj-bird {
  width: 80px;
  height: 80px;
}

/* Bigger, for the journal's prompt card: the bird sits in the middle of an
   otherwise empty card, so it carries the whole card on its own. */
.lj-loader.lj-loader--lg .lj-bird {
  width: 100px;
  height: 100px;
}

/* Wings beating, a body bobbing and a bird turning is a lot of motion. Still
   a hummingbird, just holding still, with the wings fanned so the shape reads. */
@media (prefers-reduced-motion: reduce) {
  .lj-bird,
  .lj-bird .lj-body,
  .lj-bird .lj-wing {
    animation: none;
  }
  .lj-bird-drift,
  .lj-bird-turn {
    transition: none;
  }
  .lj-bird .lj-wing { fill-opacity: 0.35; }
  .lj-bird .lj-wing:nth-child(2) { fill-opacity: 0.45; }
  .lj-bird .lj-wing:nth-child(3) { fill-opacity: 0.55; }
  .lj-bird .lj-wing:nth-child(4) { fill-opacity: 0.45; }
  .lj-bird .lj-wing:nth-child(5) { fill-opacity: 0.35; }
  .lj-bird .lj-wing:nth-child(6) { fill-opacity: 0.25; }
}

@keyframes lj-bird-hover {
  0%, 100% { transform: translateY(0); }
  45% { transform: translateY(6px); }
}
@keyframes lj-bird-twitch {
  0%, 91% { transform: rotate(0deg); }
  94% { transform: rotate(-6deg); }
  97% { transform: rotate(3deg); }
  100% { transform: rotate(0deg); }
}
@keyframes lj-bird-wing-1 {
  0%, 100% {
    opacity: 0;
  }
  5% {
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  20% {
    opacity: 0.4;
  }
  65% {
    opacity: 0.1;
  }
  70% {
    opacity: 1;
  }
  75% {
    opacity: 0.3;
  }
  90% {
    opacity: 0;
  }
}
@keyframes lj-bird-wing-2 {
  0%, 100% {
    opacity: 0;
  }
  10% {
    opacity: 0;
  }
  15% {
    opacity: 1;
  }
  25% {
    opacity: 0.4;
  }
  60% {
    opacity: 0.16;
  }
  65% {
    opacity: 1;
  }
  70% {
    opacity: 0.3;
  }
  85% {
    opacity: 0;
  }
}
@keyframes lj-bird-wing-3 {
  0%, 100% {
    opacity: 0;
  }
  15% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  30% {
    opacity: 0.4;
  }
  55% {
    opacity: 0.22;
  }
  60% {
    opacity: 1;
  }
  65% {
    opacity: 0.3;
  }
  80% {
    opacity: 0;
  }
}
@keyframes lj-bird-wing-4 {
  0%, 100% {
    opacity: 0;
  }
  20% {
    opacity: 0;
  }
  25% {
    opacity: 1;
  }
  35% {
    opacity: 0.4;
  }
  50% {
    opacity: 0.28;
  }
  55% {
    opacity: 1;
  }
  60% {
    opacity: 0.3;
  }
  75% {
    opacity: 0;
  }
}
@keyframes lj-bird-wing-5 {
  0%, 100% {
    opacity: 0;
  }
  25% {
    opacity: 0;
  }
  30% {
    opacity: 1;
  }
  40% {
    opacity: 0.4;
  }
  45% {
    opacity: 0.34;
  }
  50% {
    opacity: 1;
  }
  55% {
    opacity: 0.3;
  }
  70% {
    opacity: 0;
  }
}
@keyframes lj-bird-wing-6 {
  0%, 100% {
    opacity: 0;
  }
  30% {
    opacity: 0;
  }
  35% {
    opacity: 1;
  }
  45% {
    opacity: 0.4;
  }
  45% {
    opacity: 1;
  }
  50% {
    opacity: 0.3;
  }
  65% {
    opacity: 0;
  }
}
