feat(首页): 此刻卡换应用 logo / 树洞星夜版 / 孕期小知识带孕周并压缩 (v26100102)
- 此刻:今日三项与动态的图标换成对应应用的 logo(取 App 表 logo,后台换即生效); 消消乐、盲盒用本站同风格 logo(assets/img/429ffcba0d6e.svg、b0087c3c012a.svg) - 妈妈的树洞重做为星夜版:深夜天幕 + 剪影树 + 旋转发光的漩涡树洞;每条心事化成天上一颗星(位置按时间戳固定); 扔进去时字逐个被吸进漩涡、洞口爆亮、新星射上天空;整块比旧版更矮。心事仍只存本机,热线兜底不变 - 孕期小知识:标题改「孕 N 周 · 今日孕期小知识」,右侧「本周第 N 天」;今日卡与圆点收紧,四张小卡改一行横滑(点开看全文) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1
assets/img/429ffcba0d6e.svg
Normal file
1
assets/img/429ffcba0d6e.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#FFA8C5"/><stop offset="1" stop-color="#EE6A98"/></linearGradient></defs><rect width="512" height="512" rx="120" fill="url(#g)"/><g fill="#fff"><rect x="96" y="96" width="140" height="140" rx="38"/><rect x="276" y="96" width="140" height="140" rx="38" opacity=".55"/><rect x="96" y="276" width="140" height="140" rx="38" opacity=".55"/><rect x="276" y="276" width="140" height="140" rx="38"/></g><g fill="#EE6A98"><rect x="148" y="122" width="36" height="22" rx="8"/><rect x="138" y="140" width="56" height="74" rx="20"/></g><path d="M346 300c-30 0-44 28-44 48 0 32 26 48 44 48s44-16 44-48c0-20-14-48-44-48z" fill="#EE6A98"/><circle cx="330" cy="292" r="14" fill="#EE6A98"/><circle cx="362" cy="292" r="14" fill="#EE6A98"/></svg>
|
||||
|
After Width: | Height: | Size: 878 B |
1
assets/img/b0087c3c012a.svg
Normal file
1
assets/img/b0087c3c012a.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#FFC56B"/><stop offset="1" stop-color="#FF7E5C"/></linearGradient></defs><rect width="512" height="512" rx="120" fill="url(#g)"/><rect x="126" y="236" width="260" height="170" rx="26" fill="#fff"/><rect x="106" y="180" width="300" height="76" rx="24" fill="#fff"/><rect x="236" y="180" width="40" height="226" fill="#FFB25E"/><path d="M256 182c-28-62-92-66-92-30 0 26 46 32 92 30zM256 182c28-62 92-66 92-30 0 26-46 32-92 30z" fill="#fff"/><circle cx="388" cy="132" r="14" fill="#fff" opacity=".8"/><circle cx="132" cy="120" r="9" fill="#fff" opacity=".6"/></svg>
|
||||
|
After Width: | Height: | Size: 711 B |
66
index.html
66
index.html
@@ -7,7 +7,7 @@
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>兜爸心选 · 孕育陪伴</title>
|
||||
<!-- V:26100101 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||||
<!-- V:26100102 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||||
<link rel="stylesheet" href="mama-box.css">
|
||||
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||||
<!-- 共享助手:授权/跳商城/位置上报(分享卡片同步,见 docs/h5-auth-standard.md 第四节) -->
|
||||
@@ -332,8 +332,10 @@
|
||||
⚠️ 一周 7 个圆点 = 这一周的第 1–7 天。今天及以前可以点开回看;以后的几天锁着,
|
||||
写「明天见」—— 让每天回来看一条,而不是一口气翻完。 -->
|
||||
<section class="preg-tips hide" id="pregTips">
|
||||
<!-- 2026-10-01 用户要求:标题前写明孕周 ——「孕 26 周 · 今日孕期小知识」,按她填的孕周自动取,每天换一条;整块压矮一些。
|
||||
#ptWk 由 renderTips() 写;#ptWhen 改成「第 N 天」。下面四张小卡由 2×2 改成一行横滑,高度省一半。 -->
|
||||
<div class="pt-head">
|
||||
<h2 class="pt-title">孕期小知识</h2>
|
||||
<h2 class="pt-title"><span class="pt-wk" id="ptWk">孕 — 周</span>今日孕期小知识</h2>
|
||||
<span class="pt-when" id="ptWhen"></span>
|
||||
</div>
|
||||
<div class="pt-today" id="ptToday">
|
||||
@@ -453,40 +455,52 @@
|
||||
⚠️ 唯一的例外是安全提示:内容里出现明显的轻生字眼时,收好之后在卡内显示一行援助热线
|
||||
(12356 全国心理援助热线),这不是「回应心事」,是兜底,别删。
|
||||
⚠️ 纸团飞进树洞的动画靠 Element.animate;不支持的老内核直接跳到「已收好」,不影响收存。 -->
|
||||
<!-- 妈妈的树洞 · 星夜版(2026-10-01 重做:用户要「很有创意、炫酷,模块不用太大」)。
|
||||
一块深夜蓝的小天幕:右边一棵剪影树,树干上的洞是一个缓慢旋转的发光漩涡(#thHole);
|
||||
天上的每颗亮星 = 你扔进来的一条心事(#thSky 由 JS 按本机记录画,位置由时间戳哈希定,刷新不跳)。
|
||||
扔进去:输入的字一个个飞起、绕成弧线被吸进漩涡 → 洞口爆亮 → 一颗新星从洞里射上天空,停在那儿眨眼。
|
||||
⚠️ 心事仍然只存本机 localStorage(用户 2026-09-30 选定),不回应、不上传;轻生字眼兜底热线照旧。
|
||||
⚠️ 保留的 id:thText / thSend / thMine / thCount / thDone / thList / thHole —— app.js treeHole() 依赖。 -->
|
||||
<section class="tree-hole" id="treeHole">
|
||||
<div class="th-head">
|
||||
<h2 class="th-title">妈妈的树洞</h2>
|
||||
<span class="th-lock"><svg viewBox="0 0 24 24" width="11" height="11" aria-hidden="true"><path d="M7 10V7.5a5 5 0 0 1 10 0V10" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/><rect x="4.5" y="10" width="15" height="11" rx="3" fill="currentColor"/></svg>只存在你的手机里</span>
|
||||
</div>
|
||||
<div class="th-stage">
|
||||
<p class="th-lead">烦心、委屈、害怕、说不出口的话,<br>都可以扔进来。树洞替你收着,<br>谁也看不到。</p>
|
||||
<svg class="th-tree" id="thTree" viewBox="0 0 120 124" aria-hidden="true">
|
||||
<g class="th-crown">
|
||||
<circle cx="40" cy="42" r="26" fill="#BFE0B4"/>
|
||||
<circle cx="78" cy="38" r="28" fill="#A9D59E"/>
|
||||
<circle cx="60" cy="22" r="22" fill="#C9E7BF"/>
|
||||
<circle cx="94" cy="58" r="17" fill="#B4DBA9"/>
|
||||
<circle cx="26" cy="62" r="15" fill="#B4DBA9"/>
|
||||
<circle cx="46" cy="28" r="3.2" fill="#F7B8A6"/><circle cx="84" cy="24" r="2.8" fill="#F9C9B8"/>
|
||||
<circle cx="96" cy="50" r="2.6" fill="#F7B8A6"/><circle cx="30" cy="52" r="2.6" fill="#F9C9B8"/>
|
||||
<circle cx="66" cy="44" r="2.4" fill="#F7B8A6"/>
|
||||
<div class="th-night" id="thNight">
|
||||
<div class="th-sky" id="thSky" aria-hidden="true"></div>
|
||||
<span class="th-moon" aria-hidden="true"></span>
|
||||
<i class="th-fly f1" aria-hidden="true"></i><i class="th-fly f2" aria-hidden="true"></i><i class="th-fly f3" aria-hidden="true"></i>
|
||||
<p class="th-lead">说不出口的话,扔进来<br><em>每一句,都会变成一颗星</em></p>
|
||||
<svg class="th-tree" id="thTree" viewBox="0 0 120 130" aria-hidden="true">
|
||||
<defs>
|
||||
<radialGradient id="thCore" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0" stop-color="#FFF6D8"/><stop offset=".45" stop-color="#FFC978"/><stop offset="1" stop-color="#FF8F6B" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<g class="th-crown" fill="#2A2B5C">
|
||||
<circle cx="38" cy="44" r="26"/><circle cx="80" cy="40" r="28"/><circle cx="60" cy="22" r="22"/>
|
||||
<circle cx="98" cy="60" r="16"/><circle cx="22" cy="64" r="15"/><circle cx="60" cy="56" r="24"/>
|
||||
</g>
|
||||
<path d="M46 130c4-20 5-38 3-56h22c-2 18-1 36 3 56z" fill="#2A2B5C"/>
|
||||
<path d="M54 82c-7-6-15-8-22-7M68 82c6-6 13-8 20-7" stroke="#2A2B5C" stroke-width="5" stroke-linecap="round" fill="none"/>
|
||||
<circle class="th-halo" cx="60" cy="102" r="17" fill="url(#thCore)"/>
|
||||
<ellipse cx="60" cy="102" rx="8" ry="10.5" fill="#0E0F2B"/>
|
||||
<g id="thHole" class="th-vortex">
|
||||
<path d="M60 94a8 8 0 0 1 7 9M60 110a8 8 0 0 1-7-9M53 97a5 5 0 0 1 9 1M67 107a5 5 0 0 1-9-1" stroke="#FFD58F" stroke-width="1.4" stroke-linecap="round" fill="none"/>
|
||||
<circle cx="60" cy="102" r="1.8" fill="#FFF3CF"/>
|
||||
</g>
|
||||
<path d="M50 124c3-18 3-34 1-52h20c-2 18-2 34 1 52z" fill="#D4A27C"/>
|
||||
<path d="M56 80c-6-6-14-8-20-7M66 80c5-6 12-8 18-7" stroke="#D4A27C" stroke-width="5" stroke-linecap="round" fill="none"/>
|
||||
<ellipse id="thHole" class="th-hole" cx="61" cy="98" rx="6.5" ry="9" fill="#7A5238"/>
|
||||
<ellipse cx="61" cy="99.5" rx="4" ry="6.2" fill="#5A3A26"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="th-form">
|
||||
<textarea id="thText" maxlength="500" rows="3" placeholder="今天想说点什么……"></textarea>
|
||||
<div class="th-row">
|
||||
<button class="th-mine" id="thMine" type="button">我的心事 <b id="thCount">0</b> ›</button>
|
||||
<button class="th-send" id="thSend" type="button">扔进树洞</button>
|
||||
<div class="th-form">
|
||||
<textarea id="thText" maxlength="500" rows="1" placeholder="今天想说点什么……"></textarea>
|
||||
<button class="th-send" id="thSend" type="button" aria-label="扔进树洞"><svg viewBox="0 0 24 24" width="17" height="17" aria-hidden="true"><path d="M12 2.5l2.3 6.2 6.2 2.3-6.2 2.3L12 19.5l-2.3-6.2L3.5 11l6.2-2.3z" fill="currentColor"/></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="th-done" id="thDone" aria-live="polite"></div>
|
||||
<div class="th-row">
|
||||
<button class="th-mine" id="thMine" type="button">我的心事 · <b id="thCount">0</b> 颗星 ›</button>
|
||||
<div class="th-done" id="thDone" aria-live="polite"></div>
|
||||
</div>
|
||||
<ul class="th-list hide" id="thList"></ul>
|
||||
<p class="th-help">如果持续情绪低落、睡不好,或有伤害自己的念头,请告诉家人或医生,也可拨打心理援助热线 <a href="tel:12356">12356</a>。</p>
|
||||
<p class="th-help">持续低落、睡不好或有伤害自己的念头,请告诉家人或医生,也可拨打心理援助热线 <a href="tel:12356">12356</a></p>
|
||||
</section>
|
||||
|
||||
<!-- 模块三 · 书架卡带。
|
||||
|
||||
163
js/app.js
163
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26100101';
|
||||
var VER = '26100102';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -3100,6 +3100,16 @@
|
||||
game: '<svg viewBox="0 0 24 24"><rect x="3" y="3" width="8" height="8" rx="2.5" fill="currentColor"/><rect x="13" y="3" width="8" height="8" rx="2.5" fill="currentColor" opacity=".6"/><rect x="3" y="13" width="8" height="8" rx="2.5" fill="currentColor" opacity=".6"/><rect x="13" y="13" width="8" height="8" rx="2.5" fill="currentColor"/></svg>',
|
||||
box: '<svg viewBox="0 0 24 24"><rect x="4" y="11" width="16" height="10" rx="2" fill="currentColor"/><rect x="2.5" y="7.5" width="19" height="4.5" rx="1.6" fill="currentColor"/><path d="M12 7.5V21" stroke="#fff" stroke-width="2"/><path d="M12 7.5C10 3.5 6 4 7.5 6.6 8.3 7.8 10.4 7.6 12 7.5zM12 7.5c2-4 6-3.5 4.5-.9-.8 1.2-2.9 1-4.5.9z" fill="currentColor"/></svg>'
|
||||
};
|
||||
/* 2026-10-01 用户要求:图标一律换成对应应用的 logo(数胎动就用数胎动的 logo)。
|
||||
logo 取 App 表(APP_BY_ID[identifier].logo,后台换 logo 即生效);应用列表还没回来时先用上面的单色图标顶一下。
|
||||
消消乐、盲盒不在 App 表里 → 用本站 assets/img 里的同风格 logo。 */
|
||||
const PULSE_APP = { kick: 'taidong', weight: 'yunqitizhong', cal: 'chanjianrili' };
|
||||
const PULSE_LOGO = { game: 'assets/img/429ffcba0d6e.svg', box: 'assets/img/b0087c3c012a.svg' };
|
||||
function pulseIco(k, cls) {
|
||||
const a = APP_BY_ID[PULSE_APP[k]], src = (a && a.logo) || PULSE_LOGO[k];
|
||||
return '<span class="' + cls + (src ? ' is-logo' : '') + '">' +
|
||||
(src ? '<img class="logo" src="' + String(src).replace(/"/g, '"') + '" alt="">' : (PULSE_ICO[k] || PULSE_ICO.box)) + '</span>';
|
||||
}
|
||||
const fmtN = n => String(Math.round(n)).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
/* 数字补间:el.dataset.v 记当前值,从它平滑走到 to;首次(无 dataset.v)从 0 起 */
|
||||
function tweenNum(el, to, dur) {
|
||||
@@ -3128,8 +3138,8 @@
|
||||
const t = String(f.text || ''), i = t.indexOf('的妈妈 ');
|
||||
const who = i > 0 ? t.slice(0, i + 3) : '一位妈妈', what = i > 0 ? t.slice(i + 4) : t;
|
||||
const esc = s => s.replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' })[c]);
|
||||
return '<div class="pl-row a-' + (PULSE_ICO[f.act] ? f.act : 'box') + '"><span class="pr-ico">' + (PULSE_ICO[f.act] || PULSE_ICO.box) +
|
||||
'</span><span class="pr-t"><span class="pr-who">' + esc(who) + ' · ' + esc(f.ago || '刚刚') + '</span><span class="pr-do">' +
|
||||
return '<div class="pl-row a-' + (PULSE_ICO[f.act] ? f.act : 'box') + '">' + pulseIco(PULSE_ICO[f.act] ? f.act : 'box', 'pr-ico') +
|
||||
'<span class="pr-t"><span class="pr-who">' + esc(who) + ' · ' + esc(f.ago || '刚刚') + '</span><span class="pr-do">' +
|
||||
esc(what).replace(/(\d+)/g, '<em>$1</em>') + '</span></span></div>';
|
||||
}
|
||||
function tick() {
|
||||
@@ -3158,11 +3168,13 @@
|
||||
}
|
||||
const td = $('#plToday'), items = r.today || [];
|
||||
td.classList.toggle('hide', !items.length);
|
||||
const keys = items.map(x => x.key).join(',');
|
||||
const keys = items.map(x => x.key).join(',') + (APP_BY_ID.taidong ? '|L' : ''); // 应用 logo 到了再重画一次
|
||||
if (td.dataset.keys !== keys) {
|
||||
td.dataset.keys = keys;
|
||||
td.innerHTML = items.map(x => '<button class="pl-stat k-' + x.key + '" type="button" data-k="' + x.key + '"><span class="ps-ico">' +
|
||||
(PULSE_ICO[x.key] || PULSE_ICO.box) + '</span><b>0</b><span>' + String(x.label || '').replace(/[<>&]/g, '') + '</span><i class="go">›</i></button>').join('');
|
||||
const was = {}; // logo 到了重画时,数字接着上次的值走,不从 0 再数一遍
|
||||
$$('.pl-stat', td).forEach(b => { const n = b.querySelector('b'); if (n && n.dataset.v != null) was[b.dataset.k] = n.dataset.v; });
|
||||
td.innerHTML = items.map(x => '<button class="pl-stat k-' + x.key + '" type="button" data-k="' + x.key + '">' +
|
||||
pulseIco(x.key, 'ps-ico') + '<b' + (was[x.key] != null ? ' data-v="' + was[x.key] + '">' + fmtN(+was[x.key]) : '>0') + '</b><span>' + String(x.label || '').replace(/[<>&]/g, '') + '</span><i class="go">›</i></button>').join('');
|
||||
}
|
||||
if (seen) items.forEach(x => tweenNum(td.querySelector('[data-k="' + x.key + '"] b'), x.value, 1600));
|
||||
feed = r.feed || [];
|
||||
@@ -3499,7 +3511,8 @@
|
||||
if (!wk || !(wk.days || []).length) { sec.classList.add('hide'); return; }
|
||||
const today = Math.max(0, Math.min(6, state.day || 0));
|
||||
const size = babySize(w);
|
||||
$('#ptWhen').textContent = '孕' + state.week + '周' + (state.day ? state.day + '天' : '');
|
||||
$('#ptWk').textContent = '孕 ' + state.week + ' 周';
|
||||
$('#ptWhen').textContent = '本周第 ' + (today + 1) + ' 天';
|
||||
$('#ptFloat').textContent = size.emoji;
|
||||
$('#ptBabyIco').textContent = size.emoji;
|
||||
$('#ptBaby').textContent = '像' + size.name + '那么大。' + (wk.baby || '');
|
||||
@@ -3543,6 +3556,11 @@
|
||||
const body = $('#ptBody');
|
||||
body.classList.remove('is-in'); void body.offsetWidth; body.classList.add('is-in'); // 重播进场动画
|
||||
}
|
||||
/* 四张小卡压成横滑后正文只露 3 行,点一下展开全文、再点收起 */
|
||||
(function () {
|
||||
const g = $('#ptGrid');
|
||||
if (g) g.addEventListener('click', e => { const c = e.target.closest('.pt-card'); if (c) c.classList.toggle('is-open'); });
|
||||
})();
|
||||
function revealTipsGrid() {
|
||||
const g = $('#ptGrid');
|
||||
if (!g || g.classList.contains('is-shown')) return;
|
||||
@@ -3553,24 +3571,53 @@
|
||||
io.observe(g);
|
||||
}
|
||||
|
||||
/* ================= 妈妈的树洞(2026-09-30) =================
|
||||
/* ================= 妈妈的树洞 · 星夜版(2026-09-30 首版,2026-10-01 重做 UI) =================
|
||||
用户选定:心事**只存在本机**(localStorage,不上传),扔进去后只有「已收好」动画、不回应。
|
||||
唯一例外:出现明显轻生字眼时,在「已收好」下面多一行援助热线 —— 兜底,不是回应。 */
|
||||
唯一例外:出现明显轻生字眼时,在「已收好」下面多一行援助热线 —— 兜底,不是回应。
|
||||
星夜版:天幕上每颗亮星 = 一条心事(位置由时间戳哈希定,刷新不跳);扔进去时字逐个被吸进树洞漩涡,
|
||||
洞口爆亮,一颗新星从洞口射上天空。 */
|
||||
(function treeHole() {
|
||||
const KEY = 'mmbox.treehole.v1', MAX = 200;
|
||||
const KEY = 'mmbox.treehole.v1', MAX = 200, SHOW = 40;
|
||||
const ta = $('#thText'), send = $('#thSend'), list = $('#thList'), done = $('#thDone');
|
||||
const night = $('#thNight'), sky = $('#thSky');
|
||||
if (!ta || !send) return;
|
||||
const SOS = /想死|不想活|自杀|轻生|结束生命|活不下去|去死|割腕|跳楼/;
|
||||
const RM = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
const load = () => { try { const a = JSON.parse(localStorage.getItem(KEY) || '[]'); return Array.isArray(a) ? a : []; } catch (e) { return []; } };
|
||||
const save = a => { try { localStorage.setItem(KEY, JSON.stringify(a.slice(0, MAX))); return true; } catch (e) { return false; } };
|
||||
const pad = n => (n < 10 ? '0' : '') + n;
|
||||
const when = ts => { const d = new Date(ts); return (d.getMonth() + 1) + '月' + d.getDate() + '日 ' + pad(d.getHours()) + ':' + pad(d.getMinutes()); };
|
||||
/* 确定性伪随机:同一个种子永远落在同一个位置 */
|
||||
const rnd = seed => { let x = (seed % 2147483647) || 1; return () => (x = x * 16807 % 2147483647) / 2147483647; };
|
||||
/* 星星避开右下角的树、底部输入条和左上角的月亮:x 4~66%,y 6~58% */
|
||||
const starPos = seed => { const r = rnd(seed); r(); const x = 4 + r() * 62, y = 6 + r() * 52; return [x < 20 && y < 30 ? x + 22 : x, y]; }; // 左上角让给月亮
|
||||
function count() { $('#thCount').textContent = load().length; }
|
||||
function paintSky() {
|
||||
if (!sky) return;
|
||||
sky.textContent = '';
|
||||
const bg = rnd(20261001);
|
||||
for (let i = 0; i < 26; i++) { // 背景小星,固定一套
|
||||
const s = document.createElement('i');
|
||||
s.style.left = (bg() * 100) + '%'; s.style.top = (bg() * 70) + '%';
|
||||
s.style.setProperty('--o', (0.25 + bg() * 0.5).toFixed(2));
|
||||
s.style.animationDelay = (bg() * 3.2).toFixed(2) + 's';
|
||||
sky.appendChild(s);
|
||||
}
|
||||
load().slice(0, SHOW).forEach(e => addStar(e.t, false));
|
||||
}
|
||||
function addStar(t, fresh) {
|
||||
const p = starPos(t), s = document.createElement('i');
|
||||
s.className = 'me' + (fresh ? ' is-new' : '');
|
||||
s.style.left = p[0] + '%'; s.style.top = p[1] + '%';
|
||||
s.style.animationDelay = fresh ? '' : ((t % 3200) / 1000).toFixed(2) + 's';
|
||||
sky.appendChild(s);
|
||||
return s;
|
||||
}
|
||||
function renderList() {
|
||||
const a = load();
|
||||
list.textContent = '';
|
||||
if (!a.length) {
|
||||
const li = document.createElement('li'); li.className = 'th-empty'; li.textContent = '树洞还是空的';
|
||||
const li = document.createElement('li'); li.className = 'th-empty'; li.textContent = '天上还没有你的星星';
|
||||
list.appendChild(li); return;
|
||||
}
|
||||
a.forEach(e => {
|
||||
@@ -3581,15 +3628,15 @@
|
||||
del.setAttribute('aria-label', '删除这条'); del.textContent = '×';
|
||||
del.addEventListener('click', () => {
|
||||
if (!window.confirm('删掉这条心事?删了就找不回来了')) return;
|
||||
save(load().filter(x => x.t !== e.t)); renderList(); count();
|
||||
save(load().filter(x => x.t !== e.t)); renderList(); count(); paintSky();
|
||||
});
|
||||
li.appendChild(t); li.appendChild(p); li.appendChild(del);
|
||||
list.appendChild(li);
|
||||
});
|
||||
}
|
||||
function showDone(sos) {
|
||||
function showDone(sos, n) {
|
||||
done.classList.toggle('is-sos', !!sos);
|
||||
done.textContent = '已收好 🍃';
|
||||
done.textContent = '已收好,化成了第 ' + n + ' 颗星';
|
||||
if (sos) {
|
||||
const s = document.createElement('div'); s.className = 'th-sos';
|
||||
s.textContent = '如果你现在很难受,请告诉身边的人,或拨打 12356 心理援助热线,有人愿意听你说。';
|
||||
@@ -3597,50 +3644,82 @@
|
||||
}
|
||||
done.classList.add('is-on');
|
||||
clearTimeout(showDone._t);
|
||||
if (!sos) showDone._t = setTimeout(() => done.classList.remove('is-on'), 2600);
|
||||
if (!sos) showDone._t = setTimeout(() => done.classList.remove('is-on'), 3200);
|
||||
}
|
||||
/* 纸团飞进树洞:从输入框中间出发,弧线落到树洞,边转边缩小 */
|
||||
function fly(text, cb) {
|
||||
const hole = $('#thHole'), tree = $('#thTree');
|
||||
const note = document.createElement('div');
|
||||
if (!hole || !note.animate) { cb(); return; }
|
||||
note.className = 'th-note'; note.textContent = text;
|
||||
document.body.appendChild(note);
|
||||
const a = ta.getBoundingClientRect(), h = hole.getBoundingClientRect();
|
||||
const nw = note.offsetWidth, nh = note.offsetHeight;
|
||||
const x0 = a.left + a.width / 2 - nw / 2, y0 = a.top + a.height / 2 - nh / 2;
|
||||
const x1 = h.left + h.width / 2 - nw / 2, y1 = h.top + h.height / 2 - nh / 2;
|
||||
const xm = (x0 + x1) / 2, ym = Math.min(y0, y1) - 70;
|
||||
const anim = note.animate([
|
||||
{ transform: 'translate(' + x0 + 'px,' + y0 + 'px) scale(1) rotate(0)', opacity: 1, borderRadius: '10px' },
|
||||
{ transform: 'translate(' + xm + 'px,' + ym + 'px) scale(.45) rotate(200deg)', opacity: 1, borderRadius: '50%', offset: .55 },
|
||||
{ transform: 'translate(' + x1 + 'px,' + y1 + 'px) scale(.08) rotate(420deg)', opacity: .2, borderRadius: '50%' }
|
||||
], { duration: 950, easing: 'cubic-bezier(.45,.05,.4,1)', fill: 'forwards' });
|
||||
anim.onfinish = () => {
|
||||
note.remove();
|
||||
if (tree) { tree.classList.remove('is-eat'); void tree.getBoundingClientRect(); tree.classList.add('is-eat'); setTimeout(() => tree.classList.remove('is-eat'), 1000); }
|
||||
const center = el => { const r = el.getBoundingClientRect(); return [r.left + r.width / 2, r.top + r.height / 2]; };
|
||||
/* ① 字一个个从输入条飞起,绕一道弧被吸进漩涡 */
|
||||
function suck(text, cb) {
|
||||
const hole = $('#thHole');
|
||||
if (RM || !hole || !document.body.animate) { cb(); return; }
|
||||
const chars = Array.from(text.replace(/\s+/g, '')).slice(0, 14);
|
||||
const a = ta.getBoundingClientRect(), h = center(hole);
|
||||
let left = chars.length;
|
||||
if (!left) { cb(); return; }
|
||||
chars.forEach((c, i) => {
|
||||
const el = document.createElement('span');
|
||||
el.className = 'th-ch'; el.textContent = c;
|
||||
document.body.appendChild(el);
|
||||
const x0 = a.left + 6 + Math.min(i * 14, a.width - 20), y0 = a.top + 4;
|
||||
const mx = (x0 + h[0]) / 2 + (i % 2 ? 24 : -18), my = Math.min(y0, h[1]) - 40 - (i % 3) * 14;
|
||||
const anim = el.animate([
|
||||
{ transform: 'translate(' + x0 + 'px,' + y0 + 'px) scale(1) rotate(0)', opacity: 0 },
|
||||
{ transform: 'translate(' + x0 + 'px,' + (y0 - 10) + 'px) scale(1.1) rotate(0)', opacity: 1, offset: .12 },
|
||||
{ transform: 'translate(' + mx + 'px,' + my + 'px) scale(.8) rotate(' + (i % 2 ? 160 : -160) + 'deg)', opacity: 1, offset: .55 },
|
||||
{ transform: 'translate(' + (h[0] - 6) + 'px,' + (h[1] - 8) + 'px) scale(.1) rotate(' + (i % 2 ? 540 : -540) + 'deg)', opacity: 0 }
|
||||
], { duration: 900, delay: i * 55, easing: 'cubic-bezier(.5,0,.3,1)', fill: 'forwards' });
|
||||
anim.onfinish = () => { el.remove(); if (--left === 0) cb(); };
|
||||
});
|
||||
}
|
||||
/* ② 洞口爆亮 → 新星从洞口划一道弧射上天空 */
|
||||
function shoot(t, cb) {
|
||||
const tree = $('#thTree'), hole = $('#thHole');
|
||||
if (tree) { tree.classList.remove('is-eat'); void tree.getBoundingClientRect(); tree.classList.add('is-eat'); setTimeout(() => tree.classList.remove('is-eat'), 1000); }
|
||||
const star = addStar(t, true);
|
||||
if (RM || !hole || !document.body.animate) { cb(); return; }
|
||||
star.style.visibility = 'hidden';
|
||||
const h = center(hole), d = center(star);
|
||||
const el = document.createElement('i'); el.className = 'th-shoot';
|
||||
document.body.appendChild(el);
|
||||
const mx = (h[0] + d[0]) / 2 + 30, my = Math.min(h[1], d[1]) - 30;
|
||||
el.animate([
|
||||
{ transform: 'translate(' + h[0] + 'px,' + h[1] + 'px) scale(.4)', opacity: 0 },
|
||||
{ transform: 'translate(' + h[0] + 'px,' + (h[1] - 6) + 'px) scale(1.6)', opacity: 1, offset: .15 },
|
||||
{ transform: 'translate(' + mx + 'px,' + my + 'px) scale(1)', opacity: 1, offset: .6 },
|
||||
{ transform: 'translate(' + d[0] + 'px,' + d[1] + 'px) scale(1.2)', opacity: 1 }
|
||||
], { duration: 900, delay: 250, easing: 'cubic-bezier(.3,.1,.3,1)', fill: 'forwards' }).onfinish = () => {
|
||||
el.remove();
|
||||
star.style.visibility = '';
|
||||
star.classList.remove('is-new'); void star.offsetWidth; star.classList.add('is-new');
|
||||
cb();
|
||||
};
|
||||
}
|
||||
const sync = () => { send.disabled = !ta.value.trim(); };
|
||||
ta.addEventListener('input', sync);
|
||||
ta.addEventListener('focus', () => night && night.classList.add('is-typing'));
|
||||
ta.addEventListener('blur', () => { if (night && !ta.value.trim()) night.classList.remove('is-typing'); });
|
||||
let busy = false;
|
||||
send.addEventListener('mousedown', e => e.preventDefault()); // 点按钮时别先 blur 收起输入框,免得按钮跳位
|
||||
send.addEventListener('click', () => {
|
||||
const x = ta.value.trim();
|
||||
if (!x) return;
|
||||
const a = load(); a.unshift({ t: Date.now(), x: x });
|
||||
if (!x || busy) return;
|
||||
const t = Date.now();
|
||||
const a = load(); a.unshift({ t: t, x: x });
|
||||
if (!save(a)) { toast('手机存储空间不足,没能收好'); return; }
|
||||
ta.value = ''; sync(); ta.blur();
|
||||
fly(x, () => {
|
||||
showDone(SOS.test(x));
|
||||
busy = true; haptic();
|
||||
suck(x, () => shoot(t, () => {
|
||||
busy = false;
|
||||
showDone(SOS.test(x), load().length);
|
||||
count();
|
||||
if (!list.classList.contains('hide')) renderList();
|
||||
});
|
||||
}));
|
||||
ta.value = ''; sync(); ta.blur();
|
||||
if (night) night.classList.remove('is-typing');
|
||||
});
|
||||
$('#thMine').addEventListener('click', () => {
|
||||
const open = list.classList.toggle('hide') === false;
|
||||
if (open) renderList();
|
||||
});
|
||||
sync(); count();
|
||||
sync(); count(); paintSky();
|
||||
})();
|
||||
|
||||
/* 拉卡片数据(与其它远程数据一起打;失败静默,卡上保留现有值) */
|
||||
|
||||
163
mama-box.css
163
mama-box.css
@@ -618,55 +618,95 @@ a.skip:focus{left:16px;top:16px}
|
||||
.pt-grid.is-shown .pt-card:nth-child(4){transition-delay:.24s}
|
||||
.pt-foot{margin-top:9px;font-size:11px;color:var(--muted);text-align:center}
|
||||
|
||||
/* ============ 妈妈的树洞(2026-09-30)============
|
||||
浅薄荷→奶白的底,和上下暖色块拉开,读起来「安静」。右侧一棵 SVG 小树,
|
||||
树干上的洞(#thHole)是纸团飞进去的落点。扔进去后:纸团飞入 → 洞口亮一下、树冠晃一下
|
||||
→ 卡内出现「已收好」。不做任何回应文字(用户选定)。 */
|
||||
.tree-hole{background-image:linear-gradient(160deg,#F1F8EE 0%,#FAFCF6 55%,#FFFDF9 100%)}
|
||||
/* ============ 妈妈的树洞 · 星夜版(2026-10-01 重做)============
|
||||
外层仍是统一的白块;里面一块深夜蓝小天幕 .th-night(高约 190px,比旧版矮)。
|
||||
天幕层次(下→上):渐变夜空 → 月亮光晕 → 星星(#thSky,每颗亮星 = 一条心事)→ 萤火虫 → 剪影树 + 漩涡树洞 → 输入条。
|
||||
动效:星星各自眨眼;萤火虫游走;树冠轻晃;树洞漩涡一直慢转、光晕呼吸;
|
||||
扔进去时字逐个被吸进漩涡(JS),洞口爆亮(.is-eat),新星从洞口射上天(JS)。 */
|
||||
.th-head{display:flex;align-items:center;gap:8px}
|
||||
.th-title{font-size:16.5px;font-weight:800;letter-spacing:-.2px}
|
||||
.th-lock{margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:11.5px;font-weight:600;
|
||||
color:#5E8A55;background:#E4F1DF;border-radius:999px;padding:3px 9px}
|
||||
.th-stage{display:flex;align-items:flex-end;gap:6px;margin-top:6px}
|
||||
.th-lead{flex:1;min-width:0;font-size:13px;line-height:1.7;color:#5C6B58;padding-bottom:10px}
|
||||
.th-tree{flex:0 0 auto;width:104px;height:108px;overflow:visible}
|
||||
.th-crown{transform-origin:60px 70px;animation:thSway 5s ease-in-out infinite}
|
||||
@keyframes thSway{0%,100%{transform:rotate(-1.2deg)}50%{transform:rotate(1.2deg)}}
|
||||
.th-lock{margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;
|
||||
color:#6C6FA8;background:#EFEFFB;border-radius:999px;padding:3px 9px}
|
||||
.th-night{position:relative;overflow:hidden;margin-top:10px;height:188px;border-radius:22px;isolation:isolate;
|
||||
background:radial-gradient(120% 90% at 85% 100%,#4B3F7E 0%,rgba(75,63,126,0) 60%),
|
||||
linear-gradient(170deg,#141632 0%,#1E2150 48%,#36306A 100%);
|
||||
box-shadow:inset 0 0 0 1px rgba(255,255,255,.06),0 10px 24px rgba(40,36,90,.22)}
|
||||
.th-sky{position:absolute;inset:0;z-index:0}
|
||||
.th-sky i{position:absolute;width:2px;height:2px;border-radius:50%;background:#fff;opacity:.5;
|
||||
animation:thTw 3.2s ease-in-out infinite}
|
||||
.th-sky i.me{width:5px;height:5px;background:#FFF1C9;opacity:1;
|
||||
box-shadow:0 0 6px 2px rgba(255,214,140,.75),0 0 14px 4px rgba(255,190,120,.25)}
|
||||
.th-sky i.me::before,.th-sky i.me::after{content:"";position:absolute;left:50%;top:50%;background:rgba(255,236,190,.7);
|
||||
transform:translate(-50%,-50%);border-radius:2px}
|
||||
.th-sky i.me::before{width:13px;height:1px}.th-sky i.me::after{width:1px;height:13px}
|
||||
.th-sky i.me.is-new{animation:thBorn 1.4s var(--ease) both,thTw 3.2s 1.4s ease-in-out infinite}
|
||||
@keyframes thTw{0%,100%{opacity:var(--o,.55);transform:scale(1)}50%{opacity:.15;transform:scale(.7)}}
|
||||
@keyframes thBorn{0%{transform:scale(3.2);opacity:1;filter:brightness(2)}100%{transform:scale(1);filter:none}}
|
||||
.th-moon{position:absolute;z-index:0;left:18px;top:14px;width:26px;height:26px;border-radius:50%;
|
||||
background:radial-gradient(circle at 35% 35%,#FFF7DD,#F6DFA8);box-shadow:0 0 18px 6px rgba(255,226,160,.22)}
|
||||
.th-moon::after{content:"";position:absolute;left:8px;top:-3px;width:24px;height:24px;border-radius:50%;background:#18193A}
|
||||
.th-fly{position:absolute;z-index:1;width:4px;height:4px;border-radius:50%;background:#FFE7A0;
|
||||
box-shadow:0 0 8px 3px rgba(255,220,120,.6);opacity:0;animation:thFly 7s ease-in-out infinite}
|
||||
.th-fly.f1{left:52%;top:62%}.th-fly.f2{left:70%;top:40%;animation-delay:2.4s;animation-duration:8s}
|
||||
.th-fly.f3{left:36%;top:46%;animation-delay:4.6s;animation-duration:9s}
|
||||
@keyframes thFly{0%{opacity:0;transform:translate(0,0)}20%{opacity:.95}50%{transform:translate(16px,-14px)}
|
||||
80%{opacity:.8}100%{opacity:0;transform:translate(-8px,-30px)}}
|
||||
.th-lead{position:absolute;z-index:2;left:18px;top:52px;margin:0;font-size:13px;line-height:1.7;font-weight:700;color:#F3F0FF;
|
||||
text-shadow:0 1px 8px rgba(10,10,40,.5)}
|
||||
.th-lead em{font-style:normal;font-weight:500;font-size:11.5px;color:#BDB8E8}
|
||||
.th-tree{position:absolute;z-index:1;right:-6px;bottom:44px;width:118px;height:128px;overflow:visible}
|
||||
.th-crown{transform-origin:60px 74px;animation:thSway 6s ease-in-out infinite}
|
||||
@keyframes thSway{0%,100%{transform:rotate(-1.4deg)}50%{transform:rotate(1.4deg)}}
|
||||
.th-halo{transform-origin:60px 102px;animation:thBreath 3s ease-in-out infinite}
|
||||
@keyframes thBreath{0%,100%{opacity:.55;transform:scale(.9)}50%{opacity:1;transform:scale(1.12)}}
|
||||
.th-vortex{transform-origin:60px 102px;animation:thSpin 4s linear infinite}
|
||||
@keyframes thSpin{to{transform:rotate(360deg)}}
|
||||
.th-tree.is-eat .th-halo{animation:thBurst .9s ease-out}
|
||||
.th-tree.is-eat .th-vortex{animation-duration:.5s}
|
||||
.th-tree.is-eat .th-crown{animation:thShake .7s ease-in-out}
|
||||
@keyframes thBurst{0%{opacity:1;transform:scale(1)}35%{opacity:1;transform:scale(2.3)}100%{opacity:.55;transform:scale(.9)}}
|
||||
@keyframes thShake{0%,100%{transform:rotate(0)}25%{transform:rotate(-4deg)}60%{transform:rotate(3deg)}}
|
||||
.th-tree.is-eat .th-hole{animation:thGlow .9s ease-out}
|
||||
@keyframes thGlow{0%{fill:#7A5238}35%{fill:#F4C38F}100%{fill:#7A5238}}
|
||||
.th-form{margin-top:4px;background:#fff;border:1px solid #E3EEDD;border-radius:16px;padding:10px 12px}
|
||||
.th-form textarea{display:block;width:100%;border:0;outline:0;resize:none;background:transparent;
|
||||
font:inherit;font-size:14px;line-height:1.6;color:var(--ink)}
|
||||
.th-form textarea::placeholder{color:#A9B5A4}
|
||||
.th-row{display:flex;align-items:center;gap:8px;margin-top:6px}
|
||||
.th-mine{border:0;background:none;padding:0;font:inherit;font-size:12px;font-weight:600;color:#6F8A68}
|
||||
.th-mine b{font-weight:800}
|
||||
.th-send{margin-left:auto;border:0;border-radius:999px;padding:8px 18px;font:inherit;font-size:13.5px;font-weight:700;
|
||||
color:#fff;background:linear-gradient(90deg,#7FB573,#98C98A);box-shadow:0 6px 14px rgba(110,160,95,.25)}
|
||||
.th-send:disabled{opacity:.45;box-shadow:none}
|
||||
.th-send:active{transform:scale(.96)}
|
||||
.th-done{height:0;overflow:hidden;text-align:center;font-size:13px;font-weight:700;color:#5E8A55;
|
||||
transition:height .3s var(--ease),margin .3s var(--ease)}
|
||||
.th-done.is-on{height:22px;margin-top:10px;animation:ptIn .4s var(--ease)}
|
||||
.th-done .th-sos{font-weight:500;color:var(--ink-2)}
|
||||
.th-done.is-sos{height:auto}
|
||||
.th-note{position:fixed;z-index:60;left:0;top:0;pointer-events:none;border-radius:10px;
|
||||
background:#FFFDF6;box-shadow:0 6px 18px rgba(90,110,80,.25);padding:6px 9px;font-size:12px;color:var(--ink-2);
|
||||
max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.th-list{list-style:none;margin:10px 0 0;padding:0}
|
||||
.th-form{position:absolute;z-index:3;left:10px;right:10px;bottom:10px;display:flex;align-items:flex-end;gap:8px;
|
||||
padding:5px 5px 5px 14px;border-radius:20px;background:rgba(255,255,255,.1);
|
||||
-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);box-shadow:inset 0 0 0 1px rgba(255,255,255,.16)}
|
||||
.th-form textarea{flex:1;min-width:0;display:block;border:0;outline:0;resize:none;background:transparent;
|
||||
font:inherit;font-size:13.5px;line-height:20px;height:20px;max-height:60px;margin:6px 0;color:#fff;transition:height .25s var(--ease)}
|
||||
.th-form textarea::placeholder{color:rgba(230,226,255,.55)}
|
||||
.th-night.is-typing .th-form textarea{height:60px}
|
||||
.th-night.is-typing .th-lead{opacity:0;transform:translateY(-6px)}
|
||||
.th-lead{transition:opacity .25s,transform .25s}
|
||||
.th-send{flex:0 0 auto;width:34px;height:34px;border:0;border-radius:50%;display:grid;place-items:center;color:#3A2A12;
|
||||
background:linear-gradient(135deg,#FFE3A1,#FFAE6E);box-shadow:0 0 14px rgba(255,190,110,.55);transition:transform .2s,opacity .2s}
|
||||
.th-send:disabled{opacity:.35;box-shadow:none}
|
||||
.th-send:not(:disabled){animation:thPing 2s ease-in-out infinite}
|
||||
@keyframes thPing{0%,100%{box-shadow:0 0 10px rgba(255,190,110,.45)}50%{box-shadow:0 0 20px 3px rgba(255,190,110,.8)}}
|
||||
.th-send:active{transform:scale(.9)}
|
||||
.th-row{display:flex;align-items:center;gap:8px;margin-top:9px;min-height:20px}
|
||||
.th-mine{border:0;background:none;padding:0;font:inherit;font-size:12px;font-weight:600;color:#6C6FA8}
|
||||
.th-mine b{font-weight:800;color:#4B3F9E}
|
||||
.th-done{margin-left:auto;font-size:12px;font-weight:700;color:#7A6BD0;opacity:0;transform:translateY(4px);transition:opacity .3s,transform .3s}
|
||||
.th-done.is-on{opacity:1;transform:none}
|
||||
.th-done.is-sos{margin-left:0}
|
||||
.th-done .th-sos{font-weight:500;color:var(--ink-2);margin-top:2px}
|
||||
.th-row{flex-wrap:wrap}.th-done.is-sos{flex-basis:100%}
|
||||
.th-ch{position:fixed;z-index:60;left:0;top:0;pointer-events:none;font-size:14px;font-weight:700;color:#FFF1C9;
|
||||
text-shadow:0 0 8px rgba(255,200,120,.9)}
|
||||
.th-shoot{position:fixed;z-index:60;left:0;top:0;width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;pointer-events:none;
|
||||
background:#FFF4D2;box-shadow:0 0 10px 4px rgba(255,210,130,.8)}
|
||||
.th-list{list-style:none;margin:8px 0 0;padding:0}
|
||||
.th-list.hide{display:none}
|
||||
.th-list li{position:relative;background:#fff;border-radius:14px;padding:9px 34px 9px 12px;margin-top:8px;
|
||||
border:1px solid #EAF2E6}
|
||||
.th-list time{display:block;font-size:11px;color:#8FA088}
|
||||
.th-list li{position:relative;background:#F6F5FD;border-radius:14px;padding:9px 34px 9px 30px;margin-top:8px}
|
||||
.th-list li::before{content:"";position:absolute;left:12px;top:15px;width:6px;height:6px;border-radius:50%;
|
||||
background:#FFC978;box-shadow:0 0 6px 2px rgba(255,200,120,.6)}
|
||||
.th-list time{display:block;font-size:11px;color:#9A97C2}
|
||||
.th-list p{margin:3px 0 0;font-size:13px;line-height:1.6;color:var(--ink-2);white-space:pre-wrap;word-break:break-all}
|
||||
.th-list .th-del{position:absolute;right:8px;top:8px;border:0;background:none;padding:2px 4px;font-size:15px;color:#B9C4B4}
|
||||
.th-list .th-empty{text-align:center;color:var(--muted);font-size:12px;background:none;border:0}
|
||||
.th-help{margin-top:10px;font-size:11px;line-height:1.6;color:var(--muted)}
|
||||
.th-help a{color:#5E8A55;font-weight:700}
|
||||
.th-list .th-del{position:absolute;right:8px;top:8px;border:0;background:none;padding:2px 4px;font-size:15px;color:#B8B6D6}
|
||||
.th-list .th-empty{text-align:center;color:var(--muted);font-size:12px;background:none;padding:6px}
|
||||
.th-list .th-empty::before{display:none}
|
||||
.th-help{margin:8px 0 0;font-size:10.5px;line-height:1.55;color:var(--muted)}
|
||||
.th-help a{color:#6C6FA8;font-weight:700}
|
||||
@media (prefers-reduced-motion:reduce){
|
||||
.pt-float,.pt-day.is-today i,.th-crown{animation:none}
|
||||
.pt-float,.pt-day.is-today i,.th-crown,.th-halo,.th-vortex,.th-fly,.th-sky i,.th-send{animation:none!important}
|
||||
.pt-grid .pt-card{opacity:1;transform:none;transition:none}
|
||||
}
|
||||
|
||||
@@ -2691,3 +2731,42 @@ a.skip:focus{left:16px;top:16px}
|
||||
}
|
||||
.bx-t .fb{display:grid;place-items:center;width:100%;height:100%;background:radial-gradient(circle at 50% 40%,#fff 0,#FFE6DA 70%)}
|
||||
.bx-keep,.bx-open{text-align:center}
|
||||
|
||||
/* 此刻卡 · 应用 logo(2026-10-01:图标换成对应应用自己的 logo;logo 自带圆角方底,外层底色去掉) */
|
||||
.pl-stat .ps-ico.is-logo,.pl-row .pr-ico.is-logo{background:none!important}
|
||||
.pl-stat .ps-ico img.logo{width:26px;height:26px;border-radius:8px;display:block;box-shadow:0 3px 8px rgba(120,70,50,.14)}
|
||||
.pl-stat .ps-ico{width:26px;height:26px}
|
||||
.pl-row .pr-ico img.logo{width:28px;height:28px;border-radius:9px;display:block;box-shadow:0 2px 6px rgba(120,70,50,.12)}
|
||||
.pl-row .pr-ico{width:28px;height:28px}
|
||||
|
||||
/* 孕期小知识 · 压缩版(2026-10-01:标题前带孕周;今日卡、7 天圆点、四张小卡都收紧,四卡改一行横滑) */
|
||||
.pt-head{margin-bottom:8px;align-items:center}
|
||||
.pt-title{display:flex;align-items:center;gap:6px;font-size:15.5px}
|
||||
.pt-wk{display:inline-block;font-size:12.5px;font-weight:800;color:#fff;border-radius:8px;padding:2px 8px;
|
||||
background:linear-gradient(135deg,#F4593C,#FF8A66);box-shadow:0 3px 8px rgba(244,89,60,.25);letter-spacing:0}
|
||||
.pt-when{font-size:11px;padding:2px 8px}
|
||||
.pt-today{padding:11px 14px 9px}
|
||||
.pt-float{font-size:28px;top:8px}
|
||||
.pt-body{min-height:0;padding-right:36px}
|
||||
.pt-t{margin-top:6px;font-size:15px}
|
||||
.pt-d{margin-top:3px;font-size:12.5px;line-height:1.6}
|
||||
.pt-days{margin-top:8px;padding-top:7px}
|
||||
.pt-day{gap:1px}
|
||||
.pt-day i{width:22px;height:22px;line-height:22px;font-size:11px}
|
||||
.pt-day span{font-size:9.5px}
|
||||
.pt-grid{display:flex;gap:8px;margin:8px -26px 0;padding:0 26px 2px;overflow-x:auto;scroll-snap-type:x mandatory;
|
||||
-webkit-overflow-scrolling:touch;scrollbar-width:none}
|
||||
.pt-grid::-webkit-scrollbar{display:none}
|
||||
.pt-card{flex:0 0 152px;scroll-snap-align:start;padding:9px 11px 10px;border-radius:14px;
|
||||
display:grid;grid-template-columns:auto 1fr;column-gap:6px;align-items:center}
|
||||
.pt-ico{width:24px;height:24px;border-radius:8px;font-size:14px}
|
||||
.pt-card b{margin:0;font-size:12.5px}
|
||||
.pt-card p{grid-column:1/-1;margin-top:5px;font-size:11.5px;line-height:1.5;
|
||||
display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.pt-grid .pt-card{transform:translateX(16px)}
|
||||
.pt-grid.is-shown .pt-card{transform:none}
|
||||
.pt-foot{margin-top:6px;font-size:10.5px}
|
||||
.pt-card.is-open p{-webkit-line-clamp:unset;display:block}
|
||||
.pt-grid{scroll-padding:0 26px}
|
||||
.th-tree{bottom:50px}
|
||||
.th-crown{filter:drop-shadow(0 -1px 0 rgba(170,160,255,.35)) drop-shadow(0 0 10px rgba(120,110,230,.25))}
|
||||
|
||||
Reference in New Issue
Block a user