/* ==========================================================================
   Kami Shop · FX Layer
   react-bits 语义的原生实现（零依赖，无 React / 无 motion / 无 gsap）
   --------------------------------------------------------------------------
   对照关系（react-bits → 本文件）：
     BlurText        → .fx-blur   （逐词模糊上浮入场）
     SplitText       → .fx-split  （逐字旋转入场）
     GradientText    → .fx-grad   （渐变文字流动）
     ShinyText       → .fx-shiny  （高光扫过）
     CountUp         → [data-count]（JS 数字滚动，无 CSS）
     ClickSpark      → .fx-spark  （点击溅射环，JS 生成）
     GlareHover      → .fx-glare  （悬停斜向高光）
     Magnet          → [data-magnet]（JS 位移吸附）
     LogoLoop        → .fx-loop   （无缝滚动带）
     AnimatedContent → .fx-reveal （滚动入场，带 --d 延迟）
   ========================================================================== */

:root {
  --fx-ease-out: cubic-bezier(.16, 1, .3, 1);
  --fx-ease-soft: cubic-bezier(.22, .61, .36, 1);
  --fx-glow: 0 0 0 1px rgba(99, 102, 241, .18), 0 18px 40px -18px rgba(49, 46, 129, .45);
  --fx-sheen: linear-gradient(115deg, transparent 20%, rgba(255, 255, 255, .75) 45%, transparent 70%);
}

/* --------------------------------------------------------------- BlurText */
.fx-blur {
  display: block;
}

.fx-blur .fx-w {
  display: inline-block;
  white-space: pre;
  opacity: 0;
  filter: blur(10px);
  transform: translateY(.42em);
  animation: fx-blur-in 720ms var(--fx-ease-out) forwards;
  animation-delay: calc(var(--d, 0ms) + var(--i, 0) * 62ms);
}

.fx-blur.is-in .fx-w,
.fx-blur.fx-done .fx-w {
  animation-name: fx-blur-in;
}

@keyframes fx-blur-in {
  to {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}

/* -------------------------------------------------------------- SplitText */
.fx-split .fx-c {
  display: inline-block;
  opacity: 0;
  transform: translateY(.5em) rotate(10deg) scale(.92);
  transform-origin: 50% 90%;
  animation: fx-char-in 620ms var(--fx-ease-out) forwards;
  animation-delay: calc(var(--d, 0ms) + var(--i, 0) * 34ms);
}

@keyframes fx-char-in {
  to {
    opacity: 1;
    transform: translateY(0) rotate(0) scale(1);
  }
}

/* ----------------------------------------------------------- GradientText */
.fx-grad {
  background: linear-gradient(96deg, #6366F1 0%, #8B5CF6 24%, #16A34A 48%, #0EA5E9 70%, #6366F1 100%);
  background-size: 280% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: fx-grad-shift 9s linear infinite;
}

@keyframes fx-grad-shift {
  to {
    background-position: 280% 0;
  }
}

/* -------------------------------------------------------------- ShinyText */
/* 说明：纯 CSS 无法“遮罩到自身文字形状”，这里用同语义的高光扫带（band sweep）
   实现 ShinyText 的观感；元素需 overflow:hidden + 圆角由自身承担。 */
.fx-shiny {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: inherit;
  overflow: hidden;
  border-radius: inherit;
  isolation: isolate;
}

.fx-shiny::after {
  content: "";
  position: absolute;
  top: -80%;
  left: -40%;
  width: 34%;
  height: 260%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .9), transparent);
  transform: rotate(18deg) translateX(-120%);
  animation: fx-shiny-sweep 3.8s var(--fx-ease-soft) infinite;
  mix-blend-mode: overlay;
  pointer-events: none;
}

@keyframes fx-shiny-sweep {
  0% {
    transform: rotate(18deg) translateX(-120%);
  }
  55%,
  100% {
    transform: rotate(18deg) translateX(560%);
  }
}

/* 渐变文字不能继承 text-shadow，否则透明字会露出阴影 */
.hero h1 .fx-grad {
  text-shadow: none;
  /* 深底上换成高亮渐变，避免与 Indigo 背景糊在一起 */
  background-image: linear-gradient(96deg, #FFFFFF 0%, #C7D2FE 20%, #86EFAC 44%, #67E8F9 66%, #FFFFFF 100%);
  background-size: 280% 100%;
}

/* 单行淡入（配合 GradientText 用，不带逐块切分） */
.fx-fade {
  display: inline-block;
  opacity: 0;
  transform: translateY(.3em);
  animation: fx-blur-in 820ms var(--fx-ease-out) forwards;
  animation-delay: var(--d, 300ms);
}

/* -------------------------------------------------------- AnimatedContent */
.fx-reveal {
  opacity: 0;
  transform: translateY(22px) scale(.985);
  transition:
    opacity 640ms var(--fx-ease-soft),
    transform 640ms var(--fx-ease-soft);
  transition-delay: calc(var(--d, 0ms) + var(--i, 0) * 70ms);
  will-change: opacity, transform;
}

.fx-reveal.is-in {
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------------------ GlareHover */
.fx-glare {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.fx-glare::before {
  content: "";
  position: absolute;
  top: -120%;
  left: -60%;
  width: 45%;
  height: 340%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .62), transparent);
  transform: rotate(22deg) translateX(-140%);
  transition: transform 780ms var(--fx-ease-out);
  pointer-events: none;
  z-index: 2;
}

.fx-glare:hover::before,
.fx-glare:focus-visible::before {
  transform: rotate(22deg) translateX(420%);
}

/* -------------------------------------------------------------- ClickSpark */
.fx-spark {
  position: fixed;
  width: 8px;
  height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  pointer-events: none;
  z-index: 9998;
  background: currentColor;
  animation: fx-spark-fly 560ms var(--fx-ease-out) forwards;
}

@keyframes fx-spark-fly {
  0% {
    opacity: .95;
    transform: translate(0, 0) scale(1);
  }
  100% {
    opacity: 0;
    transform: translate(var(--tx), var(--ty)) scale(.2);
  }
}

.fx-ring {
  position: fixed;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  border: 2px solid currentColor;
  pointer-events: none;
  z-index: 9997;
  animation: fx-ring-out 520ms var(--fx-ease-out) forwards;
}

@keyframes fx-ring-out {
  0% {
    opacity: .8;
    transform: scale(.4);
  }
  100% {
    opacity: 0;
    transform: scale(4.2);
  }
}

/* ---------------------------------------------------------------- LogoLoop */
.fx-loop {
  display: flex;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.fx-loop-track {
  display: flex;
  gap: 10px;
  flex: 0 0 auto;
  min-width: 100%;
  padding-right: 10px;
  animation: fx-loop-slide var(--fx-loop-dur, 38s) linear infinite;
}

.fx-loop:hover .fx-loop-track {
  animation-play-state: paused;
}

@keyframes fx-loop-slide {
  to {
    transform: translateX(-100%);
  }
}

.fx-loop .fx-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border: 2px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--primary-ink);
  white-space: nowrap;
}

.fx-loop .fx-chip b {
  color: var(--cta-dark);
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- Magnet */
[data-magnet] {
  transition: transform 260ms var(--fx-ease-out);
  will-change: transform;
}

/* =========================================================================
   缩略图（商品卡片 / 分类卡片 / 列表行 / 热门位）
   ========================================================================= */

.thumb {
  position: relative;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 2px solid var(--border);
  border-radius: 12px;
  background:
    linear-gradient(135deg, #EEF2FF, #E0E7FF);
  color: var(--primary);
}

.thumb img {
  width: 100%;
  height: 100%;
  /* 原站缩略图大量是白底商品图，用 cover 会把主体裁掉一半；
     contain 保留完整图形，配合白色底不会露出色块 */
  object-fit: contain;
  display: block;
  transition: transform 620ms var(--fx-ease-out), filter 300ms ease;
}

/* 有图时用白底，与白底商品图无缝；无图时才用渐变兜底底 */
.thumb:not(.is-fallback) {
  background: #fff;
  box-shadow: inset 0 0 0 1px rgba(199, 210, 254, .7);
}

.thumb .thumb-fallback {
  display: none;
  place-items: center;
  width: 100%;
  height: 100%;
}

.thumb .thumb-fallback .icon {
  width: 46%;
  height: 46%;
  stroke-width: 1.7;
}

.thumb.is-fallback img {
  display: none;
}

.thumb.is-fallback .thumb-fallback {
  display: grid;
}

/* 分类大卡：缩略图铺满上半区 */
.cat-card .thumb {
  width: 100%;
  height: 104px;
  border-radius: 11px;
  border-color: var(--border-strong);
}

.cat-card:hover .thumb img {
  transform: scale(1.06);
}

/* 商品列表行：46px 小图 —— 小尺寸下 contain 会留下大片空白，
   改用 cover 让它读成一个色块，辨识度更高 */
.sub-item .thumb {
  width: 46px;
  height: 46px;
  border-radius: 10px;
}
.sub-item .thumb img { object-fit: cover; }

/* 热门位：叠在卡片顶层的角标图 */
.cat-card .thumb.is-hot {
  height: 92px;
}

/* 图片上的渐变遮罩：只给铺满裁切的 hot 位用，避免白底商品图发灰 */
.thumb.is-hot::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 56%, rgba(49, 46, 129, .16));
  pointer-events: none;
}
.thumb.is-hot img { object-fit: cover; }

/* =========================================================================
   前台局部增强（不改原有布局语义）
   ========================================================================= */

.hero h1 .fx-grad {
  display: inline-block;
}

.hero-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 18px 0 0;
}

.hero-stat {
  min-width: 104px;
  padding: 9px 14px;
  border: 2px solid rgba(255, 255, 255, .38);
  border-radius: 12px;
  background: rgba(255, 255, 255, .12);
  backdrop-filter: blur(6px);
  color: #fff;
}

.hero-stat b {
  display: block;
  font-family: var(--font-display);
  font-size: 19px;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.hero-stat span {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  opacity: .82;
}

.hero-loop {
  margin: 20px 0 0;
}

.hero-loop .fx-chip {
  border-color: rgba(255, 255, 255, .35);
  background: rgba(255, 255, 255, .14);
  color: #fff;
  backdrop-filter: blur(6px);
}

.hero-loop .fx-chip b {
  color: #BBF7D0;
}

/* 卡片入场：由 fx.js 打 is-in */
.cat-card,
.sub-item,
.hot-card {
  --d: 0ms;
}

/* 数字滚动期间避免抖动 */
[data-count] {
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  .fx-blur .fx-w,
  .fx-split .fx-c {
    animation: none !important;
    opacity: 1 !important;
    filter: none !important;
    transform: none !important;
  }

  .fx-grad {
    animation: none !important;
    background-position: 0 0;
  }

  .fx-shiny::after {
    display: none;
  }

  .fx-reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .fx-loop-track {
    animation: none !important;
    flex-wrap: wrap;
  }

  .fx-spark,
  .fx-ring {
    display: none !important;
  }

  .fx-glare::before {
    transition: none !important;
  }

  .thumb img {
    transition: none !important;
  }
}

@media (max-width: 640px) {
  .cat-card .thumb {
    height: 88px;
  }

  .hero-stat {
    min-width: 88px;
    padding: 7px 11px;
  }

  .hero-stat b {
    font-size: 16px;
  }
}
