[v-cloak] { display: none !important; }
html, body { background: var(--page-bg, #FFF9FA); }
body {
    font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC",
    Arial, "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
    background: var(--page-bg, #FFF9FA);
    cursor: default;
    user-select: none;
}

/* iPad/Safari：展开搜索不用原生 placeholder，用覆盖层提示，避免「占位在左、光标在右」的 WebKit 绘制 bug */
.pet-mobile-header-search-wrap {
    flex: 1 1 0%;
    min-width: 0;
    position: relative;
}
.pet-mobile-header-search-input {
    width: 100%;
    display: block;
    box-sizing: border-box;
    direction: ltr;
    unicode-bidi: isolate;
    text-align: left;
    -webkit-user-select: text;
    user-select: text;
    /* 避免 iOS 聚焦时整页缩放，减少与光标相关的布局抖动 */
    font-size: 16px;
    line-height: 1.4;
}
/* 小屏用 contenteditable 代替 input：规避 fixed+backdrop-filter 下 WebKit 绘制 input 光标错位 */
.pet-mobile-header-search-input[contenteditable="true"] {
    min-height: 2.5rem;
    white-space: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    word-break: keep-all;
    -webkit-tap-highlight-color: transparent;
}
/* 展开搜索时去掉顶栏毛玻璃，减轻 Safari 合成层与光标不同步 */
@media (max-width: 1023px) {
    .pet-header-mobile-search-active.glass {
        -webkit-backdrop-filter: none !important;
        backdrop-filter: none !important;
    }
}

/* 6 套皮肤：通过 <html data-skin="..."> 切换 */
:root[data-skin="pink"] {
    --primary: #f43f5e;        /* rose-500 */
    --primary-600: #e11d48;    /* rose-600 */
    --primary-50: #fff1f2;     /* rose-50 */
    --primary-100: #ffe4e6;    /* rose-100 */
    --primary-300: #fda4af;    /* rose-300 */
    --page-bg: #FFF9FA;
    --primary-r: 244;
    --primary-g: 63;
    --primary-b: 94;
}
:root[data-skin="purple"] {
    --primary: #a855f7;        /* purple-500 */
    --primary-600: #9333ea;    /* purple-600 */
    --primary-50: #faf5ff;     /* purple-50 */
    --primary-100: #f3e8ff;    /* purple-100 */
    --primary-300: #d8b4fe;    /* purple-300 */
    --page-bg: #FCFAFF;
    --primary-r: 168;
    --primary-g: 85;
    --primary-b: 247;
}
:root[data-skin="indigo"] {
    --primary: #6366f1;        /* indigo-500 */
    --primary-600: #4f46e5;    /* indigo-600 */
    --primary-50: #eef2ff;     /* indigo-50 */
    --primary-100: #e0e7ff;    /* indigo-100 */
    --primary-300: #a5b4fc;    /* indigo-300 */
    --page-bg: #FAFBFF;
    --primary-r: 99;
    --primary-g: 102;
    --primary-b: 241;
}
:root[data-skin="teal"] {
    --primary: #14b8a6;        /* teal-500 */
    --primary-600: #0d9488;    /* teal-600 */
    --primary-50: #f0fdfa;     /* teal-50 */
    --primary-100: #ccfbf1;    /* teal-100 */
    --primary-300: #5eead4;    /* teal-300 */
    --page-bg: #F7FFFE;
    --primary-r: 20;
    --primary-g: 184;
    --primary-b: 166;
}
:root[data-skin="orange"] {
    --primary: #f97316;        /* orange-500 */
    --primary-600: #ea580c;    /* orange-600 */
    --primary-50: #fff7ed;     /* orange-50 */
    --primary-100: #ffedd5;    /* orange-100 */
    --primary-300: #fdba74;    /* orange-300 */
    --page-bg: #FFFBF7;
    --primary-r: 249;
    --primary-g: 115;
    --primary-b: 22;
}
:root[data-skin="verdigris"] {
    /* 铜青（偏青绿，比“蓝绿 teal”更沉稳） */
    --primary: #2a9d8f;
    --primary-600: #21867a;
    --primary-50: #ecf8f7;
    --primary-100: #d0efec;
    --primary-300: #7ec4bc;
    --page-bg: #F6FFFE;
    --primary-r: 42;
    --primary-g: 157;
    --primary-b: 143;
}

/* 皮肤通用工具类（不依赖 Tailwind 生成） */
.bg-skin { background-color: var(--primary) !important; }
.text-skin { color: var(--primary) !important; }
.border-skin { border-color: var(--primary) !important; }
.border-skin-100 { border-color: var(--primary-100) !important; }
.border-skin-300 { border-color: var(--primary-300) !important; }
.shadow-skin {
    box-shadow:
        0 16px 28px -18px rgba(var(--primary-r, 244), var(--primary-g, 63), var(--primary-b, 94), 0.22),
        0 10px 16px -14px rgba(var(--primary-r, 244), var(--primary-g, 63), var(--primary-b, 94), 0.12);
}
.bg-skin-50 { background-color: var(--primary-50) !important; }
.bg-skin-100 { background-color: var(--primary-100) !important; }
.bg-skin-300 { background-color: var(--primary-300) !important; }
.hover\:bg-skin-50:hover { background-color: var(--primary-50) !important; }
.hover\:bg-skin-100:hover { background-color: var(--primary-100) !important; }
.hover\:bg-skin-600:hover { background-color: var(--primary-600) !important; }
.hover\:text-skin:hover { color: var(--primary) !important; }
.hover\:border-skin:hover { border-color: var(--primary) !important; }
.hover\:border-skin-100:hover { border-color: var(--primary-100) !important; }
.hover\:border-skin-300:hover { border-color: var(--primary-300) !important; }
.skin-page { background: linear-gradient(135deg, #fdf2f8, #eef2ff) !important; }
.bg-skin-gradient { background: linear-gradient(90deg, var(--primary-100), var(--primary)) !important; }
.glass {
    background: #FFFFFF;
    backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.5);
}
.pink-shadow {
    /* 顶栏 / 底栏：主题色扩散 + 中性底层（略淡） */
    box-shadow:
        0 3px 14px -6px rgba(15, 23, 42, 0.11),
        0 10px 26px -14px rgba(15, 23, 42, 0.06),
        0 16px 38px -20px rgba(var(--primary-r, 244), var(--primary-g, 63), var(--primary-b, 94), 0.38);
    filter: none;
}
.modal-overlay {
    background: rgba(15, 23, 42, 0.5);
    backdrop-filter: blur(4px);
}
/* 系统设置中新增行的高亮动画 */
@keyframes added-row {
    0% { background-color: rgb(209 250 229); }
    60% { background-color: rgb(209 250 229); }
    100% { background-color: transparent; }
}
.row-added-highlight {
    animation: added-row 1.4s ease-out forwards;
}
/* 成长阶段错误提示：一次高亮动画（底色、边框、阴影）后恢复静态 */
@keyframes growth-stage-hint-pulse {
    0% {
        background-color: rgb(255 228 230);
        border-color: rgb(251 113 133);
        box-shadow: 0 0 0 3px rgba(251, 113, 133, 0.35), 0 4px 14px -4px rgba(244, 63, 94, 0.25);
    }
    100% {
        background-color: rgb(255 241 242);
        border-color: rgb(254 205 211);
        box-shadow: none;
    }
}
.growth-stage-hint-error-anim {
    animation: growth-stage-hint-pulse 2s ease-out forwards;
}
/* --- 喂养：礼炮纸屑（从宠物区中心向四周喷射）--- */
.feed-confetti-burst {
    position: absolute;
    width: 8px;
    height: 8px;
    border-radius: 2px;
    pointer-events: none;
    z-index: 36;
    left: 50%;
    top: 32%;
    margin-left: -4px;
    margin-top: -4px;
    animation: feed-confetti-burst 2s cubic-bezier(0, 0, 0.2, 1) forwards;
}
@keyframes feed-confetti-burst {
    0% { transform: translate(0, 0) rotate(0deg); opacity: 1; }
    100% { transform: translate(var(--dx), var(--dy)) rotate(var(--dr)); opacity: 0; }
}
/* --- 喂养：宠物加分 Q 弹 --- */
.feed-pet-pop {
    animation: feed-pet-pop 1.1s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes feed-pet-pop {
    0%, 100% { transform: scale(1); }
    40% { transform: scale(1.22) translateY(-12px); }
    60% { transform: scale(0.92); }
}
/* --- 喂养：扣分宠物 — 底部中心为轴左右摇摆，不改变大小 --- */
.feed-pet-minus {
    transform-origin: 50% 100%;
    animation: feed-pet-minus-sway 1.4s ease-in-out;
}
@keyframes feed-pet-minus-sway {
    0%, 100% { transform: rotate(0deg); }
    12% { transform: rotate(-18deg); }
    28% { transform: rotate(16deg); }
    44% { transform: rotate(-14deg); }
    58% { transform: rotate(12deg); }
    72% { transform: rotate(-8deg); }
    86% { transform: rotate(4deg); }
}
/* --- 喂养：分值浮现（居中）--- */
.feed-float-score-plus {
    animation: feed-float-score-plus 1.45s ease-out forwards;
    color: #f97316;
    text-shadow: 0 2px 16px rgba(249, 115, 22, 0.45);
}
@keyframes feed-float-score-plus {
    0% { opacity: 0; transform: translateY(24px) scale(0.5); }
    22% { opacity: 1; transform: translateY(-14px) scale(1.25); }
    55% { opacity: 1; transform: translateY(-22px) scale(1.08); }
    100% { opacity: 0; transform: translateY(-64px) scale(1); }
}
.feed-float-score-minus {
    animation: feed-float-score-minus 1.5s cubic-bezier(0.33, 0, 0.2, 1) forwards;
    color: #334155;
    letter-spacing: -0.02em;
    text-shadow:
        0 1px 0 rgba(255, 255, 255, 0.9),
        0 3px 14px rgba(71, 85, 105, 0.35),
        0 0 24px rgba(148, 163, 184, 0.45);
}
@keyframes feed-float-score-minus {
    0% { opacity: 0; transform: translateY(-36px) scale(0.55); filter: blur(2px); }
    14% { opacity: 1; transform: translateY(4px) scale(1.18); filter: blur(0); }
    28% { opacity: 1; transform: translateY(0) scale(1.05); }
    55% { opacity: 1; transform: translateY(14px) scale(1); }
    100% { opacity: 0; transform: translateY(72px) scale(0.92); }
}
/* --- 喂养：闪烁星星（仅加分）--- */
.feed-star-pop {
    position: absolute;
    z-index: 37;
    pointer-events: none;
    animation: feed-star-spin 1.4s ease-out forwards;
    color: #fbbf24;
}
@keyframes feed-star-spin {
    0% { transform: scale(0) rotate(0deg); opacity: 0; }
    35% { opacity: 1; }
    65% { opacity: 1; transform: scale(1.35) rotate(120deg); }
    100% { transform: scale(1.5) rotate(220deg); opacity: 0; }
}
/* 喂养动效：整卡遮罩淡出（时长与 startFeedAnim 清理时间大致一致） */
@keyframes feed-scrim-fade-out {
    0% { opacity: 1; }
    18% { opacity: 1; }
    100% { opacity: 0; }
}
.feed-anim-card-scrim {
    position: absolute;
    inset: 0;
    border-radius: 1.5rem;
    pointer-events: none;
    z-index: 38;
    /* 偏亮、偏暖的雾面，避免 slate 压暗发灰 */
    background: linear-gradient(
        165deg,
        rgba(255, 255, 255, 0.42) 0%,
        rgba(255, 251, 247, 0.32) 45%,
        rgba(255, 255, 255, 0.28) 100%
    );
    animation: feed-scrim-fade-out 2.65s ease-out forwards;
}
/* 扣分：略偏冷的雾面，与加分区分 */
.feed-anim-card-scrim--minus {
    background: linear-gradient(
        195deg,
        rgba(248, 250, 252, 0.52) 0%,
        rgba(241, 245, 249, 0.38) 45%,
        rgba(226, 232, 240, 0.34) 100%
    );
}
/* ====== 升级动效 ====== */
.levelup-anim-card-scrim {
    position: absolute;
    inset: 0;
    border-radius: 1.5rem;
    pointer-events: none;
    z-index: 38;
    background:
        radial-gradient(ellipse at 50% 50%, rgba(251,191,36,0.52) 0%, rgba(245,158,11,0.30) 35%, rgba(252,211,77,0.15) 60%, rgba(255,255,255,0.04) 100%),
        linear-gradient(160deg, rgba(251,191,36,0.18) 0%, rgba(245,158,11,0.10) 50%, rgba(217,119,6,0.12) 100%);
    animation: levelup-scrim 4s ease-out forwards;
}
@keyframes levelup-scrim {
    0%   { opacity: 0; }
    10%  { opacity: 1; }
    65%  { opacity: 1; }
    100% { opacity: 0; }
}
.levelup-pet {
    animation: levelup-pet 3.4s cubic-bezier(0.34,1.56,0.64,1);
}
@keyframes levelup-pet {
    0%   { transform: scale(1); filter: brightness(1); }
    10%  { transform: scale(0.82) translateY(8px); filter: brightness(1); }
    24%  { transform: scale(1.38) translateY(-22px); filter: brightness(1.35) drop-shadow(0 0 24px rgba(251,191,36,0.7)); }
    40%  { transform: scale(1.12) translateY(-8px); filter: brightness(1.15) drop-shadow(0 0 14px rgba(251,191,36,0.4)); }
    60%  { transform: scale(1.04); filter: brightness(1.06); }
    100% { transform: scale(1); filter: brightness(1); }
}
.levelup-ring {
    position: absolute;
    left: 50%; top: 45%;
    width: 36px; height: 36px;
    margin-left: -18px; margin-top: -18px;
    border-radius: 50%;
    border: 3px solid rgba(251,191,36,0.65);
    pointer-events: none;
    z-index: 39;
    animation: levelup-ring-expand 2.6s ease-out forwards;
}
.levelup-ring-2 { animation-delay: 0.35s; border-color: rgba(245,158,11,0.5); }
.levelup-ring-3 { animation-delay: 0.7s; border-color: rgba(252,211,77,0.38); }
@keyframes levelup-ring-expand {
    0%   { transform: scale(0); opacity: 1; }
    55%  { opacity: 0.5; }
    100% { transform: scale(14); opacity: 0; }
}
.levelup-particle {
    position: absolute;
    width: 6px; height: 6px;
    border-radius: 50%;
    pointer-events: none;
    z-index: 40;
    background: radial-gradient(circle, #fbbf24, #f59e0b);
    box-shadow: 0 0 6px 2px rgba(251,191,36,0.5);
    animation: levelup-particle-rise 3.4s ease-out forwards;
    animation-delay: var(--delay, 0s);
}
@keyframes levelup-particle-rise {
    0%   { transform: translateY(0) translateX(0) scale(0); opacity: 0; }
    10%  { transform: translateY(0) translateX(0) scale(1.1); opacity: 1; }
    100% { transform: translateY(var(--dy)) translateX(var(--dx)) scale(0.2); opacity: 0; }
}
.levelup-level-text {
    animation: levelup-text-pop 4s ease-out forwards;
    color: #b45309;
    font-weight: 900;
    text-shadow:
        0 0 24px rgba(251,191,36,0.7),
        0 0 48px rgba(245,158,11,0.35),
        0 2px 10px rgba(0,0,0,0.12);
}
@keyframes levelup-text-pop {
    0%   { opacity: 0; transform: scale(0.2) rotate(-8deg); }
    15%  { opacity: 1; transform: scale(1.45) rotate(2deg); }
    26%  { transform: scale(0.95) rotate(0deg); }
    40%  { transform: scale(1.05); }
    70%  { opacity: 1; transform: scale(1); }
    100% { opacity: 0; transform: scale(0.85) translateY(-28px); }
}
.levelup-subtitle {
    animation: levelup-subtitle-pop 4s ease-out forwards;
    color: #d97706;
    font-weight: 800;
    text-shadow:
        0 0 16px rgba(251,191,36,0.6),
        0 1px 6px rgba(0,0,0,0.08);
}
@keyframes levelup-subtitle-pop {
    0%   { opacity: 0; transform: translateY(8px) scale(0.6); }
    20%  { opacity: 0; transform: translateY(8px) scale(0.6); }
    32%  { opacity: 1; transform: translateY(0) scale(1.15); }
    44%  { transform: translateY(0) scale(1); }
    70%  { opacity: 1; }
    100% { opacity: 0; transform: translateY(-18px); }
}
.levelup-sparkle {
    position: absolute;
    pointer-events: none;
    z-index: 41;
    color: #fbbf24;
    animation: levelup-sparkle-spin 2.4s ease-out forwards;
    animation-delay: var(--delay, 0s);
}
@keyframes levelup-sparkle-spin {
    0%   { transform: scale(0) rotate(0deg); opacity: 0; }
    25%  { opacity: 1; }
    55%  { opacity: 1; transform: scale(1.5) rotate(140deg); }
    100% { transform: scale(1.8) rotate(260deg); opacity: 0; }
}
/* 学生资料 · 徽章方案三：浮雕奖章内凹阴影 */
.inner-shadow-heavy {
    box-shadow: inset 0 4px 12px 0 rgba(0, 0, 0, 0.08);
}
.pet-badge-medal-radial {
    background: radial-gradient(circle at center, rgba(180, 83, 9, 0.14) 0%, transparent 68%);
}
/* ====== 养成成功庆祝动画 ====== */
.congrats-confetti {
    position: fixed;
    width: 10px; height: 10px;
    border-radius: 2px;
    z-index: 200;
    pointer-events: none;
    animation: congrats-confetti-fall var(--dur, 4s) linear infinite;
    animation-delay: var(--delay, 0s);
}
@keyframes congrats-confetti-fall {
    0%   { transform: translateY(-20px) rotate(0deg); opacity: 1; }
    85%  { opacity: 1; }
    100% { transform: translateY(calc(100vh + 40px)) rotate(var(--rot, 720deg)); opacity: 0; }
}
.congrats-star-float {
    position: fixed;
    z-index: 201;
    pointer-events: none;
    color: #fbbf24;
    animation: congrats-star-float var(--dur, 5s) ease-in-out infinite;
    animation-delay: var(--delay, 0s);
}
@keyframes congrats-star-float {
    0%, 100% { transform: translateY(0) scale(0.8) rotate(0deg); opacity: 0.3; }
    50%      { transform: translateY(-30px) scale(1.2) rotate(180deg); opacity: 1; }
}
.congrats-modal-enter {
    animation: congrats-modal-pop 0.6s cubic-bezier(0.34,1.56,0.64,1) forwards;
}
@keyframes congrats-modal-pop {
    0%   { opacity: 0; transform: scale(0.5) translateY(40px); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
.congrats-pet-glow {
    animation: congrats-pet-glow-pulse 2.5s ease-in-out infinite;
}
@keyframes congrats-pet-glow-pulse {
    0%, 100% { box-shadow: 0 0 30px 8px rgba(251,191,36,0.25), 0 0 60px 20px rgba(245,158,11,0.1); }
    50%      { box-shadow: 0 0 40px 14px rgba(251,191,36,0.4), 0 0 80px 30px rgba(245,158,11,0.18); }
}
.congrats-shimmer {
    animation: congrats-shimmer 3s ease-in-out infinite;
}
@keyframes congrats-shimmer {
    0%, 100% { opacity: 0.5; transform: scale(1); }
    50%      { opacity: 1; transform: scale(1.08); }
}
/* ====== 满级学生卡片常驻效果 ====== */
.maxed-progress-bar {
    background: linear-gradient(90deg, #f59e0b, #fbbf24, #f59e0b);
    background-size: 200% 100%;
    animation: maxed-progress-shimmer 2.5s ease-in-out infinite;
}
@keyframes maxed-progress-shimmer {
    0%, 100% { background-position: 0% 50%; opacity: 0.85; }
    50%      { background-position: 100% 50%; opacity: 1; }
}
.maxed-level-badge {
    background: linear-gradient(135deg, #f59e0b, #d97706);
    box-shadow: 0 0 10px 2px rgba(245,158,11,0.35);
    animation: maxed-level-pulse 2.5s ease-in-out infinite;
}
@keyframes maxed-level-pulse {
    0%, 100% { box-shadow: 0 0 10px 2px rgba(245,158,11,0.3); }
    50%      { box-shadow: 0 0 16px 5px rgba(245,158,11,0.55); }
}
.maxed-summon-btn {
    animation: maxed-summon-breathe 2.8s ease-in-out infinite;
}
@keyframes maxed-summon-breathe {
    0%, 100% { background-color: rgba(245,158,11,0.55); }
    50%      { background-color: rgba(217,119,6,0.75); }
}
.maxed-card-border {
    border-color: transparent !important;
    border-width: 0 !important;
}
.maxed-card-sweep {
    position: absolute;
    inset: 0;
    z-index: 35;
    pointer-events: none;
    overflow: hidden;
    border-radius: 1.5rem;
}
.maxed-card-sweep::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 50%;
    height: 100%;
    background: linear-gradient(
        to right,
        transparent,
        rgba(255,255,255,0.5),
        transparent
    );
    transform: skewX(-25deg);
    animation: maxed-sweep 3.5s ease-in-out infinite;
}
@keyframes maxed-sweep {
    0%   { left: -100%; }
    45%  { left: 150%; }
    100% { left: 150%; }
}
.maxed-card-border::before {
    content: '';
    position: absolute;
    inset: -75%;
    z-index: 1;
    background: conic-gradient(
        #f59e0b, #f97316, #ef4444, #a855f7, #3b82f6, #10b981, #f59e0b
    );
    animation: maxed-border-spin 4s linear infinite;
}
.maxed-card-border::after {
    content: '';
    position: absolute;
    inset: 3px;
    z-index: 2;
    border-radius: calc(1.5rem - 3px);
    background: white;
}
@keyframes maxed-border-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
/* ====== 徽章飞行 + 弹跳 ====== */
.badge-fly {
    position: fixed;
    z-index: 9999;
    pointer-events: none;
    font-size: 28px;
    filter: drop-shadow(0 2px 6px rgba(245,158,11,0.5));
}
.badge-bounce {
    animation: badge-btn-bounce 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes badge-btn-bounce {
    0%   { transform: scale(1); }
    30%  { transform: scale(1.35); }
    50%  { transform: scale(0.9); }
    70%  { transform: scale(1.15); }
    100% { transform: scale(1); }
}
/* ====== 养成弹窗特殊样式 ====== */
.congrats-modal-wrapper {
    position: relative;
}
.congrats-modal-glow-bg {
    position: absolute;
    inset: -30px;
    border-radius: 2rem;
    z-index: -1;
    background: conic-gradient(from var(--glow-angle, 0deg), #fbbf24, #f97316, #ec4899, #a855f7, #3b82f6, #10b981, #fbbf24);
    opacity: 0.55;
    filter: blur(24px);
    animation: congrats-glow-rotate 4s linear infinite;
}
@property --glow-angle { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
@keyframes congrats-glow-rotate { to { --glow-angle: 360deg; } }
.congrats-modal-border {
    position: relative;
    overflow: hidden;
    border-radius: 1.5rem;
    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.congrats-modal-border::before {
    content: '';
    position: absolute;
    inset: -75%;
    z-index: 0;
    background: conic-gradient(
        #f59e0b, #f97316, #ef4444, #a855f7, #3b82f6, #10b981, #f59e0b
    );
    animation: maxed-border-spin 4s linear infinite;
}
.congrats-modal-border::after {
    content: '';
    position: absolute;
    inset: 4px;
    z-index: 1;
    border-radius: calc(1.5rem - 4px);
    background: white;
}
/* ====== 礼炮喷射 ====== */
.congrats-cannon {
    position: fixed;
    pointer-events: none;
    z-index: 202;
}
.congrats-cannon-particle {
    position: absolute;
    border-radius: 2px;
    pointer-events: none;
    animation: congrats-cannon-fly var(--dur, 2.5s) cubic-bezier(0.15,0.8,0.3,1) infinite;
    animation-delay: var(--delay, 0s);
}
@keyframes congrats-cannon-fly {
    0%   { transform: translate(0,0) rotate(0deg) scale(1); opacity: 1; }
    70%  { opacity: 1; }
    100% { transform: translate(var(--cx), var(--cy)) rotate(var(--cr, 360deg)) scale(0.3); opacity: 0; }
}
/* 首页班级数据加载：三点错落跳动（避免整圆旋转视觉上像没动） */
@keyframes pet-home-loader-dot {
    0%, 70%, 100% { transform: translateY(0); opacity: 0.45; }
    35% { transform: translateY(-12px); opacity: 1; }
}
.pet-home-loader-dot {
    width: 10px;
    height: 10px;
    border-radius: 9999px;
    background: rgb(var(--primary-r, 244), var(--primary-g, 63), var(--primary-b, 94));
    animation: pet-home-loader-dot 0.9s ease-in-out infinite;
}
.pet-home-loader-dot:nth-child(1) { animation-delay: 0s; }
.pet-home-loader-dot:nth-child(2) { animation-delay: 0.14s; }
.pet-home-loader-dot:nth-child(3) { animation-delay: 0.28s; }

@keyframes fade-in-up {
    from { opacity: 0; transform: translate(-50%, 20px); }
    to { opacity: 1; transform: translate(-50%, 0); }
}
.animate-fade-in-up {
    animation: fade-in-up 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

/* 隐藏滚动条但保留功能 */
.no-scrollbar::-webkit-scrollbar {
    display: none;
}
.pet-card:hover {
    transform: scale(1.05);
}
.btn-press:active {
    transform: scale(0.96);
}
.bg-paper {
    background-color: var(--page-bg, #fdfbf7);
    background-image: radial-gradient(rgba(var(--primary-r, 244), var(--primary-g, 63), var(--primary-b, 94), 0.18) 1px, transparent 1px);
    background-size: 28px 28px;
}
/* 深色主题 */
html.dark body {
    background: #0f172a !important;
    color: #e2e8f0;
}
html.dark .bg-paper {
    background-color: #0f172a;
    background-image: radial-gradient(#334155 1px, transparent 1px);
}

[v-cloak] {
    display: none;
}
.animate-bounce-slow {
    animation: bounce 3s infinite;
}
.animate-breathe {
    animation: breathe 4s ease-in-out infinite;
}
@keyframes bounce {
    0%, 100% {
        transform: translateY(-5%);
        animation-timing-function: cubic-bezier(0.8,0,1,1);
    }
    50% {
        transform: none;
        animation-timing-function: cubic-bezier(0,0,0.2,1);
    }
}
@keyframes breathe {
    0%, 100% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.06);
    }
}
/* Tailwind 动画扩展 */
.list-enter-active, .list-leave-active {
    transition: all 0.5s ease;
}
.list-enter-from, .list-leave-to {
    opacity: 0; transform: translateX(30px);
}
