/* Shared motion layer for travx.me. Loaded after styles.css.
   Behaviour lives in motion.js; every effect degrades to a static site
   without it. See design/TRAVX.ME-ANIMATION-STRATEGY.md. */

:root{
  --motion-fast:150ms;
  --motion-normal:250ms;
  --motion-slow:450ms;
  --motion-ambient:850ms;
  --ease-standard:cubic-bezier(.2,.8,.2,1);
  --ease-spring:cubic-bezier(.34,1.4,.64,1);
}

/* --- Compact sticky header on scroll (mobile) ----------------------------- */
.navigation,.name,.name span,.nav-links,.nav-links a{transition:font-size var(--motion-normal) ease,line-height var(--motion-normal) ease,gap var(--motion-normal) ease,padding var(--motion-normal) ease,margin var(--motion-normal) ease,min-height var(--motion-normal) ease}
@media(max-width:760px){
  .site-header.compact .navigation{min-height:58px}
  .site-header.compact .nav-links{gap:16px;font-size:12px}
  .site-header.compact .nav-links a{padding:6px 0}
  .site-header.compact .nav-links a:last-child{font-size:inherit}
}
@media(max-width:420px){
  .site-header.compact .navigation{flex-wrap:nowrap;padding:8px 0;gap:12px;min-height:0}
  .site-header.compact .nav-links{width:auto;justify-content:flex-end;gap:14px;font-size:11px}
  .site-header.compact .nav-links a:last-child{font-size:inherit}
  .site-header.compact .name{font-size:14px}
  .site-header.compact .name span{font-size:10px;margin-top:2px}
}

/* --- Read-progress hairline on the header edge ---------------------------- */
/* Sits on top of the header's existing 1px border, so it costs no layout and
   reads as that line filling in rather than as a new element. */
.site-header{--progress:0}
.scroll-progress{position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--violet);transform:scaleX(var(--progress));transform-origin:left center;pointer-events:none;will-change:transform}

/* --- Live status dot ------------------------------------------------------- */
[data-motion-status]{display:inline-flex;align-items:center;gap:8px}
[data-motion-status]:before{content:'';width:7px;height:7px;border-radius:50%;background:var(--crimson);flex:0 0 auto}
[data-motion-status].is-live:before{animation:status-pulse 2.4s ease-in-out infinite}
@keyframes status-pulse{0%,100%{opacity:1}50%{opacity:.35}}

/* --- Springing shared nav underline (pointer, desktop) -------------------- */
.nav-links{position:relative}
.nav-underline{position:absolute;left:0;bottom:0;height:1px;background:var(--ink);transform-origin:left center;opacity:0;pointer-events:none;transition:transform var(--motion-normal) var(--ease-spring),opacity var(--motion-fast) ease,background-color var(--motion-normal) ease}
.nav-underline.is-visible{opacity:1}
.nav-links.has-underline a,
.nav-links.has-underline a:hover,
.nav-links.has-underline a[aria-current=page]{border-bottom-color:transparent}

/* --- Title micro-glitch --------------------------------------------------- */
/* The glitch arrives instantly and leaves on a cross-fade: the ghost fades out
   while the real character fades back in, so the exit does not pop a second
   time. Both durations must match FADE in motion.js. */
.glitch-slot{position:relative;transition:color 110ms linear}
.glitch-slot[data-glitch-hidden]{color:transparent;transition:none}
.glitch-ghost{position:absolute;left:0;top:0;white-space:pre;color:inherit;pointer-events:none;will-change:transform,opacity;transition:opacity 110ms linear}
.glitch-ghost[data-leaving]{opacity:0}

/* --- Magnetic cards / counter-motion depth -------------------------------- */
[data-motion=magnetic]{transition:transform var(--motion-fast) ease-out,background-color var(--motion-normal) ease,border-color var(--motion-normal) ease}
[data-motion=magnetic] > h3,
[data-motion=magnetic] > p{transition:transform var(--motion-fast) ease-out}
[data-motion=magnetic].is-magnetic{will-change:transform}
@media(hover:hover) and (pointer:fine){
  .capability-list article:hover,
  .character-grid article:hover{background:rgba(94,74,227,.045)}
  .chapter:hover{border-top-color:#7A7E86}
}

/* --- Oversized outlined capability numbers -------------------------------- */
@supports ((-webkit-text-stroke:1px currentColor) or (text-stroke:1px currentColor)){
  .capability-list article > span{
    font-size:25px;font-weight:750;line-height:1;padding-top:2px;letter-spacing:-.02em;
    -webkit-text-fill-color:transparent;-webkit-text-stroke:1px var(--violet);
    transition:transform var(--motion-normal) var(--ease-standard),-webkit-text-fill-color var(--motion-normal) ease,opacity var(--motion-normal) ease;
    opacity:.75;
  }
  .capability-list article:hover > span{-webkit-text-fill-color:var(--violet);transform:translateY(-1px) scale(1.06);opacity:1}
}

/* --- Ambient blurred glow behind the connection section ------------------- */
.connection{position:relative;isolation:isolate;overflow:hidden}
.connection > .wrap{position:relative;z-index:1}
.ambient-glow{position:absolute;z-index:0;left:50%;top:46%;width:min(760px,86vw);aspect-ratio:1.55;border-radius:50%;pointer-events:none;background:var(--glow-color,var(--ion));filter:blur(90px);opacity:0;transform:translate(-50%,-50%);transition:background-color var(--motion-ambient) ease,opacity var(--motion-ambient) ease,transform var(--motion-ambient) ease}
.ambient-glow.is-lit{opacity:.13}
.ambient-glow.is-focused{opacity:.26}

/* --- Personal mark: proximity glow ---------------------------------------- */
/* The mark is a pseudo-element, so JS cannot touch it directly -- it sets
   --mark-glow (0..1) on the host and every property below is derived from it.
   Changing a custom property still fires the transitions on the properties
   that read it, which is what smooths the pointer tracking.
   --mark-rgb mirrors --crimson; drop-shadow needs channels, not a hex. */
.puzzle-art{--mark-glow:0;--mark-rgb:200 29 37}
.puzzle-art:after{
  opacity:calc(.72 + .28*var(--mark-glow));
  transform:translate(-50%,-50%) scale(calc(1 + .05*var(--mark-glow)));
  /* Two shadows: a tight one that reads as the ink itself getting hotter, and
     a wider one kept faint so it does not smear across the light puzzle piece. */
  filter:drop-shadow(0 0 calc(4px*var(--mark-glow)) rgb(var(--mark-rgb)/calc(.55*var(--mark-glow))))
         drop-shadow(0 0 calc(12px*var(--mark-glow)) rgb(var(--mark-rgb)/calc(.3*var(--mark-glow))));
  transition:opacity 220ms ease,transform 220ms ease,filter 220ms ease;
}

/* --- Interactive surfaces: borders, tints, arrows -------------------------- */
.connection-note{transition:transform var(--motion-normal) var(--ease-standard),border-left-width var(--motion-normal) ease,padding-left var(--motion-normal) ease}
.connection-note:hover{transform:translateX(3px)}
.case,.chapter{transition:border-top-color var(--motion-normal) ease}
.outcome{transition:transform var(--motion-normal) var(--ease-standard),border-left-color var(--motion-normal) ease}
.outcome:hover{transform:translateX(3px)}
.case:hover{border-top-color:var(--violet)}
.case h3,.chapter h3,.capability-list h3,.character-grid h3{transition:color var(--motion-normal) ease}
.case:hover h3{color:var(--violet)}
.text-link span,.project-arrow{transition:transform var(--motion-fast) ease}
.text-link:active span{transform:translate(6px,-6px)}
.text-link,.email-link{transition:color var(--motion-normal) ease,transform var(--motion-fast) ease}
.text-link:active,.email-link:active{transform:scale(.985)}
.jump-links a{transition:color var(--motion-normal) ease,border-color var(--motion-normal) ease}

/* --- Image zoom / brightness lift ----------------------------------------- */
.puzzle-art img,.chart img{transition:transform var(--motion-slow) var(--ease-standard),filter var(--motion-slow) ease}
.puzzle-art:hover img{transform:scale(1.025);filter:grayscale(1) contrast(1.06) brightness(1.24)}
.chart:hover img{transform:scale(1.03);filter:brightness(1.05)}

/* --- Precision on the remaining lists (borders, not movement) -------------- */
.trait-list div,.interest-list li,.practice-flow span,.direction-steps div,.story-timeline li{transition:border-color var(--motion-normal) ease,color var(--motion-normal) ease}
.trait-list div:hover,.story-timeline li:hover{border-color:var(--violet)}
.interest-list li:hover{border-color:var(--paper)}
.practice-flow span:hover{color:var(--ink)}
.jump-links a span{display:inline-block;transition:transform var(--motion-fast) ease}
.jump-links a:hover span{transform:translateY(3px)}
.jump-links a:active span{transform:translateY(5px)}

/* --- Reduced motion -------------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  .navigation,.name,.name span,.nav-links,.nav-links a,
  [data-motion=magnetic],[data-motion=magnetic] > h3,[data-motion=magnetic] > p,
  .connection-note,.outcome,.puzzle-art img,.chart img,.nav-underline,
  .glitch-slot,.glitch-ghost,.puzzle-art:after,
  .text-link,.text-link span,.email-link,.capability-list article > span{transition:none}
  .puzzle-art:hover img,.chart:hover img,.connection-note:hover,.outcome:hover,.text-link:active,.email-link:active{transform:none}
  [data-motion-status].is-live:before{animation:none}
  .scroll-progress{transition:none}
  .puzzle-art{--mark-glow:0}
  .jump-links a span,.trait-list div,.interest-list li,.practice-flow span,.story-timeline li{transition:none}
  .jump-links a:hover span,.jump-links a:active span{transform:none}
  .ambient-glow{display:none}
}
