/* WenKai 常用字兜底分片(gen-common-shards.py 产物清单驱动)——声明在主
   子集之前:主子集(后声明,优先)缺字时浏览器才按需下载对应分片。 */
@font-face{font-family:"WenKai";src:url(./wenkai-c01.f4eb78f2.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+3400-358F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c02.964983f1.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+3590-371F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c03.c62f5bd9.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+3720-38AF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c04.294c5841.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+38B0-3A3F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c05.131de624.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+3A40-3BCF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c06.1a0b3874.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+3BD0-3D5F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c07.8530d09e.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+3D60-3EEF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c08.4f58997a.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+3EF0-407F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c09.c173e0bd.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+4080-420F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c10.ea620bb5.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+4210-439F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c11.9936636b.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+43A0-452F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c12.7720606e.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+4530-46BF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c13.44392e65.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+46C0-484F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c14.5c52616a.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+4850-49DF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c15.17515a5d.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+49E0-4B6F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c16.bb631567.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+4B70-4CFF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c17.aeee29eb.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+4D00-4DBF,U+4E00-4ECF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c18.6192bae8.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+4ED0-505F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c19.71909692.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+5060-51EF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c20.da8c932a.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+51F0-537F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c21.6f6ccad1.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+5380-550F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c22.e8a58d5d.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+5510-569F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c23.eeaa8c13.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+56A0-582F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c24.c7e54d82.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+5830-59BF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c25.d15beeba.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+59C0-5B4F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c26.3c521b74.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+5B50-5CDF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c27.7f1dc1bd.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+5CE0-5E6F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c28.94e8b95c.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+5E70-5FFF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c29.824f9eff.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6000-618F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c30.610c0c17.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6190-631F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c31.a11c59f7.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6320-64AF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c32.af0fa8c6.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+64B0-663F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c33.983f6759.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6640-67CF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c34.1b1a4418.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+67D0-695F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c35.acd702b9.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6960-6AEF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c36.259d496c.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6AF0-6C7F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c37.cbc109a5.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6C80-6E0F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c38.e246476e.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6E10-6F9F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c39.0a68ecc0.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+6FA0-712F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c40.47d1ddd2.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7130-72BF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c41.d7482fa5.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+72C0-744F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c42.a0b44b14.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7450-75DF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c43.4c10b695.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+75E0-776F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c44.7c7cc48b.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7770-78FF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c45.d7ec7cf5.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7900-7A8F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c46.75f2f05d.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7A90-7C1F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c47.20503c1a.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7C20-7DAF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c48.ddf843ab.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7DB0-7F3F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c49.6f10f790.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+7F40-80CF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c50.86df653a.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+80D0-825F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c51.bd25d094.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+8260-83EF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c52.0cdfe9b9.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+83F0-857F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c53.293d123f.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+8580-870F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c54.f1783c45.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+8710-889F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c55.01983236.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+88A0-8A2F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c56.619b2742.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+8A30-8BBF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c57.a5081555.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+8BC0-8D4F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c58.d3781933.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+8D50-8EDF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c59.5f0d355d.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+8EE0-906F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c60.e1e5a8f7.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9070-91FF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c61.e24be95c.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9200-938F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c62.810dd301.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9390-951F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c63.d4ddffbd.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9520-96AF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c64.bd5b19cd.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+96B0-983F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c65.6cdee845.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9840-99CF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c66.22167576.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+99D0-9B5F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c67.9e8f070e.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9B60-9CEF;}
@font-face{font-family:"WenKai";src:url(./wenkai-c68.ab7d5f29.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9CF0-9E7F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c69.97c71635.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+9E80-9FFF,U+F900-F90F;}
@font-face{font-family:"WenKai";src:url(./wenkai-c70.31d18d81.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+F910-FA6D,U+FA7F,U+FAD4,U+20003,U+2000B,U+2000E,U+20024,U+20027,U+2002A-2002B,U+2003E,U+2005E,U+20063,U+2006D,U+20086-20087,U+20089-2008A,U+20092,U+20094,U+200A2,U+200A4,U+200B0,U+200CA-200CD,U+200D1,U+200D3,U+200DB-200DC,U+200E9,U+200F2,U+2010C,U+2010E-2010F,U+20114,U+2011E-20120,U+20122,U+20129,U+20136,U+2013B-2013C,U+20164,U+201A2-201A3,U+201A8-201A9,U+201BE;}
@font-face{font-family:"WenKai";src:url(./wenkai-c71.c065e56d.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+201D4,U+201D7,U+201EE,U+20201,U+2020C,U+20235,U+20242,U+20263,U+2026E,U+2028E,U+2029F,U+202AC,U+202C2,U+202C6,U+202E4,U+20302,U+20316,U+2032F,U+20350,U+203AE,U+203B7,U+203C0,U+203C5,U+2040D,U+2042D,U+20435,U+2043A,U+20469,U+20509,U+2050C,U+2052D,U+2053E-2053F,U+20541-20542,U+20545-20547,U+20584,U+20587,U+205C2,U+205C9,U+205CC,U+205FB,U+20611,U+20627-20628,U+20646,U+2064F,U+20674,U+20676,U+206A4,U+206E1,U+206F1,U+20705,U+2070E,U+20731-20732,U+20734,U+20736,U+2073A,U+2073E,U+20779,U+207A9,U+207AB,U+207AD,U+207B0,U+207CD,U+207FA,U+20803-20804,U+2081D,U+20895,U+208FE,U+20904,U+2090E,U+20929,U+20930,U+20984,U+2099D,U+209AA-209AB,U+209B3,U+209DA,U+209E9,U+20A44-20A45,U+20A64,U+20A9A,U+20AB1-20AB2,U+20AE4,U+20B20,U+20B24,U+20B2A,U+20B36,U+20B56,U+20B6F,U+20B9F,U+20BB5-20BB7,U+20BBE-20BBF,U+20BD7-20BD8,U+20BE5,U+20BEA,U+20C34,U+20C41,U+20C53,U+20C5B,U+20C5E,U+20C78,U+20C8E-20C8F,U+20C96,U+20CBF,U+20CC1,U+20CC3,U+20CCF-20CD0,U+20CD4-20CD5,U+20CED,U+20CFC,U+20D02,U+20D15,U+20D1F,U+20D2B,U+20D32,U+20D46-20D47,U+20D5D,U+20D71,U+20D7C,U+20D7F,U+20DA7,U+20DE1,U+20DFA,U+20DFF,U+20E01,U+20E0E-20E0F,U+20E5A,U+20E76-20E77,U+20E95-20E96,U+20E98,U+20E9D,U+20EA2,U+20ED7-20ED8,U+20EF3,U+20EF9-20EFA,U+20F1F,U+20F22,U+20F2D-20F2E,U+20F3B,U+20F4C,U+20F7E,U+20F90-20F91,U+20F96,U+20FB4,U+20FBC,U+20FD5,U+20FEA,U+21014,U+21055,U+2105C,U+2106F,U+21075-21076,U+2107B,U+210A2,U+210AB,U+210BF,U+210C1,U+210C9,U+210E4,U+210F6,U+21116,U+21123,U+21145,U+21155,U+211A5,U+211CC,U+211D9,U+211FC,U+2123C-2123D,U+21244,U+21251,U+21265,U+2126B,U+21284,U+212EF,U+21334,U+21336,U+2134C,U+2136A,U+21372,U+21375,U+21377,U+2137C,U+2139A,U+213CB,U+21413,U+21428,U+2144D,U+2145E,U+21483-21484,U+214DA,U+21523,U+21562,U+215D7,U+215DC,U+215E6,U+21619,U+21681,U+216A6,U+216B1,U+216B4,U+216BD,U+216DF,U+216E3,U+216F0,U+21757,U+2176D,U+217C8,U+217D3,U+217DA,U+217E5,U+217EC,U+2180D,U+21824,U+21857,U+21883,U+218EA,U+2192B,U+21946,U+21948,U+21967,U+21976,U+2197C,U+21980,U+21982,U+219BC,U+219F3,U+21A18,U+21A1A,U+21A25,U+21A38,U+21A4B,U+21A61,U+21A7B,U+21ACF,U+21B36,U+21B54,U+21B90,U+21BC1-21BC2,U+21C26,U+21C2A,U+21C48,U+21C52,U+21C95,U+21CA2,U+21CAC,U+21CBE,U+21CDE,U+21D2D,U+21D49,U+21D53,U+21D59-21D5A,U+21D7B,U+21D84,U+21D8B,U+21D90,U+21DA6,U+21DAD,U+21DD1,U+21DE0,U+21DE8,U+21DEB,U+21DF8,U+21E03,U+21E16-21E17,U+21E1E,U+21E23,U+21E47,U+21E6C,U+21E8E,U+21E9F,U+21EA3,U+21EAF,U+21EB1-21EB2,U+21ECA,U+21ED5,U+21EED,U+21EEF,U+21F0F,U+21F15,U+21F31,U+21F3E-21F3F,U+21F57,U+21F71,U+21F7A,U+21F8B,U+21F9E,U+21FB0,U+21FB2,U+21FBC,U+21FD3,U+21FD6,U+21FE8,U+21FFA,U+21FFF,U+22016,U+22049,U+22058,U+220B3,U+220C7,U+22110,U+2213C,U+221A1,U+221C7,U+221CD,U+221F2,U+221F7,U+22208,U+2223B,U+2231A,U+2231E,U+22342,U+22399,U+2239E,U+223A5,U+223A8,U+22488-22489,U+224B0,U+224BC,U+224C1,U+224C9,U+224CC,U+224DC,U+224E1,U+224ED,U+224F2,U+22504,U+2251B,U+22521,U+22524,U+2256C,U+225A6,U+225A9,U+225B3,U+225BF,U+225D7,U+22609,U+2260D,U+2263F,U+22645,U+22650,U+2265D,U+226C1,U+226F3,U+2272D-2272F,U+22731,U+22736,U+22746,U+22775,U+227B5,U+22835,U+22838,U+22871,U+2289E,U+228BD,U+22927,U+22931-22932,U+2294C,U+22958,U+2295E,U+22960,U+2298F,U+2299F,U+229B6;}
@font-face{font-family:"WenKai";src:url(./wenkai-c72.6c4a461e.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+229F5,U+22A0B,U+22A41,U+22A73,U+22A83,U+22A87,U+22A8F,U+22A98,U+22AB1,U+22ACF,U+22AD3,U+22AD5,U+22AE6,U+22AEC,U+22B02,U+22B38,U+22B43,U+22BA5,U+22BCA,U+22BED,U+22BF2,U+22BF9-22BFA,U+22BFE,U+22C49,U+22C4B,U+22C51,U+22C55,U+22C62-22C64,U+22CAB,U+22CB4,U+22CB8,U+22CC0,U+22CC2,U+22CC6,U+22CCD,U+22CDA,U+22CDF,U+22CEA,U+22D08,U+22D32-22D33,U+22D4C,U+22D5E,U+22D67,U+22D80,U+22D89,U+22D8D,U+22D92,U+22DA1,U+22DEC,U+22E33,U+22E5D,U+22E72,U+22E83-22E84,U+22EB3,U+22F0C,U+22F1B,U+22F38,U+22F7E,U+22F96,U+22FBA,U+22FDB,U+23066,U+23073-23074,U+23080,U+2308F-23090,U+230DA,U+23119,U+23134,U+23138,U+23143,U+2319F,U+231C7,U+23206,U+23236,U+2329F,U+232BA,U+232C9,U+232DE,U+23350,U+23385-23386,U+23397,U+2339C,U+233B2,U+233B4,U+233B7,U+233CC,U+233DE,U+233E2,U+233FE,U+2340A,U+23415,U+23439,U+2343F,U+234C1,U+23519,U+2353A,U+235BE,U+235C4,U+235CB,U+235F6,U+23617,U+2361B,U+2363A-2363B,U+23657,U+2365C,U+23683,U+23698,U+236BA,U+236D2,U+236EE,U+23727,U+2372C,U+2373F,U+23749,U+2374B,U+2375B,U+23763,U+237C4,U+237F4,U+2385B,U+23936,U+23942,U+239D7,U+23A19,U+23A3C,U+23A81,U+23A8A-23A8B,U+23A8F,U+23A95,U+23A98,U+23AA0,U+23B02,U+23B1B,U+23B20,U+23B36,U+23B3C,U+23B61,U+23B72,U+23B88,U+23BAB,U+23BC8,U+23BCD,U+23BDA,U+23BE9,U+23BFE,U+23C07,U+23C0B,U+23C28,U+23C5D,U+23C76,U+23C7C,U+23C7E,U+23C97-23C98,U+23CA9,U+23CB5,U+23CB7,U+23CBE,U+23CE6,U+23CFE,U+23D13,U+23D18,U+23D66,U+23D7A,U+23D7D,U+23D82,U+23D88,U+23D8F-23D90,U+23D9E,U+23DFD,U+23E0E,U+23E23-23E24,U+23E70,U+23E8C,U+23EB0,U+23ECF-23ED0,U+23EF5,U+23EF8,U+23F0E,U+23F74,U+23F7D,U+24030,U+2406F,U+240D2,U+240EB-240EC,U+2410E,U+24136-24137,U+24182,U+2418A,U+241A2,U+241AC,U+241B5,U+241FE,U+2420E,U+24226,U+24259,U+242B6,U+242B9,U+242BB,U+242BE-242BF,U+242EE,U+24307,U+2430D,U+24319,U+24350,U+24352,U+2435E,U+24364,U+243D0,U+243F0,U+243F6,U+24419,U+24423,U+24430,U+24436,U+2447A,U+2447E,U+2448A,U+244D3,U+244EF,U+24514,U+24595,U+24605,U+24626-24627,U+2462F,U+24656,U+2468E,U+246A9,U+246CB,U+246CE,U+246D1,U+246D8,U+246DB,U+246DF,U+246ED,U+24716,U+24722-24723,U+24737,U+2473B,U+2474C,U+24759,U+24771,U+2477B,U+2477D,U+2479A,U+2479E,U+247A4,U+247B6,U+247C7,U+247CC,U+247CE,U+247D1,U+247E4-247E5,U+247E7,U+247EF,U+24822,U+2482B,U+24873,U+2488A,U+248B9-248BA,U+248CE,U+248E5,U+248E9,U+24904,U+24934,U+24950,U+2496D,U+249DB,U+249DF,U+24A01,U+24A0F,U+24A12,U+24A6A,U+24A7D,U+24A8C,U+24AA4,U+24AC9,U+24AF6,U+24B01,U+24B0F,U+24B1B,U+24B26,U+24B2A,U+24B5B,U+24B62,U+24B95,U+24BA6,U+24BD5,U+24BE5,U+24C00,U+24C09,U+24C1A,U+24C1C,U+24C48,U+24C4A,U+24C59,U+24C5D,U+24C8D,U+24CB0,U+24CB6,U+24CC8,U+24D13-24D14,U+24D21,U+24D25,U+24D2F,U+24D50,U+24D52,U+24D78,U+24D80,U+24D83,U+24DB8,U+24DCD,U+24DEA,U+24E01,U+24E2A,U+24E31,U+24E37,U+24E85,U+24EA5,U+24EA7,U+24EAA,U+24EBA,U+24ECA,U+24EF2,U+24F42,U+24F49,U+24F93,U+24F95,U+24FA9,U+24FD0,U+2500F,U+25050,U+25055,U+2505E,U+25061-25062,U+2506B,U+25109,U+25128,U+2512B,U+25134,U+25148,U+25160-25161,U+25167,U+2517B,U+2517E,U+2519E,U+251A7,U+251DB,U+251E2,U+25241-25242,U+25248-25249,U+2524C,U+25250,U+25273,U+2527B,U+2527F,U+25291,U+252DD,U+2531A,U+25320,U+25349,U+2538A,U+253DD,U+253EA,U+2541E,U+25435,U+2543B,U+2546A,U+2546E,U+254CD,U+254FC,U+25500,U+25532,U+2554D-2554E;}
@font-face{font-family:"WenKai";src:url(./wenkai-c73.2928d773.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+25562,U+25566,U+25584,U+2559A,U+255A8,U+255AA,U+255D9,U+255EC,U+255FD,U+2560C,U+2561E,U+25629-2562A,U+2562E,U+2563D,U+25651,U+2567F,U+256C4,U+256F1,U+25712,U+25714,U+2574C,U+25762,U+25767,U+257A5,U+257C7,U+2583B,U+25871,U+25874,U+258A7,U+258B6,U+258DB,U+258EC,U+2591A,U+2592E,U+25977,U+25997,U+259D1,U+259F2,U+25A0D-25A0E,U+25A10,U+25AB0,U+25AD7,U+25AF1,U+25AFD,U+25B1E,U+25B20,U+25B2F,U+25B98,U+25B9C,U+25BBE,U+25BD1,U+25BDB,U+25BDF,U+25BE4-25BE6,U+25BE8,U+25C14,U+25C1F,U+25C2B-25C2D,U+25C67,U+25C7C,U+25C7F,U+25C8A,U+25C91,U+25CA4,U+25CBB,U+25CC7,U+25CCE,U+25CD4,U+25CE0,U+25D0A,U+25D21,U+25D27,U+25D99,U+25DBD,U+25DD1,U+25DDA,U+25DE4,U+25DE8,U+25E46,U+25E49,U+25E77,U+25E86,U+25EC5,U+25ED7,U+25EE6,U+25EE9,U+25EF5,U+25EFF,U+25F1A,U+25F24,U+25F36,U+25F86,U+25F9D,U+25FBA,U+25FC9-25FCA,U+25FDD,U+25FEE,U+26016,U+26021,U+26049,U+26050,U+26085,U+2608C-2608D,U+260B3,U+260C2,U+260C4,U+260C7,U+260CF,U+260E9,U+2613C,U+2614C,U+261D9,U+261E7,U+26203,U+26216,U+26220-26222,U+26246,U+2624E,U+26258,U+2626A-2626B,U+26270-26271,U+26279,U+26291,U+26293-26294,U+2629A,U+2629E,U+262B1,U+262C6,U+26309-2630A,U+2633E,U+2634B-2634C,U+26351,U+26355,U+26369,U+26393,U+263B9,U+263C6,U+263F4,U+26407,U+2640A,U+2640C,U+26447,U+26476,U+26483,U+2648D,U+26491,U+264B9,U+264D6,U+264FE,U+26529,U+26548,U+26553,U+265D2,U+265F3,U+26614,U+26634,U+2664D,U+2666B,U+26676-26678,U+26690,U+2669F,U+266B0,U+266DD,U+266E8,U+26706,U+26760,U+26762,U+26769,U+2677C,U+26782,U+267A4,U+267A6,U+267CC,U+267D8,U+267EA,U+267EE,U+26806,U+2683F,U+26871,U+2688A,U+268C0,U+268DD-268DE,U+26900,U+2690E,U+26919,U+26936,U+26951,U+26954,U+2696F,U+26999,U+269C8,U+269DD,U+269DF,U+269E1,U+269F2,U+269F4,U+269FA,U+26A29,U+26A2D,U+26A34,U+26A3C,U+26A58,U+26A64,U+26A77,U+26A7A,U+26A87,U+26A99,U+26AAD,U+26ABD,U+26AC3,U+26AF8,U+26B01,U+26B28,U+26B38,U+26B3A,U+26B3C,U+26B4C,U+26B5C,U+26BB4,U+26BBC,U+26C0F,U+26C21,U+26C47,U+26C4C,U+26C52,U+26C54,U+26CC6,U+26CCB,U+26CDC-26CDD,U+26CEF,U+26D4F,U+26D67,U+26D78,U+26D7E,U+26D87,U+26D9F,U+26E05,U+26E08,U+26E87,U+26E96,U+26ED5,U+26ED8,U+26F09,U+26F4A,U+26F4F,U+26F8F,U+26F9B,U+26FAE,U+26FB6,U+26FC9,U+26FDA,U+2707E,U+27087,U+270D2,U+270FD,U+2711B-2711C,U+27138-27139,U+27141,U+27187,U+2718C,U+271E0,U+271FD,U+27222,U+27246,U+27248,U+27253,U+2725F,U+27267,U+2726A,U+2726E,U+2727E,U+27285,U+27288,U+27292,U+27294-27295,U+272B7,U+272D8,U+272E0-272E1,U+272E5,U+272F1,U+27304,U+2730F,U+27311,U+2733D,U+27355,U+27359,U+27367,U+2736A,U+27371-27372,U+27398,U+273A4-273A5,U+273BE,U+273DA,U+273E1,U+273FE,U+27410,U+27415,U+2741F,U+2742F,U+27431,U+27445,U+27452,U+27486,U+27495,U+274BD,U+274FD,U+274FF,U+27548,U+2754D,U+2755B,U+2759A,U+275E9,U+275F9,U+27607-27608,U+2763D,U+27665,U+276D7,U+276FE,U+27700,U+27741,U+27743,U+27749,U+2774B,U+2774E,U+2775D,U+27764,U+2776C,U+27794,U+277A4,U+277C4,U+277C9,U+277CC,U+277F0,U+278B2,U+278D2,U+278E6,U+278EA,U+2790F,U+27916-27917,U+2793E,U+27944,U+27963,U+2797A,U+279A0,U+279A7,U+27A33,U+27A3E-27A3F,U+27A63,U+27A76,U+27AB0,U+27ADD,U+27AF4,U+27B1E,U+27B28,U+27B2A,U+27B2F,U+27B48,U+27B53,U+27B88,U+27B99,U+27BAA-27BAB,U+27BC6,U+27BCB,U+27BF7,U+27C0E,U+27C19,U+27C28,U+27C35,U+27C49,U+27C53,U+27C82;}
@font-face{font-family:"WenKai";src:url(./wenkai-c74.72d4607b.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+27CB1,U+27CDC,U+27CDF,U+27CFD,U+27D03,U+27D06,U+27D10,U+27D2A,U+27D48,U+27D65,U+27D8A,U+27DA0,U+27DBA,U+27E18,U+27E5E,U+27EAF,U+27ED9,U+27EDE,U+27EF4,U+27F28,U+27F34,U+27F7B-27F7C,U+27FB1,U+27FB7,U+27FC1,U+27FD2,U+27FEC,U+27FF3-27FF4,U+27FF9,U+28001,U+28042,U+2804F,U+28057,U+2805D,U+280BD-280BF,U+280C5,U+280DE-280DF,U+280E9,U+280F0,U+2810C,U+2812E,U+2814D,U+28154,U+2815D,U+2816C,U+2818D,U+281AA,U+281E4,U+28201,U+28207,U+28210,U+28256,U+28263,U+282B0,U+282B8,U+282BB,U+282CC-282CD,U+282E2,U+282F0,U+28308,U+28325,U+2834F,U+2837D,U+2838A,U+2838D,U+283A5,U+283AA,U+283B9,U+283D2,U+283E9,U+283F9,U+28408,U+28420-28421,U+28468,U+2846E,U+28473,U+28485,U+28487,U+28492,U+284AB,U+284C6,U+284C8,U+284DA,U+284DC,U+284E6,U+28523,U+2853F,U+28595,U+2860C,U+2863B,U+2864A,U+28668,U+2866C,U+28676,U+28678,U+2867B,U+2868D,U+28693,U+28695,U+28697,U+286B2,U+286CB,U+286CD,U+286EB-286ED,U+286F3,U+28712,U+28714,U+2874D,U+28756,U+28778,U+287AA,U+287C9,U+287D6,U+287E0,U+287F9,U+287FB,U+28811,U+2886D,U+28891,U+288A2,U+288C8,U+288E7-288E8,U+28942,U+28948,U+28972,U+28987,U+289A1,U+289C0,U+289F1,U+28A0F,U+28A50,U+28B46,U+28B49,U+28B4E,U+28B5B,U+28C3B,U+28C3E,U+28C44,U+28C47,U+28C4D-28C4F,U+28C51,U+28C53-28C54,U+28C75,U+28C97,U+28CA0,U+28CCA,U+28CCD,U+28CD2,U+28CDD,U+28D46,U+28D66,U+28D80,U+28D88,U+28D92,U+28D99,U+28DB2,U+28DC8,U+28DF2,U+28DFA-28DFB,U+28E0F,U+28E14,U+28E17,U+28E1D,U+28E30,U+28E39,U+28E5D,U+28E93,U+28E99,U+28EAD,U+28EE7,U+28EF6,U+28EFB,U+28F4D,U+28F66,U+28F79,U+28F7B,U+28FCB,U+28FD8,U+2900E,U+290CE,U+290D9,U+290EC-290ED,U+290F1,U+29121,U+29166,U+2918A,U+29193,U+291D0,U+291D5,U+291EB,U+291EF,U+291F5,U+29259,U+2925C,U+29293,U+29299-2929A,U+29307-29308,U+2930A,U+2933D,U+2935C,U+2937F,U+29396,U+293F6-293F7,U+29405,U+29428,U+29454,U+2945D,U+2947E,U+294BA,U+294D0,U+294DE,U+294E3,U+294E5,U+29508,U+29544,U+29573,U+295D7,U+29601,U+2961A,U+2963B,U+2967F,U+2969F,U+296A8,U+296C3,U+296DE,U+296E9,U+296F2,U+296FD,U+29704,U+29707,U+29730,U+29736,U+2974E,U+29751,U+2976B,U+29781,U+297B0,U+2980C-2980D,U+29810,U+2981C,U+29869,U+2987A,U+298B0,U+298B2,U+298B7,U+298BC,U+298CA,U+298DA,U+298E1,U+298F1,U+29944,U+29947,U+29949,U+299B1,U+299BA,U+299C6,U+299D0,U+29A02,U+29A1C,U+29A2C,U+29A33,U+29A38,U+29A8B,U+29AF5,U+29AF8,U+29AFB,U+29B1E,U+29B4F,U+29B6A,U+29B9C,U+29BCB,U+29BF0,U+29C1E,U+29C24,U+29CE4,U+29D06,U+29D3E,U+29D40,U+29D4B,U+29D56,U+29D5A,U+29D60,U+29D71,U+29D88,U+29D98,U+29DA5,U+29DAD,U+29DAF,U+29DC0,U+29DD3,U+29DD5,U+29DDA,U+29DE9-29DEA,U+29DF6,U+29E00,U+29E04,U+29E0D-29E0E,U+29E19,U+29E36,U+29E3D,U+29E42,U+29E44,U+29E47,U+29E4E,U+29E7E,U+29EAC-29EAD,U+29EDF,U+29EF8,U+29F08,U+29F27,U+29F30,U+29F48,U+29F4F,U+29F70,U+29F73,U+29F7C,U+29F7E,U+29F83,U+29F87,U+29F8C,U+29F97,U+29F9A,U+29FBF,U+29FE3,U+29FE7,U+29FFA,U+2A001,U+2A00B,U+2A018,U+2A01A,U+2A049,U+2A04E-2A050,U+2A05C,U+2A05F,U+2A06A,U+2A084,U+2A086,U+2A0B4,U+2A0BA,U+2A0BF,U+2A0C8,U+2A0CF,U+2A0E7-2A0E8,U+2A106,U+2A133,U+2A136,U+2A14F,U+2A183,U+2A1A9,U+2A1BB,U+2A1C4,U+2A1C9,U+2A1D8,U+2A1E1,U+2A1F0-2A1F1,U+2A1F7,U+2A202,U+2A213,U+2A248,U+2A28D,U+2A291,U+2A2EE-2A2EF,U+2A318,U+2A32D,U+2A32F,U+2A333,U+2A351,U+2A353,U+2A35B,U+2A360,U+2A363,U+2A374,U+2A38A;}
@font-face{font-family:"WenKai";src:url(./wenkai-c75.ae789262.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+2A3AD,U+2A3BD-2A3BE,U+2A41E,U+2A434,U+2A46E,U+2A47E,U+2A49F-2A4A1,U+2A4B9,U+2A4D0,U+2A4DB,U+2A4EC,U+2A4F9,U+2A4FD,U+2A4FF,U+2A54C-2A54D,U+2A56F,U+2A581,U+2A590,U+2A599,U+2A5A2,U+2A5A8,U+2A5B7,U+2A5CB,U+2A600,U+2A612,U+2A61A,U+2A64A,U+2A668,U+2A695,U+2A6A5,U+2A6AE,U+2A6B0,U+2A6D7-2A6DF,U+2A703,U+2A736,U+2A79D,U+2A7DD,U+2A7E7,U+2A833,U+2A838,U+2A83D,U+2A848,U+2A8AE,U+2A8BC,U+2A8C8,U+2A8DD,U+2A8FB,U+2A917,U+2A970,U+2A9E6,U+2A9F7,U+2AA07,U+2AA0A,U+2AA17,U+2AA27,U+2AA30,U+2AA36,U+2AA58,U+2AAC6,U+2AB62,U+2AB75,U+2AB8B,U+2AB96,U+2ABB6,U+2ABC8,U+2ABE1,U+2AC76-2AC77,U+2AC94,U+2ADFD,U+2AE5A,U+2AED0,U+2AEDA,U+2AF47,U+2AF94,U+2AFA2,U+2AFA6,U+2AFD6,U+2B042,U+2B061,U+2B088,U+2B0D1,U+2B11B,U+2B11F,U+2B124-2B125,U+2B127-2B128,U+2B12B,U+2B136-2B138,U+2B18F,U+2B1E6,U+2B1ED,U+2B209,U+2B21F,U+2B230,U+2B241,U+2B244,U+2B2A5,U+2B2BB,U+2B2CC,U+2B300,U+2B328,U+2B359-2B35A,U+2B35F,U+2B362-2B363,U+2B36F,U+2B372,U+2B37B,U+2B37D,U+2B393,U+2B3AB-2B3AC,U+2B3CB,U+2B3D0,U+2B404,U+2B410-2B411,U+2B413,U+2B416,U+2B418,U+2B461,U+2B4A2,U+2B4E7,U+2B4E9,U+2B4EF,U+2B4F1,U+2B4F4,U+2B4F6,U+2B4F9,U+2B502,U+2B507,U+2B50D-2B50E,U+2B52D,U+2B536,U+2B583,U+2B592,U+2B594,U+2B598,U+2B5AE-2B5AF,U+2B5B3,U+2B5B9,U+2B5E0,U+2B5E6-2B5E7,U+2B5E9,U+2B5EB,U+2B5EE,U+2B5F0,U+2B5F4,U+2B61C-2B61D,U+2B624-2B628,U+2B62A,U+2B62C-2B62D,U+2B688-2B689,U+2B690,U+2B692,U+2B694-2B696,U+2B6A5,U+2B6AA,U+2B6AD,U+2B6DA,U+2B6DE-2B6DF,U+2B6E3,U+2B6E9,U+2B6ED,U+2B6F3,U+2B6F6,U+2B6F8,U+2B728-2B729,U+2B72C,U+2B730,U+2B735-2B73D,U+2B746,U+2B74F,U+2B751,U+2B758,U+2B75B,U+2B777,U+2B77A-2B77B,U+2B789,U+2B78E,U+2B797,U+2B79A-2B79B,U+2B79D,U+2B7A9,U+2B7BC-2B7BD,U+2B7C2,U+2B7C5,U+2B7D8,U+2B7E6-2B7E7,U+2B7F7,U+2B7F9,U+2B7FC,U+2B7FF,U+2B803,U+2B806,U+2B80A,U+2B81A-2B81C,U+2B823-2B824,U+2B826,U+2B892,U+2B899,U+2B8B8,U+2B8C6,U+2B8CA,U+2B92D,U+2B94E,U+2B95E,U+2B9B3,U+2B9C3,U+2B9C7,U+2B9EF,U+2B9FF,U+2BA4F,U+2BA51,U+2BA5B,U+2BA65,U+2BA6B,U+2BA74,U+2BA81,U+2BA88,U+2BA98,U+2BAC7,U+2BAE6,U+2BAFE,U+2BB37,U+2BB5F,U+2BB62,U+2BB6A,U+2BB72,U+2BB7C,U+2BB83,U+2BB85,U+2BBDC,U+2BC02,U+2BC06,U+2BC0D,U+2BC1B,U+2BC21,U+2BC2A,U+2BC30,U+2BCA6,U+2BCA8,U+2BCB7,U+2BD52,U+2BD58,U+2BD71,U+2BD77,U+2BD7A,U+2BD7C,U+2BD87,U+2BDA7,U+2BDAC,U+2BDC0,U+2BDC9,U+2BDF7,U+2BDF9,U+2BE29,U+2BE6F,U+2BE75,U+2BF17,U+2BF1D,U+2BF23,U+2BF4B,U+2BF67,U+2C029-2C02A,U+2C05F,U+2C080-2C081,U+2C089,U+2C09B,U+2C0A9,U+2C0AD,U+2C0C0,U+2C0CA,U+2C0D8,U+2C0EB,U+2C129,U+2C1AE,U+2C1D5,U+2C1D8-2C1D9,U+2C1DE,U+2C1F9,U+2C227,U+2C267,U+2C27C,U+2C288,U+2C29C,U+2C2A4,U+2C2B6,U+2C317,U+2C35B,U+2C361,U+2C364,U+2C370,U+2C386,U+2C39E,U+2C3BE,U+2C3DF,U+2C457,U+2C47D,U+2C488,U+2C494,U+2C497,U+2C4E0,U+2C533,U+2C542,U+2C58B,U+2C591,U+2C598,U+2C59E,U+2C613,U+2C616,U+2C618,U+2C61C-2C61D,U+2C621-2C622,U+2C629,U+2C62B-2C62D,U+2C62F,U+2C635,U+2C642,U+2C646-2C647,U+2C64A-2C64B,U+2C65E,U+2C696,U+2C728,U+2C72C,U+2C72F,U+2C79F,U+2C7C1,U+2C7FD,U+2C805,U+2C816,U+2C842,U+2C88A-2C88B,U+2C8C0,U+2C8D9,U+2C8DE,U+2C8E1,U+2C8F3,U+2C907,U+2C90A,U+2C910,U+2C916,U+2C91D,U+2C928;}
@font-face{font-family:"WenKai";src:url(./wenkai-c76.390e1a08.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+2C930,U+2C97A,U+2C9B0-2C9B1,U+2C9BB,U+2C9C0,U+2CA02,U+2CA0E,U+2CA7D,U+2CA8D,U+2CAA9,U+2CB29,U+2CB2B-2CB2E,U+2CB30-2CB32,U+2CB38-2CB3B,U+2CB3F,U+2CB41,U+2CB4A,U+2CB4D-2CB4E,U+2CB5A-2CB5B,U+2CB63-2CB64,U+2CB68-2CB69,U+2CB6C,U+2CB6F,U+2CB72-2CB74,U+2CB76,U+2CB78,U+2CB7C,U+2CBA4-2CBA6,U+2CBB1,U+2CBB4,U+2CBBF-2CBC0,U+2CBCE,U+2CC56,U+2CC5F,U+2CC66,U+2CC6D,U+2CCB1,U+2CCBD,U+2CCC7,U+2CCF3,U+2CCF5-2CCF6,U+2CCFD,U+2CCFF,U+2CD02-2CD03,U+2CD0A,U+2CD10,U+2CD68,U+2CD81,U+2CD8B-2CD8D,U+2CD8F-2CD90,U+2CD9F-2CDA0,U+2CDA7-2CDA8,U+2CDAD-2CDAE,U+2CDD5,U+2CE01,U+2CE05,U+2CE08,U+2CE0A,U+2CE18,U+2CE1A,U+2CE22-2CE23,U+2CE26,U+2CE29-2CE2A,U+2CE31,U+2CE7C,U+2CE88,U+2CE93,U+2CEA4,U+2CEA8,U+2CEAD,U+2CF65,U+2D026,U+2D075,U+2D079,U+2D0C2,U+2D11B,U+2D139,U+2D208,U+2D25D,U+2D382,U+2D475,U+2D544,U+2D546,U+2D613,U+2D64F,U+2D655,U+2D6A6,U+2D70C,U+2D80D,U+2D8C7,U+2D8E7,U+2D930,U+2DA5A,U+2DA86,U+2DAA4,U+2DC49-2DC4A,U+2DCFF,U+2DD08,U+2DD0A,U+2DDD4,U+2DE5C,U+2DED9,U+2DEFE,U+2E00E,U+2E014,U+2E0B9,U+2E0C4,U+2E18F,U+2E1D8,U+2E261-2E262,U+2E264,U+2E267-2E268,U+2E26A-2E26C,U+2E26F,U+2E278,U+2E41A,U+2E428,U+2E502,U+2E505,U+2E50A,U+2E51A,U+2E569,U+2E581,U+2E5B1,U+2E5FB,U+2E64A-2E64B,U+2E6EA,U+2E774-2E775,U+2E777-2E77A,U+2E81E,U+2E8F2-2E8F7,U+2E932,U+2E9F4-2E9F5,U+2EA3B,U+2EA5B,U+2EA5D-2EA5E,U+2EAA5,U+2EAC2,U+2EB1B-2EB24,U+2EB65-2EB66,U+2EB68,U+2EB6A,U+2EB70,U+2EB87,U+2EBD9,U+2F804,U+2F80F,U+2F818,U+2F81A,U+2F822,U+2F828,U+2F82C,U+2F833,U+2F83B,U+2F83F,U+2F852,U+2F862,U+2F86D,U+2F873,U+2F877-2F878,U+2F884,U+2F89A-2F89B,U+2F8AC,U+2F8B2,U+2F8B6,U+2F8D2-2F8D3,U+2F8DB-2F8DC,U+2F8E1,U+2F8EA,U+2F8ED,U+2F8FC,U+2F903,U+2F90B,U+2F90F,U+2F91A,U+2F920-2F921,U+2F945,U+2F947,U+2F96C,U+2F995,U+2F9D0,U+2F9DE-2F9DF,U+2F9F4,U+30001-30002,U+30004-30006,U+30008-30009,U+30020-30022,U+30053,U+3005C,U+30061,U+3006C,U+30072,U+30078,U+3007C,U+3008E,U+300DD,U+300EE,U+300F7,U+3011D,U+30149-3014A,U+30170,U+30174,U+30179,U+3018A,U+30196,U+301B3,U+301BB,U+301DB,U+301E0,U+301E2-301E3,U+301F0,U+30270,U+302C0,U+302D9,U+302DB-302DC,U+302DE,U+302F7,U+302FB,U+30300,U+30302,U+30335,U+3033B,U+3034E,U+30367-30368,U+30370-30371,U+30396,U+303A0,U+30409,U+30414,U+3043A,U+3043F,U+3044A,U+3044C,U+30450,U+3045D-3045E,U+304BC,U+304CA,U+304CC,U+304D9,U+304E2-304E3,U+304E8,U+304EC-304ED,U+3057A,U+305D1,U+305D6,U+305DC-305DD,U+305E3,U+305F6,U+3067D,U+306D1-306D3,U+306E6,U+306EC,U+306F4,U+30708,U+30729,U+30733,U+30776,U+30787,U+307D8,U+30828,U+30831,U+30842,U+30849,U+30853,U+30858,U+308CA,U+308F2,U+308FB,U+30915,U+3094C,U+3094F,U+30955,U+3095B,U+30969,U+30993,U+3099C,U+309AA-309AB,U+309C9,U+30A16,U+30A1B,U+30A62,U+30A67,U+30AA9,U+30AB1,U+30ABF,U+30AFD-30AFE,U+30B04,U+30B0A,U+30B14-30B15,U+30B18,U+30B2A,U+30B38,U+30B43,U+30B4B,U+30B5D,U+30B87,U+30BA4,U+30BF2,U+30BF6,U+30BFC,U+30C1F,U+30C21,U+30C24,U+30C28,U+30C2B-30C2C,U+30C53,U+30C5F,U+30C69,U+30C71-30C72,U+30CBD,U+30CC7,U+30D4B,U+30D55,U+30D5D-30D5F,U+30D63;}
@font-face{font-family:"WenKai";src:url(./wenkai-c77.21f7c549.woff2) format("woff2");font-weight:normal;font-style:normal;font-display:swap;unicode-range:U+30D64,U+30D66-30D67,U+30D69,U+30D74,U+30D7C,U+30D8A,U+30D8C,U+30DDF-30DE0,U+30DE3,U+30DE5-30DE6,U+30E01,U+30E04,U+30E6C,U+30E70,U+30E72,U+30E77,U+30E79,U+30EDD-30EDE,U+30F03,U+30F57,U+30F59-30F5A,U+30F5C,U+30F5F,U+30F62,U+30F64,U+30F66,U+30F6A,U+30F74,U+30F7C-30F7D,U+30F82,U+30F91,U+30F9B,U+30FA0,U+30FAB,U+3106C,U+31076,U+31090,U+310A8-310AA,U+310B1,U+310EA,U+310F1,U+310FA,U+31148,U+3114B-3114C,U+31151,U+3115B,U+311A5,U+311CF,U+311D1-311D2,U+311DD,U+311E3,U+311EB,U+311EE,U+311F1,U+311F3,U+311F6,U+311FB,U+311FE,U+31203,U+3120C,U+3124D,U+31250,U+31254,U+31270,U+31275,U+3127B-3127C,U+31283,U+31288,U+3128A,U+3128C,U+312AC-312AD,U+312B3,U+312D0,U+3132E,U+31342,U+31357,U+313BC,U+313F1,U+313FF,U+3143F,U+31455,U+3145E,U+3154C,U+31587,U+3158E,U+31592,U+315E9,U+31677,U+316A6,U+316E5,U+3176B-3176C,U+317DB,U+318C9,U+3190F,U+31AC9,U+31B92,U+31B9C,U+31BB8,U+31BC4,U+31BCD,U+31C17,U+31C1B,U+31C2E,U+31C3E,U+31C7F,U+31CEA,U+31D1F,U+31D31,U+31E07,U+31E25,U+31E40,U+31E4D,U+31EB0,U+31F00,U+31F11,U+32003,U+32070,U+32084,U+3208D-3208E,U+32117,U+3211A,U+321F4,U+321FD,U+32217,U+32235,U+32239,U+32245,U+322E4,U+3234C,U+3235B,U+3236D,U+3237F;}

/*
   fonts.css — 冥想统计看板 demo · V2「册页」字体子集（X1 工卡·字体子集管线）
   CARD-F3（20260721）构建拆分改造：base64 内嵌 → 二进制文件引用（长缓存友好，
   对应 SPEC §7 服务器出口 3Mbps 门；字体 274KB 终身只下一次不再随每次访问重传）。
   三个 @font-face 的 url() 目标是占位符（QIJI/WENKAI/MONONUM 三个字体 key，
   各自套双花括号+_WOFF2_URL 后缀），由 web/build.js 按内容 sha256 前 8 位替换为
   dist/assets/ 下的真实哈希文件名；占位符名字不得改（build.js 靠 includes() 校验）。
   ⚠ 本注释故意不把占位符原文整串写出——它在下方 @font-face 里只应出现一次，
   写在文档里会被构建脚本的字符串替换误命中（CARD-F3 实测踩过的坑，见 build.js
   同款注释）。
   源二进制在 web/fonts/*.woff2（只读来源=demo/fonts/*-subset.woff2 原样复制，
   本文件不再是唯一的字体真源，改动字体需同时改 demo 侧子集再复制）。

   三层字体，family 名钉死，全 OFL 授权，子集化后独立 woff2 文件，零外部运行时依赖：
     display 巨字 QiJi   ← 齐伋体（明代刻本字形，LingDong-/qiji-font，OFL-1.1）
     body   正文 WenKai  ← 霞鹜文楷 LXGW WenKai Regular（lxgw/LxgwWenKai，OFL-1.1）
     num    数字 MonoNum ← JetBrains Mono Regular（JetBrains/JetBrainsMono，OFL-1.1）

   子集来源：src/gen-chars.js 扫描/显式清单生成 fonts/chars-*.txt →
     python -m fontTools.subset <字体> --text-file=<chars.txt> --flavor=woff2 --output-file=<out.woff2>
   子集体积（子集化后，V4.2 立轴首屏+度牒字段替换重子集 20260721，CARD-F3 实测校正）：
     WenKai 122.6 KB / QiJi 52.2 KB / MonoNum 29.3 KB，合计 204.2 KB
   （远低于 SPEC 3 规定的 700KB 预算上限；WenKai 是正文字体，计入首屏关键集 gzip
   预算，QiJi/MonoNum 走 font-display: swap 异步加载，不计首屏）

   回退栈（字体加载失败/子集缺字时页面仍可读，font-display: swap）：
     QiJi   → WenKai → "KaiTi", "STKaiti", serif
     WenKai → "KaiTi", "STKaiti", "Songti SC", serif
     MonoNum → ui-monospace, Consolas, monospace

   使用规则（SPEC 3 排印细则）：
     - 齐伋体（QiJi）禁做正文：字符集不全（仅显式清单 80 字），刻本字小号难读，只用于巨字标题/地支/产品名/印章。
     - 文楷（WenKai）正文最小 15px；巨字 letter-spacing −0.01em~0、行高 1.1；正文行高 1.75。
     - 一切统计数字/日期/时刻一律 MonoNum，tabular-nums，中文与数字混排时数字不切中文字体。
*/

@font-face {
  font-family: "QiJi";
  src: url(./qiji.39c06f20.woff2) format("woff2");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "WenKai";
  src: url(./wenkai.4e908ee5.woff2) format("woff2");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "MonoNum";
  src: url(./mononum.ba347bd0.woff2) format("woff2");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* ============================================================================
   tokens.css — 冥想统计看板 demo 设计令牌（X2 工卡 · V2「册页」全案）
   ⚠ 本文件为 V2 推倒重做整体替换件，V1 双主题（极简 minimal / 水墨 ink）令牌
   契约作废；V1 成品已存档于 dist\冥想统计看板-demo-v1存档.html，不再维护。

   结构：
     第一层 primitive —— design-system-playbook/design-tokens.css 原样拷贝，
       不改一字（惯例：跨项目共享的机械尺度层：间距/控件高度/动效曲线/
       降级工具类）。V2 单主题不使用其中的通用灰阶/语义状态色/图表灰阶，
       保留只为遵循 playbook 拷贝纪律，不代表业务侧引用。
     第二层 semantic —— 本文件唯一改写区，V2「册页」单一主题
       （data-theme="ink" 沿用，同时写在 :root 上做零属性兜底）。
   使用纪律：全站业务代码（app.css 及 X3/X4 全部产物）颜色只能写 var(--*)，
   本文件是唯一允许出现裸色值（hex/rgba 字面量）的地方（gates.py no-raw-hex
   按文件名自动放行 tokens.css）。
   ========================================================================== */

/* ============================================================================
   第一层 · PRIMITIVE（原样拷贝自 design-system-playbook/design-tokens.css v1.1，
   不改一字；V2 语义层不引用其中的通用灰阶/语义色/图表灰阶/生成的 focus-ring，
   只借用间距/控件尺寸/动效时长-曲线/降级工具类这几组跨项目机械尺度）
   ========================================================================== */
:root {
  /* ---- 灰阶 · 中性系(默认;工具/精密感产品) ----------------------------------
     10 级"意图编码":每级一个固定职责,不是越深越重要 [官方:Vercel design.md] */
  --bg:        #FFFFFF;  /* 页面底 */
  --bg-2:      #FAFAFA;  /* 次级区块底/表头底 */
  --fill-1:    #F5F5F5;  /* 控件默认底 · 行 hover 底 */
  --fill-2:    #EBEBEB;  /* 控件 hover 底 */
  --fill-3:    #E0E0E0;  /* 控件 active 底 */
  --line:      #ECECEC;  /* 分隔线 —— 全站唯一 */
  --border:    #E2E2E4;  /* 控件边框 —— 全站唯一 */
  --border-hv: #CFCFD2;  /* 边框 hover(同笔更深一档,不换色) */
  --ink-ph:    #9A9A9A;  /* 仅 placeholder/禁用字。注意:白底 2.8:1 不过 WCAG AA
                            (placeholder 不在豁免清单!)——严格合规项目改 #767676
                            并靠字重/斜体区分占位与正文 [官方:WCAG 1.4.3] */
  --ink-2:     #666666;  /* 次级文字/图标(白底 5.7:1 过 AA) */
  --ink:       #111111;  /* 主文字/主按钮底 = 主色 */
  /* 次次级文字不再拍新灰值:color:var(--ink) + opacity .6/.3 [官方:Apple 同基色透明度阶梯] */

  /* ---- 半透明叠加(叠在色块/图表/图片上时用它,不用实色灰,防发脏) [官方:Vercel] */
  --alpha-1: rgba(0,0,0,.03);
  --alpha-2: rgba(0,0,0,.05);
  --alpha-3: rgba(0,0,0,.08);
  --alpha-4: rgba(0,0,0,.14);  /* 输入框默认边(alpha 式,随底色自适应) [官方:Geist] */

  /* ---- 语义色:只进状态点/pill/涨跌/告警/图表,永不进骨架 [实测:Attio 法则] ---- */
  --ok:   #16A34A;
  --warn: #D97706;
  --err:  #DC2626;
  --info: #2563EB;   /* 只许缩在圆点/pill 里,不做链接色不做焦点环 */

  /* ---- 图表灰阶(亮度必须单调:网格 > 轴线 > 轴标签,gates 可排序验证) -------- */
  --chart-s1:    #18181B;  /* 主系列(近黑非纯黑) */
  --chart-s2:    #71717A;  /* 第二系列 */
  --chart-s3:    #A1A1AA;  /* 第三系列;>3 系列才允许引入色相 */
  --chart-grid:  #F4F4F5;
  --chart-axis:  #E4E4E7;
  --chart-label: #71717A;

  /* ---- 圆角 [官方:Vercel 6/12/999 + 实测:Notion 4/8-12] ---- */
  --r-xs:   4px;    /* kbd 徽标/小按钮 */
  --r-ctl:  6px;    /* 按钮/输入框 */
  --r-card: 10px;   /* 卡片 */
  --r-pop:  12px;   /* 菜单/弹窗/抽屉 */
  --r-pill: 999px;

  /* ---- 阴影:默认态零阴影,只属于浮层 [官方:Vercel design.md 原值] ---- */
  --sh-raised: 0 2px 2px rgba(0,0,0,.04);
  --sh-pop: 0 1px 1px rgba(0,0,0,.02), 0 4px 8px -4px rgba(0,0,0,.04),
            0 16px 24px -8px rgba(0,0,0,.06);
  /* Notion 式更软替代(内容类产品):多层且每层 alpha≤.05 [实测] */

  /* ---- 焦点环:双层同心(第一层=与底同色的间隙,第二层才是环) [官方:Geist 结构] */
  --focus-ring: 0 0 0 2px #FFF, 0 0 0 4px #111;
  --focus-ring-err: 0 0 0 2px #FFF, 0 0 0 4px var(--err);

  /* ---- 动效 [官方:Vercel 150/200/300 + 一手:Emil Kowalski/Rauno] ----
     纪律: 只动 transform/opacity;禁 transition:all;退场≈进场×0.67;
     高频动作(命令面板/右键菜单)0ms;数据密集场景禁过冲(bezier 无 >1 分量) */
  --t-press: 120ms;   /* 按下反馈 */
  --t-fast:  160ms;   /* hover/tooltip/小浮层 */
  --t-pop:   200ms;   /* 菜单/下拉开合 */
  --t-modal: 240ms;   /* modal/drawer 进场 */
  --t-exit:  160ms;   /* 退场 ≈ 进场×0.67 [一手:Rauno;断言比例∈0.5-0.8] */
  --ease-out:  cubic-bezier(.23, 1, .32, 1);      /* 默认:进场与反馈 */
  --ease-exit: cubic-bezier(.4, 0, 1, 1);         /* 退场快收 [官方:M3 accelerate 系] */
  --ease-move: cubic-bezier(.77, 0, .175, 1);     /* 屏内 A→B 位移 */
  /* ---- v1.1.1 iOS 开合三 token(owner 20260806 验收 glass demo 后定案;
     曲线=Ionic 对 iOS 弹窗的工程复刻实测值,20260806 调研逐值核过源码)。
     页面切换仍走 --t-page 快切,两套体系互不相扰。 ---- */
  --ease-spring: cubic-bezier(.32, .72, 0, 1);
  --t-pop-open:  500ms;   /* 浮出物打开(浮窗/菜单/日历) */
  --t-pop-close: 280ms;   /* 浮出物收回 */
  /* 禁纯 ease-in 做进场(慢启动=迟钝感) [一手:Emil];
     spatial(transform)时长 ≥ effects(opacity/color)时长 [官方:M3,可断言] */

  /* ---- 交互状态层: 同一色源(近黑)单调递增 [官方:M3 8/10/10/16% 结构,
       数值按白底下调——彩色 tonal 面的叠加量放白底会过重] ---- */
  --state-hover: rgba(0,0,0,.04);
  --state-focus: rgba(0,0,0,.06);
  --state-press: rgba(0,0,0,.06);
  --state-drag:  rgba(0,0,0,.10);

  /* ---- 排印 ----
     中文陷阱三条 [实测/官方:clreq+Inter 文档]:
     ① 字重只用 400/600(YaHei 无 500,浏览器伪加粗会糊;中等强调用颜色不用字重)
     ② 数字必须命中西文字体(CJK 字体无 tnum,tabular-nums 才能生效)——靠栈序实现
     ③ 中文禁负 letter-spacing;按钮文字垂直居中用 flex 不用 line-height 法 */
  --font-ui: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI",
             "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
  --fs-aux:   12px;   /* 仅时间戳/版本号等强辅助,禁正文 */
  --fs-table: 13px;   /* 表格,行高 1.45 */
  --fs-body:  14px;   /* 中文正文下限 [官方:AntD 阅读距离依据],行高 1.6 */
  --fs-sub:   16px;
  --fs-h3:    20px;   /* 标题行高 1.2-1.35;层级=字号跳跃+字重跳跃,不做线性递增 */
  --fs-h1:    28px;
  --lh-body:  1.6;
  --lh-table: 1.45;
  --lh-tight: 1.3;

  /* ---- 间距(8pt 网格,半格 4 允许) [官方:Apple/Tailwind]
       两条定律 [书摘:Refactoring UI]: ①相邻档差 ≥25%(4/8/12/16/24/32/48/64 合规);
       ②组内间距 < 组间间距,比例 ≥2×(相关性=距离,可量测断言) ---- */
  --s1: 4px;  --s2: 8px;  --s3: 12px;  --s4: 16px;  --s5: 24px;  --s6: 32px;  --s7: 48px;

  /* ---- 控件尺寸 [官方:Geist] ---- */
  --h-ctl-s: 32px;  --h-ctl: 36px;  --h-ctl-l: 40px;
  --pad-ctl: 0 12px;
}

/* ---- 必备工具类(与 token 同源,业务侧直接用;沿用 primitive 惯例) ---- */
.tnum { font-variant-numeric: tabular-nums; }  /* 一切 KPI/金额/数字列必挂;
        验证法:渲染"1"和"0"量宽相等(CSS 不报错≠生效) */
kbd {
  font: 500 12px/1 var(--font-ui);
  padding: 2px 6px; border-radius: var(--r-xs);
  background: var(--fill-1); border: 1px solid var(--border); color: var(--ink-2);
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  /* 正确降级=去位移保留 opacity/color 感知,不是把"变化发生了"的信息一起删
     [官方:Apple HIG Motion] */
}


/* ============================================================================
   第二层 · SEMANTIC —— V2「册页」单一中式编辑排印主题
   （替换 V1 双主题 minimal/ink 契约；data-theme="ink" 沿用，:root 同值兜底，
   全站业务代码不再引用 --bg/--surface/--accent 等 V1 名字，一律改用下表）

   ---- 对比度实测记录（gates.py contrast，四色封顶纪律 SPEC §2）----
   fg          bg(--paper #f3ede0)   bg(--paper-2 #faf6ec)  bg(--paper-3 #eae2d0)
   --ink-2 #4a4438     8.28:1 OK            8.95:1 OK              7.49:1 OK
   --ink-3 见下条备注(已加深)
   --red-text/--line-red #b13b2e   5.09:1 OK   5.51:1 OK   4.61:1 OK(踩线达标)
   --indigo #425066    7.00:1 OK            7.57:1 OK              6.34:1 OK
   --ink   #1a1a1a     14.92:1 OK           16.13:1 OK             13.50:1 OK

   ⚠ --ink-3：SPEC §2 原值 #8a8171 实测对三种纸色均未达 4.5:1
     （3.30:1 / 3.56:1 / 2.98:1，其中对 --paper-3 甚至跌破 3.0:1 大字门槛），
     按 SPEC 本条注释「不达标则升 --ink-2」自行加深至 #675e50，
     加深后实测 5.47:1 / 5.91:1 / 4.95:1 三色全过 4.5:1，
     气质仍浅于 --ink-2（重墨），保留「淡墨」层级但不再是不可读的弱文本。
   ========================================================================== */
:root,
[data-theme="ink"] {
  /* ---- 四色封顶：纸(3阶)/墨(3阶)/朱(3用途)/黛(1) —— SPEC §2 令牌全表 ---- */
  --paper:      #f3ede0;  /* 宣纸 · 页面底（R7 验算基准，暖白非冷白） */
  --paper-2:    #faf6ec;  /* 票面 · 票据卡面/输入面/浮层底 */
  --paper-3:    #eae2d0;  /* 衬纸 · 本人行衬底/hover 衬底 */
  --paper-3-rgb: 234, 226, 208;  /* 衬纸 RGB 三元组（供 app.css 云絮渐变 rgba() 引用，避免裸色值，值与 --paper-3 保持同步） */
  --paper-2-rgb: 250, 246, 236;  /* 票面 RGB 三元组（R-032②：供成就清单浮层滚动渐变遮罩 rgba() 引用，与浮层卡底色 --paper-2 一致，避免裸色值，值与 --paper-2 保持同步） */
  --ink:        #1a1a1a;  /* 浓墨 · 主文（对纸 14.9:1） */
  --ink-2:      #4a4438;  /* 重墨 · 次级文 */
  --ink-3:      #675e50;  /* 淡墨 · 弱文/轴标/装饰刻线（已加深，见上方实测记录） */
  --line:       #c9bfa8;  /* 乌丝 · 默认界线/细线/界格 —— 全站唯一分隔灰 */
  --line-red:   #b13b2e;  /* 朱丝 · 强调界线（本人行/当前项/当前时辰弧） */
  --seal:       #ff461f;  /* 印朱 · 仅印章底色与色点，禁止做文字色 */
  --red-text:   #b13b2e;  /* 深朱 · 朱色文字唯一合法值（今日之数/榜首/校验错误） */
  --indigo:     #425066;  /* 黛蓝 · 辅强调文字（链接/次强调/英文体位） */

  /* 图表/热力/时辰盘：墨渍五阶（浓→淡），SPEC §2 固定值 */
  --chart-1: #1a1a1a;
  --chart-2: #4a4438;
  --chart-3: #7a7060;
  --chart-4: #ab9f88;
  --chart-5: #d6cdb8;

  /* ---- 字体三层（家族名钉死 QiJi/WenKai/MonoNum，由字体管线 @font-face 注册；
       本文件只声明栈序与回退，字体文件本身不属于 X2 工卡） ---- */
  --font-display: "QiJi", "WenKai", "KaiTi", "STKaiti", serif;          /* 齐伋体：巨字/地支/印章字，禁做正文；缺字回退内嵌文楷（V2 §3 规定栈） */
  --font-body:    "WenKai", "KaiTi", "STKaiti", "Songti SC", serif;     /* 霞鹜文楷：正文/按钮/标签/成员名 */
  --font-num:     "MonoNum", ui-monospace, Consolas, "WenKai", "KaiTi", "STKaiti", monospace; /* JetBrains Mono：数字/拉丁；混排汉字(时/分/天/笔/第/号/称号词)逐字回退内嵌文楷,杜绝系统黑体混入(G2 20260721 终审修) */

  /* ---- 字号（SPEC §4/§5 逐条落值） ---- */
  --fs-masthead:     11px;  /* 报头三段小字 */
  --fs-toc:          15px;  /* 目录条/纸签栏 */
  --fs-folio-d:      80px;  /* 巨字页标 · 桌面（SPEC 范围 64-88px） */
  --fs-folio-m:      50px;  /* 巨字页标 · 移动（SPEC 范围 44-56px） */
  --fs-folio-note:   12px;  /* 巨字页标小字注 */
  --fs-tagrule-label: 13px; /* 题签分隔左标题 */
  --fs-tagrule-meta:  12px; /* 题签分隔右端小字 */
  --fs-fieldlabel:   11px;  /* 字段表左列宽距小标签 */
  --fs-fieldvalue:   15px;  /* 字段表右列值 */
  --fs-ticketfoot:   11px;  /* 票据批次页脚 */
  --fs-body:         15px;  /* 正文下限（SPEC「文楷正文最小 15px」） */
  --fs-sub:          16px;  /* 面板标题/空态标题等次级标题字号 */
  --fs-body-sm:      13px;  /* 辅助/次级说明（非「正文」，不受 15px 下限约束） */
  --fs-caption:      12px;  /* 通用小字注/补录标记/页脚 */
  --fs-hero-num-d:   72px;  /* 核心数字横幅 · 桌面 */
  --fs-hero-num-m:   48px;  /* 核心数字横幅 · 移动 */
  --fs-hero-unit:    15px;  /* 「分钟」单位小字 */
  --fs-dizhi:        15px;  /* 时辰钟地支字 */
  --fs-dial-center:  32px;  /* 时辰钟盘心巨字 */
  --fs-dial-sub:     11px;  /* 时辰钟盘心小字注 */

  /* ---- V3 书名页专属字号（SPEC V3 §3，独立于站内 --fs-folio-*，
       避免登录/注册页的更高一级尺度牵动今日/我的/管理/排行榜等站内页标） ---- */
  --fs-book-title-d:   108px; /* 登录巨字「练功记录」· 桌面（SPEC 范围 96-120px） */
  --fs-book-title-m:   60px;  /* 登录巨字 · 移动（SPEC 范围 56-64px） */
  --fs-book-subtitle:  22px;  /* 注册页题签级标题「入册——新同修注册」 */

  /* ---- 行高 ---- */
  --lh-display: 1.1;   /* 巨字标题 */
  --lh-body:    1.75;  /* 正文（中文视觉密度高于西文 1.5 惯例） */
  --lh-tight:   1.3;   /* 字段表/票据内紧凑行高 */

  /* ---- 字距 ---- */
  --ls-wide:    0.18em;  /* 报头三段小字宽字距 */
  --ls-toc:     0.05em;  /* 目录条/纸签栏宽字距 */
  --ls-label:   0.08em;  /* 字段表标签/轴标宽字距 */
  --ls-display: -0.01em; /* 巨字标题（中文大字禁正向拉开，收紧近刻本观感） */

  /* ---- 线宽（乌丝栏/朱丝栏/虚线/文武线，SPEC §4.5 语汇） ---- */
  --lw-hair:  0.5px;  /* 乌丝内框/界格/时辰钟刻度环 */
  --lw-line:  1px;    /* 乌丝默认线/虚线分段/题签分隔线 */
  --lw-thick: 1.5px;  /* 票据卡外框（文武线粗线） */
  --lw-heavy: 2px;    /* 目录条当前项短朱线/巨字标题下划线 */

  /* ---- 圆角：全站硬顶 ≤4px，且仅限小控件（票据/巨字容器方角零圆角） ---- */
  --r-sm:  2px;  /* 墨块滑钮/输入格/月份小按钮 */
  --r-ctl: 3px;  /* 确认键/印章方章磨边 */

  /* ---- 动效：页面切换沿用既定单层透明度节奏，其余复用 primitive 层曲线 ---- */
  --t-page: 120ms;  /* 页面切换（SPEC §4.2「单层透明度 ≤140ms」，D13 定为 120ms） */

  /* ---- 阴影/遮罩：默认零阴影，仅浮层（录入票据/时辰钟明细浮层）使用暖褐调 ---- */
  --shadow-float: 0 6px 28px rgba(26, 20, 14, .16), 0 1px 2px rgba(26, 20, 14, .10);
  --scrim:        rgba(26, 26, 26, .35);
  /* V4.2（SPEC §3 R-014②）：登录/注册渐显浮层专用遮罩=墨色 20%（比 --scrim 更浅，
     立轴在虚焦中仍隐约可见），RGB 三元组拆出供 rgba() 引用（同 --paper-3-rgb 先例，
     token 文件本身是唯一允许裸色值的地方，业务层 app.css 只准 var()/rgba(var())）。 */
  --ink-rgb:      26, 26, 26;
  --scrim-book:   rgba(26, 26, 26, .2);
  /* V4.2（SPEC §2.2）：立轴 1280 两侧发丝竖线专用——乌丝色 30-40% 透明度 */
  --line-rgb:     201, 191, 168;

  /* ---- 宣纸纹理：构建期烘焙（feTurbulence 多层噪点合成 PNG，多重八度 + 横向轻拉伸
       还原纤维走向），data-URI 平铺，α 上限 10/255(≈3.9%)，满足「≤4% 强度」纪律，
       颜色恒定暖米（RGB 214,201,170），配 multiply 混合模式叠于 --paper 之上，
       不采用运行时 SVG filter（R7 §5.1 明确指出滚动/动画容器逐帧重算掉帧），
       静态背景一次性绘制，性能零风险 ---- */
  --texture-xuanzhi: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANwAAADcCAYAAAAbWs+BAAARrUlEQVR42u1dWbLkOA4TMnT/g8xN5gJzHczfLNWv83nhAlJ0RP10VadtWRQ3AMS//vmPvWwvXvxvML4vgn6Ly/6C0Tpf+Tu8vDdf/pvM784HvwfL/fxZOReW7oULf49D1mIu4+sT4N0iNtVpm5biz4fm3wkqBnfShQM3PIuvD7J/d89Gncv5W7PQd4f3Pv4Evwyaea2Md+LDd0HimmIik/96OBjlCHRYCAYuIJbNSe55Tzr8/lUPpJ43en0vWhrpvvChmGRsbzay+kdULJR0Mqg7ey405N0CG+nN/SH+ESN6bqd4mswQkw/Tjb/8zhZYGDy8Px5uVBRqwvOA6i6CwAQUMFzs5E2BhA3Nv/kYUz3NO1wQZBDpKKFdrCK4prk9vcjKNYHPoAfaex6vsjxEDQuBByCqIE0geB828h744TcG/ykQhezgOBgClTA4NJW9cKVw6r1FHxZ0OOxKGv0OSkjRLNfgsi3aqJfO364xhCqFGdSx0JBywg8bxAhE1vpN3gSBfpp1GkFvD4foU2Guy6FaRnsDCdECAiIYePz7oef0qkRWYKp3bbvQy+A4+7xkNROBqKBvB8Bb75TJgrhS/KFVSOkdrijwpjh5aFuPx2UTVvImswJ/GhyLebdvsCy+oPpU9dxXMaZ0wEBGw64gtua3CzUfsdMRDytkvLAIeOjZqp3aSl6aht//TXWUWSGkEpYymhZzt6eljszgA4C29/MzkHIFh0NpGYSQX59tO24oFuZgIakvZM2KsHgXOK8PBQ4A67Vkh7aAZ+MXCcb25sOxURHkbthuYWx48T3oDe1iU11BPoAmndQeQRJSpEKlmB5sgZ+smQeWm3HzZFZVqLrjSbLXO6LXBiPDu+X1tpOyEQ/S08CNCikFWMhPPQmSvg+KsMBNkCa4mVfQYQNlAl7veITIjQqDfAgvPGAn5nvoe+9G9BDL3MFL6xKGXk5BjzPK0HghfGeSTsqtQ+EjrreBhNwBa4ZfZD9HxgGEF/vk8r7ZLyyZQhJzaqrBGN6gG8TsCuroqZdzJ1JvIcBvhmSeisZm5PMw+fCAI+LDSgbEje+5BTTZIUxNYcOhkkiY21CtGu12KO6AWBzJxqY6T4wi/Dgm5808iWq0h3d1tK6+isATZ+RwzIglBXk0rN9ZypV6QFxDZFVbz//0qHfgQ+NFrgfjitid32PA0AgUFKLlQV6OVnWAHbhATCiXZyD/8bIayOQN8oSZQSfBXjpRcvCAlUELkaaPiHt+44mqDZToGM7hC8zPA+5XKcRGF5k8HLJ5szfa1fz2ikwfDdE/V5jcFDFeWBgcmiX1WD4FlEqokyu0mGz15J/20l0qGYN0ZP6yv3YjIU8vpAoS4WHVZCqYILfoKRBk/g5dRIQimOkoWHrnCzQOkqbeWhw0VM0NP4JSeBGnl6lOxWGTTHlAfk7V6TkI6OswUGmXxh9NwdhoiAll4CZF0igxqs+HQ4DwC18k1chqcgY0zN++FwyjhOyepnUhpMxARjjmHHzoOWGMjKkKp8osWMCJWc1KYf4WjLv5MMxB4iAST+k+BnpKOM1hgNCAjlUNvKyQdzz5f7zicwrPYlCZ3joskUSDQ4DhWWwYHoqeYVMmgsSz7yIvzoea/ThITVrV2N6C1lk8CjHzcFw5IFXr6hlXL8nxLuTcDiH/jx6Oxsl3xCRTPqRrQKiowvGuj7U81UNIXMnhVOgUSsUYGrQlMvpX6/DRyTyxaMJmRpodLuNlrtVlAlDpQ2MfGjbxl1nhFU5jq6YzA8VbPZAoHIM7K1dho/uwicKZrCF+To+pqyMX1pmMhQkphTwdDIGsENnAFCLsVjE23Hx3Ruz1vYqMar25yCjeMI14BibPsrMsJtFQhYyeRrerzUhuApOCoaHRSbQ3Ss9FLZT0moqK6hILSpXGN3hOOPLPaEQ2hbixwUGY1iPMbKVpUrXAEFmo4Qtvaz00Esnf42ooSuuiCRNdu1LLgIceBLzRr0PB4Shw5BLejgJ2cF41Xs3n2WjsTa5iThXzrwwS8OUD6dMYklXZ2O7AyegAT7O8d7VvCk9dmo/AQrJQ6PXnxrXAWD6lOD29N4sZFB5C1WghTW4dlu6m4jZR6rt3pa4pdqjwYfUSycK8d8SEMlKlR41vGvWLkNADosF8M0XPS8H5fbzAZKCDtgkTRnjxRhuBT7CUGaI8VjkEHcRlO9OD6PyMFNDwLKHa9VYL0Fugkw45EpMNK4sITAdjyYKpZVRBf1VS2wVOBjqJvUaTRitV+BCUd9MY5ibf+92NFIMZKHlQRaCIgvjFqA1PR23MxwiVT6HmbUS5vNKQDk/JO974b1Ztkat/5z3l1BUnusU2Bg3VtSiwiZUlGyxbAjTAZjIQ0hXJzUwDL99Z5CvDNCBYTPCkzngdLN+MCC8GrqC5nMUT2Yc0AqoHrk/N2DyR+1F51VOjUy2YpBv1LpSLYNXIgWhAAM2QtKMT4kS5+r2mSnlvMzIINvQWVqTCAbMm9aowTJBYPGFXg/sGJUIitIoFvPVIIa5aql0s3stRMLYqhvetuAWHg/Dtev45fZfKXm6/zGNQ4IRVM7bKHs8yz/NgTvB/DCByhjqu5u67OKgXTXB6EfPRrQ8wOPfXrJ8dAUZ3S9NEHSmBBC/7pCVgoZSFl8ABi9CfgiO+LIwu1bHsYsMroozOEg1PR31IBnjPjHZBFAKE0ZHJLijXjWTgMoNDRgpUEr8N7UThqiWm8Z2TC0WxsVl8kIUnlhWCRsiZnpMrfeCFjYwgnGLN4M10sdpP01FEnJFLM9k2m4rjYXBM2oxcugRRfPmTsaERcBBwDiotD+fx8S1Ehlbh98+8F1U9iLoB76TqF0RIo1kgWRTN16wn9VQYZ2Wat28xCg2KzJu2DKPooI9fBbhw511wgxgqm69uYdQ4xBN0COYvXXIhPFxznJjD8bANdLcocmqFlDeNynLegEw1dhcg7cEAI8igjYmDSuceaBKs5t58J53AeDCfgAbGFgU7gpgicKcmc+le4xYYL5TVxxuG8lzh7aLPGqSAx+y2dfA02adrwRNQNFtgczMBkIpEusuJ4SSE5cxDtS73gRsCzvy8ua6DHBBAIZISld0HeLfOQFyI3wsBHD2PYZxu+2tPlcy1+NIBvgVR2cO3MxCsvfWle+0iHx5DE3Hz6HD6thha0TKtUiLR2CYvelZlrYK7tBhdFgWEd1deVqrOeY8z7sxCxgEHXRb7hG8MDolN5pEF8KH7Q5TegwZVYN7xcCr9EjirZx2tq7FqQazQyZtuAb0RTPnfDJhtQX1ZgjC8NiHrLthHYsP5Y0PtOSQv3I1wcNU26kDD6smnL08sJQTZ2QwMtd5U+TjGNldm0aTipEs8LPqwGdiY4+VqF026UkvKjL29+a5IOFCqGR2zVLs6z3N+i47wZDLA6f53nhGCM/Mi6FQ8gYCK5N+LUkeuoPGBgBl9NPj/3s5vMGmnfJK9G52MZKqm/YoklgUzZu2Rj8jMt1M87IC9NWZKrCwv9xEaQTVeyTfMQ6KRULRXxioejgIfh+NJ5EVq6TTJtWyktItOMqUQWoRFJShQGEnCLo3v04b/IahNgYPVlOd6aXCc3CnEoFhcXr1jTs7uHs7a86CIV+FL+XgOhjL0oLyFNEHjUwmNT0444EC9w0o44Tj5co3S2AJqM9koYFQ4tGeo8KwQGRtt9gxbLC6nEIMcB4+jogB87jejoyijft3pw7FBc5RBEKnJg+Z6FFJ2lBtnQvO7m9djwqixqwWkI/pwLFY6poj2/kDW8vaHxR6AZVFrT2/myKk1SnyyTnsEVlhKi5MmYyE7GzgNWgYV15Ki3hpW4GUW3/TjVYfVYUGkhUUBbYstIJyJrjgAU4hCMhUq64OotfkUEkOFob7FeNd5r6sG+CYcx59/PmtNWDSwtbaGDidY2OPw9FNYI39O8THCCOqVqW7MPniT03kG9Rr4V6l5FXgJeICKTB4OzVc4axoq4nMlx8fD0PK36iXU+HAQ7ulAsPkbMW4KIkiOiMPGojqNyOk51gPbUdDo7nDLuM7J3ZTDbo/w8tV33w8IitNc1kY8zJWrQv11n2yD0IlTACgVSnZfPyh/t22U23Sa0XzKxuF4Nj9P9iSH46H6/ZmGh5leKm1seMuN3A83Hw8bsIcGxsbG30A6jHxSpbQsH7MgP6xCW6BbJMLVMFzdA5UyPQiQpLESIQfP5L3CDjMjOgvBPiUQeg/so8O444h1U9VvQTcC6poejimyvMJUUw8peDhpQLLS3L8dhCzpIJOuWOWjmLGxsJiSh7HBu2jC5qgIGKLNedCBxOUPFEeHKiULldWra052abiz4Oy5sP8vStOExb0eEiXXV8GSPY1ytoh9hs4DGXkQENfikFERs7V8fwYpOL9mZ6+CIkKnSq7drWwieaa156wE/vGnKgXJ5N/vQ7CLFOWMoWg1skM+iYx9vQf8uqbXqIkYQqPDVlpEqCvQmSNtN0TaQZqcB8iFQI7O4FqAzMirfQgfDUJeunr7AA83uLXHZ2AtwEzj8jPe4Cj6DIrcxyPHfOLlvlVvr0rz/99vfA6QJceI+6QfPHBorHsb3RvCK6rTcyogVXDQAMerWMqnRgfH0J4vDAanFU1OaZZnqBaf7L0ZBQz4NK/2Tahnc2Lj4Goxpi0wl4JoEaZgVhPaNTlkLeY2R6PyUmtHHtql3Feriha5E0o+QfX/ZoAQbX/gRfGFNw9kVjc4TC/Q1NjuTovB30DZaDzAhQ9+C47SESaR0G5uZBSQmFNaK888DI7SDG+YFng4Tg0n5nAYT5Y+Mw0XvJx3HujF5A6H4O3DjY2O3oMCxuK5niiqjpw6km0fYGwMSN7xsGCQZWy4eVj8ljMxeeItqvQS99BiSn1sJD4bXhwcPxVauPQqkmv4cHNZGxuWHwwseuOXMjZlg2ORDa9Gd8FNo8CLv8uk4GSKIrUNKTkCsu7lb8vG9tVKHw2rnetCXokxuBhIFYIVr2A8kw4JBml9gMDZ6K48p5Smym429B4FoEKmlP0Vj6W0gH/9hla5y62DAxby+KIJE0iDarnAnRwNAbPlrj4Pll9ObNGCCONZ7oLlfRg2aavkiJ4elMYely8RK+gsi/85tKf21nNF6aTcfU6IjCe+6+lw4/3hWDnmGJz9Rqgg741VP/QN1wup0JLahZEjWXhCOBQcEPjsDCLZXkGm0LgNYVX5dGtJ7WbwLRS6N1bOsEBcFFS1LGjczessKokwKKSYe9+RWLAzkCuKyxHtAzih/mkQRjKpoGVlfBiD06oQMgCojMIghbusA8/vyYwo6tOMAUABmhAdcZsdyuO/yYcj8F7hRZVhC+jNUIOYoXHZTTHNAkd/az2Eft/dlPumjGSP0n58G6bxYfhIw2piJhVoiibFpR2wYoVWI/Ih68NNhZbFaXzHLBiEjfjH8Udz2Enl/JPDJSoUe2qOWM/AVvIGcPDuVDH83Thfo2FzGQ7DICB66leatOrNhBiDK1BAecvbwgHrjkaaoBNSBqE57oZ5ClqS60Z5X0GvBd3Sj32IRJ5XefnqZsGIMpmGjzB6x3Ax251Eu+8ObLYYtWvB1mYDhWw4k1HhpDXjZnD8YaNUMjoFdTAIejIGIHHUJrDCW3hoHzhYEYlIEYhjOCOMrUKoC/WiCQvNcOPymSVuhRTpYGxIwHqWuAbaZVvi9tioUdQVrnotCzodaKxgcFVyOQ+lKo/yPy5W1CgU2qkZJNQKgVuY7KdkgJ5CtGjSLoDQs8PZcKnS+OaqM1yBAlQaJAm4Vp67Xhqps4O9hZfHo4EqVrQUOgSKDWsQRo9zWSpBuzI+5jdWcmaTWK3XNMb2vghGRSwljSXXOm0yOI9Y5mpQQk/aC/TcRzuxIKFQxWQzMiedDxiV9VKqzEqyBdi4r/OWH9eVvd2xYMJK9BxO7jLXgbIdkkgTNDAIjrdyo9GoG9tlaONneFnH9IystCUpqhwNEWMrxfiGAGKh46EgoVjV8NDm3WcciYXJPSrMRO8QZo7BdYELGY1kmivgm3xmg5d89ynOFF2PfwP1D+0mKbJ2/wAAAABJRU5ErkJggg==");
}

/* ============================================================================
   app.css — 冥想统计看板 demo 全站唯一样式归属（X2 工卡 · V2「册页」全案）
   依赖：tokens.css 必须先于本文件加载（本文件只用 var(--*)，零裸色值）
   ⚠ 本文件为 V2 推倒重做整体替换件：V1 双主题（.shell/.nav/.tabbar/.kpi/.card/
   .rankrow/.wheel/.badge-shichen/.seal 等）契约作废，class 命名空间全新起造，
   V1 成品已存档 dist\冥想统计看板-demo-v1存档.html，不再兼容维护。

   世界观：这不是一个 App，是社区共用的一册修习手账——纸、墨、朱印、票据、放榜。
   五条裁决基准（SPEC V2 §1，冲突时以此为准）：
     1. 纸即界面：分区靠线与留白，禁底色块分区、禁投影卡片。
     2. 中文大字当主角：层级靠字号/字重/字体切换，不靠颜色/图形。
     3. 数据=票据/档案：等宽数字、虚线分段、字段表、批次页脚。
     4. 色彩四色封顶：--seal 只进印章底/色点，--red-text 只进「今日之数」类强调。
     5. 装饰只许来自印刷文书传统：细线/虚线/界格/鱼尾/刻度尺/印章/微旋转。
   本文件仅有的两处 radial-gradient（§14 宣纸云絮）是 SPEC §6 明令的纸纤维合成
   技法，属技术性纹理生成，非「渐变」类 UI 装饰效果，与禁止项 §7.1 不冲突——
   §7.1 针对的是按钮/卡片层面的色彩渐变、光泽、玻璃拟态。

   ============================================================================
   V2 全站 DOM 契约总纲（X3 组件层 / X4 页面层按此落地，class 名为唯一真理源）
   ----------------------------------------------------------------------------
   外壳（每页 <body> 下唯一根）：
     <div class="shell">
       <header class="masthead"> ... <div class="ruler" aria-hidden="true"></div></header>
       <nav class="toc">   <!-- 桌面 ≥768px 显示，移动隐藏 -->
         <a class="toc-item" aria-current="page">今日</a> ...
       </nav>
       <main class="page">
         <section class="folio"><h1 class="folio-title">今日</h1><p class="folio-note">…</p></section>
         ...页面内容，全部由 .tag-rule + .ticket 系组件拼装...
       </main>
       <nav class="tab-paper">  <!-- 移动 <768px 显示，桌面隐藏 -->
         <a class="tab-paper-item" aria-current="page">今日</a> ...
       </nav>
     </div>
     <div class="mask" data-state="open|closed"></div>  <!-- 录入面板遮罩，shell 外层同级 -->
     <div class="entry-ticket" data-state="open|closed" role="dialog">…</div>
     <!-- CARD-G3W11：原「全站唯一 seal-erosion 崩边滤镜」SVG 契约已随印章
          DOM 改造下架（旧 .seal-v2-face/.seal-v2-frame 手绘拼字方案专用，
          新版直接内联 owner 验收终版矢量 logo，不需要再做崩边失真），见
          .seal-v2 §14 印章一节新注释。 -->

   题签分隔（替代一切卡片标题，§4.4）：
     <div class="tag-rule">
       <span class="tag-rule-label">趋势</span>
       <span class="tag-rule-line" aria-hidden="true"></span>
       <span class="tag-rule-meta">近七日</span>
     </div>

   票据卡（唯一有边框的容器，§4.5）：
     <div class="ticket">
       <div class="ticket-body">…内容/字段表…</div>
       <div class="ticket-divider" aria-hidden="true"></div>  <!-- 可多个，虚线分段 -->
       <div class="fieldrow"><span class="fieldrow-label">本周</span><span class="fieldrow-value num">4 时 10 分</span></div>
       <div class="ticket-foot">录于 申时 · 第 026 笔</div>
     </div>
   轻量列表行变体（管理列表/记录卡片等重复项，不用双线重框）：
     <div class="ticket-row"> … 同 .ticket 内部语法，单线 1px 边框 … </div>

   其余组件契约见各自小节头部注释：.ticket-hero（§6）/.shichen-ledger（§7）/
   .gridcal（§8）/.ch-*（§9）/.bang（§10）/.entry-ticket .entry-mode-switch
   .numwheel .numfield .shichen-tag（§11）/.day-tickets（§12）/
   .empty（§13）/.seal-v2 .fishtail（§14）/.book-page .scroll .scroll-title
   .book-auth-overlay（§16，登录/注册立轴首屏+渐显浮层）/.dudie .timinglu
   .nianpu .me-settings（§17，我的页度牒·题名录·年谱三件套）/.colophon（§18，牌记）。
   目录：
     0. 基础重置与排印
     1. 报头 masthead + 刻度尺 ruler（V4：三段真居中网格，R-013⑧）
     2. 目录条 toc（桌面）/ 纸签栏 tab-paper（移动）/ 页面切换
     3. 巨字页标 folio
     4. 题签分隔 tag-rule
     5. 票据卡 ticket / ticket-row / fieldrow / ticket-divider / ticket-foot
     6. 核心数字横幅票据 ticket-hero
     7. 十二时辰账页 shichen-ledger（V4：周/月/年三范围切换，R-013⑥）
     8. 打卡历 gridcal「历注墨字格」（V4，R-013⑦第三版）
     9. 趋势「账簿墨条」ch-* 上色（V4，R-013⑤）
     10. 放榜 bang
     11. 录入面板 V3「细记/约记」：entry-ticket / entry-mode-switch / numwheel /
         numfield / shichen-tag
     12. 记录卡片 day-tickets
     13. 空态 empty / 通用按钮
     14. 纸纹背景 / 印章 seal-v2「压角朱文印」（V4，R-013②）/ 鱼尾 fishtail
     15. 响应式与 reduced-motion / 触控热区
     16. 登录/注册「立轴」首屏 + 渐显浮层 book-page（V4.2 §2/§3 R-014①② 推倒重做）
     17. 我的页「度牒 · 题名录 · 年谱」三件套（V4 整页重排，R-013③）
     18. 牌记 colophon（V3 新增，SPEC §13）
     19. CC 式滚动条 + .cc-scroll 静止隐/交互显（R-019③，W13a 新增；本节起
         同时落地 R-019④全局圆边卡片：.ticket/.ticket-row/.entry-ticket/
         .book-auth-card 圆角改动分散在各自原章节内，未新增独立小节，
         详见 §5/§11/§13/§16 各处 border-radius 增量注释）
   ========================================================================== */


/* ============================================================================
   0. 基础重置与排印
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
/* R-033①(CARD-G3W13，20260723 CDP 实测坐实)：切页(今日/排行榜/我的)时 masthead
   整条发生小幅位移，根因=各页内容高度不等，纵向滚动条随页面切换动态出现/
   消失(SPA hash 路由不重载整页，纯局部换 DOM)，document.documentElement.
   clientWidth 因此跟着抖动(实测 1280 视口 有/无滚动条差 10px，masthead 靠
   grid 居中，两侧各偏 5px)——不是 masthead 自身样式或某一页布局的缺陷，是
   "滚动条是否出现"这件事本身在跨页时不稳定。scrollbar-gutter:stable 让浏览
   器无论当前页内容是否溢出都恒定预留滚动条槽位，从根上抹平这个不稳定量，
   现代 Chrome/Firefox/Edge 均支持(不支持的旧浏览器退化为原生行为，即回到
   "抖动"而非报错，不影响功能)。 */
html { scrollbar-gutter: stable; }
html, body { height: 100%; }
body {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, p, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button {
  background: none; border: none; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; /* 中文按钮禁 line-height 居中法 */
}
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
::selection { background: var(--paper-3); color: var(--ink); }

/* 字重纪律：全站只用 400/600，中等强调一律靠颜色/字号，不靠 500（雅黑伪加粗） */
b, strong { font-weight: 600; }

/* 数字纪律：一切统计数字必须 MonoNum + tabular + 右对齐由各自容器决定，
   本工具类只负责字体与等宽特性 */
.num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  /* SPEC V3 §13：CJK 与数字/字母交界处留白（text-autospace 未获浏览器普遍实现，
     不能作为唯一方案——按 .num 包裹处统一加最小行内边距，近似达到「数字汉字
     间距」效果，零新增裸色值/裸时长） */
  margin-inline: 0.06em;
}

/* 焦点环:owner 20260805 三令(第一次嫌黑框,改朱后二次录屏点名
   「我不要任何选中框」)——全站聚焦视觉指示整体移除,不留任何颜色的环。
   聚焦仍可用(tab 顺序/输入不受影响),只是不画框。 */
:focus-visible {
  outline: none;
  box-shadow: none;
}


/* ============================================================================
   1. 报头 masthead + 刻度尺 ruler
   DOM 契约（V4 §9 三段真居中网格，叠加于 V3 §4 之上）：
   <header class="masthead">
     <div class="masthead-inner">
       <span class="masthead-brand">练功志<i class="masthead-brand-dot" aria-hidden="true"></i></span>
       <span class="masthead-slogan">── 争分夺秒 · 刻不容缓 ──</span>
       <span class="masthead-meta">
         <span class="masthead-meta-item">07·20</span>
         <span class="masthead-meta-item">戌时 <span class="num masthead-clock">19:42:07</span></span>
         <span class="masthead-meta-item masthead-member">沈知远</span>
         <button class="masthead-switch masthead-meta-item">退出登录</button>
       </span>
     </div>
     <div class="ruler" aria-hidden="true"></div>
   </header>
   ========================================================================== */
.masthead {
  padding: var(--s3) var(--s4) 0;
}
.masthead-inner {
  /* V4（SPEC §9 R-013⑧）：三段改真网格居中——两侧 1fr 等宽，口号列按内容
     宽度居中；此前 flex space-between 在右段 meta 缺席时会把口号推向右边，
     grid 两侧等宽轨道结构性杜绝这个问题（不依赖各段内容多寡）。 */
  display: grid;
  /* R-022 回归修:移动端两列(品牌|meta)——旧三列 1fr auto 1fr 迫使两侧轨道
     等宽,375 端 meta(日期+时辰钟+成员+退出登录 ≈368px)撑爆网格横向溢出 78px
     (R-019⑨ 解禁日期项时漏测的既有回归);桌面 ≥768 恢复三列真居中(见下方断点) */
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--s4);
  /* V3（SPEC §4）：整体加高一档，摆脱旧版「一条 11px 细线」的局促——
     min-height 撑出内容行高度，桌面断点见下方媒体查询 */
  min-height: 34px;
  padding-bottom: var(--s3);
  font-size: var(--fs-masthead);
  letter-spacing: var(--ls-wide);
  color: var(--ink-2);
}
.masthead-brand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-self: start;
  color: var(--ink);
  cursor: pointer; /* R-020⑥:品牌名可点回首屏 */
  /* V4（SPEC §9 R-013⑧）：品牌字改齐伋体 16px + 统一 letter-spacing 0.08em
     （改名「练功志」后无 glyph-blend 拆字 span，字距天然均匀，不必再借宽字距
     掩饰拼接缝）。 */
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.08em;
  flex-shrink: 0;
  /* G2 终审修(复核P0-①):375 端右段 meta 挤压 grid 1fr 轨道时,品牌中文默认
     逐字可断行,「练功志」被拆成三行破版——品牌字永不断行 */
  white-space: nowrap;
}
/* 全站唯一「色点」用途之一：--seal 仅限印章底色与色点，此处为品牌点睛 */
.masthead-brand-dot {
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--seal);
  flex-shrink: 0;
}
.masthead-slogan {
  /* SPEC V3 §4：移动端隐藏中段口号，给右段新增的实时秒钟腾出宽度
     （375 宽实测：不隐藏会导致右段整体溢出视口触发横向滚动） */
  display: none;
  justify-self: center;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.masthead-meta {
  display: inline-flex;
  align-items: center;
  /* R-022 回归修:允许换行右对齐——375 端自然折成「日期干支 / 时辰钟·成员·
     退出登录」两行,全信息保留零溢出;桌面宽度充裕永不触发 */
  flex-wrap: wrap;
  justify-content: flex-end;
  row-gap: 2px;
  gap: 6px;
  justify-self: end;
}
/* G2 终审修(复核P0-①连带):meta 各项同样禁断行——375 端「沈知远」「切换身份」
   曾被逐字拆行;并在窄屏隐去首项日期(与今日页小字注重复,腾宽度) */
.masthead-meta-item { white-space: nowrap; }
/* R-019⑨:owner 令顶栏必显年月日+干支——旧「≤480px 整项隐藏」规则解除;
   窄屏防线=ui-pages 两级降级(≤480px 干支串降日柱)+R-022 的 meta 换行右对齐
   (当时「375 零溢出」断言实测有误,已由两列网格+换行根治) */
/* V3（SPEC §4）：段间改界行竖线（1px --line）分隔，替代旧版圆点堆砌；
   .masthead-switch 同时挂 .masthead-meta-item 以纳入同一分隔规则。
   移动端 gap/margin 收紧（375 宽实测：右段新增秒钟数字后按桌面间距会溢出
   视口触发横向滚动），桌面断点放宽回舒适间距。 */
.masthead-meta-item + .masthead-meta-item::before {
  content: "";
  display: inline-block;
  width: var(--lw-line);
  height: 12px;
  margin-right: 6px;
  background: var(--line);
  vertical-align: -2px;
}
.masthead-member { color: var(--ink-2); }
/* 时辰后接实时秒钟（MonoNum tabular，固定字宽防抖，§4） */
.masthead-clock { color: var(--ink-2); }
.masthead-switch {
  color: var(--ink-2);
  font-size: var(--fs-masthead);
  letter-spacing: var(--ls-wide);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
  transition: color var(--t-fast) var(--ease-out);
}
.masthead-switch:hover { color: var(--ink); }

/* .masthead::after 报头下压线已删(owner 20260806:「这条线仍在」——真凶就是
   这条伪元素,先前只清了 border/背景分界)。报头改玻璃材质见文末 §sticky 区。 */
/* .ruler 刻度尺装饰条已删(owner 20260806)。 */
@media (min-width: 768px) {
  .masthead { padding: var(--s3) var(--s6) 0; }
  .masthead-inner {
    min-height: 46px; /* SPEC §4：桌面内容行 44-48px */
    grid-template-columns: 1fr auto 1fr; /* 桌面恢复三段真居中(口号列) */
  }
  .masthead-slogan { display: block; }
  .masthead-meta { gap: var(--s3); }
  .masthead-meta-item + .masthead-meta-item::before { margin-right: var(--s3); }
}


/* ============================================================================
   2. 目录条 toc（桌面水平） / 纸签栏 tab-paper（移动底部） / 页面切换
   DOM 契约：
   <nav class="toc">
     <a class="toc-item" aria-current="page">今日</a>
     <a class="toc-item">同修</a>
     <a class="toc-item">我的</a>
     <a class="toc-item">管理</a>
   </nav>
   <nav class="tab-paper">
     <a class="tab-paper-item" aria-current="page">今日</a> ...
   </nav>
   页面切换：.page-fade[data-state="enter|exit"] 由 X4 挂在 <main class="page"> 上，
   单层 opacity ≤140ms，不做位移/交叉淡入。
   ========================================================================== */
.toc {
  display: none;
}
.tab-paper {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  display: flex;
  background: var(--paper-2);
  border-top: var(--lw-line) solid var(--line);
  padding: 6px 0 max(6px, env(safe-area-inset-bottom));
}
.tab-paper-item {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  color: var(--ink-2);
  font-family: var(--font-body);
  font-size: var(--fs-toc);
  font-weight: 400;
  position: relative;
  transition: color var(--t-fast) var(--ease-out);
}
.tab-paper-item[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
}
/* 当前签：签顶短朱线（题签），无图标，纯楷字导航 */
.tab-paper-item[aria-current="page"]::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 20px; height: var(--lw-heavy);
  background: var(--line-red);
}

@media (min-width: 768px) {
  .tab-paper { display: none; }
  .toc {
    display: flex;
    align-items: center;
    gap: var(--s6);
    padding: var(--s3) var(--s6);
    border-bottom: var(--lw-line) solid var(--line);
    background: var(--paper);
  }
  /* CARD-G3W11 附加项（G3W9 回执 §3 遗留裁决）：桌面顶部导航项命中区扩到
     ≥44×44——iPad 768 档命中本媒体查询分支但仍是触屏设备。配方同 G3W10
     （见上方 §13 .seg-item / 下方 §15 .masthead-brand 一族）：透明 padding+
     等量负 margin，margin-box 折算回原值不占用 .toc 的 gap（gap: var(--s6)=
     32px，本次单边只加 8px，两邻项相向合计吃 16px，剩 16px 净间隙，命中区
     不重叠）；.toc-item 自身零背景零边框，唯一可见装饰是当前项 ::after 底部
     2px 朱线，随 padding 增量用显式 inset 钉回原视觉位置（技巧同
     .seg-item::before 的 inset 补偿法）。 */
  .toc-item {
    position: relative;
    padding: 10px 8px 18px; /* 原仅 padding-bottom:8px；上/左右新增纯命中区，
      下方在原 8px 结构间距基础上再加 10px 命中区（8+10=18） */
    margin: -10px -8px -10px; /* 负 margin 只抵消「新增」的量：上 -10 对应
      padding-top 新增的 10；下 -10 对应 padding-bottom 新增的 10（不是原有
      的 8）；左右 -8 对应 padding-left/right 新增的 8 */
    font-family: var(--font-body);
    font-size: var(--fs-toc);
    letter-spacing: var(--ls-toc);
    color: var(--ink-2);
    font-weight: 400;
    transition: color var(--t-fast) var(--ease-out);
  }
  .toc-item:hover { color: var(--ink); }
  .toc-item[aria-current="page"] {
    color: var(--ink);
    font-weight: 600;
  }
  /* 当前项字底短朱线（题签），2px 朱丝；left/right:8px 抵消新增横向 padding，
     bottom:10px 抵消新增的 10px 纵向命中区（钉回原 8px 结构间距处的视觉基线，
     视觉位置与改前像素级一致） */
  .toc-item[aria-current="page"]::after {
    content: "";
    position: absolute;
    left: 8px; right: 8px; bottom: 10px;
    height: var(--lw-heavy);
    background: var(--line-red);
  }
}

.page {
  flex: 1;
  width: 100%;
  /* SPEC V3 §13「天头地脚」：页级上内边距为下内边距 1.5-2 倍，仅此一处调整
     （移动端下内边距被纸签栏让位撑大，比例天然合规；桌面端显式 1.5 倍）。 */
  padding: var(--s5) var(--s4) calc(64px + var(--s6)) var(--s4);
}
@media (min-width: 768px) {
  .page {
    max-width: 880px;
    margin: 0 auto;
    /* v1.1.1(owner 20260806 截图令):全站页面整体上提——顶部留白 48→24px */
    padding: var(--s5) var(--s6) var(--s6);
  }
}
.shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* 页面切换：单层透明度，不做位移/交叉淡入（SPEC §4.2 沿用既定口径） */
.page-fade {
  transition: opacity var(--t-page) var(--ease-out);
}
.page-fade[data-state="exit"] { opacity: 0; }
.page-fade[data-state="enter"] { opacity: 1; }


/* ============================================================================
   3. 巨字页标 folio
   DOM 契约：
   <section class="folio">
     <h1 class="folio-title">今日</h1>
     <p class="folio-note">7月20日 · 星期一 · 戌时 19:42:07</p>
   </section>
   登录/注册页不用 .folio——改用 §16 的 .book-page/.scroll-title 独立语汇（开卷
   之前不算书内页，尺度也比站内页标更高一级）。
   ========================================================================== */
.folio {
  margin-bottom: var(--s6);
}
.folio-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-folio-m);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  color: var(--ink);
}
/* R-033②(CARD-G3W13，20260723 owner 令)：页首巨字下方日期时间行三页字号/间距
   不一致——「我的」/「管理」两页套 .page-scale-lg(R-028⑥ 正文+15%)，原样式靠
   --fs-folio-note 变量间接吃到这条覆写(12px→13.8px)，「今日」/「排行榜」两页
   没套 page-scale-lg，停在变量原值 12px，三页因此字号/行高不一致(CDP 实测
   12px/21px vs 13.8px/24.15px，与巨字页标间距 8px 本身四页一致，只有字号一项
   有差)。owner 令=今日/排行榜两页向「我的」页对齐——直接把该行字号定死为
   「我的」页的计算值，不再经 --fs-folio-note 变量间接吃 page-scale-lg 覆写
   (不依赖各页缩放开关的连带，见工单原话)，四页(含管理页)逐像素一致；
   line-height 走 body 继承的 --lh-body(1.75)不必单列，13.8×1.75=24.15px 与
   实测值吻合。旧 --fs-folio-note 变量与 page-scale-lg 覆写点已随之不再被
   .folio-note 消费(见下方 §22 覆写清单同步移除该行，避免留一条不再生效的
   死配置)。 */
.folio-note {
  margin-top: var(--s2);
  font-family: var(--font-body);
  font-size: 13.8px;
  color: var(--ink-3);
}
@media (min-width: 768px) {
  .folio-title { font-size: var(--fs-folio-d); }
}


/* ============================================================================
   4. 题签分隔 tag-rule（替代一切卡片标题）
   ========================================================================== */
.tag-rule {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin: var(--s6) 0 var(--s3);
}
.tag-rule-label {
  flex-shrink: 0;
  font-family: var(--font-body);
  font-size: var(--fs-tagrule-label);
  letter-spacing: var(--ls-label);
  font-weight: 600;
  color: var(--ink);
}
.tag-rule-line {
  flex: 1;
  height: var(--lw-line);
  background: var(--line);
  align-self: center;
}
.tag-rule-meta {
  flex-shrink: 0;
  font-family: var(--font-num);
  font-size: var(--fs-tagrule-meta);
  color: var(--ink-3);
}


/* ============================================================================
   5. 票据卡 ticket / ticket-row（轻量单线变体）/ fieldrow / 虚线分段 / 页脚
   ========================================================================== */
.ticket {
  position: relative;
  background: var(--paper-2);
  border: var(--lw-thick) solid var(--line);
  border-radius: var(--r-card); /* R-019④owner令:全局圆边卡片,覆盖旧「禁大圆角」纪律(W13a) */
  padding: var(--s5);
}
/* 内 0.5px 细线，距外框 4px，构成「文武线」双线框语法；内线圆角随外框收 2px 同步跟随 */
.ticket::before {
  content: "";
  position: absolute;
  inset: 4px;
  border: var(--lw-hair) solid var(--line);
  border-radius: calc(var(--r-card) - 2px);
  pointer-events: none;
}
.ticket-body { position: relative; }
.ticket-divider {
  border-top: var(--lw-line) dashed var(--line);
  margin: var(--s4) 0;
}
.ticket-foot {
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: var(--lw-line) dashed var(--line);
  font-family: var(--font-num);
  font-size: var(--fs-ticketfoot);
  color: var(--ink-3);
  text-align: right;
}

/* 轻量列表行：管理列表/邀请码/记录卡片等重复项，单线不重框，避免密集列表过重 */
.ticket-row {
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-card); /* R-019④(W13a) */
  padding: var(--s3) var(--s4);
}
.ticket-row + .ticket-row { margin-top: var(--s2); }

.fieldrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  padding: 6px 0;
  line-height: var(--lh-tight);
}
.fieldrow + .fieldrow { border-top: var(--lw-hair) dashed var(--line); }
.fieldrow-label {
  font-family: var(--font-body);
  font-size: var(--fs-fieldlabel);
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
  flex-shrink: 0;
}
.fieldrow-value {
  font-family: var(--font-num);
  font-size: var(--fs-fieldvalue);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: right;
}
/* 涨跌双编码：箭头+数值，色盲冗余（沿用 playbook 红线），色彩只用深朱/淡墨，不引第二语义色 */
.fieldrow-value[data-trend="up"] { color: var(--red-text); }
.fieldrow-value[data-trend="down"] { color: var(--ink-2); }
.fieldrow-value[data-trend="up"]::before { content: "↑ "; }
.fieldrow-value[data-trend="down"]::before { content: "↓ "; }


/* ============================================================================
   6. 核心数字横幅票据 ticket-hero（替代 KPI 卡阵，SPEC §5.1）
   DOM 契约：
   <div class="ticket ticket-hero">
     <div class="ticket-hero-main">
       <span class="ticket-hero-num num">128</span>
       <span class="ticket-hero-unit">分钟</span>
       <p class="ticket-hero-caption">今日</p>
     </div>
     <div class="ticket-hero-fields">
       <div class="fieldrow"><span class="fieldrow-label">本周</span><span class="fieldrow-value num" data-trend="up">4 时 10 分</span></div>
       <div class="fieldrow"><span class="fieldrow-label">连续</span><span class="fieldrow-value num">5 天</span></div>
       <div class="fieldrow"><span class="fieldrow-label">本周日均</span><span class="fieldrow-value num">36 分</span></div>
       <div class="fieldrow"><span class="fieldrow-label">本月</span><span class="fieldrow-value num" data-trend="down">18 时 20 分</span></div>
     </div>
   </div>
   ========================================================================== */
.ticket-hero {
  display: flex;
  flex-direction: column;
  gap: var(--s4);
}
.ticket-hero-numrow {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
}
.ticket-hero-main {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  flex-wrap: wrap;
}
.ticket-hero-num {
  font-size: var(--fs-hero-num-m);
  font-weight: 600;
  line-height: 1;
  color: var(--red-text); /* 全站「今日之数」唯一朱色文字用途 */
}
.ticket-hero-unit {
  font-family: var(--font-body);
  font-size: var(--fs-hero-unit);
  color: var(--ink-2);
}
.ticket-hero-caption {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-3);
  order: -1;
}
.ticket-hero-fields {
  border-top: var(--lw-line) dashed var(--line);
  padding-top: var(--s2);
}
@media (min-width: 768px) {
  .ticket-hero {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--s6);
  }
  .ticket-hero-num { font-size: var(--fs-hero-num-d); }
  .ticket-hero-main { flex-direction: column; align-items: flex-start; gap: 0; }
  .ticket-hero-fields {
    border-top: none;
    border-left: var(--lw-line) dashed var(--line);
    padding-top: 0;
    padding-left: var(--s6);
    min-width: 260px;
  }
}


/* ============================================================================
   7. 十二时辰账页 shichen-ledger（SPEC V4 §6 R-013⑥，周/月/年三范围切换；
   账页本体沿用 V3 §9「替代 V2 单环日晷式 sundial」，sundial-* class 全套
   仍作废，未再被任何组件引用）
   DOM 契约（纯 flex/宽度百分比，零 SVG、零极坐标，文字零旋转）：
   <div class="shichen-ledger-wrap">
     <div class="seg shichen-ledger-seg">
       <button class="seg-item" aria-selected="true">周</button>
       <button class="seg-item" aria-selected="false">月</button>
       <button class="seg-item" aria-selected="false">年</button>
     </div>
     <div class="shichen-ledger">
       <div class="ledger-row" data-now="true|false" data-empty="false">
         <div class="ledger-dizhi">
           <span class="ledger-dizhi-name">戌时</span>
           <span class="ledger-dizhi-range num">19-21</span>
         </div>
         <span class="ledger-sep" aria-hidden="true"></span>
         <div class="ledger-bar-track"><span class="ledger-bar" style="width:64%"></span></div>
         <span class="ledger-value num">1 时 30 分 (2 次)</span>
       </div>
       ...固定 12 行，子→亥时序...
       <p class="ledger-footer">共录 18 笔 · 最常起于申时</p>
     </div>
   </div>
   ========================================================================== */
.shichen-ledger-wrap {
  display: flex;
  flex-direction: column;
}
.shichen-ledger-seg {
  align-self: flex-start;
  margin-bottom: var(--s4);
}
.shichen-ledger {
  display: flex;
  flex-direction: column;
}
.ledger-row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-bottom: var(--lw-hair) dashed var(--line);
  cursor: pointer;
}
.ledger-row:last-of-type { border-bottom: none; }
/* 当前时辰行：衬纸底 + 上下朱丝细线 + 地支/数字转深朱（复用放榜本人行语法） */
.ledger-row[data-now="true"] {
  background: var(--paper-3);
  margin: 0 calc(var(--s3) * -1);
  padding: var(--s2) var(--s3);
  border-top: var(--lw-line) solid var(--line-red);
  border-bottom: var(--lw-line) solid var(--line-red);
}
.ledger-row[data-now="true"] .ledger-dizhi-name,
.ledger-row[data-now="true"] .ledger-value {
  color: var(--red-text);
  font-weight: 600;
}
.ledger-dizhi {
  flex-shrink: 0;
  width: 46px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.3;
}
.ledger-dizhi-name {
  font-family: var(--font-body);
  font-size: 18px;
  color: var(--ink);
}
.ledger-dizhi-range {
  font-size: 11px;
  color: var(--ink-3);
}
.ledger-sep {
  align-self: stretch;
  width: var(--lw-line);
  background: var(--line);
  flex-shrink: 0;
}
.ledger-bar-track {
  flex: 1;
  min-width: 0;
  height: 8px;
  display: flex;
  align-items: flex-end;
  border-bottom: var(--lw-hair) dashed var(--line);
}
.ledger-bar {
  display: block;
  height: 6px;
  background: var(--chart-1);
}
.ledger-value {
  flex-shrink: 0;
  min-width: 7.5em;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
.ledger-footer {
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: var(--lw-hair) dashed var(--line);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-3);
}


/* ============================================================================
   8. 打卡历 gridcal「历注墨字格」（SPEC V4 §4，R-013⑦第三版，替代 V3「墨位
   量具」——彻底废除面积编码，格内只剩字/点/印三类离散符号，物理上不存在
   能连成片的色块）
   DOM 契约：
   <section class="gridcal">
     <div class="tag-rule">
       <span class="tag-rule-label">打卡历</span>
       <span class="tag-rule-line" aria-hidden="true"></span>
       <span class="gridcal-months">
         <button class="gridcal-month" aria-pressed="false">五月</button>
         <button class="gridcal-month" aria-pressed="true">六月</button>
         <button class="gridcal-month" aria-pressed="false">七月</button>
       </span>
     </div>
     <div class="gridcal-grid">
       <div class="gridcal-cell" data-today="false" data-future="false"><div class="gridcal-top"><span class="gridcal-daynum num">1</span></div></div>
       <div class="gridcal-cell" data-today="true" data-future="false">
         <div class="gridcal-top">
           <span class="gridcal-daynum num">2</span>
           <span class="gridcal-shichen" aria-hidden="true">申</span>  <!-- 当日主导时辰地支单字，全模糊录入日留空 -->
         </div>
         <span class="gridcal-dur num" data-tier="low|mid|high">3.6</span>  <!-- 当日时长(时)，一位小数，≥10 取整 -->
         <div class="gridcal-baseline"><span class="gridcal-dot" aria-hidden="true"></span></div>  <!-- 有记录=基线+实心墨点 -->
         <span class="gridcal-backfill-mark" aria-hidden="true"></span>  <!-- 补录日：墨点改为右下角空心方印，与 .gridcal-dot 互斥 -->
       </div>
       <div class="gridcal-cell" data-today="false" data-future="true"><div class="gridcal-top"><span class="gridcal-daynum num">31</span></div></div>  <!-- 未来日：仅界格+日期数字淡墨，不可点击，SPEC V4.2 §4.1 -->
       ...
     </div>
   </section>
   月历为完整自然月（1 日至月末，Engine.personalStats.heatmap[].days 逐日不
   再在「今天」处截断，SPEC V4.2 §4.1）；未来日（day.future===true）挂
   data-future="true"，仅界格+日期数字淡墨态，无墨点/时长/时辰注，不可点击。
   data-tier 语义（锚点=本人日均线 Engine.avgDailyMin，非当月最大）：
   low=淡墨（&lt;0.75×日均）/ mid=重墨（0.75-1.25×）/ high=浓墨（&gt;1.25×）；
   文字着色不是背景填色，永无连片。空日（当日无记录，含未来日）=仅界格+
   日期数字，不渲染 .gridcal-shichen/.gridcal-dur/.gridcal-baseline/.gridcal-backfill-mark。
   .gridcal-shichen 为装饰性单字，豁免正文最小字号。
   ========================================================================== */
/* 打卡历题签行：右端 meta 从 V4.2 起改今日干支全串（10 字）+「· 本月补录
   N%」，比旧版「本月补录 N%」长得多，窄屏（375）单行放不下会把月份切换按钮
   挤到换行、meta 本身溢出视口——允许本题签行整体换行，月份+干支小字整块
   落到第二行，避免横向溢出（SPEC V4.2 §4.3，只影响本题签行，不动全局
   .tag-rule 单行约定） */
.gridcal .tag-rule {
  flex-wrap: wrap;
  row-gap: var(--s2);
}
/* (已退役)旧多月按钮组 .gridcal-months/.gridcal-month——R-019⑧ 改组件内置
   箭头翻月后 DOM 已不再生成,规则保留仅为历史对照。 */
.gridcal-months {
  display: inline-flex;
  gap: var(--s2);
  flex-wrap: wrap;
}
/* R-019⑧ 组件内置翻月导航(W13b DOM 契约:.gridcal-nav > .cal-nav-prev +
   .gridcal-nav-label + .cal-nav-next):居中一行,箭头 44px 热区,边界禁用=淡墨 */
.gridcal-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s3);
  margin-bottom: var(--s3);
}
.cal-nav-prev,
.cal-nav-next {
  /* R-020④:owner 打回「按键太小」——热区补满 44px 见方,箭头字号 17→26,
     淡墨提为重墨,加细边框圈出可点感 */
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: var(--lw-hair) solid var(--line);
  border-radius: var(--r-ctl);
  color: var(--ink-2);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.cal-nav-prev:hover:not(:disabled),
.cal-nav-next:hover:not(:disabled) { background: var(--paper-3); color: var(--ink); }
.cal-nav-prev:disabled,
.cal-nav-next:disabled { color: var(--line); border-color: transparent; cursor: default; }
.gridcal-nav-label {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--ink);
  min-width: 7.5em;
  text-align: center;
}
.gridcal-month {
  font-family: var(--font-body);
  font-size: var(--fs-tagrule-meta);
  color: var(--ink-3);
  padding: 2px 4px;
  border-radius: var(--r-sm);
  transition: color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.gridcal-month[aria-pressed="true"] {
  color: var(--ink);
  font-weight: 600;
  background: var(--paper-3);
}
.gridcal-month:hover { color: var(--ink); }

.gridcal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  border-top: var(--lw-hair) solid var(--line);
  border-left: var(--lw-hair) solid var(--line);
}
.gridcal-cell {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  border-right: var(--lw-hair) solid var(--line);
  border-bottom: var(--lw-hair) solid var(--line);
  padding: 3px 4px;
}
.gridcal-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2px;
}
.gridcal-daynum {
  /* SPEC V4.2 §4.2 日期字号加档：原 10px 级读不清，375→12-13px/1280→16-18px，
     层级须保持 日期 > 时长(.gridcal-dur) > 小注(.gridcal-shichen)，见下方两组 */
  font-size: 13px;
  color: var(--ink-3);
}
@media (min-width: 768px) {
  .gridcal-daynum { font-size: 17px; }
}
/* 未来日：仅界格+日期数字淡墨态，不可点击（SPEC V4.2 §4.1），日期数字本身
   叠加半透明再淡一档，与过去/今日的空日区分开 */
.gridcal-cell[data-future="true"] {
  cursor: default;
}
.gridcal-cell[data-future="true"] .gridcal-daynum {
  color: var(--ink-3);
  opacity: .55;
}
/* 顶行右侧随行时辰小注：紧跟日期，不再独占象限（SPEC V4 §4） */
.gridcal-shichen {
  font-family: var(--font-display);
  font-size: 8px;
  line-height: 1.2;
  color: var(--ink-2);
}
@media (min-width: 768px) {
  .gridcal-shichen { font-size: 10px; }
}
/* 中段主角：当日时长数字，三档文字色锚点=本人日均线（组件内计算） */
.gridcal-dur {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 600;
}
@media (min-width: 768px) {
  .gridcal-dur { font-size: 16px; }
}
.gridcal-dur[data-tier="low"] { color: var(--ink-3); }
.gridcal-dur[data-tier="mid"] { color: var(--ink-2); }
.gridcal-dur[data-tier="high"] { color: var(--ink); }
/* 底部：极细乌丝基线，线上一枚实心墨点=当日有记录 */
.gridcal-baseline {
  position: relative;
  height: 6px;
  border-top: var(--lw-hair) solid var(--line);
  display: flex;
  justify-content: center;
}
.gridcal-dot {
  position: relative;
  top: -1.5px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink);
}
/* 补录日：墨点改为右下角空心方印（细线方框，「事后钤记」意象），与
   .gridcal-dot 互斥——补录日的 .gridcal-baseline 不放 .gridcal-dot */
.gridcal-backfill-mark {
  position: absolute;
  right: 3px;
  bottom: 3px;
  width: 6px;
  height: 6px;
  border: var(--lw-hair) solid var(--ink-3);
}
/* 今日格：朱丝细框，用 box-shadow inset 避免干扰界格边框计算 */
.gridcal-cell[data-today="true"] {
  box-shadow: inset 0 0 0 var(--lw-line) var(--line-red);
}


/* ============================================================================
   9. 趋势「账簿墨条」ch-* 上色（SPEC V4 §5，R-013⑤）
   约定（沿用既有惯例，X3 产出 SVG 必须按此挂 class，禁 inline hex）：
   - 面状元素（墨条矩形/时辰盘扇区/热力格）：挂色阶类 .ch-s1..s5（fill 生效）。
   - 网格线/坐标轴：.ch-grid（网格）/ .ch-axis（轴线+刻度文字）。
   - 中文轴标（周内分布"一二三四五六日"/时辰标签）：额外挂 .ch-axis-cn 切正文字体。
   系列色阶惯例：本人/主系列=ch-s1（最深），社区/对比系列=ch-s3，第三系列=ch-s2。
   .ch-line / .ch-area / .ch-halftone-line / #ch-halftone-pattern（折线+圆点+
   斜线半调纹理面积）随 V4 账簿墨条改造整体下架——墨条本身即量感，不再有
   面积填充；本文件同步删除，避免死代码常驻（R-012 ㉕「代码简单」）。
   ========================================================================== */
.ch-grid { stroke: var(--line); fill: none; stroke-width: var(--lw-hair); opacity: .7; }
.ch-axis { stroke: none; fill: var(--ink-3); font-family: var(--font-num); font-size: 11px; font-variant-numeric: tabular-nums; }
.ch-axis-cn { font-family: var(--font-body); fill: var(--ink-2); }
.ch-s1 { fill: var(--chart-1); stroke: var(--chart-1); }
.ch-s2 { fill: var(--chart-2); stroke: var(--chart-2); }
.ch-s3 { fill: var(--chart-3); stroke: var(--chart-3); }
.ch-s4 { fill: var(--chart-4); stroke: var(--chart-4); }
.ch-s5 { fill: var(--chart-5); stroke: var(--chart-5); }
/* 远山淡墨(R-015):脊线=数据本体,全图最深最锐;回声远山=最淡墨装饰层,
   透明度显著弱于主山,一眼分得清哪层是数据哪层是意境 */
.ch-ridge { fill: none; stroke: var(--chart-1); stroke-width: 1.6; stroke-linecap: round; }
/* .ch-echo(回声远山)已随 R-019① 删除回声层而下架,零调用方,规则移除 */
/* .ch-accent（社区日均对比线专用色，SPEC V3 §7 R-012 ⑫已删除该对比线）已随之下架，
   零调用方——ch-s1..s5 是通用系列色阶（仍供 lineChart 多系列/heatmap 场景复用），保留 */

.chart-box { width: 100%; }
.chart-box svg { width: 100%; height: auto; display: block; }


/* ============================================================================
   10. 放榜 bang（SPEC §5.5 + V4.2 §6 R-014⑥ 数字定宽对齐增量）
   DOM 契约：
   <section class="bang">
     <div class="tag-rule"><span class="tag-rule-label">放榜</span><span class="tag-rule-line"></span><span class="tag-rule-meta">本周</span></div>
     <div class="seg bang-scope"> …周/月/年 子榜切换，复用既有 .seg 语法… </div>
     <div class="ticket bang-board">
       <div class="bang-row" data-top="1">
         <span class="bang-rank num">1</span><span class="bang-name">阿雅</span>
         <span class="bang-value num bang-value--duration"><span class="bang-value-n">12</span><span class="bang-value-u">时</span><span class="bang-value-n">30</span><span class="bang-value-u">分</span></span>
       </div>
       <div class="bang-row bang-row--me">
         <span class="bang-dot" aria-hidden="true"></span>
         <span class="bang-rank num">8</span><span class="bang-name">我</span>
         <span class="bang-value num bang-value--duration"><span class="bang-value-n">4</span><span class="bang-value-u">时</span><span class="bang-value-n">10</span><span class="bang-value-u">分</span></span>
       </div>
       <div class="bang-row">
         <span class="bang-rank num">—</span><span class="bang-name">陈墨</span>
         <span class="bang-value num bang-value--duration"><span class="bang-value-n">2</span><span class="bang-value-u">时</span><span class="bang-value-n">00</span><span class="bang-value-u">分</span></span>
       </div>
     </div>
     <p class="bang-footer">本周新上路：阿雅 · 阿雅</p>
   </section>
   全员必须可见，SPEC V3 §10.2（R-012 ㉑）删除匿名占位（原「一位低调的伙伴」/
   .bang-name--anon）逻辑与榜单可见性开关，本节不再有该变体。

   V4.2 数字定宽对齐（SPEC §6 R-014⑥，仅本节榜单专用格式，站内其余时长展示
   仍走 Engine.fmt.duration 自然宽不动）：时长列格式统一「H 时 MM 分」（分钟
   补零两位、整时显「00 分」），拆 .bang-value-n（数字，右对齐定宽）/
   .bang-value-u（单位字，上下成列）两类 span；进步幅度/连续天数等非时长值
   用 .bang-value--fixed 单层右对齐定宽，同理对齐。名次列 .bang-rank 固定
   2ch 右对齐（与 .num 等宽数字字体配合，天然按列对齐，无需 JS 测宽）。
   ========================================================================== */
.bang-board { padding: var(--s2) var(--s5); }
.bang-row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) 0;
  border-bottom: var(--lw-hair) solid var(--line);
}
.bang-row:last-child { border-bottom: none; }
.bang-rank {
  flex-shrink: 0;
  width: 2ch;
  text-align: right;
  color: var(--ink-2);
  font-weight: 600;
}
.bang-name {
  flex: 1;
  min-width: 4.5em;
  /* owner 20260801：排行榜姓名与弟子列表姓名统一使用系统楷体，避免真实姓名
     因 WenKai 子集命中不完整而在同一行逐字混用字体。 */
  font-family: "KaiTi", "STKaiti", "Songti SC", serif;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bang-value {
  flex-shrink: 0;
  color: var(--ink);
  font-weight: 600;
}
/* 时长值：数字/单位各自成列。首个数字（时数）默认 2ch，百时以上由 JS 挂
   data-overhundred 扩到 3ch；分钟数字固定 2ch（已补零两位，恒 00-59）。 */
.bang-value-n {
  display: inline-block;
  min-width: 2ch;
  text-align: right;
}
.bang-value--duration[data-overhundred="1"] .bang-value-n:first-child {
  min-width: 3ch;
}
.bang-value-u {
  display: inline-block;
  min-width: 1.1em;
  text-align: left;
  color: var(--ink-2);
  font-weight: 400;
}
/* 进步幅度「+15%」/连续天数「45 天」：单层定宽右对齐（含符号最坏情形
   「+100%」5 字符，留够位不挤不抖）。 */
.bang-value--fixed {
  display: inline-block;
  min-width: 5ch;
  text-align: right;
}
/* 榜首：名次与姓名深朱（唯一「正文用深朱」的强调场景，SPEC 明示） */
.bang-row[data-top="1"] .bang-rank,
.bang-row[data-top="1"] .bang-name {
  color: var(--red-text);
}
/* 本人行：衬纸底 + 上下朱丝细线 + 行首小朱点（色点用途） */
.bang-row--me {
  background: var(--paper-3);
  margin: 0 calc(var(--s5) * -1);
  padding: var(--s3) var(--s5);
  border-top: var(--lw-line) solid var(--line-red);
  border-bottom: var(--lw-line) solid var(--line-red);
}
.bang-dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--seal);
  flex-shrink: 0;
}
.bang-footer {
  margin-top: var(--s3);
  padding-top: var(--s3);
  /* R-041(owner 20260723二次截图令,T5,截图6红框)："榜单卡内、'管理员账号不
     参与成员榜单'提示行上方的一道虚线,删"——border-top 已删除，padding-top
     保留只当纯间距用。.bang-footer 是单一组件位置在榜单卡尾部，三种文案
     （管理员不参与提示/本周期无记录提示/本周新上路名单）复用同一个 class、
     同一个视觉位置，非三张不同卡片，故一并去除，不做按角色/文案的按条件
     扣留（回执"一致性观察"列出，供 owner 复核）。 */
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-3);
}


/* ============================================================================
   11. 录入面板「记一笔 · 时段记录/模糊录入」：entry-ticket / entry-mode-switch /
   entry-mode-body(.entry-mode-layer ×2) / numwheel / numfield / shichen-tag
   （V3 SPEC §6 推倒重做，R-011 引擎口径：单笔上限 18 时 59 分=1139 分钟；
   V4 SPEC §10 R-013⑨措辞表：细记→时段记录、约记→模糊录入、签条下小字
   「择一而记」删除、「坐了多久」→「大概练了」、「此笔不计入时辰分布」提示
   行删除——.entry-mode-hint/.entry-approx-hint 两个 class 随对应元素一并
   下架；V4.2 SPEC §5 R-014④：.entry-mode-body 改 grid 双层常驻叠放，两模式
   内容层同格重合渲染，非活动层 .entry-mode-layer[data-active="false"] 走
   visibility:hidden 仍占位撑高度，切换零跳动只剩 opacity 渐换，旧版
   data-state="switching" 整体清空重建机制随之下架）
   DOM 契约：
   <div class="mask" data-state="open|closed"></div>
   <div class="entry-ticket ticket" data-state="open|closed" role="dialog" aria-modal="true">
     <div class="entry-ticket-head">
       <h2 class="entry-ticket-title">记一笔 · 七月二十</h2>
       <span class="entry-ticket-now shichen-tag">
         <span class="shichen-tag-zi">戌</span><span class="shichen-tag-suffix">时</span>
       </span>
     </div>
     <div class="ticket-divider"></div>
     <div class="entry-mode-switch">
       <button class="entry-mode-tab" aria-selected="true">时段记录</button>
       <span class="entry-mode-sep" aria-hidden="true"></span>
       <button class="entry-mode-tab" aria-selected="false">模糊录入</button>
     </div>
     <div class="entry-mode-body"><!-- SPEC V4.2 §5：grid 双层常驻叠放，同格重合 -->
       <div class="entry-mode-layer" data-mode="precise" data-active="true" aria-hidden="false">
         <!-- 时段记录：起/止两组字段，无实时派生摘要 -->
         <div class="entry-field-group">
           <p class="entry-field-label">起</p>
           … 双滚轮/输入格（时 0-23，分 0-59）…
         </div>
         <div class="ticket-divider"></div>
         <div class="entry-field-group">
           <p class="entry-field-label">止</p>
           … 同款控件 …
         </div>
       </div>
       <!-- 模糊录入层：与上面同格叠放常驻，非活动态 data-active="false"
            （visibility:hidden，仍占位撑高度）；单行「大概练了」-->
       <div class="entry-mode-layer" data-mode="approx" data-active="false" aria-hidden="true">
         <div class="entry-field-group">
           <p class="entry-field-label">大概练了</p>
           … 双滚轮/输入格（时 0-18，分 0-59）…
         </div>
       </div>
     </div>
     <p class="entry-error" data-visible="true">至少一分钟</p>
     <div class="ticket-divider"></div>
     <button class="btn entry-confirm" disabled>记下</button>
     <!-- 面板内「当日笔录」：复用 Components.dayTickets 填充，见 §12 -->
   </div>
   ========================================================================== */
.mask {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--scrim);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-modal) var(--ease-out);
}
.mask[data-state="open"] { opacity: 1; pointer-events: auto; }
/* R-019④「记一笔背景也要虚化」新契约类(W13a 新增,W13b 挂到记一笔的 .mask
   div 上，即 class="mask mask--blur")：.mask 全站共用(登录浮层遮罩另有专属
   .book-auth-mask 已带虚化，见 §16)，不直接改 .mask 基类以免波及未来其他
   用途，改用独立修饰类，强度与 .book-auth-mask 同款 blur(5px) */
.mask--blur {
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}

/* R-016③：移动端此前是从屏底升起的抽屉（translateY(100%) → 0），与桌面居中
   浮层是两套构图；owner 打回=录入要居中，移动/桌面同构——底部抽屉整套下架，
   改为全断点统一的居中浮层（位移+缩放+透明度进场，原桌面断点的进场手感直接
   收作全局默认，不再区分断点）。宽度 min(460px, 视口减两侧 --s5 留白)，最窄
   375 端得 375-48=327px，两侧各留 24px 呼吸；768px+ 走满 460px 定宽。 */
.entry-ticket {
  position: fixed;
  z-index: 51;
  left: 50%; top: 50%;
  width: min(460px, calc(100vw - var(--s5) * 2));
  max-height: 85vh;
  overflow-y: auto;
  padding: var(--s5) var(--s4) var(--s6);
  pointer-events: none;
  box-shadow: var(--shadow-float);
  border-radius: var(--r-pop); /* R-019④浮层级用 pop 令牌(大于卡片 r-card)(W13a) */
  transform: translate(-50%, -48%) scale(.98);
  opacity: 0;
  transition: transform var(--t-modal) var(--ease-out), opacity var(--t-modal) var(--ease-out);
}
.entry-ticket[data-state="open"] {
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}
/* .entry-ticket 同时挂 .ticket class(见 §5 .ticket::before 内线),浮层用
   r-pop 半径大于普通卡片 r-card，内线圆角需跟随重算(2 类复合选择器保证
   特异性稳赢 .ticket::before，不依赖源码顺序) */
.entry-ticket.ticket::before {
  border-radius: calc(var(--r-pop) - 2px);
}
.entry-ticket-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  margin-bottom: var(--s2);
}
.entry-ticket-title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-sub);
  color: var(--ink);
}
/* R-023:标题干支段换行——「{年柱}年 {月柱}月 {日柱}日」独立副行居首行下方,
   常规字重淡一档,与首行拉开主辅层级 */
.entry-ticket-title-ganzhi {
  display: block;
  margin-top: 2px;
  font-weight: 400;
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  letter-spacing: var(--ls-wide);
}
.entry-field-group { margin: var(--s4) 0; }
/* R-020②:细记 起/止 左右并排一行(止在右);窄屏(移动端双滚轮 4 列摆不开)
   经 flex-wrap 自动回退上下堆叠,不另设断点 */
.entry-precise-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s5);
}
.entry-precise-row .entry-field-group {
  /* 基宽 150px:sheet 内容宽(桌面~420/移动~340)均可容双列一行;仅极窄端
     (<320px 级)才触发 wrap 回退堆叠 */
  flex: 1 1 150px;
  min-width: 0;
}
/* R-021②:模糊录入层整组居中——「大概练了」标签与 时:分 输入组(inline-flex,
   吃 text-align)同轴;细记层不受影响 */
.entry-mode-layer[data-mode="approx"] .entry-field-group {
  text-align: center;
}
.entry-field-label {
  font-family: var(--font-body);
  font-size: var(--fs-fieldlabel);
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
  margin-bottom: var(--s3);
}
/* ---- 双签条：时段记录 / 模糊录入（SPEC §6.1 第 2 条，措辞 V4 §10 R-013⑨）---- */
.entry-mode-switch {
  display: flex;
  align-items: stretch;
  margin-top: var(--s3);
}
.entry-mode-tab {
  position: relative;
  flex: 1;
  height: 40px;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink-2); /* 未选中=重墨 */
  border-bottom: var(--lw-line) solid var(--line);
  transition: color var(--t-fast) var(--ease-out);
}
.entry-mode-tab[aria-selected="true"] {
  color: var(--ink); /* 选中=浓墨 */
  font-weight: 600;
  border-bottom-color: transparent; /* 与内容区之间不画底边线 */
}
/* 选中签：签底 2px 短朱线（非通栏），仿票号题签惯例 */
.entry-mode-tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 0;
  transform: translateX(-50%);
  width: 28px;
  height: var(--lw-heavy);
  background: var(--line-red);
}
.entry-mode-sep {
  width: var(--lw-line);
  margin-bottom: var(--lw-line);
  background: var(--line);
  flex-shrink: 0;
}
/* 模式内容区：双层常驻叠放（SPEC V4.2 §5，R-014④）——时段记录/模糊录入
   两层同格叠放（grid-area 重合），容器高度=两层最大值，切换零跳动；非活动
   层 visibility:hidden 仍占位（贡献 grid 高度但不可见/不可交互），只有
   入场层单向淡入 ≤140ms（复用 --t-page 页面切换节奏）。离场层立即 hidden，避免
   「起/止」与「大概练了」及两组时间轴在交叠淡化期间形成重影。visibility:hidden
   仍参与 grid 尺寸计算，因此组件高度不跳动。 */
.entry-mode-body {
  display: grid;
}
.entry-mode-layer {
  grid-area: 1 / 1;
  min-width: 0;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
/* 二轮盲审 P2:等高约束下模糊录入层内容少,顶排导致下方大片空白——
   内容垂直居中,留白上下分摊,观感从容 */
.entry-mode-layer[data-mode="approx"] {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.entry-mode-layer[data-active="true"] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity var(--t-page) var(--ease-out);
}
.entry-error {
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--red-text);
  margin-top: var(--s2);
  display: none;
}
.entry-error[data-visible="true"] { display: block; }
/* R-016③排版优化：确认键此前只继承 .btn 的内容宽（inline-flex 无 width），
   窄条挤在票面左侧，观感像普通行按钮而非本面板的主操作——改满宽、与
   .book-submit 同级处理，视觉上真正立住"这是这张票的唯一确认动作"。 */
.entry-confirm {
  width: 100%;
  margin-top: var(--s1);
}
/* 「记下」确认键与「当日笔录」参考列表层级拉开（同一条要求②）：确认键是本
   面板唯一的主操作，当日笔录只是只读参考，视觉权重理应明显更低——分隔线
   之外再加一段留白（--s3，与分隔线自身 --s4 margin 叠加，总间距约等于
   --s4+--s3，读作与上方字段组的 --s4 节奏有意拉开一档，而非同级紧邻）。 */
.entry-daylist { margin-top: var(--s3); }
.entry-quick {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
  transition: color var(--t-fast) var(--ease-out);
}
.entry-quick:hover:not(:disabled) { color: var(--ink); }
/* 时长未填时置灰不可点：淡墨字 + 虚线换乌丝色，不引入新灰阶 */
.entry-quick:disabled {
  color: var(--ink-3);
  text-decoration-color: var(--line);
  cursor: not-allowed;
}

/* ---- 朱丝细框小签：面板当前时辰徽章（SPEC §6.2 修正版，R-012 ⑤）----
   根因修复：齐伋体做小字违 §7.3 排印纪律，改霞鹜文楷（font-body）+ 主辅两级
   （地支字浓墨 15px / 「时」字淡墨 11px 基线微降，仿票号大数小单位）；
   框仅保留朱丝边线（--line-red），文字改墨色（不再用红做正文字色）；
   固定内边距 + line-height:1 + flex 居中，min-width 取十二字实测最宽值
   （WenKai 全角字符等宽，两字内容天然不跳宽，min-width 兜底防极端字重差异）。 */
.shichen-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 62px;
  padding: 0.35em 0.6em;
  border: var(--lw-line) solid var(--line-red);
  line-height: 1;
}
.shichen-tag-zi {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink);
}
.shichen-tag-suffix {
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--ink-3);
  position: relative;
  top: 0.15em; /* 基线微降 */
  margin-left: 1px;
}
/* 当前时辰行（时辰账页 §9）与本组件共用「主辅分级」语汇，深朱强调走
   .ledger-row[data-now="true"] 自身规则，不叠加在 shichen-tag 上 */

/* ---- 移动端苹果计时器式双滚轮（无秒，时 0-18 / 分 0-59 逐分） ---- */
.numwheel {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--s3);
  height: 176px;
}
.numwheel::before,
.numwheel::after {
  content: "";
  position: absolute;
  left: var(--s3); right: var(--s3);
  height: var(--lw-hair);
  background: var(--line);
  pointer-events: none;
  z-index: 1;
}
.numwheel::before { top: calc(50% - 18px); }
.numwheel::after { top: calc(50% + 18px); }

.numwheel-col {
  flex: 1;
  max-width: 72px;
  height: 100%;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  scroll-padding: 50% 0;
  overscroll-behavior: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
  mask-image: linear-gradient(to bottom, transparent 0%, black 34%, black 66%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 34%, black 66%, transparent 100%);
}
.numwheel-col::-webkit-scrollbar { display: none; }
.numwheel-pad { height: 72px; scroll-snap-align: none; }
.numwheel-item {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  scroll-snap-align: center;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  color: var(--ink-3);
  opacity: .5;
  transition: color var(--t-fast) var(--ease-out), opacity var(--t-fast) var(--ease-out);
}
.numwheel-item[data-selected="true"] {
  opacity: 1;
  color: var(--ink);
  font-weight: 600;
}
.numwheel-unit {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}
/* 空态：仅隐去当前居中的"选中槽"（无默认值时它不代表真实选择），其余可拨动列项
   照常可见（沿用默认的淡墨/浓墨双态），居中叠加「—」占位刻线顶替被隐去的选中项数字。
   D1 修复：旧规则曾无差别隐去整列全部项（含未选中项），导致移动端滚轮列在触碰前
   数字滚轮"完全空白不可见"，只剩「时 — 分」单位行——此规则必须只命中
   [data-selected="true"] 这一项，其余项交给默认 .numwheel-item 样式正常显示。 */
.numwheel[data-empty="true"] .numwheel-item[data-selected="true"] { color: transparent; opacity: 0; }
.numwheel-empty-mark {
  display: none;
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  transform: translateY(-50%);
  text-align: center;
  font-family: var(--font-num);
  font-size: 20px;
  color: var(--ink-3);
  pointer-events: none;
  z-index: 2;
}
.numwheel[data-empty="true"] .numwheel-empty-mark { display: block; }

/* 手机录入面板让两种模式继续在同一 grid 轨道叠放并共同决定固定高度。
   非活动层仅不可见、不可交互，仍保留几何占位；这样切换模式时，确认按钮与
   当日记录不会上下跳动。起止保持同排，触屏滚轮继续使用紧凑尺寸。 */
@media (max-width: 767px) {
  .entry-mode-body { display: grid; }
  .entry-mode-layer { grid-area: 1 / 1; }
  .entry-precise-row {
    flex-wrap: nowrap;
    gap: var(--s2);
  }
  .entry-precise-row .entry-field-group {
    flex: 1 1 0;
    margin: var(--s2) 0;
  }
  .entry-mode-layer[data-mode="approx"] {
    justify-content: flex-start;
  }
  .entry-mode-layer[data-mode="approx"] .entry-field-group {
    margin: var(--s2) 0;
  }
  .entry-field-label { margin-bottom: var(--s1); }
  .numwheel {
    height: 128px;
    gap: var(--s1);
  }
  .numwheel-col { max-width: 52px; }
  .numwheel-pad { height: 46px; }
}

/* ---- 桌面端就地数字输入格 ---- */
.numfield-group {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
}
.numfield {
  width: 64px;
  height: 40px;
  text-align: center;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl); /* R-019④小控件统一用 --r-ctl(原 --r-sm)(W13a) */
  background: var(--paper-2);
  color: var(--ink);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sub);
  transition: border-color var(--t-fast) var(--ease-out);
}
.numfield::placeholder { color: var(--ink-3); font-family: var(--font-body); }
/* .numfield:focus 聚焦变色已删——owner 20260805 三令:任何选中框都不要 */
.numfield[data-invalid="true"] { border-color: var(--red-text); color: var(--red-text); }
.numfield-sep { color: var(--ink-3); }


/* ============================================================================
   12. 记录卡片 day-tickets（一日多笔，SPEC §5.6 结尾）
   DOM 契约：
   <section class="day-tickets">
     <div class="tag-rule"><span class="tag-rule-label">今日之录</span><span class="tag-rule-line"></span></div>
     <div class="ticket-row day-ticket">  <!-- R-022③ 账目式两行 -->
       <div class="day-ticket-head">
         <span class="day-ticket-index num">第 1 笔</span>
         <span class="day-ticket-shichen">申时</span>  <!-- 模糊录入笔=「模糊录入」 -->
         <span class="day-ticket-dur num">45 分钟</span>  <!-- margin-left:auto 右靠 -->
         <span class="day-ticket-flag day-ticket-flag--backfill">补录</span>
         <span class="day-ticket-actions">
           <button class="day-ticket-action">改</button>
           <button class="day-ticket-action">删</button>
         </span>
       </div>
       <div class="day-ticket-body">  <!-- 仅时段记录笔有 -->
         <span class="day-ticket-meta">(起止对分解见下方注释)</span>
       </div>
     </div>
     ...
   </section>
   ========================================================================== */
.day-ticket {
  /* R-022③:单行 flex 改「账目式两行」块结构(head 摘要行 + body 起止行),
     根治窄容器单行挤爆叠字 */
  display: block;
  transition: background var(--t-fast) var(--ease-out);
}
.day-ticket:hover { background: var(--paper-3); }
.day-ticket-head {
  display: flex;
  align-items: center;
  gap: var(--s3);
}
.day-ticket-body {
  margin-top: var(--s2);
}
.day-ticket-index {
  flex-shrink: 0;
  color: var(--ink-2);
  font-weight: 600;
}
.day-ticket-meta {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s3);
  font-family: var(--font-body);
  color: var(--ink);
}
/* R-022③ 结构化三段(时辰签/起止对/时长),替代旧自由文本串:
   <span class="day-ticket-shichen">亥时</span>(模糊录入笔=「模糊录入」)
   <span class="day-ticket-meta">
     <span class="tk-time"><span class="tk-time-label">起</span><span class="tk-time-val num">22:39</span></span>
     <span class="tk-arrow">→</span>
     <span class="tk-time"><span class="tk-time-label">止</span>[<span class="tk-time-extra">次日</span>]<span class="tk-time-val num">23:50</span></span>
   </span>
   <span class="day-ticket-dur num">1 时 11 分</span> */
.day-ticket-shichen {
  flex-shrink: 0;
  font-size: var(--fs-caption);
  color: var(--ink-2);
  border: var(--lw-hair) solid var(--line);
  border-radius: var(--r-ctl);
  padding: 1px 6px;
  white-space: nowrap;
}
.tk-time {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  white-space: nowrap;
}
.tk-time-label,
.tk-time-extra,
.tk-arrow {
  font-size: var(--fs-caption);
  color: var(--ink-3);
}
.day-ticket-dur {
  flex-shrink: 0;
  margin-left: auto;
  white-space: nowrap;
  font-weight: 600;
  color: var(--ink);
}
.day-ticket-flag {
  flex-shrink: 0;
  font-size: var(--fs-caption);
  color: var(--ink-2);
  border: var(--lw-hair) dashed var(--line);
  padding: 1px 6px;
}
/* 行内操作：静止不可见，hover/聚焦才显影（design-taste 黄金法则③） */
.day-ticket-actions {
  flex-shrink: 0;
  display: inline-flex;
  gap: var(--s3);
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease-out);
}
.day-ticket:hover .day-ticket-actions,
.day-ticket:focus-within .day-ticket-actions { opacity: 1; }
.day-ticket-action {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
}
.day-ticket-action:hover { color: var(--ink); }


/* ============================================================================
   13. 空态 empty / 通用按钮
   ========================================================================== */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  padding: var(--s7) var(--s4);
  text-align: center;
}
.empty-title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-sub);
  color: var(--ink-2);
}
.empty-desc {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  max-width: 300px;
}

/* 通用按钮：骨架永远黑白灰，色彩只进数据（design-taste 黄金法则②），
   主按钮浓墨底+纸色字，禁彩色胶囊/渐变/投影 */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  height: 40px;
  padding: 0 var(--s4);
  border-radius: var(--r-ctl);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  border: var(--lw-line) solid var(--ink);
  background: var(--ink);
  color: var(--paper-2);
  transition: background var(--t-fast) var(--ease-out), opacity var(--t-fast) var(--ease-out);
}
.btn:hover:not(:disabled) { opacity: .9; }
.btn:active:not(:disabled) { opacity: .8; }
/* D3：禁用态不许走"现代灰"（opacity 淡化整块底+字同时褪色，视觉上是灰盒子）；
   改用票据语汇——票面底 + 乌丝虚线框 + 淡墨字，与可用态"浓墨底纸色字"区分明确，
   同一套四色令牌内表达，不引入任何新灰阶 */
.btn:disabled {
  opacity: 1;
  cursor: not-allowed;
  background: var(--paper-2);
  border-style: dashed;
  border-color: var(--line);
  color: var(--ink-3);
}
.btn-ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--ink);
}
.btn-ghost:hover { background: var(--paper-3); opacity: 1; }

/* 分段控件（周/月/年、子榜切换等，跨组件复用） */
.seg {
  display: inline-flex;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl); /* R-019④小控件统一用 --r-ctl(W13a) */
  padding: 2px;
  gap: 2px;
}
/* CARD-G3W10（F-P1-03/04：近七日/近三十日切换、榜签/子榜签命中区扩容）：
   视觉像素零变化铁律——.seg-item 选中态自带可见背景/描边，若直接放大自身
   padding 会连带放大那块可见胶囊，所以真正的可见外观（背景/边框）移到
   ::before 伪层，固定钉在原 5px/14px 的相对位置；宿主 .seg-item 自身只借
   透明 padding+等量负 margin 把「量出来的」命中盒子撑到 ≥44px，父级
   flex/grid 轨道按 margin-box 折算回原值，不占用旁边元素的空间、不移动
   布局流。横向只加 1px/边——.seg 容器自身 gap 仅 2px（三签一排的
   「周/月/年」），加满会让相邻签的命中盒真重叠；加 1px/边正好在 2px 缝隙
   中点相遇不重叠，刚好够把 F-P1-04 实测最窄 43px 一档顶到 ≥44。 */
.seg-item {
  padding: 11px 16px; /* 5px/14px 原值各 +6/+2；比命中区差额多算 1px 补偿
    「取消原占位边框」腾出的 2px(原 border 1px×2 边)，否则净增量会被吃掉
    (实测踩过一次坑：单纯 +5/+1 换算，边框归零后量出来只有 43px，达不到 44) */
  margin: -5px -1px;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  color: var(--ink-2);
  border: none;
  border-radius: calc(var(--r-ctl) - 2px); /* 内层选中态胶囊跟随外框圆角收 2px(W13a) */
  position: relative;
  z-index: 0; /* 显式建立层叠上下文，保证下方 ::before(z-index:-1) 只压在
                 自己文字下面，不牵动页面其它层叠顺序 */
  transition: color var(--t-fast) var(--ease-out);
}
.seg-item::before {
  content: "";
  position: absolute;
  top: 5px; right: 1px; bottom: 5px; left: 1px; /* 精确抵消上面加出来的
    padding，钉回原 5px/14px 视觉框位置——见上方说明 */
  border: var(--lw-line) solid transparent; /* 占位边框，防选中态描边致尺寸抖动 */
  border-radius: calc(var(--r-ctl) - 2px);
  z-index: -1;
  pointer-events: none;
  transition: background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.seg-item[aria-selected="true"] {
  color: var(--ink);
  font-weight: 600;
}
.seg-item[aria-selected="true"]::before {
  background: var(--paper-3);
  border-color: var(--ink-2);
}


/* ============================================================================
   14. 纸纹背景 / 印章 seal-v2 / 鱼尾 fishtail
   ========================================================================== */
/* 宣纸质感：构建期烘焙 PNG data-URI（见 tokens.css --texture-xuanzhi 注释），
   两层暖色云絮 radial-gradient 还原纤维疏密 + multiply 纹理平铺，
   固定于视口不随滚动重算，任何文字/图表下不可感知颗粒（纹理压字门自查通过：
   α 上限 3.9% 远低于正文墨色 14.9:1 对比度量级，不构成阅读阻碍）。 */
body {
  background-color: var(--paper);
  background-image:
    radial-gradient(ellipse 60% 40% at 15% 8%, rgba(var(--paper-3-rgb), .55), transparent 60%),
    radial-gradient(ellipse 55% 55% at 88% 82%, rgba(var(--paper-3-rgb), .45), transparent 65%),
    var(--texture-xuanzhi);
  background-repeat: no-repeat, no-repeat, repeat;
  background-size: auto, auto, 220px 220px;
  background-attachment: fixed, fixed, fixed;
  background-blend-mode: normal, normal, multiply;
}

/* 印章「正统炎黄」logo（CARD-G3W11 R-031①，接线上站，替代 V4/V4.2「压角
   朱文印」DOM 拼字方案）：owner 验收终版矢量 SVG 内联注入（来源见
   ui-pages.js buildSealQuad 头注），登录/注册书名页与首屏立轴共用同一枚，
   微旋转仅此一处使用（SPEC V4 §3 R-013②，V4.2 §2 立轴构图沿用，本卡原样
   保留）。.seal-v2 容器宽高（占位尺寸）与旧方案完全一致，零布局位移；
   内部旧三层（.seal-v2-face 印面底+.seal-v2-frame 双线印边+.seal-v2-chars
   2×2 田字格四字）随本卡整体下架，改由 .seal-v2 svg 规则把内联 SVG 撑满
   容器。 */
.seal-v2 {
  position: relative;
  display: inline-block;
  width: 50px;
  height: 50px;
  transform: rotate(-.3deg); /* SPEC §4.5「微旋转 ±0.3deg 只允许印章使用」 */
}
.seal-v2 svg {
  display: block;
  width: 100%;
  height: 100%;
}
@media (min-width: 768px) {
  .seal-v2 { width: 76px; height: 76px; }
}

/* 压角位停靠语汇沿用：立轴构图中改「与题字栏同轴水平居中」，实际定位交由
   V4.2 新增 .scroll-seal-dock 覆盖（见 §16），本类只保留内层 flex 居中骨架。 */
.seal-v2-dock {
  display: flex;
  justify-content: center;
  width: 100%;
}

/* 鱼尾：页脚窄三角收尾装饰（R7 §5.3）。纯 CSS 三角——原「〆」字符系日文占位符
   且不受子集保证，G2 终审改为零字体依赖画法（古籍版心鱼尾的窄三角转译） */
.fishtail {
  display: flex;
  justify-content: center;
  margin: var(--s6) 0 var(--s4);
}
/* R-020③:页脚收尾装饰由窄三角改「旋转太极」——单元素纯 CSS 画法(零字体
   零图片依赖):底层 180° 线性分色(上墨下纸)+两枚半径 25% 的鱼眼圆(左墨含
   纸点/右纸含墨点)拼出 S 形回旋;慢速匀速自转,reduced-motion 下静止(§15) */
.fishtail::before {
  content: "";
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: var(--lw-hair) solid var(--line);
  /* R-022②:鱼向镜像修正——顺时针自转不变,但两鱼头(圆球端带鱼眼的大圆弧)
     必须领先于旋转方向:墨鱼身居上半,鱼头圆球改在右侧中线(左侧为其收尖鱼尾),
     顺时针时头在前尾在后「顺着圆球方向」游;纸鱼对偶。旧版头尾颠倒=倒着游 */
  background:
    radial-gradient(circle at 25% 50%, var(--ink-3) 0 2px, var(--paper-2) 2px 4.5px, transparent 4.5px),
    radial-gradient(circle at 75% 50%, var(--paper-2) 0 2px, var(--ink-3) 2px 4.5px, transparent 4.5px),
    linear-gradient(180deg, var(--ink-3) 0 50%, var(--paper-2) 50% 100%);
  animation: taiji-spin 14s linear infinite;
}
@keyframes taiji-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}


/* ============================================================================
   15. 响应式与 reduced-motion / 触控热区
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .mask, .entry-ticket, .numwheel-item,
  .btn, .toc-item, .tab-paper-item, .entry-mode-body, .entry-mode-layer,
  .day-ticket-actions, .page-fade {
    transition: none !important;
  }
  .fishtail::before { animation: none !important; } /* R-020③ 太极静止 */
}

/* 触控热区兜底：一切可点击控件最小 44px（可访问性红线） */
.btn, .toc-item, .tab-paper-item, .seg-item, .gridcal-month, .day-ticket-action,
.masthead-switch, .entry-quick, .entry-mode-tab {
  min-height: 44px;
}
.seg-item, .gridcal-month, .day-ticket-action, .masthead-switch, .entry-quick {
  min-height: auto; /* 纯文字型次要操作不强制点击热区，避免行内文字被撑成大按钮块 */
}

/* ============================================================================
   CARD-G3W10 移动触达热区扩容（F-P1-01/02/05/06/07/08，依据 G3W9 回执 §3）
   统一配方：本组元素均为「纯文字/图标+下划线」型次要操作，自身零背景零
   边框，可以直接对宿主本体加透明 padding + 等量负 margin——padding 计入
   元素自身 getBoundingClientRect（命中区审计据此判定），负 margin 在父级
   flex/grid 的 margin-box 折算里精确抵消掉新增的 padding，兄弟元素间距、
   自身可见文字位置、可见描边/背景（本组均无）三者都不移动，符合工单铁律
   「布局流不许动」。.seg-item（F-P1-03/04）例外——它自带可见选中态背景，
   拆到 §13 原位用 ::before 单独处理，见上方注释。
   各元素方向偏置均取自「往非交互空白处扩、往相邻可点元素方向少扩」的
   原则，避免命中区互相重叠误触相邻控件（尤其记一笔改/删两个高风险动作）。
   ========================================================================== */

/* F-P1-01 masthead 品牌名「练功志」52×28→需高度达标，宽度已够，纯上下扩 */
.masthead-brand {
  padding-top: 9px;
  padding-bottom: 9px;
  margin-top: -9px;
  margin-bottom: -9px;
}

/* F-P1-02 masthead 右上「退出登录」59×19→高度缺口大，且紧贴上方日期/时辰
   行(两行间 row-gap 仅 2px)——绝大部分扩容量往下方乌丝线/刻度尺方向要
   (纯装饰区零冲突)，往上只留 3px 最小缓冲 */
.masthead-switch {
  padding-top: 3px;
  padding-bottom: 23px;
  margin-top: -3px;
  margin-bottom: -23px;
}

/* F-P1-05（记一笔改/删，13×23，本卡重点）+ F-P1-06（管理操作行，同一
   .day-ticket-action 视觉语汇复用，26px 高文字链接）：先统一垂直方向
   （两个场景都要达标，取两者所需的较大值）+ 一份对管理行窄标签（"成就"
   "停用"30px 宽）也够用的通用水平缓冲；记一笔面板内改/删两钮横向差距太
   大（13→44 需要单边多补近 30px），再用 :first-child/:last-child 单独
   往各自「外侧」（远离另一个按钮的一侧）加码，内侧只留 5px，两内侧共
   10px < 该容器 12px 的 gap，命中区不重叠，不会连累点错「删」。 */
.day-ticket-action {
  padding: 11px 8px;
  margin: -11px -8px;
  position: relative;
}
.day-ticket-actions .day-ticket-action:first-child {
  padding-left: 27px;
  padding-right: 5px;
  margin-left: -27px;
  margin-right: -5px;
}
.day-ticket-actions .day-ticket-action:last-child {
  padding-left: 5px;
  padding-right: 27px;
  margin-left: -5px;
  margin-right: -27px;
}

/* F-P1-07 我的页「退出登录」/「管理后台」60×26（.me-settings 纵向排列，
   gap 12px）：两条各自往「远离另一条」的方向多扩，挨着对方的一侧只留
   2px，两侧共 4px < 12px gap，不重叠；仅剩「退出登录」一条时(非管理员，
   常见情形)同时命中 :first-child 与 :last-child，取源码序靠后的
   :last-child 那套值，向下多留、向上留 2px，同样安全达标。 */
.me-settings-link {
  position: relative;
}
.me-settings-link:first-child {
  padding-top: 16px;
  padding-bottom: 2px;
  margin-top: -16px;
  margin-bottom: -2px;
}
.me-settings-link:last-child {
  padding-top: 2px;
  padding-bottom: 16px;
  margin-top: -2px;
  margin-bottom: -16px;
}

/* F-P1-08a 登录/注册/强改密卡「显示/隐藏」密码切换 26×23：field-toggle
   与下方 .field-text 输入框只隔 2px(.book-fieldrow 的 column gap)，向下
   只留 2px 防止咬进输入框可点范围，缺口全部往上要（上方是同一行的字段
   标题文字，非交互，零冲突）。横向本以为两侧都是空白余量对称外扩即可，
   实测踩坑：.book-fieldrow-head 是 justify-content:space-between，
   field-toggle 本就贴着卡片右侧内边距零富余，右侧一旦外扩就会让
   .book-auth-layer 的 scrollWidth 真的量出超出 clientWidth（哪怕像素不可见，
   仍会被 §三 A 容器横滚断言判定为「可横滚」）——右侧起初改留 1px 仍未清零
   （space-between 的自由空间分配一旦算不平，残留的 1px 一样会露出来），
   最终改成右侧完全归零（padding-right/margin-right 均不动），横向缺口
   全部改从左侧要(左侧到字段标题之间有大片留白，绝对安全)。 */
.field-toggle {
  padding: 20px 0 3px 20px; /* top/right/bottom/left：右侧维持原值 0 完全不
    动(实测 space-between 布局对右侧哪怕仅 +1px 都会让 .book-auth-layer
    量出可横滚，干脆右侧零改动最保险)，横向缺口全部改从左侧要 */
  margin: -20px 0 -3px -20px;
}

/* F-P1-08b 登录/注册卡底「去注册/去登录」39×17：所在 .book-card-foot 是
   独立段落，行内 <a>，是这一行末尾唯一的收尾元素。实测踩坑：内联(inline)
   元素的负 margin 只影响「后面还有兄弟内容」时的相对位置——它是行尾最后
   一个元素，右侧没有后续内容可以被负 margin-right"拉回去"，padding-right
   加多少，自身盒子的右边缘就真的往右多出多少，量出来是 .book-auth-layer
   真横向溢出（首次按左右对称各 +3px 处理时，6 档全部命中 §三 A 容器横滚
   断言，实测 scrollWidth 比 clientWidth 多 3px，与「唯一的行尾元素+右侧
   padding 净移动」的量完全吻合）。改法＝右侧 padding/margin 都归零(不动)，
   横向缺口全部改从左侧要（原理与 F-P1-08a 同源，见上方 .field-toggle 注释）；
   上下则不受这条「行尾元素」限制——内联元素的纵向 padding 只会视觉溢出到
   行框外，不进入横向 scrollWidth 计算，也不影响行高，两侧对称扩没有风险。 */
.book-link {
  padding: 14px 0 14px 6px;
  margin: -14px 0 -14px -6px;
}


/* ============================================================================
   16. 登录/注册「立轴」首屏 + 渐显浮层（V4.2 §2/§3 R-014①② 推倒重做，替代
   V3/V4「书名页」三件套平起平坐版式；仅登录/注册两态使用，不挂 masthead/
   toc/tab-paper——「开卷之前不算书内页」）
   DOM 契约（立轴首屏，默认态，零表单）：
   <main class="page book-page">
     <div class="book-page-inner">
       <div class="scroll">
         <p class="scroll-slogan">争分夺秒 · 刻不容缓</p>  <!-- 竖排侧款，起笔低于「練」 -->
         <div class="scroll-title-col">
           <h1 class="scroll-title">练功志</h1>            <!-- 竖排单栏，齐伋体 -->
           <div class="seal-v2-dock scroll-seal-dock">
             <div class="seal-v2 seal-v2--quad" aria-hidden="true">…印随字尾，见 §14…</div>
           </div>
         </div>
       </div>
       <button class="btn scroll-enter">进入</button>
       <div class="fishtail"></div>
     </div>
   </main>
   <div class="mask book-auth-mask" data-state="closed"></div>
   <div class="book-auth-overlay" data-state="closed" role="dialog" aria-modal="true">
     <div class="ticket book-card book-auth-card">
       <div class="ticket-body">…登录卡（默认）或注册卡内容，二态互斥渐换…</div>
     </div>
   </div>
   点「进入」→ .book-auth-mask/.book-auth-overlay 打上 data-state="open"（单层
   opacity ≤140ms + 遮罩 backdrop-filter 虚化）；浮层内「去注册」/「去登录」
   原地渐换 .ticket-body 内容（不重新开合浮层外壳）；Esc/点遮罩关闭回首屏。
   .book-card-title/.book-fieldrow/.field-text/.field-toggle/.ticket-divider/
   .book-submit/.book-card-foot/.book-link 字段语汇不变（详见下方浮层区规则）。
   1280 断点：.book-page-inner 整组偏左约 42% 视口宽，.book-page::before/::after
   两根发丝竖线=卷轴绫边。印章结构详见 §14「压角朱文印」。
   ========================================================================== */
.book-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px; /* SPEC §2.2「375：整屏即立轴画心…四边 24px 装裱留白」 */
  position: relative;
}
.book-page-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%; /* R-017 axisa:flex 下 inner 宽度塌缩会让台面百分比定位全坍中轴 */
}
/* ---- 首屏 V5「纵轴偏右」台面 axisa（R-017 方案 A 修订版,取代下方 .scroll
   立轴构图;.scroll* 规则组保留仅为历史对照,DOM 已不再引用）。台面居中于
   视口(呼应 owner 居中令),轴线在台面内偏右 73%;顶部留白 clamp 保底不出血。---- */
.axisa {
  position: relative;
  width: 100%;
  max-width: 430px;
  margin: 0 auto;
  height: 100dvh;
  min-height: 584px;
}
.axisa-title {
  position: absolute;
  left: 73%;
  top: clamp(30px, 6dvh, 56px);
  transform: translateX(-50%);
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
  font-size: 100px;
}
.axisa-c { line-height: 1.02; }
.axisa-c1 { transform: translateX(-3px); }
.axisa-c2 { font-size: 1.12em; transform: translateX(1px); }
/* R-021①:「志」增大 20%(1→1.2em,现为三字最大);横挪回 2px 防大字外飘 */
.axisa-c3 { font-size: 1.2em; transform: translateX(2px); }
.axisa-slogan {
  position: absolute;
  writing-mode: vertical-rl;
  text-orientation: upright;
  white-space: nowrap;
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: .42em;
  color: var(--ink-3);
}
.axisa-slogan--a { left: 13%; top: 31%; }
.axisa-slogan--b { left: calc(13% + 26px); top: 34.5%; }
.axisa-seal { position: absolute; left: 7%; bottom: 11%; }
.axisa-seal .seal-v2 { width: 44px; height: 44px; }
.axisa-enter {
  position: absolute;
  right: 8%;
  bottom: 7%;
  background: none;
  border: none;
  border-bottom: var(--lw-thick) solid var(--ink);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  letter-spacing: .12em;
  padding: 10px 4px 10px;
  min-height: 44px;
  cursor: pointer;
}
.axisa-enter:hover { opacity: .78; }
@media (min-width: 768px) {
  .axisa { max-width: 860px; } /* 手卷式:宽屏台面展开,列锚右、左侧大留白(母本桌面口径) */
  .axisa-title { font-size: 122px; }
  .axisa-slogan { font-size: 13px; }
  .axisa-slogan--a { left: 16%; }
  .axisa-slogan--b { left: calc(16% + 28px); }
  .axisa-seal .seal-v2 { width: 54px; height: 54px; }
  .axisa-enter { font-size: 17px; }
}

/* ---- (已退役)立轴构图本体（旧 .scroll,DOM 已不引用,仅存对照） ---- */
.scroll {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  /* G2 终审修(轴线):侧款改绝对定位脱流——在流内会把组合中心挤离題字轴,
     导致印/字轴线与「进入」钮错位 24px;脱流后題字栏=唯一居中主体,
     字、印、钮天然同轴 */
  position: relative;
}
.scroll-slogan {
  writing-mode: vertical-rl;
  text-orientation: upright;
  white-space: nowrap;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  letter-spacing: 0.14em;
  color: var(--ink-3);
  margin: 0;
  position: absolute;
  right: calc(100% + var(--s5));
  top: 2.7em; /* 起笔低于「練」约 15-20% 栏高（em 相对本行 15px 字号） */
}
@media (min-width: 768px) {
  .scroll-slogan { font-size: 16px; top: 3.6em; }
}
.scroll-title-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-size: 78px; /* 题字单字尺寸主控点：.scroll-title 与 .scroll-seal-dock
                       的 em 间距均相对此值计算（SPEC 移动 72-84px 范围内） */
}
@media (min-width: 768px) {
  .scroll-title-col { font-size: 116px; } /* SPEC 桌面 104-120px 范围内 */
}
.scroll-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1em;
  line-height: .97;  /* 字挨字，SPEC 范围 0.95-1 */
  letter-spacing: 0;
  writing-mode: vertical-rl;
  text-orientation: upright;
  white-space: nowrap;
  color: var(--ink);
  margin: 0;
}
.scroll-seal-dock {
  width: auto;              /* 覆盖 §14 .seal-v2-dock 基类的 width:100%，
                                随印面本身尺寸收缩，靠父级 align-items 居中 */
  margin-top: .22em;        /* 志字正下方，垂直间距 0.2-0.25em（相对题字单字尺寸） */
}
.scroll-enter {
  width: 280px;
  max-width: calc(100vw - 48px);
  margin-top: 84px; /* 居构图重心正下方，SPEC 范围 72-96px */
}

/* 1280：R-017 owner 令构图居中(原 42vw 偏心经营位废除);两侧发丝竖线
   =卷轴绫边,随之改对称(左右各 24vw)。 */
@media (min-width: 1280px) {
  .book-page::before,
  .book-page::after {
    content: "";
    position: fixed;
    top: 80px;
    bottom: 80px;
    width: var(--lw-line);
    background: rgba(var(--line-rgb), .35);
    pointer-events: none;
  }
  .book-page::before { left: 24vw; }
  .book-page::after { right: 24vw; }
}

/* ---- 渐显浮层：登录/注册票据卡外壳（SPEC §3）。基础 fixed/z-index/opacity
   过渡骨架复用 §11 .mask 语法（data-state="open" 才可见可交互）；本节只覆写
   遮罩强度/虚化与浮层自身定位，浮层内卡片沿用既有 .book-card/.book-fieldrow
   字段语汇（见下方 .book-card 起）。 ---- */
.book-auth-mask {
  background: var(--scrim-book); /* 墨色 20%，比 --scrim 35% 更浅——立轴在虚焦
                                     中仍隐约可见（SPEC「背景虚化」不等于遮死） */
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}
.book-auth-overlay {
  position: fixed;
  inset: 0;
  z-index: 52; /* 高于 .book-auth-mask 的 z-index:50（继承自 .mask） */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s4); /* 原 s5，为固定正方形腾多 16px 视口余量（R-016②） */
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-page) var(--ease-out); /* 单层 opacity ≤140ms 铁律 */
}
.book-auth-overlay[data-state="open"] {
  opacity: 1;
  pointer-events: auto;
}
/* R-016②：登录卡/注册卡改同一固定尺寸正方形，切换零宽高变化（此前注册比
   登录多一个字段+密码提示行，卡片实测 320×503 vs 320×398，切换时明显跳一
   下）。做法＝复用 §11 entrySheet 双签「时段记录/模糊录入」的双层常驻叠放法
   （.entry-mode-layer 同款）：.book-auth-card 定宽定高的正方形外壳，
   .ticket-body 内改 grid 单格，登录/注册两层同格叠放常驻，只切 data-active
   做 opacity 渐换；容器尺寸由外壳固定值决定，与哪层内容更高无关。
   375 端 344×344，768px+ 420×420（SPEC 建议值 330/400 附近，字段收紧+浮层
   自身内边距收窄后仍无法让注册卡零滚动完整可见，故上调半档换更少滚动，
   两态仍严格同尺寸）；每层内容 overflow-y:auto 兜底——注册三字段+密码提示
   行天然比登录高，字段/间距已按 --s 系列收紧到贴边，仍放不下整卡时层内
   滚动，绝不撑破外壳固定尺寸；justify-content:safe center 保底顶对齐，
   保证滚动场景下标题与提交键两端都可达（实测 plain center 会两端各裁一半）。 */
/* .book-card.book-auth-card 复合选择器（非单独 .book-auth-card）：这两个
   class 同挂在同一元素上，特异性需赢过后面 .book-card 自身的 width:100%/
   max-width:320px（源码顺序在后，单类选择器特异性打平时会覆盖前面的规则）。 */
.book-card.book-auth-card {
  width: 344px;
  height: 448px; /* R-018:375 端正方形数学上装不下注册三字段的从容排布(硬塞=滚动条/裁切,
                    丑的根源)——移动端改同尺寸竖幅(1:1.3),两态零跳变铁律不变;桌面正方形保留 */
  max-width: calc(100vw - var(--s4) * 2); /* 随 .book-auth-overlay 的 s4 内边距同步 */
  padding: var(--s5) var(--s5) var(--s4); /* R-018:底线式输入省出的高度还给呼吸感 */
  border-radius: var(--r-pop); /* R-019④浮层级用 pop 令牌(大于卡片 r-card)(W13a) */
  text-align: left;
  display: flex;
  flex-direction: column;
}
/* 同 .entry-ticket 处理：.book-auth-card 同时挂 .ticket class（内线 ::before
   继承自 §5），浮层圆角覆写为 r-pop 时内线需跟随重算 */
.book-auth-card.ticket::before {
  border-radius: calc(var(--r-pop) - 2px);
}
.book-auth-card .ticket-body {
  flex: 1;
  min-height: 0;
  display: grid;
}
.book-auth-layer {
  grid-area: 1 / 1;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  /* owner P5 试用意见(20260722)推翻 R-018 期"不露轨"注:真实新手在注册卡
     看不到滚动条就不知道下面还有字段,卡死在注册页。回归 §19① 全站默认
     "细滚动条常驻可见"基线(8px 胶囊 thumb,仅溢出时出现)——此处不再覆写
     scrollbar-width,继承全局 thin。 */
  /* R-041(owner 20260723二次截图令,T2)根因修复："卡内滚动条以悬浮错位形态
     叠在卡右缘"——本卡诊断：实测(headless Chrome + 真实取证脚本，未加
     --hide-scrollbars 参数以看清真实渲染)确认滚动条本身的盒模型位置是贴着
     .book-auth-layer 自己的右边界画的，问题出在"自己的右边界"与"卡片可视
     右边界"之间缺一道显式预留——多数操作系统/浏览器组合下滚动条是非叠加
     式（会挤占内容宽度），但启用了系统覆层滚动条(overlay scrollbar，Win/
     mac 触控板场景常见默认)的真实浏览器里，滚动条不挤占版面宽度，而是直接
     浮绘在内容右侧边缘之上——本容器此前没有为这种情形预留任何缓冲，滚动条
     轨道因此直接贴到内容乃至卡片内边距边界，读起来就是"悬浮、错位、叠在
     卡右缘"。通用化修法（不管注册卡本身是否还需要滚动，同款容器未来只要
     内容超高就会复现，故直接把两条加固规则写在 .book-auth-layer 基类上，
     不是给注册卡打局部补丁）：①scrollbar-gutter:stable——强制浏览器为滚动条
     恒定预留版面空间，即使当前内容不溢出也保留同样宽度，杜绝"有的浏览器
     挤内容、有的浏览器盖内容"的双重形态；②padding-right 给内容额外让出
     一点呼吸区，双重保险避免文字紧贴滚动条轨道。 */
  scrollbar-gutter: stable;
  padding-right: 6px;
  display: flex;
  flex-direction: column;
  /* safe center：内容够矮时真居中（登录卡的「内容纵向居中分布」）；内容比
     正方形更高时（注册卡三字段+密码提示行）自动回退顶对齐——纯 center 在溢出
     时会两端各裁一半，实测把标题「入册——新同修注册」和底部「去登录」都裁
     没了，两处都是这张卡必须看见的内容，safe 关键字正是为这种场景而生。 */
  justify-content: safe center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--t-page) var(--ease-out), visibility 0s linear var(--t-page);
}
.book-auth-layer[data-active="true"] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity var(--t-page) var(--ease-out);
}
@media (min-width: 768px) {
  /* R-041(owner 20260723二次截图令,T2)："注册页必须显示完整的页...保持
     正方形,所以你可能需要增加宽度。这样的话可能就不需要滑动块了"——原
     420×420 装不下注册卡四字段(实测需约 503px 内容高)，此前只能靠卡内滚动
     兜底。改法＝把"真实姓名/用户名"并成一行两列(见下方 .book-field-pair)
     省一整行竖向高度，同时加宽外壳给两列字段足够呼吸空间；两值一起调，
     使注册卡内容零溢出(实测见回执)且宽高比仍接近 1:1(590×560≈1.05:1)。
     登录/注册两态仍共用同一个固定尺寸盒子(R-016②零跳变架构不变)，登录卡
     内容改走 .book-login-narrow 把可视宽度钉回原基线，见下方规则。 */
  .book-card.book-auth-card { width: 590px; height: 560px; }
  /* 真实姓名/用户名并列一行两列，字段本身样式(.book-fieldrow)不变，只加
     栅格容器；窄屏(<768px)不进本 media query，两字段维持改版前逐字段纵向
     堆叠。 */
  .book-auth-card .book-field-pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--s5);
  }
  /* 登录卡内容视觉宽度钉回改版前 320px 基线并居中——外壳盒子客观上随注册卡
     加宽(两态共用同一固定尺寸盒子)，但登录卡本身只有账号/密码两个字段，
     不需要也不适合被拉伸铺满新宽度；.book-login-narrow 是 buildLoginCardBody
     的内容根节点(见 ui-pages.js)，只影响登录卡这一份内容，不影响注册卡。 */
  .book-auth-layer[data-mode="login"] { align-items: center; }
  .book-login-narrow { width: 100%; max-width: 320px; }
}

.book-card {
  width: 100%;
  max-width: 320px;
  text-align: left;
}
.book-card-title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-sub);
  color: var(--ink);
  margin-bottom: var(--s3); /* 原 s4，正方形定高后收紧一档（R-016③排版收紧） */
}
/* R-042(CARD-G3W22调研方案B"题签锚点版"，showConfirmOverlay 专用)：标题前置
   朱点，参数原样抄 .masthead-brand-dot(§15，见上方)，仅补一份 inline 排版
   下需要的间距/垂直微调(源规则用在 flex 行内靠 gap 控距，此处是 <p> 内文字
   前缀，flex 场景没有的 margin-right/position 由本规则自行补)。 */
.confirm-dot {
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--seal);
  margin-right: 6px;
  position: relative;
  top: -1px;
}
/* 标题下细线，参数抄 .tag-rule-line(§4，见上方) 的核心两行(height/background)；
   flex:1/align-self 是给三段式题签行(线两侧还有文字)用的，本处是独占一整行
   的 block div，不需要。 */
.dirb-rule {
  height: var(--lw-line);
  background: var(--line);
  margin: 0 0 var(--s3);
}
.book-fieldrow {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  padding: var(--s2) 0;
}
/* R-018 重做:行间虚线删除——底线式输入本身即是线,叠虚线=线噪 */
.book-fieldrow-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
/* R-018 输入位重做:大白框(票面底+四边框)整体废除,改「账簿手写位」底线式——
   透明底+一道乌丝底线,聚焦底线转浓墨加重,与全站票据字段表同语汇 */
.field-text {
  width: 100%;
  height: 40px;
  padding: 2px 2px 6px;
  border: none;
  border-bottom: var(--lw-line) solid var(--line);
  border-radius: 0;
  background: transparent;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--ink);
  letter-spacing: .02em;
}
.field-text:focus-visible {
  outline: none; /* 20260805 owner 三令:任何选中框都不要 */
}
.field-text[data-invalid="true"] {
  border-bottom-color: var(--red-text);
  box-shadow: 0 1px 0 0 var(--red-text);
}
/* 密码「显示」纯文字切换，禁图标 */
.field-toggle {
  align-self: flex-end;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--indigo);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.field-hint {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-3);
  margin-top: 2px;
}
.field-error {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--red-text);
}
.book-card-foot {
  margin-top: var(--s1); /* R-018 收紧,给注册卡脚让出完整可见空间 */
  padding-top: var(--s1);
  border-top: var(--lw-line) dashed var(--line);
  text-align: right;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}
/* R-041(owner 20260723二次截图令,T4)：登录卡「进入」按钮下方一道虚线（owner
   截图3红框点名，"这两个虚线有点多余，删"）——只加在登录卡脚注一处
   （ui-pages.js buildLoginCardBody 的 foot），去掉分隔线，间距保留不变；
   注册/强改密两张卡脚注未点名，沿用 .book-card-foot 基类原样不动。 */
.book-card-foot--noline { border-top: none; }
.book-link { color: var(--indigo); text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px; }
.book-submit { width: 100%; margin-top: var(--s3); } /* 原 s4 */
/* 登录/注册卡自身的分段虚线（.ticket-divider 用在起/止两组、确认键前等多处
   全站场景，不便改全局值）：正方形卡内收紧一档，s4→s3。 */
.book-card .ticket-divider { margin: var(--s2) 0; }


/* ============================================================================
   17. 我的页「度牒 · 题名录 · 年谱」三件套（V4 整页重排，SPEC §7 R-013③，
   替代 V3「功候」墙横条+进度条体系 gongho-* 整体下架；V4.2 §7 R-014⑦ 增量：
   度牒 编号/入册日/称号 三字段下架换新字段表，年谱收尾行改「今 · 入册第 X 日」）

   ① 度牒身份票 DOM 契约（唯一加宽票据卡，V4.2 新字段表全真数据）：
   <div class="ticket dudie">
     <div class="ticket-body">
       <p class="dudie-name">沈知远</p>
       <div class="dudie-fields">
         <div class="fieldrow"><span class="fieldrow-label">累计总时长</span><span class="fieldrow-value num">166 时 48 分</span></div>
         <div class="fieldrow"><span class="fieldrow-label">共录</span><span class="fieldrow-value num">312 笔</span></div>
         <div class="fieldrow"><span class="fieldrow-label">日均练功</span><span class="fieldrow-value num">1 时 12 分</span></div>
         <div class="fieldrow"><span class="fieldrow-label">最常练功时辰</span><span class="fieldrow-value">卯时</span></div>
         <div class="fieldrow"><span class="fieldrow-label">单笔最长</span><span class="fieldrow-value num">2 时 30 分</span></div>
       </div>
     </div>
   </div>

   ② 功候题名录 DOM 契约（字级放榜，两栏桌面并排/移动堆叠）：
   <div class="tag-rule"><span class="tag-rule-label">功候 —— 修习里程</span>...</div>
   <section class="timinglu">
     <div class="timinglu-col">
       <p class="fieldrow-label">累计功时</p>
       <div class="timinglu-row" data-reached="true">
         <span class="timinglu-name" data-tier="0">百时</span>
         <span class="timinglu-sub num">2026-05-01</span>
       </div>
       <div class="timinglu-row" data-reached="false">
         <span class="timinglu-name timinglu-name--hollow" data-tier="1">千时</span>
         <span class="timinglu-sub num">166 时 / 1000 时</span>
       </div>
     </div>
     <div class="timinglu-col">…连续功日，同构…</div>
   </section>

   ③ 年谱 DOM 契约（左乌丝竖线时间轴；V4.2 §7 R-014⑦：收尾行改「今 · 入册第
   X 日」——累计时长/最长连续/共录笔数/最常起于四项汇总数字已上移度牒身份票，
   此处不再重复）：
   <div class="tag-rule"><span class="tag-rule-label">历史纪录 —— 年谱</span>...</div>
   <ol class="nianpu-timeline">
     <li class="nianpu-row"><span class="nianpu-date num">2026-05-26</span><span class="nianpu-event">入册</span></li>
     <li class="nianpu-row nianpu-row--summary"><span class="nianpu-summary">今 · 入册第 57 日</span></li>
   </ol>

   ④ 设置降级 DOM 契约（去票据框纯文字行）：
   <div class="me-settings">
     <a class="me-settings-link" href="#/admin">管理后台</a>
     <button class="me-settings-link">退出登录</button>
   </div>
   ========================================================================== */

/* ---- ①度牒身份票 ---- */
.dudie-name {
  font-size: 19px; /* SPEC 范围 18-20px */
  font-weight: 600;
  color: var(--ink);
}
.dudie-fields {
  margin-top: var(--s3);
}

/* ---- ②功候题名录：字级放榜，已达成=实心深朱+下缀达成日期，未达成=同字号
   空心轮廓字+下缀「当前/目标」——字级两态本身即进度表达，删除墨位进度条体系 ---- */
.timinglu {
  display: flex;
  flex-direction: column;
  gap: var(--s5);
}
.timinglu-row {
  padding: var(--s3) 0;
}
.timinglu-row + .timinglu-row {
  border-top: var(--lw-hair) dashed var(--line);
}
.timinglu-name {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
  color: var(--red-text);
}
/* 未达成=空心轮廓字：Blink/WebKit 走 -webkit-text-stroke 描边+透明填色，
   非 Blink 兜底=淡墨实色（不支持该属性时 color 保持不透明的 --ink-2）。
   二轮盲审 P2 复调:深色粗描边在齐伋体繁笔画上视觉≈实心灰——改「细+浅」
   (1px --ink-3)才有真「刻而未填」的镂空感;识别度靠字号与下缀进度小字兜底。 */
.timinglu-name--hollow {
  color: var(--ink-2);
  -webkit-text-stroke: 1px var(--ink-3);
}
@supports (-webkit-text-stroke: 1px black) {
  .timinglu-name--hollow { color: transparent; }
}
.timinglu-sub {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-caption);
  color: var(--ink-3);
}
/* 字级递增梯：累计功时(5 档)/连续功日(4 档，共用同一把梯的前四级) 按
   data-tier 0-4 递增，移动端每级比桌面矮一档（SPEC「约 20→26→32→38→44px
   移动降档」） */
.timinglu-name[data-tier="0"] { font-size: 16px; }
.timinglu-name[data-tier="1"] { font-size: 20px; }
.timinglu-name[data-tier="2"] { font-size: 26px; }
.timinglu-name[data-tier="3"] { font-size: 32px; }
.timinglu-name[data-tier="4"] { font-size: 38px; }
@media (min-width: 768px) {
  .timinglu { flex-direction: row; gap: var(--s6); }
  .timinglu-col { flex: 1; min-width: 0; }
  .timinglu-name[data-tier="0"] { font-size: 20px; }
  .timinglu-name[data-tier="1"] { font-size: 26px; }
  .timinglu-name[data-tier="2"] { font-size: 32px; }
  .timinglu-name[data-tier="3"] { font-size: 38px; }
  .timinglu-name[data-tier="4"] { font-size: 44px; }
}

/* ---- ③年谱：左侧乌丝竖线时间轴，逐行 MonoNum 日期 + 文楷事件 ---- */
.nianpu-timeline {
  position: relative;
  margin: 0;
  padding-left: var(--s5);
  border-left: var(--lw-hair) solid var(--line);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}
.nianpu-row {
  position: relative;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s3);
}
.nianpu-row::before {
  content: "";
  position: absolute;
  left: calc(var(--s5) * -1 - 1px);
  top: .5em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ink-3);
}
.nianpu-date {
  flex-shrink: 0;
  color: var(--ink-2);
  font-size: var(--fs-fieldvalue);
}
.nianpu-event {
  color: var(--ink);
  font-family: var(--font-body);
}
.nianpu-row--summary {
  margin-top: var(--s2);
  padding-top: var(--s3);
  border-top: var(--lw-hair) dashed var(--line);
}
.nianpu-row--summary::before { display: none; }
.nianpu-summary {
  color: var(--ink-2);
  font-size: var(--fs-body-sm);
}

/* ---- ④设置降级：去票据框纯文字行，分量主动调低 ---- */
.me-settings {
  margin-top: var(--s6);
  padding-top: var(--s3);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s3);
  border-top: var(--lw-hair) dashed var(--line);
}
.me-settings-link {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
  transition: color var(--t-fast) var(--ease-out);
}
.me-settings-link:hover { color: var(--ink-2); }


/* ============================================================================
   18. 牌记 colophon（SPEC V3 §13 第 6 条：管理页/我的页底部一行刊记体例小字，
   仅元信息区，数据页禁用）
   ========================================================================== */
.colophon {
  margin-top: var(--s6);
  padding-top: var(--s3);
  border-top: var(--lw-hair) dashed var(--line);
  text-align: center;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-wide);
  color: var(--ink-3);
}


/* ============================================================================
   19. CC 式滚动条 + .cc-scroll 静止隐/交互显（R-019③，W13a 新增）
   配方来源：VS Code 官方设置页(10px 细滚动条) + Notion(10px)双印证，本站按
   8px 收紧一档（票据本位版式更密，8px 与 --lw-thick/--r-ctl 等小尺度更协调）。

   两层策略：
   ① 全站默认（未挂 .cc-scroll 的普通溢出容器，含 body/window 主滚动）：
      细滚动条常驻可见（8px，胶囊 thumb，track 透明），不做「静止隐藏」——
      这是「有滚动条但克制」的默认基线，不等于②。
   ② .cc-scroll 契约类（W13b/W13c 挂到需要"静止极净"的特定容器，如记一笔
      面板当日笔录列表/打卡历详情浮层等 Claude Code 设置页式局部滚动区）：
      静止态完全透明不可见，仅 hover 才显影滑块；同时叠顶部渐隐遮罩
      （内容滑入时淡出，呼应「下滑后上部虚化」，R-019④）。
      注：纯 CSS 无法感知"正在滚动中"这一状态（无对应伪类），显影只按
      hover 触发，滚动瞬间但未 hover 的边缘情形（如触屏滑动/触控板）不在
      本轮覆盖范围内，留作集成窗如需要再补 JS scroll 监听切 class。
   ========================================================================== */

/* ---- ① 全站默认：细滚动条常驻可见 ---- */
*::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background-color: rgba(var(--line-rgb), .55);
  border-radius: 4px;
  border: 2px solid transparent; /* 配 background-clip 造 4px 视觉细条，实际热区仍 8px */
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
  background-color: rgba(var(--line-rgb), .8);
}
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--line-rgb), .55) transparent;
}

/* ---- ② .cc-scroll：静止极净，仅 hover 显影滑块 ---- */
.cc-scroll {
  scrollbar-color: transparent transparent; /* Firefox 侧静止态完全透明 */
  /* R-020①：本 .cc-scroll 语汇的上下渐隐 mask 遮罩已删——owner 裁「没必要模糊」，
     列表首末条曾被淡出裁切（此教训见下方 R-032②注：成就清单另起的滚动感知
     渐变遮罩系新增实现，非本条复活，不共用同一套常驻假设）。 */
}
.cc-scroll::-webkit-scrollbar-thumb {
  background-color: transparent; /* webkit 侧静止态默认透明 */
}
.cc-scroll:hover {
  scrollbar-color: rgba(var(--line-rgb), .55) transparent;
}
.cc-scroll:hover::-webkit-scrollbar-thumb {
  background-color: rgba(var(--line-rgb), .55);
}
.cc-scroll:hover::-webkit-scrollbar-thumb:hover {
  background-color: rgba(var(--line-rgb), .8);
}

/* ============================================================================
   20. 成就清单复选行（CARD-F5，R-026）：站内首次出现「多行可勾选列表」需求，
   既有 .fieldrow/.ticket-row 均是单行 label+value，无法复用；极小增量=零自制
   方块，原生 checkbox 只接 accent-color 令牌；条目文字走默认正文墨色（不用
   .field-hint 的弱文本档——20 条是要读的正文，非提示语）。声明行「以上属实」
   复用同一行骨架，页面层自行把文字 span 改挂既有 .field-hint class 降视觉
   一档，不新增 class。清单容器叠 .cc-scroll（静止极净滚动条语汇）+ 本节
   .achv-list 给出的定高，超出部分内滚，与记一笔面板「当日记录」同语汇。
   ========================================================================== */
/* R-032②(20260723,owner 截图三张明令)：list 滚动感知的顶/底渐变遮罩重开——
   吸取 R-020①「常驻遮罩把首末条永久裁切遮挡」的教训，本轮遮罩绝非常驻：
   .achv-fade-top 仅当 scrollTop>0（已下滑）才显示，回到顶隐藏；.achv-fade-bottom
   仅当"未滚到底"才显示，滚到底隐藏——两侧独立由 JS scroll 监听切 .achv-fade--visible
   class（见 web/src/ui-pages.js buildAchvListMount），CSS 只管渐变外观与
   opacity 过渡，不接手"何时显示"的判断。.achv-list-wrap 是新增的定位宿主
   （.achv-list 本身仍是滚动容器，宿主只负责让两片遮罩 position:absolute 贴在
   滚动容器的可视顶/底边缘，随内容一起裁在同一视口内，不随内容滚走）。
   渐变色用 --paper-2（浮层卡底色，票面色，R7 令牌表），不用白色——遮罩边缘
   与卡片底色融为一体，不留可见接缝。pointer-events:none 保证遮罩纯视觉，
   不挡底下清单行的点击/勾选。 */
.achv-list-wrap {
  position: relative;
}
.achv-fade {
  position: absolute;
  left: 0;
  right: 0;
  height: 28px;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-page) var(--ease-out);
}
.achv-fade-top {
  top: 0;
  background: linear-gradient(to bottom, rgba(var(--paper-2-rgb), 1), rgba(var(--paper-2-rgb), 0));
}
.achv-fade-bottom {
  bottom: 0;
  background: linear-gradient(to top, rgba(var(--paper-2-rgb), 1), rgba(var(--paper-2-rgb), 0));
}
.achv-fade--visible {
  opacity: 1;
}
.achv-list {
  max-height: 46vh;
  overflow-y: auto;
  margin-top: var(--s3);
}
.achv-row {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s2) 0;
}
.achv-row + .achv-row { border-top: var(--lw-hair) dashed var(--line); }
.achv-row input[type="checkbox"] {
  accent-color: var(--ink);
  width: 16px;
  height: 16px;
  flex: none;
  margin-top: 3px;
}
.achv-row-text {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink);
  line-height: var(--lh-tight);
}
.achv-education {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}
.achv-education legend {
  padding: 0;
  margin-bottom: var(--s2);
}
.achv-education-options {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s2) var(--s3);
}
.achv-education-option {
  display: flex;
  align-items: center;
  gap: var(--s2);
  min-height: 32px;
  cursor: pointer;
}
.achv-education-option input[type="radio"] {
  accent-color: var(--ink);
  width: 16px;
  height: 16px;
  flex: none;
  margin: 0;
}
.achv-education-summary {
  margin: var(--s2) 0 var(--s3);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink);
}
/* R-039(owner 20260723,管理页明细浮层改纯列表)：未达成条目弱化，与已达成
   （默认 --ink 正墨）/近 7 天达成（.achv-recent 朱红）拉开三档，让"直接列
   出来"的纯文字清单仍能一眼看出勾选状态，不依赖 checkbox 图形。 */
.achv-row-text--muted {
  color: var(--ink-3);
}
.achv-row-text.achv-row-text--achieved {
  color: #000000;
  font-weight: 600;
}
/* 管理页明细浮层练功类/生活类分段线（owner 原话"画一个横线"，不带文字标签）。
   grid-column:1/-1 只在 .achv-card 桌面双列网格（下方 §「成就清单浮层双列」）
   内生效——迫使分隔线独占一整行，同时把练功类最后一条(id 11，单数)自然挤到
   独占一行，视觉上恰好与生活类分组隔开；窄屏 .achv-list 是普通块级容器，该
   属性无宿主可依附，天然是普通一整行，不需要另写规则。线宽用 --lw-line
   （题签分隔线同一量级，比 .achv-row 之间的 --lw-hair 虚线更重，读作"分类
   边界"而非"逐条分隔"）。 */
.achv-list-divider {
  grid-column: 1 / -1;
  border-top: var(--lw-line) solid var(--line);
  margin: var(--s2) 0;
}

/* ---- 成就清单浮层双列(CARD-G3W15,R-037③,owner:"现在的清单是竖长的一列
   不好看,改成两列,也就是横向要加宽")：showAchievementsOverlay(本人可编辑)
   与 showAchievementsDetailOverlay(只读明细)共用同一个 buildAchvOverlayShell
   骨架+buildAchvListMount 清单，改动只加两个新 class，不碰其余三处复用
   buildAchvOverlayShell 的场景(showInfoOverlay/showConfirmOverlay 用各自的
   .book-auth-mask 骨架，不受影响；已确认站内仅这两个成就浮层调用
   buildAchvOverlayShell)。

   .achv-card：加在 shell 的 .book-card 上(第二个 class，不改 .book-card 本身
   的 320px 基线，避免连带影响同样裸用 .book-card 的 showInfoOverlay/
   showConfirmOverlay 两处一直很短、从未需要加宽的浮层)。桌面档(768px 断点，
   沿用本项目既有断点惯例)加宽到 640px——依据：实测 21 条现行文案(产品文档/
   成就清单/成就清单-现行21条v2-R028-20260723.txt)最长一条"熟练极光法，可7脉
   轮同时共振"13 字，其余多在 5-10 字；13 字在 --fs-body-sm(13px)下约 175px，
   加 checkbox+gap 约 28px，单列内容约 203px；640px 减卡内边距(--s5×2=48px)
   减列间距(--s6=32px)再对半，单列净宽约 280px，对最长文案留出约 77px 余量，
   不会贴边换行。窄屏(<768px)维持 .book-card 原有 320px 基线+单列，不新增
   断点表述。
   .achv-actions：仅 showAchievementsOverlay(有"确认"+"稍后再填"两个按钮)用到
   ——卡片加宽后两个按钮仍各自 100% 宽堆叠会显得与新宽度不协调(工单原话
   "不能列表变宽了但底部按钮还是窄modal的尺寸")，桌面档改并排；
   showAchievementsDetailOverlay 只有一个"知道了"按钮，单按钮撑满宽度是常见
   正常形态，不视为不协调，不额外处理。 ---- */
@media (min-width: 768px) {
  .achv-card { max-width: 640px; }
  .achv-card .achv-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--s6);
  }
  /* 双列后第一视觉行是第 1、2 两个 DOM 子项(grid 默认逐行填充，先填满第一行
     再换行)，原 .achv-row + .achv-row 的虚线顶边界(见上方)会连第 2 项也画上
     (它在 DOM 序里紧跟第 1 项之后)，但视觉上第 1、2 项同处第一行、上方均无
     更早内容——只有第 1 项因 :first-child 被上面的 + 选择器天然排除，第 2 项
     漏排除，会出现"同一行左边无线右边有线"的不对称。按"首视觉行两项都不画
     顶边界"显式补上。 */
  .achv-card .achv-row:nth-child(-n+2) { border-top: none; }
  /* R-041(owner 20260723二次截图令,T6,截图4红框)：分类横线(.achv-list-divider,
     grid-column:1/-1，见上方§)正下方、右列第一条上方出现一小段孤立虚线——
     根因与上面 nth-child(-n+2) 那条是同一类不对称，只是发生在"分隔线之后"
     而非"清单开头"：分隔线强制换行，紧跟它的第一项(左列)因上一个 DOM 兄弟
     是 .achv-list-divider 而非 .achv-row，天然不被 .achv-row + .achv-row 选中，
     没有顶边线；但第二项(右列)的上一个兄弟是"分隔线之后的第一项"(一个真
     .achv-row)，会被该选择器命中，画出一条只在右列出现的孤立虚线。
     修复：显式对"紧跟分隔线之后的第二个 .achv-row"去掉顶边线，用兄弟选择器
     定位（不依赖固定第 N 个 DOM 位置——divider 出现在哪，这条规则就近旁生效，
     天然适配"过滤后清单不定长"的动态序列，也天然支持未来出现多道分隔线的
     场景，每道分隔线各自的正下方两项都会被独立命中）。窄屏(<768px)不进本
     media query：单列布局下分隔线后第一项本就因同一 DOM 兄弟关系天然无顶边
     线，不需要、也不应该额外去掉第二项的顶边线（那是同一分组内正常的逐条
     分隔，若也去掉反而会漏画）。 */
  .achv-card .achv-list-divider + .achv-row + .achv-row { border-top: none; }
  .achv-card .achv-actions {
    display: flex;
    gap: var(--s3);
    margin-top: var(--s3);
  }
  .achv-card .achv-actions .book-submit {
    width: auto;
    flex: 1;
    margin-top: 0;
  }
}
/* R-042(owner 20260724三次截图令):"成就清单做成三列，这样就能完整展示"——
   在独立的更宽断点新增三列档，不直接把上面 768px 档改成三列，理由是 768px
   视口宽度本身容不下三列还留白（算法见下方），这里复用本项目 .disciple-grid
   (§20) 已验收的同款"两档断点分层加列"策略(768px 两列/1024px 三列)，不是
   另创一套新逻辑。
   .achv-card 宽度重算(同上方 640px 那条注释的口径，最长文案13字场景不变)：
   三列每列净宽目标 ≈230px(单列最短净宽 203px 之上留约13%余量，同一量级的
   留白比例)；800px 卡宽 - 卡内边距(--s5×2=48px) - 两道列间距(--s6×2=64px)
   =688px，三等分 ≈229px，达标。1024px 断点下 800px 卡宽 + 浮层左右内边距
   (--s4×2=32px)=832px，距 1024px 视口仍留 192px 余量，不会在断点临界值触发
   横向溢出（640px 档在 768px 断点做过同款验证，见上方注释）。
   下面两条边框抑制规则是 768px 档同款规则的三列版本，写法与上方 R-041 T6
   注释同一套推理："-n+2"→"-n+3"（首视觉行三项都不画顶边界）；分隔线后需要
   抑制的项从 1 个(右列)扩到 2 个(中列+右列)，故追加一条三层兄弟选择器命中
   分隔线后第三项。两档规则同时存在不冲突——768px 档的 -n+2/单层兄弟选择器
   命中的项是本档 -n+3/多层兄弟选择器命中范围的真子集，且都是同一个值
   (border-top:none)，非覆盖关系，是并集叠加。 */
@media (min-width: 1024px) {
  .achv-card { max-width: 800px; }
  .achv-card .achv-list { grid-template-columns: 1fr 1fr 1fr; }
  .achv-card .achv-row:nth-child(-n+3) { border-top: none; }
  .achv-card .achv-list-divider + .achv-row + .achv-row + .achv-row { border-top: none; }
}


/* ============================================================================
   21. R-028 弟子列表卡片（CARD-G3W6，取代原「成员列表」.ticket-row 单行体例）：
   每位弟子一张 .ticket 卡（.disciple-card 仅补卡间纵向节奏，卡片本体外观完全
   复用既有 .ticket），内部头行（姓名+状态元信息+操作按钮组）与既有 .fieldrow
   四件套/成就行之间用既有 .ticket-divider 分隔，零新增结构类语言。
   ========================================================================== */
/* .disciple-card 卡间距规则随甲案账行化删除(20260805,卡墙退役)。 */

/* .disciple-achv-row/.disciple-achv-row .fieldrow-value（原内联成就文案清单
   字段行的换行支持）随 CARD-G3W15(R-037①)整体下架——该字段行本身已被移除，
   改图标+紧凑计数，见下方 §26；不留死 class。 */

/* 成就条目「近 7 天内首次勾选」高亮：唯一新增颜色类，值仍是全站「新达成」
   合法朱色令牌 --red-text（R-019 色彩四色封顶纪律未破例，只是多一个使用
   场景：弟子列表新达成条目，与「今日之数/榜首」同一朱色语义"新/当下"）。 */
.achv-recent {
  color: var(--red-text);
}


/* ============================================================================
   22. R-028⑥ 我的/管理两页正文与标题字号 +15%（页面范围限定，页首巨字页标
   --fs-folio-d/--fs-folio-m 两个变量刻意不在覆写清单内，故不受影响；masthead/
   toc/tab-paper 属于 shell 级共享结构，不在 .page 容器内，天然不受牵连）。
   实现=CSS 变量覆写（限定在 .page.page-scale-lg 作用域内），15% 后数值向
   0.05px 舍入；两处硬编码 px（.dudie-name 与 .timinglu-name 五档字号）同比例
   覆写，其余站内组件均通过 --fs-* 变量间接受益，零回归到其它页面。
   ========================================================================== */
.page.page-scale-lg {
  --fs-body:          16.1px;  /* 14px  *1.15 */
  --fs-sub:           18.4px;  /* 16px  *1.15 */
  --fs-body-sm:       14.95px; /* 13px  *1.15 */
  --fs-caption:       13.8px;  /* 12px  *1.15 */
  --fs-tagrule-label: 14.95px; /* 13px  *1.15 */
  --fs-tagrule-meta:  13.8px;  /* 12px  *1.15 */
  --fs-fieldlabel:    12.65px; /* 11px  *1.15 */
  --fs-fieldvalue:    17.25px; /* 15px  *1.15 */
  --fs-ticketfoot:    12.65px; /* 11px  *1.15 */
  /* --fs-folio-note 覆写行已随 R-033②(CARD-G3W13)移除：.folio-note 改为四页
     统一硬编码 13.8px(见 §3 .folio-note 注释)，不再经这条变量覆写间接生效，
     留在这里会变成一条不影响任何选择器的死配置，故删除，避免误导后来者。 */
}
.page.page-scale-lg .dudie-name { font-size: 21.85px; } /* 19px * 1.15 */
.page.page-scale-lg .timinglu-name[data-tier="0"] { font-size: 18.4px; } /* 16*1.15 */
.page.page-scale-lg .timinglu-name[data-tier="1"] { font-size: 23px; }   /* 20*1.15 */
.page.page-scale-lg .timinglu-name[data-tier="2"] { font-size: 29.9px; } /* 26*1.15 */
.page.page-scale-lg .timinglu-name[data-tier="3"] { font-size: 36.8px; } /* 32*1.15 */
.page.page-scale-lg .timinglu-name[data-tier="4"] { font-size: 43.7px; } /* 38*1.15 */
@media (min-width: 768px) {
  .page.page-scale-lg .timinglu-name[data-tier="0"] { font-size: 23px; }   /* 20*1.15 */
  .page.page-scale-lg .timinglu-name[data-tier="1"] { font-size: 29.9px; } /* 26*1.15 */
  .page.page-scale-lg .timinglu-name[data-tier="2"] { font-size: 36.8px; } /* 32*1.15 */
  .page.page-scale-lg .timinglu-name[data-tier="3"] { font-size: 43.7px; } /* 38*1.15 */
  .page.page-scale-lg .timinglu-name[data-tier="4"] { font-size: 50.6px; } /* 44*1.15 */
}


/* ============================================================================
   CARD-G3W10 移动端辅助字号 11px→12px（F-P2-01/02，依据 G3W9 回执 §3；
   F-P2-03 打卡历干支单字装饰 8px 已裁候豁免，本卡不动）。
   --fs-masthead 全站仅 masthead-inner/.masthead-switch 两处消费（报头日期/
   时辰/秒钟/成员名/退出登录文案）；--fs-fieldlabel 全站仅 .fieldrow-label/
   .entry-field-label 两处消费（登录注册字段标题/记一笔起止大概练了当日记录/
   今日页数据行本周连续本周日均本月等标题）——均为 F-P2 清单里点名的目标，
   变量改值零株连其它字号。桌面 ≥768px 不落这条媒体查询，原样保持 11px，
   与工单「仅移动档」要求一致；.page.page-scale-lg 的 +15% 覆写（见上方
   §22，12.65px）class 选择器特异性更高，两档媒体查询同时命中时该覆写
   仍会照常生效，互不冲突。 */
@media (max-width: 767px) {
  :root {
    --fs-masthead: 12px;
    --fs-fieldlabel: 12px;
  }
}

/* ============================================================================
   24. 成就浮层复选行移动档触达(对抗复审 VERDICT-RWD P1-2,G3 亲执,20260723)
   行=label 整行可点(真实触达目标),但 13px 文 + 8px 纵 padding 单行高约 33px,
   低于 44px 移动触达基线。移动档纵 padding 提至 14px(单行高约 45px)。
   内部 16px 复选框本身被 C 类扫描按元素口径命中属"伪命中"(点整行即可勾选,
   无需精确点中方框),已在专项报告口径节说明,不放大方框(视觉语言不动)。
   ========================================================================== */
@media (max-width: 767px) {
  .achv-row { padding: 14px 0; }
}

/* ============================================================================
   25. 弟子列表栅格(R-035②,20260723):管理视角=电脑浏览器,横向空间要吃满。
   owner 20260801 进一步明确：五列必须保持原 880px 页面三列时的卡片宽度，
   即 (880 - 左右各32内边距 - 两个16列间距) / 3 = 261.333px；实现方式是
   只扩大管理页画布到 1434.665px，而不是在原画布内压缩五张卡。

   align-items 由 start 改 stretch(CARD-G3W15,R-037①「确保每个弟子卡片尺寸
   一致」)：此前卡内还有内联成就文案清单(逗号分隔最多21条)这一巨大高度变量，
   同行三卡自然高度可能相差几倍，此时若用默认 stretch 会让内容少的卡片底部
   出现一大截突兀空白，start(各卡按自身内容高度顶对齐)反而是当时更不难看的
   选择。本卡①把该内联清单整体移除、换成右上角小图标+紧凑计数(见下方 §26)，
   卡内剩余内容(头行+四个定长 fieldrow)天然同构，不再有巨幅高度变量来源——
   改回 stretch 让同行卡片严格拉伸对齐(不足内容的卡片仅底部留少量呼吸空白，
   而非依赖"新内容恰好高度一致"这种未经断言的巧合)，直接达成 owner 原话
   "确保每个弟子卡片尺寸是一致的"，比停留在 start 更稳妥。实测截图见回执。 */
/* .disciple-grid 五列卡墙与 .page-admin-wide 固定 1434.665px 画布随甲案退役
   删除(owner 20260805 拍板书案骨架;固定画布在 1024-1450px 视口横向溢出的
   旧病同此根治,管理页画布改用 .page--notes 1360px 自适应)。

   ============================================================================
   §25b 管理页·书案三栏(甲案,owner 20260805):左身份入口/中名册账行/右整理
   面板(.notes-side 复用)。owner 同轮细则:标题无红点/排序无姓名项/三点横排。
   ========================================================================== */
.adm-layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr) 240px;
  gap: var(--s6);
  align-items: start;
}
.adm-rail {
  border-right: var(--lw-hair) solid var(--line);
  padding-right: var(--s5);
  min-height: 480px;
  display: flex;
  flex-direction: column;
  /* owner 20260806(录屏令):管理页下滑时左栏固定——与右整理面板同款 sticky */
  position: sticky;
  top: var(--s4);
}
.adm-title {
  font-family: var(--font-display);
  font-size: 44px;
  line-height: 1.15;
  font-weight: 400;
  letter-spacing: 2px;
  margin: 0;
}
.adm-count {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  margin: 6px 0 20px;
}
/* 弟子总数居左栏链列之下(owner 20260806 三调:贴底太深,提到导出数据包下方
   约一节的位置) */
.adm-count--rail { margin: 44px 0 0; }
/* .adm-notes-btn 独立主按钮已删(owner 20260805 二轮:弟子心得与其余入口统一) */
.adm-links { border-top: var(--lw-line) dashed var(--line); margin-top: var(--s3); }
.adm-link {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
  text-decoration: none;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  padding: 10px 2px;
}
.adm-link + .adm-link { border-top: var(--lw-line) dashed rgba(201, 191, 168, .5); }
.adm-link:hover { color: var(--ink); }
/* ---- 名册·案三「榜式」(owner 20260806 定案,取代二轮的灰底表头+圆角盒
   grid 账行——那版四怪:灰底带违「纸即界面」/圆角盒=网页表格控件/同列混用
   两种时长格式/22 个带框小方钮):无盒无底直接落纸;无表头(「姓名」小标题
   owner 判多余,四项数字每格自带小字标);姓名(21px,20260805「+20%」裁决沿用)
   →点线引路→四项定宽数字右对齐挂行尾(整组左移留 ⋯ 呼吸位,owner 红框令);
   ⋯无框悬停现(owner:「非常棒」)。姓名字体口径(文楷,分片兜底后回归)不变。 */
.adm-ledger { }
/* 行内弹性收缩次序(owner 20260806 录屏:窄窗下 ⋯ 仍被挤——原全固定宽总和
   可超中栏宽,溢出顶飞操作列):点线引路先缩(flex:1 1 0)→数字格允许微缩
   (0 1 112,内容实宽约 70px,缩不伤数字)→姓名与 ⋯ 永不缩;操作列加宽 76px,
   四维度数字组整体再左移一步。 */
.adm-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 13px 8px 12px 14px;
  border-bottom: var(--lw-hair) solid rgba(201, 191, 168, .5);
}
.adm-row:first-child { border-top: var(--lw-hair) solid rgba(201, 191, 168, .5); }
.adm-row:hover { background: rgba(250, 246, 236, .9); }
.adm-name-wrap { flex: 0 0 140px; }
.adm-name {
  font-family: var(--font-body);
  font-size: 21px;
  font-weight: 600;
  color: var(--ink);
}
.adm-meta {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--red-text);
  margin-left: 8px;
}
/* 点线引路已删(owner 20260806 明令),中段纯留白弹性件 */
.adm-gap { flex: 1 1 0; }
.adm-stat { flex: 0 1 112px; min-width: 74px; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.adm-stat-k { font-family: var(--font-body); font-size: 11.5px; color: var(--ink-3); letter-spacing: 1px; }
.adm-stat-na { font-family: var(--font-body); font-size: 12.5px; color: var(--ink-3); }
.dur { font-family: var(--font-num); font-size: 13.5px; color: var(--ink-2); display: inline-flex; align-items: baseline; }
.dur-n { display: inline-block; min-width: 2ch; text-align: right; }
.dur-u { font-family: var(--font-body); font-size: .88em; color: var(--ink-3); padding: 0 2px 0 4px; }
/* ⋯ 呼吸位:操作列固定 76px 永不收缩(owner 两轮「往左/仍被挤」令),数字组
   整体因此离右缘一大步 */
.adm-op { flex: 0 0 76px; align-self: center; text-align: right; position: relative; }
/* ⋯ 无框+悬停现;菜单开着时保持可见 */
.adm-row .disciple-actions-toggle { opacity: 0; border-color: transparent; background: none; }
.adm-row:hover .disciple-actions-toggle,
.adm-row .disciple-actions-toggle:focus-visible,
.adm-row .disciple-actions-toggle[aria-expanded="true"] { opacity: 1; }
.adm-row .disciple-actions-toggle:hover { color: var(--ink); background: #efe8d6; }
.adm-empty { padding: 26px 4px 6px; }
/* 响应式:≤1120 三栏塌为纵排(左栏横条+整理面板横排),≤760 砍本月/日均两列
   (与心得页三栏同思路的两档降级)。.adm-side 复合选择器特异性压过通用
   .notes-side{display:none} 断点规则,整理面板在窄窗仍可用。 */
@media (max-width: 1120px) {
  .adm-layout { display: block; }
  .adm-rail {
    border-right: 0;
    min-height: 0;
    padding-right: 0;
    display: flex;
    align-items: center;
    gap: var(--s4);
    flex-wrap: wrap;
  }
  .adm-title { font-size: 32px; }
  .adm-count { margin: 0; }
  .adm-links { border-top: 0; margin-top: 0; display: flex; gap: var(--s3); margin-left: auto; }
  .adm-link { width: auto; padding: 6px 2px; }
  .adm-link + .adm-link { border-top: 0; }
  .adm-side.notes-side {
    display: flex;
    gap: var(--s6);
    margin: var(--s3) 0 var(--s4);
    position: static;
    border-left: 0;
    padding: 0;
  }
  .adm-side .notes-side-sec { margin-bottom: 0; flex: 0 1 260px; }
}
@media (max-width: 760px) {
  /* 案三窄屏降级:砍本月/日均两格与点线引路,姓名列收窄 */
  .adm-name-wrap { flex-basis: 108px; }
  .adm-stat { flex-basis: 104px; }
  .adm-stat.s-m, .adm-stat.s-d { display: none; }
  .adm-side.notes-side { display: block; }
  .adm-side .notes-side-sec { margin-bottom: var(--s4); }
}

/* ---- 排行榜滚动固定(owner 20260806):顶部导航 .toc 与放榜 sorting 组件
   (日周月年签+子榜签)下翻时钉住。.toc 移动端 display:none(底部固定签栏
   .tab-paper 早已常驻),两条 sticky 实际只作用于桌面;top 值=toc 实测高
   (12px 内边距×2+行高约 25px+底线),背景铺纸色防下层内容透缝。 */
/* 排行榜固定导航改「液态玻璃药丸」(owner 20260806,参考 aethercss Mercury Drop
   实测配方:blur+半透底+28px 大圆角+内圈白高光 inset 0 0 20px -5px+柔和外晕),
   在宣纸色系上落地为暖纸半透。sorting 固定已撤(同轮裁决),仅导航钉住。
   无 backdrop-filter 的浏览器回退实底纸色。 */
/* 报头玻璃化(owner 20260806「顶部也要玻璃化」):钉顶全宽玻璃条,同 Mercury
   Drop 配方;导航药丸 top 随之下移到报头之下。无 backdrop-filter 回退近实底。 */
/* owner 20260806 终口径:页头=玻璃材质但不固定、零线零影;口号删除后报头只剩
   品牌|meta 两段,布局从三列网格改 flex 两端(网格三列在中列缺席时会把 meta
   吸到中间)。 */
.masthead {
  border-bottom: 0;
  box-shadow: none;
  background: rgba(250, 246, 236, .5);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .masthead {
    background: rgba(250, 246, 236, .35);
    -webkit-backdrop-filter: blur(10px) saturate(1.25);
    backdrop-filter: blur(10px) saturate(1.25);
  }
}
.masthead .masthead-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.toc--sticky {
  position: sticky;
  top: 10px;
  z-index: 30;
  width: max-content;
  margin: 6px auto 2px;
  padding: 10px 26px;
  border-radius: 28px;
  border: 1px solid rgba(255, 255, 255, .55);
  border-bottom-color: rgba(201, 191, 168, .45);
  background: rgba(250, 246, 236, .92);
  box-shadow: inset 0 0 20px -5px rgba(255, 255, 255, .7), 0 6px 18px rgba(26, 26, 26, .08);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .toc--sticky {
    background: rgba(250, 246, 236, .55);
    -webkit-backdrop-filter: blur(14px) saturate(1.35);
    backdrop-filter: blur(14px) saturate(1.35);
  }
}

/* ============================================================================
   26. 弟子卡图标化操作(CARD-G3W15,R-037②，owner:"单独做一个成就的图标放到
   右上角,另外要把'重置密码 停用 设为/取消管理员'也做成一个图标入口放到右
   上角(点击图标后下拉选项)")。

   独立盲测面板 20260723 通报的真实 P0（记档供后来者理解本节为何这样设计，
   非本卡引入的缺陷——是本卡要连根清除的既有缺陷）：改版前"重置密码/成就/
   停用/设为管理员"四个 .day-ticket-action 文字链接横排，在 1024-1920px 桌面
   宽度下会 flex-wrap 换行；叠加 F-P1-06 给 .day-ticket-action 做触达热区扩容
   用的负 margin 技巧（首/尾项分别 margin-left:-27px/margin-right:-27px 撑出
   比可见文字大得多的不可见可点区域），换行后相邻行之间这些不可见区域会几何
   重叠，真机坐实"点'重置密码'实际命中'确认设为管理员'"。本节两个新控件的
   根治办法：①下拉菜单项(.disciple-actions-menu-item)改用真实 padding 撑满
   44px 触达高度，不再用负 margin 扩容技巧；②菜单项纵向堆叠单列布局，同一
   时刻只有一条可点目标位于任一 Y 坐标，结构上不可能出现同行多目标几何重叠
   ——不是给旧技巧打补丁，是整类问题随交互形态改变一并消失。真实坐标点击
   验证结果见回执"P0 命中验证"专节。
   ========================================================================== */
/* ---- 弟子卡头行两栏骨架(R-039,owner 20260723,截图三张点名卡片结构不一致)：
   header 本身不换行——identityWrap(姓名+meta)与 iconsWrap(R-041起只剩操作菜单
   一项，成就徽标已下架见下方 §)各自独占一个 flex 子项，图标组因而永远停在
   头行第一行最右侧，不随姓名长短或 meta 有无被挤到第二行(旧版三者同层
   flex-wrap 正是结构不一致的根因，见 ui-pages.js paintAdmin 头行构造处头注)。
   identityWrap 自己 flex-wrap，姓名超长只在自己范围内折行，不牵连 iconsWrap
   位置。 ---- */
/* .disciple-card-header/.disciple-identity/.disciple-name/.disciple-card-icons
   四条卡头骨架规则随甲案账行化删除(20260805,卡墙退役;R-039/R-042 的历史
   语境见 git 历史)。姓名字体口径见上方 .adm-name 注记。 */

/* R-041(owner 20260723二次截图令,T7)：成就徽标(.disciple-achv-badge/
   .disciple-achv-badge-text，"成就 N/21"紧凑计数按钮及其"未填写"文案态)
   整块下架——owner 原话"取消数字化显示成就(不要出现成就xx/21)，只保留一个
   成就入口也就是三个点那"。唯一入口收敛到下方操作下拉菜单里的"成就"项，
   openAchvDetail 逻辑与 showAchievementsDetailOverlay 明细浮层内部展示不受
   影响。原两条规则已整体删除，不留死 class。 */

/* ---- 操作下拉：重置密码/成就/设为管理员或取消管理员(R-041起"停用/启用"
   两项已随本节一并下架，见 ui-pages.js paintAdmin 内 R-041 注释)，原四个
   横排文字链接收进一个图标按钮触发的下拉面板。.disciple-actions-anchor 是
   定位宿主(position:relative)，面板 position:absolute 挂在它下面——不是整屏
   overlay(那是 buildAchvOverlayShell 一类"独立小窗"的形态，本卡工单原话
   "下拉面板通常是绝对定位在图标下方而非整屏overlay，选合适的实现方式"，
   点外部关闭沿用同一套 e.target 判断精神但改用 document 级捕获点击+命中
   anchor 之外即关闭，实现见 ui-pages.js openMenu/onDocClick)。 ---- */
.disciple-actions-anchor {
  position: relative;
  flex-shrink: 0;
}
.disciple-actions-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  background: transparent;
  color: var(--ink-2);
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.disciple-actions-toggle:hover,
.disciple-actions-toggle[aria-expanded="true"] {
  background: var(--paper-3);
  color: var(--ink);
}
.disciple-actions-toggle-icon {
  display: inline-flex;
  width: 16px;
  height: 16px;
}
.disciple-actions-toggle-icon svg { display: block; width: 100%; height: 100%; }
/* 面板：右对齐挂在图标下方(right:0 令面板右边界=图标右边界，向左侧展开)——
   桌面三栏栅格里卡片本身较窄时，向左展开比向右展开更不容易探出卡片右边界
   撞到相邻卡片(工单②不遮挡相邻卡片要求)；min-width 148px 在本页 +15%
   字号覆写(.page-scale-lg)下也够放下最长的"设为管理员"5 字项，不换行。
   浮层级语汇=--r-pop(菜单/弹窗/抽屉，tokens.css 原生定义此用途)+
   --shadow-float(唯一允许出现阴影的浮层场景，golden rule①"默认态零阴影,
   阴影只属于浮层")，不新造投影语言。z-index:5 保证面板画在同一行/下一行
   兄弟 .disciple-card 之上(卡片自身 .ticket 是 position:relative 但
   z-index:auto，不建立独立层叠上下文，本面板需要显式 z-index 才能稳定盖住
   兄弟卡片；数值远低于全站浮层层 50+，不会与 mask/overlay 抢层)。 */
/* v1.1.1:菜单玻璃化+iOS 弹簧从按钮角落生长/收回(demo 验收件),display 硬切
   退役改常驻+opacity/scale。 */
.disciple-actions-menu {
  display: flex;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 5;
  min-width: 148px;
  flex-direction: column;
  padding: var(--s1);
  background: rgba(250, 246, 236, .95);
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: 14px;
  box-shadow: inset 0 0 20px -5px rgba(255, 255, 255, .6), 0 10px 26px rgba(26, 26, 26, .13);
  opacity: 0;
  pointer-events: none;
  transform: scale(.86);
  transform-origin: top right;
  transition: opacity var(--t-pop-close) var(--ease-spring), transform var(--t-pop-close) var(--ease-spring);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .disciple-actions-menu {
    background: rgba(250, 246, 236, .72);
    -webkit-backdrop-filter: blur(14px) saturate(1.35);
    backdrop-filter: blur(14px) saturate(1.35);
  }
}
.disciple-actions-menu[data-open="true"] {
  opacity: 1;
  pointer-events: auto;
  transform: scale(1);
  transition-duration: var(--t-pop-open);
}
/* 视口底自适应(owner 20260806 录屏):下方放不下时翻到按钮上方;生长原点随翻 */
.disciple-actions-menu[data-flip="up"] { top: auto; bottom: calc(100% + 6px); transform-origin: bottom right; }

/* 回到顶部(owner 20260806):下滚过约 2/3 现身;柔和不抢眼(85% 不透明,
   hover 提满);opacity-only 140ms;移动端抬高让开底部签栏。 */
.backtop {
  position: fixed;
  right: 26px;
  bottom: 26px;
  z-index: 45;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: var(--lw-line) solid var(--line);
  background: var(--paper-2);
  color: var(--ink-3);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms var(--ease-out);
}
.backtop svg { width: 15px; height: 15px; }
.backtop[data-show="1"] { opacity: .85; pointer-events: auto; }
.backtop[data-show="1"]:hover { opacity: 1; color: var(--ink); border-color: var(--ink-3); }
@media (max-width: 767px) { .backtop { bottom: 88px; right: 16px; } }

/* ============================================================================
   §29 v1.1.1 玻璃+iOS 开合全站落地(demo-玻璃化对比-全站-20260806 验收件)。
   范围=悬浮物一族:浮窗卡/记一笔面板/两处下拉(上方已改)/底部签栏/回顶钮。
   正文区一律不动(调研稀疏原则);页面切换保持 --t-page 快切。
   ========================================================================== */
/* 浮窗卡:玻璃底(浓度 .8 保楷体可读)+弹簧生长收回 */
.book-auth-overlay .book-card {
  background: rgba(250, 246, 236, .92);
  border-color: rgba(255, 255, 255, .6);
  box-shadow: inset 0 0 24px -6px rgba(255, 255, 255, .6), 0 18px 44px rgba(26, 26, 26, .16);
  transform: scale(.94);
  transition: transform var(--t-pop-close) var(--ease-spring);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .book-auth-overlay .book-card {
    background: rgba(250, 246, 236, .8);
    -webkit-backdrop-filter: blur(18px) saturate(1.3);
    backdrop-filter: blur(18px) saturate(1.3);
  }
}
.book-auth-overlay[data-state="open"] .book-card {
  transform: scale(1);
  transition-duration: var(--t-pop-open);
}
/* 记一笔面板同族换弹簧(原 240ms ease-out) */
.entry-ticket {
  transition: transform var(--t-pop-close) var(--ease-spring), opacity var(--t-pop-close) var(--ease-spring);
}
.entry-ticket[data-state="open"] { transition-duration: var(--t-pop-open); }
/* 底部签栏(手机):悬浮玻璃胶囊 */
.tab-paper {
  left: 10px;
  right: 10px;
  bottom: max(10px, env(safe-area-inset-bottom));
  border-radius: 24px;
  border: 1px solid rgba(255, 255, 255, .55);
  border-top: 1px solid rgba(255, 255, 255, .55);
  background: rgba(250, 246, 236, .94);
  box-shadow: inset 0 0 18px -5px rgba(255, 255, 255, .65), 0 8px 20px rgba(26, 26, 26, .12);
  padding: 8px 0 10px;
}
/* 回顶钮玻璃化 */
.backtop {
  background: rgba(250, 246, 236, .94);
  border: 1px solid rgba(255, 255, 255, .55);
  box-shadow: inset 0 0 12px -4px rgba(255, 255, 255, .7), 0 4px 12px rgba(26, 26, 26, .12);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .tab-paper {
    background: rgba(250, 246, 236, .6);
    -webkit-backdrop-filter: blur(14px) saturate(1.35);
    backdrop-filter: blur(14px) saturate(1.35);
  }
  .backtop {
    background: rgba(250, 246, 236, .55);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
  }
}
/* 减少动态效果:只留透明度,去缩放位移 */
@media (prefers-reduced-motion: reduce) {
  .book-auth-overlay .book-card,
  .disciple-actions-menu,
  .notes-minical {
    transition-property: opacity;
    transform: none !important;
  }
  /* `left:50%` needs this static translate to remain centered.  Some Android
     browsers honour reduced motion; clearing every transform moves this fixed
     sheet's left edge to the viewport midpoint.  Keep the final geometry, but
     remove the scale/vertical entrance movement. */
  .entry-ticket {
    transition-property: opacity;
    transform: translate(-50%, -50%) !important;
  }
}
/* 触达热区=真实 padding(min-height 44px)撑出，非负 margin 扩容技巧——见本节
   头注"P0"说明，这是本节存在的核心理由。纵向堆叠单列，同一 Y 坐标同一时刻
   只有一个可点目标。 */
.disciple-actions-menu-item {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 44px;
  padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  text-align: left;
  white-space: nowrap;
  transition: background var(--t-fast) var(--ease-out);
}
.disciple-actions-menu-item:hover { background: var(--paper-3); }

/* ============================================================================
   27. 「修改个人信息」/「修改密码」两小窗(CARD-G3W15，R-037③初版+R-038
   拆分)：复用 buildAchvOverlayShell 同一套独立小窗骨架(背景虚化+
   .book-auth-overlay+.book-card+点外部关闭)，不新起视觉语言，函数名沿用
   未改(见 ui-pages.js showEditProfileOverlay/showChangePasswordOverlay 两
   函数头注)。R-038 前是"一窗两区"(资料+密码共一个浮层)，R-038 后拆成两个
   各自独立的小窗，每个都更短(各自只有两字段+一按钮)，但仍共用这一个专属
   class——.book-card 基线无固定高度(不像 .book-auth-card 登录/注册那样
   定高+内层滚动)，拆分后单个小窗内容已经很短、正常视口下这条兜底基本不会
   触发，但矮视口(如横屏手机)仍有理论溢出风险，保留同一兜底比拆两个更细的
   class 简单，不为已经不太可能触发的场景过度拆分令牌。
   ========================================================================== */
.book-card.profile-edit-card {
  max-height: calc(100vh - var(--s4) * 2);
  overflow-y: auto;
}


/* ============================================================================
   28. 每日练功记事 + 三入口 + 里程碑悬浮页(feat/daily-practice-notes,20260805)
   owner 20260804 逐条:三入口纯文字用主标题字体不带数字;记事独立页每页 10 则
   +search bar+重点笔记;管理员只读全员且重点优先;编辑器/月历居中小窗(不从
   底部弹);成员筛选下拉自建(原生 select 弹层系统蓝白与宣纸打架)。
   ========================================================================== */

/* ---- 三入口:并排三块票据小卡,名字走 --font-display(巨字页标同源字体) ---- */
.me-entries {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--s3);
  margin-top: var(--s4);
}
.me-entry {
  position: relative;
  background: var(--paper-2);
  border: var(--lw-thick) solid var(--line);
  border-radius: var(--r-card);
  padding: var(--s5) var(--s2);
  cursor: pointer;
  font: inherit;
  color: var(--ink);
  transition: background var(--t-fast) var(--ease-out);
}
.me-entry::before {
  content: "";
  position: absolute;
  inset: 4px;
  border: var(--lw-hair) solid var(--line);
  border-radius: calc(var(--r-card) - 2px);
  pointer-events: none;
}
.me-entry:hover { background: var(--paper-3); }
/* (me-entries--two / me-entry--admin-notes 已随管理员我的页取消而删,不留死样式) */
/* owner 20260805 截图圈定:入口字体用正文楷体(--font-body,与牒页字段标签
   同族、稍大一档)。原 --font-display 齐伋体字库不全,「记/功」等字回退成
   混搭观感,弃用。 */
.me-entry-name {
  position: relative;
  font-family: var(--font-body);
  font-size: 19px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: var(--ls-label);
  color: var(--ink);
}

/* ============================================================
   心得页三栏布局(owner 20260805 demo 验收后实装)。
   桌面:左时间轴 170px / 中卡流 / 右整理面板 310px;
   ≤1120px 右栏收(控件回顶部行 .notes-mobilebar);≤760px 时间轴也收。
   原顶部搜索栏/过滤行/分页(.notes-search/.notes-filter/.notes-pager 一族)
   随三栏与无限滚动一并下架,不留死样式。
   ============================================================ */
/* 心得页专用放宽:全站 .page 桌面 max-width 880px,三栏(170+310+64 间距)塞进去
   中栏只剩 ~270px,严重挤压(owner 20260805 截图实锤)。仅此一页放宽到 1360px,
   与验收 demo 同画布;其余页面 880px 口径不动。 */
@media (min-width: 768px) {
  .page.page--notes { max-width: 1360px; }
}
.notes-layout {
  display: grid;
  grid-template-columns: 170px minmax(0, 1fr) 310px;
  gap: var(--s6);
  align-items: start;
}
.notes-mobilebar { display: none; }
@media (max-width: 1120px) {
  .notes-layout { grid-template-columns: 170px minmax(0, 1fr); }
  .notes-side { display: none; }
  .notes-mobilebar {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-wrap: wrap;
    margin-bottom: var(--s4);
  }
}
@media (max-width: 760px) {
  .notes-layout { grid-template-columns: minmax(0, 1fr); }
  .notes-rail { display: none; }
}
.notes-actbar { display: flex; gap: var(--s2); margin-bottom: var(--s4); }
.notes-act { flex: 1; }
.notes-main { min-width: 0; }

/* ---- 左栏:时间轴(sticky;可滚但永不显滑动块——owner 终调) ---- */
.notes-rail {
  position: sticky;
  z-index: 10; /* sticky 自建堆叠上下文但默认 auto,后续中栏卡片会盖住浮标签(owner 视频b) */
  top: var(--s4);
  max-height: calc(100vh - var(--s6));
  overflow-y: auto;
  scrollbar-width: none;
  padding: var(--s1) 0;
}
.notes-rail::-webkit-scrollbar { display: none; }
.notes-rail-title {
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
  margin: 0 0 var(--s3);
}
.notes-rail-month { margin-bottom: var(--s3); }
.notes-rail-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  background: none;
  border: 0;
  padding: 2px 0;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease-out);
}
.notes-rail-label:hover { color: var(--line-red); }
.notes-rail-month[data-cur="1"] .notes-rail-label { color: var(--ink); }
.notes-rail-month[data-cur="1"] .notes-rail-label::after {
  content: "";
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--seal);
  margin-left: 6px;
  vertical-align: 3px;
}
/* 刻度:一天一条(间距=demo 终版 10.5px);重点日默认加粗加长;当前=朱 */
.notes-tick {
  position: relative;
  display: flex;
  justify-content: flex-start; /* 全站按钮规则会给 button 打 center,显式压回(owner 视频实锤) */
  align-items: center;
  height: 10.5px;
  width: 100%;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
}
.notes-tick i {
  display: block;
  width: 14px;
  height: var(--lw-line);
  background: var(--line);
  transition: width 140ms var(--ease-out), background-color 140ms var(--ease-out);
}
.notes-tick[data-star="1"] i { width: 20px; height: var(--lw-heavy); background: var(--ink-3); }
.notes-tick[data-cur="1"] i { width: 22px; height: var(--lw-heavy); background: var(--line-red); }
.notes-tick:hover i { width: 26px; background: var(--line-red); }

.notes-tick-tip {
  /* 20260805:改 fixed+JS 定位——原 absolute 挂在 rail 滚动容器内,
     长标签(…·有重点)伸出容器右缘被裁,即 owner 说的「无形的边界」 */
  position: fixed;
  left: 0;
  top: 0;
  transform: translateX(-4px);
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  padding: 1px 8px;
  font-size: var(--fs-caption);
  color: var(--ink-2);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms var(--ease-out), transform 140ms var(--ease-out);
  box-shadow: var(--shadow-float);
  z-index: 5;
}
.notes-tick-tip[data-show="1"] {
  opacity: 1;
  transform: translateX(0);
}

/* ---- 中栏:月锚(无月柱,owner 终裁)+ 哨兵 ---- */
.notes-month-anchor {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--ink-2);
  margin: var(--s5) 0 var(--s1);
  display: flex;
  align-items: baseline;
  gap: var(--s3);
}
.notes-month-anchor small { font-size: var(--fs-caption); color: var(--ink-3); font-weight: 400; }
.notes-month-anchor::after {
  content: "";
  flex: 1;
  height: var(--lw-hair);
  background: var(--line);
  align-self: center;
}
.notes-sentinel { text-align: center; padding: var(--s3) 0; min-height: 28px; }
/* 卡片右下「删除笔记」(owner 20260805,仅本人卡;点击二次确认后删) */
.note-del {
  position: relative;
  display: block;
  margin-left: auto;
  margin-top: var(--s2);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-3);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
}
.note-del:hover { color: var(--red-text); }
/* owner 20260805 二改:删除不做显性——桌面悬停卡片才现 */
.note-del { opacity: 0; transition: opacity var(--t-fast) var(--ease-out); }
.note-card:hover .note-del { opacity: 1; }
@media (max-width: 760px) {
  .note-del { display: none; } /* 手机走左滑红键 */
}

/* 左滑删除(手机,iOS 邮件/微信会话惯例):红键垫底,卡体左移露出 */
.note-swipe { position: relative; }
.note-swipe-del {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 88px;
  border: 0;
  border-radius: 0 var(--r-card) var(--r-card) 0;
  background: var(--line-red);
  color: var(--paper-2);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  cursor: pointer;
  display: none;
}
.note-swipe .note-card { position: relative; z-index: 1; transition: transform 180ms var(--ease-out); }
.note-swipe[data-open="1"] .note-card { transform: translateX(-96px); }
@media (max-width: 760px) { .note-swipe-del { display: block; } }

/* 点评第一版「查看窗左右双栏内嵌」整组样式已删(20260806 复审判死代码:
   该设计被 owner 回滚于 4ada5fa,现行=批阅台 desk-* + 师父来信独立页)。 */

/* 「师父来信」入口未读角标 */
.notes-act--cmt { position: relative; }
.notes-cmt-badge {
  display: none;
  position: absolute;
  top: -7px;
  right: -7px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--seal);
  color: #fff;
  font-size: 11px;
  line-height: 18px;
  text-align: center;
}
.notes-cmt-badge[data-show="1"] { display: block; }

/* ---- 批阅台(师父方案二,owner 20260805 定案):宽幅双栏 ---- */
@media (min-width: 720px) {
  .book-card.desk-card { width: min(980px, 94vw); max-width: 94vw; padding: var(--s5) var(--s6); }
}
.book-card.desk-card { max-height: calc(100vh - 40px); overflow-y: auto; }
/* owner 20260805:长文时点评组件要固定右侧不随滚;且整卡滚动会把 .ticket::before
   内线(按可视高度画的绝对定位框)滚出错位,下边框横在正文中间(截图实锤的
   "莫名横线")。桌面端改:卡壳定高不滚,左栏正文自己内滚(滑动块全隐,同时间轴
   惯例)——标题/右栏/内线框全部天然固定。≤760 单列维持整卡滚不动。 */
@media (min-width: 761px) {
  .book-card.desk-card { overflow: hidden; display: flex; }
  .desk-card .ticket-body { display: flex; flex-direction: column; min-height: 0; flex: 1; min-width: 0; }
  .desk-card .desk-cols { flex: 1; min-height: 0; }
  .desk-card .desk-left { overflow-y: auto; min-height: 0; scrollbar-width: none; }
  .desk-card .desk-left::-webkit-scrollbar { display: none; }
}
/* desk-nav/navbtn/pos/label/skip 等批阅流控件样式已删(20260806 复审判死代码:
   对应 UI 被 owner 明令删除「这些都是废话」);.note-view-name 同批清理。 */
.desk-cols { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--s6); }
@media (max-width: 760px) { .desk-cols { grid-template-columns: 1fr; } }
.desk-right { border-left: var(--lw-hair) solid var(--line); padding-left: var(--s5); }
@media (max-width: 760px) {
  .desk-right { border-left: 0; padding-left: 0; border-top: var(--lw-hair) dashed var(--line); padding-top: var(--s3); }
}
.desk-clist { max-height: 200px; overflow-y: auto; }
.desk-citem { padding: var(--s2) 0; }
.desk-citem + .desk-citem { border-top: var(--lw-hair) dashed rgba(177, 59, 46, .35); }
.desk-cdate { font-size: 11px; color: var(--ink-3); margin: 0 0 1px; }
.desk-ctext { font-size: var(--fs-body-sm); color: var(--line-red); margin: 0; line-height: 1.8; }
.desk-input {
  width: 100%;
  min-height: 120px;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
  padding: var(--s2) var(--s3);
  resize: none;
  font-family: "KaiTi", "STKaiti", "楷体", serif;
  font-size: var(--fs-body-sm);
  line-height: 1.8;
  color: var(--ink);
}
.desk-input::placeholder { color: var(--ink-3); opacity: .6; }
.desk-btnrow { display: flex; gap: var(--s2); margin-top: var(--s3); }
.desk-btnrow .btn { flex: 1; }
.desk-clist { margin-bottom: var(--s3); }
/* owner 20260805:批阅台整体字号 +25%(嫌太小);同日补令:点评/关闭按钮不调。
   逐类显式 calc(各自原 token *1.25),不动全局 token(只放大这一个窗)。 */
.desk-card .book-card-title { font-size: calc(var(--fs-sub) * 1.25); }
.desk-card .note-edit-sub { font-size: calc(var(--fs-caption) * 1.25); }
.desk-card .note-view-text { font-size: calc(var(--fs-body) * 1.25); }
.desk-card .field-hint { font-size: calc(var(--fs-caption) * 1.25); }
.desk-card .desk-cdate { font-size: 13.75px; } /* 11px * 1.25 */
.desk-card .desk-ctext { font-size: calc(var(--fs-body-sm) * 1.25); }
.desk-card .desk-input { font-size: calc(var(--fs-body-sm) * 1.25); }
/* 师父来笺独立页:信笺铺主栏 */
.letters-list--page { max-width: 860px; }
.letters-list--page .letter-head { padding: var(--s3) var(--s5); font-size: var(--fs-body); }
.letters-list--page .letter-body { padding: 0 var(--s5) var(--s4); }

/* .letters-card(来笺旧弹窗皮肤)已删(20260806 复审判死代码:来信改独立页
   c2a36d4 后无实例化;现行=.letters-list--page)。 */
.letters-list { margin-bottom: var(--s4); }
.letter {
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-sm);
  margin-bottom: var(--s3);
  background: var(--paper-2);
  overflow: hidden;
}
.letter-head {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s3) var(--s4);
  cursor: pointer;
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
}
.letter-seal {
  width: 22px;
  height: 15px;
  border: var(--lw-line) solid var(--line-red);
  border-radius: 2px;
  position: relative;
  flex-shrink: 0;
}
.letter-seal::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-top: 8px solid rgba(177, 59, 46, .35);
}
.letter[data-open="1"] .letter-seal::before { border-top-color: transparent; }
.letter-date { margin-left: auto; font-size: var(--fs-caption); color: var(--ink-3); }
.letter[data-unread="1"] .letter-head { color: var(--ink); font-weight: 600; }
.letter[data-unread="1"] .letter-seal { background: rgba(177, 59, 46, .08); }
.letter-body { display: none; padding: 0 var(--s4) var(--s3); border-top: var(--lw-hair) dashed var(--line); }
.letter[data-open="1"] .letter-body { display: block; }
.letter-quote { font-size: var(--fs-caption); color: var(--ink-3); margin: var(--s2) 0 var(--s1); font-family: "KaiTi", "STKaiti", "楷体", serif; }
.letter-text { font-size: var(--fs-body); color: var(--ink); margin: 0; line-height: 1.9; font-family: "KaiTi", "STKaiti", "楷体", serif; }

/* ---- 右栏:整理面板 ---- */
.notes-side {
  position: sticky;
  top: var(--s4);
  border-left: var(--lw-hair) solid var(--line);
  padding: var(--s1) 0 var(--s2) var(--s5);
}
.notes-side-sec { margin-bottom: var(--s5); position: relative; }
.notes-side-title {
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
  margin: 0 0 var(--s2);
}
/* 搜索弟子盒(owner 20260805 红框示意:严格=一张弟子卡的列宽;
   间距=组件高(约44px)为基数,上留 10%+(5px)、下留 20%(9px,叠加原 16px=25px)) */
/* .disciple-search(管理页正文内搜索盒)随甲案删除——搜索移入右栏整理面板。 */
.notes-sideinput {
  display: flex;
  align-items: center;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  background: var(--paper-2);
  padding: 5px 10px;
  margin-bottom: var(--s2);
}
.notes-sideinput input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  /* 搜索关键词/弟子姓名用系统默认楷体(owner 20260805) */
  font-family: "KaiTi", "STKaiti", "楷体", serif;
  font-size: var(--fs-body-sm);
  color: var(--ink);
}
.notes-sideinput input::placeholder { color: var(--ink-3); opacity: .6; }
/* 聚焦变色已删(owner:任何选中框都不要) */
.notes-sortopt {
  display: flex;
  justify-content: flex-start; /* 同上:压掉全站按钮的居中 */
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  width: 100%;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
}
.notes-sortopt i {
  width: 12px;
  height: 12px;
  border: var(--lw-line) solid var(--line);
  border-radius: 50%;
  flex-shrink: 0;
  position: relative;
  transition: border-color var(--t-fast) var(--ease-out);
}
.notes-sortopt[data-on="1"] { color: var(--ink); }
.notes-sortopt[data-on="1"] i { border-color: var(--line-red); }
.notes-sortopt[data-on="1"] i::after {
  content: "";
  position: absolute;
  inset: 2.5px;
  border-radius: 50%;
  background: var(--line-red);
}
.notes-sortopt:hover { color: var(--ink); }
.notes-chip {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  background: transparent;
  cursor: pointer;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  padding: 3px 10px;
  color: var(--ink-2);
}
.notes-chip[data-on="1"] { border-color: var(--line-red); color: var(--line-red); }
/* 下拉小三角(CSS 画,零字体依赖——▾ 字形 LXGW 没有) */
.notes-chip--dd::after {
  content: "";
  display: inline-block;
  margin-left: 6px;
  vertical-align: 2px;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--ink-3);
}
.notes-count { font-size: var(--fs-caption); color: var(--ink-3); margin: var(--s2) 0 0; }
.notes-reset {
  background: none;
  border: 0;
  padding: 0;
  margin-top: var(--s2);
  cursor: pointer;
  color: var(--ink-3);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
}
.notes-reset:hover { color: var(--ink); }
/* 窄屏控件行里的输入 */
.notes-mobilebar-search,
.notes-mobilebar-name {
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  background: var(--paper-2);
  padding: 5px 10px;
  font-family: "KaiTi", "STKaiti", "楷体", serif;
  font-size: var(--fs-body-sm);
  color: var(--ink);
  outline: 0;
}
.notes-mobilebar-search { flex: 1; min-width: 120px; }
.notes-mobilebar-name { width: 110px; }


/* ---- 迷你月历(「选择日期」;恒 6 行 42 格,切月高度零跳变) ---- */
/* v1.1.1:心得日历玻璃化+弹簧(与 ⋯ 菜单同族,origin 取按钮左上) */
.notes-minical {
  display: block;
  position: absolute;
  right: 0;
  top: calc(100% - 4px);
  z-index: 60;
  width: 286px;
  background: rgba(250, 246, 236, .95);
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: 14px;
  box-shadow: inset 0 0 20px -5px rgba(255, 255, 255, .6), 0 10px 26px rgba(26, 26, 26, .13);
  padding: var(--s3);
  opacity: 0;
  pointer-events: none;
  transform: scale(.88);
  transform-origin: top left;
  transition: opacity var(--t-pop-close) var(--ease-spring), transform var(--t-pop-close) var(--ease-spring);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .notes-minical {
    background: rgba(250, 246, 236, .78);
    -webkit-backdrop-filter: blur(14px) saturate(1.35);
    backdrop-filter: blur(14px) saturate(1.35);
  }
}
.notes-minical[data-open="1"] {
  opacity: 1;
  pointer-events: auto;
  transform: scale(1);
  transition-duration: var(--t-pop-open);
}
.notes-mc-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s2); }
.notes-mc-title { font-size: var(--fs-body-sm); color: var(--ink); }
.notes-mc-nav {
  width: 28px;
  height: 28px;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
}
.notes-mc-nav:disabled { opacity: .3; cursor: not-allowed; }
.notes-mc-dow {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  font-size: 12px;
  color: var(--ink-3);
  text-align: center;
  margin-bottom: 3px;
}
.notes-mc-grid { display: grid; grid-template-columns: repeat(7, 1fr); grid-template-rows: repeat(6, 34px); }
.notes-mc-cell {
  position: relative;
  border: 0;
  background: transparent;
  text-align: center;
  font-family: var(--font-num);
  font-size: 13px;
  color: var(--ink-2);
  cursor: pointer;
  border-radius: var(--r-sm);
}
.notes-mc-cell:hover:not(:disabled) { background: var(--paper-3); }
.notes-mc-cell:disabled { color: var(--ink-3); opacity: .32; cursor: default; }
.notes-mc-cell i {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 3px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--ink-3);
}
.notes-mc-cell[data-star="1"] i { background: var(--line-red); }

/* ---- 记事卡 ---- */
.note-list { display: flex; flex-direction: column; gap: var(--s3); }
.note-card {
  position: relative;
  background: var(--paper-2);
  border: var(--lw-thick) solid var(--line);
  border-radius: var(--r-card);
  padding: var(--s4) var(--s4);
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out);
}
.note-card::before {
  content: "";
  position: absolute;
  inset: 4px;
  border: var(--lw-hair) solid var(--line);
  border-radius: calc(var(--r-card) - 2px);
  pointer-events: none;
}
.note-card:hover { background: var(--paper-3); }
.note-card[data-star="1"]::before { border-color: var(--line-red); }
.note-card-head {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s3);
}
.note-card-left p { margin: 0; }
.note-date { font-size: var(--fs-body); color: var(--ink); }
.note-today-dot {
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--seal);
  margin-right: 6px;
  vertical-align: 3px;
}
.note-who { font-size: var(--fs-caption); color: var(--ink-2); letter-spacing: var(--ls-label); }
.note-ganzhi { font-size: var(--fs-caption); color: var(--ink-3); letter-spacing: var(--ls-label); }
.note-card-right { display: flex; align-items: center; gap: var(--s2); flex-shrink: 0; }
.note-practice { font-size: var(--fs-caption); color: var(--ink-3); white-space: nowrap; }
.note-practice[data-none="1"] { opacity: .45; }
.note-star {
  background: none;
  border: 0;
  padding: 2px;
  cursor: pointer;
  line-height: 0;
  color: var(--line);
  transition: color var(--t-fast) var(--ease-out);
}
.note-star:hover:not(:disabled) { color: var(--ink-3); }
.note-star[data-on="1"] { color: var(--line-red); }
.note-star:disabled { cursor: default; }
.note-excerpt {
  position: relative;
  margin: var(--s2) 0 0;
  /* 笔记正文一律系统楷体(owner 20260805 重申,列表卡/查看窗/编辑器三处同规) */
  font-family: "KaiTi", "STKaiti", "楷体", serif;
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  line-height: var(--lh-body);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* (翻页 .notes-pager 一族已随无限滚动下架——Q1 拍板,不留死样式) */

/* ---- 编辑器小窗(居中,复用 book-card 骨架) ----
   owner 20260805 桌面截图:「不好看,不协调,很小气」——桌面端小窗按内容
   放宽放大(编辑器 600px/月历 480px/里程碑 520px),内边距同步加一档;
   窄屏(手机)沿用 book-card 原生宽度,不受影响。 */
.book-card.note-edit-card,
.book-card.note-view-card,
.book-card.note-cal-card {
  max-height: calc(100vh - var(--s4) * 2);
  overflow-y: auto;
}
@media (min-width: 720px) {
  .book-card.note-edit-card,
  .book-card.note-view-card { width: 600px; max-width: 92vw; padding: var(--s6) var(--s6) var(--s5); }
  .book-card.note-cal-card { width: 480px; max-width: 92vw; padding: var(--s6) var(--s6) var(--s5); }
  .book-card.mile-card { width: 520px; max-width: 92vw; padding: var(--s5) var(--s6); max-height: calc(100vh - 40px); overflow-y: auto; }
  .note-editor { min-height: 260px; }
  .note-cal-cell { min-height: 52px; }
}
.note-edit-sub { font-size: var(--fs-caption); color: var(--ink-3); margin: 0 0 var(--s3); }
/* 乌丝栏界行按 28px 整行网格铺;上下留 4px 齐口,正文行高锁 28px,
   高度=整行数——首行/末行都是完整一行(owner 20260805 截图2:原 padding 12px+
   行高 26.25px 非整倍,顶底各剩半行)。手动拉伸取消(拉出非整行必破界行)。 */
.note-editor-frame {
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-sm);
  padding: 4px var(--s3);
  background: var(--paper);
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 27px,
    rgba(201, 191, 168, .35) 27px,
    rgba(201, 191, 168, .35) 28px
  );
  background-position: 0 4px;
}
.note-editor {
  width: 100%;
  min-height: 180px;
  resize: vertical;
  background: transparent;
  border: 0;
  outline: 0;
  /* owner 20260805:笔记正文用系统默认楷体(不走 webfont,与搜索/姓名输入同规) */
  font-family: "KaiTi", "STKaiti", "楷体", serif;
  font-size: var(--fs-body);
  line-height: 28px !important;
  height: 280px;
  min-height: 280px;
  resize: none;
  line-height: var(--lh-body);
  color: var(--ink);
  padding: 0;
}
.note-editor::placeholder { color: var(--ink-3); opacity: .6; }
.note-editor-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: var(--s2);
  font-size: var(--fs-caption);
  color: var(--ink-3);
}
.note-save-state[data-state="saving"] { color: var(--indigo); }
.note-save-state[data-state="dirty"] { color: var(--red-text); }
.note-star-row {
  display: flex;
  align-items: center;
  gap: var(--s2);
  margin: var(--s3) 0;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
}
.note-star-row .note-star { pointer-events: none; }
.note-view-text {
  font-family: "KaiTi", "STKaiti", "楷体", serif; /* 同上 */
  font-size: var(--fs-body);
  color: var(--ink);
  line-height: var(--lh-body);
  white-space: pre-wrap;
  margin: 0 0 var(--s3);
}

/* ---- 月历小窗 ---- */
.note-cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--s2);
}
.note-cal-title { font-size: var(--fs-body); color: var(--ink); }
.note-cal-nav {
  width: 32px;
  height: 32px;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}
.note-cal-nav:disabled { opacity: .3; cursor: not-allowed; }
.note-cal-dow {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  font-size: var(--fs-caption);
  color: var(--ink-3);
  text-align: center;
  margin-bottom: var(--s1);
}
.note-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  border-top: var(--lw-hair) solid var(--line);
  border-left: var(--lw-hair) solid var(--line);
  margin-bottom: var(--s3);
}
.note-cal-cell {
  border: 0;
  border-right: var(--lw-hair) solid var(--line);
  border-bottom: var(--lw-hair) solid var(--line);
  min-height: 42px;
  padding: 4px 0 0;
  text-align: center;
  position: relative;
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  cursor: pointer;
  background: transparent;
}
.note-cal-cell:hover:not(:disabled) { background: var(--paper-3); }
.note-cal-cell:disabled { color: var(--ink-3); opacity: .35; cursor: not-allowed; }
.note-cal-cell[data-empty="1"] { border-color: transparent; cursor: default; }
.note-cal-cell[data-today="1"] { box-shadow: inset 0 0 0 var(--lw-line) var(--line-red); }
.note-cal-dot {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 5px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ink);
}

/* ---- 里程碑悬浮页 ---- */
.book-card.mile-card {
  max-height: calc(100vh - var(--s4) * 2);
  overflow-y: auto;
}
.mile-now {
  position: relative;
  background: var(--paper);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-sm);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s3);
}
.mile-now-k { font-size: var(--fs-caption); letter-spacing: var(--ls-label); color: var(--ink-3); margin: 0; }
.mile-now-big {
  font-family: var(--font-display);
  font-size: 32px;
  line-height: 1.15;
  color: var(--ink);
  margin: 2px 0 0;
}
.mile-now-unit { font-family: var(--font-body); font-size: 14px; color: var(--ink-3); margin-left: 4px; }
.mile-bar {
  height: 8px;
  background: var(--paper-3);
  border: var(--lw-hair) solid var(--line);
  border-radius: 1px;
  margin: var(--s2) 0 6px;
  overflow: hidden;
}
.mile-bar i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--ink-2);
  transition: width 700ms var(--ease-out);
}
.mile-bar-foot {
  display: flex;
  justify-content: space-between;
  font-size: 11.5px;
  color: var(--ink-3);
}
.mile-bar-pct { color: var(--line-red); }
.mile-now-next {
  margin: var(--s2) 0 0;
  padding-top: var(--s2);
  border-top: var(--lw-hair) dashed var(--line);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
}
.mile-streak-line { font-size: var(--fs-body-sm); color: var(--ink-2); margin: 0 0 var(--s3); }
.mile-seals-label { margin-bottom: var(--s2); }
.mile-seals {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s2);
  margin-bottom: var(--s2);
}
.mile-seal {
  position: relative;
  /* 原 aspect-ratio:1/1 在 520px 宽卡内每格 ~150px,三行加头部必超视口,
     浮层默认被截半(owner 20260805 截图)。改定高紧凑格,默认一屏完整。 */
  min-height: 76px;
  padding: var(--s2) var(--s1);
  border: var(--lw-hair) dashed var(--line);
  border-radius: var(--r-sm);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
}
.mile-seal[data-got="1"] {
  border: var(--lw-thick) solid var(--line-red);
  background: rgba(177, 59, 46, .055);
}
.mile-seal[data-got="1"]::before {
  content: "";
  position: absolute;
  inset: 3px;
  border: var(--lw-hair) solid var(--line-red);
  opacity: .5;
  border-radius: 1px;
  pointer-events: none;
}
.mile-seal-name {
  position: relative;
  font-family: var(--font-display);
  font-size: 19px;
  line-height: 1.1;
  color: var(--ink-3);
}
.mile-seal[data-got="1"] .mile-seal-name { color: var(--line-red); }
.mile-seal-name[data-long="1"] { font-size: 14px; }
.mile-seal-sub { position: relative; font-size: 9.5px; color: var(--ink-3); line-height: 1.2; }
.mile-seal[data-got="1"] .mile-seal-sub { color: var(--line-red); opacity: .85; }
.mile-legend { font-size: var(--fs-caption); color: var(--ink-3); margin: 0 0 var(--s3); }
