/*
 * Appesto — scroll interaction layer.
 * Loaded after style.css. Adds scroll reveals, reading progress, active TOC,
 * hero parallax and card hover polish without touching the base design tokens.
 *
 * Contract:
 *  - Nothing here hides content unless <html> carries .ap-js (set by an inline
 *    snippet in header.php, and removed again if scroll.js never boots).
 *  - Every hidden state is opacity + transform only, so there is no reflow.
 */

/* ------------------------------------------------------------
   1. Reveal primitives
   ------------------------------------------------------------ */
:root{
  --ap-reveal-dist:44px;
  --ap-reveal-dist-x:46px;
  --ap-reveal-time:1150ms;
  /* Expo-out: most of the travel happens early, so the movement stays
     clearly readable instead of finishing before the eye catches it. */
  --ap-reveal-ease:cubic-bezier(.16,1,.3,1);
  --ap-reveal-delay:0ms;
}

html.ap-js .ap-reveal{
  opacity:0;
  transform:translate3d(0,var(--ap-reveal-dist),0);
  transition:
    opacity var(--ap-reveal-time) var(--ap-reveal-ease) var(--ap-reveal-delay),
    transform var(--ap-reveal-time) var(--ap-reveal-ease) var(--ap-reveal-delay);
  will-change:opacity,transform;
}
html.ap-js .ap-reveal--down{transform:translate3d(0,calc(var(--ap-reveal-dist) * -.7),0)}
html.ap-js .ap-reveal--left{transform:translate3d(calc(var(--ap-reveal-dist-x) * -1),0,0)}
html.ap-js .ap-reveal--right{transform:translate3d(var(--ap-reveal-dist-x),0,0)}
html.ap-js .ap-reveal--scale{transform:translate3d(0,20px,0) scale(.94)}
html.ap-js .ap-reveal--fade{transform:none}
html.ap-js .ap-reveal--cta{transform:translate3d(0,32px,0) scale(.96)}

html.ap-js .ap-reveal.ap-reveal-in{
  opacity:1;
  transform:none;
  will-change:auto;
}

/* Reveal targets are horizontal-overflow safe: transforms only move within
   an already-clipped flow, and side movement is disabled on narrow screens. */
@media (max-width:700px){
  :root{--ap-reveal-dist:22px;--ap-reveal-dist-x:0px;--ap-reveal-time:950ms}
  html.ap-js .ap-reveal--scale{transform:translate3d(0,14px,0) scale(.96)}
}

/* ------------------------------------------------------------
   2. Reading progress bar (single posts / long-form pages)
   ------------------------------------------------------------ */
.ap-progress{
  position:fixed;top:0;left:0;right:0;height:3px;z-index:70;
  pointer-events:none;background:transparent;
}
.ap-progress__bar{
  height:100%;width:100%;transform:scaleX(0);transform-origin:0 50%;
  background:linear-gradient(90deg,var(--ap-accent,var(--ap-lime)),var(--ap-accent-2,var(--ap-cyan)));
  box-shadow:0 0 10px -2px rgba(var(--ap-accent-rgb,183,255,42),.6);
}

/* ------------------------------------------------------------
   3. Active table of contents
   The theme ships no TOC of its own — these rules only decorate an existing
   TOC (theme markup or a TOC plugin) once JS marks the current section.
   ------------------------------------------------------------ */
.ap-toc-link{transition:color .2s ease,border-color .2s ease,background-color .2s ease}
.ap-toc-link.ap-toc-active{
  color:var(--ap-accent,var(--ap-lime));
  font-weight:700;
}
/* Layout is deliberately untouched: the marker is an inset bar drawn with
   box-shadow, so an active item never shifts the existing TOC. */
.ap-toc-list .ap-toc-link.ap-toc-active{
  box-shadow:inset 2px 0 0 var(--ap-accent,var(--ap-lime));
  background:rgba(var(--ap-accent-rgb,183,255,42),.07);
  border-radius:4px;
}

/* Sticky-header safe anchor landings (header min-height 76px + breathing room). */
.ap-article [id],
.ap-prose [id]{scroll-margin-top:var(--ap-anchor-offset,110px)}

/* ------------------------------------------------------------
   4. Hero parallax (decorative layer only)
   ------------------------------------------------------------ */
.ap-parallax{will-change:transform}
/* The 1.04 overscan only covers the few pixels the shift would otherwise
   expose inside the clipped frame; aspect ratio is untouched. */
.ap-parallax > img{transform:translate3d(0,var(--ap-parallax-y,0),0) scale(1.04)}
@media (max-width:860px){
  .ap-parallax > img{transform:none}
}

/* ------------------------------------------------------------
   5. Card hover polish (pointer devices only, existing design kept)
   ------------------------------------------------------------ */
@media (hover:hover) and (pointer:fine){
  .ap-post,.ap-card,.ap-focus__card,.ap-about__card,.ap-enquiry{
    transition:transform .22s var(--ap-reveal-ease),border-color .22s ease,background-color .22s ease,box-shadow .22s ease;
  }
  .ap-post:hover,.ap-card:hover,.ap-focus__card:hover,.ap-about__card:hover,.ap-enquiry:hover{
    transform:translate3d(0,-2px,0);
    box-shadow:0 14px 30px -22px rgba(0,0,0,.9);
  }
}

/* ------------------------------------------------------------
   6. Code blocks — copy button (only added where none exists)
   ------------------------------------------------------------ */
.ap-codewrap{position:relative}
.ap-copy{
  position:absolute;top:10px;right:10px;z-index:2;
  font-family:var(--ap-mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ap-muted);background:rgba(255,255,255,.05);
  border:1px solid var(--ap-line);border-radius:8px;padding:6px 10px;cursor:pointer;
  opacity:0;transition:opacity .2s ease,color .2s ease,border-color .2s ease;
}
.ap-codewrap:hover .ap-copy,.ap-copy:focus-visible{opacity:1}
.ap-copy:hover{color:var(--ap-accent,var(--ap-lime));border-color:rgba(var(--ap-accent-rgb,183,255,42),.5)}
.ap-copy.is-copied{color:var(--ap-accent,var(--ap-lime));opacity:1}
@media (max-width:700px){.ap-copy{opacity:1}}

/* ------------------------------------------------------------
   7. Page intro — the top block plays once on arrival
   ------------------------------------------------------------ */
html.ap-js .ap-intro-item{
  opacity:0;
  transform:translate3d(0,30px,0);
  transition:
    opacity 1100ms var(--ap-reveal-ease) var(--ap-intro-delay,0ms),
    transform 1100ms var(--ap-reveal-ease) var(--ap-intro-delay,0ms);
}
html.ap-js .ap-intro-item.ap-intro-in{opacity:1;transform:none}
@media (max-width:700px){
  html.ap-js .ap-intro-item{transform:translate3d(0,18px,0);transition-duration:950ms}
}

/* ------------------------------------------------------------
   8. Section dots — current position on the page, right edge
   ------------------------------------------------------------ */
.ap-dots{
  position:fixed;right:20px;top:50%;transform:translateY(-50%);z-index:65;
  display:none;
}
.ap-dots ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:16px}
.ap-dots__item{
  display:flex;align-items:center;justify-content:flex-end;gap:10px;
  color:var(--ap-muted);text-decoration:none;
}
.ap-dots__label{
  font-family:var(--ap-mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  white-space:nowrap;padding:5px 10px;border-radius:99px;
  background:rgba(10,13,11,.88);border:1px solid var(--ap-line);
  backdrop-filter:blur(10px);
  opacity:0;transform:translateX(8px);pointer-events:none;
  transition:opacity .22s ease,transform .22s ease;
}
.ap-dots__dot{
  width:9px;height:9px;flex:none;border-radius:99px;
  background:transparent;border:1.5px solid var(--ap-line-2);
  transition:background-color .25s ease,border-color .25s ease,height .25s var(--ap-reveal-ease),box-shadow .25s ease;
}
.ap-dots__item:hover .ap-dots__label,
.ap-dots__item:focus-visible .ap-dots__label{opacity:1;transform:translateX(0)}
.ap-dots__item:hover .ap-dots__dot{border-color:var(--ap-accent,var(--ap-lime))}
.ap-dots__item.is-active .ap-dots__dot{
  height:24px;background:var(--ap-accent,var(--ap-lime));
  border-color:var(--ap-accent,var(--ap-lime));
  box-shadow:0 0 12px -2px rgba(var(--ap-accent-rgb,183,255,42),.8);
}
/* Wide viewports only: the rail must never sit on top of the content. */
@media (min-width:1200px){
  .ap-dots{display:block}
}

/* ------------------------------------------------------------
   9. Back to top
   ------------------------------------------------------------ */
.ap-totop{
  position:fixed;right:20px;bottom:22px;z-index:66;
  width:48px;height:48px;padding:0;border-radius:99px;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  color:var(--ap-text);
  background:
    linear-gradient(rgba(10,13,11,.92),rgba(10,13,11,.92)) padding-box,
    conic-gradient(
      var(--ap-accent,var(--ap-lime)) calc(var(--ap-totop-progress,0) * 1%),
      rgba(255,255,255,.12) 0
    ) border-box;
  border:2px solid transparent;
  backdrop-filter:blur(12px);
  opacity:0;transform:translate3d(0,12px,0) scale(.9);pointer-events:none;
  transition:opacity .3s ease,transform .3s var(--ap-reveal-ease),color .2s ease;
}
.ap-totop.is-visible{opacity:1;transform:none;pointer-events:auto}
.ap-totop:hover{color:var(--ap-accent,var(--ap-lime))}
.ap-totop__icon{font-size:17px;line-height:1;display:block}
@media (max-width:700px){
  .ap-totop{width:42px;height:42px;right:14px;bottom:14px}
}

/* ------------------------------------------------------------
   10. Returning to a listing — marks the card the reader opened
   ------------------------------------------------------------ */
.ap-return-focus{
  animation:ap-return-focus 2.4s var(--ap-reveal-ease) 1;
}
@keyframes ap-return-focus{
  0%,70%{
    box-shadow:0 0 0 2px rgba(var(--ap-accent-rgb,183,255,42),.55),
      0 0 26px -6px rgba(var(--ap-accent-rgb,183,255,42),.45);
  }
  100%{box-shadow:0 0 0 0 rgba(var(--ap-accent-rgb,183,255,42),0)}
}

/* ------------------------------------------------------------
   11. Reduced motion / no-JS safety
   ------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  html.ap-js .ap-reveal,
  html.ap-js .ap-reveal.ap-reveal-in{
    opacity:1 !important;transform:none !important;transition:none !important;
  }
  .ap-parallax > img{transform:none !important}
  .ap-post:hover,.ap-card:hover,.ap-focus__card:hover,.ap-about__card:hover,.ap-enquiry:hover{
    transform:none;box-shadow:none;
  }
  .ap-progress__bar{transition:none}
  html.ap-js .ap-intro-item,
  html.ap-js .ap-intro-item.ap-intro-in{
    opacity:1 !important;transform:none !important;transition:none !important;
  }
  .ap-dots__dot,.ap-dots__label,.ap-totop{transition:none}
  /* The marker stays, it just stops pulsing. */
  .ap-return-focus{animation:none;box-shadow:0 0 0 2px rgba(var(--ap-accent-rgb,183,255,42),.55)}
}
