/* ============ BLOCKLIST 开屏 Loader · 一次性（不循环）· 无粒子 ============ */
#loader {
  position: fixed; inset: 0;
  z-index: 9999;
  background:
    radial-gradient(900px 600px at 50% 20%, rgba(180,180,200,0.08) 0%, transparent 70%),
    #070708;
  display: grid;
  place-items: center;
  overflow: hidden;
  transition: opacity 820ms cubic-bezier(0.2, 0.8, 0.2, 1),
              visibility 820ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
#loader::before {
  /* 纯CSS颗粒噪点（无canvas粒子，不重复动画）*/
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  opacity: 0.08;
  mix-blend-mode: overlay;
  background-image:
    radial-gradient(rgba(255,255,255,0.95) 1px, transparent 1px),
    radial-gradient(rgba(255,255,255,0.55) 1px, transparent 1px);
  background-size: 3px 3px, 7px 7px;
  background-position: 0 0, 1px 2px;
}
#loader.hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.loader-inner {
  position: relative;
  width: min(480px, calc(100vw - 48px));
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  padding: 40px 20px 34px;
  border-radius: 28px;
  border: 1px solid rgba(255,255,255,0.08);
  background: linear-gradient(180deg, rgba(255,255,255,0.025) 0%, rgba(255,255,255,0) 100%);
}

/* 4 个方块组成的 "像素"标记 —— 一次性到位+微旋转 */
.loader-mark {
  position: relative;
  width: 60px;
  height: 60px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 6px;
  transform-origin: 50% 50%;
  animation:
    markIn 620ms cubic-bezier(0.2, 0.8, 0.2, 1) both,
    markTurn 1500ms cubic-bezier(0.2, 0.8, 0.2, 1) 620ms forwards;   /* 只转一次 */
}
@keyframes markIn {
  0%   { transform: scale(0.4); opacity: 0; filter: blur(8px); }
  60%  { transform: scale(1.08); opacity: 1; filter: blur(0); }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes markTurn {
  0%   { transform: rotate(0deg); }
  55%  { transform: rotate(-8deg) translateY(-2px); }
  100% { transform: rotate(0deg); }
}
.mark-block {
  display: block;
  border-radius: 8px;
  background: #ececec;
  opacity: 0;
  transform: translateY(12px) scale(0.8);
  animation: blockIn 460ms cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
.mark-b1 { animation-delay: 90ms;  background: #f5f5f7; }
.mark-b2 { animation-delay: 180ms; background: #dcdce0; }
.mark-b3 { animation-delay: 260ms; background: #cfcfd4; }
.mark-b4 { animation-delay: 340ms; background: #bdbdc4; }
@keyframes blockIn {
  0%   { opacity: 0; transform: translateY(12px) scale(0.7); }
  60%  { opacity: 1; transform: translateY(-2px) scale(1.05); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* 文字：字母逐字淡入 */
.loader-wordmark {
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-size: 30px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #ececed;
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.loader-wordmark span {
  display: inline-block;
  opacity: 0;
  transform: translateY(8px);
  animation: letterIn 520ms cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
.loader-wordmark .dot { color: #7d7d82; margin: 0 6px; }
.loader-wordmark span:nth-child(1)  { animation-delay: 680ms; }
.loader-wordmark span:nth-child(2)  { animation-delay: 720ms; }
.loader-wordmark span:nth-child(3)  { animation-delay: 760ms; }
.loader-wordmark span:nth-child(4)  { animation-delay: 800ms; }
.loader-wordmark span:nth-child(5)  { animation-delay: 840ms; }
.loader-wordmark span:nth-child(6)  { animation-delay: 880ms; }  /* 点 */
.loader-wordmark span:nth-child(7)  { animation-delay: 920ms; }
.loader-wordmark span:nth-child(8)  { animation-delay: 960ms; }
.loader-wordmark span:nth-child(9)  { animation-delay: 1000ms; }
.loader-wordmark span:nth-child(10) { animation-delay: 1040ms; }
@keyframes letterIn {
  0%   { opacity: 0; transform: translateY(8px); filter: blur(6px); }
  100% { opacity: 1; transform: translateY(0);   filter: blur(0); }
}

/* 副标题 */
.loader-sub {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.18em;
  color: #7d7d82;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(4px);
  animation: subIn 680ms cubic-bezier(0.2, 0.8, 0.2, 1) 1080ms forwards;
}
@keyframes subIn {
  to { opacity: 1; transform: translateY(0); }
}

/* 进度条（扫光仅1次，不循环）*/
.loader-bar {
  width: 100%;
  max-width: 320px;
  height: 3px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  overflow: hidden;
  position: relative;
  opacity: 0;
  animation: fadeIn 420ms ease 1180ms forwards;
}
.loader-bar-fill {
  position: absolute; inset: 0;
  width: 0%;
  background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.85) 50%, rgba(255,255,255,0) 100%);
  transform-origin: left;
  animation: barFill 1500ms cubic-bezier(0.65, 0, 0.2, 1) 1260ms forwards;
}
@keyframes barFill {
  0%   { width: 0%;   transform: translateX(-12%); }
  60%  { width: 78%; }
  100% { width: 100%; transform: translateX(0); }
}
@keyframes fadeIn { to { opacity: 1; } }
