/* =========================================================================
   animations.css
   Two families of animation, both CSS-only (no JS) unless noted:

   1. .shelf     — the "books read" shelf. Books lean, drift and glow
                   on an ambient loop, and tilt upright on hover/focus.
   2. .viz-*     — small reusable DSA visualizations dropped into blog
                   posts (array bars, stack, linked list, recursion tree).
                   Each is pure HTML+CSS so it keeps working with
                   JavaScript disabled; a couple of posts layer a small
                   JS controller on top only where a post needs a button
                   (e.g. "step forward") rather than a passive loop.
   ========================================================================= */

/* ---------------------------------------------------------------------- *
 * 1. Book shelf
 * ---------------------------------------------------------------------- */
.shelf {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  padding: 28px 20px 20px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  position: relative;
  overflow: hidden;
}
.shelf::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 14px;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--line) 15%, var(--line) 85%, transparent);
}

.book {
  --hue-shift: 0deg;
  width: 34px;
  height: 148px;
  border-radius: 2px 4px 4px 2px;
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 8px;
  color: #12161c;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  cursor: default;
  transform-origin: bottom center;
  box-shadow: inset -4px 0 6px rgba(0,0,0,0.25), 2px 4px 8px rgba(0,0,0,0.35);
  animation: book-breathe 6s ease-in-out infinite;
  animation-delay: var(--delay, 0s);
  transition: transform 0.35s ease, box-shadow 0.35s ease;
}
.book:hover, .book:focus-visible {
  transform: translateY(-10px) rotate(0deg) !important;
  box-shadow: 0 10px 18px rgba(0,0,0,0.45);
  z-index: 2;
}

/* gentle alternating lean, like books settled on a shelf */
.book:nth-child(4n+1) { transform: rotate(-2deg); }
.book:nth-child(4n+2) { transform: rotate(1.5deg); }
.book:nth-child(4n+3) { transform: rotate(-0.5deg); }
.book:nth-child(4n)   { transform: rotate(2deg); }

@keyframes book-breathe {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.08); }
}

.book__spine-title {
  transform: rotate(180deg);
  max-height: 90%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.book--reading {
  outline: 2px dashed rgba(227,179,65,0.7);
  outline-offset: 2px;
}
.book--reading::before {
  content: "reading";
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  writing-mode: horizontal-tb;
  font-size: 0.62rem;
  color: var(--accent-gold);
  font-family: var(--font-mono);
  white-space: nowrap;
}

.shelf-legend {
  display: flex;
  gap: 18px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--text-faint);
  margin-top: 12px;
  flex-wrap: wrap;
}

/* ---------------------------------------------------------------------- *
 * 2. DSA visualizations
 * ---------------------------------------------------------------------- */

/* --- array / bubble sort bars ------------------------------------------ */
.viz-bars {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 140px;
  padding: 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.viz-bars .bar {
  width: 26px;
  background: var(--accent-teal);
  border-radius: 2px 2px 0 0;
  position: relative;
  animation: bubble-pass 6s ease-in-out infinite;
}
.viz-bars .bar span {
  position: absolute;
  top: -20px;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--text-faint);
}
/* each bar gets its own keyframe offset inline via style="animation-delay" */
@keyframes bubble-pass {
  0%, 100% { transform: translateX(0); }
  10%      { background: var(--accent-gold); }
  20%      { transform: translateX(16px); background: var(--accent-gold); }
  30%      { transform: translateX(0); background: var(--accent-teal); }
}

/* --- stack (push/pop) --------------------------------------------------- */
.viz-stack {
  display: flex;
  flex-direction: column-reverse;
  gap: 6px;
  width: 160px;
  padding: 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  min-height: 180px;
}
.viz-stack .frame {
  background: var(--panel-alt);
  border: 1px solid var(--accent-violet);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  text-align: center;
  padding: 8px 6px;
  border-radius: 2px;
  animation: stack-push 5s ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}
@keyframes stack-push {
  0%   { opacity: 0; transform: translateY(12px) scale(0.9); }
  10%  { opacity: 1; transform: translateY(0) scale(1); }
  75%  { opacity: 1; transform: translateY(0) scale(1); }
  90%  { opacity: 0; transform: translateY(-8px) scale(0.9); }
  100% { opacity: 0; }
}

/* --- linked list traversal --------------------------------------------- */
.viz-linked-list {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 16px 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow-x: auto;
}
.viz-linked-list .node {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border: 1px solid var(--accent-teal);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  position: relative;
  background: var(--panel-alt);
}
.viz-linked-list .arrow {
  color: var(--text-faint);
  font-family: var(--font-mono);
}
.viz-linked-list .cursor-dot {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent-gold);
  animation: ll-travel 6s linear infinite;
}
@keyframes ll-travel {
  0%   { opacity: 0; }
  5%   { opacity: 1; }
  95%  { opacity: 1; }
  100% { opacity: 0; }
}
/* horizontal translation is applied per-instance via a wrapper transform
   using CSS variables so the same rule works for lists of any length */
.viz-linked-list--traveling .cursor-dot {
  animation-name: ll-travel-move;
}
@keyframes ll-travel-move {
  0%   { left: 23px; opacity: 1; }
  90%  { left: calc(100% - 23px); opacity: 1; }
  100% { left: calc(100% - 23px); opacity: 0; }
}

/* --- recursion tree (grows then resets) --------------------------------- */
.viz-tree {
  padding: 20px 10px 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.viz-tree ul {
  list-style: none;
  margin: 0;
  padding-left: 24px;
  border-left: 1px dashed var(--line);
}
.viz-tree > ul { padding-left: 0; border-left: none; }
.viz-tree li {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--text-dim);
  margin: 6px 0;
  position: relative;
  animation: tree-grow 6s ease-in-out infinite;
  animation-delay: var(--delay, 0s);
  transform-origin: left center;
}
@keyframes tree-grow {
  0%   { opacity: 0; transform: scale(0.85); }
  15%  { opacity: 1; transform: scale(1); color: var(--accent-gold); }
  30%  { color: var(--text-dim); }
  85%  { opacity: 1; }
  100% { opacity: 1; }
}

/* --- code diff / complexity meter --------------------------------------- */
.viz-meter {
  display: flex;
  gap: 3px;
  align-items: flex-end;
  height: 40px;
}
.viz-meter i {
  display: block;
  width: 8px;
  background: var(--line);
  border-radius: 1px;
}
.viz-meter i.on { background: var(--accent-rose); }
