/* TIL File Manager 배포 페이지 — 플러그인 패널의 다크·바이올렛 톤을 그대로 가져온 전용 테마.
   본 사이트(크림/오렌지)와 의도적으로 분리한다: 이 페이지가 소개하는 제품 자체의 색이기 때문. */

:root {
  --v-bg: #0E0D14;
  --v-bg-soft: #15141D;
  --v-surface: #1B1926;
  --v-surface-2: #232032;
  --v-border: #2E2A40;
  --v-border-soft: #262238;

  --v-primary: #8B7CF6;
  --v-primary-bright: #A78BFA;
  --v-primary-dim: #6D5FD0;
  --v-primary-soft: rgba(139, 124, 246, 0.14);

  --v-text: #EDEAF7;
  --v-text-muted: #A9A2C4;
  --v-text-faint: #7A7396;

  --v-radius-sm: 8px;
  --v-radius-md: 14px;
  --v-radius-lg: 20px;
  --v-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --v-shadow: 0 24px 60px -24px rgba(0, 0, 0, 0.75);
}

* { box-sizing: border-box; }

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scroll-behavior: smooth;
}

.plugin-body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--v-bg);
  color: var(--v-text);
  font-family: "Pretendard", "Malgun Gothic", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  line-height: 1.6;
  overflow-x: hidden;
}

/* ================= 배경 오로라 ================= */
.aurora {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.aurora-blob {
  position: absolute;
  border-radius: 50%;
  opacity: 0.5;
}

/* 보라 한 가지로 고정하지 않고, 각 블롭을 저마다 다른 주기로 hue-rotate시켜
   보라 -> 청록 -> 로즈 -> 앰버를 자연스럽게 돌게 한다(어두운 바탕은 그대로 유지). */
.aurora-blob-1 {
  width: 620px; height: 620px;
  top: -220px; left: -140px;
  background: radial-gradient(circle, rgba(139, 124, 246, 0.55) 0%, rgba(139, 124, 246, 0) 70%);
  animation: drift-1 24s ease-in-out infinite, hue-1 40s linear infinite;
}

.aurora-blob-2 {
  width: 540px; height: 540px;
  top: 12%; right: -180px;
  background: radial-gradient(circle, rgba(109, 95, 208, 0.5) 0%, rgba(109, 95, 208, 0) 70%);
  animation: drift-2 30s ease-in-out infinite, hue-2 48s linear infinite reverse;
}

.aurora-blob-3 {
  width: 700px; height: 700px;
  bottom: -300px; left: 30%;
  background: radial-gradient(circle, rgba(167, 139, 250, 0.34) 0%, rgba(167, 139, 250, 0) 70%);
  animation: drift-3 36s ease-in-out infinite, hue-3 56s linear infinite;
}

@keyframes hue-1 {
  0%   { filter: blur(90px) hue-rotate(0deg); }
  50%  { filter: blur(90px) hue-rotate(170deg); }
  100% { filter: blur(90px) hue-rotate(360deg); }
}
@keyframes hue-2 {
  0%   { filter: blur(90px) hue-rotate(60deg); }
  50%  { filter: blur(90px) hue-rotate(230deg); }
  100% { filter: blur(90px) hue-rotate(420deg); }
}
@keyframes hue-3 {
  0%   { filter: blur(90px) hue-rotate(-40deg); }
  50%  { filter: blur(90px) hue-rotate(150deg); }
  100% { filter: blur(90px) hue-rotate(320deg); }
}

/* 아주 옅은 격자 — 다크 배경이 밋밋해지지 않게 질감만 준다 */
.aurora-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.028) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse 90% 60% at 50% 0%, #000 30%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 90% 60% at 50% 0%, #000 30%, transparent 78%);
}

@keyframes drift-1 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(70px, 60px, 0) scale(1.12); }
}
@keyframes drift-2 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); }
  50%      { transform: translate3d(-80px, 50px, 0) scale(0.94); }
}
@keyframes drift-3 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(50px, -70px, 0) scale(1.1); }
}

/* ================= 헤더 ================= */
.pg-header {
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  max-width: 1180px;
  margin: 0 auto;
  padding: 22px 28px;
}

.pg-back {
  color: var(--v-text-muted);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  transition: color 0.16s var(--v-ease);
}

.pg-back:hover,
.pg-back:focus-visible {
  color: var(--v-primary-bright);
  outline: none;
}

.pg-header-right { display: flex; align-items: center; gap: 10px; }

/* 언어 드롭다운 (다크 버전) */
.lang-menu { position: relative; display: flex; align-items: center; }

.btn-lang {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border: none;
  border-radius: 999px;
  background: none;
  color: var(--v-text-muted);
  cursor: pointer;
  transition: color 0.16s var(--v-ease), background-color 0.16s var(--v-ease);
}

.btn-lang:hover,
.btn-lang:focus-visible {
  color: var(--v-primary-bright);
  background: var(--v-surface-2);
  outline: none;
}

.lang-dropdown {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 132px;
  padding: 6px;
  border-radius: var(--v-radius-md);
  background: var(--v-surface);
  border: 1px solid var(--v-border);
  box-shadow: var(--v-shadow);
  z-index: 60;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 0.16s var(--v-ease), transform 0.16s var(--v-ease), visibility 0s linear 0.16s;
}

.lang-menu.is-open .lang-dropdown {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
  transition-delay: 0s;
}

.lang-option {
  border: none;
  background: none;
  text-align: left;
  padding: 9px 12px;
  border-radius: var(--v-radius-sm);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--v-text);
  cursor: pointer;
  transition: background-color 0.16s var(--v-ease);
}

.lang-option:hover,
.lang-option:focus-visible { background: var(--v-surface-2); outline: none; }
.lang-option.is-active { color: var(--v-primary-bright); background: var(--v-primary-soft); }

/* ================= 본문 ================= */
.pg-main {
  position: relative;
  z-index: 5;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 28px 96px;
}

/* ---- 히어로 ---- */
.pg-hero {
  display: grid;
  grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
  align-items: center;
  gap: 40px;
  min-height: calc(100vh - 190px);
  min-height: calc(100dvh - 190px);
  padding: 24px 0 72px;
}

.pg-badge {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--v-primary-soft);
  border: 1px solid rgba(139, 124, 246, 0.3);
  color: var(--v-primary-bright);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.pg-title {
  margin: 18px 0 0;
  font-size: clamp(2.4rem, 5.4vw, 3.7rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.08;
  text-wrap: balance;
  background: linear-gradient(120deg, #FFFFFF 8%, var(--v-primary-bright) 62%, var(--v-primary) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.pg-tagline {
  margin: 16px 0 0;
  font-size: 1.02rem;
  color: var(--v-text-muted);
  text-wrap: pretty;
}

.pg-downloads {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

.pg-dl {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 14px 22px;
  border-radius: 999px;
  font-size: 0.92rem;
  font-weight: 700;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition-property: transform, box-shadow, background-color, border-color, color;
  transition-duration: 180ms;
  transition-timing-function: var(--v-ease);
}

.pg-dl-primary {
  background: linear-gradient(135deg, var(--v-primary) 0%, var(--v-primary-dim) 100%);
  color: #fff;
  border: 1px solid transparent;
  box-shadow: 0 12px 30px -12px rgba(139, 124, 246, 0.8);
}

.pg-dl-primary:hover,
.pg-dl-primary:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 18px 40px -12px rgba(139, 124, 246, 0.95);
  outline: none;
}

.pg-dl-secondary {
  background: var(--v-surface-2);
  color: var(--v-text);
  border: 1px solid var(--v-border);
}

.pg-dl-secondary:hover,
.pg-dl-secondary:focus-visible {
  transform: translateY(-2px);
  border-color: var(--v-primary);
  color: var(--v-primary-bright);
  outline: none;
}

.pg-dl:active { transform: translateY(0); }

/* ================= 떠다니는 패널 (TIL File Manager 실물 재현) ================= */
.pg-stage {
  position: relative;
  min-height: 560px;
  perspective: 1600px;
}

/* ---- 슬롯: 위치·앞뒤 교차·등장을 담당한다. 안쪽 .tfm은 계속 자기 자리에서만 부유해서
   두 애니메이션이 같은 transform을 두고 싸우지 않는다. ---- */
.mock-slot {
  position: absolute;
  cursor: pointer;
  transform-style: preserve-3d;
  --enter-y: 34px;
  --enter-blur: 8px;
  --rest-scale: 1;
  --rest-bright: 1;
  opacity: 0;
  transform: translate3d(0, var(--enter-y), 0) scale(var(--rest-scale));
  filter: blur(var(--enter-blur)) brightness(var(--rest-bright));
  transition-property: opacity, transform, filter;
  transition-duration: 560ms;
  transition-timing-function: var(--v-ease);
}

.mock-slot.is-in { opacity: 1; --enter-y: 0px; --enter-blur: 0px; }

/* 정지 상태 — 아래 교차 키프레임의 100% 값과 정확히 같아야 애니메이션이 끝난 뒤 튀지 않는다.
   ★ 앞 패널은 반드시 scale(1)이다. 확대해두면 브라우저가 레이어를 1배로 래스터한 뒤 GPU로
   늘려서 글자가 뭉갠다 — 정작 사용자가 읽는 건 앞 패널이라 여기가 제일 선명해야 한다.
   깊이감은 뒤 패널을 줄이고 어둡게 하는 쪽으로만 만든다. */
.mock-slot.is-front { z-index: 3; --rest-scale: 1; --rest-bright: 1; }
.mock-slot.is-back  { z-index: 1; --rest-scale: 0.945; --rest-bright: 0.74; }

/* 두 패널의 폭·위치는 "어느 쪽이 앞이든 뒤 패널의 일부가 반드시 드러나도록" 잡혀 있다.
   앞으로 나온 패널은 1.045배로 커지므로, 겹침이 과하면 뒤 패널을 통째로 덮어 클릭할 곳이
   사라진다(실제로 그렇게 만들었다가 되돌린 적 있음). 좌측 띠와 하단 띠를 항상 남긴다. */
/* --arc-dir: 이 패널이 교차할 때 빠져나가는 세로 방향(-1 위 / +1 아래).
   각자 상대의 반대쪽으로 빠져야 서로를 뚫고 지나가는 것처럼 보이지 않는다.
   위쪽에 있는 그리드 패널은 위로, 아래쪽에 있는 홈 패널은 아래로 빠진다. */
.mock-slot-grid { width: 86%; max-width: 495px; top: 0; right: 0; --arc-dir: -1; }
.mock-slot-home { width: 68%; max-width: 360px; bottom: 0; left: 0; --arc-dir: 1; }

/* 테두리(포커스 링 포함)는 두지 않는다 — 패널 자체가 커지고 밝아지는 것으로 상태를 알린다 */
.mock-slot:focus,
.mock-slot:focus-visible { outline: none; }

/* 뒤에 있는 패널만 "누르면 올라온다"는 신호를 준다 */
.mock-slot.is-back:hover { --rest-bright: 0.88; }
.mock-slot.is-front { cursor: default; }

/* ---- 교차 모션 ----
   각 패널은 자기 --arc-dir 방향(위 패널은 위, 아래 패널은 아래)으로 빠져나갔다가 제자리로
   돌아온다. 둘이 서로 반대쪽으로 벌어지므로 상대를 뚫고 지나가는 구간이 생기지 않는다.

   타이밍은 linear로 두고 궤적 자체를 사인 곡선(sin πt)으로 10% 간격까지 찍었다 —
   가감속을 타이밍 함수에 맡기면 시작·끝이 뻣뻣하게 튀는데, 값을 촘촘히 깔면
   프레임이 고르게 이어져 등속으로 미끄러지는 느낌이 난다.
   z-index는 두 패널이 가장 크게 벌어진 50% 지점에서 한 번만 교차한다. */
.mock-slot.flip-to-front { animation: slot-to-front 700ms linear both; }
.mock-slot.flip-to-back  { animation: slot-to-back  700ms linear both; }

/* 진폭은 px로 고정한다(%는 패널 높이에 비례해 큰 패널이 헤더까지 튀어 올랐다).
   앞으로 오는 쪽 95px + 뒤로 가는 쪽 80px = 교차 순간 175px 벌어진다.
   밝기는 앞당겨 갈라놓는다 — 50%에서 둘 다 0.87로 같으면 z가 바뀌는 순간이
   그대로 눈에 띄어 관통처럼 보였다. 이제 그 시점에 0.98 대 0.79로 명확히 다르다. */
@keyframes slot-to-front {
  0%   { z-index: 1; transform: translate3d(0, 0, 0) scale(0.9450) rotateZ(0deg); filter: brightness(0.740); }
  10%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 29.4px), 43px)  scale(0.9465) rotateZ(calc(var(--arc-dir) * -0.62deg)); filter: brightness(0.800); }
  20%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 55.9px), 82px)  scale(0.9507) rotateZ(calc(var(--arc-dir) * -1.18deg)); filter: brightness(0.860); }
  30%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 76.9px), 113px) scale(0.9569) rotateZ(calc(var(--arc-dir) * -1.62deg)); filter: brightness(0.910); }
  40%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 90.3px), 133px) scale(0.9644) rotateZ(calc(var(--arc-dir) * -1.90deg)); filter: brightness(0.950); }
  50%  { z-index: 4; transform: translate3d(0, calc(var(--arc-dir) * 95px), 140px)   scale(0.9725) rotateZ(calc(var(--arc-dir) * -2.00deg)); filter: brightness(0.980); }
  60%  { z-index: 4; transform: translate3d(0, calc(var(--arc-dir) * 90.3px), 133px) scale(0.9806) rotateZ(calc(var(--arc-dir) * -1.90deg)); filter: brightness(0.992); }
  70%  { z-index: 4; transform: translate3d(0, calc(var(--arc-dir) * 76.9px), 113px) scale(0.9881) rotateZ(calc(var(--arc-dir) * -1.62deg)); filter: brightness(0.998); }
  80%  { z-index: 4; transform: translate3d(0, calc(var(--arc-dir) * 55.9px), 82px)  scale(0.9943) rotateZ(calc(var(--arc-dir) * -1.18deg)); filter: brightness(1); }
  90%  { z-index: 4; transform: translate3d(0, calc(var(--arc-dir) * 29.4px), 43px)  scale(0.9985) rotateZ(calc(var(--arc-dir) * -0.62deg)); filter: brightness(1); }
  100% { z-index: 4; transform: translate3d(0, 0, 0) scale(1.0000) rotateZ(0deg); filter: brightness(1); }
}

@keyframes slot-to-back {
  0%   { z-index: 3; transform: translate3d(0, 0, 0) scale(1.0000) rotateZ(0deg); filter: brightness(1); }
  10%  { z-index: 3; transform: translate3d(0, calc(var(--arc-dir) * 24.7px), -37px)  scale(0.9985) rotateZ(calc(var(--arc-dir) * 0.49deg)); filter: brightness(0.950); }
  20%  { z-index: 3; transform: translate3d(0, calc(var(--arc-dir) * 47.0px), -71px)  scale(0.9943) rotateZ(calc(var(--arc-dir) * 0.94deg)); filter: brightness(0.900); }
  30%  { z-index: 3; transform: translate3d(0, calc(var(--arc-dir) * 64.7px), -97px)  scale(0.9881) rotateZ(calc(var(--arc-dir) * 1.29deg)); filter: brightness(0.860); }
  40%  { z-index: 3; transform: translate3d(0, calc(var(--arc-dir) * 76.1px), -114px) scale(0.9806) rotateZ(calc(var(--arc-dir) * 1.52deg)); filter: brightness(0.820); }
  50%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 80px), -120px)   scale(0.9725) rotateZ(calc(var(--arc-dir) * 1.60deg)); filter: brightness(0.790); }
  60%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 76.1px), -114px) scale(0.9644) rotateZ(calc(var(--arc-dir) * 1.52deg)); filter: brightness(0.770); }
  70%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 64.7px), -97px)  scale(0.9569) rotateZ(calc(var(--arc-dir) * 1.29deg)); filter: brightness(0.755); }
  80%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 47.0px), -71px)  scale(0.9507) rotateZ(calc(var(--arc-dir) * 0.94deg)); filter: brightness(0.747); }
  90%  { z-index: 1; transform: translate3d(0, calc(var(--arc-dir) * 24.7px), -37px)  scale(0.9465) rotateZ(calc(var(--arc-dir) * 0.49deg)); filter: brightness(0.742); }
  100% { z-index: 1; transform: translate3d(0, 0, 0) scale(0.9450) rotateZ(0deg); filter: brightness(0.740); }
}

/* ================= 패널 본체 — TIL File Manager 디자인 토큰 그대로 =================
   원본: TIL File Manager/client/css/style.css */
.tfm {
  --tfm-bg: #1e1e1e;
  --tfm-bg-elevated: #262626;
  --tfm-bg-card: #272727;
  --tfm-bg-card-hover: #323232;
  --tfm-bg-card-playing: #3a2f57;
  --tfm-border: rgba(255, 255, 255, 0.08);
  --tfm-border-strong: rgba(255, 255, 255, 0.16);
  --tfm-text: #e9e9ea;
  --tfm-text-muted: #9a9a9d;
  --tfm-text-faint: #6c6c6f;
  --tfm-accent: #8b7cf6;
  --tfm-accent-strong: #a596ff;
  --tfm-accent-soft: rgba(139, 124, 246, 0.16);
  --tfm-favorite: #f5c542;
  --tfm-radius-thumb: 5px;
  --tfm-radius-card: 10px;
  --tfm-control-h: 25px;

  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  border-radius: var(--v-radius-md);
  background: var(--tfm-bg);
  border: 1px solid var(--tfm-border-strong);
  box-shadow: var(--v-shadow);
  overflow: hidden;
  color: var(--tfm-text);
  font-family: "Segoe UI", -apple-system, sans-serif;
  /* 9.5px는 한글이 뭉개져 흐릿하게 보였다 — 실제 패널과 같은 비율감을 유지하면서
     읽히는 하한선까지 올린다. will-change는 두지 않는다(레이어를 1배로 고정 래스터해
     확대·회전 시 글자가 뭉갠다 — 부유 애니메이션 정도는 없어도 충분히 매끄럽다). */
  font-size: 11px;
  line-height: 1.4;
  /* 포인터 시차용 — JS가 --px/--py를 채운다 */
  --px: 0px;
  --py: 0px;
}

/* 상시 부유 모션 — 회전 기울기(-1.8deg/1.4deg)는 패널의 기본 스큐이고, 애니메이션은
   그 값을 중심으로 위치·각도를 오간다. .mock-slot(바깥, 앞뒤 교차 담당)과 별개 레이어인
   .tfm(안쪽)에서만 돈다 — 그래서 뒤로 넘어간 뒤에도 자기 궤도를 멈추지 않고 계속 돈다.
   주기·경로·시작 지연을 서로 다르게 둬서 두 패널이 한 몸처럼 안 보이게 한다. */
.float-a { animation: float-a 12s ease-in-out infinite; }
.float-b { animation: float-b 15.5s ease-in-out infinite 0.7s; }

@keyframes float-a {
  0%   { transform: translate3d(0, 0, 0) rotate(-1.8deg); }
  22%  { transform: translate3d(-4px, -10px, 0) rotate(-2.7deg); }
  48%  { transform: translate3d(3px, -15px, 0) rotate(-1.0deg); }
  74%  { transform: translate3d(5px, -6px, 0) rotate(-2.3deg); }
  100% { transform: translate3d(0, 0, 0) rotate(-1.8deg); }
}

@keyframes float-b {
  0%   { transform: translate3d(0, 0, 0) rotate(1.4deg); }
  30%  { transform: translate3d(6px, 9px, 0) rotate(2.4deg); }
  58%  { transform: translate3d(-4px, 13px, 0) rotate(0.5deg); }
  83%  { transform: translate3d(-6px, 4px, 0) rotate(2.0deg); }
  100% { transform: translate3d(0, 0, 0) rotate(1.4deg); }
}

/* ---- 타이틀바 ---- */
.tfm-titlebar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 9px;
  background: #171717;
  border-bottom: 1px solid var(--tfm-border);
  flex-shrink: 0;
}
.tfm-titlebar span {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: #3a3a3d;
}

/* ---- 헤더 ---- */
.tfm-header {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 8px;
  padding: 7px 9px;
  background: var(--tfm-bg-elevated);
  border-bottom: 1px solid var(--tfm-border);
  flex-shrink: 0;
}

.tfm-btn-icon {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: var(--tfm-control-h);
  padding: 0 8px;
  background: transparent;
  border: 1px solid var(--tfm-border-strong);
  border-radius: 5px;
  color: var(--tfm-text);
  font-family: inherit;
  font-size: 11px;
  cursor: pointer;
  white-space: nowrap;
  transition-property: background-color, border-color, transform;
  transition-duration: 120ms;
  transition-timing-function: ease-out;
}

.tfm-btn-icon:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--tfm-accent);
}
.tfm-btn-icon:active { transform: scale(0.96); }

.tfm-breadcrumb {
  display: flex;
  align-items: center;
  gap: 3px;
  min-width: 0;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
}

.tfm-crumb {
  color: var(--tfm-text-muted);
  padding: 2px 4px;
  border-radius: 3px;
  cursor: pointer;
  transition-property: color, background-color;
  transition-duration: 100ms;
}
.tfm-crumb:hover { color: var(--tfm-accent-strong); background: rgba(255, 255, 255, 0.05); }
.tfm-crumb.current { color: var(--tfm-text); cursor: default; }
.tfm-crumb.current:hover { background: none; color: var(--tfm-text); }
.tfm-crumb-sep { color: var(--tfm-text-faint); flex-shrink: 0; }

/* ---- 툴바 ---- */
.tfm-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 9px;
  padding: 7px 9px;
  background: var(--tfm-bg-elevated);
  border-bottom: 1px solid var(--tfm-border);
  flex-shrink: 0;
}

.tfm-tool-group {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 5px;
  color: var(--tfm-text-muted);
}

.tfm-tool-label { font-size: 10.5px; white-space: nowrap; }

.tfm-select {
  position: relative;
  height: var(--tfm-control-h);
  display: inline-flex;
  align-items: center;
  background: var(--tfm-bg);
  color: var(--tfm-text);
  border: 1px solid var(--tfm-border-strong);
  border-radius: 5px;
  padding: 0 17px 0 8px;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 120ms ease-out;
}
.tfm-select:hover { border-color: var(--tfm-accent); }
.tfm-select::after {
  content: "";
  position: absolute;
  right: 5px; top: 50%;
  width: 4px; height: 4px;
  border-right: 1.2px solid var(--tfm-text-muted);
  border-bottom: 1.2px solid var(--tfm-text-muted);
  transform: translateY(-70%) rotate(45deg);
}

/* 슬라이더 — 원본의 --fill 그라디언트 트랙 방식 그대로 */
.tfm-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 54px;
  height: var(--tfm-control-h);
  background: transparent;
  cursor: pointer;
}
.tfm-slider::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(to right,
    var(--tfm-accent) 0%, var(--tfm-accent) var(--fill, 50%),
    var(--tfm-border-strong) var(--fill, 50%), var(--tfm-border-strong) 100%);
}
.tfm-slider::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(to right,
    var(--tfm-accent) 0%, var(--tfm-accent) var(--fill, 50%),
    var(--tfm-border-strong) var(--fill, 50%), var(--tfm-border-strong) 100%);
}
.tfm-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 11px; height: 11px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--tfm-accent-strong);
  border: 1.5px solid var(--tfm-bg-elevated);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  transition: transform 100ms ease-out;
}
.tfm-slider::-moz-range-thumb {
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--tfm-accent-strong);
  border: 1.5px solid var(--tfm-bg-elevated);
}
.tfm-slider:active::-webkit-slider-thumb { transform: scale(1.15); }

.tfm-fav-group { margin-left: auto; }

.tfm-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: var(--tfm-control-h);
  color: var(--tfm-text-muted);
  font-size: 10.5px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.tfm-checkbox:hover { color: var(--tfm-text); }
.tfm-checkbox input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.tfm-checkbox-box {
  position: relative;
  width: 13px; height: 13px;
  flex-shrink: 0;
  border: 1px solid var(--tfm-border-strong);
  border-radius: 3px;
  background: var(--tfm-bg);
  transition-property: background-color, border-color;
  transition-duration: 120ms;
}
.tfm-checkbox:hover .tfm-checkbox-box { border-color: var(--tfm-accent); }
.tfm-checkbox input:checked + .tfm-checkbox-box {
  background: var(--tfm-accent);
  border-color: var(--tfm-accent);
}
.tfm-checkbox-box::after {
  content: "";
  position: absolute;
  left: 3.5px; top: 0.5px;
  width: 3px; height: 6.5px;
  border: solid #17131f;
  border-width: 0 1.6px 1.6px 0;
  transform: rotate(45deg) scale(0);
  transition: transform 120ms ease-out;
}
.tfm-checkbox input:checked + .tfm-checkbox-box::after { transform: rotate(45deg) scale(1); }

.tfm-lang-btn { font-variant-numeric: tabular-nums; font-weight: 600; }
.tfm-lang-right { margin-left: auto; }

/* ---- 드롭다운 (원본 .dropdown-menu 이식) ---- */
.tfm-menu { position: relative; display: inline-flex; align-items: center; }
.tfm-menu-right { margin-left: auto; }

.tfm-select[data-menu] {
  border: 1px solid var(--tfm-border-strong);
  font-family: inherit;
  font-size: 11px;
}

.tfm-dropdown {
  position: absolute;
  top: calc(100% + 5px);
  left: 0;
  min-width: 118px;
  padding: 4px;
  background: var(--tfm-bg-elevated);
  border: 1px solid var(--tfm-border-strong);
  border-radius: 7px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  z-index: 20;
  opacity: 0;
  transform: translateY(-4px) scale(0.98);
  transform-origin: top left;
  pointer-events: none;
  transition-property: opacity, transform;
  transition-duration: 130ms;
  transition-timing-function: ease-out;
}

.tfm-menu-right .tfm-dropdown {
  left: auto;
  right: 0;
  transform-origin: top right;
  min-width: 126px;
}

.tfm-menu.is-open .tfm-dropdown {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.tfm-dropdown-item {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  height: 26px;
  padding: 0 7px;
  background: transparent;
  border: none;
  border-radius: 5px;
  color: var(--tfm-text);
  font-family: inherit;
  font-size: 11px;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 100ms;
}

.tfm-dropdown-item:hover {
  background: var(--tfm-accent-soft);
  color: var(--tfm-accent-strong);
}

.tfm-dropdown-item.is-active { color: var(--tfm-accent-strong); }

/* ---- 그리드 ---- */
.tfm-grid {
  flex: 1;
  padding: 10px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  align-content: start;
}

.tfm-grid-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 150px;
}

.tfm-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 5px;
  border-radius: var(--tfm-radius-card);
  border: 1px solid transparent;
  position: relative;
  cursor: pointer;
  transition-property: background-color, border-color, transform;
  transition-duration: 120ms;
  transition-timing-function: ease-out;
}
.tfm-card:hover { background: var(--tfm-bg-card-hover); border-color: var(--tfm-border-strong); }
.tfm-card.playing { background: var(--tfm-bg-card-playing); border-color: var(--tfm-accent); }

.tfm-thumb {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--tfm-radius-thumb);
  background: var(--tfm-bg-card);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 파형 — 원본 canvas(rgba(165,150,255,.85), 1px 간격, 중앙 기준 대칭)를 막대로 재현 */
.tfm-wave {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
  width: 100%;
  height: 100%;
  padding: 0 2px;
}
.tfm-wave i {
  flex: 1 1 auto;
  min-width: 1px;
  background: rgba(165, 150, 255, 0.85);
  border-radius: 0.5px;
}

.tfm-wave-progress {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0%;
  background: rgba(255, 255, 255, 0.14);
  border-right: 1px solid var(--tfm-accent-strong);
  pointer-events: none;
  transition: width 60ms linear;
}

.tfm-eq {
  position: absolute;
  left: 5px; top: 5px;
  display: flex;
  align-items: flex-end;
  gap: 1.5px;
  height: 9px;
  opacity: 0;
  transition: opacity 120ms;
}
.tfm-card.playing .tfm-eq { opacity: 1; }
.tfm-eq i {
  width: 2px;
  background: var(--tfm-accent-strong);
  border-radius: 1px;
  animation: tfm-eq 0.9s ease-in-out infinite;
}
.tfm-eq i:nth-child(1) { height: 40%; animation-delay: 0ms; }
.tfm-eq i:nth-child(2) { height: 90%; animation-delay: 150ms; }
.tfm-eq i:nth-child(3) { height: 60%; animation-delay: 300ms; }

/* ---- 즐겨찾기 별 (원본 .fav-btn 이식 — 평소 숨었다가 카드 hover 시 뜬다)
   원본은 좌상단에 둔다: 우상단의 가져오기/제거 버튼과 자리를 겹치지 않게 하려는
   의도적 배치라 그대로 따른다(원본 주석: "misaimed click can't hit the wrong one"). ---- */
.tfm-fav-btn {
  position: absolute;
  left: 5px; top: 5px;
  z-index: 2;
  width: 20px; height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: rgba(0, 0, 0, 0.55);
  border: none;
  border-radius: 50%;
  color: var(--tfm-text);
  cursor: pointer;
  opacity: 0;
  transform: translateY(-2px);
  transition-property: opacity, transform, background-color, color;
  transition-duration: 130ms;
  transition-timing-function: ease-out;
}

.tfm-card:hover .tfm-fav-btn { opacity: 1; transform: translateY(0); }
.tfm-fav-btn:hover { background: rgba(0, 0, 0, 0.75); color: var(--tfm-favorite); }
.tfm-fav-btn:active { transform: scale(0.9); }

/* 켜둔 별은 hover가 아니어도 계속 보인다 */
.tfm-fav-btn.is-on {
  opacity: 1;
  transform: translateY(0);
  color: var(--tfm-favorite);
}
.tfm-fav-btn.is-on svg { fill: currentColor; }

@keyframes tfm-eq {
  0%, 100% { transform: scaleY(0.4); }
  50%      { transform: scaleY(1); }
}

.tfm-name {
  font-size: 10.5px;
  color: var(--tfm-text);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.tfm-meta { font-size: 9.5px; color: var(--tfm-text-faint); font-variant-numeric: tabular-nums; }

/* ---- 빈 상태 ---- */
.tfm-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: var(--tfm-text-faint);
  text-align: center;
}
.tfm-empty p { margin: 0; font-size: 11px; }

.tfm-btn-primary {
  height: 27px;
  padding: 0 13px;
  background: var(--tfm-accent);
  color: #17131f;
  border: none;
  border-radius: 5px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition-property: background-color, transform;
  transition-duration: 120ms;
}
.tfm-btn-primary:hover { background: var(--tfm-accent-strong); }
.tfm-btn-primary:active { transform: scale(0.96); }

/* ---- 상태바 ---- */
.tfm-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 5px 9px;
  background: var(--tfm-bg-elevated);
  border-top: 1px solid var(--tfm-border);
  color: var(--tfm-text-faint);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.tfm-now-playing {
  display: none;
  align-items: center;
  gap: 4px;
  color: var(--tfm-accent-strong);
  min-width: 0;
}
.tfm-now-playing.is-on { display: flex; }
.tfm-now-playing-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 150px;
}

/* ---- 조작은 앞으로 나온 패널에서만 ----
   뒤 패널에서는 내부 컨트롤이 클릭을 먹지 않아야 '앞으로 꺼내기'가 항상 우선한다. */
.mock-slot.is-back .tfm { pointer-events: none; }
.mock-slot.is-back .tfm * { pointer-events: none; }

/* ================= 등장 모션 ================= */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  filter: blur(5px);
}

.reveal.is-in {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  transition-property: opacity, transform, filter;
  transition-duration: 620ms;
  transition-timing-function: var(--v-ease);
}

/* ================= 반응형 ================= */
@media (max-width: 940px) {
  .pg-hero {
    grid-template-columns: 1fr;
    min-height: auto;
    padding-bottom: 40px;
  }
  .pg-stage {
    min-height: 400px;
    margin-top: 20px;
  }
  .mock-slot-grid { max-width: 452px; }
  .mock-slot-home { max-width: 320px; }
}

@media (max-width: 620px) {
  .pg-header { padding: 18px 18px; }
  .pg-main { padding: 0 18px 64px; }
  .pg-downloads { flex-direction: column; align-items: stretch; }
  .pg-dl { justify-content: center; }
  .pg-stage { min-height: 340px; }
  .tfm { font-size: 8.5px; }
  .tfm-grid { grid-template-columns: repeat(3, 1fr); gap: 7px; padding: 7px; }
  .mock-slot-grid { width: 92%; max-width: 100%; }
  .mock-slot-home { width: 66%; max-width: 232px; }
  /* 좁은 화면에선 뒤 패널 우측 항목이 잘려 단어가 끊겨 보인다 — 통째로 뺀다 */
  .tfm-fav-group,
  .tfm-breadcrumb { display: none; }
}

/* ================= 접근성 ================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .aurora-blob,
  .float-a,
  .float-b,
  .tfm-eq i {
    animation: none !important;
  }
  .reveal {
    opacity: 1;
    transform: none;
    filter: none;
  }
  .reveal.is-in { transition: none; }
  .mock-slot {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
  /* 교차 자체는 유지하되 궤적 없이 즉시 자리만 바뀌게 한다 */
  .mock-slot.flip-to-front,
  .mock-slot.flip-to-back { animation: none !important; }
  .pg-dl:hover { transform: none; }
}
