/* --- Black Han Sans — Korean companion for Notable (display only) --- */
@font-face{font-family:'BlackHanSans';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/blackhansans-kr.woff2) format('woff2');unicode-range:U+3001-3002,U+3008-3009,U+301C,U+AC00,U+AC04,U+AC10,U+AC15,U+AC1C,U+AC74,U+ACB0,U+ACC4,U+ACE1,U+ACF5,U+ACFC,U+AD11,U+AD6C-AD6D,U+AD8C,U+ADF8,U+AE09,U+AE30,U+AE34,U+AE40,U+AE43,U+B098,U+B0A9,U+B0B4,U+B108,U+B110,U+B140,U+B144,U+B155,U+B192,U+B258,U+B294,U+B298,U+B2A5,U+B2C8,U+B2D8,U+B2E4,U+B2EC,U+B2F4,U+B2F9,U+B300,U+B304,U+B354-B355,U+B358,U+B370,U+B3C4-B3C5,U+B410,U+B4DC,U+B4E0,U+B4E4,U+B514,U+B527,U+B529,U+B530,U+B54C,U+B610,U+B77C,U+B780,U+B78C,U+B799,U+B7EC,U+B808-B809,U+B80C,U+B825,U+B85C,U+B860,U+B8E8,U+B974,U+B978,U+B97C,U+B984,U+B9AC-B9AD,U+B9B0,U+B9BC,U+B9C1,U+B9C8,U+B9D0,U+B9DE,U+B9E4,U+B9E8,U+BA3C,U+BA54,U+BA5C,U+BA70,U+BA74,U+BA85,U+BAA8,U+BB34,U+BB38,U+BB3C,U+BBF8,U+BBFC,U+BC0F,U+BC14,U+BC18,U+BC1C,U+BC24,U+BC29,U+BC30,U+BC84,U+BC8C,U+BC94,U+BCBD,U+BCC0,U+BCD1,U+BCF4,U+BCF8,U+BCFC,U+BD80,U+BD84,U+BD88,U+BDF0,U+BE0C,U+BE14,U+BE44,U+C0AC,U+C0B0,U+C0C1,U+C0C8,U+C0E4,U+C11C,U+C120,U+C124,U+C131,U+C138,U+C140,U+C149,U+C158,U+C18C,U+C190,U+C194,U+C1A1,U+C1FC,U+C218,U+C288,U+C2A4,U+C2B9,U+C2DC-C2DD,U+C2EB-C2EC,U+C544,U+C548,U+C54C,U+C560,U+C564,U+C5B4,U+C5BC,U+C5C4-C5C5,U+C5C7,U+C5D0,U+C5D4,U+C5D8,U+C5F0,U+C5F4,U+C601,U+C608,U+C624,U+C635,U+C640,U+C644,U+C694,U+C6A9,U+C6B0,U+C6B4,U+C6C3,U+C6CC,U+C6D0,U+C6E8,U+C704,U+C720,U+C73C,U+C740,U+C744,U+C74C,U+C758,U+C774,U+C778,U+C77C,U+C784,U+C787-C788,U+C791,U+C7A5,U+C7AC,U+C801,U+C804,U+C808,U+C815,U+C81C,U+C820,U+C870-C871,U+C874,U+C885,U+C8FC,U+C900,U+C911,U+C988,U+C990,U+C9C0,U+C9D5,U+C9DD,U+CC2C,U+CC98,U+CCAD,U+CCB4,U+CD08,U+CD5C,U+CD94,U+CD98,U+CD9C,U+CE90,U+CEE4,U+CEE8,U+CEEC,U+CF00,U+CF04,U+CF54,U+CF58,U+D004,U+D06C,U+D0C0,U+D130,U+D140,U+D15C,U+D1A4,U+D29C,U+D2B8,U+D2F0,U+D305,U+D30C,U+D310,U+D31D,U+D37C,U+D39C,U+D3B8,U+D3EC,U+D45C,U+D478,U+D488,U+D504,U+D50C,U+D53C,U+D558,U+D55C,U+D560,U+D568-D569,U+D574,U+D5A5,U+D5D8,U+D604,U+D611,U+D61C,U+D638,U+D63C,U+D64D,U+D654-D655,U+D669,U+D6C4-D6C5,U+D750,U+D76C,U+D799,U+FF08-FF09,U+FF1C,U+FF1E,U+FF3B,U+FF3D,U+FF5C}

/* --- Gothic A1 (Hangul companion to Notable, site subset) --- */
@font-face{font-family:'GothicA1';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/gothica1-kr.woff2) format('woff2');unicode-range:U+0020,U+00B7,U+2014,U+2026,U+3008-3009,U+AC00-AC01,U+AC04,U+AC08,U+AC10,U+AC15,U+AC19,U+AC1C,U+AC70,U+AC74,U+AC78,U+AC83,U+AC8C,U+ACAC,U+ACB0,U+ACB9,U+ACC4,U+ACE0-ACE1,U+ACF5,U+ACFC,U+AD00,U+AD11,U+AD50,U+AD6C-AD6D,U+AD73-AD75,U+AD8C,U+ADE0,U+ADF8,U+ADFC,U+AE00,U+AE08-AE09,U+AE30,U+AE34,U+AE40,U+AE43,U+AE5C,U+AFB8,U+AFBC,U+B010,U+B014,U+B044,U+B04C,U+B05D,U+B07C,U+B08C,U+B098,U+B09C,U+B0A1,U+B0A8-B0A9,U+B0AE,U+B0B4,U+B108,U+B110,U+B113,U+B140,U+B178,U+B192-B193,U+B204,U+B20C,U+B258,U+B290,U+B294,U+B298,U+B2A5,U+B2C8,U+B2E4,U+B2E6,U+B2E8,U+B2EB-B2EC,U+B2F4,U+B300,U+B304,U+B354-B355,U+B358,U+B370,U+B3C4-B3C5,U+B3C8,U+B3CC,U+B3D9,U+B41C,U+B450,U+B461,U+B465,U+B4A4,U+B4DC,U+B4E0,U+B4E3-B4E4,U+B4EF,U+B4F1,U+B514-B515,U+B527,U+B529,U+B530-B531,U+B534,U+B54C,U+B5A4,U+B5A8,U+B610,U+B6A4,U+B72C,U+B760,U+B77C,U+B780,U+B798-B799,U+B7AB,U+B7EC,U+B7FC-B7FD,U+B808-B809,U+B824-B825,U+B837,U+B840,U+B85C-B85D,U+B864,U+B8E8,U+B974,U+B978,U+B97C,U+B984,U+B9AC-B9AD,U+B9B0,U+B9BC-B9BD,U+B9C1,U+B9C8,U+B9CC,U+B9D1,U+B9DE,U+B9E4,U+B9E8,U+B9FA,U+BA3C,U+BA40,U+BA48,U+BA54,U+BA5C,U+BA70,U+BA74,U+BA85,U+BAA8-BAA9,U+BB34-BB35,U+BB38,U+BB3C,U+BBF8,U+BBFC,U+BC00,U+BC0F,U+BC14-BC15,U+BC18,U+BC1C-BC1D,U+BC24,U+BC29,U+BC30-BC31,U+BC84,U+BC88,U+BC8C,U+BC94,U+BCA8,U+BCBD,U+BCC0,U+BCCD,U+BCF4,U+BCF8,U+BCFC,U+BD80,U+BD84,U+BD93,U+BDF0,U+BE0C,U+BE14,U+BE44,U+BE57,U+BE5B,U+BE60-BE61,U+C090,U+C0AC,U+C0B0,U+C0B4,U+C0C1,U+C0C8-C0C9,U+C0DD,U+C0E4,U+C11C,U+C120,U+C12C,U+C131,U+C138,U+C140,U+C149,U+C154,U+C158,U+C18C-C18D,U+C190,U+C194,U+C1A1,U+C1FC,U+C218-C219,U+C21C,U+C220,U+C22B,U+C288,U+C2A4,U+C2AC,U+C2B7,U+C2DC-C2DD,U+C2E0,U+C2E4,U+C2EC,U+C4F4,U+C4F8,U+C528,U+C544,U+C548,U+C54C,U+C558-C559,U+C55E,U+C560,U+C564,U+C568,U+C570,U+C587,U+C5B4,U+C5BC,U+C5C4-C5C5,U+C5C7,U+C5D0,U+C5D4,U+C5D8,U+C5EC,U+C5F0,U+C5F4,U+C601,U+C608,U+C61B,U+C624,U+C628,U+C62C,U+C635,U+C640,U+C644,U+C67C,U+C694,U+C6A9,U+C6B0,U+C6B4,U+C6B8,U+C6C0,U+C6C3,U+C6CC,U+C6D0,U+C6E8,U+C704,U+C717,U+C720-C721,U+C73C,U+C740,U+C744,U+C74C,U+C751,U+C758,U+C774-C775,U+C778,U+C77C,U+C784,U+C787-C788,U+C790-C791,U+C794,U+C798,U+C7A0-C7A1,U+C7A5,U+C7AC,U+C801,U+C804,U+C808,U+C811,U+C815,U+C81C,U+C84C,U+C870-C871,U+C874,U+C881,U+C885,U+C88B-C88C,U+C8FC,U+C900,U+C904,U+C911,U+C988,U+C9C0-C9C1,U+C9C4,U+C9D1,U+C9D5,U+C9DD,U+C9E7,U+C9F8,U+CABD,U+CC28,U+CC2C,U+CC44,U+CC98,U+CC9C,U+CCA0,U+CCAB,U+CCB4,U+CCD0,U+CD08,U+CD5C,U+CD94-CD95,U+CD98,U+CD9C,U+CDB0,U+CE58,U+CE5C,U+CE60,U+CE68,U+CE74,U+CE78,U+CE90,U+CEA1,U+CEE4,U+CEE8,U+CEEC,U+CF00,U+CF04,U+CF20,U+CF54,U+CF58,U+D004,U+D06C,U+D070,U+D074,U+D0A4,U+D0C0,U+D0D5,U+D130,U+D140,U+D154,U+D15C,U+D1A0,U+D1A4,U+D1B5,U+D22D,U+D280,U+D284,U+D29C,U+D2B8,U+D2C0,U+D2F0,U+D2F4,U+D305,U+D30C,U+D310,U+D31D,U+D37C,U+D398,U+D39C,U+D3B8,U+D3EC-D3ED,U+D45C,U+D480,U+D488,U+D504,U+D50C,U+D53C,U+D544,U+D558-D559,U+D55C,U+D568-D569,U+D574,U+D5A5,U+D5E4,U+D604,U+D611,U+D614-D615,U+D61C,U+D638,U+D63C,U+D654-D655,U+D669,U+D68C-D68D,U+D6C4-D6C5,U+D6D1,U+D71C,U+D750,U+D754,U+D758,U+D769,U+D76C,U+D770,U+D788,U+D78C,U+D798-D799,U+FF08-FF09}

/* --- Notable (display / brand headlines, latin only) --- */
@font-face{font-family:'Notable';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/notable-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* --- Archivo (variable weight 100-900 / width 62-125%) --- */
@font-face{font-family:'Archivo';font-style:normal;font-weight:100 900;font-stretch:62% 125%;font-display:swap;src:url(fonts/archivo-vietnamese.woff2) format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB}
@font-face{font-family:'Archivo';font-style:normal;font-weight:100 900;font-stretch:62% 125%;font-display:swap;src:url(fonts/archivo-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Archivo';font-style:normal;font-weight:100 900;font-stretch:62% 125%;font-display:swap;src:url(fonts/archivo-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}

/* --- Pretendard (Hangul). Full faces first, used-glyph subsets last:
       later @font-face wins, so pages ship the 20KB subset and the full
       file is fetched only if a character outside it ever appears. --- */
@font-face{font-family:'Pretendard';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/pretendard-full-400.woff2) format('woff2');unicode-range:U+1100-11FF,U+3000-303F,U+3130-318F,U+AC00-D7A3,U+FF00-FFEF}
@font-face{font-family:'Pretendard';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/pretendard-full-700.woff2) format('woff2');unicode-range:U+1100-11FF,U+3000-303F,U+3130-318F,U+AC00-D7A3,U+FF00-FFEF}
@font-face{font-family:'Pretendard';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/pretendard-kr-400.woff2) format('woff2');unicode-range:U+3001-3002,U+3008-3009,U+301C,U+AC00,U+AC04,U+AC10,U+AC15,U+AC1C,U+AC74,U+ACB0,U+ACC4,U+ACE1,U+ACF5,U+ACFC,U+AD11,U+AD6C-AD6D,U+AD8C,U+ADF8,U+AE09,U+AE30,U+AE34,U+AE40,U+AE43,U+B098,U+B0A9,U+B0B4,U+B108,U+B110,U+B140,U+B144,U+B155,U+B192,U+B258,U+B294,U+B298,U+B2A5,U+B2C8,U+B2D8,U+B2E4,U+B2EC,U+B2F4,U+B2F9,U+B300,U+B304,U+B354-B355,U+B358,U+B370,U+B3C4-B3C5,U+B410,U+B4DC,U+B4E0,U+B4E4,U+B514,U+B527,U+B529,U+B530,U+B54C,U+B610,U+B77C,U+B780,U+B78C,U+B799,U+B7EC,U+B808-B809,U+B80C,U+B825,U+B85C,U+B860,U+B8E8,U+B974,U+B978,U+B97C,U+B984,U+B9AC-B9AD,U+B9B0,U+B9BC,U+B9C1,U+B9C8,U+B9D0,U+B9DE,U+B9E4,U+B9E8,U+BA3C,U+BA54,U+BA5C,U+BA70,U+BA74,U+BA85,U+BAA8,U+BB34,U+BB38,U+BB3C,U+BBF8,U+BBFC,U+BC0F,U+BC14,U+BC18,U+BC1C,U+BC24,U+BC29,U+BC30,U+BC84,U+BC8C,U+BC94,U+BCBD,U+BCC0,U+BCD1,U+BCF4,U+BCF8,U+BCFC,U+BD80,U+BD84,U+BD88,U+BDF0,U+BE0C,U+BE14,U+BE44,U+C0AC,U+C0B0,U+C0C1,U+C0C8,U+C0E4,U+C11C,U+C120,U+C124,U+C131,U+C138,U+C140,U+C149,U+C158,U+C18C,U+C190,U+C194,U+C1A1,U+C1FC,U+C218,U+C288,U+C2A4,U+C2B9,U+C2DC-C2DD,U+C2EB-C2EC,U+C544,U+C548,U+C54C,U+C560,U+C564,U+C5B4,U+C5BC,U+C5C4-C5C5,U+C5C7,U+C5D0,U+C5D4,U+C5D8,U+C5F0,U+C5F4,U+C601,U+C608,U+C624,U+C635,U+C640,U+C644,U+C694,U+C6A9,U+C6B0,U+C6B4,U+C6C3,U+C6CC,U+C6D0,U+C6E8,U+C704,U+C720,U+C73C,U+C740,U+C744,U+C74C,U+C758,U+C774,U+C778,U+C77C,U+C784,U+C787-C788,U+C791,U+C7A5,U+C7AC,U+C801,U+C804,U+C808,U+C815,U+C81C,U+C820,U+C870-C871,U+C874,U+C885,U+C8FC,U+C900,U+C911,U+C988,U+C990,U+C9C0,U+C9D5,U+C9DD,U+CC2C,U+CC98,U+CCAD,U+CCB4,U+CD08,U+CD5C,U+CD94,U+CD98,U+CD9C,U+CE90,U+CEE4,U+CEE8,U+CEEC,U+CF00,U+CF04,U+CF54,U+CF58,U+D004,U+D06C,U+D0C0,U+D130,U+D140,U+D15C,U+D1A4,U+D29C,U+D2B8,U+D2F0,U+D305,U+D30C,U+D310,U+D31D,U+D37C,U+D39C,U+D3B8,U+D3EC,U+D45C,U+D478,U+D488,U+D504,U+D50C,U+D53C,U+D558,U+D55C,U+D560,U+D568-D569,U+D574,U+D5A5,U+D5D8,U+D604,U+D611,U+D61C,U+D638,U+D63C,U+D64D,U+D654-D655,U+D669,U+D6C4-D6C5,U+D750,U+D76C,U+D799,U+FF08-FF09,U+FF1C,U+FF1E,U+FF3B,U+FF3D,U+FF5C}
@font-face{font-family:'Pretendard';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/pretendard-kr-700.woff2) format('woff2');unicode-range:U+3001-3002,U+3008-3009,U+301C,U+AC00,U+AC04,U+AC10,U+AC15,U+AC1C,U+AC74,U+ACB0,U+ACC4,U+ACE1,U+ACF5,U+ACFC,U+AD11,U+AD6C-AD6D,U+AD8C,U+ADF8,U+AE09,U+AE30,U+AE34,U+AE40,U+AE43,U+B098,U+B0A9,U+B0B4,U+B108,U+B110,U+B140,U+B144,U+B155,U+B192,U+B258,U+B294,U+B298,U+B2A5,U+B2C8,U+B2D8,U+B2E4,U+B2EC,U+B2F4,U+B2F9,U+B300,U+B304,U+B354-B355,U+B358,U+B370,U+B3C4-B3C5,U+B410,U+B4DC,U+B4E0,U+B4E4,U+B514,U+B527,U+B529,U+B530,U+B54C,U+B610,U+B77C,U+B780,U+B78C,U+B799,U+B7EC,U+B808-B809,U+B80C,U+B825,U+B85C,U+B860,U+B8E8,U+B974,U+B978,U+B97C,U+B984,U+B9AC-B9AD,U+B9B0,U+B9BC,U+B9C1,U+B9C8,U+B9D0,U+B9DE,U+B9E4,U+B9E8,U+BA3C,U+BA54,U+BA5C,U+BA70,U+BA74,U+BA85,U+BAA8,U+BB34,U+BB38,U+BB3C,U+BBF8,U+BBFC,U+BC0F,U+BC14,U+BC18,U+BC1C,U+BC24,U+BC29,U+BC30,U+BC84,U+BC8C,U+BC94,U+BCBD,U+BCC0,U+BCD1,U+BCF4,U+BCF8,U+BCFC,U+BD80,U+BD84,U+BD88,U+BDF0,U+BE0C,U+BE14,U+BE44,U+C0AC,U+C0B0,U+C0C1,U+C0C8,U+C0E4,U+C11C,U+C120,U+C124,U+C131,U+C138,U+C140,U+C149,U+C158,U+C18C,U+C190,U+C194,U+C1A1,U+C1FC,U+C218,U+C288,U+C2A4,U+C2B9,U+C2DC-C2DD,U+C2EB-C2EC,U+C544,U+C548,U+C54C,U+C560,U+C564,U+C5B4,U+C5BC,U+C5C4-C5C5,U+C5C7,U+C5D0,U+C5D4,U+C5D8,U+C5F0,U+C5F4,U+C601,U+C608,U+C624,U+C635,U+C640,U+C644,U+C694,U+C6A9,U+C6B0,U+C6B4,U+C6C3,U+C6CC,U+C6D0,U+C6E8,U+C704,U+C720,U+C73C,U+C740,U+C744,U+C74C,U+C758,U+C774,U+C778,U+C77C,U+C784,U+C787-C788,U+C791,U+C7A5,U+C7AC,U+C801,U+C804,U+C808,U+C815,U+C81C,U+C820,U+C870-C871,U+C874,U+C885,U+C8FC,U+C900,U+C911,U+C988,U+C990,U+C9C0,U+C9D5,U+C9DD,U+CC2C,U+CC98,U+CCAD,U+CCB4,U+CD08,U+CD5C,U+CD94,U+CD98,U+CD9C,U+CE90,U+CEE4,U+CEE8,U+CEEC,U+CF00,U+CF04,U+CF54,U+CF58,U+D004,U+D06C,U+D0C0,U+D130,U+D140,U+D15C,U+D1A4,U+D29C,U+D2B8,U+D2F0,U+D305,U+D30C,U+D310,U+D31D,U+D37C,U+D39C,U+D3B8,U+D3EC,U+D45C,U+D478,U+D488,U+D504,U+D50C,U+D53C,U+D558,U+D55C,U+D560,U+D568-D569,U+D574,U+D5A5,U+D5D8,U+D604,U+D611,U+D61C,U+D638,U+D63C,U+D64D,U+D654-D655,U+D669,U+D6C4-D6C5,U+D750,U+D76C,U+D799,U+FF08-FF09,U+FF1C,U+FF1E,U+FF3B,U+FF3D,U+FF5C}

/* ============================================================
   THE TOPDOWN — type-led system
   Archivo (variable width/weight) + Pretendard for Hangul
   ============================================================ */
:root{
  --bg:#000;
  --fg:#f4f4f0;
  --muted:#a5a59e;
  --dim:#8a8a83;
  --line:#232320;
  --line-2:#3a3a35;
  --soft:#0a0a09;
  --acc:#ffc400;
  --display:'Notable','BlackHanSans','Archivo','Pretendard','Helvetica Neue',Arial,sans-serif;
  /* the one Hangul face used beside Notable — swap this single token to
     change every Korean artist name at once */
  --ko-display:'GothicA1','Pretendard','Apple SD Gothic Neo',sans-serif;
  --sans:'Archivo','Pretendard','Helvetica Neue',Arial,'Apple SD Gothic Neo',
         'Hiragino Sans','PingFang SC','Thonburi',sans-serif;
  --gut:clamp(18px,3.6vw,56px);
  --maxw:1720px;
  --bar:46px;                         /* == the landing page's top rail */
  --pad-y:clamp(22px,4vh,48px);       /* == .home-main's top padding */
  --ease:cubic-bezier(.22,.61,.36,1);
  /* transparent margin on the right side of case.png, as a share of card width */
  --case-inset:1.43%;
  --case-inset-l:1.07%;
  /* chromatic split (resting) — left fringe warm, right fringe cool */
  --cs-warm:rgba(255,196,0,.72); --cs-cool:rgba(120,190,255,.66);
}

*{box-sizing:border-box;margin:0;padding:0}
/* every Hangul run is wrapped in .kk at build time — one knob for the
   Korean tracking across the whole site */
.kk{letter-spacing:-.04em}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
/* scrollbar-gutter keeps the layout width identical on pages that scroll
   and pages that do not — without it the header nav jumped 9px moving from
   WORKS to the single-screen BILLS. */
html{background:var(--bg);color-scheme:dark;scroll-behavior:smooth;-webkit-text-size-adjust:100%;
  scrollbar-gutter:stable}
/* Lenis owns the scroll position once it boots — a native smooth-scroll on
   top of it makes anchor jumps fight the rAF loop */
html.lenis{scroll-behavior:auto}
body{overflow-x:clip;
  min-height:100%;background:var(--bg);color:var(--fg);
  font-family:var(--sans);font-weight:400;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  font-synthesis-weight:none;
}
a{color:inherit;text-decoration:none}
img{max-width:100%;border:0}
button,input{font:inherit;color:inherit;background:none;border:0}
::selection{background:var(--acc);color:#000}
:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
[hidden]{display:none !important}
.num{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
.wrap{width:100%;max-width:var(--maxw);margin:0 auto;padding-inline:var(--gut)}

*::-webkit-scrollbar{width:9px;height:9px}
*::-webkit-scrollbar-track{background:#000}
*::-webkit-scrollbar-thumb{background:#242422;border:2px solid #000}
*::-webkit-scrollbar-thumb:hover{background:#3d3d38}

/* display type — condensed, heavy, uppercase */
.tt{
  font-family:var(--display);font-weight:400;font-stretch:100%;
  text-transform:uppercase;letter-spacing:-.01em;line-height:.92;
}
/* micro label */
.lbl{font:600 9.5px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}

/* ============================================================
   SITE BAR
   ============================================================ */
.site-bar{
  position:sticky;top:0;z-index:40;height:var(--bar);
  background:rgba(0,0,0,.82);
  -webkit-backdrop-filter:saturate(150%) blur(18px);backdrop-filter:saturate(150%) blur(18px);
  border-bottom:1px solid var(--line);
}
.site-bar__inner{
  height:100%;max-width:var(--maxw);margin:0 auto;padding:0 var(--gut);
  display:flex;align-items:center;justify-content:space-between;gap:20px;
}
.site-mark{
  font-weight:800;font-stretch:72%;font-size:17px;letter-spacing:.005em;
  text-transform:uppercase;white-space:nowrap;
  transition:color .25s var(--ease);
}

/* The floor has to clear 2 x --wipe-pad (18px) or adjacent links overlap in
   their padding and a tap between the words lands on the wrong one. */
.site-nav{display:flex;align-items:center;gap:clamp(20px,1.8vw,30px)}
/* "Wipe Reveal" — an accent plane rises through the label. Identical on the
   home hero and on every in-page bar. The horizontal padding is cancelled by
   an equal negative margin so the text edge, not the plate edge, stays on the
   gutter line. */
.site-nav a{
  --wipe-pad:9px;
  --nav-pad-y:5px;
  /* Notable reserves descender room its caps never use, so a symmetric padding
     leaves the label sitting low in the plate. Shift it back up by the measured
     offset (2.54px at 17px = .149em) while keeping the plate's height. */
  --nav-optical:.149em;
  position:relative;
  padding:calc(var(--nav-pad-y) - var(--nav-optical)) var(--wipe-pad)
          calc(var(--nav-pad-y) + var(--nav-optical));
  margin:0 calc(-1 * var(--wipe-pad));
  overflow:hidden;isolation:isolate;white-space:nowrap;
  font:600 10px/1 var(--sans);letter-spacing:.045em;text-transform:uppercase;color:var(--muted);
  transition:color .3s var(--ease);
}
.site-nav a::before{
  content:"";position:absolute;inset:0;z-index:-1;background:var(--acc);
  transform:translateY(101%);transition:transform .42s var(--ease);
}
.site-nav a:hover,.site-nav a:focus-visible{color:#000}
.site-nav a:hover::before,.site-nav a:focus-visible::before{transform:translateY(0)}
/* the current page is marked by brightness only — never a filled plate */
.site-nav a[aria-current="page"]{color:var(--fg)}

/* scroll progress */
.progress{position:fixed;top:0;left:0;height:2px;background:var(--acc);width:0;z-index:60;transition:width .1s linear}

/* ============================================================
   HOME
   ============================================================ */
.home{min-height:100svh}

.home-spec{
  /* Above the mirror. The mirror is absolutely positioned at the top of
     .home-main with a z-index, so it paints over this row — on a wide screen
     it is 660px centred and misses the right-aligned nav by luck, but on a
     phone it spans the full width and was eating every tap on WORKS/BILLS.
     Navigation outranks decoration, so the row is raised rather than the
     mirror being made inert: the belt keeps its own hover. */
  position:relative;z-index:3;
  display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:10px 26px;
  width:100%;max-width:var(--maxw);margin-inline:auto;min-height:var(--bar);
  padding-inline:var(--gut);padding-block:0;border-bottom:1px solid var(--line);
  font:600 9.5px/1.28 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim);
}
.home-spec b{color:var(--muted);font-weight:600}
.spec-set{display:flex;flex-wrap:wrap;gap:6px 26px;min-width:0}

.home-main{display:flex;flex-direction:column;justify-content:flex-end;container-type:inline-size;
  width:100%;max-width:var(--maxw);margin-inline:auto;padding:var(--pad-y) var(--gut)}
.home-tail{width:100%;max-width:var(--maxw);margin-inline:auto;padding:0 var(--gut)}
.wordmark{
  /* 9.47 = measured advance ratio of "THE TOPDOWN" in Notable at -.022em,
     so 100cqi (= .home-main content box) lands the final N on the gutter edge */
  font-family:var(--display);font-weight:400;font-stretch:100%;text-transform:uppercase;
  font-size:min(calc(100cqi / 9.47),30svh,190px);
  line-height:.95;letter-spacing:-.022em;white-space:nowrap;max-width:100%;
  overflow:clip;overflow-clip-margin:10px;
}
@supports not (width:1cqi){
  .wordmark{font-size:min(calc((100vw - 2 * var(--gut) - 12px) / 9.47),30svh,190px)}
}
/* 15.362 = measured advance ratio of "MECHANIZED TO MAKE IT" in Notable at
   -.022em tracking; 18.5svh mirrors the wordmark's 30svh cap proportionally
   so both stop growing at the same viewport height. */
.slogan{
  margin:0;
  font-family:var(--display);font-weight:400;font-stretch:100%;text-transform:uppercase;
  font-size:min(calc(100cqi / 15.362),18.5svh);
  line-height:calc(.95 * 15.362 / 9.47);letter-spacing:-.022em;white-space:nowrap;max-width:100%;
  overflow:visible;color:var(--fg);
}
/* stretched, not squashed: scaling by the ratio of the two advance divisors
   lifts the slogan's cap height to exactly the wordmark's, so the swap reads
   as one line changing its words rather than two lines of different weight */
.slogan>span{display:block;transform:scaleY(calc(15.362 / 9.47));transform-origin:50% 50%}

/* ---- partner belt --------------------------------------------------------
   A slow drift of partner marks directly above the wordmark. Slow on purpose:
   this is a credit, not a carousel — at 118s a mark takes most of a minute to
   cross, which reads as drifting rather than scrolling.

   The chromatic split the display type carries is a text-shadow, which an
   <img> cannot take. drop-shadow does the same job on the logo's alpha, so
   the marks get the identical mis-registered plate: warm fringe left, cool
   right, at the same em-scaled offset.

   The track holds the run twice and travels -50%, so the second copy is
   already in place when the first leaves and the loop never shows a seam. */
.pbelt{
  position:relative;overflow:hidden;width:100%;
  margin:0 0 clamp(8px,1.4vh,20px);
  /* fades at both ends so marks enter and leave rather than pop */
  -webkit-mask:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent);
          mask:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent);
}
.pbelt__track{
  display:flex;align-items:center;width:max-content;
  gap:clamp(7px,1.6vw,14px);
  animation:pbelt var(--pdur,118s) linear infinite;
}
.pbelt__m{
  /* Height was keyed to vh alone, which is exactly wrong on a phone: the
     viewport is tall and narrow, so 5.4vh gave a 44px mark whose artwork is
     three times as wide, and two of them filled the screen. Marks are wide,
     so the width of the screen is what has to bound them — min() takes
     whichever runs out first. */
  height:clamp(16px,min(5.4vh,6.4vw),66px);width:auto;flex:none;display:block;
  opacity:.5;
  --cs:max(1px,.06em);
  filter:drop-shadow(calc(-1 * var(--cs)) 0 var(--cs-warm))
         drop-shadow(var(--cs) 0 var(--cs-cool));
  transition:opacity .4s var(--ease);
}
.pbelt:hover .pbelt__m{opacity:.68}
/* one run's width exactly, whatever K is, so the loop closes on itself */
.pbelt__l{display:block;flex:none;line-height:0;text-decoration:none;
  transition:opacity .3s var(--ease),transform .3s var(--ease)}
.pbelt__l:hover .pbelt__m,.pbelt__l:focus-visible .pbelt__m{opacity:1}
.pbelt__l:focus-visible{outline:1px solid var(--acc);outline-offset:6px;border-radius:3px}
/* the belt keeps drifting under the cursor; stopping it would make a mark
   hard to hit rather than easy, since it stops somewhere other than where
   the pointer already is */
@keyframes pbelt{to{transform:translateX(calc(-100% / var(--pk,2)))}}
@media(prefers-reduced-motion:reduce){.pbelt__track{animation:none}}

/* ---- wordmark <-> slogan swap -------------------------------------------
   Both lines are laid into the same grid cell, so the block never changes
   height and nothing below it moves. Wrapping them also lifts them out of
   .stg's reveal, which owns opacity and transform on .home-main's direct
   children and would otherwise cancel the cross-fade. */
/* "Roll Down": the slogan drops in from above as the wordmark rolls out below.
   The cell clips so both lines leave the frame instead of overlapping the
   mirror and the tagline; the clip margin keeps the chromatic fringe intact. */
.mark-swap{position:relative;
  display:grid;grid-template-columns:minmax(0,1fr);
  overflow:clip;overflow-clip-margin:12px}
.mark-swap>.wordmark,.mark-swap>.slogan{grid-area:1 / 1;align-self:center;
  /* 14% of the cell = the 18.6px the caps hang below its centre at 140px */
  position:relative;top:-14%;
  transition:transform .52s var(--ease),opacity .3s var(--ease)}
.mark-swap>.slogan{opacity:0;transform:translateY(-105%)}
.mark-swap:hover>.wordmark,.mark-swap:focus-within>.wordmark{opacity:0;transform:translateY(105%)}
.mark-swap:hover>.slogan,.mark-swap:focus-within>.slogan{opacity:1;transform:translateY(0)}
@supports not (width:1cqi){
  .slogan{font-size:min(calc((100vw - 2 * var(--gut) - 12px) / 15.362),18.5svh)}
}
.tagline{margin:0;min-width:0;display:flex;flex-wrap:wrap;gap:3px 16px;align-items:baseline;
  text-transform:uppercase}

/* home hero nav — "Wipe Reveal": an accent plane rises through the label.
   Horizontal padding is cancelled by an equal negative margin so the text's
   right edge stays on the wordmark / social / rule line. */
.home-nav{flex:0 0 auto}

/* tagline row — copy left, social flush right */
/* the slogan is the wordmark's hover state — it holds its space so nothing
   jumps, and the rule that used to sit under it is gone */
.tag-row{
  margin-top:clamp(2px,.5vh,8px);padding-top:4px;
  display:flex;align-items:center;justify-content:space-between;gap:16px 24px;flex-wrap:wrap;
}
/* the 34px hit area insets the 17px glyph by 8.5px — pull it back out so the
   last icon's edge sits on the same line as the wordmark and the tag-row rule */
.tag-row .social{margin:0 -8.5px 0 auto;display:flex;gap:4px;flex:0 0 auto}
.tag-row .social a{width:34px;height:34px;display:grid;place-items:center;color:var(--muted);
  transition:color .25s var(--ease),background-color .25s var(--ease)}
.tag-row .social a:hover{color:var(--acc);background:#111}
.tag-row .social svg{width:17px;height:17px;fill:currentColor;display:block}
.tagline span{color:#cfcfc9}
.tagline strong{color:var(--fg);font-weight:400}

/* release ticker */
/* ============================================================
   REAR-VIEW MIRROR
   The frame is a cut-out of the source photograph (glass knocked out to
   transparency). The glass is a black plate clipped to the exact outline
   of the real glass, and the release belt runs inside it.
   ============================================================ */
.mirror-defs{position:absolute;width:0;height:0;overflow:hidden}
.home-main{--mw:min(46cqi,660px);--mh:calc(var(--mw) * 256 / 660)}
.mirror{
  /* centred with a margin, not translateX — .stg's reveal animation owns
     `transform` on every direct child of .home-main and would cancel it */
  position:absolute;top:0;left:50%;margin-left:calc(var(--mw) / -2);
  width:var(--mw);aspect-ratio:660 / 256;z-index:1;
}
/* The lockup is bottom-aligned, so it can only meet the mirror when the two
   together outgrow the section — which is exactly when .hero-sec drops out of
   its full-height grid. The reserve therefore lives only in that branch. */
.home-main{padding-top:var(--pad-y)}
@supports not (width:1cqi){ .home-main{--mw:min(46vw,660px)} }
@media(max-width:1000px){ .home-main{--mw:min(72cqi,560px)} }
/* the same conditions that turn .hero-sec into a plain block: there is no
   leftover space to align into, so the mirror must be reserved outright */
@media(max-width:1000px),(max-height:660px),(hover:none),(prefers-reduced-motion:reduce){
  .home-main{padding-top:calc(var(--mh) - var(--bar) + var(--pad-y))}
}
@media(max-width:760px){ .home-main{--mw:min(100cqi,460px)} }
.mirror-frame{
  position:absolute;inset:0;z-index:2;width:100%;height:100%;
  pointer-events:none;filter:drop-shadow(0 16px 30px rgba(0,0,0,.78));
}
.mirror-glass{
  /* the pane the belt runs in: the clip path is the exact outline of the
     glass pocket in the photograph, so the belt can never spill onto the frame */
  position:absolute;inset:0;z-index:1;background:#000;
  clip-path:url(#mirrorGlass);
  display:flex;align-items:center;overflow:hidden;
}
/* Park the belt on the glass, not on the frame — the stalk owns the top third.
   These are the measured bounds of the glass pocket in mirror.png, as a share
   of the frame's height; percentage insets resolve against height, a margin
   would resolve against width. */
.mirror-glass .ticker{position:absolute;left:0;right:0;top:34.4%;bottom:11.3%;
  display:flex;align-items:center}
.mirror .ticker{margin-top:0;width:100%}
/* ignition: the reflection jolts the way a mirror does when the engine turns
   over — vertical only, and it is the image that shakes, not the mirror */
/* 02's rocking tilt + 16's vibrato zoom. No vertical travel at all — the
   pure up-and-down read as machinery rather than something hanging off a
   stalk, so the rock carries the motion and the zoom gives it depth. */
@keyframes ignition{
  0%{transform:none}
  5%{transform:rotate(-1.2deg) scale(1.032)}
 12%{transform:rotate(.95deg)  scale(.984)}
 20%{transform:rotate(-.7deg)  scale(1.017)}
 29%{transform:rotate(.5deg)   scale(.992)}
 39%{transform:rotate(-.33deg) scale(1.007)}
 50%{transform:rotate(.2deg)   scale(.997)}
 62%{transform:rotate(-.11deg) scale(1.002)}
 75%{transform:rotate(.05deg)}
 88%{transform:rotate(-.02deg)}
100%{transform:none}
}
.mirror-glass .ticker{--ignite:4.4s;animation:ignition var(--ignite) cubic-bezier(.34,.7,.38,1) both}
/* travel and rattle run together: the belt is already moving while the
   reflection settles */
@media (prefers-reduced-motion:reduce){ .mirror-glass .ticker{animation:none} }
/* 11 SHEEN — a highlight travels across the glass, the way a windscreen
   throws light across a mirror as the car moves. It lives on .mirror-glass's
   own ::after, so the clip path already keeps it off the frame, and it sits
   above the belt but under the frame image.
   `screen` so it only ever adds light: over a dark tile it reads as a wipe,
   over a bright one it barely registers, which is how a real reflection
   behaves. */
.mirror .tick{width:clamp(34px,6.2cqi,70px);height:clamp(34px,6.2cqi,70px)}
.mirror-glass::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(104deg,transparent 38%,rgba(255,255,255,.30) 50%,transparent 62%);
  background-size:300% 100%;mix-blend-mode:screen;
  animation:sheen var(--sheen,7s) linear infinite;
}
@keyframes sheen{from{background-position:140% 0}to{background-position:-60% 0}}
@media(prefers-reduced-motion:reduce){.mirror-glass::after{animation:none;opacity:0}}

.ticker{
  margin-top:clamp(20px,3.2vh,40px);border:0;overflow:hidden;position:relative;min-width:0;
  /* a long two-stage ramp: the tiles are already half-gone before the hard
     edge of the glass, so the belt reads as receding rather than cut off */
  -webkit-mask:linear-gradient(90deg,transparent 0,rgba(0,0,0,.28) 13%,#000 34%,
    #000 66%,rgba(0,0,0,.28) 87%,transparent 100%);
  mask:linear-gradient(90deg,transparent 0,rgba(0,0,0,.28) 13%,#000 34%,
    #000 66%,rgba(0,0,0,.28) 87%,transparent 100%);
}
.ticker__track{display:flex;width:max-content;animation:slide 78s linear infinite}
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.tick{
  position:relative;flex:0 0 auto;display:block;overflow:hidden;
  width:clamp(54px,6.2vh,78px);height:clamp(54px,6.2vh,78px);
  margin-right:1px;background:var(--soft);
}
.tick img{width:100%;height:100%;object-fit:cover;display:block;filter:saturate(.85);
  transition:transform .6s var(--ease),filter .35s var(--ease)}
/* The name is the Latin spelling only — the builder strips the Hangul, since
   both together will not sit in a 70px tile. Tracking and leading are wound
   right down for the same reason: at 9px in a tile this small, every bit of
   space between letters and lines is a word that has to wrap instead. */
.tick__name{
  position:absolute;inset:0;display:grid;place-items:center;padding:3px 2px;
  background:rgba(0,0,0,.7);color:var(--fg);text-align:center;overflow-wrap:anywhere;
  font:400 9px/1 var(--sans);letter-spacing:-.02em;word-spacing:-.04em;
  text-transform:uppercase;
  opacity:0;transition:opacity .3s var(--ease);
}
.tick:hover img,.tick:focus-visible img{transform:scale(1.06);filter:brightness(.34) saturate(.9)}
.tick:hover .tick__name,.tick:focus-visible .tick__name{opacity:1}

.home-contact{
  margin-top:clamp(26px,4vh,44px);
  /* content-sized columns: the Seoul address is the long one and gets the
     room it needs instead of being forced into an equal third */
  display:grid;grid-template-columns:auto auto auto;justify-content:end;
  text-align:right;border-top:1px solid var(--line);
}
.home-contact div{padding:11px 0 11px 20px;border-left:1px solid var(--line);margin-left:18px}
.home-contact div:first-child{border-left:0;padding-left:0;margin-left:0}
.home-contact dt{font:600 9px/1 var(--sans);letter-spacing:.05em;text-transform:uppercase;color:var(--dim);margin-bottom:9px}
.home-contact dd{font:400 12px/1.12 var(--sans);letter-spacing:.01em;color:#d2d2cd;
  white-space:nowrap}
.home-contact a{border-bottom:1px solid var(--line-2);transition:color .25s var(--ease),border-color .25s var(--ease)}
.home-contact a:hover{color:var(--acc);border-color:var(--acc)}


/* ---- selected achievements / key works (home) ---- */
.keyworks{padding-top:clamp(30px,4.6vh,58px)}
.kw-head{display:flex;align-items:baseline;justify-content:space-between;gap:14px 24px;flex-wrap:wrap;
  padding-bottom:13px;border-bottom:1px solid var(--line-2)}
.kw-head h2{font-size:clamp(30px,4.6vw,64px)}
.kw-cta{display:inline-flex;align-items:center;gap:9px;padding-bottom:5px;
  font:700 10px/1 var(--sans);letter-spacing:.045em;text-transform:uppercase;color:var(--acc)}
.kw-cta .ar{display:inline-flex;transition:transform .3s var(--ease)}
.kw-cta:hover .ar{transform:translateX(4px)}

.stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-bottom:1px solid var(--line)}
.stats div{display:flex;align-items:center;gap:clamp(14px,1.4vw,24px);
  padding:20px 24px 22px;border-left:1px solid var(--line);min-width:0}
.stats div:first-child{border-left:0;padding-left:0}
.stat-n{flex:0 0 auto;font-weight:800;font-stretch:68%;font-size:clamp(30px,2.55vw,42px);line-height:1;
  letter-spacing:-.03em;color:var(--fg);
  /* Notable reserves descender space the digits never use — nudge the ink
     back onto the row's optical centre */
  transform:translateY(var(--stat-nudge,-.093em))}
.stat-n .plus{color:var(--acc)}
.stats dt{flex:1 1 auto;min-width:0;margin:0;font:600 12px/1.14 var(--sans);letter-spacing:.02em;
  text-transform:uppercase;color:var(--muted);max-width:40ch}
.stats-note{padding:12px 0;border-bottom:1px solid var(--line);
  font:400 10px/1.22 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:#d6d6d1}
.stats-note .dim{color:var(--dim)}

.kw-note{margin-top:10px;font:400 9.5px/1.24 var(--sans);letter-spacing:.02em;color:#84847d;max-width:96ch}

/* ---- full-page snap (home only) ---- */
html.snap{scroll-snap-type:y mandatory}
.snap-sec{min-height:100svh;scroll-snap-align:start;scroll-snap-stop:always}
/* CSS snap comes off wherever a section cannot own a screen: below the
   full-height thresholds, under reduced motion, and on touch. Forcing 100svh
   sections onto a phone left the wordmark stranded on its own screen and the
   whole stack reading as one cramped block. */
@media (prefers-reduced-motion:reduce),
       (max-width:1000px),
       (max-height:660px),
       (hover:none){
  html.snap{scroll-snap-type:none}
  .snap-sec{min-height:0;scroll-snap-align:none;scroll-snap-stop:normal}
}
.hero-sec{position:relative;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr) auto;padding-bottom:12px}
.end-sec{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr)}
/* two rows: the achievement/partner block keeps its optical centre inside the
   free space, the contact rail sits on the floor. A flex `margin-top:auto`
   would eat all the slack and pin the block to the top instead. */
.end-body{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto;
  width:100%;min-height:0}
.end-body .split{align-self:center}
.end-body .home-tail{align-self:end;padding-top:clamp(20px,4vh,52px)}
.scroll-cue{
  justify-self:start;display:inline-flex;align-items:center;gap:10px;
  padding:0 var(--gut) 4px;
  font:600 8.5px/1 var(--sans);letter-spacing:.05em;text-transform:uppercase;color:#84847d;
}
.scroll-cue__line{display:block;width:34px;height:1px;background:#2c2c28;position:relative;overflow:hidden}
.scroll-cue__line::after{content:"";position:absolute;inset:0;background:var(--acc);
  transform:translateX(-100%);animation:cue 2.4s var(--ease) infinite}
@keyframes cue{0%{transform:translateX(-100%)}55%{transform:translateX(100%)}100%{transform:translateX(100%)}}
/* snapping only makes sense when a screen can actually hold a section */
@media (max-height:660px),(max-width:1000px),(hover:none),(prefers-reduced-motion:reduce){
  .hero-sec{display:block}
  .end-sec{display:block}
  .scroll-cue{display:none}
}

/* ---- track record + partners (one screen, split) ---- */
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(26px,3.6vw,64px);align-items:start}
.col-numbers,.col-partners{min-width:0}
.partners{padding-top:0}

.stats--stack{grid-template-columns:1fr}
.stats--stack div{border-left:0;border-top:1px solid var(--line);padding:10px 0 11px}
.stats--stack div:first-child{border-top:0;padding-top:4px}
.stats--stack dt{max-width:42ch}

.pmq{
  margin-top:clamp(12px,1.8vh,20px);
  display:grid;grid-template-columns:minmax(0,1fr);gap:1px;background:var(--line);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
.pmq-row{background:#000;overflow:hidden;padding:7px 0;position:relative;min-width:0}
.pmq-row::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,#000 0,transparent 7%,transparent 93%,#000 100%);
}
.pmq-track{display:flex;gap:clamp(18px,2vw,30px);width:max-content;animation:mq 58s linear infinite}
.pmq-row:nth-child(2) .pmq-track{animation-duration:74s;animation-direction:reverse}
.pmq-row:nth-child(3) .pmq-track{animation-duration:66s}
.pmq-row:nth-child(4) .pmq-track{animation-duration:86s;animation-direction:reverse}
.pmq-row:nth-child(even) .pmq-track span{color:#d3d3cd}
.pmq-track span{
  font:800 clamp(14px,1.4vw,21px)/1 var(--sans);font-stretch:70%;
  text-transform:uppercase;letter-spacing:-.015em;white-space:nowrap;
}
.pmq:hover .pmq-track{animation-play-state:paused}
@keyframes mq{to{transform:translateX(-50%)}}

/* ============================================================
   CATALOG
   ============================================================ */
/* WORKS and BILLS run entirely in capitals. Hangul has no case, so this only
   touches the Latin runs; the Korean half of a name is unaffected. */
.catalog-page,.bill-page{text-transform:uppercase}
.catalog-page{min-height:100vh;padding-bottom:var(--pad-y)}
.catalog-tools{padding-top:var(--pad-y)}
.eyebrow{font:600 9.5px/1.1 var(--sans);letter-spacing:.05em;text-transform:uppercase;color:var(--dim);margin-bottom:10px}
.catalog-intro h1{font-size:clamp(58px,12.5vw,190px)}
.catalog-summary{display:grid;gap:0;border:1px solid var(--line);min-width:230px}
.catalog-summary div{display:flex;justify-content:space-between;gap:18px;padding:6px 12px;border-top:1px solid var(--line)}
.catalog-summary div:first-child{border-top:0}
.catalog-summary .k{font:600 9px/1.1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim)}
.catalog-summary .v{font:600 10px/1.1 var(--sans);letter-spacing:.02em;color:var(--fg);font-variant-numeric:tabular-nums}

/* toolbar */
.catalog-tools{
  position:sticky;top:var(--bar);z-index:20;
  background:rgba(0,0,0,.88);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);
  border-block:1px solid var(--line);
}
.catalog-tools__inner{
  max-width:var(--maxw);margin:0 auto;padding:9px var(--gut);
  display:flex;align-items:center;gap:10px 18px;flex-wrap:wrap;
}
/* horizontal scrollers: a fade at the trailing edge shows there is more,
   and the pseudo-element keeps a gutter after the last chip */
.filters{display:flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;overflow-x:auto;
  scrollbar-width:none;padding:2px 0;scroll-padding-inline:var(--gut)}
.filters::-webkit-scrollbar{display:none}
.chip{
  flex:0 0 auto;cursor:pointer;white-space:nowrap;
  padding:8px 12px;border:1px solid var(--line-2);
  font:600 9px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--muted);
  transition:color .22s var(--ease),border-color .22s var(--ease),background-color .22s var(--ease);
}
.chip:hover{color:var(--fg);border-color:#8f8f87}
.chip[aria-pressed="true"],.chip[aria-current="page"]{background:var(--acc);border-color:var(--acc);color:#000}
.chip .c{font-variant-numeric:tabular-nums;opacity:.55;margin-left:6px}
/* The language rail is a setting somebody picks once, not this page's
   navigation — but it was wearing the same outlined box and the same amber
   fill as the service tabs below it, so two rows argued for the same job.
   Stripped back to plain text: the current language is amber and heavier,
   the rest are quiet. The filled amber now belongs to the tabs alone.
   Scoped to .lang-switch so the WORKS filter chips keep their box. */
.lang-switch .chip{padding:4px 2px;border-color:transparent;background:transparent}
.lang-switch .chip:hover{color:var(--fg);border-color:transparent}
.lang-switch .chip[aria-current="page"]{background:transparent;border-color:transparent;
  color:var(--acc);font-weight:800}
.tool-right{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.search{display:flex;align-items:center;gap:8px;height:33px;padding:0 12px;border:1px solid var(--line-2);min-width:0;
  transition:border-color .22s var(--ease)}
.search:focus-within{border-color:var(--acc)}
.search svg{width:12px;height:12px;fill:none;stroke:var(--dim);stroke-width:1.7;flex:0 0 auto}
.search input{width:120px;min-width:0;font:400 11px/1 var(--sans);letter-spacing:.05em;
  text-transform:uppercase}
.search input::placeholder{color:var(--dim);letter-spacing:.04em;text-transform:uppercase;font-size:9px;font-weight:600}
.search input:focus{outline:0}
.sort-btn{
  cursor:pointer;height:33px;padding:0 13px;border:1px solid var(--line-2);white-space:nowrap;flex:0 0 auto;
  font:600 9px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--muted);
  display:inline-flex;align-items:center;gap:8px;transition:color .22s var(--ease),border-color .22s var(--ease);
}
.sort-btn:hover{color:var(--fg);border-color:#8f8f87}
.sort-btn .arrow{display:inline-block;transition:transform .3s var(--ease)}
.sort-btn[data-order="asc"] .arrow{transform:rotate(180deg)}
.result-count{font:600 9px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim);
  font-variant-numeric:tabular-nums;white-space:nowrap}

/* grid */
.catalog-grid{
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  gap:clamp(20px,2.4vw,34px) clamp(10px,1.4vw,18px);
  padding-top:clamp(16px,2.6vh,28px);
}

.catalog-card{display:flex;flex-direction:column;min-width:0;height:100%}
/* ---- cassette ------------------------------------------------------------
   The stage is locked to the asset canvas, 1672 x 941. Every full-canvas
   layer registers on it at inset:0; change this ratio and object-fit:contain
   letterboxes them, at which point the hubs orbit instead of spinning.
   Defaults below are the ones picked off the demo. */
.cover-media{
  container-type:inline-size;
  --cass-tex:0;              /* label_texture_overlay opacity */
  --cass-blend:overlay;        /* screen blows out light artwork */
  --cass-art-y:0%;             /* which band of a square cover shows */
  --cass-spin:3.4s;            /* one hub revolution */
  --cass-sat:0.84;              /* label chroma — 1 leaves the cover untouched */
  --cass-con:1.6;                /* label contrast, same scale */
  --cass-rx:0deg; --cass-ry:0deg; --cass-sc:1;   /* set by the pointer, below */
  position:relative;aspect-ratio:1672/941;background:transparent;overflow:visible;
  /* The tape tips toward whatever the cursor is nearest, like a thing you are
     holding rather than a picture of one. The angle is written by JS as two
     variables so the resting state, the easing and the limits all stay here.
     Transform does not affect layout, so the container query still measures
     the same box and the aspect ratio still rules the height. */
  transform:perspective(900px) rotateX(var(--cass-rx)) rotateY(var(--cass-ry))
            scale(var(--cass-sc));
  transition:transform .5s var(--ease);
}
/* while a card is actually being tracked it should follow, not lag; letting go
   hands it back to the slow ease above so it settles instead of snapping */
.catalog-card.is-tilting .cover-media{transition-duration:.1s}
@media(hover:none){.cover-media{transform:none}}
@media(prefers-reduced-motion:reduce){.cover-media{transform:none}}
.cass-art,.cass-shell,.cass-tex{position:absolute;inset:0;display:block}
/* The shell's window is transparent — whatever sits behind the cassette is
   what shows through it. With nothing back there the window reads as a black
   hole, so each card lays its own cover down, blurred, and the window picks
   up that record's colour. Bleeds past the stage so the blur has room. */
/* The slot mask was re-cut: it used to stop at y=274, which left a dead band
   between the top shell bar and the label with nothing behind the clear
   plastic. It now opens at y=112, where the shell window itself opens, so
   the artwork fills the whole window. 1456x556 instead of 1456x395. */
.cass-art{z-index:1;
  -webkit-mask:url(cassette/artwork_slot_mask.webp?v=e0b68533) center/100% 100% no-repeat;
  mask:url(cassette/artwork_slot_mask.webp?v=e0b68533) center/100% 100% no-repeat}
/* The cover sits behind aged plastic. At full chroma it reads as a sticker
   stuck on the tape rather than a label printed into it, so the two knobs
   above pull it back. They are variables, not baked-in values: set them on
   .cover-media to move every card, or on one card to treat it on its own. */
/* The gear centres are open in the sprites — alpha runs to zero inside 56%
   of the gear radius — so the artwork was showing through them like a window
   onto the label. A real reel well is a hole: you look past the tape at
   nothing. These two discs sit under the hubs and above the artwork, so the
   opening and the gaps between the teeth read as the same black the page is
   on. r=90px on the 1672 canvas: wider than the 57px opening, inside the
   shell's 97px ring hole, so nothing peeks out from behind the gear. */
.cass-hole{position:absolute;z-index:1;width:10.766%;aspect-ratio:1;border-radius:50%;
  background:#000;transform:translate(-50%,-50%);pointer-events:none}
.cass-hole--l{left:27.7213%;top:45.4835%}
.cass-hole--r{left:72.1890%;top:45.4835%}
.cass-cover{width:100%;height:100%;object-fit:cover;object-position:center var(--cass-art-y);
  display:block;filter:saturate(var(--cass-sat)) contrast(var(--cass-con));
  transition:object-position .6s var(--ease),filter .5s var(--ease)}
.cass-shell{z-index:3;background:url(cassette/cassette_shell_base.webp) center/100% 100% no-repeat;
  filter:drop-shadow(0 10px 20px rgba(0,0,0,.5));transition:filter .55s var(--ease)}
.cass-tex{z-index:4;background:url(cassette/label_texture_overlay.webp?v=7000053f) center/100% 100% no-repeat;
  opacity:var(--cass-tex);mix-blend-mode:var(--cass-blend);pointer-events:none}
/* Hubs are 1254px square sprites, not full canvas, so they are placed by the
   measured numbers from the reference build: top-left offsets, each sprite
   scaled so its gear reads 200px on the 1672px canvas (width sizes the whole
   sprite, so each is divided by its own gear radius, 428 and 410 of 1254).
   transform-origin is the MEASURED disc centre, not 50% 50% — the gears sit
   slightly off-centre in their sprites, so spinning about the sprite centre
   makes them orbit instead of turn.
   The radial mask cuts each sprite to r=112px about that same centre: wider
   than the shell's 97.5px ring hole so the hole stays filled, inside the ring
   itself so the cut edge hides. It also removes the clear plastic collar on
   hub_right, which is moulded into the shell and must not rotate. */
.cass-hub{position:absolute;z-index:2;aspect-ratio:1;
  background-size:100% 100%;background-repeat:no-repeat;
  animation:cass-spin var(--cass-spin) linear infinite;animation-play-state:paused}
.cass-hub--l{left:19.0295%;top:30.1389%;width:17.5234%;
  transform-origin:49.6013% 49.2823%;
  -webkit-mask:radial-gradient(ellipse 38.2265% 38.2265% at 49.6013% 49.2823%,#000 0 95%,transparent 100%);
          mask:radial-gradient(ellipse 38.2265% 38.2265% at 49.6013% 49.2823%,#000 0 95%,transparent 100%);
  background-image:url(cassette/hub_left.webp)}
.cass-hub--r{left:63.0572%;top:29.2320%;width:18.2927%;
  transform-origin:49.9203% 50.0000%;
  animation-name:cass-spin-r;animation-duration:calc(var(--cass-spin)*.84375);
  -webkit-mask:radial-gradient(ellipse 36.6188% 36.6188% at 49.9203% 50.0000%,#000 0 95%,transparent 100%);
          mask:radial-gradient(ellipse 36.6188% 36.6188% at 49.9203% 50.0000%,#000 0 95%,transparent 100%);
  background-image:url(cassette/hub_right.webp)}
/* The reels turn at their own rates and against each other, as in the
   reference: 3.2s one way, 2.7s the other. Locking both to one speed and one
   direction is what read as mechanical. */
@keyframes cass-spin{to{rotate:360deg}}
@keyframes cass-spin-r{to{rotate:-360deg}}
/* 46 cards will not all animate at once: a hub only turns while its card is
   under the cursor, the way the disc used to spin. */
.catalog-card:hover .cass-hub,.catalog-card:focus-visible .cass-hub{animation-play-state:running}
@media(prefers-reduced-motion:reduce){.cass-hub{animation:none!important}}
/* ---- the copy, over the tape ---------------------------------------------
   The artist/title/date used to sit under the cassette and repeat inside the
   hover overlay. It is now only the overlay, so the grid reads as tape until
   something is pointed at. Cards on screen at load carry .is-revealed, and
   touch devices (no hover to rely on) show it always. */
.tone{
  position:absolute;inset:0;z-index:6;pointer-events:none;
  display:flex;align-items:flex-end;padding:0 5.2% 4.4%;
  background:linear-gradient(to top,rgba(0,0,0,.82) 0,rgba(0,0,0,.55) 26%,rgba(0,0,0,.1) 56%,transparent 78%);
  opacity:0;transition:opacity .45s var(--ease)}
.catalog-card:hover .tone,.catalog-card:focus-visible .tone,.catalog-card.is-revealed .tone{opacity:1}
@keyframes spin{to{transform:rotate(360deg)}}

.card-copy{display:block;width:100%;min-width:0;
  transform:translateY(9px);opacity:0;
  transition:transform .45s var(--ease) .05s,opacity .45s var(--ease) .05s}
.catalog-card:hover .card-copy,.catalog-card:focus-visible .card-copy,
.catalog-card.is-revealed .card-copy{transform:translateY(0);opacity:1}
/* Two lines the same weight and much the same brightness read as one block,
   which is what they were doing. The title takes the weight and the light and
   the artist steps back a shade — the difference is carried by contrast, not
   by leading, so the copy stays as tight as it was asked to be. */
.card-artist{margin:0 0 2px;font:700 clamp(10.5px,5cqw,14px)/1.05 var(--ko-display);letter-spacing:-.035em;
  color:var(--fg);overflow-wrap:anywhere;text-shadow:0 1px 2px #000,0 2px 12px rgba(0,0,0,.8)}
/* One face for both scripts. Notable is a display cut — wide, heavy, tight
   counters — and at 12px over artwork the Latin half was the hard half to
   read while the Hangul beside it was clean. GothicA1 carries both, so the
   name reads as one word instead of two typefaces meeting in the middle.
   Colour still separates them; leading and tracking are pulled right in. */
/* The Hangul takes the colour step but not the weight, for two reasons and
   the second is the decisive one.
   It is a gloss on the Latin, not a second item, so weight can mark the
   primary reading while colour marks the gloss — one signal each, rather
   than both piled on one half.
   And there is no bold Korean face here to ask for. GothicA1 ships at 400
   only, and its unicode-range is Korean, so the Latin falls through to
   Pretendard, which does have a real 700. Measured: the Latin gains 19% ink
   at 700, the Hangul 3% and no width at all — the browser is faking it.
   Setting 400 explicitly says what is actually rendering, and keeps this
   from changing under us if a bold Korean face is ever added.
   pretendard-kr-700.woff2 is already in the fonts folder if bold Hangul is
   ever wanted; it would need adding to the --ko-display stack. */
.card-artist .ko{font-weight:400;letter-spacing:-.045em;color:var(--muted);margin-left:.34em}
.card-artist .la{letter-spacing:-.03em;color:var(--fg)}
.card-artist .sep{color:var(--dim);margin:0 .1em}
.card-line{display:flex;align-items:flex-end;justify-content:space-between;gap:6px;min-width:0;
  text-shadow:0 1px 2px #000,0 2px 10px rgba(0,0,0,.8)}
.card-title{flex:1 1 auto;min-width:0;font:500 clamp(9.5px,4.4cqw,12.5px)/1.16 var(--sans);text-wrap:pretty;
  letter-spacing:-.01em;color:#cfcfc9;overflow-wrap:anywhere}
.card-date{flex:0 0 auto;margin-left:auto;text-align:right;white-space:nowrap;
  font:600 clamp(9px,3.6cqw,10.5px)/1.3 var(--sans);letter-spacing:.02em;color:var(--muted);
  font-variant-numeric:tabular-nums}
/* No hover to reveal on, so the copy simply stands */
@media(hover:none){
  .tone{opacity:1}
  .card-copy{transform:none;opacity:1}
}

.catalog-empty{display:none;padding:clamp(40px,8vh,84px) 0;text-align:center;
  font:600 11px/1.14 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim)}
.catalog-page.is-empty .catalog-empty{display:block}

.catalog-footer{
  display:flex;justify-content:space-between;align-items:flex-end;gap:20px;
  margin-top:clamp(42px,6.5vh,84px);padding-top:15px;border-top:1px solid var(--line);
  font:600 9.5px/1.32 var(--sans);letter-spacing:.04em;color:var(--dim);text-transform:uppercase;
}
.catalog-footer a{transition:color .25s var(--ease)}
.catalog-footer a:hover{color:var(--acc)}

.to-top{
  position:fixed;right:clamp(14px,2.4vw,28px);bottom:clamp(14px,2.4vw,28px);z-index:50;
  width:42px;height:42px;display:grid;place-items:center;cursor:pointer;
  border:1px solid var(--line-2);color:var(--muted);background:rgba(0,0,0,.75);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  opacity:0;visibility:hidden;transform:translateY(10px);
  transition:opacity .3s var(--ease),transform .3s var(--ease),visibility .3s,color .2s,border-color .2s,background-color .2s;
}
.to-top.show{opacity:1;visibility:visible;transform:none}
.to-top:hover{color:#000;background:var(--acc);border-color:var(--acc)}

/* ============================================================
   RELEASE DETAIL
   ============================================================ */
.detail-page{min-height:100vh;padding-bottom:var(--pad-y)}
.detail-shell{max-width:var(--maxw);margin:0 auto;padding:var(--pad-y) var(--gut) 0}
.crumbs{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding-bottom:clamp(22px,3.4vh,38px);
  font:600 9.5px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim);
}
.crumbs a{color:var(--muted);transition:color .25s var(--ease)}
.crumbs a:hover{color:var(--acc)}
.crumbs .sep{color:#333}
.detail-back{display:inline-flex;align-items:center;gap:8px}
.detail-back .ar{display:inline-block;transition:transform .3s var(--ease)}
.detail-back:hover .ar{transform:translateX(-4px)}

.release-hero{display:grid;grid-template-columns:minmax(280px,420px) minmax(0,1fr);gap:clamp(34px,4.6vw,80px);align-items:start}
.cover-col{position:sticky;top:calc(var(--bar) + 24px)}
.release-cover{aspect-ratio:1;background:var(--soft);overflow:hidden;position:relative}
.release-cover::after{content:"";position:absolute;inset:0;box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}
.release-cover img{width:100%;height:100%;display:block;object-fit:cover}
.cover-caption{margin-top:10px;display:flex;justify-content:space-between;gap:12px;
  font:600 9px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim);font-variant-numeric:tabular-nums}
.cover-caption .hl{color:var(--acc)}

.release-info{min-width:0}
.release-artist{font:600 11px/1.28 var(--sans);letter-spacing:.05em;color:var(--muted);text-transform:uppercase;margin-bottom:14px}
.release-title{font-size:clamp(34px,4.6vw,72px);line-height:.98;letter-spacing:-.032em;font-weight:800;overflow-wrap:anywhere}
.roles{display:flex;flex-wrap:wrap;gap:6px;margin-top:20px}
.role{padding:7px 11px;border:1px solid var(--acc);color:var(--acc);
  font:700 8.5px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase}

.meta-grid{margin-top:clamp(26px,4vh,42px);display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-block:1px solid var(--line)}
.meta-grid div{padding:12px 15px 14px;border-left:1px solid var(--line);min-width:0}
.meta-grid div:first-child{border-left:0;padding-left:0}
.meta-grid dt{font:600 9px/1 var(--sans);letter-spacing:.045em;text-transform:uppercase;color:var(--dim);margin-bottom:9px}
.meta-grid dd{font:600 13px/1.28 var(--sans);letter-spacing:.02em;color:var(--fg);font-variant-numeric:tabular-nums}

.section-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding-bottom:11px;border-bottom:1px solid var(--line-2)}
.section-label{font:700 10px/1 var(--sans);letter-spacing:.05em;text-transform:uppercase;color:var(--fg)}
.section-note{font:600 9px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim);font-variant-numeric:tabular-nums}

.credit-section{margin-top:clamp(38px,5.6vh,64px)}
.credit-head,.credit-row{display:grid;grid-template-columns:40px minmax(0,1fr) minmax(190px,.7fr);gap:clamp(12px,1.8vw,24px);align-items:baseline}
.credit-head{padding:11px 0;border-bottom:1px solid var(--line);font:600 8.5px/1 var(--sans);letter-spacing:.04em;color:#87877f;text-transform:uppercase}
.credit-row{padding:13px 0;border-bottom:1px solid var(--line);transition:background-color .25s var(--ease)}
.credit-row:hover{background:#080807}
.track-no{font:700 10px/1.32 var(--sans);letter-spacing:.02em;color:var(--dim);font-variant-numeric:tabular-nums}
.track-name{font-size:16px;line-height:1.22;font-weight:700;letter-spacing:-.012em;overflow-wrap:anywhere}
.track-credit{font:600 11px/1.25 var(--sans);letter-spacing:.04em;color:#c9c9c3;text-align:right;text-transform:uppercase}

.media-section{margin-top:clamp(38px,5.6vh,64px)}
.players{margin-top:18px;display:grid;grid-template-columns:1fr;gap:14px}
.players.multi{grid-template-columns:repeat(2,minmax(0,1fr))}
.youtube-frame{width:100%;border:0;display:block;aspect-ratio:16/9;background:#050505}
.spotify-frame{width:100%;height:152px;border:0;background:#050505}
.no-player{border:1px solid var(--line);padding:30px 22px;text-align:center;
  font:600 10px/1.38 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--dim)}

.release-nav{margin-top:clamp(48px,8vh,100px);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border-block:1px solid var(--line)}
.rel-link{display:flex;align-items:center;gap:13px;padding:14px 20px;min-height:88px;transition:background-color .3s var(--ease)}
.rel-link+.rel-link{border-left:1px solid var(--line)}
.rel-link.prev{padding-left:0}
.rel-link.next{flex-direction:row-reverse;text-align:right;padding-right:0}
.rel-link:hover{background:#080807}
.rel-link img{width:58px;height:58px;object-fit:cover;flex:0 0 auto;background:var(--soft);transition:opacity .3s var(--ease)}
.rel-link:hover img{opacity:.75}
.rel-copy{min-width:0}
.rel-dir{display:block;font:600 8.5px/1 var(--sans);letter-spacing:.05em;text-transform:uppercase;color:var(--dim);margin-bottom:9px;
  transition:color .25s var(--ease)}
.rel-link:hover .rel-dir{color:var(--acc)}
.rel-title{font-size:15px;line-height:1.18;font-weight:700;letter-spacing:-.014em;overflow-wrap:anywhere}
.rel-artist{margin-top:5px;font:400 10px/1.28 var(--sans);letter-spacing:.04em;color:var(--muted)}
.rel-link.plain .rel-title{font-size:14px}

.detail-footer{margin-top:clamp(42px,6vh,78px);padding-top:18px;border-top:1px solid var(--line);
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  font:600 9px/1.32 var(--sans);letter-spacing:.04em;color:#87877f;text-transform:uppercase}
.detail-footer a{transition:color .25s var(--ease)}
.detail-footer a:hover{color:var(--acc)}

/* ============================================================
   BILLS
   ============================================================ */
/* the site header sits above this block in flow, so a full 100svh here
   always pushed the page one header past the fold */
.bill-page{min-height:calc(100vh - var(--bar));min-height:calc(100svh - var(--bar));
  /* Redefining --sans is not enough: most BILLS text inherits its family
     from <body>, which sits outside .bill-page and resolved var(--sans)
     against the root value. Set the family here so it actually inherits. */
  --sans:'Archivo','GothicA1','Pretendard','Helvetica Neue',Arial,sans-serif;
  font-family:var(--sans);
  display:flex;flex-direction:column}
.bill-page>*:last-child{margin-top:auto}
.bill-page>.lang-bar + .wrap{padding-top:clamp(20px,2.8vh,36px)}
.bill-rate{display:block}
.bill-rate>*:last-child{margin-top:0}
.bill-hero h1{font-size:clamp(44px,7.6vw,124px);display:flex;align-items:baseline;gap:clamp(10px,1.4vw,20px);flex-wrap:wrap}
.bill-rate .bill-hero h1{font-size:clamp(32px,3.8vw,56px)}
.bill-rate .bill-claim{margin-top:clamp(7px,1vh,12px);padding-top:8px}
.bill-lang-mark{font:700 11px/1 var(--sans);font-stretch:100%;letter-spacing:.05em;color:#000;background:var(--acc);
  padding:8px 11px;transform:translateY(-.3em)}
.bill-claim{margin-top:clamp(7px,1.1vh,12px);padding-top:8px;border-top:1px solid var(--line-2);
  font:700 11px/1.22 var(--sans);letter-spacing:.055em;text-transform:uppercase;color:var(--acc)}

.bill-langs{margin-top:clamp(12px,1.8vh,20px)}
.lang-grid{margin-top:14px;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}
.lang-card{background:#000;padding:14px clamp(12px,1.2vw,18px) 12px;display:flex;flex-direction:column;gap:4px;min-height:92px;
  transition:background-color .3s var(--ease)}
.lang-card:hover{background:#0a0a09}
.lang-code{font-weight:800;font-stretch:70%;text-transform:uppercase;font-size:clamp(22px,1.9vw,30px);line-height:1;letter-spacing:-.015em;
  transition:color .25s var(--ease)}
.lang-card:hover .lang-code{color:var(--acc)}
.lang-name{font:400 11px/1.14 var(--sans);letter-spacing:.04em;color:var(--muted)}
.lang-go{margin-top:auto;display:inline-flex;align-items:center;gap:6px;
  font:600 8px/1 var(--sans);letter-spacing:.05em;text-transform:uppercase;color:var(--dim);
  opacity:0;transform:translateY(6px);transition:opacity .3s var(--ease),transform .3s var(--ease),color .3s}
.lang-card:hover .lang-go,.lang-card:focus-visible .lang-go{opacity:1;transform:none;color:var(--acc)}

.lang-bar{position:sticky;top:var(--bar);z-index:20;background:rgba(0,0,0,.88);
  -webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border-bottom:1px solid var(--line)}
.lang-bar__inner{max-width:var(--maxw);margin:0 auto;padding:9px var(--gut);display:flex;align-items:center;gap:14px}
/* on a phone both rails centre — nothing sits to their left any more */
@media(max-width:560px){
  .lang-bar__inner{justify-content:center}
  .lang-switch{justify-content:center;flex:0 1 auto}
}
.lang-switch{display:flex;gap:clamp(13px,2.4vw,20px);overflow-x:auto;scrollbar-width:none;padding:2px 0;min-width:0;
  scroll-padding-inline:var(--gut)}
.lang-switch::-webkit-scrollbar{display:none}

.bill-section{display:block}
.bill-section__head{display:block}
.bill-section h2{font-size:clamp(16px,1.45vw,21px);line-height:1.02;letter-spacing:-.028em;font-weight:800;
  overflow-wrap:break-word;text-wrap:balance}
/* ---- BILLS: scan layer -------------------------------------------------
   The tables were all one weight, so a reader had to price the work out for
   themselves. Three additions carry the scan: a derived range on each section
   head and one action per section. Starting prices say so in words. Add-on
   groups drop a step in contrast so the core work reads first. */
.bill-range{display:flex;align-items:baseline;gap:8px;margin:3.5px 0 0;flex-wrap:wrap}
.bill-range .k{font:600 8px/1 var(--sans);letter-spacing:.09em;text-transform:uppercase;color:var(--dim)}
/* Not condensed. 70% is the site's width for standalone figures — the home
   stats still use it — but this one sits on the same line as the service
   title, and two widths side by side read as two fonts. Matches the title's
   tracking too, and the estimate bar's total was already 100%. */
.bill-range .v{font:800 clamp(13px,1.22vw,17px)/1 var(--sans);
  letter-spacing:-.028em;color:var(--acc);font-variant-numeric:tabular-nums}
/* ---- BILLS: one service at a time ---------------------------------------
   Three panels, one visible, chosen by a named button. Without script every
   panel shows and the page stacks, which is why the hiding is gated on .js. */
.bill-deck{display:block}
.bill-deck>.bill-section{display:block;margin:0;border-top:0;padding-top:0}
.js .bill-deck>.bill-section{display:none}
.js .bill-deck>.bill-section.is-active{display:block}
.bill-section__head{position:static;padding-bottom:clamp(15px,1.5vw,24px);
  border-bottom:1px solid var(--line-2)}
.bill-section h2{display:block;font-size:clamp(20px,2vw,30px)}
/* One card owns the full width, so the groups sit side by side again.
   Everything loose lives out here, between blocks. Everything inside a group
   stays tight, so each paragraph still reads as a single object. */
.bill-groups{margin-top:clamp(18px,1.9vw,30px);gap:clamp(15px,1.6vw,28px);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,250px),1fr))}
/* a service with a single group would otherwise stretch that one card across
   1,600px and stop reading as a card at all */
.bill-groups:has(> details:only-child){grid-template-columns:minmax(0,min(100%,560px))}

/* The chooser. No boxes: one rule runs under the whole row and a single
   amber bar slides along it to whichever service is open. The bar moving
   from one place to another is what says these three are one control —
   three separate filled boxes never did. Labels wrap rather than truncate,
   so a long service name is never cut down to a guess. */
.deck-tabs{position:relative;display:flex;flex-wrap:nowrap;
  gap:0 clamp(20px,2.4vw,40px);margin:0 0 clamp(18px,2vw,30px);
  border-bottom:1px solid var(--line)}
.deck-tab{
  display:block;flex:0 0 auto;white-space:nowrap;text-align:left;cursor:pointer;
  padding:clamp(9px,.8vw,12px) 0 clamp(11px,1vw,15px);
  border:0;background:transparent;color:var(--muted);
  font:700 9.5px/1.24 var(--sans);letter-spacing:.05em;text-transform:uppercase;
  overflow-wrap:break-word;text-wrap:balance;
  transition:color .25s var(--ease);
}
.deck-tab:hover{color:var(--fg)}
.deck-tab[aria-selected="true"]{color:var(--acc)}
.deck-tab:focus-visible{outline:1px solid var(--acc);outline-offset:2px}
/* the bar. Script sets width and offset; the transition does the sliding,
   and it only animates once a first position has been set so the page does
   not open with the bar flying in from the corner. */
.deck-ink{position:absolute;left:0;bottom:-1px;height:2px;width:0;
  background:var(--acc);pointer-events:none}
.deck-ink.ready{transition:transform .38s var(--ease),width .38s var(--ease)}
@media(prefers-reduced-motion:reduce){.deck-ink{transition:none!important}}
/* One row at every width. The labels are one word each, and the widest set
   (Japanese) needs 184px of the 284px a 320px phone has — so the stack that
   used to kick in under 560px is gone, and with it 70px of chrome. */
@media(max-width:560px){
  .deck-tabs{gap:0 clamp(16px,5vw,26px);justify-content:center}
  .deck-tab{padding:11px 0 12px}
}
@media(max-width:760px){
}
/* add-ons: same information, quieter voice */
.bill-group--add{opacity:.68;border-style:dashed;
  transition:opacity .3s var(--ease),border-color .28s var(--ease)}
.bill-group--add .bill-item__price{color:var(--muted)}
.bill-group--add:hover{opacity:1}

/* This is a sentence, not a label. Tracked-out 8.5px caps is what made it
   hard to read — caps suit CORE RANGE, they do not suit a clause. */
.bill-note{margin:6px 0 0;font:400 10.5px/1.42 var(--sans);letter-spacing:0;color:var(--muted);
  /* the one exception to the page's capitals: Hangul has no case so the
     Korean note was already fine, but the Latin ones were a full clause
     set in caps, which is the hardest thing on the page to read */
  text-transform:none;
  max-width:62ch;overflow-wrap:break-word;text-wrap:pretty}
.bill-groups{
  /* was CSS multi-column: it balanced groups of unequal length into ragged
     columns and made the reading order run down-then-across, which is wrong
     for a price list. Equal-width cards read left-to-right and give each
     group a visible boundary. */
  margin-top:0;display:grid;align-items:start;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,232px),1fr));
  gap:clamp(15px,1.6vw,28px);
}
.bill-group{
  margin:0;display:block;min-width:0;
  border:1px solid var(--line);padding:clamp(16px,1.3vw,22px);
  transition:border-color .28s var(--ease);
}
.bill-group:hover{border-color:var(--line-2)}
/* <summary> is the whole group header: title left, item count right. On a
   wide screen the group never closes, so the row is inert there. */
.bill-group__sum{display:flex;align-items:center;gap:9px;list-style:none;cursor:pointer;
  padding:1px 0;transition:color .2s var(--ease)}
.bill-group__sum::-webkit-details-marker{display:none}
.bill-group__sum::marker{content:""}
.bill-group__sum:hover .bill-group__title{color:var(--acc)}
.bill-group__sum:focus-visible{outline:1px solid var(--acc);outline-offset:3px}
/* the toggle sign: a plus that becomes a minus when the group is open */
.bill-group__sum::after{content:"";flex:none;width:8px;height:8px;position:relative;
  background:
    linear-gradient(var(--dim),var(--dim)) 50% 50%/8px 1px no-repeat,
    linear-gradient(var(--dim),var(--dim)) 50% 50%/1px 8px no-repeat;
  transition:background-size .22s var(--ease)}
details[open]>.bill-group__sum::after{background-size:8px 1px,1px 0}
.bill-group__title{flex:1 1 auto;min-width:0;font:700 9.5px/1.1 var(--sans);letter-spacing:.05em;
  text-transform:uppercase;color:var(--fg);overflow-wrap:break-word;text-wrap:balance}
.bill-group__n{flex:none;font:700 9px/1 var(--sans);color:var(--dim);
  font-variant-numeric:tabular-nums}
details[open]>.bill-group__sum>.bill-group__n{opacity:0}
.bill-group__desc{margin-top:4px;font:400 10px/1.26 var(--sans);letter-spacing:.01em;color:var(--muted);
  overflow-wrap:break-word;text-wrap:balance}
.bill-list{margin-top:clamp(12px,1.1vw,17px);border-top:1px solid var(--line-2)}
/* A row is a <label>, so the whole strip is the hit area for its box. */
.bill-item{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:1px 9px;
  padding:9px 0;border-bottom:1px solid var(--line);align-items:baseline;
  cursor:pointer;transition:background-color .25s var(--ease)}
.bill-item:last-child{border-bottom:0;padding-bottom:0}
.bill-item:hover{background:#0b0b0a}
.bill-item:has(.bi-box:checked){background:#0e0d0a}
/* Every row is a checkbox and every row can be unticked, so they all read as
   one: a square that takes a tick. The exclusive groups used to be drawn as
   circles to borrow a radio's "one of these", but that also promised a
   control you cannot clear, which is not what these are. Exclusivity is
   carried by the behaviour and by the group copy instead. */
.bi-box{appearance:none;-webkit-appearance:none;margin:0;flex:none;
  width:13px;height:13px;align-self:center;background:transparent;cursor:pointer;
  border:1px solid var(--line-2);border-radius:2px;position:relative;
  transition:background-color .18s var(--ease),border-color .18s var(--ease)}
.bi-box:hover{border-color:var(--acc)}
.bi-box:checked{background:var(--acc);border-color:var(--acc)}
/* the tick is drawn, not a glyph: no font to load and it scales cleanly */
.bi-box:checked::after{content:"";position:absolute;left:3.5px;top:.5px;
  width:4px;height:8px;border:solid #000;border-width:0 1.7px 1.7px 0;
  transform:rotate(42deg)}
.bi-box:focus-visible{outline:1px solid var(--acc);outline-offset:2px}
/* `overflow-wrap:anywhere` was breaking Korean mid-word ("사용 범/위 조건").
   keep-all breaks on 어절 instead, and text-wrap:balance stops a label from
   dropping one stray word onto a line of its own. */
.bill-item__label{font-size:11.5px;line-height:1.14;font-weight:700;letter-spacing:-.012em;
  overflow-wrap:break-word;text-wrap:balance}
.bill-item__price{font:700 11.5px/1.14 var(--sans);letter-spacing:.01em;color:var(--acc);text-align:right;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.bill-item__desc{grid-column:2/-1;margin-top:1px;font:400 9.5px/1.26 var(--sans);color:var(--dim);
  /* balance, not pretty: these run two or three lines, and evening them out
     beats leaving a 10%-wide tail under a full line */
  overflow-wrap:break-word;text-wrap:balance}
/* A worded price ("70% of list price", "open for discussion") is nowrap like
   any other, so it was claiming half the row and shredding the label into
   five lines. Those two take a line of their own instead. */
.bill-item[data-kind="ratio"] .bill-item__label,
.bill-item[data-kind="ask"] .bill-item__label{grid-column:2/-1}
.bill-item[data-kind="ratio"] .bill-item__price,
.bill-item[data-kind="ask"] .bill-item__price{grid-column:2/-1;white-space:normal;margin-top:2px}

/* keep-all belongs to Korean only: it breaks lines on 어절 instead of
   mid-word. Japanese and Chinese want the opposite — a break between any two
   characters, with the browser's kinsoku rules keeping 。 off a line start —
   and applying keep-all there was stranding punctuation on its own line. */
html:lang(ko) .bill-section h2,
html:lang(ko) .bill-group__title,
html:lang(ko) .bill-group__desc,
html:lang(ko) .bill-item__label,
html:lang(ko) .bill-item__desc,
html:lang(ko) .bill-note{word-break:keep-all}

/* ---- BILLS · Korean tracking ---------------------------------------------
   Gothic A1 stays, but the site-wide -.04em was not enough here: at the card
   title's 30px the runs read loose against the tightly-tracked Archivo they
   sit beside, so the Hangul is pulled in further, hardest at display size.
   Scoped to html:lang(ko) .bill-page — the works pages keep -.04em. */
html:lang(ko) .bill-page .kk{letter-spacing:-.055em}
html:lang(ko) .bill-page h2 .kk{letter-spacing:-.078em}
html:lang(ko) .bill-page .bill-group__title .kk,
html:lang(ko) .bill-page .bill-item__label .kk{letter-spacing:-.05em}
html:lang(ko) .bill-page .bill-note .kk,
html:lang(ko) .bill-page .bill-range .k{letter-spacing:-.05em}
/* the estimate sheet is written by script, so its Hangul never passes
   through a .kk wrapper — set the whole block instead */
html:lang(ko) .bill-page .est__lines,
html:lang(ko) .bill-page .est__foot,
html:lang(ko) .bill-page .est__bar,
html:lang(ko) .bill-page .est__note,
html:lang(ko) .bill-page .est__acts{letter-spacing:-.055em}

/* ---- ESTIMATE BAR ---------------------------------------------------------
   Docked to the bottom of the viewport and hidden until the first tick, so an
   untouched page still reads as a plain rate card. The sheet expands upward
   from the same rail. */
.est{position:fixed;left:0;right:0;bottom:0;z-index:60;
  background:rgba(4,4,4,.94);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  border-top:1px solid var(--line-2);
  animation:est-in .34s var(--ease) both}
@keyframes est-in{from{transform:translateY(100%)}to{transform:none}}
@media(prefers-reduced-motion:reduce){.est{animation:none}}
.est__bar{display:flex;align-items:center;gap:10px;
  padding:9px var(--gut);min-height:44px;cursor:pointer;
  transition:background-color .2s var(--ease)}
.est__bar:hover{background:rgba(255,255,255,.035)}
.est__bar:hover .est__toggle{border-color:var(--acc);color:var(--acc)}
.est__count{flex:none;min-width:20px;height:20px;display:grid;place-items:center;
  background:var(--acc);color:#000;font:800 11px/1 var(--sans);
  font-variant-numeric:tabular-nums;padding:0 5px}
.est__label{font:700 9.5px/1 var(--sans);letter-spacing:.05em;color:var(--muted);
  text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.est__sum{margin-left:auto;font:800 15px/1 var(--sans);color:var(--acc);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.est__toggle{flex:none;display:inline-flex;align-items:center;gap:6px;
  background:transparent;border:1px solid var(--line-2);color:var(--fg);
  padding:8px 10px;font:700 9.5px/1 var(--sans);letter-spacing:.05em;
  text-transform:uppercase;cursor:pointer;
  transition:border-color .25s var(--ease),color .25s var(--ease)}
.est__toggle:hover{border-color:var(--acc);color:var(--acc)}

.est__sheet{border-top:1px solid var(--line);padding:14px var(--gut) 16px;
  max-height:min(62svh,520px);overflow-y:auto;overscroll-behavior:contain}
.est__title{font:800 11px/1 var(--sans);letter-spacing:.06em;text-transform:uppercase;
  color:var(--fg);margin-bottom:10px}
.est__sec{margin:12px 0 4px;font:700 9px/1 var(--sans);letter-spacing:.08em;
  text-transform:uppercase;color:var(--acc)}
.est__sec:first-child{margin-top:0}
.est__row{display:flex;align-items:baseline;gap:12px;padding:4px 0;
  border-bottom:1px solid var(--line)}
.est__row .l{flex:1 1 auto;min-width:0;font:400 11.5px/1.25 var(--sans);
  color:var(--fg);overflow-wrap:anywhere}
.est__row .v{flex:none;font:700 11.5px/1.25 var(--sans);color:var(--muted);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.est__row.is-ask .v{color:var(--dim)}
/* remove-this-line. Quiet until the row is touched, so the sheet still reads
   as a bill rather than a row of controls — but always present in the layout
   so nothing shifts when it appears. */
/* A ringed minus, and it stands whether or not anything is hovering it:
   taking a line back out is the whole point of the sheet, so it should not
   be something you have to go looking for. */
.est__drop{flex:none;width:16px;height:16px;padding:0;background:transparent;
  border:1px solid var(--line-2);border-radius:50%;cursor:pointer;position:relative;
  align-self:center;opacity:.72;
  transition:opacity .18s var(--ease),border-color .18s var(--ease),background-color .18s var(--ease)}
.est__drop::before{content:"";position:absolute;left:50%;top:50%;
  width:7px;height:1.5px;background:var(--muted);transform:translate(-50%,-50%);
  transition:background-color .18s var(--ease)}
.est__row:hover .est__drop{opacity:1}
.est__drop:hover{opacity:1;border-color:var(--acc);background:var(--acc)}
.est__drop:hover::before{background:#000}
.est__drop:focus-visible{opacity:1;outline:1px solid var(--acc);outline-offset:2px}
/* a finger needs the whole 40px, but the ring should stay the size it reads at */
@media(hover:none){.est__drop{width:22px;height:22px;opacity:.85}
  .est__drop::before{width:9px}}
.est__foot{margin-top:12px;border-top:1px solid var(--line-2);padding-top:8px}
.est__foot .est__row{border-bottom:0;padding:3px 0}
.est__foot .l{color:var(--muted);font-weight:700;font-size:10px;
  letter-spacing:.05em;text-transform:uppercase}
.est__row.is-total .l{color:var(--fg);font-size:11px}
.est__row.is-total .v{color:var(--acc);font-size:16px;font-weight:800}
.est__note{margin-top:10px;font:400 10px/1.35 var(--sans);color:var(--dim)}
.est__acts{margin-top:12px;display:flex;flex-wrap:wrap;gap:8px}
.est__go,.est__copy,.est__reset{font:700 9.5px/1 var(--sans);letter-spacing:.05em;
  text-transform:uppercase;padding:10px 13px;cursor:pointer;
  border:1px solid var(--line-2);background:transparent;color:var(--fg);
  transition:background-color .25s var(--ease),border-color .25s var(--ease),color .25s var(--ease)}
.est__go{background:var(--acc);border-color:var(--acc);color:#000}
.est__go:hover{filter:brightness(1.12)}
.est__copy:hover,.est__reset:hover{border-color:var(--acc);color:var(--acc)}
.est__reset{color:var(--dim)}
/* Hangul in the bar and the sheet is rendered by script, so it never passes
   through the per-run .kk wrapper — tighten the whole block instead. */
.est[data-ko] .est__lines,.est[data-ko] .est__toggle,
.est[data-ko] .est__copy,.est[data-ko] .est__reset{letter-spacing:-.04em}
/* keep the last section clear of the docked bar */
.bill-page{padding-bottom:80px}

/* ---- contact strip -------------------------------------------------------
   It used to inherit .meta-grid's fixed three columns, which only collapse to
   one at 620px — but the BILLS copy drops its horizontal padding at 760px, so
   between those two numbers three columns sat edge to edge and a value ran
   straight into the next label. The strip now sizes itself: auto-fit steps
   3 -> 2 -> 1 before anything can touch, the gap is always real, and inside a
   cell the value wraps onto its own line rather than colliding. */
.bill-contact{margin-top:clamp(30px,3.8vh,56px);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,215px),1fr));
  column-gap:clamp(16px,2.4vw,36px)}
.bill-contact div{display:flex;flex-wrap:wrap;align-items:baseline;
  justify-content:space-between;gap:1px 12px;padding:8px 0 9px;border-left:0}
.bill-contact div + div{border-top:1px solid transparent}
.bill-contact dt{margin:0;flex:0 0 auto;font-size:8.5px;line-height:1.2}
.bill-contact dd{flex:1 1 auto;min-width:0;text-align:right;
  font-size:11.5px;line-height:1.2;overflow-wrap:anywhere}
.bill-contact dd a{border-bottom:1px solid var(--line-2);transition:color .25s var(--ease),border-color .25s var(--ease)}
.bill-contact dd a:hover{color:var(--acc);border-color:var(--acc)}

/* ============================================================
   MOTION
   ============================================================ */
@media (prefers-reduced-motion:no-preference){
  .js .rv{opacity:0;transform:translateY(18px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
  .js .rv.in{opacity:1;transform:none}
  .js .stg>*{opacity:0;transform:translateY(14px)}
  .js .stg.in>*{opacity:1;transform:none;transition:opacity .6s var(--ease),transform .6s var(--ease)}
  .js .stg.in>*:nth-child(1){transition-delay:.02s}
  .js .stg.in>*:nth-child(2){transition-delay:.09s}
  .js .stg.in>*:nth-child(3){transition-delay:.16s}
  .js .stg.in>*:nth-child(4){transition-delay:.23s}
  .js .stg.in>*:nth-child(5){transition-delay:.3s}
  .js .stg.in>*:nth-child(6){transition-delay:.37s}
  .js .stg.in>*:nth-child(n+7){transition-delay:.44s}
}

/* ============================================================
   NOTABLE — uppercase label / display layer
   Latin-only font: Korean characters fall back to Pretendard by
   unicode-range, so mixed-script body copy stays on Archivo.
   ============================================================ */
.site-mark,.site-nav a,.btn,.eyebrow,.chip,.sort-btn,.result-count,
.section-label,.section-note,
.credit-head,.cover-caption,.crumbs,.rel-dir,.catalog-footer,.detail-footer,
.home-spec,.stat-n,.stats dt,.stats-note,.pmq-track span,
.lang-code,.bill-lang-mark,.bill-claim,.scroll-cue,.catalog-empty,.no-player,
.kw-cta,.p-name{font-family:var(--display)}

/* ============================================================
   CHROMATIC SPLIT — static, never animated.
   Applied across the display-type layer: a warm fringe left, a cool one
   right, like a mis-registered offset plate. Offsets are em-based so the
   effect keeps the same weight from a 13px label to a 170px wordmark.
   Excluded: sub-10px micro-labels (the fringe would swallow the letterform)
   and all body copy, which stays clean for reading.
   ============================================================ */
.wordmark,.slogan,.tt,.stat-n,.lang-code,
.site-mark,.tagline,.bill-item__label,
.p-name{
  --cs:max(1px,.013em);
  text-shadow:calc(-1 * var(--cs)) 0 var(--cs-warm), var(--cs) 0 var(--cs-cool);
}
.site-mark{--cs:1.2px}                    /* the calibration already signed off on */
.bill-item__label{--cs:.8px}              /* 13.5px: a full pixel closes the counters */

/* Notable runs ~1.8x wider than Archivo — trim the label sizes to match */
.site-mark{font-size:20px;letter-spacing:-.005em}
.site-nav a{font-size:17px;letter-spacing:.02em}
.eyebrow{font-size:8.5px;letter-spacing:.03em}
.chip{font-size:8px;letter-spacing:.03em}
.sort-btn,.result-count{font-size:8px;letter-spacing:.03em}
.section-label{font-size:9px;letter-spacing:.05em}
.section-note{font-size:8px;letter-spacing:.03em}
.credit-head{font-size:7.5px;letter-spacing:.03em}
.cover-caption{font-size:8px;letter-spacing:.04em}
.crumbs{font-size:8.5px;letter-spacing:.05em}
.rel-dir{font-size:7.5px;letter-spacing:.05em}
.catalog-footer,.detail-footer{font-size:8.5px;letter-spacing:.03em}
.home-spec{font-size:8.5px;letter-spacing:.04em}
.stats dt{font-size:11px;letter-spacing:.015em}
.stats-note{font-size:9px;letter-spacing:.02em}
.pmq-track span{font-size:clamp(12px,1.15vw,17px);letter-spacing:.005em}
.bill-claim{font-size:9.5px;letter-spacing:.09em}
.scroll-cue{font-size:7.5px;letter-spacing:.04em}
.catalog-empty,.no-player{font-size:9.5px;letter-spacing:.04em}
.kw-cta{font-size:9px;letter-spacing:.05em}
.tagline{font-family:var(--display);font-size:clamp(13px,1.35vw,19px);letter-spacing:.015em;line-height:1.1}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media(max-width:1200px){.lang-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:620px){.lang-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1900px){.catalog-grid{grid-template-columns:repeat(6,minmax(0,1fr))}}
@media(max-width:1180px){
  .release-hero{grid-template-columns:minmax(240px,350px) minmax(0,1fr)}
  .catalog-grid{grid-template-columns:repeat(4,minmax(0,1fr))}
}
@media(max-width:1000px){
  /* Stacked, RECORDS and PARTNERS are two separate statements with nothing
     but whitespace between them, so the gap has to read as a section break —
     roughly a quarter of the screen, plus a rule to mark the seam. */
  .split{grid-template-columns:1fr;gap:0}
  /* --seam is the whole gap a reader actually sees, from the last RECORDS
     line to the first PARTNERS line. The rule sits inside it, not on top of
     it — measuring only down to the rule is what made an earlier "180px"
     still read as 223px on screen. */
  .col-partners{--seam:clamp(119px,19.3vh,178px);
    margin-top:calc(var(--seam) * .56);padding-top:calc(var(--seam) * .44);
    border-top:1px solid var(--line)}
  .end-sec{padding-top:clamp(84px,14vh,140px)}
  .end-body .home-tail{padding-top:clamp(72px,11vh,112px)}
  .bill-section__head{position:static;margin-bottom:14px;
    display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 14px}
  .bill-section__head h2{flex:1 0 100%;min-width:0}
  .bill-range{margin-top:0;flex:1 0 100%}
  .bill-note{flex-basis:100%;margin-top:2px}
  .catalog-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
  .players.multi{grid-template-columns:1fr}
}
@media(max-width:860px){
  :root{--bar:42px}
  .site-mark{font-size:17px}
  .home-contact{grid-template-columns:1fr}
  .stats{grid-template-columns:1fr}
  .stats div{border-left:0;border-top:1px solid var(--line);padding:14px 0 16px}
  .stats div:first-child{border-top:0;padding-top:4px}
  .home-contact div{border-left:0;border-top:1px solid var(--line);padding:12px 0}
  .home-contact div:first-child{border-top:0}
  .catalog-intro{grid-template-columns:1fr;align-items:start}
  .catalog-summary{min-width:0}
  .release-hero{grid-template-columns:1fr;gap:28px}
  .cover-col{position:static}
  .release-cover,.cover-caption{max-width:400px}
  .credit-head{display:none}
  .credit-row{grid-template-columns:28px minmax(0,1fr);gap:11px;padding:14px 0}
  .track-credit{grid-column:2;text-align:left;margin-top:7px}
  .release-nav{grid-template-columns:1fr}
  .rel-link.next{flex-direction:row;text-align:left}
  .rel-link+.rel-link{border-left:0;border-top:1px solid var(--line)}
  .rel-link.prev,.rel-link.next{padding-left:0;padding-right:0}
}
@media(max-width:760px){

  /* micro-label floor. Everything under ~9px was set for a desktop viewing
     distance; on a phone these are the labels people actually squint at. */
  .chip,.sort-btn,.result-count,.eyebrow,.section-note,.year-band .n,
  .catalog-footer,.detail-footer,.home-spec,.credit-head,.cover-caption,
  .crumbs,.rel-dir,.bill-claim,.bill-range .k,
  .stats-note,.kw-cta,.home-contact dt,.scroll-cue{
    font-size:10px;letter-spacing:.03em;
  }
  /* touch targets: the visual size stays, the hit area grows to ~40px */
  .site-nav a{--nav-pad-y:11px}
  .site-mark{display:inline-block;padding-block:11px}
  .search input{padding-block:9px}
  .bill-group__sum{padding:7px 0}
  /* the layout is shared now — only the sizes change on a phone, and stacked
     cells get a real rule between them */
  .bill-contact{margin-top:12px}
  .bill-page .bill-contact div{padding:6px 0 5px}
  .bill-page .bill-contact div + div{border-top-color:var(--line)}
  .bill-page .bill-contact dt{font-size:9px}
  .bill-page .bill-contact dd{font-size:11px;line-height:1.15}
  /* no margin-top:auto here — the page is meant to end, not to be filled */
  .bill-page>*:last-child{margin-top:0}
  .bill-page .catalog-footer{margin-top:clamp(14px,2vh,22px);padding-top:12px}
  .detail-back,.rel-link,.to-top{padding-block:10px}
  .tag-row .social a{width:40px;height:40px}

  .stats dt{font-size:12px}
  .role{font-size:10px}
  .meta-grid dt,.home-contact dt,.bill-contact dt{font-size:10px}
  .section-label{font-size:10.5px}
  .tick__name{font-size:10px}
  .bill-group__desc,.bill-item__desc{font-size:11px}
  .catalog-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:30px 12px}
  .catalog-tools__inner{gap:8px}
  .chip{padding:8px 11px}
  /* no box to fill out any more — the padding is only the tap target */
  .lang-switch .chip{padding:8px 3px}
  .tool-right{width:100%;justify-content:space-between}
  .search{flex:1 1 auto}
  .search input{width:100%}
  .result-count{display:none}
  .catalog-footer,.detail-footer{display:block}
  .catalog-footer div+div,.detail-footer div+div{margin-top:9px}
  .bill-item{grid-template-columns:auto minmax(0,1fr) auto;gap:3px 12px}
  .bill-item__price{text-align:right}
  .lang-bar__inner{gap:11px}
}
@media(max-width:620px){
  .meta-grid{grid-template-columns:1fr}
  .meta-grid div{border-left:0;border-top:1px solid var(--line);padding:12px 0}
  .meta-grid div:first-child{border-top:0}
  .bill-section__head{grid-template-columns:1fr;gap:8px}
  .bill-note{text-align:left;flex-basis:100%;margin-top:6px}
}
@media(max-width:520px){
  .site-mark{font-size:14px}
  /* The links cancel their 9px padding with a -9px margin, so a gap under
     18px leaves adjacent hit boxes overlapping — at 12px the two plates
     shared 6px and a tap in the sliver between the words could open the
     wrong page. 20px keeps them apart. */
  .site-nav{gap:20px}
  .site-nav a{font-size:13px;letter-spacing:.02em}
  .home-spec{padding-inline:var(--gut)}
  .lang-card{min-height:0;padding:12px 14px}
  .lang-go{opacity:1;transform:none}
  .catalog-grid{gap:26px 10px}
  .bill-item__label{font-size:13.5px}
}

@media(max-width:400px){
  :root{--bar:38px}
  .site-mark{font-size:13px}
  /* the label shrinks here, so the plate padding shrinks with it — and the
     gap still has to clear 2 x --wipe-pad or the hit boxes overlap */
  .site-nav{gap:16px}
  /* 4px left a 19px tap target; the label shrinks here but the finger does
     not, so the plate keeps roughly the height it has on bigger phones */
  .site-nav a{font-size:11px;--nav-pad-y:10px;--wipe-pad:7px}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important}
  .ticker__track{animation:none}
}

/* ============================================================
   BILLS — every size on the page, up 15%.
   Written as an override scoped to .bill-page rather than edited at
   source, because half of these selectors are shared with WORKS:
   .chip is the language switch here and the format filter there,
   .catalog-footer and the contact dt/dd are on every page. Scoping is
   what keeps the other pages at the size they were signed off at.
   Each value is the original times 1.15, kept in that form so the next
   pass can see what it started from.
   ============================================================ */
.bill-page .bill-section h2{font-size:clamp(23px,2.3vw,34.5px)}   /* 20 / 2vw / 30 */
.bill-page .bill-range .k{font-size:9.2px}                        /* 8 */
.bill-page .bill-range .v{font-size:clamp(15px,1.4vw,19.6px)}     /* 13 / 1.22vw / 17 */
.bill-page .bill-note{font-size:12.1px}                           /* 10.5 */
.bill-page .deck-tab{font-size:12.55px}                           /* 9.5 → 15% → 15% */
.bill-page .bill-group__title{font-size:10.9px}                   /* 9.5 */
.bill-page .bill-group__n{font-size:10.35px}                      /* 9 */
.bill-page .bill-group__desc{font-size:11.5px}                    /* 10 */
.bill-page .bill-item__label{font-size:13.2px}                    /* 11.5 */
.bill-page .bill-item__price{font-size:13.2px}                    /* 11.5 */
.bill-page .bill-item__desc{font-size:10.9px}                     /* 9.5 */
.bill-page .lang-switch .chip{font-size:10.6px}                   /* 8 → 15% → 15% */
.bill-page .bill-contact dt{font-size:9.8px}                      /* 8.5 */
.bill-page .bill-contact dd{font-size:13.2px}                     /* 11.5 */
.bill-page .catalog-footer{font-size:9.8px}                       /* 8.5 */
.bill-page .est__count{font-size:12.65px}                         /* 11 */
.bill-page .est__label,
.bill-page .est__toggle,
.bill-page .est__go,
.bill-page .est__copy,
.bill-page .est__reset{font-size:10.9px}                          /* 9.5 */
.bill-page .est__sum{font-size:17.25px}                           /* 15 */
.bill-page .est__title{font-size:12.65px}                         /* 11 */
.bill-page .est__row .l,
.bill-page .est__row .v{font-size:13.2px}                         /* 11.5 */
.bill-page .est__foot .l{font-size:11.5px}                        /* 10 */
.bill-page .est__row.is-total .l{font-size:12.65px}               /* 11 */
.bill-page .est__row.is-total .v{font-size:18.4px}                /* 16 */
.bill-page .est__note{font-size:11.5px}                           /* 10 */
@media(max-width:760px){
  .bill-page .bill-range .k,
  .bill-page .catalog-footer{font-size:11.5px}                    /* 10 */
  .bill-page .lang-switch .chip{font-size:13.25px}                 /* 10 → 15% → 15% */
  .bill-page .bill-contact dt{font-size:10.35px}                   /* 9 */
  .bill-page .bill-contact dd{font-size:12.65px}                   /* 11 */
  .bill-page .bill-group__desc,
  .bill-page .bill-item__desc{font-size:12.65px}                   /* 11 */
}
@media(max-width:520px){
  .bill-page .bill-item__label{font-size:15.5px}                   /* 13.5 */
}
/* The language switch and the section tabs take a second 15% on top of the
   first, at the request of whoever has to read them across a room. The tabs'
   sliding underline is measured off the label at runtime, so it follows on
   its own; the tap targets are widened to stay ahead of the bigger type. */
.bill-page .lang-switch{gap:clamp(15px,2.8vw,23px)}
.bill-page .lang-switch .chip{padding:5px 3px}
@media(max-width:560px){
  .bill-page .lang-switch .chip{padding:9px 4px}
  .bill-page .deck-tab{padding:13px 0 14px}
}
