/* 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.9734dfde.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;

  /* ---- 三栏页栅格（v1.6.0 六轮 X5，owner H9 逐字：「现在 公告 阳神班 管理
       里面的 左侧栏 中间内容 和右侧栏 每点开一个都是一个布局位置，请你同意
       优化一个最优解，所有页面用一个规范 布局位置」）：公告 / 阳神班 / 管理 /
       弟子心得（及师父来信）四张三栏页共用这一组数，改栏宽只改这里一处。
       取值按 owner「两页不一致取更大值」：左栏 200（管理 / 阳神班 / 公告 200 >
       心得 170）、右栏 340（公告 340 > 心得 310 > 管理 300）、栏距 --s6 32
       （心得 / 公告 32 > 管理 24）、画布 1560（管理 1560 > 其余 1360）、
       右栏与左栏 sticky 顶距 --s4 16（四页原本同值）。 ---- */
  --rail-l:     200px;
  --rail-r:     340px;
  --rail-gap:   var(--s6);
  --rail-top:   var(--s4);
  --canvas-tri: 1560px;

  /* ---- 控件尺寸 [官方: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 覆写清单同步移除该行，避免留一条不再生效的
   死配置)。 */
/* 六轮 X5(索引 §4「三栏页面内最小字号 13」且本行是副说明;工单契约 2 逐字
   「.folio-note 升 13.8 -> 15」):13.8 是旧 +15% 乘数留下的余数,不是标准里的
   任何一档,按 owner「统一标准 而不是每个页自己发明一个」定死 15。四页(今日 /
   排行榜 / 我的 / 师父来信)仍逐像素一致,行盒 15 × 1.6 = 24 定高。
   弟子心得页的这一行随 H8 整行删除,不在本规则的消费者里。 */
.folio-note {
  margin-top: var(--s2);
  font-family: var(--font-body);
  font-size: 15px;
  height: 24px;
  line-height: 24px;
  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;
}
/* 返工一（主编排硬规则「不得变小」）：空态标题基座在挂 .page-scale-lg 的页是
   18.4、在没挂的页是 16，总闸统一成 16 就把前者压小了。索引 §4 没有「空态标题」
   这一角色，按「取更大的那个值」再就近取字号阶梯上的一档 20（--fs-h3 那一级），
   全站同值且一处不变小。 */
.empty-title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 20px;
  line-height: 28px;
  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 注释)，不再经这条变量覆写间接生效，
     留在这里会变成一条不影响任何选择器的死配置，故删除，避免误导后来者。 */
}
/* ============================================================================
   §22b 三栏页字号基准 .page--notes（v1.6.0 六轮 X5；owner H5 逐字「所有的字体
   字号 要有统一标准 而不是每个页自己发明一个，当出现两个页不一致的时候，
   字号取更大的那个值」）。

   owner 那句抱怨的机械成因就在上面这条 .page-scale-lg：管理 / 阳神班 / 弟子
   心得三页挂它（全 --fs-* ×1.15），公告页没挂，于是同一支 var(--fs-body) 在
   管理页算出 16.1px、在公告页算出 15px，同一支 var(--fs-body-sm) 算出 14.95px
   与 13px——「每个页一个字号」不是谁手写错了，是同一套变量在四页取了两组值。
   X2 / X3 / X4 三卡的绕法是逐条写字面量，只治了各自改到的那几行。

   本块把三栏页的语义字号钉回索引 §4 的一套数：正文 15 / 节题 16 / 字段标签与
   副说明 13，乘数在这些页不再生效。钩子直接用既有的 .page--notes——公告 /
   阳神班 / 管理 / 弟子心得（外加同骨架的师父来信）挂的就是它，不必新造一个
   类，也不会漏挂。写在 .page-scale-lg 之后、同为 0,2,0 特异性，靠文件顺序赢；
   两个类仍可同时挂在一张页上（巨字页标等非 --fs-* 的硬编码尺度继续吃
   .page-scale-lg 那套，不受影响）。

   与「取更大值」的关系：12 / 11 / 11.5 / 12.5 / 12.65 / 13.8 一律抬到 13，
   13 / 14.95 抬到 15，是取大；13.8 的副说明与 14.95 的次级文字落到 13，是把
   乘数余数收回标准档——索引 §4 已由主编排按 owner 原话裁定为 13，四页同值优先
   于保留某一页的零头。落差 ≤ 1.95px，且全部发生在辅助文字上。
   ========================================================================== */
.page.page--notes {
  --fs-body:          15px;
  --fs-sub:           16px;
  --fs-body-sm:       13px;
  /* 返工一（复核 P1-2 的根因面 + 主编排硬规则「与基座相比任何可见文字不得
     变小」）：小字注 / 副说明这一档，基座在公告页是 12、在挂 .page-scale-lg 的
     三页是 13.8。首版按索引 §4 一律写 13，结果把三页的 13.8 压成 13——公告页
     变大、另三页变小，恰好撞上 owner「两个页不一致的时候，字号取更大的那个
     值」。改取两者中的大者 13.8：五页同值、一处不变小、仍 ≥ 索引 §4 的「三栏
     页面内最小 13」。13.8 不是字号阶梯上的标准档，是基座留下的乘数余数；要不
     要再往上并到 15，属主编排 / owner 的一句话，本卡不擅动（写进交回件候裁）。
     --fs-tagrule-* 同理按「取大」落：label 14.95 -> 就近的标准档 15，meta 13.8。 */
  --fs-caption:       13.8px;
  --fs-fieldlabel:    13px;
  /* --fs-fieldvalue 不写：基线 15、.page-scale-lg 下 17.25，索引 §4 没有这一
     角色的定值，按 owner「取更大的那个值」保留原样，不往下压。 */
  --fs-tagrule-label: 15px;
  --fs-tagrule-meta:  13.8px;
  --fs-table:         13px;
  --fs-aux:           13px;
}
.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):左身份入口/中名册账行/右整理
   面板。owner 同轮细则:标题无红点/排序无姓名项/三点横排。
   v1.6.0 二轮 W7(owner 20260915「所有管理员界面都是默认要利用横向空间【因为
   管理员一般都是电脑打开】」「时段统计不要做浮层,直接像截图三那样做到右侧,
   在右侧进行 configure」):右栏由 .notes-side 复用改为 .adc 配置面板(样式在
   lgj-160-admin.css),栏宽 240 -> 300、栏距 --s6 -> --s5;名册每行在「日均」
   之后按所选时段追加时段三格(.s-r1/.s-r2/.s-r3;四轮 T5 起与四格互斥,分组竖线
   .adm-sep 随之退役已摘),固定宽合计
   因此收窄(姓名 140 -> 112、四格 112 -> 82、操作列 76 -> 56)。
   ========================================================================== */
/* v1.6.0 六轮 X5(owner H9「所有页面用一个规范 布局位置」):管理页与心得页
   「两页各走各的口径」的分流退役——四张三栏页共用 --canvas-tri(1560,取原先
   最大者)与 --rail-l / --rail-r / --rail-gap,画布规则只剩 .page--notes 那一条
   (见 §心得页三栏布局),.page--admin 的 1560 覆写因此成为同值重复,已删。 */
.adm-layout {
  display: grid;
  grid-template-columns: var(--rail-l) minmax(0, 1fr) var(--rail-r);
  gap: var(--rail-gap);
  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(--rail-top);
}
.adm-title {
  font-family: var(--font-display);
  font-size: 44px;
  line-height: 1.15;
  font-weight: 400;
  letter-spacing: 2px;
  margin: 0;
}
/* 六轮 X5(索引 §4「左栏计数 15px」):13 -> 15,写字面量——三栏页挂
   .page--notes 的 §22b 覆写后 --fs-body 已是 15,但管理 / 阳神班 / 心得同时挂 .page-scale-lg,
   字面量是四页逐像素同值最不依赖叠加顺序的写法(与 X2 .adc-*、X3 .ntc-* 同源)。
   行盒 = 15 × 1.6 = 24,定高 24 不用 min-height。 */
.adm-count {
  font-family: var(--font-body);
  font-size: 15px;
  height: 24px;
  line-height: 24px;
  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);
  /* 六轮 X5(索引 §4「左栏链接项 15px」;owner H5「字太小了，尤其是左侧栏 你
     明显和 其他页的左侧栏字号大小不一致」):13(挂 .page-scale-lg 的管理 /
     阳神班实得 14.95)-> 15 字面量,与公告页 .ntc-filter 逐像素同值。
     行盒 = 10 上 + 24 行 + 10 下 = 44,与 .ntc-filter / .ntc-railstat 同高。 */
  font-size: 15px;
  line-height: 24px;
  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 112px; }
.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; }
/* v1.6.0 六轮 X2(owner H10 逐字「截图9 截图10,字号要加大」;六轮字号标准:字段
   标签 13px、名册格数值 17px `--font-num`):
   · 标签 11.5 -> 13、数值 13.5 -> 17、缺数句 12.5 -> 13,三者都写字面量——管理页
     挂 .page-scale-lg(那条 +15% 覆写会把 --fs-body-sm 顶成 14.95px、--fs-body 顶成
     16.1px),走变量就对不上 owner 定的 13 / 17,与 .adc-readout 的既有做法同源。
   · 逐行定高(定高纪律,一处不用 min-height):标签行 18、数值行 24、缺数句 24
     ——「有数 / 暂无数据 / 「—」」三态同高 24,格高恒 18 + 1(gap) + 24 = 43,
     名册行不因某格缺数而错位。
   · 字号变大后一格实宽约 83px(2ch 数字 ×2 + 两个 .88em 单位 + 左右间距),故
     flex-basis 82 -> 96、min-width 74 -> 88;四格与时段四格共用这一个基数,
     两态逐格等宽(owner H11 两组格子一一对位)。 */
.adm-stat { flex: 0 1 96px; min-width: 88px; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
/* v1.6.0 七轮 Y3(owner J2 逐字:「红框的部分 这么多空间 可以利用好,把 本日
   本周 本月 总累计之间的 间距 调大一点,美观一点 凑在一起太拥挤了」):
   非时段态四格全显(排序键=总累计)时,格与格之间由行自带的 10px 紧排拉到
   --s7 = 48px。行的 gap 本身已给 10px,故这里只补差额 38——两者相加恰是
   --s7,computed 间距 = 48.0,不另立第二套间距口径。
   · 只挂在非时段态那四格(s-td / s-w / s-m 之后的兄弟格)上:时段四格
     (s-r1..s-r4)是 X2 契约 5 的禁区,一个像素不动。
   · 每格仍 flex 0 1 96px,整组仍由 .adm-gap 顶到操作列前右对齐,故单格态那一
     格的右缘与四格态「总累计」的右缘天然同位(右侧固定件只有 .adm-op 56 +
     一个 10px 行 gap),不漂。
   · 边距不影响格高,定高纪律(18 + 1 + 24)原样。 */
.adm-stat.s-td + .adm-stat,
.adm-stat.s-w + .adm-stat,
.adm-stat.s-m + .adm-stat { margin-left: calc(var(--s7) - 10px); }
.adm-stat-k { font-family: var(--font-body); font-size: 13px; height: 18px; line-height: 18px; color: var(--ink-3); letter-spacing: 1px; white-space: nowrap; }
.adm-stat-na { font-family: var(--font-body); font-size: 13px; height: 24px; line-height: 24px; color: var(--ink-3); }
.dur { font-family: var(--font-num); font-size: 17px; height: 24px; line-height: 24px; 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; }
/* 零记录:同一支笔更浅一档,不写「—」不加灰底行(图纸 D6 §三) */
.adm-stat[data-zero="1"] .dur { color: var(--ink-3); }
.adm-stat[data-zero="1"] .dur-u { color: var(--ink-3); }
/* 六轮 X2:时段态由三格(时段总时长 / 时段天数 / 时段日均)改四格(练功时长 /
   请假次数 / 迟到次数 / 练功天数),四格与非时段四格逐格等宽,故三条各自加宽的
   覆写整块退役——共用 .adm-stat 那一个基数即是「等宽」。 */
/* ⋯ 呼吸位:操作列固定 56px 永不收缩(owner 两轮「往左/仍被挤」令),数字组
   整体因此离右缘一大步;二轮为时段三格腾位由 76 收到 56 */
.adm-op { flex: 0 0 56px; 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; }
/* 响应式——两套折法,靠 .page--admin 作用域分流(复核 P1-2 实锤) ---------
   §25b 这套骨架(.adm-layout/.adm-rail/.adm-main/.adm-row/.adm-name-wrap/
   .adm-stat)不是「管理」页专用:阳神班管理页 ui-yangshen-admin.js:1017 也用
   它,且右栏至今仍是 aside.notes-side.adm-side。所以:
     · 下面第一套(≤1120 / ≤760)是基座原样,服务阳神班管理页——其中那两条
       .adm-side.notes-side 覆写必须在:它们的特异性压过通用
       @media(max-width:1439px){.notes-side{display:none}}(本文件下方),
       删掉就等于把阳神班管理员的搜索/排序/筛选整块吞掉;
     · 第二套只在 .page--admin 作用域内生效,是本卡 D6 的新折法,不外溢。
   六轮 X5(owner H9「所有页面用一个规范 布局位置」):第一套的 1120 档提到
   1439——四张三栏页的三栏 / 纵排断点统一为 1439 与 760 两道,1120 与 767 两套
   旧折法退役。第二套(.page--admin 作用域)与第一套现在同档触发,它只是把同名
   属性用更高特异性再钉一遍,结果一致,保留不删是因为其中 position:static 与
   order 三条基座没有。
   ----------------------------------------------------------------------- */
@media (max-width: 1439px) {
  /* 返工一（复核 P1-3 的同一个病，在阳神班管理页上的实例）：本档原本只写
     display:block，右栏因此按 DOM 次序落到整份名册【之后】（1280 实测
     .adm-side top = 4124）。契约 1 逐字是「右栏落到中栏上方成工具条」，故与
     .page--admin 那一块同法改纵排 flex + order；管理页那一块特异性更高，
     它自己的 order 不受影响（.adc 的 order:1 在 lgj-160-admin.css）。 */
  .adm-layout { display: flex; flex-direction: column; align-items: stretch; }
  .adm-layout > .adm-rail { order: 0; }
  .adm-layout > .adm-side { order: 1; }
  .adm-layout > .adm-main { order: 2; }
  .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) {
  /* 案三窄屏降级:砍本月一格与点线引路,姓名列收窄(六轮 X2:「日均」那一格
     .s-d 随该维度下架,选择器一并摘掉,不留指向空气的规则) */
  .adm-name-wrap { flex-basis: 108px; }
  .adm-stat { flex-basis: 104px; }
  .adm-stat.s-m { display: none; }
  .adm-side.notes-side { display: block; }
  .adm-side .notes-side-sec { margin-bottom: var(--s4); }
}

/* ---- 「管理」页(.page--admin)自己的折法:三栏只在 ≥1440 生效 -----------
   复核 P1-1 实锤:有时段态一行七格的内容最小宽恒约 809px(所有格子都已到
   min-width,再没有压缩余地),而三栏下中栏净宽 = 视口 − 622,要到 1431px
   才容得下。1121–1439 硬挤三栏,时段三格会直接压在右栏面板的搜索框与排序键
   上(实测 1121 压 220px、1280 压 61px),1440 也只富余 9px。
   改法:三栏留给 ≥1440(1440 那一档像素逐格不变),1121–1439 走纵排——但配置
   面板不是摊成一根长条,而是三节并排的一条工具条(与基座 .adm-side 在窄窗
   横排同一思路),名册因此拿到整幅宽度,七格反而比三栏时宽松得多,
   owner「管理员界面默认要利用横向空间」照样成立。
   align-items 在纵排档必须回 stretch(复核 P2-3):grid 时代留下的 start 会
   把每个子项压成内容宽,整页只用左半屏。
   ----------------------------------------------------------------------- */
@media (max-width: 1439px) {
  .page--admin .adm-layout { display: flex; flex-direction: column; align-items: stretch; }
  .page--admin .adm-rail { order: 0; }
  .page--admin .adm-main { order: 2; }
  .page--admin .adm-rail {
    border-right: 0;
    min-height: 0;
    padding-right: 0;
    display: flex;
    align-items: center;
    gap: var(--s4);
    flex-wrap: wrap;
    position: static;
  }
  .page--admin .adm-title { font-size: 32px; }
  .page--admin .adm-count { margin: 0; }
  .page--admin .adm-count--rail { margin: 0; }
  .page--admin .adm-links { border-top: 0; margin-top: 0; display: flex; gap: var(--s3); margin-left: auto; }
  .page--admin .adm-link { width: auto; padding: 6px 2px; }
  .page--admin .adm-link + .adm-link { border-top: 0; }
}
@media (max-width: 760px) {
  /* 一人两行(图纸 D6-管理页-375.html):第一行姓名,第二行七个小字标格随宽
     自然折——二轮起名册有七格,基座「砍本月/日均两列」的降级已不够用,改整行
     纵排 + 格子转横向小字标(与既有 durCell 同源,仍不加表头)。只作用在
     .page--admin,阳神班管理页仍走上面那套基座降级。 */
  .page--admin .adm-row { display: block; padding: 8px 2px; }
  .page--admin .adm-name-wrap { display: block; flex-basis: auto; }
  .page--admin .adm-gap { display: none; }
  .page--admin .adm-stat {
    flex: none;
    display: inline-flex;
    flex-direction: row;
    align-items: baseline;
    gap: 4px;
    min-width: 0;
    margin-right: 12px;
    flex-basis: auto;
  }
  /* 基座那档把本月砍掉,管理页四格全留(小字标随宽自然折) */
  .page--admin .adm-stat.s-m { display: inline-flex; }
  /* 七轮 Y3:窄屏行已纵排、格子转行内横排(靠 margin-right 12 分隔并自然换行,
     四格态即 2×2、单格态即一格),桌面那条 48px 格间距在这里没有意义,归零。 */
  .page--admin .adm-stat + .adm-stat { margin-left: 0; }
  /* 六轮 X2:窄屏同比例降一档,但标签不再降到 10.5——六轮字号标准「三栏页面内
     最小字号 13」在 375 档同样成立;数值 17 -> 15(仍是 --font-num)。
     行内横排形态下标签与数值同处一条基线,两者的定高各自回落到 20。 */
  .page--admin .adm-stat-k { font-size: 13px; height: 20px; line-height: 20px; }
  .page--admin .adm-stat .dur { font-size: 15px; height: 20px; line-height: 20px; }
  .page--admin .adm-stat .adm-stat-na { font-size: 13px; height: 20px; line-height: 20px; }
  .page--admin .adm-op { display: block; text-align: left; margin-top: 2px; }
  /* 窄屏无 hover,「⋯」常显 */
  .page--admin .adm-row .disciple-actions-toggle { opacity: 1; }
}

/* ---- 排行榜滚动固定(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);
  /* 返工一（复核 P1-2）：13 / 14.95 -> 15（索引 §4「控件 15px」）。44 的触控
     热区不动，15px 文字在 44 的行里不触边。 */
  font-size: 15px;
  line-height: 20px;
  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;
   里程碑悬浮页那一节已随 v1.6.0 九轮 M1 整段退役)
   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 验收后实装)。
   桌面:左时间轴 / 中卡流 / 右整理面板;
   ≤1439px 右栏收(控件回顶部行 .notes-mobilebar);≤760px 时间轴也收。
   原顶部搜索栏/过滤行/分页(.notes-search/.notes-filter/.notes-pager 一族)
   随三栏与无限滚动一并下架,不留死样式。
   六轮 X5(owner H9):栏宽 170/310、栏距、画布 1360 三项自创口径退役,改吃
   --rail-l / --rail-r / --rail-gap / --canvas-tri,与公告 / 阳神班 / 管理同值。
   ============================================================ */
/* 三栏页画布:全站 .page 桌面 max-width 880px,三栏塞进去中栏被严重挤压
   (owner 20260805 截图实锤)。挂 .page--notes 的四张三栏页(心得 / 公告 /
   阳神班 / 管理,外加同骨架的师父来信)统一放宽到 --canvas-tri;其余页面
   880px 口径不动。原「管理 1560 / 其余 1360」的两套口径按 owner「取更大的
   那个值」合并为一个数。 */
@media (min-width: 768px) {
  .page.page--notes { max-width: var(--canvas-tri); }
}
.notes-layout {
  display: grid;
  grid-template-columns: var(--rail-l) minmax(0, 1fr) var(--rail-r);
  gap: var(--rail-gap);
  align-items: start;
}
.notes-mobilebar { display: none; }
/* 六轮 X5:折法与管理 / 阳神班 / 公告统一——≤1439 整个栅格塌成纵排,左栏折成
   顶部横条、**右栏整块作为工具条落到中栏之上**(契约 1 逐字「右栏落到中栏上方
   成工具条,沿用管理页折法」),≤760 再退回窄屏形态。
   返工一(复核 P1-4):首版把这一档写成 `.notes-side{display:none}` + 交给
   .notes-mobilebar,结果 1121-1439 这段常用笔记本宽度上——
     · 弟子心得页丢了「日历 / 排序 / 共 N 则 / 清空全部条件」四项(mobilebar 只
       接了搜索、只看重点、弟子姓名三样);
     · 师父来信页压根没有 mobilebar(它只在 paintNotesPage 里建),右栏零替代地
       整块消失,且那两条无作用域的 `.notes-rail-title{display:none}` /
       `.notes-tick{display:none}` 把它的左栏一起吞成 8px。
   两处都不是 DOM 删控件,是把「≤1120 才降级」的旧折法整体上移带出来的破口。
   本档改法:右栏成横条(与公告页 .ntc-side / 阳神班 .adm-side 同一支笔),
   mobilebar 因此不再需要(它接的三样右栏里都有,留着就是同一控件出现两次);
   ≤760 的形态与基座逐字不变(右栏收、mobilebar 上、时间轴收)。 */
@media (max-width: 1439px) {
  /* 纵排 + order:左栏 0 / 右栏工具条 1 / 中栏 2,与 app.css §25b 管理页那套
     `.page--admin .adm-rail{order:0}` `.adm-main{order:2}` 同一支笔。 */
  .notes-layout { display: flex; flex-direction: column; align-items: stretch; }
  .notes-layout > .adm-rail,
  .notes-layout > .notes-rail { order: 0; }
  .notes-layout > .notes-side { order: 1; }
  .notes-layout > .notes-main { order: 2; }
  /* 左栏折成横条之后时间轴跟着横过来：月签一行排开（仍可点、仍高亮当月），
     一天一条的刻度在横排里没有落点，只在本档隐藏——月份跳转这个控件本身一个
     没少，刻度是它的细粒度形态，属降级不属删控件（写进交回件）。
     两条选择器都写成后代式：心得页的时间轴嵌在 .adm-rail 里，师父来信页的
     是栅格直接子项，作用域必须各自限定，不许再写裸类名外溢到别的页。 */
  .adm-rail > .notes-rail,
  .notes-layout > .notes-rail {
    position: static;
    z-index: auto;
    display: flex;
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s4);
    width: auto;
    max-height: none;
    overflow: visible;
  }
  .adm-rail > .notes-rail .notes-rail-title,
  .notes-layout > .notes-rail .notes-rail-title { display: none; }
  .adm-rail > .notes-rail .notes-tick,
  .notes-layout > .notes-rail .notes-tick { display: none; }
  .notes-rail .notes-rail-month { margin-bottom: 0; }
  /* 右栏 = 一条三节并排的工具条,压在中栏之上;竖着分栏那道乌丝换成顶上一道,
     sticky 一并解除（范式的 .notes-side 只在三栏态成立）。
     选择器写成 `.notes-layout > .notes-side`(0,2,0)是必需的:范式基类
     `.notes-side`(0,1,0)在本文件**下方**定义 position / border-left / padding
     三条,同特异性下后写的赢,裸类名在这里改不动它们(首版只写 display:none
     没暴露这个坑,因为基类里没有 display)。 */
  .notes-layout > .notes-side {
    display: flex;
    gap: var(--s6);
    flex-wrap: wrap;
    position: static;
    border-left: 0;
    border-top: var(--lw-hair) solid var(--line);
    padding: var(--s4) 0 0;
    margin: var(--s4) 0 var(--s5);
  }
  .notes-layout > .notes-side .notes-side-sec { margin-bottom: 0; flex: 0 1 260px; }
}
@media (max-width: 760px) {
  /* ≤760 回到基座形态:右栏收、控件回 .notes-mobilebar、时间轴收。 */
  .notes-layout > .notes-side { display: none; }
  .notes-mobilebar {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-wrap: wrap;
    margin-bottom: var(--s4);
  }
  .adm-rail > .notes-rail,
  .notes-layout > .notes-rail { display: none; }
}
.notes-actbar { display: flex; gap: var(--s2); margin-bottom: var(--s4); }
/* 六轮 X5 返工一（主编排硬规则「不得变小」）：心得页那三枚主操作键走全站
   .btn 的 var(--fs-body)，基座在本页是 16.1，总闸拉回 15 即变小。按字号
   阶梯就近取上一档 17。只钉这一处（.notes-act 在 .btn 之后定义，同特异性
   后写者胜），不动全站 .btn——管理页 .adm-simbtn 等控件另有各自的 15 钉。
   40 的键高不动，17px 文字在 40 的键里不触边。 */
.notes-act { flex: 1; font-size: 17px; }
.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; }
/* 六轮 X5：心得页把巨字页标迁进左栏后，时间轴由栅格子项降一层，钉住的活儿交给
   外层 .adm-rail（同一个 --rail-top），内层只管滚。max-height 减去的 100 =
   16 顶距 + 51（44px 标题的 1.15 行盒）+ 32 底部呼吸位，整条左栏因此不会长过
   一屏、sticky 才成立。零 min-height。 */
.adm-rail > .notes-rail {
  position: static;
  z-index: auto;
  max-height: calc(100vh - 100px);
  width: 100%;
}
/* 六轮 X5(索引 §4「栏内节题 16px 600」):12(挂 .page-scale-lg 实得 13.8)
   -> 16/600 字面量,与 .adc-sec-title / .notes-side-title / 公告右栏节题同值。
   行盒 = 24,定高 24 不用 min-height。 */
.notes-rail-title {
  font-size: 16px;
  font-weight: 600;
  height: 24px;
  line-height: 24px;
  letter-spacing: var(--ls-label);
  color: var(--ink-2);
  margin: 0 0 var(--s3);
}
.notes-rail-month { margin-bottom: var(--s3); }
.notes-rail-label {
  font-family: var(--font-body);
  font-weight: 600;
  /* 六轮 X5（索引 §4「左栏链接项 15px」）：月签是左栏里唯一的可点项，与
     .adm-link / .ntc-filter 同角色同值。行盒 = 2 + 20 + 2 = 24。 */
  font-size: 15px;
  line-height: 20px;
  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(--rail-top);
  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; }
/* 六轮 X5(索引 §4「栏内节题 16px 600」;owner H5「所有的字体 字号 要有统一
   标准 而不是每个页自己发明一个」):12(挂 .page-scale-lg 的阳神班 / 心得实得
   13.8)-> 16/600 字面量。本类是阳神班范式的节题,公告页 X3 已复用它并在
   lgj-160-notice.css 里覆写成 16/600;改基类之后三页同出一处,公告那条覆写
   变成同值重复(保留不删:它同时钉了 24 的定高)。定高 24。 */
.notes-side-title {
  font-size: 16px;
  font-weight: 600;
  height: 24px;
  line-height: 24px;
  letter-spacing: var(--ls-label);
  color: var(--ink-2);
  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;
  /* 六轮 X5(索引 §4「正文 15px」):13(挂 .page-scale-lg 实得 14.95)-> 15 */
  font-size: 15px;
  line-height: 24px;
  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);
  /* 六轮 X5(索引 §4「右栏选项 15px」):13(挂 .page-scale-lg 实得 14.95)
     -> 15 字面量;行盒 = 6 上 + 20 行 + 6 下 = 32,与公告页 X3 钉的右栏选项
     槽位 32 同高。 */
  font-size: 15px;
  line-height: 20px;
  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); }
/* 返工一（复核 P1-2）：右栏里的三枚控件（只看重点 / 选择日期 / 清空全部条件）
   与读数「共 N 则」原走 --fs-caption，在 §22b 总闸下算 13，比基座的 13.8 还小，
   且与它们正上方被本卡抬到 15 的 .notes-sortopt 在同一栏里一大一小。
   索引 §4「右栏选项 / 左栏计数 15px」，四处一律 15 字面量。 */
.notes-chip {
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 20px;
  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: 15px; line-height: 24px; height: 24px; 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: 15px;
  line-height: 20px;
  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; }
/* 返工一（主编排硬规则「不得变小」）：心得卡的日期抬头基座在本页是 16.1，
   总闸把 var(--fs-body) 拉回 15 就是变小。按字号阶梯就近取上一档 17
   （与名册格数值同档），日期仍比同卡摘要 15 高一级，卡内层级不变。 */
.note-date { font-size: 17px; line-height: 24px; 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;
  /* 返工一（复核 P1-2）：心得卡摘要是这一页的主内容，13 / 14.95 -> 15
     （索引 §4「正文 / 卡摘要 15px」）；同一张卡上的日期 .note-date 也是 15，
     不再出现「正文比日期小」。两行 clamp 的行盒随之 15 × --lh-body。 */
  font-size: 15px;
  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),内边距同步加一档;
   窄屏(手机)沿用 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); }
  .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 / .mile-now一族 / .mile-bar一族 /
   .mile-seal一族 / .mile-legend 整节随 v1.6.0 九轮 M1 退役——owner L1
   「里程碑功能相当于不要了」,浮页与入口一并下架,不留死样式。) */

/* 阳神班(v1.4.0)打卡历:本页语义是「当日有无阳神班记录」,不是练功时长。
   Components.heatmap 是通用时长热力图,其 hasData 判定与数字展示都锚定
   min>0,本页只能喂固定占位值去触发「有记录」视觉态,该数字本身无意义
   (会显示 "1.0")。组件本体是冻结件,故在本页作用域内隐藏这个数字,
   格子只保留日期与有无记录/是否违规的视觉区分。 */
.ys-heatmap--nodur .gridcal-dur { display: none; }

/* ==========================================================================
   阳神班(v1.4.0)版式 —— owner 20260901 UI 令三条:
   ① 总览合成一个组件(对齐「我的」页度牒票),不再是并排三张小卡;
   ② 总览/记录/打卡历三段之间要有分隔,不能挨在一起;
   ③ 页首巨字「阳神班」逐字做光学微调——齐伋体里「阳」字面偏大。
   ========================================================================== */

/* ① 单卡总览:字段行沿用 .fieldrow 语汇(与度牒票同源),行间细分隔线 */
.ys-overview-fields { display: flex; flex-direction: column; }
.ys-overview-fields .fieldrow { padding: var(--s2) 0; }
.ys-overview-fields .fieldrow + .fieldrow { border-top: 1px solid var(--rule-weak, rgba(26,26,26,.10)); }

/* ② 节间距:三段拉开;题签行与「我的」页小节标题同调 */
.ys-section + .ys-section { margin-top: var(--s6, 32px); }
.ys-section-title {
  font-size: var(--fs-note, 13px);
  letter-spacing: .08em;
  color: var(--ink-weak, rgba(26,26,26,.55));
  margin: 0 0 var(--s3, 12px);
  padding-bottom: var(--s2, 8px);
  border-bottom: 1px solid var(--rule-weak, rgba(26,26,26,.10));
}

/* ③ 巨字光学微调:整体收紧字距,「阳」单字缩 6% 并做基线补偿,使三字视觉等重。
   inline-block + transform 只影响本页标题,不动 .folio-title 基类。 */
.ys-folio-title { letter-spacing: .02em; }
.ys-folio-ch { display: inline-block; }
.ys-folio-ch--1 { font-size: .94em; transform: translateY(.012em); margin-right: .015em; }

/* 管理页阳神班节:与管理页其它区块拉开,并给一条起始界行 */
.adm-yangshen-mount { margin-top: var(--s7, 40px); }
.adm-yangshen-mount:not(:empty) { border-top: 1px solid var(--rule-weak, rgba(26,26,26,.10)); padding-top: var(--s5, 24px); }

/* ys-141 · 阳神班弟子侧作用域样式（v1.4.1）
   归 W1 一家所有；管理员侧样式一律写 ys-admin-141.css。
   只写阳神班页作用域内的选择器，禁改写全站基类。 */

/* --------------------------------------------------------------------------
   G1(v1.4.2)/F4 · 口令层
   G1 根因①：v1.4.1 在此给口令框加过文字圆点遮罩（webkit 私有遮罩属性），
   把用户正在输入的中文连同 IME 组字过程一并遮住——owner 原话「还是看不到
   输入的中文」。遮罩整条删除且回归钉禁止再现（测试对本文件做属性字面量
   扫描）：班级口令是全班共用口令，非个人密钥，明文可见即需求本身。（G1 根因②"错误提示隐形"在 ui-yangshen.js 修，走 .entry-error
   的 data-visible 既有机制，无需新样式。）
   F4：owner「横线贴框」——.ticket 内边距是 s5，输入框满宽时下划线几乎顶到
   卡片内层乌丝框。此处在卡内再收一档左右留白。
   -------------------------------------------------------------------------- */
.ys-passphrase-card .ticket-body {
  padding: var(--s2, 8px) var(--s3, 12px);
}
.ys-passphrase-input {
  margin-top: var(--s2, 8px);
}
.ys-passphrase-card .ys-passphrase-submit {
  margin-top: var(--s4, 16px);
}

/* --------------------------------------------------------------------------
   F5 · 记录浮层三道选择题题面字号增大 30-50%
   基类 .achv-row-text 用 --fs-body-sm(13px)，成就清单语境下合适，浮层语境偏小。
   本处 ×1.4 = 18.2px（+40%，落在 owner 要求的 30-50% 区间内），只影响本浮层。
   -------------------------------------------------------------------------- */
.ys-record-checks .achv-row-text {
  font-size: calc(var(--fs-body-sm, 13px) * 1.4);
  line-height: 1.5;
}
.ys-record-checks .achv-row {
  padding: var(--s3, 12px) 0;
}
.ys-record-checks .achv-row input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin-top: 5px;
}

/* 时间控件与上下两段之间留白（桌面直填格与触屏滚轮共用同一挂载点） */
.ys-time-mount {
  margin: var(--s3, 12px) 0 var(--s4, 16px);
}

/* --------------------------------------------------------------------------
   F8 · 阳神班打卡历格内：睡觉时间 + 违规红点 / 无违规黑点
   网格与格子沿用全站 .gridcal-* 语汇（Components.ysCalendar 自绘时照抄类名），
   本文件只补两样本页独有的东西：格中主角的时间文字、点的红黑语义。
   .ys-cal-time 的排布参数照 .gridcal-dur（flex:1 居中）抄，保证与全站打卡历
   的格内重心一致；.ys-cal-dot 的尺寸与基线位置照 .gridcal-dot 抄。
   -------------------------------------------------------------------------- */
.ys-cal-time {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-num);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-2);
  letter-spacing: .01em;
}
@media (min-width: 768px) {
  .ys-cal-time { font-size: 14px; }
}
.ys-cal-cell[data-future="true"] .ys-cal-time {
  color: var(--ink-3);
}
.ys-cal-dot {
  position: relative;
  top: -2px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--ink);
}
.ys-cal-dot[data-violation="true"] {
  background: var(--line-red);
}

/* --------------------------------------------------------------------------
   G3(v1.4.2) · 页首标题「阳」字光学微调
   owner 二轮验收仍判「阳」略大（QiJi 字形本身偏大，v1.4.1 的朴素排印治不了），
   令「阳整体缩小5-9%、阳和神的宽间距增加5-9%，直到截图复核对比找到最优」。
   v1.4.2 冻结 scale(.93)+0.07em；v1.4.3(H1) 依 owner「增大3%,往左上方挪
   5%左右」调到 t(-5%,-5%) s.958+0.07em；v1.4.4(J5) owner 四轮再调,逐字:
   「阳看着还是非常不是很和谐,略高了一点,间距也有点过宽,继续调整」——
   上移 5% 收敛到 2%,左移取消(左移与 0.07em 叠加即"过宽"根源),间距收到
   0.05em(仍在 v1.4.2「加宽 5-9%」带内)。scale 不动(.958,owner 未再提大小)。
   参数经 v1.4.4 矩阵(六案)+决选轮(170px 三案)选优冻结,证据图在
   阳神班-v144-图纸-20260902 目录。transform-origin 仍取基线附近(50% 78%)；
   只作用于 ysFolioTitle() 产出的 .ys-folio-yang 一个 span,其它页零影响。
   -------------------------------------------------------------------------- */
.ys-folio-yang {
  display: inline-block;
  transform: translate(0, -2%) scale(0.958);
  transform-origin: 50% 78%;
  margin-right: 0.05em;
}

/* --------------------------------------------------------------------------
   F3 历史说明（v1.4.1，保留存证）
   v1.4.0 曾在 app.css 写 .ys-folio-title / .ys-folio-ch--n 做逐字光学微调，
   owner 判观感不达标；v1.4.1 回退朴素排印后 app.css 那几条失去命中对象，属
   无害残留，不动 app.css（全站共享文件）。v1.4.2 的 G3 重新引入光学微调，
   但类名与规则全在本文件（上一节），与 app.css 残留无关。
   同理 .ys-heatmap--nodur / .adm-yangshen-mount 两条也已失去对象。
   -------------------------------------------------------------------------- */

/* ys-admin-141 · 阳神班管理员侧作用域样式（v1.4.2）
   归 W3 一家所有；弟子侧样式一律写 ys-141.css。

   v1.4.2（G2/G4/G5，owner 二轮亲验反馈）：整页改为与「管理」页同款左中右
   三栏——布局骨架直接复用 app.css 全局类（.adm-layout/.adm-rail/.adm-title/
   .adm-links/.adm-link/.adm-count--rail/.adm-main/.notes-side 族），本文件
   只写阳神班页独有的东西：账行 stat 值、设置浮层、日历范围选择器。
   v1.4.1 的「班务设置/班级总览/弟子行表」三段主区样式随 DOM 一并作废删除；
   弟子明细浮层（adm-ys-detail-*）不变，原样保留。
   ========================================================================== */

/* ---- 中栏账行（沿用全局 .adm-row/.adm-stat/.adm-name 语汇，此处只补
   阳神班字段组的值样式与行可点性） ------------------------------------- */
.ys-adm-ledger { width: 100%; }
.ys-adm-row {
  width: 100%;
  text-align: left;
  background: none;
  border-left: 0;
  border-right: 0;
  border-top: 0;
  cursor: pointer;
}
.ys-adm-row:hover { background: rgba(250, 246, 236, .9); }
/* v1.4.3(H5):.ys-adm-no(local_xxx 编码)与 168px 加宽随编码展示一并删除,
   姓名列回落全局 .adm-name-wrap 140px(管理页同款,H4 范式沿用)。 */
.ys-adm-stat { flex: 0 1 118px; min-width: 78px; }
.ys-adm-v {
  font-family: var(--font-num);
  font-size: 13.5px;
  color: var(--ink-2);
  white-space: nowrap;
}
/* 违规列：非零才标朱，零违规保持墨色——整列全红等于没有指示作用 */
.ys-adm-stat--viol[data-nonzero="1"] .ys-adm-v {
  color: var(--red-text);
  font-weight: 600;
}
.ys-adm-empty { padding: 22px 4px 6px; }

/* ---- 阳神班设置浮层（G5，图纸2 定案） -------------------------------- */
.ys-adm-settings-card {
  max-width: 560px;
  width: min(560px, calc(100vw - 48px));
  max-height: calc(100vh - 80px);
  overflow-y: auto;
}
.ys-adm-settings-body { margin-top: var(--s3, 12px); }
.ys-adm-set-k {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  letter-spacing: .14em;
  color: var(--ink-3);
  margin: 0 0 var(--s2, 8px);
}
.ys-adm-set-range {
  display: flex;
  align-items: baseline;
  gap: 14px;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: var(--lw-hair) solid rgba(201, 191, 168, .9);
  padding: 6px 2px 10px;
  cursor: pointer;
}
.ys-adm-set-range:hover .ys-adm-set-date { color: var(--ink); }
.ys-adm-set-date {
  font-family: var(--font-num);
  font-size: 19px;
  color: var(--ink-2);
}
.ys-adm-set-date--end { color: var(--ink-3); }
.ys-adm-set-sep { color: var(--ink-3); }
.ys-adm-set-code {
  margin-left: auto;
  font-family: var(--font-num);
  font-size: var(--fs-caption);
  letter-spacing: .08em;
  color: var(--ink-3);
}
.ys-adm-set-msg[data-kind="ok"] { color: var(--ink-2); }
/* v1.4.3:.ys-adm-set-btnrow(卡内保存行)删——保存钮随日历浮片走(H8);
   .ys-adm-set-div(班期与口令间虚线 hr)删——owner「有一个多余虚线」(H9)。 */
/* 虚线删除后,「当前口令」小节与班期行之间的分区改靠留白(紧邻兄弟选择器:
   班期行之后的下一小节题) */
.ys-adm-set-range + .ys-adm-set-k { margin-top: var(--s5, 24px); }
.ys-adm-set-pass {
  font-family: var(--font-body);
  font-size: 19px;
  letter-spacing: .06em;
  color: var(--ink);
  margin: 0 0 var(--s4, 16px);
}
.ys-adm-set-passfield { max-width: 360px; }
/* v1.4.4(J4,图纸4):设置卡按钮全部收窄自适应宽——owner「修改口令的UI排版
   布局非常丑」根因即满宽 book-submit 黑条/幽灵条错位堆叠。 */
.ys-adm-actbtn {
  min-width: 132px;
  padding-left: var(--s5, 24px);
  padding-right: var(--s5, 24px);
}
.ys-adm-settings-card .ys-adm-actbtn { margin-top: var(--s3, 12px); }
.ys-adm-btnrow { display: flex; align-items: center; gap: 12px; }
.ys-adm-btnrow .ys-adm-actbtn { margin-top: 0; }
/* v1.4.5(K1):设置卡纵排,「关闭」沉底靠右——与浮片保存钮同一条底线 */
.ys-adm-settings-card { display: flex; flex-direction: column; }
.ys-adm-settings-card .ys-adm-settings-body { margin-bottom: var(--s4, 16px); }
.ys-adm-set-close { display: flex; margin-left: auto; margin-top: auto; }
.ys-adm-pass-confirm {
  margin-top: var(--s3, 12px);
  padding: var(--s4, 16px);
  border: var(--lw-hair) solid var(--line-red);
  border-radius: var(--r-card, 8px);
  background: rgba(177, 59, 46, .04);
}
.ys-adm-pass-warn {
  color: var(--red-text);
  margin: 0 0 var(--s3, 12px);
}
.ys-adm-pass-msg[data-kind="ok"] { color: var(--ink-2); }

/* ---- 日历范围选择器（G5，gridcal 语汇；同一本日历点两次定起止）
   v1.4.3(H8):容器由卡内 calwrap 改为 duo 里的横向浮片 .ys-adm-calpop——
   点开日历不再竖向撑开设置卡,浮片并排出现在卡右侧(图纸3 定案,380px);
   窄屏 duo 折行回落卡下。duo 自身 pointer-events:none,两片之间的空隙点击
   穿透到 overlay,「点外关闭」不破。 ------------------------------------ */
/* v1.4.4(J1,owner「确保屏幕自适应,上下间距随着屏幕适应居中」):overlay 纵向
   可滚,直接子件(卡或 duo)上下 margin:auto——空间足够时上下留白严格对称,
   内容超屏高时自动回落顶对齐+overlay 滚动,不再被 flex 居中溢出顶裁。 */
.book-auth-overlay.ys-adm-overlay {
  align-items: flex-start;
  overflow-y: auto;
}
.book-auth-overlay.ys-adm-overlay > .book-card {
  margin-top: auto;
  margin-bottom: auto;
}

/* 右列内日历不套第二层框(v1.4.3 浮片时代规则沿用) */
.ys-adm-calpop .ys-adm-cal {
  margin: 0;
  border: 0;
  border-radius: 0;
  padding: 0;
  background: none;
}
.ys-adm-cal {
  margin: var(--s4, 16px) 0 var(--s2, 8px);
  border: var(--lw-hair) solid rgba(201, 191, 168, .7);
  border-radius: var(--r-card, 8px);
  padding: 14px 16px;
  background: rgba(250, 246, 236, .6);
}
.ys-adm-cal-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.ys-adm-cal-month {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .1em;
}
.ys-adm-cal-navbtn {
  background: none;
  border: 0;
  font-size: 15px;
  color: var(--ink-3);
  cursor: pointer;
  padding: 2px 10px;
}
.ys-adm-cal-navbtn:hover { color: var(--ink); }
.ys-adm-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  /* v1.4.8 二轮(owner「切一个按键画面抖动一次」):行高定死、恒 6 周行——
     4/5/6 周的月份切换与浮片其它状态切换都不再改变浮片高度 */
  grid-template-rows: 24px repeat(6, 31px);
  gap: 4px;
}
/* v1.6.0 六轮 X5（X2 复核员留件 + 索引 §4「三栏页面内最小字号 13」）：星期表头
   10.5 -> 13。本类由 _buildRangeCalendar 共用，一处改三处受益：阳神班设置浮层
   月历、管理页右栏双月浮层 .adc-calpop、弟子详情浮窗 .mdp-calpop。
   24px 的表头行高与 31px 的日格不动（13px 文字在 24 的行盒里不触边），
   浮片恒 6 周行的总高因此一格不变。 */
.ys-adm-cal-h {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-3);
  text-align: center;
  padding: 0;
  line-height: 24px;
}
.ys-adm-cal-c {
  font-family: var(--font-num);
  font-size: 13px;
  text-align: center;
  padding: 0;
  line-height: 31px;
  border: 0;
  border-radius: 5px;
  background: none;
  color: var(--ink);
  cursor: pointer;
}
.ys-adm-cal-c:hover { background: rgba(201, 191, 168, .25); }
.ys-adm-cal-c--pad { visibility: hidden; pointer-events: none; }
.ys-adm-cal-c--in { background: rgba(201, 191, 168, .32); }
.ys-adm-cal-c--start,
.ys-adm-cal-c--end {
  background: var(--ink);
  color: var(--paper-2, #faf6ec);
  font-weight: 600;
}
/* v1.4.5(K2):.ys-adm-cal-foot/.ys-adm-cal-hint/.ys-adm-cal-clearend 随脚注
   删除(owner「圆框里面属于废话 去掉」)。 */

/* ---- 弟子明细浮层（只读，v1.4.1 原样保留） --------------------------- */
/* 八轮 Z1（owner K3 逐字「阳神班卡片宽度 宽一点，同日不要换行，如截图1」）：
   截图一里「超时: 否」被挤到第二行，成因不是宽度不够，是栅格少了一列——
   v1.6.0 N3 在行里插了「午功」这一格（一行从五个节点变六个），列声明
   `… repeat(3, 1fr)` 却没跟着改，第六个节点按 grid 自动流落到下一行。
   两处一起改：列数补到 4（四个 flag 一格一列且等宽），卡宽 520 -> 560 让四格
   在同一行里各自有余量。
   宽度算式（1440 / 1280 / 1024 同一个数，卡是定宽不随视口变）：
     卡内容盒 = 560 - 2×24(.ticket padding --s5) = 512
     日期列 max-content「2026-09-01」13px 等宽数字 ≈ 76 -> 取下限 84
     睡时列 max-content「21:34」≈ 34 -> 取下限 52
     列间 5 道 × 8 = 40
     余给四格 = 512 - 84 - 52 - 40 = 336，每格 84
     单格最宽文字 = 劣态「起床功：否」5 字 × 12px × 1.1(劣态放大) = 66 < 84
   故四项 + 日期时间在 1440 / 1280 / 1024 都是一行，且每格还留 18px 余量。 */
.adm-ys-detail-card {
  max-width: 560px;
  max-height: calc(100vh - 80px);
  overflow-y: auto;
}
.adm-ys-detail-list {
  margin: var(--s3, 12px) 0;
}
.adm-ys-detail-row {
  display: grid;
  /* 八轮 Z1：repeat(3, 1fr) -> repeat(4, 1fr)，日期 / 睡时 / 起床功 / 午功 /
     同房 / 超时 六个节点一一对位，不再有节点被挤到第二行。 */
  grid-template-columns: minmax(84px, auto) minmax(52px, auto) repeat(4, 1fr);
  align-items: baseline;
  gap: 8px;
  padding: 9px 2px;
  border-bottom: var(--lw-hair) dashed rgba(201, 191, 168, .7);
}
.adm-ys-detail-row:last-child { border-bottom: none; }
.adm-ys-detail-date {
  font-family: var(--font-num);
  font-size: 13px;
  color: var(--ink);
}
.adm-ys-detail-sleep {
  font-family: var(--font-num);
  font-size: 13px;
  color: var(--ink);
}
.adm-ys-detail-flag {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-3);
  white-space: nowrap;
}
/* v1.4.4(J3,owner 逐字「起床功 否 / 违规 是 / 超时 是 这三种都是需要加粗
   字体加大10%+标红色」):劣态值加粗+字号×1.1+朱红。 */
.adm-ys-detail-flag[data-bad="1"] {
  color: var(--red-text);
  font-weight: 600;
  font-size: calc(var(--fs-caption) * 1.1);
}
.adm-ys-detail-card .book-submit { margin-top: var(--s3, 12px); }

/* ---- 窄屏降级 --------------------------------------------------------- */
@media (max-width: 760px) {
  /* 账行改逐人成块（v1.4.1 实拍 390px 后的定案思路沿用）：姓名整行，
     六个 stat 各占一行、label 左值右。全局 .adm-row 在窄屏仍是 flex，
     此处覆写为块排。 */
  .ys-adm-row { display: block; padding: 14px 10px 13px; }
  .ys-adm-namewrap { display: block; margin-bottom: 8px; }
  .ys-adm-stat {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 3px 0;
  }
  /* v1.4.8 二轮:格高由栅格行定死(31px),窄屏不再加 padding */
  .ys-adm-set-code { display: none; } /* 窄屏班期行放不下编号，信息不关键 */
  .adm-ys-detail-row {
    grid-template-columns: minmax(84px, auto) minmax(52px, auto);
    row-gap: 4px;
  }
}

/* ---- v1.4.8(M3/M4)豁免面板(图纸 v148 定案,阳神班-v148-图纸-20260904) ----
   落点=日历浮片格子与「保存班期」之间(owner 截图1 红框)。两态签沿录入面板
   题签语汇(.entry-mode-tab:底线+选中签下 28px 短朱线);开关=iOS 风格自绘
   (owner「可以参考 ios的开关键」):关=衬纸底乌丝框、开=浓墨底,滑钮票面色;
   日历格豁免标记:浓墨实点=完全 / 空心环=睡觉,反白格(起止日)上改票面色。 */
.ys-adm-exempt { margin-top: var(--s3, 12px); }
.ys-adm-mode { display: flex; align-items: stretch; }
.ys-adm-mode-tab {
  position: relative;
  flex: 1;
  height: 34px;
  background: none;
  border: 0;
  border-bottom: var(--lw-line) solid var(--line);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  cursor: pointer;
  letter-spacing: .04em;
}
.ys-adm-mode-tab[aria-selected="true"] {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: transparent;
}
.ys-adm-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);
}
/* 面板槽位:body 常驻文档流只切 visibility,摘要绝对定位盖在同一槽位——
   班期态/未选日/完全/睡觉 四态浮片高度完全一致(owner 二轮:零抖动) */
.ys-adm-exempt-slot { position: relative; }
.ys-adm-exempt-body {
  padding: var(--s3, 12px) 2px 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ys-adm-exempt-body[aria-hidden="true"] { visibility: hidden; }
.ys-adm-exempt-date {
  font-family: var(--font-num);
  font-size: 15px;
  color: var(--ink);
  margin: 0 0 4px;
  letter-spacing: .04em;
  /* 四轮:日期(等宽数字)与「在日历上点选一天」(文楷)行高不同会差 1-2px,定死 */
  height: 24px;
  line-height: 24px;
  white-space: nowrap;
  overflow: hidden;
}
.ys-adm-exempt-date[data-empty="1"] {
  font-family: var(--font-body);
  color: var(--ink-3);
  letter-spacing: .06em;
}
.ys-adm-switchrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
}
.ys-adm-switchrow-k {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink);
}
.ys-switch {
  position: relative;
  width: 44px;
  height: 25px;
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  border: var(--lw-line) solid var(--line);
  background: var(--paper-3);
  padding: 0;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.ys-switch i {
  position: absolute;
  top: 2px; left: 2px;
  width: 19px; height: 19px;
  border-radius: 50%;
  background: var(--paper-2);
  box-shadow: 0 1px 2px rgba(26, 26, 26, .28);
  transition: transform .15s;
}
.ys-switch[aria-checked="true"] { background: var(--ink); border-color: var(--ink); }
.ys-switch[aria-checked="true"] i { transform: translateX(19px); }
.ys-switch:disabled { opacity: .45; cursor: default; }
.ys-adm-exempt-delay {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 2px 0 6px;
}
.ys-adm-exempt-delay[data-visible="0"] { visibility: hidden; }
.ys-adm-exempt-delay-k {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  margin-right: auto;
}
.ys-adm-exempt-delay-in {
  width: 64px;
  font-family: var(--font-num);
  font-size: 14px;
  text-align: right;
  padding: 4px 8px;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper-2);
  color: var(--ink);
}
.ys-adm-exempt-delay-unit {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
}
/* 四轮(owner「"已改动，点「保存」生效" 出现这个字后 上下高度还是出现了微小的
   增高」):站内 .entry-error 自带 8px 上边距+加粗行高,显示时超过 min-height——
   槽位改为定死高度且裁切,提示行零外边距、行高=槽高,单行省略 */
.ys-adm-exempt-msgslot { height: 28px; overflow: hidden; }
.ys-adm-exempt-msg {
  margin: 0;
  line-height: 28px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ys-adm-exempt-msg[data-kind="ok"] { color: var(--ink-2); }
.ys-adm-cal-c { position: relative; }
.ys-adm-cal-c--ex-full::after,
.ys-adm-cal-c--ex-sleep::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 2px;
  transform: translateX(-50%);
  width: 5px; height: 5px;
  border-radius: 50%;
  box-sizing: border-box;
}
.ys-adm-cal-c--ex-full::after { background: var(--ink); }
.ys-adm-cal-c--ex-sleep::after { border: 1.5px solid var(--ink); }
.ys-adm-cal-c--start.ys-adm-cal-c--ex-full::after,
.ys-adm-cal-c--end.ys-adm-cal-c--ex-full::after { background: var(--paper-2, #faf6ec); }
.ys-adm-cal-c--start.ys-adm-cal-c--ex-sleep::after,
.ys-adm-cal-c--end.ys-adm-cal-c--ex-sleep::after { border-color: var(--paper-2, #faf6ec); }
.ys-adm-cal-c--picked { box-shadow: inset 0 0 0 1.5px var(--ink); }
.ys-adm-cal-c:disabled { color: var(--ink-ph); cursor: default; }
.ys-adm-cal-c:disabled:hover { background: none; }

/* ---- v1.4.8 二轮整体重排(owner「上下宽度不一致…画面抖动」「左侧下方空白
   明显…允许整体重做大改」「保存班期应该变成 保存」):一张宽卡两列——左列
   班期/口令/本期豁免清单,右列日历常驻+两态签+定高面板;底部一条共用动作行
   「关闭」「保存」。两列各自 flex-start,不再互相拉伸;高度只由右列决定且恒定。 */
.book-auth-overlay .ys-adm-settings-card--wide {
  max-width: 980px;
  width: min(980px, calc(100vw - 48px));
  padding: 22px 26px 20px;
}
.ys-adm-settings-cols {
  display: flex;
  /* 三轮(owner「上下高度要固定 且固定居中/不允许因为切换某个值而改变」):
     卡高只由右列(恒定)决定——左列拉伸到与右列等高,清单占左列剩余空间并在
     自己区域内滚动(owner「允许超过一定数量之后加一个滑动块」),条数多少
     都不再改变卡高与居中位置 */
  align-items: stretch;
  flex-wrap: wrap;
  gap: 32px;
  margin-top: var(--s3, 12px);
}
.ys-adm-settings-cols > .ys-adm-settings-body {
  flex: 1 1 320px;
  min-width: 260px;
  min-height: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
}
.ys-adm-settings-cols > .ys-adm-settings-body > * { flex: 0 0 auto; }
/* 左列纵向 flex 后按钮会被交叉轴拉满宽——J4(owner「按钮不再满宽」)钉回内容宽 */
.ys-adm-settings-cols > .ys-adm-settings-body > .ys-adm-actbtn { align-self: flex-start; }
.ys-adm-settings-cols > .ys-adm-calpop {
  flex: 0 0 348px;
  width: 348px;
  max-width: 100%;
  border-left: var(--lw-hair) solid rgba(201, 191, 168, .7);
  padding-left: 28px;
}
.ys-adm-set-foot {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 12px;
  margin-top: var(--s4, 16px);
  padding-top: var(--s3, 12px);
  border-top: var(--lw-hair) solid rgba(201, 191, 168, .7);
}
.ys-adm-set-foot .ys-adm-actbtn { margin-top: 0; }
.ys-adm-set-foot .ys-adm-set-close { margin-left: 0; margin-top: 0; }
.ys-adm-set-save { min-width: 132px; }
/* 左列「本期豁免」清单:日期等宽 + 类型淡墨,虚线分行;点一行=切豁免签并选中该日 */
.ys-adm-exlist-k { margin-top: var(--s5, 24px); }
.ys-adm-exlist {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;          /* 占左列剩余空间(覆盖上方的 0 0 auto) */
  min-height: 96px;     /* 至少两行可见 */
  overflow-y: auto;     /* 超出在区域内滚动:滚轮可滑、出滚动条 */
  padding-right: 4px;
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 191, 168, .9) transparent;
}
.ys-adm-settings-cols > .ys-adm-settings-body > .ys-adm-exlist { flex: 1 1 0; }
.ys-adm-exlist-row { flex: 0 0 auto; }
.ys-adm-exlist-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  width: 100%;
  background: none;
  border: 0;
  border-bottom: var(--lw-hair) dashed rgba(201, 191, 168, .7);
  padding: 7px 2px;
  text-align: left;
  cursor: pointer;
}
.ys-adm-exlist-row:hover { background: rgba(250, 246, 236, .9); }
.ys-adm-exlist-date { font-family: var(--font-num); font-size: 13.5px; color: var(--ink); }
.ys-adm-exlist-kind { font-family: var(--font-body); font-size: var(--fs-body-sm); color: var(--ink-2); }
.ys-adm-exlist-empty {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  margin: 4px 2px 0;
}
/* 班期态读数:盖在豁免 body 同一槽位上(绝对定位),四态零抖动 */
.ys-adm-exempt-readout {
  position: absolute;
  left: 0; right: 0; top: 0;
  padding: var(--s3, 12px) 2px 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  visibility: hidden;
}
.ys-adm-exempt[data-mode="range"] .ys-adm-exempt-readout { visibility: visible; }
.ys-adm-readrow { padding: 8px 0; }
.ys-adm-readrow-v { font-family: var(--font-num); font-size: 14px; color: var(--ink); }
@media (max-width: 760px) {
  .ys-adm-settings-cols { gap: 20px; }
  /* 窄屏两列纵排,左列不再与右列等高:清单改为封顶高度内滚动 */
  .ys-adm-settings-cols > .ys-adm-settings-body > .ys-adm-exlist { flex: 0 0 auto; max-height: 240px; }
  .ys-adm-settings-cols > .ys-adm-calpop {
    flex: 1 1 100%;
    width: 100%;
    border-left: 0;
    padding-left: 0;
    border-top: var(--lw-hair) solid rgba(201, 191, 168, .7);
    padding-top: var(--s4, 16px);
  }
}

/* lgj-149 · v1.4.9 两处新界面的作用域样式（20260910）
   ① 模拟弟子视角横幅 .sim-bar（N2）
   ② 「我的」页请假浮层 .leave-card / .lv-*（N3）

   纪律：本文件按 build.js 的拼接顺序排在 app.css / ys-141.css /
   ys-admin-141.css 之后，覆盖既有基类只用作用域内选择器，不改上游文件一个字
   （与 ys-141.css 拆文件同源的做法：并行施工线零文件交集）。

   定高纪律（v1.4.8 owner 四轮 UI 反馈的教训，逐条落在下面）：
     - 会随状态/数据变高的区域一律 height 定死，不用 min-height；
     - 两态切换用 visibility，不用 display（display 一切换就重排，必抖）；
     - 清单条数增长不许把卡撑高，超出在区域内滚动；
     - 提示文案出现/消失不许改变高度（提示槽定高 + overflow 裁切）。

   六轮 X4（20260917，owner「优化一下截图11，请假和迟到做成两个区域，请假需要写
   理由，最多30字。迟到不需要写理由，但是需要双重确认」）在本文件里的四件事：
     ① 左半拆成「请假区 / 迟到区」两个区块，各自一行 16px 600 节题 + 一道乌丝收底
        （.lv-sec）；迟到区一句 13px 淡墨说明（.lv-note）+ 一枚幽灵键（.lv-late），
        二次确认浮层复用站内既有的 showConfirmOverlay，本文件零新浮层样式；
     ② 四轮那套「请假 | 迟到」二选一分段（.lv-kindslot / .lv-kind / .lv-kindtab）
        连同窄屏两条收窄规则整组删除——类型现在由「按哪个区的键」决定；
     ③ 两列定高由 280 重算到 412，月历格 38 → 60（逐项算式见下方 §三 头注），
        原因框槽 76 → 66（30 字上限两行足够）；
     ④ 本段内所有 11 / 12px 一律升到 13（六轮字号标准），每处所在行的定高逐条复核。

   四轮（20260916，owner「所有的请假字样 都换成 请假迟到……相当于新增了一个
   "迟到"的概念，依靠弟子主动报备」）在本文件里的三件事：
     ① 新增类型分段控件 .lv-kind（请假 | 迟到），笔法与三轮管理页配置面板的
        .adc-dir 完全同一支笔（32 高、乌丝描边、3px 圆角、生效格衬纸底 600）；
        它落在既有 34px 动作行行首的 .lv-kindslot 定高槽里——两列 280 的高度
        由右列月历定死，新控件一个像素都不许撑高卡；
     ② 只读块题行拆成「原因」+ 右端类型签；清单行的「·」换成类型签；
     ③ 本浮层零朱：请假与迟到是同一支笔的两档中性事实（四轮工单契约 5），
        原先把「已请假」染朱的三处（状态 pill、撤销键 hover、已请假日格与
        选中且已请假日格）一并退回墨阶；唯一保留的朱是 .lv-hint[data-kind="bad"]，
        那是报错文案，不是请假状态。
   ========================================================================== */

/* ============================================================
   一、模拟弟子视角横幅（N2）
   固定在视口顶端，全站每页都在；#app 同步让出 36px，.toc--sticky 的吸顶位
   下移一档，避免玻璃药丸导航钻到横幅底下。
   ============================================================ */

.sim-bar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 60; /* > .tab-paper(40) > .toc--sticky(30) */
  height: 36px;
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: 0 var(--s4);
  background: var(--paper-2);
  border-bottom: var(--lw-line) solid var(--line-red);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-2);
}
.sim-bar-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--line-red);
  flex: 0 0 auto;
}
.sim-bar-text {
  color: var(--ink);
  font-weight: 600;
  flex: 0 0 auto;
}
.sim-bar-long {
  color: var(--ink-3);
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.sim-bar-exit {
  flex: 0 0 auto;
  margin-left: auto;
  height: 24px;
  padding: 0 12px;
  border: var(--lw-line) solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out);
}
.sim-bar-exit:hover { background: var(--paper-3); }

body[data-sim="1"] #app { padding-top: 36px; }
body[data-sim="1"] .toc--sticky { top: 46px; }

/* 窄屏：长说明让位，只留「模拟弟子视角」+ 退出按钮 */
@media (max-width: 860px) {
  .sim-bar-long { display: none; }
}

/* ============================================================
   二、「我的」页入口砖：v1.4.9 增「请假」后由三枚变四枚
   app.css §28 的 .me-entries 三列规则原样保留，这里按拼接顺序覆盖列数。
   ============================================================ */

.me-entries { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 560px) {
  .me-entries { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   三、请假浮层（N3；三轮设计复核后重做）
   二轮实拍暴露的毛病与对策：已请假态还画着一个禁用的空输入框（占位字写「必填」）
   → 两态各画各的；两个日期抬头叠着 → 合成一行「选中 …」＋状态 pill；撤销和确认
   同样是黑底 → 撤销降成幽灵键；选中格是实心黑块 → 改 2px 墨色内描边；月首月末的
   空格子还画着边框 → 边框透明；通栏清单横向一大片空白 → 清单收进左列。
   结构：一张宽卡 → 两列（左＝抬头/请假单/按钮行/已请假清单，右＝月历）→ 关闭。
   定高（六轮 X4 契约 5 重算，owner「优化一下截图11，请假和迟到做成两个区域」）：
   左列由「抬头 + 一张报备单」变成「抬头 + 请假区 + 迟到区 + 已报备清单」四段，
   再也塞不进原来的 280，故两列行整体由 280 抬到 412，月历格随之由 38 抬到 60
   （412 ＝ 32 月历抬头 + 20 星期行 + 6×60），两列仍严格等高、右列下方零空带
   （owner 六轮 H4 刚点名过「不要留空间，对齐下沿」）。
   左列 412 的逐项算式：
     32 抬头
     + 8 + 22 请假节题（16px 600 + 一道乌丝收底）
     + 8 + 66 原因框（30 字上限，2 行足够：13 × 1.5 × 2 ＝ 39 + 16 内边距 + 2 描边）
     + 12 + 34 「确认请假」动作行
     + 16 + 22 迟到节题
     + 8 + 20 「迟到不需要写原因」说明句（13px --ink-3）
     + 8 + 34 「登记迟到」动作行
     + 12 + 20 「已报备」清单标题
     + 90 清单（3 行 × 30，整行倍数，底部不切半行）
     ＝ 412
   左列各块定高，清单吃掉剩余的 90px 并内滚；提示与字数共用按钮行左侧同一个定高
   槽。全篇不出现 min-height。
   ============================================================ */

.book-card.leave-card {
  max-height: calc(100vh - var(--s4) * 2);
  overflow-y: auto;
}
@media (min-width: 900px) {
  .book-card.leave-card { width: 780px; max-width: 94vw; padding: var(--s5) var(--s5) var(--s4); }
}

/* ---- 两列 ---- */
.lv-cols {
  display: grid;
  grid-template-columns: 1fr 378px;
  gap: var(--s5);
  height: 412px; /* = 右列月历的净高：32＋20＋6×60；左列逐项算式见本节头注 */
}
.lv-left {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.lv-right { min-width: 0; }

/* 窄屏：两列落成一列，月历排在请假单下面 */
@media (max-width: 899px) {
  .lv-cols { grid-template-columns: 1fr; height: auto; gap: var(--s3); }
}

/* ---- 抬头：一行「选中 <日> <周几>」＋状态 pill（今日行与「今天请假」已删） ---- */
.lv-head {
  height: 32px;
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  min-width: 0;
}
/* 六轮字号标准（六轮关键事实索引 §4「字段标签 / 副说明 一律 13」）：本段内原先
   的 11 / 12 一律升到 13（--fs-body-sm），各自所在行的定高逐条复核过，见下方每处
   的行高注。 */
.lv-head-label { font-size: var(--fs-body-sm); color: var(--ink-3); white-space: nowrap; }
.lv-head-date {
  font-family: var(--font-num);
  font-size: var(--fs-body);
  color: var(--ink);
  white-space: nowrap;
}
.lv-head-week { font-size: var(--fs-body-sm); color: var(--ink-3); white-space: nowrap; }
.lv-head-pill {
  align-self: center;
  height: 20px;
  line-height: 18px;
  padding: 0 8px;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-pill);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  white-space: nowrap;
}
/* 四轮：已报备是中性事实，不是告警——同一支笔深一档（法则④），零朱。
   两种类型（请假 / 迟到）共用这一档，差别写在文案里而不是颜色里。 */
.lv-head-pill[data-on="1"] { border-color: var(--ink); color: var(--ink); font-weight: 600; }

/* ---- 请假单：一个定高槽，两态各放各的控件（不共用输入框） ---- */
/* 六轮 X4：原因上限由 100 收到 30 字，两行足够，槽由 76 收到 66（算式见头注）。
   两态仍共用这一个定高槽：textarea 与只读块都是 66，切态不改高度。 */
.lv-form { height: 66px; margin-top: 8px; }
.lv-reason {
  display: block;
  width: 100%;
  height: 100%; /* 槽定高 76px＝3 行，理由框不再吃满左列（二轮那块大空洞的来源） */
  box-sizing: border-box;
  padding: 8px 10px;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-card);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.5;
  resize: none;
  outline: none;
}
.lv-reason::placeholder { color: var(--ink-ph); }
.lv-reason:focus { border-color: var(--ink-3); }
/* 已请假态的只读读出块：不是输入控件，就别长得像输入框（无描边、衬纸底） */
/* 六轮 X4：槽由 76 收到 66，只读块的内边距随之 8 → 6，正文两行的高度 40 → 36
   （6 + 16 题行 + 2 + 36 正文 + 6 ＝ 66，一个像素不溢出）。 */
.lv-read {
  height: 100%;
  box-sizing: border-box;
  padding: 6px 10px;
  border-radius: var(--r-card);
  background: var(--paper-2);
  overflow: hidden;
}
.lv-read-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  height: 16px;
  overflow: hidden;
}
.lv-read-label {
  display: block;
  height: 16px;
  line-height: 16px;
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}
/* 类型签：淡墨文字，零底色零描边（它是一条事实，不是状态告警）。
   六轮字号标准：11 → 13，题行仍定高 16。 */
.lv-read-kind {
  flex: 0 0 auto;
  height: 16px;
  line-height: 16px;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  white-space: nowrap;
}
.lv-read-body {
  margin: 2px 0 0;
  height: 36px;
  font-size: var(--fs-body-sm);
  line-height: 18px;
  color: var(--ink);
  overflow: hidden;
}
.lv-read[data-empty="1"] .lv-read-body { color: var(--ink-ph); }

/* ---- 区块节题（六轮 X4 契约 5）：请假 / 迟到两区各一行 ------------------
   owner「请假和迟到做成两个区域」。区界不用卡框、不用底色（三层纸法则：这里是
   同一张纸上的两段，不是两张纸），只用「16px 600 的题 + 一道乌丝收底」——与下方
   「已报备」清单标题那根顶线同一支笔，全卡因此只有一种分隔写法。
   定高 22（16 × 1.25 ＝ 20，含那道 hairline 取 22），两区的题一个像素不差。 */
.lv-sec {
  margin: 8px 0 0;
  height: 22px;
  line-height: 20px;
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-sub);
  font-weight: 600;
  color: var(--ink);
  border-bottom: var(--lw-hair) solid var(--line);
}
/* 迟到区的题与上一区的动作行之间留一档更大的间距（16 > 8）：两区之间的距离要
   大于区内各行的距离，区块感才立得住（对齐 / 平行 / 垂直，owner 六轮原话）。 */
.lv-actrow + .lv-sec { margin-top: 16px; }
/* 迟到区那句说明：13px 淡墨一行，定高 20，不带任何图标与感叹号——它是一条事实，
   不是一条警告。 */
.lv-note {
  margin: 8px 0 0;
  height: 20px;
  line-height: 20px;
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}
/* 迟到动作行：与请假动作行同高 34，但只有右端一枚幽灵键（全卡唯一的黑底主按钮
   仍然只有「确认请假」那一枚，法则二）。
   选择器写成两个类叠用（而不是单写 .lv-actrow--late）：.lv-actrow 的
   margin-top / justify-content 排在本段之后，同特指度下后写的会盖回去。 */
.lv-actrow.lv-actrow--late { margin-top: 8px; justify-content: flex-end; }
.lv-late {
  flex: 0 0 auto;
  height: 34px;
  padding: 0 16px;
  font-size: var(--fs-body-sm);
  font-weight: 400;
  color: var(--ink-2);
}
.lv-late:hover:not(:disabled) { color: var(--ink); border-color: var(--ink); background: transparent; }
/* 选中的那天已经报备过：这一区整个不可用（要改先取消报备）。禁用态只降墨阶，
   不换颜色、不加说明行——一行说明会把两区的定高账全部推翻。 */
.lv-late:disabled { color: var(--ink-ph); cursor: default; }

/* ---- 按钮行：左＝类型分段控件定高槽，中＝字数/提示同一个定高槽，
       右＝本态唯一的动作键 ---- */
.lv-actrow {
  height: 34px;
  /* 四轮：主按钮不再贴着理由框（owner 原话「确认请假 不要贴着框」）。
     4px→12px 的 8px 从上下两处 12px→8px 的间距里匀出来，清单仍是整整 90px＝3 行，卡高不变 */
  margin-top: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
}
.lv-hint {
  min-width: 0;
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.lv-hint[data-kind="count"] { font-family: var(--font-num); color: var(--ink-ph); }
.lv-hint[data-kind="bad"] { color: var(--line-red); }
.lv-confirm {
  flex: 0 0 auto;
  height: 34px;
  padding: 0 22px;
  font-size: var(--fs-body-sm);
}
/* 撤销不与主动作平权：幽灵描边，hover 才转朱字（黄金法则②的层级） */
.lv-cancel {
  flex: 0 0 auto;
  height: 34px;
  padding: 0 16px;
  font-size: var(--fs-body-sm);
  font-weight: 400;
  color: var(--ink-2);
}
.lv-cancel:hover { color: var(--ink); border-color: var(--ink); background: transparent; }

/* ---- 月历 ---- */
.lv-cal-head {
  height: 32px; /* 与左列抬头同一基线 */
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.lv-cal-title {
  font-family: var(--font-num);
  font-size: var(--fs-body-sm);
  color: var(--ink);
}
.lv-cal-navs { display: flex; align-items: center; gap: 2px; }
.lv-cal-nav {
  width: 28px; height: 28px;
  border: 0;
  background: none;
  color: var(--ink-2);
  font-size: var(--fs-sub);
  line-height: 1;
  cursor: pointer;
}
.lv-cal-nav:hover { color: var(--ink); }
.lv-cal-dow {
  height: 20px;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}
/* 恒 6 行：翻月/有无补白都不改高度。
   六轮 X4：左列拆两区之后定高 412，月历格随之由 38 抬到 60（32 + 20 + 6×60 ＝
   412），两列严格等高、右列下方零空带；格子 54 宽 × 60 高，日数字与今日标点的
   写法一个值未改。 */
.lv-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: repeat(6, 60px);
}
.lv-cal-cell {
  height: 60px;
  border: 0;
  border-right: var(--lw-hair) solid var(--line);
  border-bottom: var(--lw-hair) solid var(--line);
  background: transparent;
  font-family: var(--font-num);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  cursor: pointer;
  position: relative;
  transition: background var(--t-fast) var(--ease-out);
}
/* 外框也由格子自己画（首列补左线、首行补顶线）：栅格容器一根线都不画，空格子
   才能连外框一起隐形——否则月末那一整行还剩一条容器左线吊在那里；格子只在自己
   缺的那一边补线，不会与右/下线重叠成双线 */
.lv-cal-cell:nth-child(7n+1) { border-left: var(--lw-hair) solid var(--line); }
.lv-cal-cell:nth-child(-n+7) { border-top: var(--lw-hair) solid var(--line); }
.lv-cal-cell:hover:not(:disabled) { background: var(--paper-3); }
.lv-cal-cell:disabled { cursor: default; color: var(--ink-ph); }
/* 月首前/月末后的空格子：格子还在（恒 6 行定高），但一根线都不画——二轮实拍里
   末行一整排空框像没渲染完 */
.lv-cal-cell[data-empty="1"] {
  background: transparent;
  color: transparent;
  border-color: transparent;
}
.lv-cal-cell[data-today="1"] { font-weight: 600; color: var(--ink); }
.lv-cal-cell[data-today="1"]::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 4px;
  width: 10px; height: 1px;
  transform: translateX(-50%);
  background: var(--ink-3);
}
/* 四轮：已报备（请假或迟到）＝衬纸底 + 浓墨 600，零朱、零额外描边——
   格子本身已经有一道乌丝，再套一圈描边就是框打架（SPEC §11.1）。 */
.lv-cal-cell[data-leave="1"] {
  background: var(--paper-3);
  color: var(--ink);
  font-weight: 600;
}
/* 选中的那天：同一支笔更深一档——2px 墨色内描边 + 加粗，不再实心黑块反白（法则④） */
.lv-cal-cell[data-picked="1"] {
  font-weight: 600;
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--ink);
}
/* 四轮：选中且已报备＝衬纸底（已报备那档）+ 2px 墨色内描边（选中那档），
   两种记号各管一层，不再靠换色区分。 */
.lv-cal-cell[data-picked="1"][data-leave="1"] {
  background: var(--paper-3);
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--ink);
}

/* ---- 「已报备」清单（收进左列，吃掉剩余空间，定高内滚） ---- */
.lv-list-title {
  margin: 12px 0 0;
  height: 20px;
  line-height: 20px;
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  /* 这根下沿线就是清单的顶线：清单本体零边框，flex 分到的 90px 才是整整 3 行，
     底部不会切出半行（v1.4.8 的教训：切半行看着像渲染坏了） */
  border-bottom: var(--lw-hair) solid var(--line);
}
.lv-list {
  flex: 1 1 0; /* 左列剩余的 90px＝3 行×30px；卡高只由右列月历决定 */
  overflow-y: auto;
}
.lv-list-row {
  height: 30px;
  display: flex;
  align-items: center;
  gap: var(--s2);
  border-bottom: var(--lw-hair) solid var(--line);
}
.lv-list-date {
  flex: 0 0 auto;
  font-family: var(--font-num);
  font-size: var(--fs-body-sm);
  color: var(--ink);
}
.lv-list-week { flex: 0 0 auto; font-size: var(--fs-body-sm); color: var(--ink-3); }
/* 四轮：原先分隔用的「·」换成类型签（请假 / 迟到），淡墨文字，零底色（六轮字号
   标准：11 → 13，行高 30 不变）。
   它承载信息，比一个装饰性圆点值那点横向空间。 */
.lv-list-kind {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  white-space: nowrap;
}
.lv-list-reason {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.lv-list-reason[data-empty="1"] { color: var(--ink-ph); }
/* 取消平时不显形，hover 该行才出现在行尾（法则③：次要动作不常驻） */
.lv-list-cancel {
  flex: 0 0 auto;
  visibility: hidden;
  border: 0;
  background: none;
  color: var(--ink-3);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  cursor: pointer;
  padding: 0 2px;
}
.lv-list-row:hover .lv-list-cancel { visibility: visible; }
.lv-list-cancel:focus-visible { visibility: visible; }
.lv-list-cancel:hover { color: var(--ink); }

/* 窄屏：两列落一列后父容器高度 auto，没有剩余空间可分，
   清单回落到定高（与宽屏一样的 3 行），免得被压成 0。
   写在 .lv-list 之后：同特指度，后写的才盖得住。 */
@media (max-width: 899px) {
  .lv-list { flex: 0 0 auto; height: 90px; }
}

/* ---- 底部 ---- */
.lv-foot {
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-top: var(--s3);
}
.lv-close { height: 30px; padding: 0 18px; font-size: var(--fs-body-sm); }

/* 窄屏(375 实测)：抬头四段横排会挤到折行——「选中」二字与周几让位，
   行高 32px 保持不动（定高是纪律，让位只能从字号/内边距上找）。 */
@media (max-width: 480px) {
  .lv-head-label { display: none; }
  .lv-head-date { font-size: var(--fs-body-sm); }
  /* 六轮 X4：动作行上原来的类型分段控件已随两区拆分退役，窄屏那两条收窄规则
     （.lv-kind / .lv-kindtab）一并删除；现在这一行只剩字数槽与一枚按钮，
     375 下横向不再吃紧。 */
}

/* lgj-1410 · 「管理」页请假总览作用域样式（v1.4.10，20260910 立，20260911 改挂，
   20260915 二轮由浮层改整页，20260916 三轮改三层纸层次 + 当日详情 + 总览联动）
   契约=SPEC-练功志-v1.6.0-20260915.md §8.3（三轮）+ §1.2「二轮修订」块；
   方案=.openaccp/coordination/练功志-v160-三轮设计方案-20260916.md §一 + §三；
   二轮图纸=.openaccp/coordination/练功志-v160-图纸-二轮-20260915/D6-请假总览-*.html。

   20260911 owner 逐字：「请假是覆盖全日期的 不仅限阳神班，因此应该是在“管理”
   里，而不是阳神班」——本文件因此只服务「管理」页的请假视图，对 .ys-adm-* /
   .adm-ys-* 的作用域覆写一条不留，阳神班页的版式回到 v1.4.9 原样。

   20260915 owner 二轮逐字：「请假总览这个界面太小了，做大一点」「任何地方都不
   应该展示编号」——形态由 560px 浮层（.adl-*，含编号列）改为整页模式（.alo-*
   = admin leave overview）：左栏原样留着，中栏 + 右栏整体换成本视图。

   20260916 owner 三轮逐字：「感觉层次感不够，结构不够分明，日历组件可以适当
   apple glass 化 或者 层次感突出一点 现在是所有东西都在一个平面【但是不能太重，
   不然加载太慢】」——层次在本文件里只用【三层纸】表达，零阴影做基面：
     L0 页面 = 宣纸 --paper（页底；月历里周日/周六整列也用它，比纸面深一档，
               用来分出周末列）；
     L1 抬起的面 = 票面 --paper-2 + 一道乌丝 + 3px 圆角，零阴影
               （.alo-cal 月历纸、.alo-overview 本月总览纸）；
     L2 浮层 = 半透票面 + backdrop-filter blur(12px) saturate(1.2) +
               --shadow-float + 乌丝描边，无 backdrop-filter 时实底 --paper-2
               （仅 .alo-detail 一块，296 × 340 的小面积卡）。
   全页 blur 只此一个元素，不铺月历、不铺整块面板——owner「不能太重」。
   层与层的关系靠「纸色深一档 + 一道乌丝」，不靠阴影；本文件 box-shadow 只出现
   两处：.alo-detail 的 --shadow-float，与选中格的 inset 1px 浓墨内描边
   （后者是描边不是阴影）。

   为什么仍是独立文件而不并进 app.css：拼接顺序排在最末，回滚只需摘掉这一段。

   三条设计法则在本文件里的落法：
     · 请假是中性事实，一律墨与灰，禁上朱——本文件零 --red-text / --line-red，
       「今日」格靠日号 600 + 格顶 1.5px 浓墨横线标出，不上朱；
     · 定高纪律：会随数据变高的区域一律 height 定死，禁 min-height；月历恒
       660（29 表头 + 6 × 104 格 + 5 × 1 网格线 + 2 描边），右侧两张纸
       296 + 16 + 348 = 660，两栏底边齐，翻月零抖动；内滚区高度取整行倍数
       （行高 30：详情 240 = 8 行、总览 270 = 9 行），底部切在行界上；
     · 数字 tabular-nums、右对齐。
   行间分隔线一律用相邻选择器（.alo-item + .alo-item）只画在行与行之间，
   末行不画——避免与纸的描边共边（设计规范 §11 第 1 条「禁框打架」）。
   内滚区的滚动条条带一律隐藏、滚动能力保留（设计规范 §11 第 7 条）。
   空月照画格子，汇总区留白不写引导词（v1.4.9 owner 裁决沿用：请假不是要
   鼓励的行为）。

   20260916 owner 四轮逐字：「所有的请假字样 都换成 请假迟到」「截图4 总览小
   组件，框的地方做一个图标类似就是暗示 点开看完整详情，然后下方我标了三个
   红点，当人数超过8个人的时候 下方要模糊 并且 也做一个【点开看完整】的暗示
   入口。点开以后是一个浮页 完整的名录【要做】」——本轮在本文件里加三件：
     · .alo-sec-right（题行右端一组：读数 + 展开图钮，五轮 G3 读数下架后
       随之退役）与 .alo-expand（12px 内联 SVG，零填色、描边取 currentColor、
       默认淡墨 hover 浓墨）。这是全站唯一一处图标，owner 逐字点名，不推广；
     · .alo-more / .alo-morelink（> 8 人时第 9 行位置的渐隐层 + 幽灵文字链）。
       渐隐是 ::before 的一道 15px 纸色渐变，覆在第 8 行下半，pointer-events
       关掉；它不是装饰渐变，是「下面还有」的唯一视觉编码（owner 点名要求）；
     · .alo-roster-*（完整名录浮页）。卡壳走 window.UI._overlayShell 的
       .book-card，阴影由 app.css 既有语汇给——本文件 box-shadow 仍只有
       .alo-detail 与选中格 inset 两处，一处不增。
   四轮的类型签（.alo-drow-kind）与弟子端同一支笔：11px 淡墨文字，零底色零
   描边——请假与迟到都是中性事实，本文件仍是零朱。

   20260916 owner 五轮逐字（截图 3 / 4 + 补充 G8）：「本月请假迟到总览 改为
   "本月请假迟到列表"打叉的都是废话，不要有，然后"查看完整名录"要加粗」
   「截图4，也是打叉的地方去掉，取而代之的是切换月的组件……然后正文和标题的
   字体再大一些，太小了！！！！」「当月份从单位数月份切换到双位数月份（例如
   9月份切到10月份），年月的位置就会漂移，建议固定，预留好位置」——本轮：
     · 小组件与浮页题行右端的读数整只下架（.alo-sec-right 退役；.alo-sec-meta
       规则留着，当日详情卡还在用）；.alo-morelink 加字重 600；
     · .alo-mswitch-*（名录浮页题行右端的切月组件）：36×36 两枚幽灵键 + 17px
       600 的月份读数，年与月各落在一个 inline-block 定 width 的右对齐数字槽
       里，9 与 10 占同一个槽，「年」「月」与两枚键的位置与月份位数无关；
     · 名录浮页五带由 48/36/30/360/48 改 56/36/32/400/48（卡 600 -> 650），
       标题 22 -> 26、表头 -> 15、正文三列 -> 16、行高 30 -> 40、可视 12 -> 10 行；
     · .alo-roster-empty（切到零记录的月份时的一句空态，本文件唯一一句）。

   20260917 owner 七轮逐字（截图一）：「原因摘要在列表里面不写，优化一下UI，
   然后点名字的话应该能点进去看到这个人的历史所有请假 迟到 次数 本年次数 和
   每次请假 迟到 具体到日期 的 明细 原因 这个要做出来 也是在同一个组件里」——
   本轮在本文件里加两件（算式逐条写在各自的规则上方）：
     · 名录表由五列收成四列：.alo-roster-reason 不再由名录行消费（规则留着，
       历史明细的「原因」列接着用，同一支笔零新写法），列宽改
       minmax(0,1fr) 96 96 96 + --s6 列距；.alo-roster-name 由纯文本改幽灵
       文字键（静止同正文色，hover 才浓墨 + 下划线）；
     · .alo-hist-*（同一张卡内的弟子历史视图）+ [data-view] 两态开关。两态卡高
       都配平到正文 600（375 档 500），一处 min-height 都没有；本文件的
       box-shadow 仍只有 .alo-detail 与选中格 inset 两处，一处不增，零 blur。

   20260917 owner 八轮逐字（截图二 / 三）：「当日详情里面的名字也需要可点 点进去
   打开的是已有的 弟子请假迟到详情组件，不重复做」「左上角这个返回名册不好看，
   保留返回功能，但是要用更好看的UI图标【区别返回情况……】」「我无法筛选月，
   也要把现有的按月组件 放进来，然后自定义范围；优化一下UI审美」——本轮四件：
     · .alo-drow-namebtn（当日详情姓名的幽灵文字键，与名录那枚逐字同一支笔）；
     · .alo-hist-back 由文字键改 20×20 线性箭头图标 + 36×36 命中区（全站零图标
       规则的例外之二，owner 逐字点名，不推广）；
     · .alo-hist-filter（题行右端的时段筛选）＝ 把 ui-range-stats.js 的导出
       window.UI._buildAdminRangePanel 那一节【原件】在本卡作用域内重排成横向
       一条。lgj-160-admin.css 一个字节不改：本文件所有覆写都带
       .alo-hist-filter 前缀（0,2,0 > 裸 .adc-* 的 0,1,0），与拼接顺序无关；
       日历浮出层在卡内改成【向下弹、右缘对齐筛选条】，材质回落成实底票面 +
       一道乌丝——本文件的 box-shadow 仍只有那两处，blur 仍只有当日详情一块；
     · 审美：四计数与明细表头间距 4 -> 16，名录态搜索带下间距 12 -> 24 接住，
       两态卡高由正文 600 长到 612 且仍逐像素相同（375 档两态仍同为 500）。
   ========================================================================== */

/* ---- 整页壳：接管 .adm-layout 的中栏 + 右栏两格 ------------------------- */
.alo { display: flex; flex-direction: column; }
.adm-layout > .alo { grid-column: 2 / span 2; }

/* ---- 抬头一行定高 34px：标题 + 月份读数 + ‹ › + 右端幽文「返回名册」 ---- */
.alo-head {
  display: flex;
  align-items: center;
  gap: var(--s4);
  height: 34px;
  overflow: hidden;
  border-bottom: var(--lw-hair) solid var(--line);
}
/* 页块题走文楷 600 而不是齐伋：齐伋是明刻本提字体，「请假总览」四字里
   请/总/览 三字出的是繁体字形，与左栏暗文链同名入口的简体同屏打架（站内既有
   的齐伋页标「管理/今日/排行榜/我的」简繁同形，所以过去没暴露这件事）。
   主编排 20260916 13:1x 裁决：方案 §3.3「22px 齐伋」是方案缺陷，改文楷 600，
   字号 22 与其余笔法不动。 */
.alo-title {
  font-family: var(--font-body);
  font-size: 22px;
  font-weight: 600;
  line-height: 30px;
  letter-spacing: var(--ls-display);
  color: var(--ink);
  flex: 0 0 auto;
}
.alo-month { display: flex; align-items: center; flex: 0 0 auto; }
.alo-monthread {
  font-family: var(--font-num);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  min-width: 96px;
  text-align: center;
}
/* 次要动作低一档、hover 才显影（法则三），沿用日历月导航同款笔法 */
.alo-navbtn { font-size: 15px; line-height: 20px; color: var(--ink-3); padding: 0 8px; }
.alo-navbtn:hover { color: var(--ink); }
/* 六轮 X5 返工一（主编排硬规则「与基座相比任何可见文字不得变小」）：
   请假总览页挂在管理页壳里（.page--notes），本卡的 §22b 总闸把
   var(--fs-body-sm) 由 14.95 拉回 13 就是变小。这三处分别是「返回名册」
   控件与两处弟子姓名，按索引 §4「正文 / 控件 15px」写 15 字面量；三处
   原本都没定高，行盒随字号补 20，一处不用 min-height。 */
.alo-back {
  margin-left: auto;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 20px;
  color: var(--ink-3);
}
.alo-back:hover { color: var(--ink); }

/* ---- 三读数：无框无底，靠竖细线分格（禁卡内卡、禁 KPI 卡模板） --------- */
.alo-kpis {
  display: flex;
  align-items: stretch;
  height: 72px;
  overflow: hidden;
  border-bottom: var(--lw-hair) solid var(--line);
}
.alo-kpi {
  flex: 0 0 200px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 0 var(--s5);
}
.alo-kpi:first-child { padding-left: 0; }
.alo-kpi + .alo-kpi { border-left: var(--lw-hair) solid var(--line); }
.alo-kpi-k {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
}
.alo-kpi-v {
  font-family: var(--font-num);
  font-size: 26px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  line-height: 1.2;
}
.alo-kpi-v i {
  font-family: var(--font-body);
  font-style: normal;
  font-size: 13px;
  color: var(--ink-3);
  padding-left: 4px;
}

.alo-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--s5);
  margin-top: var(--s5);
}

/* ============================================================
   左 · 月历纸（L1）：--paper-2 底 + 乌丝描边 + 3px 圆角，零阴影
   恒 660 = 29 表头 + 629 网格（6 × 104 + 5 × 1 网格线）+ 2 描边
   ============================================================ */
.alo-cal {
  box-sizing: border-box;
  height: 660px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
}
/* 表头行底一道乌丝；周日、周六两格底色随整列深一档 */
.alo-cal-head {
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  height: 29px;
  flex: 0 0 auto;
  overflow: hidden;
  border-bottom: var(--lw-line) solid var(--line);
}
.alo-cal-h {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
  text-align: left;
  padding-left: 8px;
  line-height: 28px;
}
.alo-cal-h:nth-child(7n+1), .alo-cal-h:nth-child(7n) { background: var(--paper); }
/* 格间 1px 乌丝网格：gap + 容器底色即网格线，不给每格画 border（42 条边框
   相接就是「框打架」）；外圈一道由 .alo-cal 的描边给，不重复画。 */
.alo-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: repeat(6, 104px);
  gap: 1px;
  height: 629px;
  flex: 0 0 auto;
  overflow: hidden;
  background: var(--line);
}
.alo-cell {
  position: relative;
  background: var(--paper-2);
  padding: 6px 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: background 120ms ease;
}
/* 周日（每行第 1 格）与周六（每行第 7 格）整列深一档 */
.alo-cell:nth-child(7n+1), .alo-cell:nth-child(7n) { background: var(--paper); }
/* 有请假的格才可点（空格不可点：点了也没有名单可看） */
.alo-cell[role="button"] { cursor: pointer; }
.alo-cal-grid .alo-cell[role="button"]:hover { background: var(--paper-3); }
.alo-cell:focus-visible { outline: var(--lw-line) solid var(--ink); outline-offset: -2px; }
/* 今日：日号 600 + 格顶 1.5px 浓墨横线（owner「请假永不用朱色」） */
.alo-cell[data-today="1"]::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--lw-thick);
  background: var(--ink);
}
.alo-cell[data-today="1"] .alo-cell-d { color: var(--ink); font-weight: 600; }
/* 选中格：衬纸底 + 1px 浓墨内描边（inset 是描边不是阴影） */
.alo-cal-grid .alo-cell[data-selected="1"] {
  background: var(--paper-3);
  box-shadow: inset 0 0 0 var(--lw-line) var(--ink);
}
/* 总览联动：含命中弟子的格，日号转浓墨 600 */
.alo-cell[data-hit="1"] .alo-cell-d { color: var(--ink); font-weight: 600; }

.alo-cell-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  height: 20px;
  overflow: hidden;
}
.alo-cell-d {
  font-family: var(--font-num);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
/* 人数签：有请假才出；衬纸底 pill，数字 600——人数是数据，要被强调 */
.alo-cell-n {
  margin-left: auto;
  flex: 0 0 auto;
  font-family: var(--font-num);
  font-size: var(--fs-caption);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  background: var(--paper-3);
  border-radius: var(--r-pill);
  height: 18px;
  line-height: 18px;
  padding: 0 6px;
  white-space: nowrap;
}
.alo-cell-name {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 18px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 联动：命中的姓名转浓墨 600，其余姓名退淡墨（同一支笔深浅两档，不跳色） */
.alo-cell-name[data-hit="1"] { color: var(--ink); font-weight: 600; }
.alo-cell-name[data-hit="0"] { color: var(--ink-3); }
.alo-cell-more {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  line-height: 18px;
  color: var(--ink-3);
}

/* ============================================================
   右 · 两张纸上下叠：296 当日详情（L2 玻璃）+ 16 + 348 本月总览（L1）= 660
   ============================================================ */
.alo-side { display: flex; flex-direction: column; gap: var(--s4); height: 660px; }

/* 小节题行：12px 淡墨宽字距 + 右端 num 读数，定高 32，零边框（与下面带描边的
   搜索框不共边、不相切） */
.alo-sec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  height: 32px;
  flex: 0 0 auto;
  overflow: hidden;
}
.alo-sec-title {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
}
.alo-sec-meta {
  font-family: var(--font-num);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  white-space: nowrap;
}
/* 五轮 G3：小组件题行右端的读数「N 人 · N 人次」整只下架（owner「打叉的都是
   废话」），右端只剩展开图钮一件——space-between 下单件自然贴右端，原来把
   读数与图钮合成一组的 .alo-sec-right 随之退役。.alo-sec-meta 本身留着：
   当日详情卡的右端读数还在用它，owner 五轮没点那一件。 */
/* 展开图钮：全站唯一一处图标（owner 四轮点名）。零边框零底色，静止淡墨、
   交互显影（法则③）；12 的图配 24 的点击面，不靠撑大图标换命中率。 */
.alo-expand {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  border: 0;
  background: none;
  padding: 0;
  color: var(--ink-3);
  cursor: pointer;
}
.alo-expand:hover { color: var(--ink); }
.alo-expand:focus-visible { outline: var(--lw-line) solid var(--ink); outline-offset: -2px; }

/* ---- 当日详情：全页唯一一块 L2 玻璃（半透票面 + blur 12） -------------- */
.alo-detail {
  box-sizing: border-box;
  height: 296px;
  flex: 0 0 auto;
  overflow: hidden;
  padding: 0 var(--s3) var(--s3);
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  box-shadow: var(--shadow-float);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .alo-detail {
    background: rgba(var(--paper-2-rgb), .78);
    -webkit-backdrop-filter: blur(12px) saturate(1.2);
    backdrop-filter: blur(12px) saturate(1.2);
  }
}
/* 240 = 8 × 30：底部永远切在行界上；滚动条条带隐藏，滚动能力保留 */
.alo-detail-list {
  height: 240px;
  margin-top: 10px;
  overflow-y: auto;
  scrollbar-width: none;
}
.alo-detail-list::-webkit-scrollbar { display: none; }
.alo-drow {
  box-sizing: border-box;
  display: grid;
  grid-template-columns: 72px 30px minmax(0, 1fr);
  align-items: center;
  gap: var(--s2);
  height: 30px;
  overflow: hidden;
}
.alo-drow + .alo-drow { border-top: var(--lw-hair) dashed rgba(var(--line-rgb), .7); }
.alo-drow-name {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 20px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 八轮 K4（owner「当日详情里面的名字也需要可点」）：与名录那枚幽灵文字键
   逐字同一支笔——静止与正文一个字都不差（同色同字号零装饰，法则③），hover
   才显影成浓墨 + 下划线。display:block 的理由同 .alo-roster-name：button 默认
   inline-flex 的匿名文本盒吃不到 text-overflow。 */
.alo-drow-namebtn:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.alo-drow-namebtn:focus-visible { outline: var(--lw-line) solid var(--ink); outline-offset: 2px; }
/* 类型签：11px 淡墨文字，零底色零描边——它是一条事实，不是状态告警 */
.alo-drow-kind {
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--ink-3);
  white-space: nowrap;
}
.alo-drow-reason {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.alo-drow-reason[data-empty="1"] { color: var(--ink-3); }
/* 未选日的一句引导词（空位用引导词不用空白），同样定高占位 */
.alo-detail-hint {
  margin: 0;
  height: 30px;
  overflow: hidden;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  line-height: 30px;
  color: var(--ink-3);
}

/* ---- 本月请假弟子总览：L1 纸，348 = 32 题 + 36 搜索 + 8 + 270 列表 + 2 描边 */
.alo-overview {
  box-sizing: border-box;
  height: 348px;
  flex: 0 0 auto;
  overflow: hidden;
  padding: 0 var(--s3);
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
}
.alo-side-search {
  display: flex;
  align-items: center;
  height: 36px;
  flex: 0 0 auto;
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  background: var(--paper);
  padding: 0 var(--s3);
}
.alo-side-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-family: "KaiTi", "STKaiti", "楷体", serif;
  font-size: var(--fs-body-sm);
  color: var(--ink);
}
.alo-side-search input::placeholder { color: var(--ink-3); opacity: .6; }
/* 270 = 9 × 30：底部永远切在行界上；滚动条条带隐藏，滚动能力保留 */
.alo-list { height: 270px; margin-top: var(--s2); overflow-y: auto; scrollbar-width: none; }
.alo-list::-webkit-scrollbar { display: none; }
.alo-item {
  box-sizing: border-box;
  display: grid;
  grid-template-columns: 72px 52px minmax(0, 1fr);
  align-items: center;
  gap: var(--s2);
  height: 30px;
  overflow: hidden;
  cursor: pointer;
  transition: background 120ms ease;
}
.alo-item + .alo-item { border-top: var(--lw-hair) dashed rgba(var(--line-rgb), .7); }
.alo-item:hover { background: rgba(var(--paper-3-rgb), .6); }
.alo-list .alo-item[data-on="1"] { background: var(--paper-3); }
.alo-item:focus-visible { outline: var(--lw-line) solid var(--ink); outline-offset: -2px; }
.alo-item-name {
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 20px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.alo-item-days {
  font-family: var(--font-num);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: right;
}
.alo-item-reason {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 理由一条都没有显灰字「未填理由」——淡墨，不是朱 */
.alo-item-reason[data-empty="1"] { color: var(--ink-3); }
.alo-err { margin: 10px 0 0; }

/* ---- > 8 人：第 9 行的位置＝渐隐层 + 完整名录入口（owner 四轮） ---------
   行数仍恒 9 行 × 30 = 270，只是最后一行不放弟子，放入口；≤ 8 人这一块整只
   不渲染，列表就是普通的 8 行以内。渐隐覆在第 8 行下半（15px），到纸色收尾，
   点击穿透关掉，免得挡住第 8 行的 hover。渐隐层本身 30px（工单契约逐字），
   正好盖住第 8 行整行：行文字居中，被盖住的是下半，读得出「还有」又不至于
   把那一行整条抹掉。 */
.alo-more {
  position: relative;
  display: flex;
  align-items: center;
  height: 30px;
  overflow: visible;
}
.alo-more::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 30px;
  height: 30px;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(var(--paper-2-rgb), 0), var(--paper-2));
}
/* 五轮 G3：文案去掉括号计数，只剩四个字，字重 600（owner「"查看完整名录"
   要加粗」）。仍是零描边零底的幽灵文字链，静止淡墨、hover 浓墨（法则③）。 */
.alo-morelink {
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--ink-3);
  cursor: pointer;
}
.alo-morelink:hover { color: var(--ink); }

/* ---- 完整名录浮页（owner 四轮「点开以后是一个浮页 完整的名录」） ---------
   960 定宽，五带：题带 56 / 搜索 36 / 表头 32 / 列表 400（10 × 40）/ 卡脚 48。
   每一带都是 height，一处不用 min-height；列表超 10 行在区域内滚，条带隐藏
   （SPEC §11.7）。卡壳的阴影由 app.css 的 .book-card 给，本文件零新增阴影。

   五轮 G4（owner「正文和标题的字体再大一些，太小了！！！！」）后的卡高算式：
     题带 56 + 题带下间距 16 + 搜索 36 + 搜索下间距 12 + 表头 32
   + 列表 400 + 卡脚 48 = 正文 600
   + .ticket 内距 24 × 2 = 48 + .ticket 外框 1.5 × 2 = 3  →  卡 651
   浮层壳 .book-auth-overlay 的内距是 16 × 2 = 32，故 1440×900 需 651 + 32
   = 683 ≤ 900、1280×800 需 683 ≤ 800，两档整卡都在视口内。 */
.book-card.alo-roster-card {
  max-width: 960px;
  width: min(960px, calc(100vw - 48px));
  border-radius: var(--r-pop);
}
.alo-roster-card .ticket-body { display: flex; flex-direction: column; }
.alo-roster-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  height: 56px;
  flex: 0 0 auto;
  overflow: hidden;
  border-bottom: var(--lw-hair) solid var(--line);
  margin-bottom: var(--s4);
}
.alo-roster-title {
  margin: 0;
  font-family: var(--font-body);
  font-size: 26px;
  font-weight: 600;
  line-height: 36px;
  letter-spacing: var(--ls-display);
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- 切月组件（五轮 G4，与管理页面板时段节同一支笔） --------------------
   「‹」36×36 / 「2026 年 9 月」17px 600 浓墨 / 「›」36×36。两枚键静止零描边
   零底（法则③），hover 才衬纸 + 转浓墨；36 的命中区里只放 20px 的 chevron
   字形，不靠撑大字形换命中率。 */
.alo-mswitch {
  display: flex;
  align-items: center;
  gap: var(--s1);
  height: 36px;
  flex: 0 0 auto;
}
.alo-mswitch-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--font-body);
  font-size: 20px;
  line-height: 20px;
  color: var(--ink-2);
  border-radius: var(--r-ctl);
  cursor: pointer;
}
.alo-mswitch-btn:hover { background: var(--paper-3); color: var(--ink); }
.alo-mswitch-btn:focus-visible { outline: var(--lw-line) solid var(--ink); outline-offset: -2px; }
.alo-mswitch-read {
  display: flex;
  align-items: baseline;
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 600;
  line-height: 24px;
  color: var(--ink);
  white-space: nowrap;
}
.alo-mswitch-read .num { margin-inline: 0; }
/* owner 五轮补充 G8：9 → 10 年月不许漂移。年恒 4 位、月走定宽槽右对齐，
   两个汉字与两枚键的位置因此与月份位数无关（定 width，不用 min-width）。 */
.alo-mswitch-yr {
  display: inline-block;
  width: 41px;
  text-align: right;
}
.alo-mswitch-mo {
  display: inline-block;
  width: 21px;
  text-align: right;
}
.alo-mswitch-cn { white-space: pre; }
/* 搜索框与小组件那只逐字同款（同挂 .alo-side-search），这里只补一个下间距，
   让它的描边与表头那道乌丝隔开一档（SPEC §11.1 禁框打架）。
   八轮 K6 审美：12 -> 24（--s5）。这一档不是为了好看而加的——历史态的四计数
   与明细表头之间由 4 加到 16（owner「优化一下UI审美」），历史态因此比名录态
   高出 12；名录态的搜索带下间距同加 12，两态回到【逐像素同高】（算式见下方
   .alo-hist-* 规则头）。顺带这条也是名录态自己想要的呼吸量。 */
.alo-roster-search { margin-bottom: var(--s5); }
.alo-roster-hrow,
.alo-roster-row,
.alo-hist-hrow,
.alo-hist-row {
  box-sizing: border-box;
  display: grid;
  align-items: center;
  overflow: hidden;
}
/* 七轮 J1 列宽算式（owner 逐字「原因摘要在列表里面不写」）：
   卡 960 − .ticket 内距 24 × 2 − 外框 1.5 × 2 ＝ 正文净宽 909。
   旧五列：120 姓名 + 8 + 72 + 8 + 72 + 8 + 72 + 8 + 541 原因摘要 ＝ 909。
   新四列：1fr 姓名 + 32 + 96 + 32 + 96 + 32 + 96 ＝ 909，姓名 ＝ 909 − 96 × 3
   − 32 × 3 ＝ 525（旧 120 + 释放的 405）。三数列等宽 96、彼此 --s6 ＝ 32
   相隔（契约「≥ --s6」），右对齐由 .alo-roster-n / .alo-roster-h[data-num]
   给；姓名列左对齐吃掉全部释放宽度。 */
.alo-roster-hrow,
.alo-roster-row {
  grid-template-columns: minmax(0, 1fr) 96px 96px 96px;
  column-gap: var(--s6);
}
.alo-roster-hrow {
  height: 32px;
  flex: 0 0 auto;
  border-bottom: var(--lw-line) solid var(--line);
}
.alo-roster-row { height: 40px; }
.alo-roster-h,
.alo-hist-h {
  font-family: var(--font-body);
  font-size: 15px;
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
}
.alo-roster-h[data-num="1"] { text-align: right; }
.alo-roster-list {
  height: 400px;
  flex: 0 0 auto;
  overflow-y: auto;
  scrollbar-width: none;
}
.alo-roster-list::-webkit-scrollbar { display: none; }
.alo-roster-row + .alo-roster-row { border-top: var(--lw-hair) dashed rgba(var(--line-rgb), .7); }
/* 姓名是幽灵文字键（七轮 J1「点名字的话应该能点进去看到这个人的历史」）：
   静止与正文一个字都不差（同色同字号零装饰，法则③「静止极净」），hover 才
   显影成浓墨 + 下划线。display:block 而不是 button 默认的 inline-flex——
   inline-flex 里的匿名文本盒吃不到 text-overflow，单行省略会失效。 */
.alo-roster-name {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.alo-roster-namebtn:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.alo-roster-namebtn:focus-visible { outline: var(--lw-line) solid var(--ink); outline-offset: 2px; }
.alo-roster-n {
  font-family: var(--font-num);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: right;
}
.alo-roster-reason {
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.alo-roster-reason[data-empty="1"] { color: var(--ink-3); }
/* 切到一条记录都没有的月份（五轮 G4）：列表区写一句，占一行的位置，
   不撑高也不塌陷；本卡唯一新增的空态句。 */
.alo-roster-empty {
  margin: 0;
  height: 40px;
  line-height: 40px;
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink-3);
}
/* ---- 弟子历史视图（七轮 J1）-------------------------------------------
   owner 逐字：「点名字的话应该能点进去看到这个人的历史所有请假 迟到 次数
   本年次数 和 每次请假 迟到 具体到日期 的 明细 原因 这个要做出来 也是在同一个
   组件里」——同一张 960 卡换内容，不新开浮层、不动 _overlayShell。
   八轮 K6 契约 4（四计数与明细表头间距 4 -> --s4 16）后的两态配平，正文 612：
     名录 ＝ 题带 56 + 16 + 搜索 36 + 24 + 表头 32 + 列表 400 + 卡脚 48 ＝ 612
     历史 ＝ 题带 56 + 16 + 四计数 44 + 16 + 表头 32 + 列表 400 + 卡脚 48 ＝ 612
   两态的中段各自 60（36 + 24 ｜ 44 + 16），逐像素同高；列表仍是 10 × 40 ＝ 400
   （契约 3「同名录 10×40 ＝ 400」）。整卡 ＝ 612 + .ticket 内距 24 × 2 + 外框
   1.5 × 2 ＝ 663，浮层壳内距 16 × 2 ＝ 32 → 695，1024×768 / 1280×800 / 1440×900
   三档整卡都在视口内（七轮的 651 因这 12px 长到 663，仍有余量）。
   四计数块高 44 的余量账：13 标 × 1.3 ＝ 16.9 + 4（--s1）+ 17 数 × 1.2 ＝ 20.4
   ＝ 41.3 ≤ 44，四计数块与两列表一样定死 height，不用下限式高度。 */
.alo-roster-headl {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-width: 0;
  overflow: hidden;
}
/* 返回键（八轮 K5，owner 逐字「左上角这个返回名册不好看，保留返回功能，但是
   要用更好看的UI图标」）：七轮那枚「‹ 返回名录」文字键换成 20×20 线性箭头，
   命中区 36×36。静止 --ink-2、hover 才浓墨 + 上一层衬纸（法则③静止极净），
   零描边零底色零阴影。SVG 在 ui-admin-leave.js 的 BACK_SVG：stroke 取
   currentColor、1.5px、零填充——颜色由这里的 color 一处给，图标不自带色。
   这是全站零图标规则的例外之二（之一＝小组件题行那枚 12px 展开图钮），两处
   都由 owner 逐字点名，不得推广。 */
.alo-hist-back {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-left: -8px;        /* 36 命中区比 20 图形宽出的那 8px 收回，图形左缘与卡内距对齐 */
  border-radius: var(--r-ctl);
  color: var(--ink-2);
}
.alo-hist-back:hover { color: var(--ink); background: var(--paper-3); }
.alo-hist-back:focus-visible { outline: var(--lw-line) solid var(--ink); outline-offset: -2px; }
/* 两态切换：名录态收起历史块与返回键，历史态收起搜索带 / 名录表头 / 名录列表
   与切月组件（历史不按月）。搜索框与名录列表只是被收起来，不拆不清——
   返回时搜索词与滚动位置原样还在（滚动位置由 JS 显式存取一次）。 */
.alo-roster-card .ticket-body[data-view="roster"] .alo-hist,
.alo-roster-card .ticket-body[data-view="roster"] .alo-hist-filter,
.alo-roster-card .ticket-body[data-view="roster"] .alo-hist-back { display: none; }
.alo-roster-card .ticket-body[data-view="hist"] .alo-roster-search,
.alo-roster-card .ticket-body[data-view="hist"] .alo-roster-hrow,
.alo-roster-card .ticket-body[data-view="hist"] .alo-roster-list,
.alo-roster-card .ticket-body[data-view="hist"] .alo-mswitch { display: none; }
/* 历史态题行要让自定义范围日历浮出层探出题带（名录态没有浮出层，仍收着，
   56 的定高由 overflow:hidden 兜底）。浮出层本身落在卡内（见下方定位），
   这里只是不让题带把它裁掉。 */
.alo-roster-card .ticket-body[data-view="hist"] .alo-roster-head { overflow: visible; }

/* ---- 时段筛选（八轮 K6）------------------------------------------------
   owner 逐字：「我无法筛选月，也要把现有的按月组件 放进来，然后自定义范围」。
   控件【零自造】：整只复用 ui-range-stats.js 的导出 window.UI._buildAdminRangePanel
   （＝管理页右栏那一节本体，两签 + ‹ 年 月 › + 「清除」 + 双月日历浮出层），
   它的 DOM 与 CSS（lgj-160-admin.css 的 .adc-*）一个字节不改。本节只做
   【作用域重排】：在这张 960 卡里把那一节由竖排改横排一条，塞进 56 的题带。
   选择器一律是 .alo-hist-filter 前缀（0,2,0），比 lgj-160-admin.css 的裸
   .adc-*（0,1,0）高一档，与拼接顺序无关；管理页右栏那一份一个像素不受影响。

   横向账（正文净宽 909）：
     返回 36 + 12 + 标题（26px，最长「请假迟到历史 · 三字名」实测 258）＝ 306
     + 题带 gap 16 + 筛选 448（两签 200 + 12 + 读数行 236）＝ 770 ≤ 909。
   两签 200 是量出来的，不是估的：「自定义范围」五字 15px ＝ 75，加 .adc-tab
   的左右内距 8 × 2 ＝ 91，两签等分就得 ≥ 182；先试的 168（每签 84）会把那五个
   字折成两行，把 32 的定高撑成 53 再被 overflow 裁掉（1440 实拍逮到）。 */
.alo-hist-filter {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}
.alo-hist-filter .adc-sec {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin: 0;
  flex: 0 0 auto;           /* ≤1439 档那份 flex:0 1 300px 是右栏工具条的账，
                               这张卡里会把 416 的一条压瘪，钉死不伸不缩 */
  position: relative;       /* ≤1439 档 lgj-160-admin.css 把它改成 static，这里钉回来：
                               浮出层的定位基准必须是这一节，不能漂到卡壳上 */       /* ≤1439 档 lgj-160-admin.css 把它改成 static，这里钉回来：
                               浮出层的定位基准必须是这一节，不能漂到卡壳上 */
}
/* 节题「时段」是右栏语境的小标，题带里已有大标题，重复一次就是废话 */
.alo-hist-filter .adc-sec-title { display: none; }
.alo-hist-filter .adc-tabs { width: 200px; flex: 0 0 auto; }
.alo-hist-filter .adc-tab { white-space: nowrap; }
.alo-hist-filter .adc-range {
  width: 236px;
  flex: 0 0 auto;
  height: 36px;
  margin-top: 0;
}
/* 日历浮出层在这张卡里【向下】展开、右缘与筛选条右缘齐：右栏那份是向左向上
   弹（它贴着画布右缘），卡内向左弹会掉出卡外。定位基准＝.adc-sec（上面钉回
   relative），故 right:0 即筛选条右缘、top 即题带下沿。
   纵向账：题带下沿 56 + 12 ＝ 68 起，浮出层高 ≈ 抬头 26 + 12 + 单月历 ≈ 250
   + 消息 22 + 内距 32 ≈ 342，68 + 342 ＝ 410 ≤ 正文 612，四缘全在卡内。
   材质：本卡零阴影零 blur（契约 5），且全页玻璃只许一块（已给当日详情），
   故这一份回落成实底票面 + 一道乌丝，不继承右栏那份的 --shadow-float 与
   backdrop-filter。 */
.alo-hist-filter .adc-calpop {
  position: absolute;
  top: calc(100% + var(--s3));
  bottom: auto;
  right: 0;
  left: auto;
  width: 560px;
  max-width: 100%;
  margin-top: 0;
  padding: var(--s4);
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-pop);
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.alo-hist { display: flex; flex-direction: column; }
/* 八轮 K6 契约 4：四计数一行四列等宽（repeat(4,1fr) 本就等宽），与明细表头
   之间的 4 加到 --s4 ＝ 16——七轮复核 P2-2 与 owner「优化一下UI审美」同指这
   一处：17px 的数字紧贴着下面那道乌丝。多出的 12px 由名录态搜索带下间距同加
   12 接住，两态仍逐像素同高。 */
.alo-hist-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: center;
  gap: var(--s3);
  height: 44px;
  flex: 0 0 auto;
  overflow: hidden;
  margin-bottom: var(--s4);
}
.alo-hist-kpi {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  overflow: hidden;
}
/* 与弟子详情浮窗右下四格（.mdp-k / .mdp-v）逐字同一支笔：标 13 淡墨、数 17
   --font-num tabular；这四个是从属计数，不用数带的 22，免得主次读反。 */
.alo-hist-k {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.3;
  color: var(--ink-3);
  white-space: nowrap;
}
/* 十轮 N2（owner 逐字：「默认状态下 如 图1，但是点了按月以后就会往右挪一点，
   这个要尽可能考虑到 单位数月和双位数月的情况 但是不会形成视觉挪位」）：
   九轮 M2 的恒宽双位槽（width: 2ch; text-align: right）把单位数月的数字推离
   格左沿约一个数字宽——这正是 owner 看见的「右挪」。本轮整槽下架：月份数字
   左对齐紧贴格左沿，按月态标的可见左沿与默认态（纯文本标）落同一条线。
   单位数 / 双位数由 .num 的 tabular-nums 承担（每一位同宽），故 9 月 ↔ 12 月
   只是同一标内的尾字「月请假」按位数后移一个数字宽，格左沿 / 标左沿 / 数值
   左沿三组全不动。.num 的 margin-inline: 0.06em 是「数字与汉字交界留白」，标首
   这一侧前面无字，留着等于把数字又推离左沿，故只归零起始侧、保留结束侧
   （数字与「月」之间那处留白照旧）。 */
.alo-hist-k .alo-hist-mo {
  /* 九轮 M2 返工一（复核 P1-1）：月份数字包在 <b> 里会撞 app.css 的 b,strong{600}，
     与同一标里「月请假」三字（400）不是同一支笔；继承父标字重，同一支笔。 */
  font-weight: inherit;
  margin-inline-start: 0;
  /* 十轮 N2 合流整合（复核 P1）：保留恒宽槽（九轮「固定字段不移位」），
     只把右对齐改成左对齐——右挪的真凶是 text-align:right，不是 width。 */
  display: inline-block;
  width: 1.2em;
  text-align: left;
}
.alo-hist-v {
  margin-top: var(--s1);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
}
/* 明细三列：日期 120 + 32 + 类型 72 + 32 + 原因 1fr（909 − 256 ＝ 653） */
.alo-hist-hrow,
.alo-hist-row {
  grid-template-columns: 120px 72px minmax(0, 1fr);
  column-gap: var(--s6);
}
.alo-hist-hrow {
  height: 32px;
  flex: 0 0 auto;
  border-bottom: var(--lw-line) solid var(--line);
}
.alo-hist-row { height: 40px; }
.alo-hist-list {
  height: 400px;
  flex: 0 0 auto;
  overflow-y: auto;
  scrollbar-width: none;
}
.alo-hist-list::-webkit-scrollbar { display: none; }
.alo-hist-row + .alo-hist-row { border-top: var(--lw-hair) dashed rgba(var(--line-rgb), .7); }
.alo-hist-date {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--ink);
}
/* 类型签与当日详情那枚同一支笔的加大版（本表正文 16，签跟着走一档淡墨）：
   请假与迟到都是中性事实，零底色零描边，永不用朱。 */
.alo-hist-kind {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  white-space: nowrap;
}
/* 取数失败：一句 15px 淡墨 + 一枚幽灵「重试」，占一整行 40，不撑高也不塌陷 */
.alo-hist-fail {
  display: flex;
  align-items: center;
  gap: var(--s3);
  height: 40px;
  overflow: hidden;
}
.alo-hist-retry {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 20px;
  color: var(--ink-3);
}
.alo-hist-retry:hover { color: var(--ink); }
.alo-roster-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  height: 48px;
  flex: 0 0 auto;
  overflow: hidden;
}
.alo-roster-close { height: 32px; padding: 0 18px; font-size: var(--fs-body-sm); }

/* ---- 窄屏降级（方案 §3.6） -------------------------------------------- */
/* 断点 1439：管理页三栏只在 ≥1440 生效（复核 P1-1），纵排档本视图自然吃满
   整幅宽度，两栏主体（月历 + 右侧两张纸）照旧。 */
@media (max-width: 1439px) {
  .alo { order: 2; }
  .adm-layout > .alo { grid-column: auto; }
}
/* ≤1120：月历与右侧改上下——详情卡落在月历之下，总览再之下 */
@media (max-width: 1120px) {
  .alo-main { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .alo-side { height: auto; }
}
@media (max-width: 760px) {
  .alo-kpis { height: auto; flex-wrap: wrap; padding-bottom: var(--s3); }
  .alo-kpi { flex: 0 0 50%; padding: var(--s2) var(--s3) 0 0; }
  .alo-kpi + .alo-kpi { border-left: 0; }
  .alo-kpi-v { font-size: 22px; }
  /* 窄屏月历 348 = 29 表头 + 317 网格（6 × 52 + 5 × 1）+ 2 描边，仍是整行倍数 */
  .alo-cal { height: 348px; }
  .alo-cal-grid { grid-template-rows: repeat(6, 52px); height: 317px; }
  .alo-cal-h { font-size: 10px; padding-left: 4px; }
  .alo-cell { padding: 4px; }
  /* 窄屏格内只留日号与人数签（姓名放不下，全名单去点格看当日详情），
     两行各自定高，合计 32 ≤ 52 - 8 内距 */
  .alo-cell-top { display: block; height: auto; }
  .alo-cell-d { display: block; font-size: 12px; line-height: 16px; }
  .alo-cell-n { display: inline-block; margin-left: 0; height: 16px; line-height: 16px; font-size: 10.5px; padding: 0 4px; }
  .alo-cell-name, .alo-cell-more { display: none; }
  .alo-head { gap: var(--s2); }
  .alo-title { font-size: 18px; }
  /* 名录浮页 375 折法：卡吃满可用宽，数字三列各收到 40，列表降到 8 行＝320
     （仍是整行倍数，底部不切半行）；题带 48（切月组件 36 + 上下各 6），
     标题收到 18 给切月组件让宽，卡脚收 8。
     375 卡高 = 48 + 12 + 36 + 12 + 32 + 320 + 40 = 500 正文
     + 内距 16 × 2 = 32 + 外框 3 = 535。 */
  .book-card.alo-roster-card { width: calc(100vw - 32px); padding: var(--s4); }
  .alo-roster-head { height: 48px; margin-bottom: var(--s3); }
  .alo-roster-title { font-size: 18px; line-height: 26px; }
  /* 七轮 J1 的 375 列宽账：卡 375 − 32 ＝ 343，内距 16 × 2 ＝ 32、外框 3
     → 正文净宽 308。四列 ＝ 1fr 姓名 + 12 + 44 + 12 + 44 + 12 + 44，姓名
     ＝ 308 − 132 − 36 ＝ 140，四列都留着（「天数」不隐藏）。三数列间距在这一
     档由 --s6 降到 --s3：308 的净宽放不下 32 × 3，这是写明的降级。 */
  .alo-roster-hrow,
  .alo-roster-row { grid-template-columns: minmax(0, 1fr) 44px 44px 44px; column-gap: var(--s3); }
  .alo-roster-list { height: 320px; }
  .alo-roster-foot { height: 40px; }
  /* 八轮：题带下间距在本档不跟着 ≥768 加到 24——375 的账另算（见下），
     名录态仍是 48 + 12 + 36 + 12 + 32 + 320 + 40 ＝ 500，一像素没动。 */
  .alo-roster-search { margin-bottom: var(--s3); }
  /* 历史视图 375：日期 92（15px 数字 10 位约 83）+ 12 + 类型 44 + 12 + 原因 148
     ＝ 308。 */
  .alo-hist-hrow,
  .alo-hist-row { grid-template-columns: 92px 44px minmax(0, 1fr); column-gap: var(--s3); }
  .alo-hist-date { font-size: 15px; }
  .alo-hist-kpis { gap: var(--s2); }
  /* 八轮 K6 的 375 折法（写明的降级）：308 的净宽横着放不下「标题 + 两签 +
     ‹ 年 月 › + 清除」，故历史态题带在本档摊成三行——
       题行 36（返回图标 36 + 18px 标题）+ 8 + 两签 32 + 8 + 读数行 32 ＝ 116。
     卡高仍与名录态【逐像素相同】的 500：
       名录 ＝ 48 + 12 + 36 + 12 + 32 + 320(8 行) + 40 ＝ 500
       历史 ＝ 116 + 12 + 44 + 16 + 32 + 240(6 行) + 40 ＝ 500
     降级点＝历史明细在本档可视 8 行收到 6 行（240 仍是 40 的整数倍，底部切在
     行界上），条数一条不丢，超出的照旧内滚。 */
  .alo-roster-card .ticket-body[data-view="hist"] .alo-roster-head {
    height: 116px;
    flex-wrap: wrap;
    align-content: center;
    row-gap: var(--s2);
  }
  .alo-roster-card .ticket-body[data-view="hist"] .alo-roster-headl {
    width: 100%;
    height: 36px;
  }
  .alo-hist-list { height: 240px; }
  .alo-hist-filter { width: 100%; }
  .alo-hist-filter .adc-sec { width: 100%; flex-direction: column; align-items: stretch; gap: var(--s2); }
  .alo-hist-filter .adc-tabs { width: 100%; }
  .alo-hist-filter .adc-range { width: 100%; height: 32px; }
  .alo-hist-filter .adc-range .adc-navbtn { width: 32px; height: 32px; }
  /* 本档的浮出层就地收成单月（lgj-160-admin.css 已把 .adc-cal2 收成一列并藏起
     上个月那一列），但位置仍是【卡内向下弹的浮层】而不是内容层——题带的定高
     不能被它撑开。宽度吃满筛选条（max-width:100% 已在基规则里给）。
     上间距与内距各收一档：375 卡只有 534 高，实测 12 + 内距 16 的版本浮出层
     下缘会探出卡外缘 6px（[33,284,309,395] vs 卡下缘 673），收成 8 + 12 后
     四缘全在卡内。 */
  .alo-hist-filter .adc-calpop { top: calc(100% + var(--s2)); padding: var(--s3); }
  /* 切月组件在 375 仍是 36 命中区，只把读数收一档 15px，年月两槽随字号同收 */
  .alo-mswitch { gap: 0; }
  .alo-mswitch-read { font-size: 15px; }
  .alo-mswitch-yr { width: 36px; }
  .alo-mswitch-mo { width: 19px; }
}


/* ============================================================================
   lgj-160-notice.css —— 「公告」页作用域样式（v1.6.0 W9 二轮重做，N4，20260915；
   四轮 T4 改博客 / 日志格式，20260916；五轮 V3 改横向长卡 + 简约排序，20260916）
   契约 = `练功志-v160-四轮工单集-T0-T6-20260916.md`「T4」卡七条 +
   `练功志-v160-五轮工单集-V1-V3-20260916.md`「V3」卡契约四条。
   owner 四轮逐字：「你的公告 全都不能点进去看，不要默认展示公告的全部内容，
   每个做成一个固定长宽的卡片，显示摘要，点进去才是完整内容，10个卡片就换页，
   就是做成博客 / 日志 的格式【不允许评论】」「截图8，右侧这个发布新公告组件
   去掉，换成sorting逻辑的组件」「截图9，"新公告"换成"发布公告"，做成一个入口
   按钮，然后点击后是一个新页」。

   四轮改动面（二轮骨架里留下来的、owner 没点名的一律不动）：
     · 保留：三栏 .ntc-layout（列宽一格不改）、左栏筛选链 .ntc-filter 一族、
       弟子左栏读数 .ntc-railstat、中栏读数条 .ntc-stats 一族、置顶小标
       .ntc-pin、空态 .ntc-empty、行内二次确认 .ntc-acts / .ntc-confirm /
       .ntc-act 的笔法与文案。
     · 退役：一条一行的账（.ntc-list / .ntc-item / .ntc-head / .ntc-title /
       .ntc-sub / .ntc-excerpt / .ntc-date / .ntc-body / .ntc-item--read）、
       右栏常驻发布表单（.ntc-field / .ntc-textarea / .ntc-form-foot /
       .ntc-form-btns）、左栏暗文链 .ntc-newlink、弟子两栏态 .ntc-layout--read
       （弟子改与管理员同一套三栏，逐像素同位，S8 精神由「同一个类」保证）。
     · 新增：卡阵 .ntc-grid / .ntc-card 一族、分页条 .ntc-pager
       一族、右栏排序组件 .ntc-side / .ntc-sorts / .ntc-sort、详情页 .ntc-art
       一族。（四轮编辑器 .ntc-ed 一族随五轮 V5 换 Quill 退役，样式在 lgj-160-editor.css；
       本文件零 .ntc-ed 规则，.ntc-label / .ntc-input / .ntc-count / .ntc-pinbox 四条随之退役——集成修补三。）

   五轮 V3 改动面（owner G5 逐字「公告的卡片不是正方形，而是一行一行的长方形
   矩形，一行就一个长卡片，总共10个就换页」「右侧的sorting也不好看，建议换成
   简单的 不是按钮版本的 简约点的」）：
     · .ntc-grid 由 3/2/1 列改单列（列数断点整块退役），.ntc-card 由 220 见方
       改 112 横向长卡（≤767 折成 134），卡内由五段纵排改两列三行网格。
     · .ntc-sort 由 32 高描边格改幽灵文字项（生效 = 浓墨 600 + 2px 短竖线）。
     · 其余（.ntc-side 面板纸、节题、分页条、置顶小标、二次确认文案、详情页与
       编辑器一族）owner 没点名，一字不动。

   六轮 X3 改动面（owner H6 逐字「截图5 这整个组件 多余，去掉」；H7 逐字
   「截图6，不要有框感，我说了要做成简单的，可以参考截图7的范式。截图6这个
   位置 做成：搜索 功能，排序用选择的方式 选 最新公告，最早公告。 筛选 有这
   几个分类可选【置顶】【农业】以后再慢慢加」；H5 逐字「字太小了，尤其是左侧栏
   你明显和 其他页的左侧栏字号大小不一致…当出现两个页不一致的时候，字号取更大
   的那个值」）：
     · 退役：中栏四格读数条 .ntc-stats / .ntc-stat / .ntc-stat-k / .ntc-stat-v
       / .ntc-stat--date（DOM 与 CSS 两边全删，含 767 档那一组折法）；右栏面板纸
       .ntc-side 的底 / 框 / 圆角 / 内距与节题 .ntc-side-title、幽灵文字列
       .ntc-sorts / .ntc-sort。
     · 新增：右栏改挂 app.css 的 .notes-side / .notes-side-sec /
       .notes-side-title / .notes-sideinput / .notes-sortopt（阳神班右栏范式，
       只复用不改一个字，本文件只作公告页作用域的字号与定高覆写）；编辑器
       分类行 .ntc-catrow / .ntc-catlabel / .ntc-catopts。
     · 字号（索引 §4 标准，三栏页面内最小 13）：左栏筛选项 13 → 15、计数
       12 → 15、公告总数 13 → 15、发布公告键 13 → 15、弟子左栏读数 13 → 15；
       卡内「置顶」小标 11 → 13、卡脚「编辑 / 置顶 / 删除」12 → 15、
       「阅读全文」12 → 13、删除确认那句 12 → 13；分页条 13 → 15、分隔点
       12 → 13；详情页日期 12 → 13；右栏节题 12 → 16/600、选项 13 → 15。
     · 定高重算（字号一涨，槽位一律跟着重算，不许靠行高溢出撑）：
       卡脚 36（18+18）→ 40（20+20）；置顶槽 16 → 18；长卡 112 → 118
       （= 2×16 内距 + 28 题 + 18 置顶槽 + 40 卡脚）；375 档 148 → 152
       （= 2×16 + 28 + 52 摘要 + 40）；删除确认组 22 → 24；右栏节题 24、
       右栏选项 32、编辑器分类行 58（= 18 标签 + 8 + 32 选项）。
       一处仍不用 min-height。

   三条纪律在本文件里的落法：
     · 一种边框灰：只用 var(--line) 一支笔；生效态的浓墨描边是状态色不是第二
       种边框灰；卡内只有一层描边，卡与卡之间隔 12px 不相接不共边（SPEC §11.1）。
     · 定高纪律：会随状态切换的槽位一律 height 定死，禁 min-height；卡内三行
       与右区三槽全部定高，操作组与「阅读全文」同槽，删除确认组让摘要
       visibility 让开（卡高一格不动），窄屏无 hover 才常显。
     · 色彩只落数据：本页零朱零彩，置顶只用一个淡墨小标；破坏性确认也走墨色。
     · 层次只到 L1：卡纸 / 详情纸 / 编辑器纸 = --paper-2 + 一道乌丝 + 3px，零
       阴影；本页没有浮在别的内容之上的层，故零 box-shadow 零 backdrop-filter。
   注释里禁写星号斜杠连写，会提前关注释。
   ========================================================================== */

/* ---- 三栏布局：横向空间先给中栏，右栏 340px 装下排序组件 ---------------
   弟子与管理员**同一个类**：四轮 owner 把右栏换成排序组件之后，两个身份的
   右栏内容完全一样，两栏态没有存在理由了；同类即同栅格，左栏 x 不可能漂移
   （三轮 W12 S8「弟子视角的 公告 左栏位置需要和 管理员视角一样」由此变成
   结构上不可违反，而不是两条规则对齐出来的）。 */
/* 六轮 X5(owner H9「所有页面用一个规范 布局位置」):本页原本已是 200 / 340 /
   32,四页统一后这三个数改由 --rail-l / --rail-r / --rail-gap 供给,值不变,
   改栏宽只改 tokens.css 一处。 */
.ntc-layout {
  display: grid;
  grid-template-columns: var(--rail-l) minmax(0, 1fr) var(--rail-r);
  gap: var(--rail-gap);
  align-items: start;
}
/* 详情页与编辑器页：同一张壳的读页态，左栏仍是第一列 200px（x 一个数不动），
   右栏排序组件在这两页无意义故不渲染。
   八轮 Z1（owner K2 逐字「公告详情页 的 卡片宽度 要和 公告列表页 的宽度一致，
   目前是详情页宽度太窄了」）：原先这一态自立一套两列栅格（200 / minmax(0,780)），
   中栏宽度由 780 这个自创上限说了算，与列表页中栏（1fr，1440 实测 762）不是
   一个数，卡片左缘对齐、右缘却各走各的——两页来回切时纸的边在动。改成与列表
   【同一条栅格】：三列原样声明（左 --rail-l / 中 1fr / 右 --rail-r），右栏这两页
   不渲染节点，第三列留空占位。中栏因此与列表页逐像素相同（栅格算式相同即相同），
   780 这个上限整条退役；行宽不再靠容器上限管，改由 .ntc-art-body 的 max-width
   管（见下方）——容器管对齐，行宽管阅读，两件事分开。 */
.ntc-layout--doc {
  grid-template-columns: var(--rail-l) minmax(0, 1fr) var(--rail-r);
}

/* ---- 左栏：筛选暗文链（同 .adm-link 一支笔，右端挂读数） -----------------
   六轮 H5：owner 点名「字太小了，尤其是左侧栏 你明显和 其他页的左侧栏字号
   大小不一致」。按索引 §4「左栏链接项 15 / 左栏计数 15 等宽」上调；行盒
   = 10 上 + 24 行 + 10 下 = 44，与弟子左栏 .ntc-railstat 同高。 */
.ntc-filter {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  font-size: var(--fs-body);
  line-height: 24px;
}
.ntc-filter-n {
  flex: 0 0 auto;
  font-family: var(--font-num);
  font-size: var(--fs-body);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
/* 「公告总数 N 条」与左栏项同一档（app.css 的 .adm-count 是 13）。
   .adm-count--rail 是管理页 / 阳神班共用的全局类，故必须挂在本页的栅格容器
   之下限定作用域——本文件不许改到别的页（X5 才做全站统一）。 */
.ntc-layout .adm-count--rail { font-size: var(--fs-body); }
.ntc-filter[data-on="1"] { color: var(--ink); font-weight: 600; }
.ntc-filter[data-on="1"] .ntc-filter-n { color: var(--ink); }
/* owner F9：「新公告」暗文链 -> 「发布公告」入口按钮。满栏宽 36px 幽灵按钮，
   沉在「公告总数」之下（位次与二轮那条暗文链一致），黑底留给编辑器那一枚。 */
.ntc-newbtn {
  display: flex;
  width: 100%;
  height: 36px;
  margin-top: var(--s4);
  font-size: var(--fs-body);
}

/* 弟子视图左栏的三行读数（不可点，只是数） */
.ntc-railstat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 24px;
  color: var(--ink-3);
  padding: 10px 2px;
}
.ntc-railstat + .ntc-railstat { border-top: var(--lw-line) dashed rgba(var(--line-rgb), .5); }
.ntc-railstat b {
  font-family: var(--font-num);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* ---- 中栏顶部读数条（.ntc-stats 一族）：六轮 X3 契约 1 整块删除 ----------
   owner H6 逐字「截图5 这整个组件 多余，去掉」。类与 DOM 两边都不再有，中栏
   顶部直接是长卡列（同一组读数在左栏筛选链右端与「公告总数」那行仍在，owner
   没点名的不删）。 */

/* ---- 中栏卡阵：一行一张的横向长卡（五轮 G5），全档单列 ------------------
   owner 逐字「公告的卡片不是正方形，而是一行一行的长方形矩形，一行就一个长
   卡片，总共10个就换页」。列数不再随视口变：1440 / 1280 / 1024 / 375 一律
   单列，只有卡高按档位分两档（>=768 是 112，<=767 因为右区折下来是 134）。
   10 卡一页 = 10 × 112 + 9 × 12 = 1228 高的一列，分页条 32 收底。 */
.ntc-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s3);
}
/* 卡 = L1 抬起的面：票面纸 + 一道乌丝 + 3px，零阴影；高 118 定死（六轮 H5
   字号上调后重算，五轮是 112）。
   卡内是一张两列三行的网格，每一行都定高（28 / 18 / 40 = 86 = 118 − 2×16）：
     行一  题（一行截断，18px 600 浓墨）      | 日期 18（右对齐，等宽数字）
     行二  摘要（两行截断，48 = 2 × 24）      | 置顶小标槽 18（有无置顶都占位）
     行三  摘要（同上，纵跨二三行）            | 卡脚槽 40 = 两行 × 20
   右列定宽 120：不管标题多长，日期与卡脚永远在同一条竖线上收齐。
   卡脚槽 40 是**两行**（返工一，复核 P1-1）：上行管理员操作组、下行「阅读全文」
   幽灵字。六轮把操作组的字从 12 提到 15（owner 截图四红框点名卡脚），15px 的行盒
   放不进 18 的行，两行各由 18 改 20，槽由 36 改 40，卡高随之 112 → 118；
   置顶小标 11 → 13 同理把槽由 16 提到 18。10 卡整列 = 10 × 118 + 9 × 12 = 1288。 */
.ntc-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 120px;
  grid-template-rows: 28px 18px 40px;
  grid-template-areas:
    "title date"
    "sum   flag"
    "sum   foot";
  column-gap: var(--s4);
  height: 118px;
  padding: var(--s4);
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out);
}
.ntc-card:hover { background: var(--paper-3); }
/* 刚发布/刚保存的那一条：同一支笔深一档（衬纸 + 浓墨描边），不跳色不加阴影 */
.ntc-card[data-focus="1"],
.ntc-card[data-focus="1"]:hover { background: var(--paper-3); border-color: var(--ink); }
.ntc-card-flag {
  grid-area: flag;
  align-self: start;
  height: 18px;
  overflow: hidden;
  text-align: right;
}
/* 置顶小标：同一支笔淡一档的墨字，无底无框无朱（六轮 H5：11 → 13，槽 16 → 18） */
.ntc-pin {
  display: block;
  line-height: 18px;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
}
/* 集成修补二（V3 复验 P2-2）：小标默认行高 19.25 装进 16 的槽会被裁掉下半截
   （四轮起就如此），钉成 16 行高的块，槽高与卡高零变化。 */
/* 题：横向长卡上只留一行，18px 600（长卡的横向余量换成了更大的题字号）。 */
.ntc-card-title {
  grid-area: title;
  height: 28px;
  margin: 0;
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: 600;
  line-height: 28px;
  color: var(--ink);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  overflow: hidden;
  word-break: break-all;
  line-break: strict;
}
.ntc-card-date {
  grid-area: date;
  align-self: start;
  display: block;
  height: 18px;
  line-height: 18px;
  font-family: var(--font-num);
  font-size: var(--fs-body-sm);
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--ink-3);
}
/* 摘要：两行截断，48 = 2 × 24。服务端 summary 是 81 字，长卡左区只放得下前
   两行，第三行没有落脚处（与四轮三行卡同一口径，只是行数改了）。 */
.ntc-card-sum {
  grid-area: sum;
  align-self: start;
  height: 48px;
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 24px;
  color: var(--ink-2);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  word-break: break-all;
  line-break: strict;
}
/* 卡脚：右区最底下那个 40px 槽，两行各 20，一律右对齐——
   上行 = 管理员三键操作组（弟子没有，那一行空着但槽照占，卡高两角色恒等）；
   下行 = 「阅读全文」幽灵字（两个角色都有，四轮就有，返工一还回来）。 */
.ntc-card-foot {
  grid-area: foot;
  position: relative;
  height: 40px;
}
.ntc-acts {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s3);
  height: 20px;
  white-space: nowrap;
}
/* 删除确认组不进那个 120 的槽：「删除之后不能恢复 · 确认删除 · 取消」比 120
   宽得多，挂在卡上靠右下角贴住，确认态让摘要 visibility 让开（高度不动）。 */
.ntc-confirm {
  position: absolute;
  right: var(--s4);
  bottom: var(--s4);
  display: flex;
  align-items: center;
  gap: var(--s2);
  height: 24px;
  white-space: nowrap;
  visibility: hidden;
}
/* 那句话让位给两枚键:窄卡上先截它,不许把「确认删除 / 取消」挤出卡外 */
.ntc-confirm-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ntc-confirm .ntc-act { flex: 0 0 auto; }
/* 下行：top 20 = 顶着操作组那一行的底边，两行零重叠（实拍逐 px 钉） */
.ntc-more {
  position: absolute;
  right: 0;
  top: 20px;
  height: 20px;
  line-height: 20px;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
  white-space: nowrap;
}
/* 法则③：静止极净，hover / 聚焦才显影 */
.ntc-acts,
.ntc-more { opacity: 0; transition: opacity var(--t-fast) var(--ease-out); }
.ntc-card:hover .ntc-acts,
.ntc-card:hover .ntc-more,
.ntc-card:focus .ntc-more,
.ntc-card:focus-within .ntc-acts,
.ntc-card:focus-within .ntc-more,
.ntc-card[data-hover="1"] .ntc-acts,
.ntc-card[data-hover="1"] .ntc-more { opacity: 1; }
/* 确认态：那一句话横着压过来，摘要整段让开（visibility 不动高度） */
.ntc-card[data-confirm="1"] .ntc-acts,
.ntc-card[data-confirm="1"] .ntc-card-sum,
.ntc-card[data-confirm="1"] .ntc-more { visibility: hidden; }
.ntc-card[data-confirm="1"] .ntc-confirm { visibility: visible; }
/* 六轮 H5：owner 截图四把卡脚「编辑 返回公告」红框点名，12 → 15（索引 §4
   「左栏链接项 / 右栏选项 / 分段键 15」同档，卡上与详情页同一支笔）。 */
.ntc-act {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 20px;
  color: var(--ink-3);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}
.ntc-act:hover { color: var(--ink); }
/* 二次确认的那一下是行内文字，不是系统弹窗；用浓墨加重，不上朱 */
.ntc-act--strong { color: var(--ink); font-weight: 600; }
.ntc-confirm-text {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 24px;
  color: var(--ink-2);
}

/* ---- 分页条：「上一页 · 第 n / N 页 · 下一页」，等宽数字，居中收底 ------ */
.ntc-pagerwrap { margin-top: var(--s5); }
.ntc-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s3);
  height: 32px;
}
.ntc-page {
  height: 32px;
  padding: 0 var(--s3);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink-2);
  background: transparent;
  border: none;
  cursor: pointer;
}
.ntc-page:hover { color: var(--ink); }
.ntc-page[aria-disabled="true"],
.ntc-page[aria-disabled="true"]:hover { color: var(--ink-3); cursor: default; }
.ntc-pager-sep { font-family: var(--font-body); font-size: var(--fs-body-sm); color: var(--ink-3); }
.ntc-pager-at { font-family: var(--font-body); font-size: var(--fs-body); color: var(--ink-3); }
.ntc-pager-n {
  font-family: var(--font-num);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* ---- 右栏：搜索 / 排序 / 筛选（六轮 X3 契约 2；管理员与弟子同一套）------
   owner H7 逐字「截图6，不要有框感，我说了要做成简单的，可以参考截图7的范式」
   ——截图7 = 阳神班右栏。于是五轮那张 L1 面板纸（底 + 一圈乌丝 + 3px 圆角 +
   16 内距）与 .ntc-sorts / .ntc-sort 幽灵文字列整块退役，右栏改挂 app.css 里
   阳神班那套现成语汇：
     壳   aside.notes-side      —— sticky、只左侧一道乌丝、零底零框零圆角
     节   .notes-side-sec + .notes-side-title
     搜索 .notes-sideinput（一枚 input）
     选项 .notes-sortopt（12px 圆点单选，选中 i::after 填色）
   那四支笔一个字不改（X3 禁区），本文件只在 .ntc-side 作用域内做公告页的
   字号与定高覆写：索引 §4「栏内节题 16/600、右栏选项 15」。 */
.ntc-side { padding-bottom: var(--s5); }
/* 节题：范式里是 12px 400，六轮 H5 统一到 16/600；定高 24 一行，切节零跳动。
   颜色不覆写——那是范式的一部分（app.css 的 --ink-3）。 */
.ntc-side .notes-side-title {
  height: 24px;
  line-height: 24px;
  font-size: var(--fs-sub);
  font-weight: 600;
  margin: 0 0 var(--s3);
}
.ntc-side .notes-sideinput input { font-size: var(--fs-body); }
/* 选项行：范式用 padding 撑高（13px + 6 上 6 下），六轮字号提到 15 之后改为
   直接定高 32，三节的行距因此逐行相等（定高纪律：不靠内距推算高度）。 */
.ntc-side .notes-sortopt {
  height: 32px;
  padding: 0;
  font-size: var(--fs-body);
}
/* 选中态加重一档：范式只换墨色，公告页的三节都是单选，600 让当前项一眼可辨
   （与左栏筛选链 [data-on] 同一手法，零第二种指示语汇）。 */
.ntc-side .notes-sortopt[data-on="1"] { font-weight: 600; }

/* ---- 编辑器「分类」行（X3 契约 3）：标题位之下一行，同款圆点单选 --------
   定高 58 = 标签 18 + 8 + 选项 32。标签与 .lgjed-label 同位同色，只是按索引
   §4「字段标签 13」由 11 提到 13。选项复用 .notes-sortopt，横排。 */
.ntc-catrow {
  height: 58px;
  margin-bottom: var(--s4);
}
.ntc-catlabel {
  display: block;
  height: 18px;
  line-height: 18px;
  margin: 0 0 var(--s2);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
}
.ntc-catopts {
  display: flex;
  align-items: center;
  gap: var(--s5);
  height: 32px;
}
.ntc-catopts .notes-sortopt {
  width: auto;
  height: 32px;
  padding: 0;
  font-size: var(--fs-body);
}
.ntc-catopts .notes-sortopt[data-on="1"] { font-weight: 600; }

/* ---- 详情页：中栏一张纸，正文按白名单富文本渲染，零评论 ---------------- */
.ntc-art {
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  padding: var(--s6);
}
.ntc-art-flag { height: 16px; overflow: hidden; }
.ntc-art-title {
  margin: 0;
  font-family: var(--font-body);
  font-size: 22px;
  font-weight: 600;
  line-height: 32px;
  color: var(--ink);
}
.ntc-art-date {
  height: 20px;
  line-height: 20px;
  margin: var(--s2) 0 0;
  font-family: var(--font-num);
  font-size: var(--fs-body-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
/* 八轮 Z1（owner K2「优化一下详情页UI」）：行宽上限由 62ch 改 40em。
   换单位不是换写法，是因为 `ch` 在本站【随字体到货而变】。`ch` = 当前字体里
   「0」的 advance；本站 WenKai 按 unicode-range 切了 77 个分片异步到货，
   字体未到货时用回退 KaiTi 的零（7.5px = 0.5em → 62ch = 465px），到货后
   Chrome 会重排成 WenKai 的零（9px = 0.6em → 62ch = 558px）。465 只是首屏
   瞬态：1440 档 headless + CDP 实测，fonts.status='loading' 时读到 465，
   同一元素不碰 DOM 3/3 自行重排成 558；等 fonts.ready 后 13/13 恒 558。
   而 40em = 600px 从首屏到到货后恒定，与字体无关。
   （复核复验一更正了返工一里「到货 7.5 / 未到 9」与「解析一次不再重算」
   两处写反的归因；像素结论不变。）
   取 40em 的另一半理由是它按汉字说得清：实测本页汉字 advance = 15px = 1em，
   故 600px 恰好每行 40 个汉字，落在中文正文 30-45 字舒适区的上沿；对比
   62ch 的到货态与瞬态分别是每行 37 字与 31 字。行宽因此比基座到货态
   宽 42px、比首屏瞬态宽 135px。
   卡内容盒 = 762 - 2×32 = 698，600 < 698，右侧留 98px 余白不顶到边框。 */
.ntc-art-body {
  margin-top: var(--s5);
  max-width: 40em;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink-2);
  word-break: break-all;
  line-break: strict;
}
.ntc-art-body p { margin: 0; }
.ntc-art-body p + p { margin-top: var(--s3); }
.ntc-art-body a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.ntc-art-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s4);
  height: 24px;
  margin-top: var(--s6);
}
.ntc-art-wait {
  height: 24px;
  line-height: 24px;
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}

/* ---- 空态：一句引导词，不写说明句不放按钮 ---- */
.ntc-empty {
  grid-column: 1 / -1;
  height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---- 五轮起卡阵没有列数断点了 -------------------------------------------
   四轮那一档「≤1439 收两列」是为了保住 220 见方的卡宽，五轮 owner 把卡改成
   一行一张的长卡之后，列数在任何视口都只有一列，1439 那道闸整块退役：长卡
   只需要横向够宽，视口越窄它只是越短，不会互相压字。剩下两档媒体查询——
   ≤1120 跟着 app.css 塌栏，≤767 把右区折下来。
   ------------------------------------------------------------------------ */

/* ---- ≤1120 塌栏：与 app.css 的 .adm-layout 同一道断点 --------------------
   本页复用 .adm-rail / .adm-links，而 app.css 在 ≤1120 就把左栏改横条、把链列
   改 flex 横排；三栏栅格必须在同一道断点塌，否则 768-1120 这一档中栏被挤到
   一两百像素。该档长卡照旧单列 112 高（卡反而更宽），右栏排序组件落到分页条
   之下。
   ------------------------------------------------------------------------ */
@media (max-width: 1439px) {
  /* 六轮 X5：三栏 / 纵排断点全站统一为 1439，本页原 1120 退役。
     返工一（复核 P1-3）：原本这一档只写 display:block，右栏因此按 DOM 次序落到
     25 张长卡与分页条【之后】（1280 实测 .ntc-side top = 1711，基座同视口是
     146.25 的三栏态）——用户要滚过整页才够得着「搜索 / 排序 / 筛选」。契约 1
     逐字是「右栏落到中栏上方成工具条，沿用管理页折法」，故改纵排 flex + order，
     与 app.css §25b 的 `.page--admin .adm-rail{order:0}` `.adm-main{order:2}`
     同一支笔；DOM 一个节点没动（order 只改视觉次序，tab 顺序仍按 DOM，右栏在
     中栏之后读到，读屏用户的次序与三栏态一致）。 */
  .ntc-layout, .ntc-layout--doc { display: flex; flex-direction: column; align-items: stretch; }
  .ntc-layout > .adm-rail { order: 0; }
  .ntc-layout > .ntc-side { order: 1; }
  .ntc-layout > .adm-main { order: 2; }
  /* 左栏此档已是横条：筛选链与读数一律不断字，右端计数跟在标签后一格 */
  .ntc-filter, .ntc-railstat { white-space: nowrap; }
  .ntc-railstat { padding: 6px 2px; }
  .ntc-railstat + .ntc-railstat { border-top: 0; }
  .ntc-newbtn { width: auto; margin-top: 0; padding: 0 var(--s4); }
  /* 右栏落到分页条之下成一块横条：三节并排（同阳神班管理页在本档的折法
     `.adm-side.notes-side{display:flex}`），左侧那道乌丝（竖着分栏用的）换成
     顶上一道，sticky 一并解除——范式的 .notes-side 在三栏态才成立。
     写成 .ntc-side.notes-side（两个类）是必需的：app.css 的弟子心得页在本档
     有一条 `.notes-side{display:none}`（那页改用 .notes-mobilebar），公告页
     复用范式壳之后会被它一并吞掉（首版实拍在 1024 / 375 量到右栏整块 0 高，
     就是这条）。特异性压过它，不靠文件先后。 */
  .ntc-side.notes-side {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s6);
    position: static;
    /* 返工一：工具条现在排在中栏【之上】，上距由「跟在分页条后面」的 --s6
       改成 --s4，下面再留 --s5 与长卡列分组（组内 < 组间）。 */
    margin: var(--s4) 0 var(--s5);
    padding: var(--s4) 0 0;
    border-left: 0;
    border-top: var(--lw-hair) solid var(--line);
  }
  .ntc-side .notes-side-sec { margin-bottom: 0; flex: 0 1 260px; }
  .ntc-art { margin-top: var(--s5); }
}

/* ---- 375 折法：读数条收成二×二，长卡把右区折下来，操作组与「阅读全文」常显 ---- */
@media (max-width: 760px) {
  /* 六轮 X5：窄屏断点全站统一为 760，本页原 767 退役。
     375 只有 343 的卡宽，装不下「左区 + 120 右区」两列：日期折到标题行右端，
     置顶槽与卡脚折到最后一行。每一行仍定高，卡高 152 = 2×16 padding +
     28（题/日期）+ 52（摘要 48 靠上）+ 40（置顶槽 / 两行卡脚）。
     卡脚仍是桌面档那两行（操作组 20 + 「阅读全文」20），笔法一档不变。 */
  .ntc-card {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: 28px 52px 40px;
    grid-template-areas:
      "title date"
      "sum   sum"
      "flag  foot";
    height: 152px;
  }
  .ntc-card-date { align-self: center; margin-left: var(--s3); }
  .ntc-card-flag { align-self: center; text-align: left; }
  /* 触屏没有 hover：卡脚三组常显，删除确认仍走同槽 visibility */
  .ntc-acts, .ntc-more { opacity: 1; }
  /* 375 单列：三节由并排回到纵排（同阳神班管理页 ≤760 的 `display:block`） */
  .ntc-side.notes-side { display: block; }
  .ntc-side .notes-side-sec { margin-bottom: var(--s5); }
  .ntc-art { padding: var(--s4); }
  .ntc-art-title { font-size: 20px; line-height: 28px; }
}

/* ==========================================================================
   lgj-160-editor.css —— 公告编辑器页（v1.6.0 五轮 V5，20260916）
   作用域：.lgjed 一族（ui-notice-editor.js 产出的那张纸）+ 该纸内部 Quill
   Snow 主题的令牌化覆写。独立成文件是并行纪律：本卡与 V3 卡（公告列表页
   lgj-160-notice.css）零文件交集。上游任何文件一个字不动。

   owner 五轮补充原话 G6：「你为什么用文字 而不用业界通用的图标？比如加粗和
   斜体都有通用图标 居中居左居右都有通用图标，字号也有下拉选项 这些都是基本
   的啊，为什么不按照业界默认的去做【全部真实前后端，直接用现有的，尽量避免
   重复发明】？」——这句是对本项目「零图标」设计硬门的明确例外：编辑器工具条
   按业界默认用图标（Quill Snow 自带 SVG，随 currentColor 吃墨色令牌）。
   除工具条之外，本页其余各处仍旧零图标零 emoji 零彩。

   落法（三轮方案 §一 层次）：
     · L0 页底宣纸 --paper；L1 抬起的面 = 这张编辑器纸 --paper-2 + 一道乌丝
       + 3px 圆角 + 零阴影；正文纸面比纸再深一档（--paper）表达「这里可以写」。
     · box-shadow 只出现在两处真正浮在内容之上的 L2：字号下拉的选项面板、
       Quill 自带的链接浮条。零 backdrop-filter（本页零玻璃层）。
     · 一支边框灰 --line；色彩零处（朱零处，彩零处）；字重只有 400 / 600。
     · 定高纪律：全文件零 min-height；纸内每一行都用 height 占位。
     · 数字（两处字数计数、字号下拉的档位数字）一律 --font-num + tabular。

   一屏可见（G6「默认展示不全」）：纸内固定件合计 316（见下方定高表），正文
   纸面用 height: clamp(260px, calc(100vh - 520px), 420px) 吃掉剩下的高度，
   1440×900 与 1280×800 两档下纸的 bottom 都落在 innerHeight 之内。

   Snow 覆写的特异度纪律：vendor 的 quill.snow.css 由 ui-notice-editor.js 在
   运行时把 <link> 插在 <head> 最前，业务样式表（app.<hash>.css，末尾就是本
   文件）排在它之后，所以同特异度时本文件天然胜出，不必靠加权堆特异度。
   vendor css 原样不改、不算业务 CSS（它自带的裸色值全部被本文件覆写掉）。

   Snow 把「Visit URL / Enter link / Edit / Save / Remove」五句文案写死在
   css 的 content 里。本文件把这五处改成 content: attr(data-*)，值由
   ui-notice-editor.js 写进 data-*——因为 web/tools/gen-charset.js 只扫 .js
   的字符串字面量，汉字若写在 css 的 content 里不会进字体子集必需字符集，
   上屏必掉出子集回退系统楷体（owner 两次实锤投诉过的混搭）。
   注释里禁写星号斜杠连写，会提前关注释。
   ========================================================================== */

/* ---- 那张纸 ---- */
.lgjed {
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  padding: var(--s5);
}

/* ---- 题签 ---- */
.lgjed-title {
  height: 24px;
  line-height: 24px;
  margin: 0 0 var(--s4);
  font-family: var(--font-body);
  font-size: var(--fs-sub);
  font-weight: 600;
  color: var(--ink);
}

/* ---- 标题位：定高 76 = 标签 14 + 4 + 输入 36 + 4 + 计数 18 ---- */
.lgjed-field {
  height: 76px;
  margin-bottom: var(--s4);
}
.lgjed-label {
  display: block;
  height: 14px;
  line-height: 14px;
  font-family: var(--font-body);
  font-size: var(--fs-fieldlabel);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  color: var(--ink-3);
  margin: 0 0 var(--s1);
}
.lgjed-input {
  display: block;
  width: 100%;
  height: 36px;
  padding: 0 2px;
  border: none;
  border-bottom: var(--lw-line) solid var(--line);
  border-radius: 0;
  background: transparent;
  font-family: var(--font-body);
  font-size: var(--fs-fieldvalue);
  color: var(--ink);
}
.lgjed-count {
  height: 18px;
  line-height: 18px;
  margin: var(--s1) 0 0;
  font-family: var(--font-num);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--ink-3);
}

/* ---- 组件没能加载时的一句话（纸面不留空白，提交仍旧锁住）---- */
.lgjed-fallback {
  height: 260px;
  line-height: 260px;
  margin: 0;
  text-align: center;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}

/* ---- 底行：置顶勾选 + 幽灵「取消」+ 黑底「发布 / 保存」（全页唯一黑底）--
   两枚按钮之间留一档间距，两个带边的件不许相接（SPEC §11.1）。按钮 44 高是
   app.css 的全站触控红线（.btn min-height: 44px），本文件用等值 height 占位，
   不破那道红线也不被它撑破定高表。 */
.lgjed-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  height: 56px;
  margin-top: var(--s4);
}
.lgjed-pinbox {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  cursor: pointer;
}
.lgjed-pinbox input { width: 15px; height: 15px; accent-color: var(--ink); margin: 0; }
.lgjed-btns { display: flex; align-items: center; gap: var(--s3); }
.lgjed-btns .btn { height: 44px; padding: 0 var(--s4); }

/* ==========================================================================
   Quill Snow 令牌化覆写（vendor 原样不改，全部在这里改）
   ========================================================================== */

/* ---- 工具条：定高 40，零外框，只留一道收底乌丝 ---- */
.lgjed .ql-toolbar.ql-snow {
  height: 40px;
  padding: 0;
  border: 0;
  border-bottom: var(--lw-line) solid var(--line);
  border-radius: 0;
  display: flex;
  align-items: center;
  gap: var(--s4);
  font-family: var(--font-body);
}
.lgjed .ql-toolbar.ql-snow .ql-formats {
  display: flex;
  align-items: center;
  gap: var(--s1);
  margin-right: 0;
}
.lgjed .ql-toolbar.ql-snow button {
  width: 32px;
  height: 32px;
  padding: 6px;
  border: 0;
  border-radius: var(--r-ctl);
  background: transparent;
  float: none;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.lgjed .ql-toolbar.ql-snow button svg { float: none; width: 100%; height: 100%; }

/* 静止极净、交互显影（五法则③）：静止淡一档，hover 与生效态才衬纸 + 浓墨 */
.lgjed .ql-snow .ql-stroke,
.lgjed .ql-snow .ql-stroke-miter { stroke: var(--ink-2); }
.lgjed .ql-snow .ql-fill,
.lgjed .ql-snow .ql-stroke.ql-fill { fill: var(--ink-2); }

.lgjed .ql-toolbar.ql-snow button:hover,
.lgjed .ql-toolbar.ql-snow button:focus,
.lgjed .ql-toolbar.ql-snow button.ql-active,
.lgjed .ql-toolbar.ql-snow .ql-picker-label:hover,
.lgjed .ql-toolbar.ql-snow .ql-picker-label.ql-active,
.lgjed .ql-toolbar.ql-snow .ql-picker-item:hover,
.lgjed .ql-toolbar.ql-snow .ql-picker-item.ql-selected {
  color: var(--ink);
  background: var(--paper-3);
}
.lgjed .ql-toolbar.ql-snow button:hover .ql-stroke,
.lgjed .ql-toolbar.ql-snow button:focus .ql-stroke,
.lgjed .ql-toolbar.ql-snow button.ql-active .ql-stroke,
.lgjed .ql-toolbar.ql-snow button:hover .ql-stroke-miter,
.lgjed .ql-toolbar.ql-snow button:focus .ql-stroke-miter,
.lgjed .ql-toolbar.ql-snow button.ql-active .ql-stroke-miter,
.lgjed .ql-toolbar.ql-snow .ql-picker-label:hover .ql-stroke,
.lgjed .ql-toolbar.ql-snow .ql-picker-label.ql-active .ql-stroke {
  stroke: var(--ink);
}
.lgjed .ql-toolbar.ql-snow button:hover .ql-fill,
.lgjed .ql-toolbar.ql-snow button:focus .ql-fill,
.lgjed .ql-toolbar.ql-snow button.ql-active .ql-fill,
.lgjed .ql-toolbar.ql-snow button:hover .ql-stroke.ql-fill,
.lgjed .ql-toolbar.ql-snow button:focus .ql-stroke.ql-fill,
.lgjed .ql-toolbar.ql-snow button.ql-active .ql-stroke.ql-fill,
.lgjed .ql-toolbar.ql-snow .ql-picker-label:hover .ql-fill,
.lgjed .ql-toolbar.ql-snow .ql-picker-label.ql-active .ql-fill {
  fill: var(--ink);
}
/* 触屏档 Snow 自己把 hover 拉回 #444，一并令牌化 */
@media (pointer: coarse) {
  .lgjed .ql-toolbar.ql-snow button:hover:not(.ql-active) { color: var(--ink-2); }
  .lgjed .ql-toolbar.ql-snow button:hover:not(.ql-active) .ql-stroke,
  .lgjed .ql-toolbar.ql-snow button:hover:not(.ql-active) .ql-stroke-miter { stroke: var(--ink-2); }
  .lgjed .ql-toolbar.ql-snow button:hover:not(.ql-active) .ql-fill,
  .lgjed .ql-toolbar.ql-snow button:hover:not(.ql-active) .ql-stroke.ql-fill { fill: var(--ink-2); }
}

/* ---- 字号下拉：档位数字用等宽数字体，五档各自按真实字号预览 ---- */
.lgjed .ql-toolbar.ql-snow .ql-picker {
  height: 32px;
  color: var(--ink-2);
  font-family: var(--font-num);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  float: none;
}
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size { width: 56px; }
.lgjed .ql-toolbar.ql-snow .ql-picker-label {
  height: 32px;
  padding: 0 18px 0 var(--s2);
  border: 0;
  border-radius: var(--r-ctl);
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.lgjed .ql-toolbar.ql-snow .ql-picker-label::before { line-height: 32px; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
  color: var(--ink);
  background: var(--paper-3);
  border: 0;
}
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke { stroke: var(--ink); }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill { fill: var(--ink); }
/* L2 之一：下拉选项面板真的浮在正文之上，这里的阴影是方案允许的那一类 */
.lgjed .ql-toolbar.ql-snow .ql-picker-options {
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  box-shadow: var(--shadow-float);
  padding: var(--s1) 0;
  min-width: 56px;
}
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options { border-color: var(--line); }
.lgjed .ql-toolbar.ql-snow .ql-picker-item {
  height: 30px;
  padding: 0 var(--s3);
  line-height: 30px;
  color: var(--ink-2);
}
.lgjed .ql-toolbar.ql-snow .ql-picker-item.ql-selected { font-weight: 600; }

/* 档位文案只写数字（零汉字：css content 里的汉字不进字体子集）。未选档时
   显示 15 —— 正文纸面的默认字号就是 --fs-body 15px，不是随口写的占位。 */
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item::before { content: "15"; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="13px"]::before,
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="13px"]::before { content: "13"; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="15px"]::before,
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="15px"]::before { content: "15"; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="17px"]::before,
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="17px"]::before { content: "17"; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before { content: "20"; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before { content: "24"; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="13px"]::before { font-size: 13px; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="15px"]::before { font-size: 15px; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="17px"]::before { font-size: 17px; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before { font-size: 20px; }
.lgjed .ql-toolbar.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before { font-size: 24px; }

/* ---- 正文纸面：一屏可见的那道 clamp（height，不是 min-height）----------
   520 = 纸上方页面浏览高 204（报头 + 巨字页标行）+ 纸内固定件 316。
   钳在 260..420：短屏不至于挤成一条缝，长屏也不放任正文无限长。 */
.lgjed .ql-container.ql-snow {
  height: clamp(260px, calc(100vh - 520px), 420px);
  padding-top: var(--s4);
  border: 0;
  border-radius: 0;
  font-family: var(--font-body);
  font-size: var(--fs-body);
}
.lgjed .ql-editor {
  padding: var(--s3);
  background: var(--paper);
  border-radius: var(--r-ctl);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink);
  word-break: break-all;
  line-break: strict;
  scrollbar-width: none;
}
.lgjed .ql-editor::-webkit-scrollbar { display: none; }
.lgjed .ql-editor p + p { margin-top: var(--s3); }
.lgjed .ql-snow .ql-editor a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---- 链接浮条（L2 之二）：文案由 js 写进 data-*，见文件头注 ---- */
.lgjed .ql-snow .ql-tooltip {
  height: 40px;
  padding: 0 var(--s3);
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  box-shadow: var(--shadow-float);
  color: var(--ink-2);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  z-index: 2;
}
.lgjed .ql-snow .ql-tooltip::before {
  content: attr(data-lgj-view);
  line-height: 38px;
  margin-right: var(--s2);
  color: var(--ink-3);
}
.lgjed .ql-snow .ql-tooltip[data-mode="link"]::before { content: attr(data-lgj-edit); }
.lgjed .ql-snow .ql-tooltip a { line-height: 38px; color: var(--ink-2); }
.lgjed .ql-snow .ql-tooltip a:hover { color: var(--ink); }
.lgjed .ql-snow .ql-tooltip a.ql-action::after {
  content: attr(data-lgj-act);
  border-right: var(--lw-line) solid var(--line);
  margin-left: var(--s4);
  padding-right: var(--s2);
}
.lgjed .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  content: attr(data-lgj-save);
  border-right: 0;
  padding-right: 0;
}
.lgjed .ql-snow .ql-tooltip a.ql-remove::before {
  content: attr(data-lgj);
  margin-left: var(--s2);
}
.lgjed .ql-snow .ql-tooltip input[type="text"] {
  width: 240px;
  height: 28px;
  padding: 0 var(--s2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  background: var(--paper);
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink);
}

/* ---- ≤1120：三栏塌成堆叠（同 lgj-160-notice.css 的那道闸），纸让一档 ---- */
@media (max-width: 1120px) {
  .lgjed { margin-top: var(--s5); }
}

/* ---- 375：纸收一档，工具条由 Quill 自行折行（两行定高 76）---------------
   76 = 32 × 2 + 12 行距。正文纸面再钳短一档，保住底行两枚按钮在视口内。 */
@media (max-width: 767px) {
  .lgjed { padding: var(--s4); }
  .lgjed .ql-toolbar.ql-snow {
    height: 76px;
    flex-wrap: wrap;
    align-content: center;
    gap: var(--s2) var(--s3);
  }
  .lgjed .ql-container.ql-snow { height: clamp(220px, calc(100vh - 560px), 360px); }
  .lgjed .ql-snow .ql-tooltip input[type="text"] { width: 150px; }
}

/* 练功志 v1.6.0 · N5 排行榜弟子详情浮窗（W14 三轮重做 + T2 四轮改 + V4 五轮改）
   契约 = SPEC-练功志-v1.6.0-20260915.md §8.5 + 四轮工单集 T2 卡 F1/F2/F7
   + 五轮工单集 V4 卡 G7/G8/G9；
   方案 = .openaccp/coordination/练功志-v160-三轮设计方案-20260916.md §一 + §四。

   五轮三处改动（owner 图三「这两条横线去掉」「月份从单位数切到双位数，年月的
   位置就会漂移，建议固定，预留好位置」「确认成就年谱超过 7 个以后是否支持下
   滚，下方要虚化，暗示下面还有内容」）：
     · G7 .mdp-rangebar 的 border-bottom 与 .mdp-foot 的 border-top 两条横线整
       条删除（两条都是本文件自己写的，app.css 零触碰）。定高账不变。
     · G8 按月态读数拆成「年数 / 年 / 月数槽 / 月」四段，月数进 .mdp-ro-m 定宽
       两位槽，读数总宽与月份位数解耦。
     · G9 .mdp-nianpu 拆成「定高宿主 + .mdp-nianpu-scroll 滚动层」，宿主底沿
       30px 纸色渐隐（只在 [data-overflow="1"] 时生成）。

   六轮 X4 四处改动（owner「箭头处 插入一个本日练功……字号加大一些……当用户是按月
   的时候 你就不应该有"所选时段"这个词……右下方的要把 请假和迟到分开记录」）：
     · 近况三格 .mdp-stats--recent（等分三列）；
     · 两态签 .mdp-tab 13 → 15，.mdp-tabs 签距 --s4 → --s3；
     · 格标 .mdp-k 12 → 13、kind 签 .mdp-leave-kind 11 → 13（定宽 22 → 26）、
       越界提示 .mdp-msg 12 → 13（六轮字号标准「标签最小 13」）；
     · 右下 .mdp-lc 两格改 2×2 四格，块高 62 → 92，年谱 .mdp-nianpu 210 → 180。

   四轮三处改动（owner「每个月的 总时长 打卡天数 的位置 都随机的，为什么不固
   定？」「截图3，重做，只展示 近一年请假次数 和 全部请假次数」「所有的请假字样
   都换成 请假迟到」）：
     · F1 .mdp-stats 由 flex space-between 改 CSS Grid 等分列（三数 1fr 1fr 1fr，
       数带两组 1fr 1fr），.mdp-stat 标与数左对齐叠放在列起点。位置由列宽定死，
       与数字宽度解耦——翻月三个标的 left 恒等。
     · F2 .mdp-year 一族（12 月条带、柱、月号）整段删除，换成同高 62 的
       .mdp-lc 两格大数网格（近一年 N 次 / 全部 M 次），右列定高账分毫不变。
     · F7 新增 .mdp-leave-kind（11px 淡墨 kind 签）；请假与迟到同一支笔，
       迟到不上朱、不加底色——它是一个类目，不是一个警告。

   三轮 owner 原话：「还是不够好看，优化一下」「我方框框起来的都是标题，要字体
   加大」「自定义点开以后不要在横向加组件，而是直接一个浮层进行选范围就行」
   「打叉是都是不需要的统计范围」「在成就下方增加一个近一年请假情况」。

   相对二轮的三处结构变化：
     · 六个小节题从 11px 淡墨宽字距的小标签，升为 16px 齐伋浓墨的真标题（.mdp-sec）。
     · 双列带两列各是一张 L1 票面纸（--paper-2 + 乌丝 + 3px + padding），层次靠
       「纸色深一档 + 一道乌丝」，不靠阴影。
     · 自定义态的日历从卡外伴片（.mdp-duo）与卡内原位宿主（.mdp-calhost）整段
       作废，改成左列纸内一张绝对定位的 L2 玻璃浮层 .mdp-calpop——本文件唯一一处
       box-shadow、唯一一处 backdrop-filter。

   纪律（与方案 §一同）：零裸色值（颜色/线宽/间距/圆角/动效一律 var(--*)）、一种
   边框灰（--line）、默认态零阴影（阴影只在 L2 浮层）、字重只 400/600、会随数据
   变高的区域一律 height 定死禁 min-height、请假永不用朱色、任何位置不出现编号。

   定高账（卡 722 = 24 纸上边距 + 64 题带 + 16 + 92 数带 + 24 + 406 双列带 + 16 +
   64 卡脚 + 16 纸下边距）：
     .mdp-cols 406 = 两列纸的外框高；每列纸 = 12 padding + 380 内容 + 12 padding
       + 1+1 乌丝描边。
     左列内容 380 = 28 题 + 12 + 36 工具条 + 22 提示位 + 12 + 52 三数 + 24 + 28 题
       + 16 + 150 请假（5 行 × 30）。
     右列内容 380 = 28 题 + 12 + 210 成就（十轮 N1 起＝两列 11 行栅格；此前是
       年谱 7 行 × 30，块高同为 210，账面一个数未动） + 24 + 28 题 + 16 + 62 四计数。
     （六轮 X4 契约 4：右下两计数拆成四计数。返工一（复核 P1-1）：四计数由 2×2 改
      **一行四列**，块高退回 62 ＝ 与拆分前完全同值，右列这一行算式因此一个数都没动，
      年谱回到 owner 两轮亲验、SPEC §10 冻结的 210（7 行 × 30）。
      一行四列的列宽 ＝ (405 − 3 × 12 列距) ÷ 4 ＝ 92.25px。）
     方案把 406 写成「内容总和」，未计 L1 纸的 padding 与描边（每列 26px）。这里
     以 406 为纸的外框高（1024×768 视口下整卡不裁切是硬约束，卡高只有 722 的余量），
     两个内滚窗因此各降一行：请假 6→5 行、年谱 8→7 行；其余每一行与每一档间距
     与方案分毫不差，全部落在 --s 令牌上。 */

/* ============================================================================
   .mdp-*（member detail popup）—— 弟子详情浮窗 · 三轮重做（W14，20260916）
   ========================================================================== */

/* ---- 卡：960 定宽，三带（题带 / 数带 / 双列带）+ 卡脚 -------------------- */
.book-card.mdp-card {
  max-width: 960px;
  width: min(960px, calc(100vw - 48px));
  border-radius: var(--r-pop);
}
.mdp-card .ticket-body { display: flex; flex-direction: column; }

/* ---- 题带：姓名 26px（左）+「查看心得」幽灵入口（右），定高 64px ----------
   三轮 owner「方框框起来的都是标题，要字体加大」：姓名 22 → 26，字族仍是楷体系
   （--font-body 文楷，不用齐伋，同小节题那条裁决），与六个小节题一起构成本卡的
   两级标题。64 = 幽灵按钮 32 + 上下各 16，让按钮
   描边与下沿那道乌丝不相切（SPEC §11.1 禁框打架）。 */
.mdp-top {
  display: flex;
  align-items: center;
  gap: var(--s4);
  height: 64px;
  flex: 0 0 auto;
  border-bottom: var(--lw-hair) solid var(--line);
  margin-bottom: var(--s4);
}
.mdp-name {
  margin-right: auto;
  min-width: 0;
  font-family: var(--font-body);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: var(--ls-display);
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 只读卡零黑底主按钮：心得入口是幽灵键（.btn.btn-ghost），比通用 40 档矮一档，
   让它读作「卡内的一个去处」而不是卡的主操作。 */
.mdp-notes {
  flex: 0 0 auto;
  height: 32px;
  padding: 0 var(--s3);
  font-size: var(--fs-body-sm);
}

/* ---- 小节题：六个（练功累计 / 近况 / 时段统计 / 请假迟到（所选时段） / 成就 / 请假迟到）
   16px 浓墨 600，高 28。编码真实结构，不是 eyebrow，不带任何解释句。
   字族走文楷 --font-body 而不是齐伋 --font-display（主编排 20260916 13:1x 裁决，
   盖过方案 §四与 SPEC §8.5 原文）：齐伋是明刻本字体，会把「练／况／时段统计／
   年谱／请假」渲染成繁体，与卡内简体同屏（W13 已实拍撞上）。 */
.mdp-sec {
  display: flex;
  align-items: center;
  height: 28px;
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-sub);
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink);
}
.mdp-sec--gap { margin-top: var(--s5); }
/* 小节右端挂一个数（请假天数 / 近一年合计）：省掉一整行独立汇总行，也让这一节
   在展开逐条之前先给结论。请假永不上朱，用重墨。 */
.mdp-sec-count {
  margin-left: auto;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body-sm);
  font-weight: 400;
  color: var(--ink-2);
}

/* ---- 数带：练功累计 两数 | 近况 两数 --------------------------------------
   三轮删「单次最长」「连续天数」（owner 红叉）。两组之间一道竖乌丝：留白已经
   用在了组内两数之间，组界要读得出来就得有一道线，这是全站唯一那种边框灰。 */
.mdp-band { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s6); flex: 0 0 auto; }
.mdp-group { display: flex; flex-direction: column; min-width: 0; }
.mdp-group + .mdp-group {
  border-left: var(--lw-line) solid var(--line);
  padding-left: var(--s6);
}

/* 四轮 F1（owner「每个月的 总时长 打卡天数 的位置 都随机的，为什么不固定？」）：
   原写法是 flex + space-between + flex:0 1 auto，每块收成自身宽度，于是「2 天」
   与「22 天」两个月份下三块的宽度不同、整排的分界随数据左右漂。改成 CSS Grid
   等分列——列宽只由列数决定（三数 1fr 1fr 1fr，数带两组 1fr 1fr），标与数一律
   左对齐叠放在各自列的起点，任何月份、任何位数，三个标的 left 一个像素不动。
   与法则⑤「数字右对齐」的取舍：owner 逐字要的是位置固定，本卡按四轮工单契约 1
   取左对齐；--font-num 与 tabular-nums 全保留，同一列跨月的数字仍逐位对齐。 */
.mdp-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: var(--s3);
  height: 52px;
  flex: 0 0 auto;
  margin-top: var(--s3);
}
/* 六轮 X4 契约 1（owner「箭头处 插入一个本日练功」）：近况由两格改三格，与时段
   三数同一种等分列写法；「练功累计」仍是两格，两组各自等分，标与数照旧左对齐叠放
   在列起点（四轮 F1 的位置固定不受影响）。 */
.mdp-stats--recent { grid-template-columns: 1fr 1fr 1fr; }
.mdp-stats--range { grid-template-columns: 1fr 1fr 1fr; }
.mdp-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  min-width: 0;
  overflow: hidden;
}
/* 六轮字号标准（六轮关键事实索引 §4「字段标签…11 / 11.5 / 12 / 12.5 一律升到
   13」）：格标签 12 → 13。.mdp-stats 定高 52 不变：13 × 1.3 ＝ 16.9 标 + 4 +
   22 × 1.2 ＝ 26.4 数 ＝ 47.3 < 52。 */
.mdp-k {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.3;
  color: var(--ink-3);
  white-space: nowrap;
}
.mdp-v {
  margin-top: var(--s1);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  white-space: nowrap;
}
.mdp-v-u { font-family: var(--font-body); font-size: var(--fs-body-sm); font-weight: 400; color: var(--ink-2); }
/* 零值：同一支笔更浅一档，不写「暂无数据」一类句子 */
.mdp-v[data-zero="1"] { color: var(--ink-3); }
/* 时段三数比数带低一档（22 → 17 / 600 → 400）：卡的主数在数带，时段三数是随
   时段变的从属数，字号跳跃 + 字重跳跃双重编码层级。 */
.mdp-stats--range .mdp-v { font-size: 17px; font-weight: 400; }

/* ---- 双列带：左＝时段统计 + 请假迟到（所选时段），右＝成就 + 请假迟到两计数 ----
   左列的请假内滚窗取整行倍数（行高 30）：150＝5 行，底边永远切在行界上，不露
   半行。右列（十轮 N1 起）是一块 210 的成就栅格，不滚。 */
.mdp-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s6);
  height: 406px;
  flex: 0 0 auto;
  margin-top: var(--s5);
}
.mdp-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  position: relative;
  padding: var(--s3) var(--s4);
  background: var(--paper-2);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
}

/* ---- 时段选择器：一整行横排，不把内容往下推 ------------------------------
   两态签（按月 / 自定义范围）+ 生效区间读数 + 翻月 ‹ › / 「重选」，全在同一条
   36px 工具条里。选完即取数，零「查询」按钮；越界提示行恒占 22px，两态切换
   只换字不换高。
   五轮 G7（owner 图三红框一「这两条横线去掉」）：工具条原来的 border-bottom
   整条删除。提示位 .mdp-msg 与它那 22px 槽位一律不动——那一行还要承载「查询
   跨度不能超过 366 天」的朱字（owner 只点了线，没点位）。 */
.mdp-rangebar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  height: 36px;
  flex: 0 0 auto;
  overflow: hidden;
  margin-top: var(--s3);
}
/* 六轮 X4 契约 2（owner「左侧圆圈圈起来的地方 字号加大一些」）：两态签 13 → 15
   （--fs-body），选中态仍是 600 浓墨 + 一道 --line 下划线。两签变宽约 14px，读数
   的净宽随之收窄，所以两签之间的间距同步由 --s4 收到 --s3（补回 4px）；工具条仍
   定高 36，切月键与「重选」一格未动。 */
.mdp-tabs { display: flex; align-items: center; gap: var(--s3); flex: 0 0 auto; }
.mdp-tab {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink-3);
}
.mdp-tab:hover { color: var(--ink); }
.mdp-tab[aria-pressed="true"] {
  color: var(--ink);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: var(--line);
}
.mdp-readout {
  margin-left: auto;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 五轮 G8（owner 图三箭头「当月份从单位数月份切换到双位数月份，年月的位置就
   会漂移，建议固定，预留好位置」）：按月态读数拆成四段——年数 / 「年」/ 月数
   槽 / 「月」。.mdp-readout 是 margin-left:auto 顶在 ‹ › 左边的，整条一变宽，
   「年」「月」两个字连同两枚切月键一起往左漂。把月份数字关进一个定宽两位的槽
   （--font-num tabular 下两位数的宽度恒定，2ch 正好两位；槽内右对齐，个位数月
   份左侧留白＝「预留好位置」），读数总宽与月份位数彻底解耦，五个锚点的
   getBoundingClientRect().left 一个像素不动。
   自定义范围态的读数是两个零补齐的 ISO 日期（2026-08-20 至 2026-09-12），宽度
   本就与月份位数无关，无等价漂移，不另加槽。 */
.mdp-ro-m {
  display: inline-block;
  width: 2ch;
  text-align: right;
}
.mdp-nav { display: flex; align-items: center; gap: var(--s1); flex: 0 0 auto; }
.mdp-navbtn {
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 20px;
  color: var(--ink-3);
  padding: 0 var(--s2);
}
.mdp-navbtn:hover { color: var(--ink); }
.mdp-reset { font-size: var(--fs-body-sm); }
.mdp-msg {
  height: 22px;
  line-height: 22px;
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--red-text);
  overflow: hidden;
}

/* ---- 「自定义范围」浮层：左列纸内绝对定位的 L2 玻璃卡 ---------------------
   三轮 owner「不要在横向加组件，而是直接一个浮层进行选范围」。锚在工具条与
   提示位的下沿：110 ＝ 12（纸的上内边距）+ 28 题 + 12 + 36 工具条 + 22 提示位；
   right 取 --s4 与纸的内边距对齐，两圈描边不相切（SPEC §11.1）。浮层盖住三数与
   请假列，卡外形一像素不变。 */
.mdp-calpop {
  position: absolute;
  top: 110px;
  right: var(--s4);
  z-index: 2;
  width: 360px;
  padding: var(--s3);
  border: var(--lw-line) solid var(--line);
  border-radius: var(--r-ctl);
  background: var(--paper-2);
  box-shadow: var(--shadow-float);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .mdp-calpop {
    background: rgba(var(--paper-2-rgb), .78);
    -webkit-backdrop-filter: blur(12px) saturate(1.2);
    backdrop-filter: blur(12px) saturate(1.2);
  }
}
.mdp-calpop-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  height: 32px;
}
.mdp-calpop-read {
  min-width: 0;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body-sm);
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mdp-calpop-reset {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}
.mdp-calpop-reset:hover { color: var(--ink); }
.mdp-calpop-body { margin-top: var(--s2); }
/* 浮层本身已是一张描边卡，日历再自带一圈框＝卡内卡（SPEC §9 反 slop 1 /
   §11.1 禁框打架）——把日历那圈框剥掉，只留网格本体，做法同既有
   .ys-adm-calpop 先例。 */
.mdp-calpop .ys-adm-cal { margin: 0; border: 0; border-radius: 0; padding: 0; background: none; }
.mdp-calpop .ys-adm-cal-nav { margin-bottom: var(--s2); }

/* ---- 请假迟到（所选时段）：逐条「日期 · 类目 · 原因」，定高 150px＝5 整行内滚 --
   零朱色（v1.6.0 §7 红线「请假永不用朱色」）；条带按 SPEC §11.7 隐藏，
   滚动能力保留。空区间一个字都不写：天数已在小节右端给了结论。 */
.mdp-leaves {
  height: 150px;
  flex: 0 0 auto;
  margin-top: var(--s4);
  overflow-y: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.mdp-leaves::-webkit-scrollbar { display: none; }
.mdp-leave-row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  height: 30px;
  overflow: hidden;
}
.mdp-leave-date {
  flex: 0 0 auto;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: var(--ink-2);
}
/* kind 签（四轮 F7，T0 契约 3 的 leaves.kind）：11px 淡墨纯文字，两种报备同一支
   笔，迟到零朱零底色——它是一个类目，不是一个警告。
   六轮字号标准（索引 §4「标签最小 13」）：11 → 13，定宽随之 22 → 26 ＝ 两个 13px
   汉字，「请假」与「迟到」两态签宽仍相等，原因列的起点照旧不随类目漂；行高 30 不
   变（13 × 1.2 ＝ 15.6）。 */
.mdp-leave-kind {
  flex: 0 0 auto;
  width: 26px;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink-3);
  white-space: nowrap;
}
.mdp-leave-reason {
  min-width: 0;
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mdp-leave-reason[data-empty="1"] { color: var(--ink-3); }

/* ---- 成就：21 项全集，两列 11 行，一次放下，零滚动 -----------------------
   十轮 N1（owner「弟子详情【无论是弟子视角还是管理员视角】里的成就年谱 要换成
   "成就"，逻辑变成了 已实现的成就加粗并排列在前面，未实现的变灰不变粗排在后面，
   两列，字号加大15%，不要时间」）。

   相对五/八轮年谱的整套下架：定高宿主 + .mdp-nianpu-scroll 滚动层、底沿 30px
   纸色渐隐（[data-overflow]）、4px 自绘滑块与 Firefox 的 @supports 回退、左乌丝
   竖轴与日期列——六件全部删除。理由是同一条：G9 与 Z3 解的都是「内容比框高、下面
   还有看不见的行」，21 项两列 11 行一次就放得下，没有下文可暗示，再留一层渐隐和
   一根滑块就是给一个不存在的溢出画提示。

   块高 210 一个像素未动：右列 380 那本账（28 题 + 12 + 210 + 24 + 28 题 + 16 +
   62 四计数）里，题与四计数都不在本卡改动面内，所以这一格的高度由账面定死，
   改的只是格子里的排法。11 行 × 19.09（210 ÷ 11）＝ 210，行内 15px 文字按
   line-height 1.25 ＝ 18.75，居中落在 19.09 的行里。

   字号 15 ＝ 原年谱条目 13（--fs-body-sm，日期段也是 13）× 1.15 ＝ 14.95，按契约
   四舍五入到 0.5px 取 15，且 ≥ 13（六轮字号标准下限）。对基座只增不减。

   两列的宽度账（Chrome 实测，1440 档）：右列纸内净宽 404.5；21 项里最长的
   「熟练极光法，可7脉轮同时共振」在 15px 文楷下实测 204.0px（600 与 400 同宽，
   加粗不改字距），两列等宽要放下它至少要 204 × 2 + 列距 ＞ 404.5 —— 净宽不够。
   故本块按 8px 出血（margin 左右各 −var(--s2)）占到 420.5，列距 var(--s2)，
   列宽 (420.5 − 8) ÷ 2 ＝ 206.25，最长的一条仍余 2.25px，21 项零截断。
   代价是这一块的左右沿比同列的题与四计数各外扩 8px（题仍在纸的 16 内边距上）。
   ellipsis 只作兜底，正常档位不触发。

   两态（按月 / 自定义范围）与两视角（管理员面 / 本人面）共用这一份规则，
   卡高、列宽、行高全部与数据无关，恒等。 */
.mdp-achv {
  height: 210px;
  flex: 0 0 auto;
  margin-top: var(--s3);
  /* 十轮 N1 合流整合（复核 P1）：两列改 auto auto 自适应列宽（实测 171.5 / 225.5），
     零出血、零截断，块沿与节题、四计数齐平；块高 210 与卡高 732 不变。 */
  overflow: hidden;
}
.mdp-achv-list {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-rows: repeat(11, 1fr);
  grid-auto-flow: row;
  align-items: center;
  column-gap: var(--s2);
  height: 100%;
}
.mdp-achv-item {
  min-width: 0;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 已达成 / 未达成两态：字重 600↔400 + 浓墨↔淡墨双重编码（只靠一种会在打印或
   低对比屏上读丢一半）。零裸色值，两个值都落在既有令牌上。 */
.mdp-achv-item[data-done="1"] { font-weight: 600; color: var(--ink); }
.mdp-achv-item[data-done="0"] { font-weight: 400; color: var(--ink-3); }
/* 清单取不到：槽位照样占满（两态卡高恒等），栅格让位给一行引导词。 */
.mdp-achv[data-empty="1"] .mdp-achv-list { display: block; }
.mdp-achv-empty {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 30px;
  color: var(--ink-3);
}

/* ---- 请假迟到（近一年 / 全部）：两格大数，定高 62px -----------------------
   四轮 owner「截图3，重做，只展示 近一年请假次数 和 全部请假次数」。三轮那条
   12 列条带整段下架：12 个月里 11 个写 0 的条带占满一整行却只说了一件事，
   owner 一眼判它没信息量。改成大数，笔法与数带两组完全同款（.mdp-stat /
   .mdp-k / .mdp-v 复用，零新写法）。

   六轮 X4 契约 4（owner「右下方的要把 请假和迟到分开记录」）：两格改四格
   （近一年请假 / 近一年迟到 / 全部请假 / 全部迟到），四个数直出 profile 的
   leaveCountLastYearByKind / leaveCountTotalByKind，前端零换算。

   返工一（复核 P1-1）：四格由 2×2 改 **一行四列**，块高退回 62 ＝ 与两格时完全同值
   ——owner 原话只说「请假和迟到分开记录」，没说摆成 2×2；一个推定的排版形状不该吃掉
   年谱那一行。算式：
     列宽 ＝ (405 纸内净宽 − 3 × 12 列距) ÷ 4 ＝ 92.25px
     块高 62 ＝ 16.9（13 标 × 1.3）+ 4（--s1）+ 20.4（17 数 × 1.2）＝ 41.3，62 的槽
                内垂直居中（与两格时同一支笔、同一个高，右列 380 一个数没动）
   四个标最长「近一年请假」实测 65px、三位数值实测 44px，都远小于 92.25，零截断。
   窄屏（≤760）另见文末：375 档左列净宽只有 275，一行四列会把 65px 的标挤断，
   那一档仍走 2×2（单列堆叠下右列本就是 auto 高，不占年谱的账）。
   四个数取 17（与 .mdp-stats--range .mdp-v 同一档）而不是数带的 22：本卡的主数在
   数带，这四个是从属计数，用 22 会把主次读反。 */
.mdp-lc {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: center;
  gap: var(--s3);
  height: 62px;
  flex: 0 0 auto;
  margin-top: var(--s4);
}
.mdp-lc .mdp-v { font-size: 17px; font-weight: 400; }

/* ---- 卡脚：右下一个幽灵「关闭」，零黑底主按钮 ---------------------------
   五轮 G7（owner 图三红框二「这两条横线去掉」）：卡脚原来的 border-top 整条
   删除。这条线本就是本文件自己写的（app.css 的 .book-card-foot 那条 border-top
   管的是登录/注册卡脚，本浮窗的卡脚是 .mdp-foot，不吃那条规则），所以按工单
   「若来自 app.css 通用规则再覆写为 0」的次优路径未走——直接在自己这里删，
   app.css 一个字不碰。全站 box-sizing 是 border-box，64 的定高含边框在内，
   删线后卡脚仍 64、整卡仍 722，定高账分毫不动。 */
.mdp-foot {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  height: 64px;
  flex: 0 0 auto;
  margin-top: var(--s4);
}

/* ---- 窄屏 375 折法 -------------------------------------------------------
   双列带拆成上下两张纸，数带两组上下叠；两个内滚窗按整行倍数降档：请假 60＝
   2 行、年谱 90＝3 行，两计数块一格不降（它是四轮点名的那件事，且只有 62）。
   三带加两张纸的内边距之后，375×812 仍装不下整卡（实测见交回件），按
   SPEC §11.7 优先级③ 走卡内滚动：滚动条条带隐藏，滚动能力保留。 */
@media (max-width: 760px) {
  .book-card.mdp-card {
    width: calc(100vw - 32px);
    padding: var(--s4);
    max-height: calc(100vh - var(--s4) * 2);
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .book-card.mdp-card::-webkit-scrollbar { display: none; }
  .mdp-top { height: 52px; margin-bottom: var(--s3); }
  .mdp-notes { height: 28px; }
  .mdp-name { font-size: 20px; }
  .mdp-sec { height: 24px; }
  .mdp-stats { height: 44px; }
  .mdp-band { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .mdp-group + .mdp-group { border-left: 0; padding-left: 0; }
  .mdp-cols { grid-template-columns: minmax(0, 1fr); gap: var(--s4); height: auto; margin-top: var(--s4); }
  /* 六轮 X4 契约 3:右端计数由一个数变成两个数(「请假 N 次 · 迟到 M 次」,13px 下
     实测 146.84px),375 档左列净宽只有 275——与 16px 的题并排就要折行,折出来的
     那半行会压到下一块上。窄屏档把这一题的槽由一行 24 改成两行 44(题一行、计数
     独占一行,定高仍是写死的 height,不是 min-height),文案一个字不缩。 */
  .mdp-sec--lv { height: 44px; flex-wrap: wrap; align-content: center; }
  .mdp-sec--lv .mdp-sec-count { width: 100%; margin-left: 0; }
  /* 返工一：宽屏四计数是一行四列（列宽 92.25），375 档左列净宽只有 275，四列就成了
     59.75 —— 最长的标「近一年请假」实测 65px 会被挤断。窄屏档因此摆 2×2（两行 42 +
     8 行距 ＝ 92）。这一档双列带是 auto 高、两张纸上下堆叠，年谱 90 的窄屏值不动，
     右列 380 那本账只管宽屏，不受影响。 */
  .mdp-lc { grid-template-columns: 1fr 1fr; grid-template-rows: 42px 42px; row-gap: var(--s2); height: 92px; }
  .mdp-leaves { height: 60px; }
  /* 十轮 N1：375 档右列纸内净宽只有 275，两列各 133.5 放不下 204px 的那一条，
     所以这一档两列保留、改为可折行：整条双列带在 ≤760 本就是 auto 高、两张纸
     上下堆叠（.mdp-cols height: auto），本块跟着走 auto，行高由 --s5（24）的
     行槽给下限，折出来的第二行不会压到下一块。宽屏那 8px 出血在这一档收回 0
     ——275 的纸再外扩只会顶到乌丝上。 */
  .mdp-achv { height: auto; }
  .mdp-achv-list {
    grid-template-rows: none;
    grid-auto-rows: minmax(var(--s5), auto);
    column-gap: var(--s3);
    row-gap: var(--s1);
    height: auto;
  }
  .mdp-achv-item { overflow: visible; text-overflow: clip; white-space: normal; }
  /* 五轮 V4 返工一（复核 P1-1）：窄屏档读数 computed 13px（复核三档实测），
     36px 工具条里留给读数的净宽只有 91px，而 G8 的定宽两位槽把读数撑到 96px，
     于是 .mdp-readout 的 text-overflow: ellipsis 把「9 月」两个字吃掉，屏上读作
     「2026 年 …」（双位数月份在本卡之前就已被吃掉，个位数月份是本卡撑出来的
     新回归）。腾地方的一刀落在两枚切月键的左右内边距上（8 → 4，两枚共腾
     16px）：读数是 owner 这一条原话的题眼，宁可收键的留白也不降读数的字号、
     更不动那个 2ch 槽（一动 G8 就塌）。键的字形与命中高度一格未变。 */
  .mdp-navbtn { padding: 0 var(--s1); }
  /* 浮层改满列宽：106 ＝ 12（纸的上内边距）+ 24 题 + 12 + 36 工具条 + 22 提示位 */
  .mdp-calpop { top: 106px; left: var(--s4); right: var(--s4); width: auto; }
  .mdp-foot { height: 52px; margin-top: var(--s3); }
}

/* ============================================================================
   排行榜行「可点」的表达（.bang-row--clickable）——静止时极净，hover 才显影
   （一轮 D5 已定，二、三轮一个值未改，照录；三轮起该类只由管理员身份加挂，
   加挂的判据在 ui-pages.js bangRow，不在本文件）。
   ========================================================================== */
.bang-row--clickable { cursor: pointer; }
.bang-row--clickable .bang-name {
  text-decoration: underline;
  text-decoration-style: dotted;
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--t-fast) var(--ease-out);
}
.bang-row--clickable:hover,
.bang-row--clickable[data-hover="1"] { background: rgba(var(--line-rgb), .16); }
.bang-row--clickable:hover .bang-name,
.bang-row--clickable[data-hover="1"] .bang-name { text-decoration-color: var(--ink-3); }
.bang-row--me.bang-row--clickable:hover,
.bang-row--me.bang-row--clickable[data-hover="1"] { background: var(--paper-3); }
.bang-row[data-top="1"].bang-row--clickable:hover .bang-name,
.bang-row[data-top="1"].bang-row--clickable[data-hover="1"] .bang-name { text-decoration-color: var(--red-text); }
.bang-board .bang-row--clickable:hover,
.bang-board .bang-row--clickable[data-hover="1"] {
  margin: 0 calc(var(--s5) * -1);
  padding-left: var(--s5);
  padding-right: var(--s5);
}

/* ============================================================================
   v1.6.0 五轮 V6（owner G11「管理员的 - 管理 ，也要能够点开某个弟子 查看详情，
   和排行榜的查看弟子详情是完全一样的」）：管理页名册行「可点」的表达
   （.adm-row--clickable）。与上面 .bang-row--clickable 同一支笔——令牌与数值
   逐字相同（衬底 rgba(var(--line-rgb), .16)、点线下划线 var(--ink-3)、
   offset 3px、同一条过渡），差别只在挂点类名与行内的姓名格类名。

   为什么落在本文件而不是 app.css：app.css 的 .adm-row 一族（含既有
   .adm-row:hover 那层票面色衬底）是基座规则，本卡只读不改；本文件在
   build.js 的拼接顺序里排在 app.css 之后，同特指度（0,2,0）靠源序覆盖，
   hover 底从「票面 .9」换成「乌丝 .16」= 同一支笔更深一档。静止态一条规则
   都不加，像素零变化（只多一个 cursor）。

   加挂判据（window.App.role() === 'admin'）在 ui-pages.js buildRow，不在本
   文件——弟子/模拟弟子视角下行不带这个类，即一处都不显影。
   ========================================================================== */
.adm-row--clickable { cursor: pointer; }
/* 行尾操作列是自己的交互件（⋯ 与下拉菜单），点它不开浮窗，指针也不该假装可点 */
.adm-row--clickable .adm-op { cursor: auto; }
.adm-row--clickable .adm-name {
  /* 静止态的下划线是透明的(与排行榜同一招:交互态显影,不改几何)。样式取 solid
     而非 dotted,只为静止态逐像素零差异——实测:页面上只要存在一条 dotted 的
     text-decoration(哪怕是透明的),Chrome 对报头「退出登录」那条既有 dotted 下
     划线的栅格化就会重走一遍,52 个像素各通道深 9/255(几何一格不变)。改 solid
     后静止态与基座逐像素恒等;hover 时再把 style 切成 dotted,屏上看到的显影与
     排行榜逐字相同(dotted / --ink-3 / offset 3px / 同一条过渡)。 */
  text-decoration: underline;
  text-decoration-style: solid;
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--t-fast) var(--ease-out);
}
.adm-row--clickable:hover,
.adm-row--clickable[data-hover="1"] { background: rgba(var(--line-rgb), .16); }
.adm-row--clickable:hover .adm-name,
.adm-row--clickable[data-hover="1"] .adm-name,
.adm-row--clickable .adm-name-wrap:focus-visible .adm-name {
  text-decoration-style: dotted;
  text-decoration-color: var(--ink-3);
}

/* lgj-160-admin · 「管理」页右栏配置面板作用域样式（v1.6.0 二轮 W7 立，
   三轮 W15 重做，20260916）
   契约=SPEC-练功志-v1.6.0-20260915.md §8.2「三轮修订」块；方案=
   .openaccp/coordination/练功志-v160-三轮设计方案-20260916.md §一 + §五。
   类前缀 .adc-（admin config）。

   owner 20260916 三轮逐字：「截图3，自己找问题，我反正觉得做的很差，让人摸不着
   头脑，也是没有层次感，逻辑混乱 拥挤，不清晰」「所有"自定义"都要换成"自定义
   范围"」。二轮 owner 原话（形态前提，仍有效）：「所有管理员界面都是默认要利用
   横向空间」「时段统计不要做浮层，直接像截图三那样做到右侧，在右侧进行
   configure」。

   拼接顺序排在最末（build.js 登记；lgj-160-stats.css 已随 v1.6.0 九轮 M1
   整份删除）——回滚只需摘掉这一段，
   对 app.css 的 .adm-* 与 ys-admin-141.css 的 .ys-adm-cal* 一条覆写都不加，
   只在 .adc-cal2 作用域内剥掉日历自带的框与内边距（同 .ys-adm-calpop 既有做法）。
   注释里禁写星号斜杠连写，会提前关注释（20260915 合流期实锤）。

   三轮的层次做法（方案 §一「三层纸」）：面板整块 = L1 票面纸（--paper-2 + 一道
   乌丝 + 3px + padding --s4），零阴影；双月日历浮层 = L2 玻璃（rgba 票面 .78 +
   blur 12 + --shadow-float + 乌丝），全页唯一一个 blur 元素，且压在名册之上有
   东西可透。层与层的关系靠纸色深一档 + 一道乌丝，不靠阴影。

   三条落法：一种边框灰（只写 var(--line)；生效键的浓墨描边是状态色不是第二种
   边框灰）／默认态零阴影（唯一阴影属日历浮层）／色彩只落数据（面板骨架零着色，
   生效态靠衬纸 + 浓墨 + 600）。
   定高纪律：节题 26、搜索输入 36、命中回显 20、子题 16、四键 32、方向条 32、
   时段分段条 32、读数行 44——每一行都是 height，一处不用 min-height，面板高度
   在「未选／按月／自定义范围」三态之间一格不变，中栏名册永不被推下去。

   v1.6.0 四轮 T5（owner F10 逐字：「"时段总时长"和"时段打卡天数"这两个维度直接
   删掉…当用户"按月""自定义范围"的时候，就不要展示 任何截图10大方框里的数据，
   只展示时段数据，同时也不应该选中任何的排序依据」）：排序键六 -> 四（2×2），
   面板因此矮 40px（一行 32 + 一道 8 的 gap），三态总高由 560 -> 520，算式见
   range-stats-ui.test.js 里那条钉。禁用态的样式一条没改，只是触发条件反了过来：
   从「时段未选时后两键禁用」变成「时段已选时四键全禁用」。
   另 owner F6「切换弟子视角入口做成一个简约的按钮UI」：左栏那枚暗文链改 .btn
   .btn-ghost，尺寸与字面由本文件末尾的 .adm-simbtn 给（app.css 的 .btn 一族
   零改动）。

   v1.6.0 五轮 V1（owner G1 逐字：「太小了，这个月份切换的区域无论是按键还是字
   都要大一点，优化一下这里的UI；然后不要显示 记录XX人-合计XX时 分，完全多余，
   去掉」；G2 逐字：「点自定义范围，日历会溢出往下，优化一下，变成往上打开」；
   补充 G8 逐字：「当月份从单位数月份切换到双位数月份…年月的位置就会漂移，建议
   固定，预留好位置」）：
   ① 合计条 .adc-sum 整条下架（本文件三处规则一并删：基础、≤1439、≤760），
      面板底部回到正常 padding 收口，负 margin 随之退场——全文件零负 margin。
   ② 读数行 32 -> 44，按月态三段：（字号写字面量不写 --fs-body：管理页挂
      .page-scale-lg，那条 +15% 覆写会把 --fs-body 顶成 16.1px，与契约的 15px
      对不上；本行三态字号是 owner 点名的具体数，故直接钉死）两枚 36×36 的切月键（静止零描边零底、hover
      才上衬纸，法则③④）夹一段 17px/600 浓墨的年月；月份数字占 2ch 恒宽槽
      （G8），自定义已成态 15px/600（比按月小一档，因字数长）；返工一起自定义
      已成态读数只写「起 至 止」，不写「· 共 N 天」（15px 下两位数天数会被
      text-overflow 截断，动用契约 2 预置的降级）。
   ③ 双月浮层由「顶对齐时段节向左弹」改为「底对齐读数行、向上向左展开」：
      top:22px -> bottom:0，宽 560 / 向左 / 玻璃材质一个数不动；≤1439 的工具条
      形态同样改成向上展开（该档实测向下弹会让底缘落到 1017 > 800，正是 owner
      截图二那条「日历会溢出往下」在本档的同一个病），只是底缘对齐的是整条工具条
      下沿而不是读数行下沿——那一档的定位基准必须留在 .adc 上，否则右缘不再贴
      画布右缘（复核 P1-3 的成因）。
   三态总高由 520 -> 504（合计条 28 + 上距 16 − 负 margin 吃掉的 16 = −28，
   读数行 +12），算式见 range-stats-ui.test.js 里那条钉。
   ========================================================================== */

/* ---- L1 面板纸：右栏 300（宽由 app.css §25b 的三栏网格给），净宽 266 ---- */
.adc{position:sticky;top:var(--s4);background:var(--paper-2);
  border:var(--lw-line) solid var(--line);border-radius:var(--r-ctl);padding:var(--s4)}
.adc-sec{margin-bottom:var(--s5);position:relative}
.adc-sec:last-child{margin-bottom:0}
/* 节题：16px/600 重墨宽字距 + 一道收底乌丝（三节靠它分组，不靠各自画框）
   六轮 X2（owner H5「字太小了…所有的字体 字号 要有统一标准…两个页不一致的时候，
   字号取更大的那个值」，六轮字号标准「栏内节题 16px 600」）：13 -> 16，字面量
   （管理页挂 .page-scale-lg，var(--fs-sub) 在本页会被顶成 18.4px）。26 的定高不动
   （16px 文字在 26 高的居中行里仍不触边），面板三态总高因此一格不变。 */
.adc-sec-title{display:flex;align-items:center;height:26px;margin:0 0 var(--s3);
  font-family:var(--font-body);font-size:16px;font-weight:600;letter-spacing:var(--ls-label);
  color:var(--ink-2);border-bottom:var(--lw-line) solid var(--line)}

/* ---- 搜索节：一只 36 高满宽的输入井（井底比面板纸深一档才读得出是输入格） ---- */
.adc-input{display:flex;align-items:center;height:36px;padding:0 10px;
  border:var(--lw-line) solid var(--line);border-radius:var(--r-ctl);background:var(--paper)}
/* 六轮 X5（索引 §4「正文 15px」；本框与阳神班 / 公告右栏搜索框 .notes-sideinput
   input 同角色，三页必须同值）：var(--fs-body-sm) 在挂 .page-scale-lg 的本页
   实得 14.95，改 15 字面量。36 的井高不动，15px 文字在 36 的井里不触边。 */
.adc-input input{flex:1;min-width:0;border:0;outline:0;background:transparent;
  font-family:var(--font-body);font-size:15px;line-height:24px;color:var(--ink)}
/* placeholder 不豁免对比度（设计规范 §1 红线）：只降色阶不降透明度 */
.adc-input input::placeholder{color:var(--ink-3)}
/* 命中回显：有输入写「匹配 N 人」，无输入空占位——两态同高 20px，面板不抖 */
.adc-hint{height:20px;line-height:20px;overflow:hidden;margin:0;
  font-family:var(--font-body);font-size:var(--fs-caption);color:var(--ink-3)}
.adc-hint:empty::before{content:"\200b"}

/* ---- 子题：节内再分一层（「排序依据」「方向」），13px 淡墨，不画框 ------
   六轮 X2（六轮字号标准「三栏页面内最小字号 13」）：11 -> 13。16 的定高不动，
   13px 文字在 16 的行盒里不裁切，面板三态总高一格不变（算式见测试那条钉）。 */
.adc-sublabel{height:16px;line-height:16px;margin:0 0 var(--s2);
  font-family:var(--font-body);font-size:13px;color:var(--ink-3)}
.adc-sortgrid + .adc-sublabel{margin-top:var(--s3)}

/* ---- 排序节：四键 2×2 描边格，每格 32 高吃满半栏（四轮 T5 由 2×3 改） --- */
.adc-sortgrid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
/* 六轮 X2（六轮字号标准「右栏选项 / 分段键 15px」）：四键 -> 15px 字面量。 */
.adc-sort{width:100%;height:32px;padding:0 var(--s2);
  font-family:var(--font-body);font-size:15px;color:var(--ink-2);
  background:transparent;border:var(--lw-line) solid var(--line);border-radius:var(--r-ctl)}
.adc-sort:hover{color:var(--ink);background:var(--paper-3)}
/* 生效=衬纸底 + 浓墨 1px 描边 + 600（同一支笔更深一档，不跳色不加阴影） */
.adc-sort[data-on="1"]{color:var(--ink);font-weight:600;background:var(--paper-3);border-color:var(--ink)}
/* 六轮 X2（owner H3 逐字：「界面按月的时候 却不能点 本周本月... 这是不对的，要允许
   用户点，点了以后相当于自动清除 按月 或者 自定义范围 的选择」）：四轮 T5 那套
   「时段已选时四键全禁用」的样式（虚线乌丝 + 淡墨 + cursor:default）整块退役，
   连同它的 :hover 伴生规则——键不再有禁用态，DOM 上也不再写 aria-disabled，
   留着规则就是指向空气。时段态四键只是零选中（data-on 全 0），仍可点、仍 hover。 */

/* ---- 方向 / 时段：同一支笔的两格分段控件，32 高满宽，中间一道乌丝 ------- */
.adc-dir,
.adc-tabs{display:grid;grid-template-columns:1fr 1fr;height:32px;
  border:var(--lw-line) solid var(--line);border-radius:var(--r-ctl);overflow:hidden}
/* 六轮 X2（六轮字号标准「分段键 15px」）：方向两签与时段两签 -> 15px 字面量。 */
.adc-dirtab,
.adc-tab{height:100%;padding:0 var(--s2);font-family:var(--font-body);
  font-size:15px;color:var(--ink-2);background:transparent}
.adc-dirtab + .adc-dirtab,
.adc-tab + .adc-tab{border-left:var(--lw-line) solid var(--line)}
.adc-dirtab:hover,
.adc-tab:hover{color:var(--ink);background:var(--paper-3)}
.adc-dirtab[aria-pressed="true"],
.adc-tab[aria-pressed="true"]{color:var(--ink);font-weight:600;background:var(--paper-3)}

/* ---- 时段读数行 44（五轮 V1 由 32 加大），它是时段节的收底行 ------------
   中文走文楷、数字走 MonoNum + tabular（法则⑤不因字号变大而改笔），故读数由
   一条纯文本改成混排：.adc-readout 给中文，里面的 .num 给数字。 */
.adc-range{display:flex;align-items:center;height:44px;margin-top:var(--s3);overflow:hidden}
.adc-readout{flex:1 1 auto;font-family:var(--font-body);font-size:15px;
  color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left}
.adc-readout .num{font-family:var(--font-num);font-variant-numeric:tabular-nums}
/* 按月态：夹在 ‹ › 之间居中，17px/600 浓墨（owner G1「字要大一点」） */
.adc-readout--month{text-align:center;font-size:17px;font-weight:600;color:var(--ink)}
/* G8：月份数字占恒宽双位槽，单位数月右对齐进去——9 月切 10 月时「年」「月」
   两字与两枚切月键一像素不动。ch = MonoNum 一个数字宽（等宽字体，与 tabular
   同源），不用 min-width（定高定宽纪律）。 */
.adc-readout--month .adc-mo{display:inline-block;width:2ch;text-align:right}
/* 自定义已成态：同一支笔小一档（15px/600），因「08-20 至 09-12 · 共 24 天」字数长 */
.adc-readout--custom{font-weight:600;color:var(--ink)}
.adc-readout[data-empty="1"]{color:var(--ink-3)}
/* 切月键：36×36 命中区、chevron 20px 重墨，静止零描边零底，hover 才上衬纸 */
.adc-range .adc-navbtn{width:36px;height:36px;display:flex;align-items:center;justify-content:center;
  font-size:20px;line-height:1;color:var(--ink-2);background:transparent;border:0;padding:0;
  border-radius:var(--r-ctl)}
.adc-range .adc-navbtn:hover{color:var(--ink);background:var(--paper-3)}
/* 浮层抬头那对「上两月 / 下两月」仍是小号（它夹在 26 高的抬头里） */
.adc-navbtn{flex:0 0 auto;font-size:15px;line-height:20px;color:var(--ink-3);padding:0 8px}
.adc-navbtn:hover{color:var(--ink)}
/* 六轮 X5（索引 §4「左栏链接项 / 右栏选项 / 分段键 15px」，「清除」是控件字）：
   var(--fs-caption) -> 15，与下面 .adc-range .adc-clear 那条自定义范围态同值，
   两态不再一大一小。20 的行盒不动。 */
.adc-clear{flex:0 0 auto;font-family:var(--font-body);font-size:15px;line-height:20px;color:var(--ink-3);padding:0 0 0 8px}
.adc-clear:hover{color:var(--ink)}
/* 读数行里的「清除 / 重选」随行加大到 15px 重墨（hover 才浓墨，法则③） */
.adc-range .adc-clear{font-size:15px;color:var(--ink-2)}
.adc-range .adc-clear:hover{color:var(--ink)}

/* ---- 左栏「切换弟子视角」：一枚简约按钮（v1.6.0 四轮 T5，owner F6）-------
   基类 .btn.btn-ghost 来自 app.css（零改动），这里只收三样：高 40 -> 32、字
   15px/600 -> 13px/400、默认色 --ink -> --ink-2（hover 才回浓墨，法则③静止极
   净交互显影）。宽随内容（.btn 本就是 inline-flex），位置仍紧随「弟子总数 N 人」。
   它是全页唯一一枚带框按钮：周遭全是暗文链，一道乌丝足够读成按钮，不上黑底
   （黑底是页面主行动的笔，管理页没有主行动）。
   min-height 这一处是【解除】不是【新增】：app.css:1861 给一切 .btn 压了一条
   44px 触控热区兜底，它会盖过 32 的定高；这里把它收回到与 height 同值（不是
   放任内容撑高，两值相等，仍是定高），好让这枚按钮与它周遭的面板控件（.adc-sort
   / .adc-dirtab / .adc-tab 都是 32）同一档高度。本文件其余一处不用 min-height。 */
/* 返工一（复核 P1-1；索引 §4「左栏链接项 / 控件 15px」，owner H5「字太小了，
   尤其是左侧栏」）：var(--fs-body-sm) 在 §22b 总闸下算 13，比它正上方同一条
   左栏里的 .adm-link（15）小一档，且比基座的 14.95 还小——违「只许不变或变大」。
   改 15 字面量；32 的定高与 min-height 兜底（本文件头注解释过的触控热区，两值
   相等仍是定高）一个数不动，15px 文字在 32 的按钮里不触边。 */
.adm-simbtn{align-self:flex-start;height:32px;min-height:32px;margin-top:var(--s3);padding:0 var(--s3);
  font-size:15px;line-height:20px;font-weight:400;color:var(--ink-2)}
.adm-simbtn:hover{color:var(--ink)}

/* ---- 自定义双月日历：从右栏向左弹的 L2 玻璃浮层，两月并排 --------------
   560 宽／向左弹一个数不动（二轮 D6 §二定案，复核 P1-3 钉过）；三轮只换材质：
   实底票面 -> rgba 票面 .78 + blur 12 + saturate 1.2，无 backdrop-filter 的浏览器
   留在上面那条实底回退上，视觉降级对用户无感。
   五轮 V1（owner G2「日历会溢出往下…变成往上打开」）只换纵向锚点：top:22px
   （顶对齐时段节）-> bottom:0（底对齐读数行，向上展开）。.adc-sec 是定位基准，
   读数行是它的末行且 :last-child 的 margin-bottom 归零，故 bottom:0 正是「贴着
   读数行下沿往上长」。
   六轮 X2（owner H4 逐字：「截图3，不要留空间，对齐下沿」）：底缘锚点由「读数行
   下沿」下移到「右栏 .adc 的外缘下沿」。成因＝定位基准是 .adc-sec，它的下沿只到
   .adc 的内容盒，与 .adc 外缘之间隔着 padding(--s4 16px) + 一道 border(--lw-line
   1px)，那 17px 正是 owner 红框圈住的空带。故 bottom 由 0 改为
   calc(-1 * (var(--s4) + var(--lw-line)))，两条边严丝合缝（|calpop.bottom −
   adc.bottom| < 1，两档实拍取证）。横向 560 / 向左弹 / 玻璃材质一个数不动。 */
.adc-calpop{position:absolute;bottom:calc(-1 * (var(--s4) + var(--lw-line)));top:auto;right:calc(100% + var(--s4));width:560px;z-index:20;
  background:var(--paper-2);border:var(--lw-line) solid var(--line);border-radius:var(--r-pop);
  box-shadow:var(--shadow-float);padding:var(--s4)}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .adc-calpop{background:rgba(var(--paper-2-rgb), .78);
    -webkit-backdrop-filter:blur(12px) saturate(1.2);backdrop-filter:blur(12px) saturate(1.2)}
}
.adc-calpop-head{display:flex;align-items:center;height:26px;overflow:hidden;
  border-bottom:var(--lw-hair) solid var(--line);margin-bottom:var(--s3)}
/* 六轮 X5（X2 复核员留件：「三栏页面内最小字号 13」在浮层内同样成立）：
   12.5 -> 13。抬头 26 的定高不动，13px 数字在 26 的行盒里不触边。 */
.adc-calpop-read{flex:1 1 auto;font-family:var(--font-num);font-size:13px;font-variant-numeric:tabular-nums;
  color:var(--ink-2);white-space:nowrap}
.adc-calpop-nav{flex:0 0 auto;display:flex;align-items:center}
.adc-cal2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);align-items:start}
.adc-cal2 .ys-adm-cal{border:0;border-radius:0;background:none;padding:0}
/* 两月之间一道竖细线，分组不靠框 */
.adc-cal2 > div:first-child{border-right:var(--lw-hair) solid var(--line);padding-right:var(--s5)}
.adc-calpop-msg{height:22px;line-height:22px;overflow:hidden;font-family:var(--font-body);
  font-size:var(--fs-caption);color:var(--red-text);margin-top:var(--s2)}
.adc-calpop-msg:empty::before{content:"\200b"}

/* ---- 窄屏降级（图纸 D6-管理页-375.html） -------------------------------
   断点由 1120 提到 1439（复核 P1-1）：一行七格的内容最小宽约 809px，三栏下
   中栏净宽 = 视口 − 622，要 1431px 才容得下，1121–1439 硬挤三栏会把时段三格
   压到本面板上。1121–1439 因此走纵排——但面板不摊成一根长条，而是三节并排
   的一条工具条（与基座 .adm-side 在窄窗横排同一思路），名册拿到整幅宽度。
   面板排在名册【之前】——配置是操作前提，不能沉到列表尾巴（.adm-layout 的
   flex 纵排与 .adm-rail/.adm-main 的 order 落在 app.css §25b）。
   工具条形态下三节并排，合计条不再贴纸下沿（它只属于第三节），负 margin 收回。
   ≤760 再塌回纵排，浮出层就地回落成面板内的单月日历（隐藏上个月那一列、
   去掉阴影与外框），单月日历是七列网格不是竖向长条。 */
@media (max-width: 1439px) {
  .adc{order:1}
  /* position:relative 不是装饰:纵排档浮出层的定位基准要从「时段」那一节
     上移到整条工具条(见下方 .adc-sec{position:static}),这样右缘才能对齐
     画布右缘——复核 P1-3 实锤:锚在第三节上向右弹,右缘恒为 1256,视口窄于
     约 1266 就掉出画布右缘并撑出横向滚动(1121 档九月末三列被切在屏外)。 */
  .adc{position:relative;margin:var(--s3) 0 var(--s4);
    display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--s6)}
  .adc-sec{flex:0 1 300px;margin-bottom:0;position:static}
  /* 本档左栏塌成一条横排（app.css §25b），按钮与「弟子总数」同行，纵向间距收零
     ——原先 app.css:3200 给 .adm-link--rail-sim 做的同一件事，类名随 T5 改笔。 */
  .page--admin .adm-simbtn{margin-top:0}
  /* 工具条形态下浮出层向下弹,并把右缘钉在工具条(=画布)右缘:工具条恒占满
     画布宽,画布在本断点区间最窄也有 687px(761 − 10 滚动条 − 64 内边距)，
     560px 的浮出层因此左右两缘恒在画布内,零横向滚动。max-width 是兜底。
     纵向:本档同样【向上】展开(owner G2),但定位基准是整条工具条而不是时段节
     (基准不能改,改了右缘就不再贴画布右缘——复核 P1-3 的成因),故底缘对齐工具条
     下沿 bottom:0 而不是读数行下沿。实测 1280×800:工具条 bottom 615,浮层
     top 219 / bottom 614,四缘全在视口内;原先的 top:100% 向下弹实测 bottom 1017,
     正是 owner 截图二那条「日历会溢出往下」在本档的同一个病。
     六轮 X2（owner H4「不要留空间，对齐下沿」）：本档要补的偏移比三栏档【少一个
     padding】——绝对定位的 bottom 量的是包含块的【内边距盒】下沿，而本档的包含块
     就是 .adc 本身（.adc-sec 已 position:static），它的内边距盒下沿只比外缘高出
     一道 border。三栏档的包含块是 .adc-sec（.adc 的内容盒下沿），才要补
     padding + border。实拍 1280×800 实测：补 17 会多掉 16px（pop.bottom 631.36
     vs adc.bottom 615.36），补 1 即两缘重合。 */
  .adc-calpop{top:auto;bottom:calc(-1 * var(--lw-line));right:0;left:auto;margin-top:0;max-width:100%}
}
@media (max-width: 760px) {
  .adc{display:block}
  /* 浮出层在本档就地回落成面板【内】的单月日历,DOM 上排在读数行之后,自然
     落在节的末尾(五轮 V1 删掉合计条后,原先那套「把合计条 order 排到最后」的
     安排没有了对象,纵向 flex 保留是为了 order 语义清晰与既有降级不回归)。 */
  .adc-sec{display:flex;flex-direction:column;margin-bottom:var(--s5)}
  .adc-sec:last-child{margin-bottom:0}
  /* 玻璃只属于浮层:本档它不再是浮层而是内容层的一段,材质随之回落成透明直排
     (设计规范 §4.2 生效口径第 2 条「内容层不加玻璃」)。 */
  .adc-calpop{position:static;width:auto;right:auto;left:auto;bottom:auto;box-shadow:none;border:0;padding:0;margin-top:var(--s3);
    background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}
  .adc-cal2{grid-template-columns:1fr;gap:var(--s3)}
  .adc-cal2 > div:first-child{border-right:0;padding-right:0;display:none}
  .adc-sortgrid{grid-template-columns:1fr 1fr}
}
