/* ============================================================
   css/farm.css - 草地小农场（QQ 农场式种植经营）场景样式
   依赖：global.css（变量/按钮/模态）、map.css（.gb-scene/.rt 等）
   结构：
     #scene-farm
       .farm-sky / .farm-veil            -- 昼夜 + 天气氛围
       .farm-hud                         -- 等级 / 经验 / 金币 / 环境
       .farm-board                       -- 田地画布（可滚动）
         .farm-grid > .plot              -- 土地格子（主角）
         .farm-deco                      -- 小路 / 水井 / 稻草人 / 木牌
       .farm-dock                        -- 底部工具条
       .farm-caption                     -- 狗宝吐槽
   昼夜：day-dawn / day-day / day-dusk / day-night / day-deep
   天气：wx-rain / wx-snow / wx-cloudy
   兼容：320px ~ 4K；横屏矮屏自动压缩；土地点击区 ≥ 44px
   ============================================================ */

#scene-farm {
    padding: 0;
    overflow: hidden;
    background: #cfe3b0;
    touch-action: manipulation;
    --farm-plot-min: 64px;
}

/* ============================================================
   美术资产层（js/art/farm-art.js）
   全部是内联 SVG 字符串，这里只负责「摆放与缩放」。
   统一约定：
     .fa-i       1em 级内联小图标（随父级 font-size 缩放，能跟文字混排）
     .fa-fx      特效碎片（同样 1em 级）
     .fallback   没有尺寸时别撑成 300×150
   ============================================================ */

/* 共享 <defs>（渐变/图案）：只插一次，必须存在但不能占位 */
.farm-defs {
    position: absolute; width: 0; height: 0;
    overflow: hidden; pointer-events: none;
}

/* 内联图标：跟字号缩放，垂直方向跟文字基线对齐 */
.fa-i {
    width: 1em; height: 1em;
    display: inline-block; vertical-align: -0.14em;
    flex: 0 0 auto;
    pointer-events: none;
}
.fa-fx {
    width: 1em; height: 1em;
    display: block;
    pointer-events: none;
}
.fa-bird {
    width: 1em; height: 1em;
    display: block;
    pointer-events: none;
}

/* ---------------- 草地上的入口按钮 ---------------- */
.meadow-farm {
    position: absolute; right: calc(16px + var(--sa-right));
    bottom: calc(86px + var(--sa-bottom)); z-index: 20;
    border-color: #d7b06a; color: #6a5320;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
    min-height: 44px;
}
@media (max-width: 560px) {
    .meadow-farm { right: calc(10px + var(--sa-right)); bottom: calc(72px + var(--sa-bottom)); padding: 8px 12px; font-size: 0.86rem; }
}

/* ---------------- 天空 / 地面 ---------------- */
.farm-sky {
    position: absolute; inset: 0; z-index: 1;
    background: linear-gradient(180deg, #bfe6f2 0%, #daf0c6 58%, #b8d894 58%, #a9cd82 100%);
    transition: background 2s ease;
}
#scene-farm.day-dawn .farm-sky { background: linear-gradient(180deg, #ffd9b0, #ffe9cf 52%, #cddda6 52%, #b6cc8d 100%); }
#scene-farm.day-day .farm-sky { background: linear-gradient(180deg, #bfe6f2, #e4f3df 52%, #bfe0a2 52%, #a9cd82 100%); }
#scene-farm.day-dusk .farm-sky { background: linear-gradient(180deg, #ff9e6b, #ffd39b 52%, #cdbb84 52%, #b0a06d 100%); }
#scene-farm.day-night .farm-sky { background: linear-gradient(180deg, #243a6b, #4a5a80 52%, #3d4a63 52%, #33405a 100%); }
#scene-farm.day-deep .farm-sky { background: linear-gradient(180deg, #101836, #26304f 52%, #202a44 52%, #1b2338 100%); }
#scene-farm.wx-cloudy .farm-sky { filter: saturate(0.62) brightness(0.92); }
#scene-farm.wx-rain .farm-sky { background: linear-gradient(180deg, #6b7d94, #93a1ac 52%, #7d8b7a 52%, #6f7d6c 100%); }

/* 夜间压暗层：让字与作物在暗底上依然清楚（不吃掉白天） */
.farm-veil {
    position: absolute; inset: 0; z-index: 3; pointer-events: none;
    background: transparent; transition: background 2s ease;
}
#scene-farm.day-dusk .farm-veil { background: rgba(120, 70, 40, 0.14); }
#scene-farm.day-night .farm-veil { background: rgba(14, 22, 48, 0.42); }
#scene-farm.day-deep .farm-veil { background: rgba(8, 12, 30, 0.55); }
#scene-farm.wx-rain .farm-veil { background: rgba(60, 80, 100, 0.22); }

/* 雨丝（复用地图雨的观感，但只落在田地范围） */
#scene-farm.wx-rain .farm-board::after {
    content: ''; position: absolute; inset: 0; z-index: 9; pointer-events: none;
    background: repeating-linear-gradient(90deg, transparent 0 26px, rgba(255, 255, 255, 0.22) 26px 27px);
    animation: farm-rain 0.45s linear infinite;
}
@keyframes farm-rain { from { background-position: 0 0; } to { background-position: 0 40px; } }
#scene-farm.wx-snow .farm-board::after {
    content: ''; position: absolute; inset: 0; z-index: 9; pointer-events: none;
    background-image: radial-gradient(rgba(255, 255, 255, 0.85) 1.5px, transparent 2px);
    background-size: 42px 42px;
    animation: farm-snow 6s linear infinite;
}
@keyframes farm-snow { from { background-position: 0 0; } to { background-position: 12px 42px; } }

/* 太阳 / 月亮（跟场景时间走，不用定时器） */
.farm-sun, .farm-moon {
    position: absolute; right: 10%; top: 7%; z-index: 2;
    font-size: 2.2rem; filter: drop-shadow(0 0 12px rgba(255, 240, 190, 0.55));
    transition: opacity 1.6s ease; pointer-events: none;
}
.farm-moon { opacity: 0; }
#scene-farm.day-night .farm-sun, #scene-farm.day-deep .farm-sun { opacity: 0; }
#scene-farm.day-night .farm-moon, #scene-farm.day-deep .farm-moon { opacity: 1; }

/* ---------------- 顶部 HUD ---------------- */
.farm-hud {
    position: absolute; z-index: 40;
    left: calc(12px + var(--sa-left)); top: calc(10px + var(--sa-top));
    display: flex; flex-direction: column; gap: 6px;
    pointer-events: none;
}
.farm-hud-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.farm-chip {
    pointer-events: auto;
    background: rgba(255, 250, 240, 0.94);
    border: 2px solid #d9c39c;
    border-radius: 16px; padding: 4px 12px;
    font-size: 0.9rem; color: #5d4a33;
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.14);
    white-space: nowrap;
}
.farm-chip b { font-weight: normal; color: #c8672f; }
.farm-chip.clickable { cursor: pointer; }
.farm-chip.clickable:active { transform: scale(0.95); }

.farm-lv-exp {
    pointer-events: auto; display: flex; align-items: center; gap: 8px;
    background: rgba(255, 250, 240, 0.94);
    border: 2px solid #d9c39c; border-radius: 16px;
    padding: 4px 10px; box-shadow: 0 3px 8px rgba(0, 0, 0, 0.14);
}
.farm-lv-badge {
    background: linear-gradient(180deg, #ffe3a8, #ffc45e);
    border-radius: 12px; padding: 1px 9px; font-size: 0.86rem; color: #6b4a11;
    border: 1px solid #e2ab3f;
}
.farm-exp-bar {
    width: 96px; height: 9px; border-radius: 9px; background: #e7d9c2; overflow: hidden; position: relative;
}
.farm-exp-bar i {
    display: block; height: 100%; width: 0;
    background: linear-gradient(90deg, #9fd67a, #6fbf4a);
    transition: width 0.5s ease;
}
.farm-exp-txt { font-size: 0.76rem; color: #8a7a66; }

/* ---------------- 田地画布 ---------------- */
.farm-board {
    position: absolute; z-index: 5;
    left: 0; right: 0; top: calc(64px + var(--sa-top));
    bottom: calc(var(--dock-h, 62px) + 16px + var(--farm-extra, 0px) + var(--sa-bottom));
    display: flex; flex-direction: column; align-items: center;
    /* 安全居中：不放 justify-content:center —— 内容比可视区高时
       居中会把上半截推到「滚不到」的负区（横屏地块点不到的根因）。
       改用子元素 margin:auto：放得下就居中，放不下就从顶部开始滚。 */
    overflow: auto; -webkit-overflow-scrolling: touch;
    padding: 6px 10px 14px;
    scrollbar-width: thin;
}
.farm-grid-wrap { margin: auto; }   /* 与上条配合：占满时顶对齐可滚，空间够时自动居中 */
/* 这块「翻过的土」放在 .farm-grid-wrap 里，所以能正好把田格托住：
   田格变大变小它跟着变，不会露出草地也不会糊成一大片棕色。
   P1：田格去了卡片壳，格与格之间的缝就是田埂小路 —— 底色改成
   被踩实的浅土路色 + 零星石子，田块和路一眼分得开。 */
.farm-ground {
    position: absolute; inset: -20px -14px;
    background:
        radial-gradient(circle at 22% 34%, rgba(120, 90, 55, 0.22) 2px, transparent 3px),
        radial-gradient(circle at 68% 22%, rgba(120, 90, 55, 0.18) 1.6px, transparent 2.6px),
        radial-gradient(circle at 82% 72%, rgba(120, 90, 55, 0.2) 2.2px, transparent 3px),
        radial-gradient(circle at 38% 82%, rgba(120, 90, 55, 0.16) 1.5px, transparent 2.4px),
        linear-gradient(180deg, #c9a26e 0%, #b28a58 100%);
    background-size: 90px 90px, 70px 70px, 110px 110px, 80px 80px, 100% 100%;
    border-radius: 26px;
    border: 4px solid #8d6440;
    box-shadow: inset 0 6px 18px rgba(0, 0, 0, 0.18), 0 10px 22px rgba(60, 40, 20, 0.22);
    opacity: 0.96;
    pointer-events: none;
    z-index: 0;
}
/* 田埂边缘的草：一圈细细的草色毛边，路是路、草地是草地 */
.farm-ground::before {
    content: ''; position: absolute; inset: 4px; border-radius: 22px;
    border: 2px dashed rgba(143, 181, 109, 0.55);
    background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 0 2px, transparent 2px 16px);
    pointer-events: none;
}

.farm-grid-wrap {
    position: relative; z-index: 6;
    width: 100%; max-width: 900px;
    display: flex; justify-content: center;
}
.farm-grid {
    position: relative; z-index: 1;   /* 压在 .farm-ground 上面 */
    display: grid;
    gap: clamp(6px, 1.2vw, 14px);
    width: 100%;
    justify-content: center;
    grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
    grid-template-rows: repeat(var(--rows, 3), auto);
}

/* ---------------- 土地格子 ----------------
   P1 去卡片化：卡片的「壳」（边框/底色/投影/方角裁切）全部撤掉，
   造型交给每格自己的手绘 soil SVG —— 一块一块的是田，不是一张一张的卡。
   overflow 放开是给果树用的：树冠可以探出格子，像真的长在田埂上。 */
.plot {
    position: relative;
    min-width: 44px; min-height: 44px;
    aspect-ratio: 1 / 1;
    border: 0; border-radius: 16px;
    background: transparent;
    box-shadow: none;
    cursor: pointer; overflow: visible;
    /* 底部留出进度条的位置：否则作物/名称会压在那条 6px 的进度槽上 */
    padding: 4px 4px 13px;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    transition: transform 0.16s ease, filter 0.2s ease;
    font-family: inherit;
}
.plot:active { transform: scale(0.95); }
.plot:focus-visible { outline: 3px solid #ffd66b; outline-offset: 2px; border-radius: 16px; }

/* 开垦过：深色松土 + 垄沟（颜色由 soil SVG 承担，这里只管交互反馈） */
.plot.s-tilled { background: transparent; }
.plot.s-tilled::after {
    content: ''; position: absolute; inset: 14% 10%;
    background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.12) 0 3px, transparent 3px 12px);
    border-radius: 6px; pointer-events: none;
}
/* 已种植 / 生长中 */
.plot.s-planted, .plot.s-growing { background: transparent; }
/* 成熟：金环贴着「地块形状」发光（drop-shadow 跟 SVG 轮廓走，不是方的） */
.plot.s-mature {
    background: transparent; border: 0;
    box-shadow: none;
    animation: plot-ready 1.6s ease-in-out infinite;
}
.plot.s-mature .plot-soil { filter: drop-shadow(0 0 5px rgba(255, 214, 107, 0.75)); }
@keyframes plot-ready {
    0%, 100% { filter: none; }
    50% { filter: brightness(1.08); }
}
/* 枯萎 */
.plot.s-withered { background: transparent; filter: saturate(0.35); }
/* 未解锁：荒地就是荒地（SVG 画了杂草石子），不再叠条纹底 */
.plot.s-locked {
    background: transparent; cursor: pointer; filter: saturate(0.72);
}
/* 锁地的价格：一枚小胶囊，不再整行大字 */
.plot-cost {
    position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%);
    z-index: 4; display: inline-flex; align-items: center; gap: 2px;
    font-size: 0.6rem; color: #ffe9b8; background: rgba(58, 44, 28, 0.72);
    padding: 1px 6px; border-radius: 999px; white-space: nowrap;
}
.plot-cost .fa-i, .plot-cost svg { width: 10px; height: 10px; }
/* 土地底：铺满整格的手绘土（每格一份 SVG，渐变引用场景里那份共享 defs） */
.plot-soil {
    position: absolute; inset: 0; z-index: 1;
    width: 100%; height: 100%; display: block;
    pointer-events: none;
}
/* 田里的作物：手绘 SVG（方形裁切框 + 底边对齐地平线）
   尺寸按「可用高度」算而不是宽度 —— 格子是正方形的，名称那行要占一截，
   若按宽度 100% 算，作物就会把名称挤出格子里 */
.plot-art {
    position: relative; z-index: 3;
    flex: 0 0 auto;
    height: 100%; width: auto;
    max-width: 100%;
    aspect-ratio: 1 / 1;
    filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.28));
    transform-origin: 50% 88%;
    pointer-events: none;
}
.plot.s-growing .plot-art { animation: plot-sway 3.4s ease-in-out infinite; }
@keyframes plot-sway { 0%, 100% { transform: rotate(-2.2deg); } 50% { transform: rotate(2.2deg); } }
.plot.s-mature .plot-art { animation: plot-bounce 1.1s ease-in-out infinite; }
@keyframes plot-bounce { 0%, 100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-3px) scale(1.06); } }
.plot.s-withered .plot-art { filter: grayscale(1) drop-shadow(0 2px 2px rgba(0, 0, 0, 0.3)); }

/* ★ 生长阶段尺寸档（2026-10-01）：种子/幼芽只占格子一小角，越长大越大，
   挂果期才吃满整格 —— 解决「刚种下去就像成熟」的观感问题。
   用 height 而不是 transform 缩放：不跟风摆/弹跳动画的 transform 打架。 */
.plot.st-0 .plot-art { height: 46%; }
.plot.st-1 .plot-art { height: 62%; }
.plot.st-2 .plot-art { height: 76%; }
.plot.st-3 .plot-art { height: 90%; }
.plot.st-4 .plot-art { height: 100%; }
/* 果树是绝对定位大图（132%），同样按档收：树苗别探出一整棵大树 */
.plot.pt-orchard.st-0 .plot-art { height: 60%; }
.plot.pt-orchard.st-1 .plot-art { height: 82%; }
.plot.pt-orchard.st-2 .plot-art { height: 108%; }
.plot.pt-orchard.st-3 .plot-art { height: 122%; }
.plot.pt-orchard.st-4 .plot-art { height: 132%; }

/* 果树是「树」不是贴片（§十六）：树冠探出格子、树冠探到上一排田上，
   风摆要慢要轻 —— 大树的摆法和小苗不一样。 */
.plot.pt-orchard { z-index: 2; }
.plot.pt-orchard .plot-art {
    position: absolute; bottom: 13px; left: 50%;
    height: 132%; max-width: none;
    margin-left: -66%;
}
.plot.pt-orchard.s-growing .plot-art,
.plot.pt-orchard.s-planted .plot-art { animation: tree-sway 5.8s ease-in-out infinite; }
.plot.pt-orchard.s-mature .plot-art { animation: tree-sway 5.8s ease-in-out infinite; }
@keyframes tree-sway {
    0%, 100% { transform: rotate(-1.4deg); }
    50% { transform: rotate(1.4deg); }
}

/* 作物名称贴在格子底部（绝对定位，让上面的作物能吃满整个格高）。
   作物长得大，名称必然压到它的根部 —— 所以做成一块半透明「名牌」，
   压在土上/作物上都读得清，看起来也是故意设计的而不是撞在一起 */
.plot-label {
    position: absolute; left: 3px; right: 3px; bottom: 19px; z-index: 4;
    text-align: center;
    font-size: 0.72rem; color: #fff6e6;
    background: rgba(74, 56, 38, 0.66);
    border-radius: 8px; padding: 1px 4px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 未解锁格：标签是「锁 · 🪙价」。手机上格子只有 46~60px，
   而 .plot 是 column flex + align-items:center，标签默认按内容撑宽不换行，
   会被 nowrap+ellipsis 截成「Lv.3 · 0..」→ 这里强制拉伸 + 允许折两行。
   标签里现在放的是 SVG 图标，所以用 flex 对齐而不是纯文字排版 */
.plot.s-locked .plot-label {
    left: 4px; right: 4px; bottom: 10px;
    white-space: normal; text-overflow: clip;
    line-height: 1.05; padding: 0 1px;
    display: flex; align-items: center; justify-content: center;
    gap: 2px; flex-wrap: wrap;
}
.plot.s-locked .plot-state { background: rgba(0, 0, 0, 0.3); }
.plot-state {
    position: absolute; left: 4px; top: 4px; z-index: 5;
    font-size: 0.62rem; padding: 1px 6px; border-radius: 8px;
    background: rgba(0, 0, 0, 0.42); color: #fff3df;
    max-width: calc(100% - 8px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.plot-progress {
    position: absolute; left: 6px; right: 6px; bottom: 6px; z-index: 4;
    height: 6px; border-radius: 6px; background: rgba(0, 0, 0, 0.35); overflow: hidden;
}
/* 不显示进度时（成熟/空地）把整条槽藏掉，别让空槽压着「可收」角标 */
.plot-progress:empty { display: none; }
.plot-progress i {
    display: block; height: 100%; background: linear-gradient(90deg, #ffe08a, #8fd267);
    transition: width 0.6s ease;
}
.plot-icons {
    position: absolute; right: 4px; top: 4px; z-index: 6;
    display: flex; gap: 2px; font-size: 0.95rem;
}
.plot-icons span { display: inline-flex; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.4)); }
/* 未浇水：干旱提示（只在需要浇水的作物上出现）。
   z-index 必须夹在「土(1)」与「作物(3)」之间，否则会把土盖住。
   格子已经没有方角壳，这里跟着补圆角。 */
.plot.need-water::before {
    content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
    border-radius: 16px;
    background: radial-gradient(circle at 50% 60%, rgba(255, 140, 90, 0.26), transparent 70%);
}
/* 可收获：不再另挂一个「可收」角标（会和作物名撞在一起），
   直接把左上角的状态胶囊染成暖橙色 —— 加上金环 + 呼吸动效已经足够醒目 */
.plot.ready-badge .plot-state { background: rgba(200, 103, 47, 0.94); color: #fff6e6; }

/* 浮层卡片里的生长阶段一览条（pc-stage）：当前档实心，走过的档半透明 */
.pc-stage { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 2px; }
.pc-stage i { font-style: normal; font-size: 0.68rem; line-height: 1.5;
    padding: 1px 6px; border-radius: 9px;
    background: rgba(74, 56, 38, 0.14); color: #8a7a64; }
.pc-stage i.past { color: #6f9152; background: rgba(111, 145, 82, 0.16); }
.pc-stage i.on { color: #fff6e6; background: rgba(111, 145, 82, 0.92); font-weight: 700; }

/* 收获飘字 */
.farm-pop {
    position: absolute; z-index: 60; font-size: 0.95rem; color: #fff6e6;
    background: rgba(74, 56, 38, 0.88); border-radius: 12px; padding: 3px 10px;
    pointer-events: none; animation: farm-pop-up 1.5s ease forwards; white-space: nowrap;
    display: inline-flex; align-items: center; gap: 4px;
}
.farm-pop .fp-ico { font-size: 1.1rem; display: inline-flex; flex: 0 0 auto; }
@keyframes farm-pop-up {
    0% { opacity: 0; transform: translate(-50%, 6px) scale(0.85); }
    18% { opacity: 1; transform: translate(-50%, -6px) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -46px) scale(1); }
}
.farm-spark { position: absolute; z-index: 59; font-size: 1.1rem; pointer-events: none; animation: farm-sparkle 0.9s ease forwards; }
@keyframes farm-sparkle {
    0% { opacity: 0; transform: translate(-50%, 0) scale(0.6); }
    35% { opacity: 1; }
    100% { opacity: 0; transform: translate(-50%, -30px) scale(1.2); }
}

/* ---------------- 装饰物（全部手绘 SVG） ---------------- */
.farm-deco { position: absolute; inset: 0; pointer-events: none; z-index: 4; }
.farm-deco .deco {
    position: absolute; transform: translateX(-50%);
    filter: drop-shadow(0 3px 4px rgba(60, 40, 20, 0.22));
    line-height: 0;
}
.farm-deco .deco > svg { width: 100%; height: auto; display: block; }
/* 每件装饰单独定尺寸 + 站位：围着田地的边角摆，不压到中间的格子 */
/* 装饰统一放在田格下方那条「院子」里（bottom 很小 = 贴着底边），
   摆在上一排会被田格盖住 —— 田格是不透明的 */
.deco-hut { left: 13%; bottom: 2%; width: clamp(56px, 10vw, 94px); }
.deco-tree { left: 4%; bottom: 6%; width: clamp(52px, 9.5vw, 92px); }
.deco-bush { left: 96%; bottom: 4%; width: clamp(38px, 7vw, 66px); }
.deco-scarecrow { left: 22%; bottom: 25%; width: clamp(44px, 8.5vw, 76px); }
.deco-well { left: 87%; bottom: 26%; width: clamp(42px, 8vw, 72px); }
.deco-barrow { left: 73%; bottom: 10%; width: clamp(40px, 8vw, 70px); }
.deco-flower { left: 27%; bottom: 9%; width: clamp(28px, 5.5vw, 48px); }
/* 木牌要能点开（父层 .farm-deco 是 pointer-events:none，这里必须单独放行） */
/* 木牌原来在正下方中间，被狗宝 + 台词气泡 + 教程条压住看不见，挪到左下角空地 */
.deco-sign {
    left: 30%; bottom: 19%; width: clamp(62px, 11vw, 104px);
    pointer-events: auto; cursor: pointer;
    transition: transform 0.16s ease;
}
.deco-sign:active { transform: translateX(-50%) scale(0.94); }
.deco-sign:focus-visible { outline: 3px solid #ffd66b; outline-offset: 2px; }
.deco-path {
    left: 50%; bottom: 8%; width: 46px; height: 34%;
    background: repeating-linear-gradient(180deg, #c8a877 0 10px, #b8986a 10px 20px);
    border-radius: 12px; opacity: 0.75;
}
.farm-bird {
    position: absolute; z-index: 10; font-size: 1.55rem; pointer-events: none;
    animation: farm-bird-fly 5.5s linear forwards;
}
@keyframes farm-bird-fly {
    0% { opacity: 0; transform: translate(0, 0) scale(0.8); }
    12% { opacity: 1; }
    100% { opacity: 0; transform: translate(-46vw, -60px) scale(1.05); }
}

/* ---------------- 狗宝 / NPC ---------------- */
.farm-dog {
    position: absolute; z-index: 12; bottom: calc(84px + var(--sa-bottom)); left: 50%;
    transform: translateX(-50%);
    transition: left 1.1s cubic-bezier(.4, .05, .3, 1);
    pointer-events: none;
}
.farm-npc {
    position: absolute; bottom: calc(96px + var(--sa-bottom)); left: 18%; z-index: 11;
    width: clamp(46px, 8.5vw, 66px); cursor: pointer;
    filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.25));
    animation: npc-idle 3.2s ease-in-out infinite;
}
/* NPC = 食堂那只猫（复用 GB.RestaurantArt.cat）+ 头上压一顶草帽 */
.farm-npc .fa-npc-wrap { position: relative; display: block; line-height: 0; }
.farm-npc .fa-npc-wrap > .rs-cat-svg,
.farm-npc .fa-npc-wrap > .fa-cat-fallback { width: 100%; height: auto; display: block; }
.farm-npc .fa-npc-hat {
    position: absolute; left: 50%; top: -15%; width: 72%;
    transform: translateX(-50%); display: block; pointer-events: none;
}
/* 旁白为空时不占位（否则猫头上会顶着一个空气泡） */
.farm-npc .npc-bubble:empty { display: none; }
@keyframes npc-idle { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
.farm-npc.helping { animation: npc-help 0.9s ease infinite; }
@keyframes npc-help { 0%, 100% { transform: translateY(0) rotate(-4deg); } 50% { transform: translateY(-8px) rotate(4deg); } }
.farm-npc .npc-bubble {
    position: absolute; left: 50%; bottom: 108%; transform: translateX(-50%);
    background: rgba(255, 250, 240, 0.96); border: 2px solid #d9c39c; color: #5d4a33;
    border-radius: 14px; padding: 4px 10px; font-size: 0.8rem; white-space: nowrap;
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16);
}

/* ---------------- 底部工具条 ---------------- */
.farm-dock {
    position: absolute; z-index: 45;
    left: 50%; bottom: calc(10px + var(--sa-bottom)); transform: translateX(-50%);
    display: flex; gap: 8px; flex-wrap: nowrap;
    max-width: calc(100vw - 20px); overflow-x: auto; padding: 6px 10px;
    background: rgba(255, 250, 240, 0.9);
    border: 2px solid #d9c39c; border-radius: 20px;
    box-shadow: 0 6px 16px rgba(90, 60, 30, 0.2);
    scrollbar-width: none;
}
.farm-dock::-webkit-scrollbar { display: none; }
.farm-dock .dock-btn {
    flex: 0 0 auto; min-height: 44px; min-width: 48px;
    background: rgba(255, 255, 255, 0.75); border: 2px solid #cbb48f; color: #5d4a33;
    border-radius: 14px; padding: 5px 9px; font-size: 0.88rem; cursor: pointer;
    /* 图标在上、文字在下：横排 6 个按钮在窄屏会撑到滚动，竖排更省地方 */
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 1px; white-space: nowrap;
    font-family: inherit; transition: transform 0.15s ease, background 0.2s ease;
}
.farm-dock .dock-btn .fa-i { font-size: 1.28rem; }
.farm-dock .dock-btn .dk-t { font-size: 0.68rem; line-height: 1.15; }
.farm-dock .dock-btn:active { transform: scale(0.94); }
.farm-dock .dock-btn.hot { background: rgba(255, 224, 138, 0.85); border-color: #e0a83a; }
/* 角标改成绝对定位：按钮已经是 column flex，留在流里会被挤到文字下面 */
.farm-dock .dock-btn { position: relative; }
.farm-dock .dock-btn .dot {
    position: absolute; top: -5px; right: -5px;
    display: inline-block; min-width: 16px; height: 16px; line-height: 16px; text-align: center;
    border-radius: 8px; background: #f76c8a; color: #fff; font-size: 0.66rem; padding: 0 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.farm-back {
    position: absolute; z-index: 46;
    right: calc(12px + var(--sa-right)); top: calc(10px + var(--sa-top));
    background: rgba(255, 250, 240, 0.94); border: 2px solid #cbb48f; color: #6b4f3f;
    border-radius: 22px; padding: 8px 16px; cursor: pointer;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15); font-family: inherit;
    min-height: 44px;
}

/* ---------------- 说服气泡 ---------------- */
.farm-caption {
    position: absolute; z-index: 47;
    left: 50%; bottom: calc(72px + var(--sa-bottom)); transform: translateX(-50%);
    background: rgba(74, 56, 38, 0.88); color: #fff3df;
    padding: 8px 18px; border-radius: 16px; font-size: 0.95rem; text-align: center;
    opacity: 0; transition: opacity 0.32s; pointer-events: none;
    max-width: 88vw; line-height: 1.5;
}
.farm-caption.show { opacity: 1; }

/* ---------------- 面板内通用件（模态里也在用） ---------------- */
.farm-panel { display: flex; flex-direction: column; gap: 10px; }
.farm-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.farm-tabs button {
    background: rgba(255, 255, 255, 0.8); border: 2px solid #e0d2ba; color: #6b5a45;
    border-radius: 14px; padding: 6px 12px; font-size: 0.86rem; cursor: pointer; font-family: inherit;
    /* 触摸目标：原来只有 27~30px 高，手机上手指容易点偏（实测 82x27 / 71x30） */
    min-height: 36px;
}
.farm-tabs button.on { background: var(--pink); border-color: var(--pink-deep); color: #fff; }

.farm-list { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.farm-item {
    display: flex; align-items: center; gap: 8px;
    background: rgba(255, 255, 255, 0.86); border: 2px solid #e8dcc6; border-radius: 14px;
    padding: 8px 10px; text-align: left; cursor: pointer; font-family: inherit; color: #5d4a33;
    min-height: 44px; transition: transform 0.15s ease, border-color 0.2s ease;
}
.farm-item:hover { border-color: var(--pink); }
.farm-item:active { transform: scale(0.97); }
.farm-item.locked { opacity: 0.55; cursor: not-allowed; }
.farm-item .fi-ico { font-size: 1.5rem; }
.farm-item .fi-main { flex: 1; min-width: 0; }
.farm-item .fi-name { font-size: 0.92rem; }
/* 改造用途列表里「已解锁」标记：买过的用途可免费切回 */
.farm-item .fi-owned {
    font-size: 0.66rem; font-style: normal; color: #2e7d4f;
    background: #e7f5ec; border: 1px solid #bfe3cd; border-radius: 999px;
    padding: 0 6px; margin-left: 4px; vertical-align: middle;
}
.farm-item .fi-sub { font-size: 0.74rem; color: #8a7a66; }
.farm-item .fi-price { font-size: 0.84rem; color: #c8672f; white-space: nowrap; }
/* 卡片左侧的图标位：里面是 SVG（种子包/肥料袋/农具/作物），固定方形防止串行 */
.farm-item .fi-ico {
    width: 36px; height: 36px; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
}
.farm-item .fi-ico svg { width: 100%; height: 100%; display: block; }
/* 「先不种 / 不施肥」这种取消项 */
.farm-item.none { cursor: default; justify-content: center; color: #a08371; border-style: dashed; }
.farm-item.none:hover { border-color: #e8dcc6; }

/* 面板顶部：SVG 头图 + 纯文字标题（模态标题走 textContent，塞不进 SVG） */
.farm-head { display: flex; align-items: center; gap: 10px; }
.farm-head .fh-ico {
    width: 42px; height: 42px; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255, 224, 138, 0.42); border: 2px solid #e0c07a; border-radius: 14px;
}
.farm-head .fh-ico svg { width: 74%; height: 74%; display: block; }
.farm-head .fh-main { display: flex; flex-direction: column; min-width: 0; }
.farm-head .fh-t { font-size: 1rem; color: #6b4f3f; }
.farm-head .fh-s { font-size: 0.76rem; color: #8a7a66; }

/* 任务行的「已领 / 进行中」状态 */
.farm-row .fr-done {
    display: inline-flex; align-items: center; gap: 3px;
    font-size: 0.82rem; color: #5f9a72; white-space: nowrap;
}
.farm-row .fr-doing { font-size: 0.82rem; color: #a08371; white-space: nowrap; }
/* 土地面板里的作物概览行：左边大图，右边名字 */
.farm-row-crop { justify-content: flex-start; gap: 10px; }
.farm-row .fr-crop {
    width: 46px; height: 46px; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
}
.farm-row .fr-crop svg { width: 100%; height: 100%; display: block; }
.farm-row-crop b { font-size: 1rem; color: #5d4a33; }

.farm-rows { display: flex; flex-direction: column; gap: 6px; }
.farm-row {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    background: rgba(255, 255, 255, 0.75); border-radius: 12px; padding: 8px 12px;
    font-size: 0.9rem; color: #5d4a33;
}
.farm-row.done { background: rgba(168, 220, 208, 0.4); }
.farm-row b { font-weight: normal; color: #c8672f; }
.farm-row .fr-bar { flex: 1; height: 8px; border-radius: 8px; background: #e7d9c2; overflow: hidden; max-width: 120px; }
.farm-row .fr-bar i { display: block; height: 100%; background: linear-gradient(90deg, #ffe08a, #8fd267); }

.farm-note { font-size: 0.82rem; color: #8a7a66; line-height: 1.6; }
.farm-empty { text-align: center; color: #a08371; font-size: 0.92rem; padding: 18px 0; }
.farm-stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
.farm-stat {
    background: rgba(255, 255, 255, 0.82); border: 2px solid #ece0cb; border-radius: 14px;
    padding: 8px 12px;
}
.farm-stat .fs-k { font-size: 0.76rem; color: #8a7a66; }
.farm-stat .fs-v { font-size: 1.05rem; color: #c8672f; }

/* 土地操作面板（底部弹层里的大按钮） */
.farm-actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; }
.farm-actions button {
    min-height: 46px; border-radius: 16px; border: 2px solid var(--pink);
    background: rgba(255, 255, 255, 0.9); color: #5d4a33; cursor: pointer;
    font-size: 0.92rem; font-family: inherit;
}
.farm-actions button.primary { background: var(--pink); border-color: var(--pink-deep); color: #fff; }
.farm-actions button:disabled { opacity: 0.45; cursor: not-allowed; }

/* 教程 */
.farm-tut {
    position: absolute; z-index: 55; left: 50%; bottom: calc(140px + var(--sa-bottom));
    transform: translateX(-50%); max-width: 86vw;
    background: rgba(255, 250, 240, 0.97); border: 2px solid #e0a83a;
    border-radius: 18px; padding: 10px 16px; box-shadow: 0 8px 20px rgba(90, 60, 30, 0.25);
    display: flex; align-items: center; gap: 10px; font-size: 0.9rem; color: #5d4a33;
}
.farm-tut .tut-ico { flex: 0 0 auto; display: flex; align-items: center; font-size: 1.3rem; }
.farm-tut button {
    background: var(--pink); color: #fff; border: 2px solid var(--pink-deep);
    border-radius: 14px; padding: 6px 12px; cursor: pointer; font-family: inherit; white-space: nowrap;
}

/* 升级庆祝 */
.farm-levelup {
    position: absolute; inset: 0; z-index: 70; display: flex; align-items: center; justify-content: center;
    pointer-events: none;
}
.farm-levelup .lu-card {
    background: rgba(255, 250, 240, 0.97); border: 3px solid #e0a83a; border-radius: 22px;
    padding: 18px 28px; text-align: center; box-shadow: 0 14px 30px rgba(90, 60, 30, 0.3);
    animation: lu-in 0.5s ease;
}
@keyframes lu-in { from { opacity: 0; transform: scale(0.8) translateY(12px); } to { opacity: 1; transform: none; } }
.farm-levelup .lu-t { font-size: 1.15rem; color: #c8672f; }
.farm-levelup .lu-d { font-size: 0.88rem; color: #6b5a45; margin-top: 6px; }
/* 升级解锁的新作物：直接把手绘成品摆出来 */
.farm-levelup .lu-crops {
    display: flex; align-items: center; justify-content: center;
    flex-wrap: wrap; gap: 8px; margin-top: 8px;
}
.farm-levelup .lu-crop { width: 54px; height: 54px; display: block; flex: 0 0 auto; }
.farm-levelup .lu-crops .lu-d { flex: 1 0 100%; margin-top: 0; }

/* ---------------- 响应式 ---------------- */
/* 窄屏手机：一格最小 44px，田块用 3 列起步，取消固定 aspect 撑高 */
@media (max-width: 560px) {
    :root { --farm-plot-min: 48px; }
    .farm-grid { gap: 6px; }
    .plot { border-width: 2px; border-radius: 13px; }
    .plot-state { font-size: 0.56rem; padding: 0 4px; }
    .plot-label { font-size: 0.64rem; }
    /* 作物尺寸是「按格高」算的，会自己跟着格子缩，这里不用再调宽 */
    .plot-icons { font-size: 0.78rem; }
    /* 锁定格在两行内塞下「锁 + 价格」 */
    .plot.s-locked .plot-label { font-size: 0.58rem; }
    .plot.s-locked .plot-label .fa-i { font-size: 0.72rem; }
    .farm-hud { left: calc(8px + var(--sa-left)); }
    .farm-chip { font-size: 0.8rem; padding: 3px 9px; }
    .farm-exp-bar { width: 68px; }
    .farm-dock { gap: 6px; padding: 5px 8px; }
    .farm-dock .dock-btn { padding: 4px 7px; min-width: 46px; }
    .farm-dock .dock-btn .fa-i { font-size: 1.16rem; }
    .farm-dock .dock-btn .dk-t { font-size: 0.62rem; }
    .farm-item .fi-ico { width: 30px; height: 30px; }
    .farm-head .fh-ico { width: 36px; height: 36px; }
    .farm-levelup .lu-crop { width: 44px; height: 44px; }
    /* 商店/仓库卡片：手机上两列会把「小麦种子」「5分钟」挤成竖排，改单列 */
    .farm-list { grid-template-columns: 1fr; }
    .farm-back { padding: 7px 12px; font-size: 0.86rem; }
    .farm-board { top: calc(58px + var(--sa-top)); bottom: calc(var(--dock-h, 62px) + 12px + var(--farm-extra, 0px) + var(--sa-bottom)); }
    .farm-npc { left: 12%; bottom: calc(88px + var(--sa-bottom)); }
}
/* 矮屏横屏（手机横放 / 小笔记本）：把田地压扁，保证 HUD 与工具条都在 */
@media (max-height: 520px) {
    .farm-board { top: calc(50px + var(--sa-top)); bottom: calc(var(--dock-h, 62px) + 10px + var(--farm-extra, 0px) + var(--sa-bottom)); }
    .plot .plot-label { display: none; }
    .plot-art { width: 80%; }
    .farm-dock .dock-btn { min-height: 38px; }
    .farm-dock .dock-btn .dk-t { font-size: 0.6rem; }
    /* 矮屏先把不重要的装饰收起来，保证田地和工具条都在 */
    .deco-hut, .deco-tree, .deco-bush, .deco-barrow, .deco-flower,
    .farm-deco .deco-scarecrow, .farm-deco .deco-well { display: none; }
    /* 木牌也得收：短横屏里院坝（工坊带）几乎占满宽度，木牌正好卡在它下沿，
       一半被果酱机压住、一半被滚出可视区 —— 留着反而是「看得见的乱」。 */
    .deco-sign { display: none !important; }
    /* 矮横屏塞不下独立装备条 ⇒ 收起 bar，把同一份 chips 并进 dock 当第一段，
       地图因此不必再为它让高度（--farm-extra 会量到 0）。 */
    #farm-toolbar { display: none !important; }
    .farm-dock .dock-tools {
        display: flex; gap: 5px; align-items: center; flex: 0 1 auto;
        max-width: 44vw; overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
        padding-right: 7px; margin-right: 5px;
        border-right: 2px dashed rgba(122, 96, 58, .28);
    }
    .farm-dock .dock-tools::-webkit-scrollbar { display: none; }
    .farm-dock .dock-tools:empty { display: none; }
    .farm-dock .dock-tools .tb-item { min-height: 40px; padding: 3px 8px 3px 5px; }
    /* 只留图标分不清浇水壶还是播种机 —— 短名留着，字号压小，超宽自己滚 */
    .farm-dock .dock-tools .tb-name { font-size: .6rem; }
    .farm-dock .dock-tools .tb-ico { width: 20px; height: 20px; }
}
/* 大屏：田地更大更松弛 */
@media (min-width: 1100px) {
    .farm-grid-wrap { max-width: 1040px; }
    .farm-grid { gap: 14px; }
}
@media (min-width: 1600px) {
    .farm-grid-wrap { max-width: 1200px; }
}

/* 减少动效偏好 */
@media (prefers-reduced-motion: reduce) {
    .plot.s-mature,
    .plot.s-growing .plot-art,
    .plot.s-mature .plot-art,
    .farm-npc,
    .farm-bird { animation: none !important; }
    #scene-farm.wx-rain .farm-board::after,
    #scene-farm.wx-snow .farm-board::after { animation: none; }
}

/* ---------------- V2.0：地块类型角标 / 农具面板 ---------------- */
.plot { position: relative; }
.plot-ptype {
    position: absolute; top: 2px; right: 2px;
    font-size: 0.92rem; line-height: 1; pointer-events: none;
    filter: drop-shadow(0 1px 1px rgba(0,0,0,.35));
}
.farm-mod-sum {
    background: rgba(108,192,108,.16);
    border: 1px solid rgba(108,192,108,.42);
    border-radius: 10px; padding: 7px 10px; margin: 6px 0;
    font-size: 0.82rem; color: #2f6b2f;
}
.farm-item.on { outline: 2px solid var(--farm-accent, #6cc06c); outline-offset: -2px; }
.farm-item.on .fi-name { font-weight: 700; }

/* ---------------- V2.0：加工坊 / 订单卡片 ---------------- */
.farm-card {
    background: #fff;
    border: 1px solid var(--farm-line, #e3e6dd);
    border-radius: 12px; padding: 9px 11px; margin: 8px 0;
    box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
.fc-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.fc-ico { font-size: 1.06rem; }
.fc-head b { font-size: 0.92rem; }
.fc-tag {
    font-size: 0.68rem; padding: 1px 7px; border-radius: 999px;
    background: #f0f1ec; color: #8a8f80; margin-left: 4px;
}
.fc-tag.ok { background: rgba(108,192,108,.18); color: #2f6b2f; }
.fc-sub { font-size: 0.7rem; color: #9a9f90; margin-left: auto; }
.farm-sub { font-size: 0.74rem; color: #8a8f80; margin: 7px 0 3px; font-weight: 600; }
.farm-reqs { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.ord-req {
    font-size: 0.76rem; padding: 3px 8px; border-radius: 8px;
    background: #f6f7f2; border: 1px solid var(--farm-line, #e3e6dd); color: #6b6f63;
}
.ord-req.ok { background: rgba(108,192,108,.16); border-color: rgba(108,192,108,.45); color: #2f6b2f; }
.farm-item .fr-bar { flex: 1; min-width: 46px; max-width: 130px; margin: 0 6px; }
.farm-item .fr-bar i {
    display: block; height: 7px; border-radius: 6px;
    background: linear-gradient(90deg, #ffce6a, #ffb347);
}

/* ---------------- V2.0：猫助手 / 图鉴 / 升级详情 ---------------- */
.aff-bar { display: inline-block; width: 76px; height: 8px; border-radius: 6px; background: #eee; overflow: hidden; vertical-align: middle; }
.aff-bar i { display: block; height: 100%; background: linear-gradient(90deg, #ffb3c8, #ff7aa8); }
.farm-progress { height: 9px; border-radius: 6px; background: #eee; overflow: hidden; margin: 4px 0 8px; }
.farm-progress i { display: block; height: 100%; background: linear-gradient(90deg, #8fd18f, #5fae5f); }
.farm-grid-sm { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 6px; margin: 4px 0 10px; }
.cat-cell {
    font-size: 0.7rem; text-align: center; padding: 7px 3px; border-radius: 8px;
    background: #f4f5f0; border: 1px solid var(--farm-line, #e3e6dd); color: #b3b7aa;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cat-cell.found { background: rgba(108,192,108,.16); border-color: rgba(108,192,108,.45); color: #2f6b2f; cursor: pointer; }
.cat-cell.found:active { transform: scale(.96); }
/* 图鉴条目「详细介绍」子视图（2026-10-04c） */
.cat-detail-desc { font-size: .9rem; line-height: 1.7; color: #4a4030; background: #fffaf0; border: 1px solid #ecdcb6;
    border-radius: 12px; padding: 12px 14px; margin: 4px 0 12px; }
.cat-detail-desc.cat-detail-empty { color: #9a8f76; background: #f7f4ec; border-style: dashed; }
.cat-detail-fields { display: grid; grid-template-columns: 1fr; gap: 6px; margin: 4px 0 12px; }
.cat-df { display: flex; align-items: baseline; gap: 10px; font-size: .86rem;
    padding: 7px 10px; background: #f5f7ef; border: 1px solid #e3e6dd; border-radius: 9px; }
.cat-df-k { flex: 0 0 56px; color: #8a7d5e; }
.cat-df-v { flex: 1; color: #3a3326; font-weight: 600; }
.cat-rarity { font-size: .72rem; padding: 2px 8px; border-radius: 999px; margin-left: 6px; vertical-align: middle; }
.cat-rarity.r-common { background: #eef0e8; color: #7c8a6a; }
.cat-rarity.r-uncommon { background: #e3eef7; color: #4a7aa8; }
.cat-rarity.r-rare { background: #f6e6ef; color: #b15a8e; }
.farm-levelup .lvup-banner {
    text-align: center; font-size: 1.05rem; padding: 14px 8px; margin: 4px 0 8px;
    background: linear-gradient(90deg, rgba(255,206,106,.25), rgba(108,192,108,.22));
    border-radius: 12px; color: #5a4a2a;
}
.farm-levelup .lvup-banner b { color: #d9822b; }

/* ============================================================
   V2.1 美术表现升级（配合 farm-art.js / farm-scene.js 的 class 钩子）
   土地用途 / 建筑带 / 视觉时代 / 季节色调 / 猫动作 / 砍树动画
   原则：轻微、低频、不吵；全部有 prefers-reduced-motion 守护
   ============================================================ */

/* ---------- ① 土地用途：不看字也能认出来 ---------- */
/* 水田：水纹缓慢漂移 + 微微偏蓝的田框 */
.plot.pt-paddy { border-color: #7fa8b8; }
.plot.pt-paddy .fa-ripple {
    animation: fa-ripple-drift 9s ease-in-out infinite;
}
@keyframes fa-ripple-drift {
    0%, 100% { transform: translateX(-3px); opacity: .4; }
    50%      { transform: translateX(3px);  opacity: .65; }
}

/* 月亮田：星屑极轻闪烁；夜晚整格泛月光 */
.plot.pt-moon { border-color: #6a66a8; }
.plot.pt-moon .fa-moonstars circle { animation: fa-twinkle 4.5s ease-in-out infinite; }
.plot.pt-moon .fa-moonstars circle:nth-child(2n) { animation-delay: 1.4s; }
.plot.pt-moon .fa-moonstars circle:nth-child(3n) { animation-delay: 2.6s; }
@keyframes fa-twinkle { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
.farm-scene.day-night .plot.pt-moon {
    box-shadow: 0 0 14px rgba(150,158,255,.32), inset 0 0 12px rgba(168,176,255,.16);
}
.farm-scene.day-night .plot.pt-moon .fa-moonstars circle { opacity: 1; }

/* 果园：草色田框（树盘草地都在 SVG 里画好了） */
.plot.pt-orchard { border-color: #7ea75f; }

/* ---------- ② 工坊院：买下的加工台长在地图上，错落成小村落 ----------
   不再「尺子对齐」一字排：会自然换行、高低错落、大小不一，
   背后垫一块圆形『院坝地坪』，整组像散落在田头上的一处村舍。
   仍保留 .farm-buildings / .fbuilding / .fb-art 类名，
   ambient() / collectFx() 的取数逻辑不受影响。 */
.farm-buildings {
    position: relative;                 /* 给 ::before 院坝地坪做定位上下文 */
    display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-end;
    gap: clamp(8px, 2vw, 22px) clamp(10px, 2.4vw, 26px);
    /* margin-top 由 JS 量 HUD 底边写入（--yard-clear）：
       窄屏 HUD 换行变高，院子必须从它下方开始，否则第一排被压住。
       margin-bottom 28px：地坪 inset 向上扩 20px + 错落 --ty(+7px)
       + 旋转下探(~4px)，少了这个量名称牌就会被 z-6 的地坪盖住。
       max-width 放宽到 780px：桌面一行能摆下更多建筑，别动不动换第二排。 */
    margin: var(--yard-clear, 8px) auto 28px; max-width: 780px;
    padding: 8px 14px 0;
    pointer-events: none; z-index: 5;
}
/* 院坝地坪：托住整簇村舍的一小块夯土广场（不挡点击，纯装饰） */
.farm-buildings::before {
    content: ''; position: absolute; inset: -6px -10px -2px;
    background: radial-gradient(120% 130% at 50% 18%, #c79a68 0%, #b0824f 68%, #9c6f40 100%);
    border-radius: 40% 44% 46% 42% / 30% 34% 38% 32%;
    border: 3px solid #8d6440;
    box-shadow: inset 0 6px 16px rgba(0, 0, 0, .16), 0 8px 18px rgba(60, 40, 20, .18);
    opacity: .42; z-index: -1; pointer-events: none;
}
.fbuilding {
    pointer-events: auto; position: relative;
    width: clamp(48px, 8vw, 74px);
    border: none; background: none; padding: 0; margin: 0;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
    filter: drop-shadow(0 4px 5px rgba(60, 40, 16, .22));
    /* 错落：用变量叠基础位移 + 轻旋转；hover/active 只改 --ty，旋转保留 */
    transform: translateY(var(--ty, 0px)) rotate(var(--rot, 0deg));
    transition: transform .18s ease;
}
/* 主建筑（磨坊 / 烘焙坊 / 乳制品屋）略大，做出村落的高低节奏 */
.fbuilding.fb-main { width: clamp(58px, 10vw, 92px); }
/* 高低错落：奇偶/三/四/五 错开基线并轻微歪一点，像随手摆的 */
.fbuilding:nth-child(2n) { --ty: -6px;  --rot: -2.5deg; }
.fbuilding:nth-child(3n) { --ty:  5px;  --rot:  2deg; }
.fbuilding:nth-child(4n) { --ty: -3px;  --rot:  3deg; }
.fbuilding:nth-child(5n) { --ty:  7px;  --rot: -1.5deg; }
.fbuilding:hover  { --ty: -9px; }
.fbuilding:active { transform: translateY(0) scale(.95) rotate(var(--rot, 0deg)); }
.fbuilding:focus-visible { outline: 3px solid #ffd66b; outline-offset: 3px; border-radius: 14px; }
.fbuilding .fb-art { width: 100%; height: auto; display: block; }

/* 完成可取（ready）：呼吸光 + 打勾角标，一眼看到「有东西好了」 */
.fbuilding.fb-ready { animation: fb-ready-glow 1.7s ease-in-out infinite; }
@keyframes fb-ready-glow {
    0%, 100% { filter: drop-shadow(0 4px 5px rgba(60, 40, 16, .22)); }
    50%      { filter: drop-shadow(0 4px 10px rgba(255, 196, 72, .7)); }
}
.fb-badge {
    position: absolute; top: -7px; right: -7px;
    width: 22px; height: 22px; border-radius: 50%;
    background: #e8863a; color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 13px; box-shadow: 0 2px 4px rgba(90, 50, 10, .35);
}
.fb-badge svg { width: 13px; height: 13px; }

/* ---------- ②-b 农机带：电动收割机 / 小型播种机（需求 §16 点名的两台批量设备） ----------
   和工坊院同一套排布规则（会换行、错落、有地坪），只是「干活的方式」不同：
   工坊是站着不动等取货，农机是**开出去一趟再回来**，所以有 drive/harvest/plant 的往返动画。
   ★ 这些 class 只管好看：业务在点击那一刻已经算完并存档了，动画播完不会回写任何数据。 */
.farm-devices {
    position: relative;
    display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-end;
    gap: clamp(10px, 2.4vw, 26px);
    margin: 8px auto 28px; max-width: 560px;
    pointer-events: none; z-index: 5;
}
.farm-devices::before {
    content: ''; position: absolute; inset: -6px -10px -2px;
    background: radial-gradient(120% 130% at 50% 30%, #b9c9d6 0%, #a3b6c6 66%, #8fa3b4 100%);
    border-radius: 46% 42% 40% 44% / 30% 34% 36% 32%;
    border: 3px solid #7d8fa0;
    box-shadow: inset 0 6px 16px rgba(0, 0, 0, .14), 0 8px 18px rgba(60, 40, 20, .16);
    opacity: .30; z-index: -1; pointer-events: none;
}
.fdevice {
    pointer-events: auto; position: relative;
    width: clamp(52px, 9vw, 80px);
    border: none; background: none; padding: 0; margin: 0;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
    filter: drop-shadow(0 4px 5px rgba(40, 40, 50, .26));
    transform: translateY(var(--ty, 0px)) rotate(var(--rot, 0deg));
    transition: transform .18s ease;
}
.fdevice:nth-child(2n) { --ty: -5px; --rot: -2deg; }
.fdevice:nth-child(3n) { --ty:  4px; --rot: 1.8deg; }
.fdevice:hover  { --ty: -8px; }
.fdevice:active { transform: translateY(0) scale(.95) rotate(var(--rot, 0deg)); }
.fdevice:focus-visible { outline: 3px solid #ffd66b; outline-offset: 3px; border-radius: 14px; }
.fdevice .fb-art { width: 100%; height: auto; display: block; }
.fdevice .fb-label { background: rgba(246,250,255,.94); border-color: rgba(90,110,130,.55); }

/* idle：原地待机，轻微起伏说明「它是活的」 */
.fdevice.fd-idle      { animation: fd-idle-bob 3.4s ease-in-out infinite; }
@keyframes fd-idle-bob {
    0%, 100% { transform: translateY(var(--ty, 0px)) rotate(var(--rot, 0deg)); }
    50%      { transform: translateY(calc(var(--ty, 0px) - 3px)) rotate(calc(var(--rot, 0deg) + .6deg)); }
}
/* 出发：开出画面边缘（视觉上离开地块区） */
.fdevice.fd-drive     { animation: fd-drive .72s ease-in both; }
@keyframes fd-drive {
    0%   { transform: translate(0, var(--ty, 0px)) rotate(var(--rot, 0deg)); opacity: 1; }
    70%  { transform: translate(46px, calc(var(--ty, 0px) - 10px)) rotate(4deg); opacity: .9; }
    100% { transform: translate(70px, calc(var(--ty, 0px) - 16px)) rotate(6deg); opacity: 0; }
}
/* 收割：横扫一遍（对应「批量」这个动作） */
.fdevice.fd-harvest   { animation: fd-sweep .9s ease-in-out both; }
@keyframes fd-sweep {
    0%   { transform: translate(70px, calc(var(--ty, 0px) - 16px)) rotate(6deg) scale(.9); opacity: 0; }
    25%  { transform: translate(-24px, calc(var(--ty, 0px) - 2px)) rotate(-5deg) scale(1.04); opacity: 1; }
    75%  { transform: translate(24px, var(--ty, 0px)) rotate(5deg) scale(1.04); opacity: 1; }
    100% { transform: translate(0, var(--ty, 0px)) rotate(var(--rot, 0deg)) scale(1); opacity: 1; }
}
/* 播种：撒种的小抖动 */
.fdevice.fd-plant     { animation: fd-scatter .9s ease-in-out both; }
@keyframes fd-scatter {
    0%   { transform: translate(70px, calc(var(--ty, 0px) - 16px)) rotate(6deg) scale(.9); opacity: 0; }
    30%  { transform: translate(-20px, calc(var(--ty, 0px) - 4px)) rotate(-6deg) scale(1.03); opacity: 1; }
    60%  { transform: translate(0, calc(var(--ty, 0px) + 6px)) rotate(0deg) scale(1.03); opacity: 1; }
    100% { transform: translate(0, var(--ty, 0px)) rotate(var(--rot, 0deg)) scale(1); opacity: 1; }
}
/* 机器内部件：干活时转起来 */
.fdevice.fd-working .fd-rotor  { animation: fd-spin .55s linear infinite; }
.fdevice.fd-working .fd-drum   { animation: fd-bob .5s ease-in-out infinite; }
.fdevice.fd-working .fd-seeds  { animation: fd-pop-up 1s ease-in-out infinite; }
.fdevice.fd-working .fd-arm    { animation: fd-wave .8s ease-in-out infinite; }
/* 收工：抬手回程（与 fd-drive 反向） */
.fdevice.fd-return    { animation: fd-return-back .7s ease-out both; }
@keyframes fd-return-back {
    0%   { transform: translate(-30px, calc(var(--ty, 0px) + 8px)) rotate(-5deg) scale(.94); opacity: .9; }
    100% { transform: translate(0, var(--ty, 0px)) rotate(var(--rot, 0deg)) scale(1); opacity: 1; }
}

/* 院子里每个工坊的名字小木牌（一眼看清是哪一坊） */
.fb-label {
    display: block; text-align: center; margin-top: 1px;
    font: 600 clamp(9px, 2.2vw, 12px)/1.1 'PingFang SC','Microsoft YaHei',sans-serif;
    color: #4f3a1e; background: rgba(255,247,228,.92);
    border: 1px solid rgba(120,80,40,.55); border-radius: 7px;
    padding: 1px 6px; box-shadow: 0 1px 2px rgba(60,40,16,.28);
    pointer-events: none; white-space: nowrap;
}
/* 单坊专属面板：介绍 + 它自己的配方清单（点地图上的工坊才进这里） */
.fb-detail-head {
    display: flex; gap: 12px; align-items: center;
    background: linear-gradient(180deg, #fff7e6, #ffefd2);
    border: 2px solid #e3c79a; border-radius: 14px;
    padding: 12px 14px; margin-bottom: 10px;
    box-shadow: 0 3px 10px rgba(120,80,30,.12);
}
.fb-detail-art { width: clamp(78px, 20vw, 104px); flex: 0 0 auto; }
.fb-detail-art .fb-art { width: 100%; height: auto; display: block; filter: drop-shadow(0 4px 5px rgba(60,40,16,.22)); }
.fb-detail-meta { min-width: 0; }
.fb-detail-name { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.fb-detail-name b { font-size: 1.12rem; color: #5a3c1c; }
.fb-detail-tag {
    font-size: .72rem; color: #9a6a2c; background: #fbe6c4;
    border: 1px solid #e9c98f; border-radius: 999px; padding: 1px 8px;
}
.fb-intro { margin: 6px 0 0; font-size: .82rem; line-height: 1.55; color: #6b5333; }
.fb-soon {
    background: #fff4dc; border: 1px dashed #d8b572; color: #8a6630;
    border-radius: 10px; padding: 10px 12px; font-size: .82rem; line-height: 1.5;
}

/* ============================================================
   ★ 2026-10-03 加工设施**等级**UI（需求 §四 / §六 / §二十一）
   ------------------------------------------------------------
   原则：等级不能只藏在存档里，玩家要在三个地方看见它
     ① 地图上：.fb-lvtxt（Lv.n 小圆角标，贴在工坊名下）
     ② 单坊面板头：.fb-lvchip（Lv.x / maxLv 大号等级牌）
     ③ 升级卡：.fb-upg —— 「下一级给什么」直接排在按钮上方，
        而不是让玩家去猜（§六「升级必须有感觉」）。
   颜色沿用本项目农场面板的暖木色 + 粉色主色；
   够钱够等级 = .ok 偏绿醒目；任一条不满足 = .lock 灰但**保留文字**
   （不藏掉需要多少金币/多少农场等级）。
   ============================================================ */
.fb-lvtxt {
    font-size: .66rem; font-weight: 700; color: #b4742a;
    background: #ffeccc; border: 1px solid #e9c98f;
    border-radius: 999px; padding: 0 6px; white-space: nowrap;
}
/* 单坊面板头那枚等级牌 */
.fb-lvchip {
    font-size: .74rem; font-weight: 700; color: #fff;
    background: linear-gradient(180deg, #f3a35c, #e07b34);
    border: 1px solid #c4651f; border-radius: 999px; padding: 1px 9px;
    box-shadow: 0 1px 3px rgba(150, 80, 20, .28); white-space: nowrap;
}
/* 当前等级给了什么（一行看完：加速 / 加产 / 槽位 / 配方解锁） */
.fb-lvx { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.fb-lvx .fb-x {
    font-size: .7rem; color: #6b5333; background: #fff6e4;
    border: 1px solid #ecd6ab; border-radius: 999px; padding: 2px 9px;
}
/* 升级卡本体 */
.fb-upg {
    margin: 2px 0 4px; border-radius: 14px; padding: 11px 13px;
    background: linear-gradient(180deg, #fff8ea, #ffefd6);
    border: 2px solid #e6c68f; box-shadow: 0 3px 10px rgba(120, 80, 30, .1);
}
.fb-upg-h {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    font-size: .96rem; font-weight: 700; color: #5a3c1c;
}
.fb-upg-cost { font-size: .84rem; font-weight: 700; color: #c8672f; }
.fb-upg-n { margin-top: 4px; font-size: .8rem; line-height: 1.55; color: #6b5333; }
.fb-upg-list { margin: 6px 0 0; padding-left: 18px; }
.fb-upg-list li { font-size: .78rem; line-height: 1.6; color: #7a6440; }
.fb-upg .farm-actions { grid-template-columns: 1fr; margin-top: 10px; }
.fb-upg.ok {
    border-color: #7fc08a;
    background: linear-gradient(180deg, #f2fbf2, #e6f6e8);
}
.fb-upg.ok .fb-upg-h { color: #3f7a4c; }
.fb-upg.lock { border-color: #ddcdb2; background: #f8f2e6; }
.fb-upg.lock .fb-upg-h { color: #8a7a66; }
/* 满级（大师设施） */
.fb-upg.max {
    text-align: center; color: #8a6315;
    background: linear-gradient(180deg, #fff4d2, #ffe6a6);
    border: 2px solid #e0b45c; box-shadow: 0 3px 10px rgba(150, 110, 30, .16);
}
/* 配方行里的两枚小徽标：用途 / 等级加成 */
.farm-item .fi-use   { display: block; margin-top: 2px; font-size: .7rem;  color: #8a7a66; }
.farm-item .fi-bonus { display: inline; margin-left: 4px; font-size: .7rem; color: #4f8a5c; }

/* 三态的内部动画（组都长在 SVG 里，CSS 只负责动起来） */
.fb-idle .fb-rotor     { animation: fb-spin 15s linear infinite; }
.fb-working .fb-rotor  { animation: fb-spin 2.4s linear infinite; }
.fb-working .fb-smoke circle  { animation: fb-rise 2.4s ease-out infinite; }
.fb-working .fb-steam path    { animation: fb-rise 1.8s ease-out infinite; }
.fb-working .fb-bubbles circle{ animation: fb-pop-up 1.5s ease-in-out infinite; }
.fb-working .fb-churn  { animation: fb-bob 1.1s ease-in-out infinite; }
.fb-working .fb-sway   { animation: fb-sway 2.4s ease-in-out infinite; }
.fb-working .fb-shuttle{ animation: fb-weave 1.2s ease-in-out infinite; }
.fb-working .fb-threads{ animation: fb-shimmer 2.8s ease-in-out infinite; }
.fb-ready  .fb-lamp    { animation: fb-lamp 1.2s steps(1) infinite; }
.fb-ready  .fb-jar,
.fb-ready  .fb-cloth   { animation: fb-pop .45s ease-out both; }
.fb-build              { animation: fb-wobble .55s ease-in-out infinite; }
@keyframes fb-spin { to { transform: rotate(360deg); } }
@keyframes fb-rise {
    0%   { transform: translateY(0);     opacity: .7; }
    100% { transform: translateY(-14px); opacity: 0; }
}
@keyframes fb-pop-up {
    0%   { transform: translateY(0);  opacity: .3; }
    40%  { opacity: .9; }
    100% { transform: translateY(-8px); opacity: .15; }
}
@keyframes fb-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes fb-sway { 0%, 100% { transform: rotate(-4deg); } 50% { transform: rotate(4deg); } }
@keyframes fb-weave {
    0%, 100% { transform: translateX(-9px); }
    50%      { transform: translateX(9px); }
}
@keyframes fb-shimmer { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
@keyframes fb-lamp { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .3; } }

/* ============================================================
   ★ 2026-10-03 外观等级的两枚小动画（需求 §二十二「动画等级」）
   ------------------------------------------------------------
   与 §十 的材料动画同一套做法：SVG 里只留结构，CSS 只管动起来，
   没有 setInterval、没有新粒子。两条都刻意低频（3.2s / 2.6s）。
     .fb-lvflag   Lv≥2 屋檐那面小旗 —— 绕旗杆顶端轻摆（transform-box:fill-box）
     .fb-lvstring Lv5 灯串上的三颗灯 —— 依次错开呼吸式闪（不用 steps，柔和）
   ⚠ 放在 .fb-ready .fb-lamp 之后：Lv5 建筑 ready 时两规则同权重，
     后写的胜出，灯串保持自己的节奏而不是被 ready 的闪烁接管。
   ============================================================ */
.fb-lvflag {
    transform-box: fill-box; transform-origin: left top;
    animation: fb-flagwave 3.2s ease-in-out infinite;
}
.fb-lvstring .fb-lamp { animation: fb-lvblink 2.6s ease-in-out infinite; }
.fb-lvstring .fb-lamp:nth-of-type(2) { animation-delay: .35s; }
.fb-lvstring .fb-lamp:nth-of-type(3) { animation-delay: .7s; }
@keyframes fb-flagwave {
    0%, 100% { transform: rotate(0deg)   skewY(0deg); }
    50%      { transform: rotate(-3deg)  skewY(2deg); }
}
@keyframes fb-lvblink { 0%, 100% { opacity: .78; } 50% { opacity: 1; } }

/* ============================================================
   ★ 2026-10-03 磨坊升级 · 材料差异化动画
   ------------------------------------------------------------
   目标（需求 §十）：不同材料有不同的「正在加工」手感，且要
   「可爱、治愈、轻量、细腻」（需求 §十一）—— 所以只用 3 个
   小圆点 + 每类一条 keyframes，透明度封顶 0.6，绝不铺满屏。
   四种手感：
     powder 面粉/豆粉  —— 浅色粉尘缓缓下沉并横向轻摆（柔和细腻）
     grit   玉米粉/糖  —— 偏黄颗粒直落、跳动更明显（粒感强）
     rice   精米/糯米粉 —— 洁白短粒、快落轻弹（清爽干脆）
     gloss  食用油      —— 透亮金黄、缓缓上浮（油光）
   入料 fb-grain 统一：三点从上往下落进磨盘。
   ⚠ 全部纯 CSS，SVG 只留结构（与本项目既有约定一致，无 JS 定时器）。
   ============================================================ */
.fb-working .fb-grain circle { animation: fb-feed 1.5s ease-in infinite; }
.fb-working .fb-grain circle:nth-child(2) { animation-delay: .34s; }
.fb-working .fb-grain circle:nth-child(3) { animation-delay: .68s; }
@keyframes fb-feed {
    0%   { transform: translateY(-8px) scale(.7);  opacity: 0; }
    28%  { opacity: .9; }
    100% { transform: translateY(12px) scale(1);   opacity: 0; }
}

/* 出料默认按 grit 表现，class 覆盖 */
.fb-working .fb-flour circle { animation: fb-grit 1.35s ease-in infinite; }
.fb-working .fb-flour circle:nth-child(2) { animation-delay: .45s; }
.fb-working .fb-flour circle:nth-child(3) { animation-delay: .9s; }
@keyframes fb-grit {
    0%   { transform: translateY(-6px); opacity: 0; }
    25%  { opacity: .6; }
    100% { transform: translateY(9px);  opacity: 0; }
}

.fb-working .fb-mat-powder circle { animation: fb-powder 2.1s ease-in-out infinite; }
.fb-working .fb-mat-powder circle:nth-child(2) { animation-delay: .7s; }
.fb-working .fb-mat-powder circle:nth-child(3) { animation-delay: 1.4s; }
@keyframes fb-powder {
    0%   { transform: translate(0, -4px) scale(.6);   opacity: 0; }
    30%  { opacity: .5; }
    100% { transform: translate(-4px, 11px) scale(1.15); opacity: 0; }
}

.fb-working .fb-mat-rice circle { animation: fb-rice 1.05s cubic-bezier(.4, .1, .6, .9) infinite; }
.fb-working .fb-mat-rice circle:nth-child(2) { animation-delay: .3s; }
.fb-working .fb-mat-rice circle:nth-child(3) { animation-delay: .62s; }
@keyframes fb-rice {
    0%   { transform: translateY(-9px) scale(.8); opacity: 0; }
    30%  { opacity: .6; }
    70%  { transform: translateY(6px) scale(1); }
    100% { transform: translateY(9px) scale(.95); opacity: 0; }
}

.fb-working .fb-mat-gloss circle { animation: fb-gloss 1.8s ease-out infinite; }
.fb-working .fb-mat-gloss circle:nth-child(2) { animation-delay: .6s; }
.fb-working .fb-mat-gloss circle:nth-child(3) { animation-delay: 1.2s; }
@keyframes fb-gloss {
    0%   { transform: translateY(8px) scale(.7);   opacity: 0; }
    35%  { opacity: .55; }
    100% { transform: translateY(-9px) scale(1.2); opacity: 0; }
}

/* 2026-10-04 自由磨·混合研磨（杂粮粉）：金白两色交错的旋落，区别于单一粉/米 */
.fb-working .fb-mat-mixed circle { animation: fb-mixed 1.9s ease-in-out infinite; }
.fb-working .fb-mat-mixed circle:nth-child(2) { animation-delay: .5s; }
.fb-working .fb-mat-mixed circle:nth-child(3) { animation-delay: 1.0s; }
@keyframes fb-mixed {
    0%   { transform: translate(-3px, -5px) scale(.6);   opacity: 0; }
    30%  { opacity: .55; }
    55%  { transform: translate(3px, 2px) scale(1); }
    100% { transform: translate(-4px, 11px) scale(1.1);  opacity: 0; }
}

/* 尊重「减少动态」偏好：关掉加工粒子，风车照转（信息不丢，只是不晃眼） */
@media (prefers-reduced-motion: reduce) {
    .fb-working .fb-grain circle,
    .fb-working .fb-flour circle,
    .fb-working .fb-mat-powder circle,
    .fb-working .fb-mat-rice circle,
    .fb-working .fb-mat-gloss circle,
    .fb-working .fb-mat-mixed circle { animation: none; opacity: .45; }
}
@keyframes fb-pop {
    0%   { transform: scale(.4); opacity: 0; }
    70%  { transform: scale(1.15); opacity: 1; }
    100% { transform: scale(1); }
}
@keyframes fb-wobble {
    0%, 100% { transform: rotate(-1.6deg) translateY(0); }
    50%      { transform: rotate(1.6deg)  translateY(-2px); }
}

/* ---------- ③ 视觉时代（era-1 ~ era-5）：等级看得见 ---------- */
/* 路：泥路 → 石子路 → 石板路 → 石板+花边 → 庄园石路 */
.farm-deco .deco-path {
    left: 8%; bottom: 0; width: 84%; height: 9%;
    background: linear-gradient(180deg, rgba(150,112,70,.0), rgba(150,112,70,.32));
    border-radius: 50% 50% 0 0 / 90% 90% 0 0;
}
.era-2 .farm-deco .deco-path,
.era-3 .farm-deco .deco-path {
    background:
        radial-gradient(circle at 18% 55%, rgba(190,180,160,.55) 2.5%, transparent 3.4%),
        radial-gradient(circle at 42% 40%, rgba(190,180,160,.5) 2%, transparent 3%),
        radial-gradient(circle at 66% 62%, rgba(190,180,160,.55) 2.6%, transparent 3.5%),
        radial-gradient(circle at 86% 44%, rgba(190,180,160,.5) 2%, transparent 3%),
        linear-gradient(180deg, rgba(120,110,95,.08), rgba(120,110,95,.26));
}
.era-4 .farm-deco .deco-path,
.era-5 .farm-deco .deco-path {
    background:
        radial-gradient(circle at 20% 55%, rgba(210,205,190,.75) 3%, transparent 4%),
        radial-gradient(circle at 50% 42%, rgba(210,205,190,.7) 2.6%, transparent 3.6%),
        radial-gradient(circle at 80% 58%, rgba(210,205,190,.75) 3%, transparent 4%),
        linear-gradient(180deg, rgba(90,88,84,.14), rgba(90,88,84,.3));
    box-shadow: inset 0 2px 0 rgba(255,255,255,.18);
}

/* 夜灯：era-3 起有路灯，夜里亮起来 */
.farm-scene.day-night .deco-lamp svg { filter: drop-shadow(0 0 10px rgba(255, 210, 110, .85)); }
.farm-scene.day-night .deco-lamp .fa-lampdot { opacity: 1; }

/* 大门在 era-5 夜里点灯 */
.farm-scene.day-night.era-5 .deco-gate svg { filter: drop-shadow(0 0 9px rgba(255, 214, 120, .6)); }

/* 升级卡里的时代名 */
.lu-era-name {
    margin-top: 8px; padding: 8px 10px; border-radius: 10px;
    background: rgba(108, 158, 255, .14);
    color: #3c5aa0; font-weight: 700; letter-spacing: .5px;
}

/* ---------- ④ 季节色调（不改天空系统，只给地面/装饰加一层滤镜） ---------- */
.farm-deco, .farm-ground { transition: filter 1.2s ease; }
.season-spring .farm-deco { filter: saturate(1.12) hue-rotate(-4deg); }
.season-summer .farm-deco { filter: saturate(1.18) brightness(1.03); }
.season-autumn .farm-deco { filter: sepia(.22) saturate(1.14) brightness(.97); }
.season-winter .farm-deco { filter: saturate(.55) brightness(1.05); }
.season-autumn .farm-ground { filter: sepia(.16) saturate(1.1); }
.season-winter .farm-ground { filter: saturate(.5) brightness(1.07); }

/* ---------- ⑤ 猫咪动作反馈：谁在干活，一眼看到 ---------- */
.farm-catact {
    position: absolute; z-index: 8; width: 64px;
    pointer-events: none;
    animation: catact-in 1.5s ease forwards;
    filter: drop-shadow(0 3px 4px rgba(50, 34, 14, .3));
}
.farm-catact svg { width: 100%; height: auto; display: block; }
.act-planting  { animation-name: catact-plant; }
.act-watering  { animation-name: catact-water; }
.act-harvesting{ animation-name: catact-harvest; }
@keyframes catact-in {
    0%   { transform: translateY(10px) scale(.6); opacity: 0; }
    18%  { transform: translateY(0)    scale(1);  opacity: 1; }
    78%  { transform: translateY(0)    scale(1);  opacity: 1; }
    100% { transform: translateY(8px)  scale(.85); opacity: 0; }
}
@keyframes catact-plant {
    0%, 18% { transform: translateY(0) scale(1); }
    40%, 56%{ transform: translateY(5px) scale(.96); }   /* 蹲下拍土 */
    78%, 100% { transform: translateY(0) scale(1); }
}
@keyframes catact-water {
    0%, 18% { transform: rotate(0); }
    34%, 62%{ transform: rotate(-7deg); }                /* 倾水壶 */
    78%, 100% { transform: rotate(0); }
}
@keyframes catact-harvest {
    0%, 18% { transform: translateY(0) scale(1); }
    36%     { transform: translateY(-7px) scale(1.05); } /* 伸手一摘 */
    52%     { transform: translateY(0) scale(1); }
    66%     { transform: translateY(-4px) scale(1.03); }
    100%    { transform: translateY(0) scale(1); }
}

/* ---------- ⑥ 砍树：锯 → 晃 → 落屑 → 倒（0.95s，与 chopFx 同步） ---------- */
.plot.chopping { animation: plot-shake .95s ease-in-out both; }
.plot.chopping .plot-art { animation: crop-jolt .95s ease-in-out both; }
@keyframes plot-shake {
    0%, 100% { transform: rotate(0); }
    12% { transform: rotate(-2.4deg); }
    26% { transform: rotate(2.2deg); }
    40% { transform: rotate(-1.8deg); }
    54% { transform: rotate(1.6deg); }
    68% { transform: rotate(-1deg); }
    82% { transform: rotate(.6deg); }
}
@keyframes crop-jolt {
    0%, 78% { transform: translate(0, 0) rotate(0); opacity: 1; }
    86%     { transform: translate(2px, 3px) rotate(1.6deg); }
    100%    { transform: translate(0, 10px) rotate(0); opacity: 0; }  /* 树倒了 */
}

/* ---------- ⑦ 新装饰定位（lamp / bench / windmill / garden / gate / crate / fence） ---------- */
.deco-lamp     { left: 70%; bottom: 27%; width: clamp(26px, 5vw, 42px); }
.deco-bench    { left: 57%; bottom: 5%;  width: clamp(40px, 7.5vw, 66px); }
.deco-windmill { left: 88%; bottom: 40%; width: clamp(56px, 10vw, 96px); }
.deco-garden   { left: 30%; bottom: 20%; width: clamp(44px, 8vw, 74px); }
.deco-gate     { left: 46%; bottom: -1%; width: clamp(60px, 11vw, 100px); z-index: 2; }
.deco-crate    { left: 6%;  bottom: 26%; width: clamp(30px, 6vw, 52px); }
.deco-fence    { left: 40%; bottom: 33%; width: clamp(44px, 8vw, 76px); }
/* 风车叶片慢慢转（era-4 起的常驻低频动画） */
.deco-windmill .fa-rotor { animation: fb-spin 22s linear infinite; }

/* ---------- ⑧ 响应式 ---------- */
@media (max-width: 560px) {
    .farm-buildings { gap: 6px 8px; padding: 9px 10px 2px; max-width: 96%; }
    .fbuilding { width: clamp(44px, 12.5vw, 60px); }
    .fbuilding.fb-main { width: clamp(54px, 15vw, 74px); }
    .farm-catact { width: 50px; }
    .deco-windmill { bottom: 44%; }
}
@media (max-height: 520px) {
    .farm-buildings { padding: 7px 12px 2px; }
    .fbuilding { width: clamp(42px, 8.5vw, 58px); }
    .fbuilding.fb-main { width: clamp(52px, 10vw, 70px); }
}
/* 横屏/矮屏：按可视高度收缩田格宽度，整块田完整可见、全部可点 */
@media (orientation: landscape) and (max-height: 560px) {
    .farm-buildings { gap: 12px; }
    .farm-grid-wrap { max-width: min(900px, calc(100vh - 210px)); }
}
@media (orientation: landscape) and (min-height: 561px) and (max-height: 780px) {
    /* 1280×720 这类笔记本横屏：同样收紧，避免 3 行田格超高 */
    .farm-grid-wrap { max-width: min(900px, calc(100vh - 140px)); }
}

/* ---------- ⑨ 动画克制：尊重系统减少动态设置 ---------- */
@media (prefers-reduced-motion: reduce) {
    .plot.pt-paddy .fa-ripple,
    .plot.pt-moon .fa-moonstars circle,
    .fbuilding.fb-ready,
    .fb-idle .fb-rotor, .fb-working .fb-rotor,
    .fb-working .fb-smoke circle, .fb-working .fb-steam path,
    .fb-working .fb-bubbles circle, .fb-working .fb-churn,
    .fb-working .fb-sway, .fb-working .fb-shuttle, .fb-working .fb-threads,
    .fb-ready .fb-lamp, .fb-ready .fb-jar, .fb-ready .fb-cloth,
    .fdevice.fd-idle, .fdevice.fd-drive, .fdevice.fd-harvest,
    .fdevice.fd-plant, .fdevice.fd-return,
    .fdevice.fd-working .fd-rotor, .fdevice.fd-working .fd-drum,
    .fdevice.fd-working .fd-seeds, .fdevice.fd-working .fd-arm,
    .fb-build, .deco-windmill .fa-rotor,
    .fb-lvflag, .fb-lvstring .fb-lamp,
    .farm-catact, .plot.chopping, .plot.chopping .plot-art {
        animation: none !important;
    }
    /* 关掉动画以后，旗子/灯串要停在**可见**的那一帧：
       fb-flagwave 的中帧是 -3deg 倾斜，静止态回正；灯回满亮度，
       否则会出现「装饰还在、但像是没画完」的观感（§十一 不过度） */
    .fb-lvflag { transform: none; }
    .fb-lvstring .fb-lamp { opacity: 1; }
    .farm-deco, .farm-ground { transition: none; }
}

/* ============================================================
   补遗（验收缺口）：生活感小剧场 + 成熟非持续提示
   ============================================================ */

/* ---------- 生活感小剧场：低频、一次一个、演完即走 ----------
   猫提灯逛月亮田 / 雨靴踩水田 / 坐果树下摘果 / 扛麻袋去工坊 / 打盹。
   纯一次性 CSS 动画（无 JS 逐帧），z 高于作物低于面板，永不挡点击。 */
.farm-ambient {
    position: absolute; z-index: 7;
    width: 58px; pointer-events: none;
    display: flex; flex-direction: column; align-items: center;
    filter: drop-shadow(0 2px 2px rgba(60, 40, 20, 0.20));
}
.farm-ambient svg { width: 100%; height: auto; display: block; }
.farm-ambient .fa-prop { width: 20px; height: 20px; margin-bottom: -7px; position: relative; z-index: 2; }

.amb-rest { animation: amb-in .55s ease both; }
.amb-rest::after {
    content: '💤'; position: absolute; right: -8px; top: -12px;
    font-size: 13px; opacity: 0; animation: amb-zzz 6.5s ease-in-out .9s infinite;
}
.amb-pick { animation: amb-in .55s ease both; }
.amb-pick .fa-prop-basket { animation: amb-bounce 1.9s ease-in-out infinite; }

.amb-carry, .amb-carry-out { animation: amb-walk 6s ease-in-out both; }
.amb-carry-out { animation-duration: 5s; }
.amb-carry .fa-prop-sack, .amb-carry-out .fa-prop-basket { animation: amb-bounce 1.1s ease-in-out infinite; }

.amb-lantern { animation: amb-walk 7.2s ease-in-out both; }
.amb-lantern .fa-prop-lantern {
    animation: amb-glow 2.4s ease-in-out infinite;
    filter: drop-shadow(0 0 5px rgba(255, 214, 120, 0.85));
}

.amb-boots { animation: amb-walk 7.2s ease-in-out both; }
.amb-splash .fa-prop-boots { animation: amb-splash 1.5s ease-in-out infinite; }

@keyframes amb-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
@keyframes amb-walk {
    0%   { opacity: 0; transform: translateX(-44px); }
    9%   { opacity: 1; }
    46%  { transform: translateX(38px); }
    54%  { opacity: 1; transform: translateX(44px); }
    92%  { opacity: .85; transform: translateX(-32px); }
    100% { opacity: 0; transform: translateX(-44px); }
}
@keyframes amb-zzz {
    0%, 12% { opacity: 0; transform: translateY(2px); }
    22%, 55% { opacity: .9; transform: translateY(-6px); }
    70%, 100% { opacity: 0; transform: translateY(-12px); }
}
@keyframes amb-bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-2.5px); }
}
@keyframes amb-glow {
    0%, 100% { opacity: .82; }
    50% { opacity: 1; }
}
@keyframes amb-splash {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-1.5px) rotate(2deg); }
}

/* ---------- 成熟提示：非持续（十九）----------
   4.2s 一个周期里只在前 ~8% 轻轻提亮一次 + 一次小星闪，
   绝不长亮闪烁；点击收获另有 popGain。 */
.plot.ready-badge .plot-art { animation: plot-ripe 4.2s ease-in-out infinite; }
@keyframes plot-ripe {
    0%, 90%, 100% { filter: none; }
    94%, 97% { filter: brightness(1.13) saturate(1.1); }
}
.plot.ready-badge::after {
    content: '✦';
    position: absolute; top: 2px; right: 4px;
    font-size: 13px; color: #ffd76e;
    text-shadow: 0 0 4px rgba(255, 190, 60, .9);
    pointer-events: none;
    opacity: 0; animation: ripe-twinkle 4.2s ease-in-out infinite;
}
@keyframes ripe-twinkle {
    0%, 88%, 100% { opacity: 0; transform: scale(.6) rotate(0deg); }
    93% { opacity: 1; transform: scale(1.15) rotate(18deg); }
    98% { opacity: 0; transform: scale(.7) rotate(30deg); }
}

/* ---------- reduced-motion：小剧场不上演，提示只留徽标 ---------- */
@media (prefers-reduced-motion: reduce) {
    .farm-ambient { display: none; }
    .plot.ready-badge .plot-art { animation: none; }
    .plot.ready-badge::after { animation: none; opacity: .85; transform: none; }
}

/* 窄屏：小剧场猫缩小一号，别抢田格 */
@media (max-width: 560px) {
    .farm-ambient { width: 46px; }
    .farm-ambient .fa-prop { width: 16px; height: 16px; }
}

/* ============================================================
   ⑩ 第二阶段（2026-09-27）：让数据出现在世界里
   ------------------------------------------------------------
   ① 猫实体（雇佣了就得看得见，会走会干活会回来）
   ② 当前装备条（装备了什么一眼看见，点一下换/卸）
   ③ 温室是一座真的玻璃房
   ④ 砍树时手里有链锯
   ⑤ 猫卡片 / 猫浮层（点世界里的实体给小反馈，不弹大面板）
   原则：动画走 CSS，位置走 transform；全场只有一根 tick 改状态。
   ============================================================ */

/* ---------------- ① 农场里的猫 ---------------- */
.farm-cats {
    position: absolute; inset: 0;
    pointer-events: none; z-index: 7;   /* 在作物之上、UI 之下 */
}
.farm-cat {
    position: absolute; left: 0; top: 0;
    width: 62px; height: 62px;
    pointer-events: auto; cursor: pointer;
    transition: transform 1100ms cubic-bezier(.35, .8, .3, 1);
    will-change: transform;
    filter: drop-shadow(0 3px 3px rgba(60, 40, 20, .18));
}
.farm-cat > svg, .farm-cat .fa-npc-wrap, .farm-cat .rs-cat-svg {
    width: 100%; height: 100%; display: block;
}
.farm-cat .cat-name {
    position: absolute; left: 50%; bottom: -6px; transform: translateX(-50%);
    font-size: .64rem; line-height: 1; padding: 2px 5px; border-radius: 7px;
    background: rgba(255, 252, 244, .88); color: #6b5535;
    border: 1px solid rgba(122, 96, 58, .35); white-space: nowrap;
}
.farm-cat .cat-doing {
    position: absolute; left: 50%; top: -10px; transform: translateX(-50%);
    font-size: .6rem; line-height: 1; padding: 2px 6px; border-radius: 8px;
    background: #ffe9a8; color: #7a5a18; border: 1px solid rgba(160, 120, 40, .4);
    white-space: nowrap; opacity: 0; transition: opacity .25s ease;
}
.farm-cat.busy .cat-doing { opacity: 1; }
.farm-cat.flip > svg, .farm-cat.flip .fa-npc-wrap { transform: scaleX(-1); }

/* 状态：走路上下颠，干活各有各的小动作，休息慢慢呼吸 */
.farm-cat.st-WALKING { animation: cat-bob .42s ease-in-out infinite; }
.farm-cat.st-HARVESTING { animation: cat-work .5s ease-in-out infinite; }
.farm-cat.st-WATERING { animation: cat-tilt 1.1s ease-in-out infinite; }
.farm-cat.st-PLANTING { animation: cat-work .62s ease-in-out infinite; }
.farm-cat.st-CARRYING { animation: cat-bob .56s ease-in-out infinite; }
.farm-cat.st-CELEBRATING { animation: cat-jump .6s ease-in-out 3; }
.farm-cat.st-RESTING { animation: cat-breathe 3s ease-in-out infinite; }
@keyframes cat-bob { 0%, 100% { margin-top: 0; } 50% { margin-top: -3px; } }
@keyframes cat-work { 0%, 100% { rotate: 0deg; } 35% { rotate: -6deg; } 70% { rotate: 5deg; } }
@keyframes cat-tilt { 0%, 100% { rotate: 0deg; } 50% { rotate: -8deg; } }
@keyframes cat-jump { 0%, 100% { margin-top: 0; } 40% { margin-top: -12px; } }
@keyframes cat-breathe { 0%, 100% { scale: 1; } 50% { scale: 1.03; } }
/* 定位（面板里点「查看」）：亮一下圈 */
.farm-cat.locate::after {
    content: ''; position: absolute; left: 50%; top: 55%; width: 74px; height: 74px;
    margin: -37px 0 0 -37px; border-radius: 50%;
    border: 3px solid #ffc94d; box-shadow: 0 0 0 6px rgba(255, 201, 77, .22);
    animation: cat-locate 1.8s ease-out 1 forwards; pointer-events: none;
}
@keyframes cat-locate {
    0% { transform: scale(.5); opacity: 0; }
    25% { transform: scale(1); opacity: 1; }
    100% { transform: scale(1.25); opacity: 0; }
}

/* 点猫弹的小浮层（不是大面板） */
.farm-catcard {
    position: absolute; z-index: 9; transform: translate(-50%, -100%);
    display: flex; gap: 8px; align-items: center;
    padding: 8px 10px; border-radius: 14px;
    background: rgba(255, 253, 246, .96); border: 2px solid rgba(122, 96, 58, .3);
    box-shadow: 0 8px 18px rgba(80, 60, 30, .2); pointer-events: auto;
    min-width: 168px; animation: cc-in .22s ease-out;
}
@keyframes cc-in { from { opacity: 0; transform: translate(-50%, -92%); } to { opacity: 1; } }
.farm-catcard .cc-art { width: 46px; height: 46px; flex: 0 0 auto; }
.farm-catcard .cc-art svg { width: 100%; height: 100%; display: block; }
.farm-catcard .cc-main { display: flex; flex-direction: column; gap: 2px; }
.farm-catcard .cc-main b { font-size: .92rem; color: #5b4526; }
.farm-catcard .cc-sub { font-size: .72rem; color: #8a7048; }
.farm-catcard .cc-doing { font-size: .72rem; color: #b07a1e; }
.farm-catcard .cc-close {
    position: absolute; right: 4px; top: 4px;
    border: none; background: none; cursor: pointer;
    font-size: .8rem; color: #9a8a6a;
}

/* ---------------- ② 当前装备条 ---------------- */
.farm-toolbar {
    position: absolute; left: 0; right: 0; bottom: 0;
    display: flex; gap: 6px; align-items: center;
    padding: 5px 8px; overflow-x: auto; overflow-y: hidden;
    background: linear-gradient(180deg, rgba(255, 250, 238, 0), rgba(255, 250, 238, .94) 42%);
    z-index: 30; scrollbar-width: none;
    /* 紧贴 dock 上沿（dock 高度由 JS 量出来写进 --dock-h），不用 transform 乱挪 */
    bottom: calc(var(--sa-bottom) + var(--dock-h, 62px) + 12px);
    -webkit-overflow-scrolling: touch;
}
.farm-toolbar::-webkit-scrollbar { display: none; }
.farm-toolbar.empty { pointer-events: none; }
.farm-toolbar .tb-empty {
    font-size: .72rem; color: #8a7048; background: rgba(255, 252, 244, .8);
    padding: 3px 8px; border-radius: 10px; margin: 0 auto;
}
.tb-item {
    flex: 0 0 auto; display: flex; align-items: center; gap: 4px;
    padding: 4px 9px 4px 6px; border-radius: 999px;
    border: 2px solid rgba(122, 96, 58, .28); background: #fffdf6;
    cursor: pointer; min-height: 34px; transition: transform .12s ease, border-color .2s ease;
}
.tb-item.on {
    border-color: #f2b13c; background: linear-gradient(180deg, #fff6dd, #ffe9b8);
    box-shadow: 0 2px 6px rgba(180, 130, 40, .25);
}
.tb-item:active { transform: scale(.94); }
.tb-item .tb-ico { width: 20px; height: 20px; display: block; }
.tb-item .tb-name { font-size: .74rem; color: #6b5535; white-space: nowrap; }
/* dock 内的同一份装备 chips：默认不显示，只有矮横屏才启用（见下方 max-height 媒体查询）。
   两条路共用 JS 的一份数据，CSS 二选一，避免矮屏为了一条 bar 把地图压扁。 */
.dock-tools { display: none; }

/* ---------------- ③ 温室（真的玻璃房） ---------------- */
.farm-gh { position: absolute; inset: 0; pointer-events: none; z-index: 6; }
.gh-house { position: absolute; }
.gh-house svg { width: 100%; height: 100%; display: block; }

/* ---------------- ④ 砍树：手里的链锯 ---------------- */
.farm-saw {
    position: absolute; width: 54px; height: 54px; z-index: 8;
    pointer-events: none; animation: saw-work .45s ease-in-out 3;
}
.farm-saw .saw-svg { width: 100%; height: 100%; display: block; }
@keyframes saw-work {
    0% { transform: translateX(10px) rotate(-16deg); opacity: 0; }
    25% { transform: translateX(0) rotate(0deg); opacity: 1; }
    60% { transform: translateX(-3px) rotate(-10deg); }
    100% { transform: translateX(6px) rotate(4deg); opacity: .9; }
}

/* ---------------- ⑤ 雇佣面板：猫卡片 ---------------- */
.cat-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: 10px;
}
.cat-card {
    border: 2px solid rgba(122, 96, 58, .22); border-radius: 16px;
    background: #fffdf6; padding: 10px 10px 8px; text-align: center;
    box-shadow: 0 4px 10px rgba(90, 70, 40, .1);
}
.cat-card.on { border-color: #f2b13c; background: linear-gradient(180deg, #fffaf0, #fff2dc); }
.cat-card.locked { opacity: .62; }
.cat-card .cc-art { width: 78px; height: 78px; margin: 0 auto 4px; }
.cat-card .cc-art svg { width: 100%; height: 100%; display: block; }
.cat-card .cc-name { font-weight: 700; color: #5b4526; font-size: .95rem; }
.cat-card .cc-outfit {
    display: inline-block; font-size: .68rem; color: #8a7048; margin: 2px 0 6px;
    padding: 1px 8px; border-radius: 999px; background: rgba(180, 210, 170, .28);
}
.cat-card .cc-skill { display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; }
.cat-card .cc-skill span {
    font-size: .7rem; padding: 2px 7px; border-radius: 8px;
    background: rgba(242, 193, 78, .22); color: #8a5f16;
}
.cat-card .cc-state { font-size: .74rem; color: #8a7048; margin: 6px 0 2px; }
.cat-card .cc-state.working { color: #4f7a3a; }
.cat-card .cc-foot {
    display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 4px;
}
.cat-card .cc-aff { font-size: .72rem; color: #8a7048; }
.cat-card .aff-bar {
    display: block; height: 5px; border-radius: 3px; background: rgba(122, 96, 58, .16);
    margin-top: 5px; overflow: hidden;
}
.cat-card .aff-bar i { display: block; height: 100%; background: #f2b13c; border-radius: 3px; }

/* ---------------- 窄屏：猫小一号、装备条更紧 ---------------- */
@media (max-width: 560px) {
    .farm-cat { width: 50px; height: 50px; }
    .cat-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
    /* 触屏点击区：装备 chip 抬到 40px（苹果/安卓的最小值 44 差一点，但再高就压地图了） */
    .tb-item { min-height: 40px; padding: 4px 10px 4px 7px; }
    .tb-item .tb-name { font-size: .68rem; }
}
@media (max-height: 420px) {
    .farm-cat { width: 44px; height: 44px; }
    .farm-toolbar { padding: 3px 6px; }
    /* ★ 矮横屏：院坝/农机带不许再竖着堆——各收成一行、横向滚，
       高度砍半以上，把可视区还给田地（否则 267px 里两条带吃掉 200+px）。
       ★ flex-shrink:0 必须加：board 是列 flex，overflow-x:auto 会把
       「自动最小尺寸」清零，两条带作为子项被压扁成几像素（内容 71px、
       容器 9px 的怪相就是这个根因）。 */
    .farm-buildings, .farm-devices {
        flex: 0 0 auto;
        flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start;
        max-width: calc(100vw - 20px);
        scrollbar-width: none;
        margin-bottom: 14px;
    }
    .farm-buildings::-webkit-scrollbar, .farm-devices::-webkit-scrollbar { display: none; }
    .fbuilding { width: 48px; }
    .fbuilding.fb-main { width: 56px; }
    .fdevice { width: 52px; }
    .fb-label { font-size: .58rem; padding: 1px 6px; }
}

/* ---------------- reduced-motion：猫站着不动，但仍然看得见 ---------------- */
@media (prefers-reduced-motion: reduce) {
    .farm-cat.st-WALKING, .farm-cat.st-HARVESTING, .farm-cat.st-WATERING,
    .farm-cat.st-PLANTING, .farm-cat.st-CARRYING, .farm-cat.st-CELEBRATING,
    .farm-cat.st-RESTING { animation: none; }
    .farm-saw { animation: none; opacity: .95; }
    .farm-catcard { animation: none; }
}

/* ============================================================
   P1（2026-09-28）：从「格子系统」往「一块田」再走一步
   土地质感 / 果树成树 / 升级反馈 / 建筑小浮层 / dock 精简
   原则不变：动画是演出不是数据源；全部有 reduced-motion 守护
   ============================================================ */

/* ---------- ① 水田：会活的一汪水 ----------
   光带缓慢漂 + 鱼影摆尾（都是几秒一次的 CSS 动画，不抢戏） */
.plot.pt-paddy .fa-waterglint {
    animation: fa-waterglint 8s ease-in-out infinite;
    transform-box: fill-box; transform-origin: center;
}
@keyframes fa-waterglint {
    0%, 100% { transform: translateY(-3px) scaleX(.96); opacity: .07; }
    50% { transform: translateY(4px) scaleX(1.04); opacity: .16; }
}
.plot.pt-paddy .fa-fish {
    animation: fa-fish 11s ease-in-out infinite;
    transform-box: fill-box; transform-origin: center;
}
@keyframes fa-fish {
    0%, 100% { transform: translate(0, 0); }
    30% { transform: translate(9px, 2px); }
    55% { transform: translate(-7px, -2px); }
    80% { transform: translate(4px, 1px); }
}

/* ---------- ② 月田：夜里才点亮的萤火虫 ----------
   白天几乎看不见（opacity .15），入夜场景挂 day-night 后亮起来。
   每块地只 2 只、7s 一轮，几十块月田也只是几十个合成器动画。 */
.plot.pt-moon .fa-firefly circle { opacity: .15; }
.plot.pt-moon .fa-firefly circle:first-child { animation: fa-fly-1 7s ease-in-out infinite; }
.plot.pt-moon .fa-firefly circle:last-child { animation: fa-fly-2 9s ease-in-out infinite; }
.farm-scene.day-night .plot.pt-moon .fa-firefly circle { opacity: .95; }
.farm-scene.day-night .plot.pt-moon .fa-glowplant { filter: drop-shadow(0 0 4px rgba(143, 216, 168, .8)); }
@keyframes fa-fly-1 {
    0%, 100% { transform: translate(0, 0); opacity: .5; }
    25% { transform: translate(8px, -6px); opacity: 1; }
    50% { transform: translate(-6px, 4px); opacity: .55; }
    75% { transform: translate(5px, 6px); opacity: 1; }
}
@keyframes fa-fly-2 {
    0%, 100% { transform: translate(0, 0); opacity: .6; }
    40% { transform: translate(-9px, 5px); opacity: 1; }
    70% { transform: translate(7px, -5px); opacity: .5; }
}

/* ---------- ③ 升级瞬间：镜头轻拉（约 1.2s，不过场） ---------- */
.farm-grid-wrap.lv-pulse { animation: lv-pulse 1.25s cubic-bezier(.3, .7, .3, 1) 1; }
@keyframes lv-pulse {
    0% { transform: scale(1); }
    35% { transform: scale(.955); }
    100% { transform: scale(1); }
}

/* ---------- ④ 建筑小浮层：先给一眼答案，再给操作 ---------- */
.farm-bldcard {
    position: absolute; z-index: 31;
    display: flex; align-items: center; gap: 8px;
    padding: 8px 10px; border-radius: 14px;
    background: rgba(255, 252, 244, .96); border: 2px solid #d9c39c;
    box-shadow: 0 6px 14px rgba(90, 60, 30, .22);
    transform: translate(-50%, -100%);
    animation: cc-in .18s ease both;
    /* 任意分辨率不被裁：最宽不超过视口宽（JS 侧 placeCard 还会做可视区钳制） */
    max-width: min(230px, calc(100vw - 20px));
}
.farm-bldcard .bc-art { width: 44px; height: 44px; flex: 0 0 auto; }
.farm-bldcard .bc-art svg { width: 100%; height: 100%; display: block; }
.farm-bldcard .bc-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.farm-bldcard .bc-main b { font-size: .82rem; color: #5b4526; white-space: nowrap; }
.farm-bldcard .bc-state { font-size: .7rem; color: #8a7048; white-space: nowrap; }
/* 极窄屏兜底：标题/状态文字超宽时省略号，不撑破卡片 */
.farm-bldcard .bc-main b,
.farm-bldcard .bc-state { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.farm-bldcard .bc-state.working { color: #b07a1e; }
.farm-bldcard .bc-state.ready { color: #4f7a3a; font-weight: 700; }
.farm-bldcard .bc-open {
    flex: 0 0 auto; border: 2px solid #e0a83a; border-radius: 10px;
    background: linear-gradient(180deg, #fff6dd, #ffe9b8);
    color: #6b4a14; font-size: .74rem; padding: 5px 10px; cursor: pointer;
    font-family: inherit;
}
.farm-bldcard .bc-open:active { transform: scale(.94); }

/* ---------- ⑤ dock「更多」面板 ---------- */
.more-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 10px; padding: 4px 2px 8px;
    /* 模态 body 是 flex 列：不给宽度的话 auto-fill 网格会缩成一列 */
    width: 100%;
}
.more-btn {
    position: relative; display: flex; flex-direction: column; align-items: center; gap: 5px;
    padding: 12px 6px 10px; border-radius: 14px; cursor: pointer;
    border: 2px solid #cbb48f; background: rgba(255, 253, 246, .9);
    color: #5d4a33; font-size: .78rem; font-family: inherit;
    transition: transform .12s ease, background .2s ease;
}
.more-btn .fa-i, .more-btn > svg { width: 22px; height: 22px; font-size: 1.2rem; }
.more-btn:active { transform: scale(.94); }
.more-btn.hot { background: linear-gradient(180deg, #fff6dd, #ffe9b8); border-color: #e0a83a; }

/* ---------- ⑥ dock：移动端两行，点击区 ≥44px ---------- */
@media (max-width: 560px) {
    .farm-dock {
        flex-wrap: wrap; justify-content: center;
        /* ★ 绝对定位 + left:50% 的可用宽度只有右半屏（wrap 后一行只装得下 2 个），
           必须显式给全宽，否则「两行」会退化成「五行」。 */
        left: 8px; right: auto; transform: none;
        width: calc(100vw - 16px); max-width: calc(100vw - 16px);
        row-gap: 5px; gap: 4px; padding: 5px 6px;
    }
    .farm-dock .dock-btn { min-width: 44px; min-height: 44px; padding: 3px 5px; }
    .farm-dock .dock-btn .dk-t { font-size: 0.58rem; }
}
/* 矮横屏仍保持单行滚动（高度寸土寸金，两行会把田压没了） */
@media (max-height: 520px) {
    .farm-dock { flex-wrap: nowrap; }
}

/* ---------- ⑦ reduced-motion：全关 ---------- */
@media (prefers-reduced-motion: reduce) {
    .plot.pt-paddy .fa-waterglint, .plot.pt-paddy .fa-fish,
    .plot.pt-moon .fa-firefly circle,
    .plot.pt-orchard .plot-art,
    .farm-grid-wrap.lv-pulse,
    .farm-bldcard { animation: none !important; }
    .farm-bldcard { opacity: 1; }
}

/* ============================================================
   ⑪ 第三阶段 P2（2026-09-28）：地块小浮层 / 登场动画 / 时长分级
   ============================================================ */
/* ---- 地块小浮层：复用建筑浮层（.farm-bldcard）的壳，只补按钮排 ---- */
/* ★ 两行排（2026-10-01 遮挡修复）：单行硬塞「图标+文字+两个按钮」会把
   「第 X 块地」挤到只剩省略号 —— 第一行 图标+文字独占，第二行 按钮整行 */
.farm-plotcard { max-width: min(250px, calc(100vw - 20px)); flex-wrap: wrap; }
.farm-plotcard .bc-main { flex: 1 1 0; min-width: 0; }
.farm-plotcard .pc-btns {
    display: flex; gap: 6px;
    flex: 1 1 100%;                  /* 按钮独占第二行，不和标题抢宽度 */
    justify-content: flex-start;
    padding-top: 2px;
}
.farm-plotcard .pc-btn {
    border: 2px solid #cbb48f; border-radius: 10px;
    background: rgba(255, 253, 246, .9);
    color: #5d4a33; font-size: .74rem; padding: 5px 9px; cursor: pointer;
    font-family: inherit; white-space: nowrap;
    transition: transform .12s ease;
}
.farm-plotcard .pc-btn:active { transform: scale(.94); }
.farm-plotcard .pc-btn.primary {
    border-color: #e0a83a; background: linear-gradient(180deg, #fff6dd, #ffe9b8);
    color: #6b4a14; font-weight: 700;
}
.farm-plotcard .pc-wet, .farm-plotcard .pc-dry { font-size: .68rem; white-space: nowrap; }
.farm-plotcard .pc-wet { color: #4f7a3a; }
.farm-plotcard .pc-dry { color: #c26a2e; font-weight: 700; }
.farm-bldcard .bc-state.bad { color: #a05a3a; }

/* ---- 登场动画（§29：建筑/设备登场 300~600ms）----
   设备买下时从地里「冒出来」；温室新盖时从 0.6 长到 1。只播一次。 */
.fdevice.fd-in { animation: fd-in .42s cubic-bezier(.3, 1.3, .5, 1) both; }
@keyframes fd-in {
    from { opacity: 0; transform: translateY(14px) scale(.55) rotate(var(--rot, 0deg)); }
    to   { opacity: 1; transform: translateY(var(--ty, 0px)) scale(1) rotate(var(--rot, 0deg)); }
}
.gh-house.gh-in { animation: gh-in .5s cubic-bezier(.3, 1.2, .5, 1) both; transform-origin: 50% 100%; }
@keyframes gh-in {
    from { opacity: 0; transform: scale(.6); }
    to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .fdevice.fd-in, .gh-house.gh-in { animation: none; opacity: 1; }
}

/* ============================================================
   ⑫ 种子商店子分类 + 种植面板排序分隔线（2026-09-28）
   ============================================================ */
.farm-subtabs {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin: 6px 0 2px;
}
.farm-subtabs button {
    font-size: .72rem; padding: 4px 10px;
    border-radius: 999px; border: 2px solid #d8c5a2;
    background: rgba(255, 252, 244, .85); color: #6b5535;
    cursor: pointer; font-family: inherit;
    transition: transform .12s ease;
}
.farm-subtabs button:active { transform: scale(.94); }
.farm-subtabs button.on {
    border-color: #e0a83a; background: linear-gradient(180deg, #fff6dd, #ffe9b8);
    font-weight: 700; color: #6b4a14;
}
.farm-subtabs .tab-n { opacity: .55; font-size: .68rem; }
/* 种植面板排序分隔线：细线 + 小字，不打断浏览 */
.farm-note.pc-divider {
    border-top: 1px dashed #d8c5a2;
    padding-top: 8px; margin-top: 4px;
    font-size: .68rem; opacity: .8;
}

/* ============================================================
   手机端：面板内的分类/子标签抬高到 40px
   ------------------------------------------------------------
   桌面 36px 够了，但手机上 36px 仍是「贴着指尖」的尺寸，
   一排 5 个分类（全部/农田/果树…）连着排时容易点错隔壁。
   ============================================================ */
@media (max-width: 560px) {
    .farm-tabs button { min-height: 40px; padding: 8px 14px; }
    .farm-subtabs button { min-height: 36px; padding: 6px 12px; font-size: .76rem; }
}

/* ============================================================
   2026-10-04 磨坊「自由磨」面板（需求 §二）
   与既有加工面板同色系（暖米 / 木棕 / 小麦黄），手机端不横向溢出。
   ============================================================ */
.fm-tabs { display: flex; gap: 8px; margin: 10px 0 4px; }
.fm-tab {
    flex: 1; min-height: 38px; border: 1px solid #e2d2ad; background: #fff8e8;
    border-radius: 10px; font-size: .9rem; color: #6b4a14; cursor: pointer;
}
.fm-tab.on { background: #f0a830; border-color: #e0922a; color: #3a2607; font-weight: 700; }
.fm-wrap { margin-top: 6px; }
.fm-tip { font-size: .78rem; color: #7a6a44; background: #fff6df; border: 1px dashed #e6cf87; border-radius: 10px; padding: 8px 10px; margin: 8px 0; }
.fm-label { font-size: .74rem; color: #8a7649; margin-right: 6px; }
.fm-modes { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.fm-mode {
    min-height: 36px; padding: 6px 12px; border: 1px solid #e2d2ad; background: #fff;
    border-radius: 18px; font-size: .84rem; color: #6b4a14; cursor: pointer;
}
.fm-mode.on { background: #f6c453; border-color: #e0a82a; font-weight: 700; }
.fm-mode.lock { opacity: .5; cursor: not-allowed; }
.fm-mode.lock i { font-style: normal; font-size: .7rem; margin-left: 4px; color: #b08a3a; }
.fm-mats { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 8px; margin: 8px 0; }
.fm-mat {
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 8px 4px; border: 1px solid #e6d6b0; background: #fffdf6;
    border-radius: 12px; cursor: pointer; color: #5a4a28;
}
.fm-mat-ico { font-size: 1.5rem; line-height: 1; }
.fm-mat b { font-size: .8rem; font-weight: 600; }
.fm-mat i { font-style: normal; font-size: .7rem; color: #9a8a5a; }
.fm-mat.on { background: #f6c453; border-color: #e0a82a; box-shadow: 0 2px 6px rgba(224,168,42,.3); }
.fm-mat.dis { opacity: .4; cursor: not-allowed; }
.fm-dirs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0; }
.fm-dir {
    min-height: 34px; padding: 5px 12px; border: 1px solid #e2d2ad; background: #fff;
    border-radius: 16px; font-size: .8rem; color: #6b4a14; cursor: pointer;
}
.fm-dir.on { background: #8fd0a0; border-color: #5fae78; font-weight: 700; color: #234a30; }
.fm-dir.lock { opacity: .5; cursor: not-allowed; }
.fm-hint { font-size: .78rem; color: #8a7649; background: #f3f7ee; border: 1px dashed #cfe0c2; border-radius: 10px; padding: 8px 10px; margin: 8px 0; }
.fm-qty { display: flex; align-items: center; gap: 10px; margin: 10px 0; }
.fm-step {
    width: 34px; height: 34px; border: 1px solid #e2d2ad; background: #fff; border-radius: 10px;
    font-size: 1.1rem; color: #6b4a14; cursor: pointer;
}
.fm-qty b { min-width: 28px; text-align: center; font-size: 1.05rem; color: #3a2607; }
.fm-qty i { font-style: normal; font-size: .72rem; color: #9a8a5a; }
.fm-preview {
    background: #fffaf0; border: 1px solid #ecdcb6; border-radius: 12px; padding: 10px 12px; margin: 8px 0;
}
.fm-pv { font-size: .84rem; color: #5a4a28; line-height: 1.6; }
.fm-pv.ok { color: #2f7d4f; font-weight: 600; }
.fm-pv.warn { color: #b5712a; }
.fm-preview .fm-pv + .fm-pv { margin-top: 4px; }


/* ============================================================
   2026-10-04b 自由磨 v2：投料步进列表 / 配方图鉴 / 发现徽标
   ============================================================ */
.fm-qtylist { display: flex; flex-direction: column; gap: 2px; margin: 8px 0; }
.fm-qtylist .fm-qty {
    background: #fffaf0; border: 1px solid #ecdcb6; border-radius: 10px;
    padding: 6px 10px; margin: 0; justify-content: space-between;
}
.fm-qtylist .fm-qty .fm-label { min-width: 88px; font-size: .84rem; color: #3a2607; font-weight: 600; }
.fm-qtylist .fm-qty .fm-label i { margin-left: 6px; }
.fm-pv.new { color: #8a5a9e; font-weight: 600; }
.fm-progress {
    font-size: .86rem; color: #5a4a28; background: #f3f7ee; border: 1px solid #cfe0c2;
    border-radius: 10px; padding: 7px 12px; margin: 8px 0;
}
.fm-progress b { color: #2f7d4f; font-size: 1.05rem; }
.fm-cx {
    background: #fffaf0; border: 1px solid #ecdcb6; border-radius: 12px;
    padding: 9px 12px; margin: 8px 0;
}
.fm-cx.un { background: #f7f4ec; border-style: dashed; opacity: .92; }
.fm-cx-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.fm-cx-h b { font-size: .95rem; color: #3a2607; }
.fm-cx-tag {
    font-size: .7rem; color: #7a6234; background: #f0e6c8; border: 1px solid #e0d0a0;
    border-radius: 999px; padding: 2px 8px; white-space: nowrap;
}
.fm-cx-r { font-size: .8rem; color: #5a4a28; margin-top: 4px; line-height: 1.55; }
.fm-cx-u { font-size: .76rem; color: #8a7649; margin-top: 3px; }
@media (max-width: 480px) {
    .fm-qtylist .fm-qty { flex-wrap: wrap; }
    .fm-cx-h { flex-wrap: wrap; }
}
