/* === css/style.css === */
/* frontend/css/style.css */
/* 얇고 투명한 스크롤바(전역) — 시각 노이즈 최소화. 호버 시에만 옅게 표시. */
* { scrollbar-width: thin; scrollbar-color: transparent transparent; }
*::-webkit-scrollbar { width: 5px; height: 5px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: transparent; border-radius: 6px; }
*:hover::-webkit-scrollbar-thumb { background: rgba(148, 163, 184, 0.30); }
*::-webkit-scrollbar-thumb:hover { background: rgba(148, 163, 184, 0.55); }
*::-webkit-scrollbar-corner { background: transparent; }

/* ★W-PERF3 font-face BEGIN — scripts/subset_font.py 가 쓴다(손으로 고치지 말 것). 원본 14336자 = 서브셋 2950 + 나머지 11386(겹침 0) */
/* Pretendard Variable — 로컬 벤더링(오프라인 보장, Phase 30.2). CDN 미사용.
   ★W-PERF3(kai K-PERF3-C) — 서브셋(영숫자·기호 + KS 한글 2,350자)을 기본으로 싣고, 원본은 서브셋에 없는 글자
   (나머지 한글 · 드문 문자)에만 건다
   (그 글자가 화면에 나올 때만 받는다 · 두 범위 겹침 0 · 같은 family · font-display 종전 그대로). */
@font-face {
  font-family: "Pretendard Variable";
  font-weight: 45 920;
  font-style: normal;
  font-display: swap;
  src: url("/fonts/PretendardVariable-ks.woff2?v=5c6233a6521b") format("woff2-variations");
  unicode-range: U+20-7E, U+A0-FF, U+2000-200D, U+2010-2027, U+202F-2060, U+2100-2101, U+2103, U+2105-2106, U+2109, U+2113, U+2116-2117, U+211E-2123, U+2126, U+212A-212B, U+212E, U+2132, U+213B, U+214D, U+214F, U+2190-2199, U+21A9-21AA, U+21B0-21B1, U+21B3-21B5, U+21BA-21BB, U+21D0, U+21D2, U+21D4, U+21DE-21DF, U+21E4-21E5, U+21E7, U+21EA, U+2202, U+2205-2206, U+220F, U+2211-2212, U+221A, U+221E, U+222B, U+2248, U+2260, U+2264-2265, U+226A-226B, U+22EF, U+2460-2473, U+24B6-24CF, U+24EA-24F4, U+24FF, U+25A0-25A2, U+25AA, U+25B2-25B3, U+25B6-25B7, U+25BA-25BD, U+25C0-25C1, U+25C4-25C7, U+25CA-25CB, U+25CF, U+25E6, U+25EF, U+3000-3003, U+3008-3011, U+3014-301F, U+3131-3164, U+318D, U+AC00-AC01, U+AC04, U+AC07-AC0A, U+AC10-AC17, U+AC19-AC1D, U+AC20, U+AC24, U+AC2C-AC2D, U+AC2F-AC31, U+AC38-AC39, U+AC3C, U+AC40, U+AC4B, U+AC4D, U+AC54, U+AC58, U+AC5C, U+AC70-AC71, U+AC74, U+AC77-AC78, U+AC7A, U+AC80-AC81, U+AC83-AC86, U+AC89-AC8C, U+AC90, U+AC94, U+AC9C-AC9D, U+AC9F-ACA1, U+ACA8-ACAA, U+ACAC, U+ACAF-ACB0, U+ACB8-ACB9, U+ACBB-ACBD, U+ACC1, U+ACC4, U+ACC8, U+ACCC, U+ACD5, U+ACD7, U+ACE0-ACE1, U+ACE4, U+ACE7-ACE8, U+ACEA, U+ACEC, U+ACEF-ACF1, U+ACF3, U+ACF5-ACF6, U+ACFC-ACFD, U+AD00, U+AD04, U+AD06, U+AD0C-AD0D, U+AD0F, U+AD11, U+AD18, U+AD1C, U+AD20, U+AD29, U+AD2C-AD2D, U+AD34-AD35, U+AD38, U+AD3C, U+AD44-AD45, U+AD47, U+AD49, U+AD50, U+AD54, U+AD58, U+AD61, U+AD63, U+AD6C-AD6D, U+AD70, U+AD73-AD76, U+AD7B-AD7D, U+AD7F, U+AD81-AD82, U+AD88-AD89, U+AD8C, U+AD90, U+AD9C-AD9D, U+ADA4, U+ADB7, U+ADC0-ADC1, U+ADC4, U+ADC8, U+ADD0-ADD1, U+ADD3, U+ADDC, U+ADE0, U+ADE4, U+ADF8-ADF9, U+ADFC, U+ADFF-AE01, U+AE08-AE09, U+AE0B, U+AE0D, U+AE14, U+AE30-AE31, U+AE34, U+AE37-AE38, U+AE3A, U+AE40-AE41, U+AE43, U+AE45-AE46, U+AE4A, U+AE4C-AE4E, U+AE50, U+AE54, U+AE56, U+AE5C-AE5D, U+AE5F-AE61, U+AE65, U+AE68-AE69, U+AE6C, U+AE70, U+AE78-AE79, U+AE7B-AE7D, U+AE84-AE85, U+AE8C, U+AEBC-AEBE, U+AEC0, U+AEC4, U+AECC-AECD, U+AECF-AED1, U+AED8-AED9, U+AEDC, U+AEE8, U+AEEB, U+AEED, U+AEF4, U+AEF8, U+AEFC, U+AF07-AF08, U+AF0D, U+AF10, U+AF2C-AF2D, U+AF30, U+AF32, U+AF34, U+AF3C-AF3D, U+AF3F, U+AF41-AF43, U+AF48-AF49, U+AF50, U+AF5C-AF5D, U+AF64-AF65, U+AF79, U+AF80, U+AF84, U+AF88, U+AF90-AF91, U+AF95, U+AF9C, U+AFB8-AFB9, U+AFBC, U+AFC0, U+AFC7-AFC9, U+AFCB, U+AFCD-AFCE, U+AFD4, U+AFDC, U+AFE8-AFE9, U+AFF0-AFF1, U+AFF4, U+AFF8, U+B000-B001, U+B004, U+B00C, U+B010, U+B014, U+B01C-B01D, U+B028, U+B044-B045, U+B048, U+B04A, U+B04C, U+B04E, U+B053-B055, U+B057, U+B059, U+B05D, U+B07C-B07D, U+B080, U+B084, U+B08C-B08D, U+B08F, U+B091, U+B098-B09A, U+B09C, U+B09F-B0A2, U+B0A8-B0A9, U+B0AB-B0AF, U+B0B1, U+B0B3-B0B5, U+B0B8, U+B0BC, U+B0C4-B0C5, U+B0C7-B0C9, U+B0D0-B0D1, U+B0D4, U+B0D8, U+B0E0, U+B0E5, U+B108-B109, U+B10B-B10C, U+B110, U+B112-B113, U+B118-B119, U+B11B-B11D, U+B123-B125, U+B128, U+B12C, U+B134-B135, U+B137-B139, U+B140-B141, U+B144, U+B148, U+B150-B151, U+B154-B155, U+B158, U+B15C, U+B160, U+B178-B179, U+B17C, U+B180, U+B182, U+B188-B189, U+B18B, U+B18D, U+B192-B194, U+B198, U+B19C, U+B1A8, U+B1CC, U+B1D0, U+B1D4, U+B1DC-B1DD, U+B1DF, U+B1E8-B1E9, U+B1EC, U+B1F0, U+B1F9, U+B1FB, U+B1FD, U+B204-B205, U+B208, U+B20B-B20C, U+B214-B215, U+B217, U+B219, U+B220, U+B234, U+B23C, U+B258, U+B25C, U+B260, U+B268-B269, U+B274-B275, U+B27C, U+B284-B285, U+B289, U+B290-B291, U+B294, U+B298-B29A, U+B2A0-B2A1, U+B2A3, U+B2A5-B2A6, U+B2AA, U+B2AC, U+B2B0, U+B2B4, U+B2C8-B2C9, U+B2CC, U+B2D0, U+B2D2, U+B2D8-B2D9, U+B2DB, U+B2DD, U+B2E2, U+B2E4-B2E6, U+B2E8, U+B2EB-B2EF, U+B2F3-B2F5, U+B2F7-B2FB, U+B2FF-B301, U+B304, U+B308, U+B310-B311, U+B313-B315, U+B31C, U+B354-B356, U+B358, U+B35B-B35C, U+B35E-B35F, U+B364-B365, U+B367, U+B369, U+B36B, U+B36E, U+B370-B371, U+B374, U+B378, U+B380-B381, U+B383-B385, U+B38C, U+B390, U+B394, U+B3A0-B3A1, U+B3A8, U+B3AC, U+B3C4-B3C5, U+B3C8, U+B3CB-B3CC, U+B3CE, U+B3D0, U+B3D4-B3D5, U+B3D7, U+B3D9, U+B3DB, U+B3DD, U+B3E0, U+B3E4, U+B3E8, U+B3FC, U+B410, U+B418, U+B41C, U+B420, U+B428-B429, U+B42B, U+B434, U+B450-B451, U+B454, U+B458, U+B460-B461, U+B463, U+B465, U+B46C, U+B480, U+B488, U+B49D, U+B4A4, U+B4A8, U+B4AC, U+B4B5, U+B4B7, U+B4B9, U+B4C0, U+B4C4, U+B4C8, U+B4D0, U+B4D5, U+B4DC-B4DD, U+B4E0, U+B4E3-B4E4, U+B4E6, U+B4EC-B4ED, U+B4EF, U+B4F1, U+B4F8, U+B514-B515, U+B518, U+B51B-B51C, U+B524-B525, U+B527-B52A, U+B530-B531, U+B534, U+B538, U+B540-B541, U+B543-B545, U+B54B-B54D, U+B550, U+B554, U+B55C-B55D, U+B55F-B561, U+B5A0-B5A1, U+B5A4, U+B5A8, U+B5AA-B5AB, U+B5B0-B5B1, U+B5B3-B5B5, U+B5BB-B5BD, U+B5C0, U+B5C4, U+B5CC-B5CD, U+B5CF-B5D1, U+B5D8, U+B5EC, U+B610-B611, U+B614, U+B618, U+B625, U+B62C, U+B634, U+B648, U+B664, U+B668, U+B69C-B69D, U+B6A0, U+B6A4, U+B6AB-B6AC, U+B6B1, U+B6D4, U+B6F0, U+B6F4, U+B6F8, U+B700-B701, U+B705, U+B728-B729, U+B72C, U+B72F-B730, U+B738-B739, U+B73B, U+B744, U+B748, U+B74C, U+B754-B755, U+B760, U+B764, U+B768, U+B770-B771, U+B773, U+B775, U+B77C-B77D, U+B780, U+B784, U+B78C-B78D, U+B78F-B792, U+B796-B799, U+B79C, U+B7A0, U+B7A8-B7A9, U+B7AB-B7AD, U+B7B4-B7B5, U+B7B8, U+B7C7, U+B7C9, U+B7EC-B7ED, U+B7F0, U+B7F4, U+B7FC-B7FD, U+B7FF-B801, U+B807-B809, U+B80C, U+B810, U+B818-B819, U+B81B, U+B81D, U+B824-B825, U+B828, U+B82C, U+B834-B835, U+B837-B839, U+B840, U+B844, U+B851, U+B853, U+B85C-B85D, U+B860, U+B864, U+B86C-B86D, U+B86F, U+B871, U+B878, U+B87C, U+B88D, U+B8A8, U+B8B0, U+B8B4, U+B8B8, U+B8C0-B8C1, U+B8C3, U+B8C5, U+B8CC, U+B8D0, U+B8D4, U+B8DD, U+B8DF, U+B8E1, U+B8E8-B8E9, U+B8EC, U+B8F0, U+B8F8-B8F9, U+B8FB, U+B8FD, U+B904, U+B918, U+B920, U+B93C-B93D, U+B940, U+B944, U+B94C, U+B94F, U+B951, U+B958-B959, U+B95C, U+B960, U+B968-B969, U+B96B, U+B96D, U+B974-B975, U+B978, U+B97C, U+B984-B985, U+B987, U+B989-B98A, U+B98D-B98E, U+B9AC-B9AD, U+B9B0, U+B9B4, U+B9BC-B9BD, U+B9BF, U+B9C1, U+B9C8-B9C9, U+B9CC, U+B9CE-B9D2, U+B9D8-B9D9, U+B9DB, U+B9DD-B9DE, U+B9E1, U+B9E3-B9E5, U+B9E8, U+B9EC, U+B9F4-B9F5, U+B9F7-B9FA, U+BA00-BA01, U+BA08, U+BA15, U+BA38-BA39, U+BA3C, U+BA40, U+BA42, U+BA48-BA49, U+BA4B, U+BA4D-BA4E, U+BA53-BA55, U+BA58, U+BA5C, U+BA64-BA65, U+BA67-BA69, U+BA70-BA71, U+BA74, U+BA78, U+BA83-BA85, U+BA87, U+BA8C, U+BAA8-BAA9, U+BAAB-BAAC, U+BAB0, U+BAB2, U+BAB8-BAB9, U+BABB, U+BABD, U+BAC4, U+BAC8, U+BAD8-BAD9, U+BAFC, U+BB00, U+BB04, U+BB0D, U+BB0F, U+BB11, U+BB18, U+BB1C, U+BB20, U+BB29, U+BB2B, U+BB34-BB36, U+BB38, U+BB3B-BB3E, U+BB44-BB45, U+BB47, U+BB49, U+BB4D, U+BB4F-BB50, U+BB54, U+BB58, U+BB61, U+BB63, U+BB6C, U+BB88, U+BB8C, U+BB90, U+BBA4, U+BBA8, U+BBAC, U+BBB4, U+BBB7, U+BBC0, U+BBC4, U+BBC8, U+BBD0, U+BBD3, U+BBF8-BBF9, U+BBFC, U+BBFF-BC00, U+BC02, U+BC08-BC09, U+BC0B-BC0D, U+BC0F, U+BC11, U+BC14-BC18, U+BC1B-BC1F, U+BC24-BC25, U+BC27, U+BC29, U+BC2D, U+BC30-BC31, U+BC34, U+BC38, U+BC40-BC41, U+BC43-BC45, U+BC49, U+BC4C-BC4D, U+BC50, U+BC5D, U+BC84-BC85, U+BC88, U+BC8B-BC8C, U+BC8E, U+BC94-BC95, U+BC97, U+BC99-BC9A, U+BCA0-BCA1, U+BCA4, U+BCA7-BCA8, U+BCB0-BCB1, U+BCB3-BCB5, U+BCBC-BCBD, U+BCC0, U+BCC4, U+BCCD, U+BCCF-BCD1, U+BCD5, U+BCD8, U+BCDC, U+BCF4-BCF6, U+BCF8, U+BCFC, U+BD04-BD05, U+BD07, U+BD09, U+BD10, U+BD14, U+BD24, U+BD2C, U+BD40, U+BD48-BD49, U+BD4C, U+BD50, U+BD58-BD59, U+BD64, U+BD68, U+BD80-BD81, U+BD84, U+BD87-BD8A, U+BD90-BD91, U+BD93, U+BD95, U+BD99-BD9A, U+BD9C, U+BDA4, U+BDB0, U+BDB8, U+BDD4-BDD5, U+BDD8, U+BDDC, U+BDE9, U+BDF0, U+BDF4, U+BDF8, U+BE00, U+BE03, U+BE05, U+BE0C-BE0D, U+BE10, U+BE14, U+BE1C-BE1D, U+BE1F, U+BE44-BE45, U+BE48, U+BE4C, U+BE4E, U+BE54-BE55, U+BE57, U+BE59-BE5B, U+BE60-BE61, U+BE64, U+BE68, U+BE6A, U+BE70-BE71, U+BE73-BE75, U+BE7B-BE7D, U+BE80, U+BE84, U+BE8C-BE8D, U+BE8F-BE91, U+BE98-BE99, U+BEA8, U+BED0-BED1, U+BED4, U+BED7-BED8, U+BEE0, U+BEE3-BEE5, U+BEEC, U+BF01, U+BF08-BF09, U+BF18-BF19, U+BF1B-BF1D, U+BF40-BF41, U+BF44, U+BF48, U+BF50-BF51, U+BF55, U+BF94, U+BFB0, U+BFC5, U+BFCC-BFCD, U+BFD0, U+BFD4, U+BFDC, U+BFDF, U+BFE1, U+C03C, U+C051, U+C058, U+C05C, U+C060, U+C068-C069, U+C090-C091, U+C094, U+C098, U+C0A0-C0A1, U+C0A3, U+C0A5, U+C0AC-C0AD, U+C0AF-C0B0, U+C0B3-C0B6, U+C0BC-C0BD, U+C0BF-C0C1, U+C0C5, U+C0C8-C0C9, U+C0CC, U+C0D0, U+C0D8-C0D9, U+C0DB-C0DD, U+C0E4-C0E5, U+C0E8, U+C0EC, U+C0F4-C0F5, U+C0F7, U+C0F9, U+C100, U+C104, U+C108, U+C110, U+C115, U+C11C-C120, U+C123-C124, U+C126-C127, U+C12C-C12D, U+C12F-C131, U+C136, U+C138-C139, U+C13C, U+C140, U+C148-C149, U+C14B-C14D, U+C154-C155, U+C158, U+C15C, U+C164-C165, U+C167-C169, U+C170, U+C174, U+C178, U+C185, U+C18C-C18E, U+C190, U+C194, U+C196, U+C19C-C19D, U+C19F, U+C1A1, U+C1A5, U+C1A8-C1A9, U+C1AC, U+C1B0, U+C1BD, U+C1C4, U+C1C8, U+C1CC, U+C1D4, U+C1D7-C1D8, U+C1E0, U+C1E4, U+C1E8, U+C1F0-C1F1, U+C1F3, U+C1FC-C1FD, U+C200, U+C204, U+C20C-C20D, U+C20F, U+C211, U+C218-C219, U+C21C, U+C21F-C220, U+C228-C229, U+C22B, U+C22D, U+C22F, U+C231-C232, U+C234, U+C248, U+C250-C251, U+C254, U+C258, U+C260, U+C265, U+C26C-C26D, U+C270, U+C274, U+C27C-C27D, U+C27F, U+C281, U+C288-C289, U+C290, U+C298, U+C29B, U+C29D, U+C2A4-C2A5, U+C2A8, U+C2AC-C2AD, U+C2B4-C2B5, U+C2B7, U+C2B9, U+C2DC-C2DD, U+C2E0, U+C2E3-C2E4, U+C2EB-C2ED, U+C2EF, U+C2F1, U+C2F6, U+C2F8-C2F9, U+C2FB-C2FC, U+C300, U+C308-C309, U+C30C-C30D, U+C313-C315, U+C318, U+C31C, U+C324-C325, U+C328-C329, U+C345, U+C368-C369, U+C36C, U+C370, U+C372, U+C378-C379, U+C37C-C37D, U+C384, U+C388, U+C38C, U+C3C0, U+C3D8-C3D9, U+C3DC, U+C3DF-C3E0, U+C3E2, U+C3E8-C3E9, U+C3ED, U+C3F4-C3F5, U+C3F8, U+C408, U+C410, U+C424, U+C42C, U+C430, U+C434, U+C43C-C43D, U+C448, U+C464-C465, U+C468, U+C46C, U+C474-C475, U+C479, U+C480, U+C494, U+C49C, U+C4B8, U+C4BC, U+C4E9, U+C4F0-C4F1, U+C4F4, U+C4F8, U+C4FA, U+C4FF-C501, U+C50C, U+C510, U+C514, U+C51C, U+C528-C529, U+C52C, U+C530, U+C538-C539, U+C53B, U+C53D, U+C544-C545, U+C548-C54A, U+C54C-C54E, U+C553-C555, U+C557-C559, U+C55D-C55E, U+C560-C561, U+C564, U+C568, U+C570-C571, U+C573-C575, U+C57C-C57D, U+C580, U+C584, U+C587, U+C58C-C58D, U+C58F, U+C591, U+C595, U+C597-C598, U+C59C, U+C5A0, U+C5A9, U+C5B4-C5B5, U+C5B8-C5B9, U+C5BB-C5BE, U+C5C4-C5CA, U+C5CC, U+C5CE, U+C5D0-C5D1, U+C5D4, U+C5D8, U+C5E0-C5E1, U+C5E3, U+C5E5, U+C5EC-C5EE, U+C5F0, U+C5F4, U+C5F6-C5F7, U+C5FC-C601, U+C605-C608, U+C60C, U+C610, U+C618-C619, U+C61B-C61C, U+C624-C625, U+C628, U+C62C-C62E, U+C630, U+C633-C635, U+C637, U+C639, U+C63B, U+C640-C641, U+C644, U+C648, U+C650-C651, U+C653-C655, U+C65C-C65D, U+C660, U+C66C, U+C66F, U+C671, U+C678-C679, U+C67C, U+C680, U+C688-C689, U+C68B, U+C68D, U+C694-C695, U+C698, U+C69C, U+C6A4-C6A5, U+C6A7, U+C6A9, U+C6B0-C6B1, U+C6B4, U+C6B8-C6BA, U+C6C0-C6C1, U+C6C3, U+C6C5, U+C6CC-C6CD, U+C6D0, U+C6D4, U+C6DC-C6DD, U+C6E0-C6E1, U+C6E8-C6E9, U+C6EC, U+C6F0, U+C6F8-C6F9, U+C6FD, U+C704-C705, U+C708, U+C70C, U+C714-C715, U+C717, U+C719, U+C720-C721, U+C724, U+C728, U+C730-C731, U+C733, U+C735, U+C737, U+C73C-C73D, U+C740, U+C744, U+C74A, U+C74C-C74D, U+C74F, U+C751-C758, U+C75C, U+C760, U+C768, U+C76B, U+C774-C775, U+C778, U+C77C-C77E, U+C783-C785, U+C787-C78A, U+C78E, U+C790-C791, U+C794, U+C796-C798, U+C79A, U+C7A0-C7A1, U+C7A3-C7A6, U+C7AC-C7AD, U+C7B0, U+C7B4, U+C7BC-C7BD, U+C7BF-C7C1, U+C7C8-C7C9, U+C7CC, U+C7CE, U+C7D0, U+C7D8, U+C7DD, U+C7E4, U+C7E8, U+C7EC, U+C800-C801, U+C804, U+C808, U+C80A, U+C810-C811, U+C813, U+C815-C816, U+C81C-C81D, U+C820, U+C824, U+C82C-C82D, U+C82F, U+C831, U+C838, U+C83C, U+C840, U+C848-C849, U+C84C-C84D, U+C854, U+C870-C871, U+C874, U+C878, U+C87A, U+C880-C881, U+C883, U+C885-C887, U+C88B-C88D, U+C894, U+C89D, U+C89F, U+C8A1, U+C8A8, U+C8BC-C8BD, U+C8C4, U+C8C8, U+C8CC, U+C8D4-C8D5, U+C8D7, U+C8D9, U+C8E0-C8E1, U+C8E4, U+C8F5, U+C8FC-C8FD, U+C900, U+C904-C906, U+C90C-C90D, U+C90F, U+C911, U+C918, U+C92C, U+C934, U+C950-C951, U+C954, U+C958, U+C960-C961, U+C963, U+C96C, U+C970, U+C974, U+C97C, U+C988-C989, U+C98C, U+C990, U+C998-C999, U+C99B, U+C99D, U+C9C0-C9C1, U+C9C4, U+C9C7-C9C8, U+C9CA, U+C9D0-C9D1, U+C9D3, U+C9D5-C9D6, U+C9D9-C9DA, U+C9DC-C9DD, U+C9E0, U+C9E2, U+C9E4, U+C9E7, U+C9EC-C9ED, U+C9EF-C9F1, U+C9F8-C9F9, U+C9FC, U+CA00, U+CA08-CA09, U+CA0B-CA0D, U+CA14, U+CA18, U+CA29, U+CA4C-CA4D, U+CA50, U+CA54, U+CA5C-CA5D, U+CA5F-CA61, U+CA68, U+CA7D, U+CA84, U+CA98, U+CABC-CABD, U+CAC0, U+CAC4, U+CACC-CACD, U+CACF, U+CAD1, U+CAD3, U+CAD8-CAD9, U+CAE0, U+CAEC, U+CAF4, U+CB08, U+CB10, U+CB14, U+CB18, U+CB20-CB21, U+CB41, U+CB48-CB49, U+CB4C, U+CB50, U+CB58-CB59, U+CB5D, U+CB64, U+CB78-CB79, U+CB9C, U+CBB8, U+CBD4, U+CBE4, U+CBE7, U+CBE9, U+CC0C-CC0D, U+CC10, U+CC14, U+CC1C-CC1D, U+CC21-CC22, U+CC27-CC29, U+CC2C, U+CC2E, U+CC30, U+CC38-CC39, U+CC3B-CC3E, U+CC44-CC45, U+CC48, U+CC4C, U+CC54-CC55, U+CC57-CC59, U+CC60, U+CC64, U+CC66, U+CC68, U+CC70, U+CC75, U+CC98-CC99, U+CC9C, U+CCA0, U+CCA8-CCA9, U+CCAB-CCAD, U+CCB4-CCB5, U+CCB8, U+CCBC, U+CCC4-CCC5, U+CCC7, U+CCC9, U+CCD0, U+CCD4, U+CCE4, U+CCEC, U+CCF0, U+CD01, U+CD08-CD09, U+CD0C, U+CD10, U+CD18-CD19, U+CD1B, U+CD1D, U+CD24, U+CD28, U+CD2C, U+CD39, U+CD5C, U+CD60, U+CD64, U+CD6C-CD6D, U+CD6F, U+CD71, U+CD78, U+CD88, U+CD94-CD95, U+CD98, U+CD9C, U+CDA4-CDA5, U+CDA7, U+CDA9, U+CDB0, U+CDC4, U+CDCC, U+CDD0, U+CDE8, U+CDEC, U+CDF0, U+CDF8-CDF9, U+CDFB, U+CDFD, U+CE04, U+CE08, U+CE0C, U+CE14, U+CE19, U+CE20-CE21, U+CE24, U+CE28, U+CE30-CE31, U+CE33, U+CE35, U+CE58-CE59, U+CE5C, U+CE5F-CE61, U+CE68-CE69, U+CE6B, U+CE6D, U+CE74-CE75, U+CE78, U+CE7C, U+CE84-CE85, U+CE87, U+CE89, U+CE90-CE91, U+CE94, U+CE98, U+CEA0-CEA1, U+CEA3-CEA5, U+CEAC-CEAD, U+CEC1, U+CEE4-CEE5, U+CEE8, U+CEEB-CEEC, U+CEF4-CEF5, U+CEF7-CEF9, U+CF00-CF01, U+CF04, U+CF08, U+CF10-CF11, U+CF13, U+CF15, U+CF1C, U+CF20, U+CF24, U+CF2C-CF2D, U+CF2F-CF31, U+CF38, U+CF54-CF55, U+CF58, U+CF5C, U+CF64-CF65, U+CF67, U+CF69, U+CF70-CF71, U+CF74, U+CF78, U+CF80, U+CF85, U+CF8C, U+CFA1, U+CFA8, U+CFB0, U+CFC4, U+CFE0-CFE1, U+CFE4, U+CFE8, U+CFF0-CFF1, U+CFF3, U+CFF5, U+CFFC, U+D000, U+D004, U+D011, U+D018, U+D02D, U+D034-D035, U+D038, U+D03C, U+D044-D045, U+D047, U+D049, U+D050, U+D054, U+D058, U+D060, U+D06C-D06D, U+D070, U+D074, U+D07C-D07D, U+D081, U+D0A4-D0A5, U+D0A8, U+D0AC, U+D0B4-D0B5, U+D0B7, U+D0B9, U+D0C0-D0C1, U+D0C4, U+D0C8-D0C9, U+D0D0-D0D1, U+D0D3-D0D5, U+D0DC-D0DD, U+D0E0, U+D0E4, U+D0EC-D0ED, U+D0EF-D0F1, U+D0F8, U+D10D, U+D130-D131, U+D134, U+D138, U+D13A, U+D140-D141, U+D143-D145, U+D14C-D14D, U+D150, U+D154, U+D15C-D15D, U+D15F, U+D161, U+D168, U+D16C, U+D17C, U+D184, U+D188, U+D1A0-D1A1, U+D1A4, U+D1A8, U+D1B0-D1B1, U+D1B3, U+D1B5, U+D1BA, U+D1BC, U+D1C0, U+D1D8, U+D1F4, U+D1F8, U+D207, U+D209, U+D210, U+D22C-D22D, U+D230, U+D234, U+D23C-D23D, U+D23F, U+D241, U+D248, U+D25C, U+D264, U+D280-D281, U+D284, U+D288, U+D290-D291, U+D295, U+D29C, U+D2A0, U+D2A4, U+D2AC, U+D2B1, U+D2B8-D2B9, U+D2BC, U+D2BF-D2C0, U+D2C2, U+D2C8-D2C9, U+D2CB, U+D2D4, U+D2D8, U+D2DC, U+D2E4-D2E5, U+D2F0-D2F1, U+D2F4, U+D2F8, U+D300-D301, U+D303, U+D305, U+D30C-D30E, U+D310, U+D314, U+D316, U+D31C-D31D, U+D31F-D321, U+D325, U+D328-D329, U+D32C, U+D330, U+D338-D339, U+D33B-D33D, U+D344-D345, U+D37C-D37D, U+D380, U+D384, U+D38C-D38D, U+D38F-D391, U+D398-D399, U+D39C, U+D3A0, U+D3A8-D3A9, U+D3AB, U+D3AD, U+D3B4, U+D3B8, U+D3BC, U+D3C4-D3C5, U+D3C8-D3C9, U+D3D0, U+D3D8, U+D3E1, U+D3E3, U+D3EC-D3ED, U+D3F0, U+D3F4, U+D3FC-D3FD, U+D3FF, U+D401, U+D408, U+D41D, U+D440, U+D444, U+D45C, U+D460, U+D464, U+D46D, U+D46F, U+D478-D479, U+D47C, U+D47F-D480, U+D482, U+D488-D489, U+D48B, U+D48D, U+D494, U+D4A9, U+D4CC, U+D4D0, U+D4D4, U+D4DC, U+D4DF, U+D4E8, U+D4EC, U+D4F0, U+D4F8, U+D4FB, U+D4FD, U+D504, U+D508, U+D50C, U+D514-D515, U+D517, U+D53C-D53D, U+D540, U+D544, U+D54C-D54D, U+D54F, U+D551, U+D558-D559, U+D55C, U+D560, U+D565, U+D568-D569, U+D56B, U+D56D, U+D574-D575, U+D578, U+D57C, U+D584-D585, U+D587-D589, U+D590, U+D5A5, U+D5C8-D5C9, U+D5CC, U+D5D0, U+D5D2, U+D5D8-D5D9, U+D5DB, U+D5DD, U+D5E4-D5E5, U+D5E8, U+D5EC, U+D5F4-D5F5, U+D5F7, U+D5F9, U+D600-D601, U+D604, U+D608, U+D610-D611, U+D613-D615, U+D61C, U+D620, U+D624, U+D62D, U+D638-D639, U+D63C, U+D640, U+D645, U+D648-D649, U+D64B, U+D64D, U+D651, U+D654-D655, U+D658, U+D65C, U+D667, U+D669, U+D670-D671, U+D674, U+D683, U+D685, U+D68C-D68D, U+D690, U+D694, U+D69D, U+D69F, U+D6A1, U+D6A8, U+D6AC, U+D6B0, U+D6B9, U+D6BB, U+D6C4-D6C5, U+D6C8, U+D6CC, U+D6D1, U+D6D4, U+D6D7, U+D6D9, U+D6E0, U+D6E4, U+D6E8, U+D6F0, U+D6F5, U+D6FC-D6FD, U+D700, U+D704, U+D711, U+D718-D719, U+D71C, U+D720, U+D728-D729, U+D72B, U+D72D, U+D734-D735, U+D738, U+D73C, U+D744, U+D747, U+D749, U+D750-D751, U+D754, U+D756-D759, U+D760-D761, U+D763, U+D765, U+D769, U+D76C, U+D770, U+D774, U+D77C-D77D, U+D781, U+D788-D789, U+D78C, U+D790, U+D798-D799, U+D79B, U+D79D, U+FF01-FF5E;
}
@font-face {
  font-family: "Pretendard Variable";
  font-weight: 45 920;
  font-style: normal;
  font-display: swap;
  src: url("/fonts/PretendardVariable.woff2?v=9599f12fd42f") format("woff2-variations");
  unicode-range: U+100-148, U+14A-1C3, U+1C5-31E, U+321-377, U+37A-37F, U+384-38A, U+38C, U+38E-3A1, U+3A3-3E1, U+3F0-49D, U+4A0-4FF, U+52F, U+E3F, U+1D43, U+1D47-1D49, U+1D4D, U+1D4F-1D50, U+1D52, U+1D56-1D58, U+1D5B, U+1D62-1D65, U+1D9C, U+1DA0, U+1DBB, U+1DBF-1DF5, U+1DFC-1F15, U+1F18-1F1D, U+1F20-1F45, U+1F48-1F4D, U+1F50-1F57, U+1F59, U+1F5B, U+1F5D, U+1F5F-1F7D, U+1F80-1FB4, U+1FB6-1FC4, U+1FC6-1FD3, U+1FD6-1FDB, U+1FDD-1FEF, U+1FF2-1FF4, U+1FF6-1FFE, U+2070-2071, U+2074-208E, U+2090-209C, U+20A0-20BF, U+20DB-20DE, U+20E8, U+20F0, U+2153, U+215A-2188, U+2303, U+2305, U+2318, U+2325-2327, U+2329-232B, U+2380, U+2387, U+238B, U+23CE-23CF, U+2423, U+2600, U+2605-2606, U+263C, U+2661, U+2665, U+266A, U+26A0, U+2713, U+2717, U+2756, U+2776-2789, U+27EF, U+27F5-27FA, U+2985-2986, U+2B06, U+2B12-2B13, U+2B1C, U+2C7C, U+2C7F, U+2DFF, U+2E18, U+3041-3094, U+3099-309E, U+30A1-30FE, U+321C, U+3380-3384, U+3388-33CA, U+33CF-33D0, U+33D3, U+33D6, U+33D8, U+33DB-33DD, U+A69F, U+A7FF, U+A92E, U+AC02-AC03, U+AC05-AC06, U+AC0B-AC0F, U+AC18, U+AC1E-AC1F, U+AC21-AC23, U+AC25-AC2B, U+AC2E, U+AC32-AC37, U+AC3A-AC3B, U+AC3D-AC3F, U+AC41-AC4A, U+AC4C, U+AC4E-AC53, U+AC55-AC57, U+AC59-AC5B, U+AC5D-AC6F, U+AC72-AC73, U+AC75-AC76, U+AC79, U+AC7B-AC7F, U+AC82, U+AC87-AC88, U+AC8D-AC8F, U+AC91-AC93, U+AC95-AC9B, U+AC9E, U+ACA2-ACA7, U+ACAB, U+ACAD-ACAE, U+ACB1-ACB7, U+ACBA, U+ACBE-ACC0, U+ACC2-ACC3, U+ACC5-ACC7, U+ACC9-ACCB, U+ACCD-ACD4, U+ACD6, U+ACD8-ACDF, U+ACE2-ACE3, U+ACE5-ACE6, U+ACE9, U+ACEB, U+ACED-ACEE, U+ACF2, U+ACF4, U+ACF7-ACFB, U+ACFE-ACFF, U+AD01-AD03, U+AD05, U+AD07-AD0B, U+AD0E, U+AD10, U+AD12-AD17, U+AD19-AD1B, U+AD1D-AD1F, U+AD21-AD28, U+AD2A-AD2B, U+AD2E-AD33, U+AD36-AD37, U+AD39-AD3B, U+AD3D-AD43, U+AD46, U+AD48, U+AD4A-AD4F, U+AD51-AD53, U+AD55-AD57, U+AD59-AD60, U+AD62, U+AD64-AD6B, U+AD6E-AD6F, U+AD71-AD72, U+AD77-AD7A, U+AD7E, U+AD80, U+AD83-AD87, U+AD8A-AD8B, U+AD8D-AD8F, U+AD91-AD9B, U+AD9E-ADA3, U+ADA5-ADB6, U+ADB8-ADBF, U+ADC2-ADC3, U+ADC5-ADC7, U+ADC9-ADCF, U+ADD2, U+ADD4-ADDB, U+ADDD-ADDF, U+ADE1-ADE3, U+ADE5-ADF7, U+ADFA-ADFB, U+ADFD-ADFE, U+AE02-AE07, U+AE0A, U+AE0C, U+AE0E-AE13, U+AE15-AE2F, U+AE32-AE33, U+AE35-AE36, U+AE39, U+AE3B-AE3F, U+AE42, U+AE44, U+AE47-AE49, U+AE4B, U+AE4F, U+AE51-AE53, U+AE55, U+AE57-AE5B, U+AE5E, U+AE62-AE64, U+AE66-AE67, U+AE6A-AE6B, U+AE6D-AE6F, U+AE71-AE77, U+AE7A, U+AE7E-AE83, U+AE86-AE8B, U+AE8D-AEBB, U+AEBF, U+AEC1-AEC3, U+AEC5-AECB, U+AECE, U+AED2-AED7, U+AEDA-AEDB, U+AEDD-AEE7, U+AEE9-AEEA, U+AEEC, U+AEEE-AEF3, U+AEF5-AEF7, U+AEF9-AEFB, U+AEFD-AF06, U+AF09-AF0C, U+AF0E-AF0F, U+AF11-AF2B, U+AF2E-AF2F, U+AF31, U+AF33, U+AF35-AF3B, U+AF3E, U+AF40, U+AF44-AF47, U+AF4A-AF4F, U+AF51-AF5B, U+AF5E-AF63, U+AF66-AF78, U+AF7A-AF7F, U+AF81-AF83, U+AF85-AF87, U+AF89-AF8F, U+AF92-AF94, U+AF96-AF9B, U+AF9D-AFB7, U+AFBA-AFBB, U+AFBD-AFBF, U+AFC1-AFC6, U+AFCA, U+AFCC, U+AFCF-AFD3, U+AFD5-AFDB, U+AFDD-AFE7, U+AFEA-AFEF, U+AFF2-AFF3, U+AFF5-AFF7, U+AFF9-AFFF, U+B002-B003, U+B005-B00B, U+B00D-B00F, U+B011-B013, U+B015-B01B, U+B01E-B027, U+B029-B043, U+B046-B047, U+B049, U+B04B, U+B04D, U+B04F-B052, U+B056, U+B058, U+B05A-B05C, U+B05E-B07B, U+B07E-B07F, U+B081-B083, U+B085-B08B, U+B08E, U+B090, U+B092-B097, U+B09B, U+B09D-B09E, U+B0A3-B0A7, U+B0AA, U+B0B0, U+B0B2, U+B0B6-B0B7, U+B0B9-B0BB, U+B0BD-B0C3, U+B0C6, U+B0CA-B0CF, U+B0D2-B0D3, U+B0D5-B0D7, U+B0D9-B0DF, U+B0E1-B0E4, U+B0E6-B107, U+B10A, U+B10D-B10F, U+B111, U+B114-B117, U+B11A, U+B11E-B122, U+B126-B127, U+B129-B12B, U+B12D-B133, U+B136, U+B13A-B13F, U+B142-B143, U+B145-B147, U+B149-B14F, U+B152-B153, U+B156-B157, U+B159-B15B, U+B15D-B15F, U+B161-B177, U+B17A-B17B, U+B17D-B17F, U+B181, U+B183-B187, U+B18A, U+B18C, U+B18E-B191, U+B195-B197, U+B199-B19B, U+B19D-B1A7, U+B1A9-B1CB, U+B1CD-B1CF, U+B1D1-B1D3, U+B1D5-B1DB, U+B1DE, U+B1E0-B1E7, U+B1EA-B1EB, U+B1ED-B1EF, U+B1F1-B1F8, U+B1FA, U+B1FC, U+B1FE-B203, U+B206-B207, U+B209-B20A, U+B20D-B213, U+B216, U+B218, U+B21A-B21F, U+B221-B233, U+B235-B23B, U+B23D-B257, U+B259-B25B, U+B25D-B25F, U+B261-B267, U+B26A-B273, U+B276-B27B, U+B27D-B283, U+B286-B288, U+B28A-B28F, U+B292-B293, U+B295-B297, U+B29B-B29F, U+B2A2, U+B2A4, U+B2A7-B2A9, U+B2AB, U+B2AD-B2AF, U+B2B1-B2B3, U+B2B5-B2C7, U+B2CA-B2CB, U+B2CD-B2CF, U+B2D1, U+B2D3-B2D7, U+B2DA, U+B2DC, U+B2DE-B2E1, U+B2E3, U+B2E7, U+B2E9-B2EA, U+B2F0-B2F2, U+B2F6, U+B2FC-B2FE, U+B302-B303, U+B305-B307, U+B309-B30F, U+B312, U+B316-B31B, U+B31D-B353, U+B357, U+B359-B35A, U+B35D, U+B360-B363, U+B366, U+B368, U+B36A, U+B36C-B36D, U+B36F, U+B372-B373, U+B375-B377, U+B379-B37F, U+B382, U+B386-B38B, U+B38D-B38F, U+B391-B393, U+B395-B39F, U+B3A2-B3A7, U+B3A9-B3AB, U+B3AD-B3C3, U+B3C6-B3C7, U+B3C9-B3CA, U+B3CD, U+B3CF, U+B3D1-B3D3, U+B3D6, U+B3D8, U+B3DA, U+B3DC, U+B3DE-B3DF, U+B3E1-B3E3, U+B3E5-B3E7, U+B3E9-B3FB, U+B3FD-B40F, U+B411-B417, U+B419-B41B, U+B41D-B41F, U+B421-B427, U+B42A, U+B42C-B433, U+B435-B44F, U+B452-B453, U+B455-B457, U+B459-B45F, U+B462, U+B464, U+B466-B46B, U+B46D-B47F, U+B481-B487, U+B489-B49C, U+B49E-B4A3, U+B4A5-B4A7, U+B4A9-B4AB, U+B4AD-B4B4, U+B4B6, U+B4B8, U+B4BA-B4BF, U+B4C1-B4C3, U+B4C5-B4C7, U+B4C9-B4CF, U+B4D1-B4D4, U+B4D6-B4DB, U+B4DE-B4DF, U+B4E1-B4E2, U+B4E5, U+B4E7-B4EB, U+B4EE, U+B4F0, U+B4F2-B4F7, U+B4F9-B513, U+B516-B517, U+B519-B51A, U+B51D-B523, U+B526, U+B52B-B52F, U+B532-B533, U+B535-B537, U+B539-B53F, U+B542, U+B546-B54A, U+B54E-B54F, U+B551-B553, U+B555-B55B, U+B55E, U+B562-B59F, U+B5A2-B5A3, U+B5A5-B5A7, U+B5A9, U+B5AC-B5AF, U+B5B2, U+B5B6-B5BA, U+B5BE-B5BF, U+B5C1-B5C3, U+B5C5-B5CB, U+B5CE, U+B5D2-B5D7, U+B5D9-B5EB, U+B5ED-B60F, U+B612-B613, U+B615-B617, U+B619-B624, U+B626-B62B, U+B62D-B633, U+B635-B647, U+B649-B663, U+B665-B667, U+B669-B69B, U+B69E-B69F, U+B6A1-B6A3, U+B6A5-B6AA, U+B6AD-B6B0, U+B6B2-B6D3, U+B6D5-B6EF, U+B6F1-B6F3, U+B6F5-B6F7, U+B6F9-B6FF, U+B702-B704, U+B706-B727, U+B72A-B72B, U+B72D-B72E, U+B731-B737, U+B73A, U+B73C-B743, U+B745-B747, U+B749-B74B, U+B74D-B753, U+B756-B75F, U+B761-B763, U+B765-B767, U+B769-B76F, U+B772, U+B774, U+B776-B77B, U+B77E-B77F, U+B781-B783, U+B785-B78B, U+B78E, U+B793-B795, U+B79A-B79B, U+B79D-B79F, U+B7A1-B7A7, U+B7AA, U+B7AE-B7B3, U+B7B6-B7B7, U+B7B9-B7C6, U+B7C8, U+B7CA-B7EB, U+B7EE-B7EF, U+B7F1-B7F3, U+B7F5-B7FB, U+B7FE, U+B802-B806, U+B80A-B80B, U+B80D-B80F, U+B811-B817, U+B81A, U+B81C, U+B81E-B823, U+B826-B827, U+B829-B82B, U+B82D-B833, U+B836, U+B83A-B83F, U+B841-B843, U+B845-B850, U+B852, U+B854-B85B, U+B85E-B85F, U+B861-B863, U+B865-B86B, U+B86E, U+B870, U+B872-B877, U+B879-B87B, U+B87D-B88C, U+B88E-B8A7, U+B8A9-B8AF, U+B8B1-B8B3, U+B8B5-B8B7, U+B8B9-B8BF, U+B8C2, U+B8C4, U+B8C6-B8CB, U+B8CD-B8CF, U+B8D1-B8D3, U+B8D5-B8DC, U+B8DE, U+B8E0, U+B8E2-B8E7, U+B8EA-B8EB, U+B8ED-B8EF, U+B8F1-B8F7, U+B8FA, U+B8FC, U+B8FE-B903, U+B905-B917, U+B919-B91F, U+B921-B93B, U+B93E-B93F, U+B941-B943, U+B945-B94B, U+B94D-B94E, U+B950, U+B952-B957, U+B95A-B95B, U+B95D-B95F, U+B961-B967, U+B96A, U+B96C, U+B96E-B973, U+B976-B977, U+B979-B97B, U+B97D-B983, U+B986, U+B988, U+B98B-B98C, U+B98F-B9AB, U+B9AE-B9AF, U+B9B1-B9B3, U+B9B5-B9BB, U+B9BE, U+B9C0, U+B9C2-B9C7, U+B9CA-B9CB, U+B9CD, U+B9D3-B9D7, U+B9DA, U+B9DC, U+B9DF-B9E0, U+B9E2, U+B9E6-B9E7, U+B9E9-B9EB, U+B9ED-B9F3, U+B9F6, U+B9FB-B9FF, U+BA02-BA07, U+BA09-BA14, U+BA16-BA37, U+BA3A-BA3B, U+BA3D-BA3F, U+BA41, U+BA43-BA47, U+BA4A, U+BA4C, U+BA4F-BA52, U+BA56-BA57, U+BA59-BA5B, U+BA5D-BA63, U+BA66, U+BA6A-BA6F, U+BA72-BA73, U+BA75-BA77, U+BA79-BA82, U+BA86, U+BA88-BA8B, U+BA8D-BAA7, U+BAAA, U+BAAD-BAAF, U+BAB1, U+BAB3-BAB7, U+BABA, U+BABC, U+BABE-BAC3, U+BAC5-BAC7, U+BAC9-BAD7, U+BADA-BAFB, U+BAFD-BAFF, U+BB01-BB03, U+BB05-BB0C, U+BB0E, U+BB10, U+BB12-BB17, U+BB19-BB1B, U+BB1D-BB1F, U+BB21-BB28, U+BB2A, U+BB2C-BB33, U+BB37, U+BB39-BB3A, U+BB3F-BB43, U+BB46, U+BB48, U+BB4A-BB4C, U+BB4E, U+BB51-BB53, U+BB55-BB57, U+BB59-BB60, U+BB62, U+BB64-BB6B, U+BB6D-BB87, U+BB89-BB8B, U+BB8D-BB8F, U+BB91-BBA3, U+BBA5-BBA7, U+BBA9-BBAB, U+BBAD-BBB3, U+BBB5-BBB6, U+BBB8-BBBF, U+BBC1-BBC3, U+BBC5-BBC7, U+BBC9-BBCF, U+BBD1-BBD2, U+BBD4-BBF7, U+BBFA-BBFB, U+BBFD-BBFE, U+BC01, U+BC03-BC07, U+BC0A, U+BC0E, U+BC10, U+BC12-BC13, U+BC19-BC1A, U+BC20-BC23, U+BC26, U+BC28, U+BC2A-BC2C, U+BC2E-BC2F, U+BC32-BC33, U+BC35-BC37, U+BC39-BC3F, U+BC42, U+BC46-BC48, U+BC4A-BC4B, U+BC4E-BC4F, U+BC51-BC5C, U+BC5E-BC83, U+BC86-BC87, U+BC89-BC8A, U+BC8D, U+BC8F-BC93, U+BC96, U+BC98, U+BC9B-BC9F, U+BCA2-BCA3, U+BCA5-BCA6, U+BCA9-BCAF, U+BCB2, U+BCB6-BCBB, U+BCBE-BCBF, U+BCC1-BCC3, U+BCC5-BCCC, U+BCCE, U+BCD2-BCD4, U+BCD6-BCD7, U+BCD9-BCDB, U+BCDD-BCF3, U+BCF7, U+BCF9-BCFB, U+BCFD-BD03, U+BD06, U+BD08, U+BD0A-BD0F, U+BD11-BD13, U+BD15-BD23, U+BD25-BD2B, U+BD2D-BD3F, U+BD41-BD47, U+BD4A-BD4B, U+BD4D-BD4F, U+BD51-BD57, U+BD5A-BD63, U+BD65-BD67, U+BD69-BD7F, U+BD82-BD83, U+BD85-BD86, U+BD8B-BD8F, U+BD92, U+BD94, U+BD96-BD98, U+BD9B, U+BD9D-BDA3, U+BDA5-BDAF, U+BDB1-BDB7, U+BDB9-BDD3, U+BDD6-BDD7, U+BDD9-BDDB, U+BDDD-BDE8, U+BDEA-BDEF, U+BDF1-BDF3, U+BDF5-BDF7, U+BDF9-BDFF, U+BE01-BE02, U+BE04, U+BE06-BE0B, U+BE0E-BE0F, U+BE11-BE13, U+BE15-BE1B, U+BE1E, U+BE20-BE43, U+BE46-BE47, U+BE49-BE4B, U+BE4D, U+BE4F-BE53, U+BE56, U+BE58, U+BE5C-BE5F, U+BE62-BE63, U+BE65-BE67, U+BE69, U+BE6B-BE6F, U+BE72, U+BE76-BE7A, U+BE7E-BE7F, U+BE81-BE83, U+BE85-BE8B, U+BE8E, U+BE92-BE97, U+BE9A-BEA7, U+BEA9-BECF, U+BED2-BED3, U+BED5-BED6, U+BED9-BEDF, U+BEE1-BEE2, U+BEE6-BEEB, U+BEED-BF00, U+BF02-BF07, U+BF0A-BF17, U+BF1A, U+BF1E-BF3F, U+BF42-BF43, U+BF45-BF47, U+BF49-BF4F, U+BF52-BF54, U+BF56-BF93, U+BF95-BFAF, U+BFB1-BFC4, U+BFC6-BFCB, U+BFCE-BFCF, U+BFD1-BFD3, U+BFD5-BFDB, U+BFDD-BFDE, U+BFE0, U+BFE2-C03B, U+C03D-C050, U+C052-C057, U+C059-C05B, U+C05D-C05F, U+C061-C067, U+C06A-C08F, U+C092-C093, U+C095-C097, U+C099-C09F, U+C0A2, U+C0A4, U+C0A6-C0AB, U+C0AE, U+C0B1-C0B2, U+C0B7-C0BB, U+C0BE, U+C0C2-C0C4, U+C0C6-C0C7, U+C0CA-C0CB, U+C0CD-C0CF, U+C0D1-C0D7, U+C0DA, U+C0DE-C0E3, U+C0E6-C0E7, U+C0E9-C0EB, U+C0ED-C0F3, U+C0F6, U+C0F8, U+C0FA-C0FF, U+C101-C103, U+C105-C107, U+C109-C10F, U+C111-C114, U+C116-C11B, U+C121-C122, U+C125, U+C128-C12B, U+C12E, U+C132-C135, U+C137, U+C13A-C13B, U+C13D-C13F, U+C141-C147, U+C14A, U+C14E-C153, U+C156-C157, U+C159-C15B, U+C15D-C163, U+C166, U+C16A-C16F, U+C171-C173, U+C175-C177, U+C179-C184, U+C186-C18B, U+C18F, U+C191-C193, U+C195, U+C197-C19B, U+C19E, U+C1A0, U+C1A2-C1A4, U+C1A6-C1A7, U+C1AA-C1AB, U+C1AD-C1AF, U+C1B1-C1BC, U+C1BE-C1C3, U+C1C5-C1C7, U+C1C9-C1CB, U+C1CD-C1D3, U+C1D5-C1D6, U+C1D9-C1DF, U+C1E1-C1E3, U+C1E5-C1E7, U+C1E9-C1EF, U+C1F2, U+C1F4-C1FB, U+C1FE-C1FF, U+C201-C203, U+C205-C20B, U+C20E, U+C210, U+C212-C217, U+C21A-C21B, U+C21D-C21E, U+C221-C227, U+C22A, U+C22C, U+C22E, U+C230, U+C233, U+C235-C247, U+C249-C24F, U+C252-C253, U+C255-C257, U+C259-C25F, U+C261-C264, U+C266-C26B, U+C26E-C26F, U+C271-C273, U+C275-C27B, U+C27E, U+C280, U+C282-C287, U+C28A-C28F, U+C291-C297, U+C299-C29A, U+C29C, U+C29E-C2A3, U+C2A6-C2A7, U+C2A9-C2AB, U+C2AE-C2B3, U+C2B6, U+C2B8, U+C2BA-C2DB, U+C2DE-C2DF, U+C2E1-C2E2, U+C2E5-C2EA, U+C2EE, U+C2F0, U+C2F2-C2F5, U+C2F7, U+C2FA, U+C2FD-C2FF, U+C301-C307, U+C30A-C30B, U+C30E-C312, U+C316-C317, U+C319-C31B, U+C31D-C323, U+C326-C327, U+C32A-C344, U+C346-C367, U+C36A-C36B, U+C36D-C36F, U+C371, U+C373-C377, U+C37A-C37B, U+C37E-C383, U+C385-C387, U+C389-C38B, U+C38D-C3BF, U+C3C1-C3D7, U+C3DA-C3DB, U+C3DD-C3DE, U+C3E1, U+C3E3-C3E7, U+C3EA-C3EC, U+C3EE-C3F3, U+C3F6-C3F7, U+C3F9-C407, U+C409-C40F, U+C411-C423, U+C425-C42B, U+C42D-C42F, U+C431-C433, U+C435-C43B, U+C43E-C447, U+C449-C463, U+C466-C467, U+C469-C46B, U+C46D-C473, U+C476-C478, U+C47A-C47F, U+C481-C493, U+C495-C49B, U+C49D-C4B7, U+C4B9-C4BB, U+C4BD-C4E8, U+C4EA-C4EF, U+C4F2-C4F3, U+C4F5-C4F7, U+C4F9, U+C4FB-C4FE, U+C502-C50B, U+C50D-C50F, U+C511-C513, U+C515-C51B, U+C51D-C527, U+C52A-C52B, U+C52D-C52F, U+C531-C537, U+C53A, U+C53C, U+C53E-C543, U+C546-C547, U+C54B, U+C54F-C552, U+C556, U+C55A-C55C, U+C55F, U+C562-C563, U+C565-C567, U+C569-C56F, U+C572, U+C576-C57B, U+C57E-C57F, U+C581-C583, U+C585-C586, U+C588-C58B, U+C58E, U+C590, U+C592-C594, U+C596, U+C599-C59B, U+C59D-C59F, U+C5A1-C5A8, U+C5AA-C5B3, U+C5B6-C5B7, U+C5BA, U+C5BF-C5C3, U+C5CB, U+C5CD, U+C5CF, U+C5D2-C5D3, U+C5D5-C5D7, U+C5D9-C5DF, U+C5E2, U+C5E4, U+C5E6-C5EB, U+C5EF, U+C5F1-C5F3, U+C5F5, U+C5F8-C5FB, U+C602-C604, U+C609-C60B, U+C60D-C60F, U+C611-C617, U+C61A, U+C61D-C623, U+C626-C627, U+C629-C62B, U+C62F, U+C631-C632, U+C636, U+C638, U+C63A, U+C63C-C63F, U+C642-C643, U+C645-C647, U+C649-C64F, U+C652, U+C656-C65B, U+C65E-C65F, U+C661-C66B, U+C66D-C66E, U+C670, U+C672-C677, U+C67A-C67B, U+C67D-C67F, U+C681-C687, U+C68A, U+C68C, U+C68E-C693, U+C696-C697, U+C699-C69B, U+C69D-C6A3, U+C6A6, U+C6A8, U+C6AA-C6AF, U+C6B2-C6B3, U+C6B5-C6B7, U+C6BB-C6BF, U+C6C2, U+C6C4, U+C6C6-C6CB, U+C6CE-C6CF, U+C6D1-C6D3, U+C6D5-C6DB, U+C6DE-C6DF, U+C6E2-C6E7, U+C6EA-C6EB, U+C6ED-C6EF, U+C6F1-C6F7, U+C6FA-C6FC, U+C6FE-C703, U+C706-C707, U+C709-C70B, U+C70D-C713, U+C716, U+C718, U+C71A-C71F, U+C722-C723, U+C725-C727, U+C729-C72F, U+C732, U+C734, U+C736, U+C738-C73B, U+C73E-C73F, U+C741-C743, U+C745-C749, U+C74B, U+C74E, U+C750, U+C759-C75B, U+C75D-C75F, U+C761-C767, U+C769-C76A, U+C76C-C773, U+C776-C777, U+C779-C77B, U+C77F-C782, U+C786, U+C78B-C78D, U+C78F, U+C792-C793, U+C795, U+C799, U+C79B-C79F, U+C7A2, U+C7A7-C7AB, U+C7AE-C7AF, U+C7B1-C7B3, U+C7B5-C7BB, U+C7BE, U+C7C2-C7C7, U+C7CA-C7CB, U+C7CD, U+C7CF, U+C7D1-C7D7, U+C7D9-C7DC, U+C7DE-C7E3, U+C7E5-C7E7, U+C7E9-C7EB, U+C7ED-C7FF, U+C802-C803, U+C805-C807, U+C809, U+C80B-C80F, U+C812, U+C814, U+C817-C81B, U+C81E-C81F, U+C821-C823, U+C825-C82B, U+C82E, U+C830, U+C832-C837, U+C839-C83B, U+C83D-C83F, U+C841-C847, U+C84A-C84B, U+C84E-C853, U+C855-C86F, U+C872-C873, U+C875-C877, U+C879, U+C87B-C87F, U+C882, U+C884, U+C888-C88A, U+C88E-C893, U+C895-C89C, U+C89E, U+C8A0, U+C8A2-C8A7, U+C8A9-C8BB, U+C8BE-C8C3, U+C8C5-C8C7, U+C8C9-C8CB, U+C8CD-C8D3, U+C8D6, U+C8D8, U+C8DA-C8DF, U+C8E2-C8E3, U+C8E5-C8F4, U+C8F6-C8FB, U+C8FE-C8FF, U+C901-C903, U+C907-C90B, U+C90E, U+C910, U+C912-C917, U+C919-C92B, U+C92D-C933, U+C935-C94F, U+C952-C953, U+C955-C957, U+C959-C95F, U+C962, U+C964-C96B, U+C96D-C96F, U+C971-C973, U+C975-C97B, U+C97D-C987, U+C98A-C98B, U+C98D-C98F, U+C991-C997, U+C99A, U+C99C, U+C99E-C9BF, U+C9C2-C9C3, U+C9C5-C9C6, U+C9C9, U+C9CB-C9CF, U+C9D2, U+C9D4, U+C9D7-C9D8, U+C9DB, U+C9DE-C9DF, U+C9E1, U+C9E3, U+C9E5-C9E6, U+C9E8-C9EB, U+C9EE, U+C9F2-C9F7, U+C9FA-C9FB, U+C9FD-C9FF, U+CA01-CA07, U+CA0A, U+CA0E-CA13, U+CA15-CA17, U+CA19-CA28, U+CA2A-CA4B, U+CA4E-CA4F, U+CA51-CA53, U+CA55-CA5B, U+CA5E, U+CA62-CA67, U+CA69-CA7C, U+CA7E-CA83, U+CA85-CA97, U+CA99-CABB, U+CABE-CABF, U+CAC1-CAC3, U+CAC5-CACB, U+CACE, U+CAD0, U+CAD2, U+CAD4-CAD7, U+CADA-CADF, U+CAE1-CAEB, U+CAED-CAF3, U+CAF5-CB07, U+CB09-CB0F, U+CB11-CB13, U+CB15-CB17, U+CB19-CB1F, U+CB22-CB40, U+CB42-CB47, U+CB4A-CB4B, U+CB4D-CB4F, U+CB51-CB57, U+CB5A-CB5C, U+CB5E-CB63, U+CB65-CB77, U+CB7A-CB9B, U+CB9D-CBB7, U+CBB9-CBD3, U+CBD5-CBE3, U+CBE5-CBE6, U+CBE8, U+CBEA-CC0B, U+CC0E-CC0F, U+CC11-CC13, U+CC15-CC1B, U+CC1E-CC20, U+CC23-CC26, U+CC2A-CC2B, U+CC2D, U+CC2F, U+CC31-CC37, U+CC3A, U+CC3F-CC43, U+CC46-CC47, U+CC49-CC4B, U+CC4D-CC53, U+CC56, U+CC5A-CC5F, U+CC61-CC63, U+CC65, U+CC67, U+CC69-CC6F, U+CC71-CC74, U+CC76-CC97, U+CC9A-CC9B, U+CC9D-CC9F, U+CCA1-CCA7, U+CCAA, U+CCAE-CCB3, U+CCB6-CCB7, U+CCB9-CCBB, U+CCBD-CCC3, U+CCC6, U+CCC8, U+CCCA-CCCF, U+CCD1-CCD3, U+CCD5-CCE3, U+CCE5-CCEB, U+CCED-CCEF, U+CCF1-CD00, U+CD02-CD07, U+CD0A-CD0B, U+CD0D-CD0F, U+CD11-CD17, U+CD1A, U+CD1C, U+CD1E-CD23, U+CD25-CD27, U+CD29-CD2B, U+CD2D-CD38, U+CD3A-CD5B, U+CD5D-CD5F, U+CD61-CD63, U+CD65-CD6B, U+CD6E, U+CD70, U+CD72-CD77, U+CD79-CD87, U+CD89-CD93, U+CD96-CD97, U+CD99-CD9B, U+CD9D-CDA3, U+CDA6, U+CDA8, U+CDAA-CDAF, U+CDB1-CDC3, U+CDC5-CDCB, U+CDCD-CDCF, U+CDD1-CDE7, U+CDE9-CDEB, U+CDED-CDEF, U+CDF1-CDF7, U+CDFA, U+CDFC, U+CDFE-CE03, U+CE05-CE07, U+CE09-CE0B, U+CE0D-CE13, U+CE15-CE18, U+CE1A-CE1F, U+CE22-CE23, U+CE25-CE27, U+CE29-CE2F, U+CE32, U+CE34, U+CE36-CE57, U+CE5A-CE5B, U+CE5D-CE5E, U+CE62-CE67, U+CE6A, U+CE6C, U+CE6E-CE73, U+CE76-CE77, U+CE79-CE7B, U+CE7D-CE83, U+CE86, U+CE88, U+CE8A-CE8F, U+CE92-CE93, U+CE95-CE97, U+CE99-CE9F, U+CEA2, U+CEA6-CEAB, U+CEAE-CEC0, U+CEC2-CEE3, U+CEE6-CEE7, U+CEE9-CEEA, U+CEED-CEF3, U+CEF6, U+CEFA-CEFF, U+CF02-CF03, U+CF05-CF07, U+CF09-CF0F, U+CF12, U+CF14, U+CF16-CF1B, U+CF1D-CF1F, U+CF21-CF23, U+CF25-CF2B, U+CF2E, U+CF32-CF37, U+CF39-CF53, U+CF56-CF57, U+CF59-CF5B, U+CF5D-CF63, U+CF66, U+CF68, U+CF6A-CF6F, U+CF72-CF73, U+CF75-CF77, U+CF79-CF7F, U+CF81-CF84, U+CF86-CF8B, U+CF8D-CFA0, U+CFA2-CFA7, U+CFA9-CFAF, U+CFB1-CFC3, U+CFC5-CFDF, U+CFE2-CFE3, U+CFE5-CFE7, U+CFE9-CFEF, U+CFF2, U+CFF4, U+CFF6-CFFB, U+CFFD-CFFF, U+D001-D003, U+D005-D010, U+D012-D017, U+D019-D02C, U+D02E-D033, U+D036-D037, U+D039-D03B, U+D03D-D043, U+D046, U+D048, U+D04A-D04F, U+D051-D053, U+D055-D057, U+D059-D05F, U+D061-D06B, U+D06E-D06F, U+D071-D073, U+D075-D07B, U+D07E-D080, U+D082-D0A3, U+D0A6-D0A7, U+D0A9-D0AB, U+D0AD-D0B3, U+D0B6, U+D0B8, U+D0BA-D0BF, U+D0C2-D0C3, U+D0C5-D0C7, U+D0CA-D0CF, U+D0D2, U+D0D6-D0DB, U+D0DE-D0DF, U+D0E1-D0E3, U+D0E5-D0EB, U+D0EE, U+D0F2-D0F7, U+D0F9-D10C, U+D10E-D12F, U+D132-D133, U+D135-D137, U+D139, U+D13B-D13F, U+D142, U+D146-D14B, U+D14E-D14F, U+D151-D153, U+D155-D15B, U+D15E, U+D160, U+D162-D167, U+D169-D16B, U+D16D-D17B, U+D17D-D183, U+D185-D187, U+D189-D19F, U+D1A2-D1A3, U+D1A5-D1A7, U+D1A9-D1AF, U+D1B2, U+D1B4, U+D1B6-D1B9, U+D1BB, U+D1BD-D1BF, U+D1C1-D1D7, U+D1D9-D1F3, U+D1F5-D1F7, U+D1F9-D206, U+D208, U+D20A-D20F, U+D211-D22B, U+D22E-D22F, U+D231-D233, U+D235-D23B, U+D23E, U+D240, U+D242-D247, U+D249-D25B, U+D25D-D263, U+D265-D27F, U+D282-D283, U+D285-D287, U+D289-D28F, U+D292-D294, U+D296-D29B, U+D29D-D29F, U+D2A1-D2A3, U+D2A5-D2AB, U+D2AD-D2B0, U+D2B2-D2B7, U+D2BA-D2BB, U+D2BD-D2BE, U+D2C1, U+D2C3-D2C7, U+D2CA, U+D2CC-D2D3, U+D2D5-D2D7, U+D2D9-D2DB, U+D2DD-D2E3, U+D2E6-D2EF, U+D2F2-D2F3, U+D2F5-D2F7, U+D2F9-D2FF, U+D302, U+D304, U+D306-D30B, U+D30F, U+D311-D313, U+D315, U+D317-D31B, U+D31E, U+D322-D324, U+D326-D327, U+D32A-D32B, U+D32D-D32F, U+D331-D337, U+D33A, U+D33E-D343, U+D346-D37B, U+D37E-D37F, U+D381-D383, U+D385-D38B, U+D38E, U+D392-D397, U+D39A-D39B, U+D39D-D39F, U+D3A1-D3A7, U+D3AA, U+D3AC, U+D3AE-D3B3, U+D3B5-D3B7, U+D3B9-D3BB, U+D3BD-D3C3, U+D3C6-D3C7, U+D3CA-D3CF, U+D3D1-D3D7, U+D3D9-D3E0, U+D3E2, U+D3E4-D3EB, U+D3EE-D3EF, U+D3F1-D3F3, U+D3F5-D3FB, U+D3FE, U+D400, U+D402-D407, U+D409-D41C, U+D41E-D43F, U+D441-D443, U+D445-D45B, U+D45D-D45F, U+D461-D463, U+D465-D46C, U+D46E, U+D470-D477, U+D47A-D47B, U+D47D-D47E, U+D481, U+D483-D487, U+D48A, U+D48C, U+D48E-D493, U+D495-D4A8, U+D4AA-D4CB, U+D4CD-D4CF, U+D4D1-D4D3, U+D4D5-D4DB, U+D4DD-D4DE, U+D4E0-D4E7, U+D4E9-D4EB, U+D4ED-D4EF, U+D4F1-D4F7, U+D4F9-D4FA, U+D4FC, U+D4FE-D503, U+D505-D507, U+D509-D50B, U+D50D-D513, U+D516, U+D518-D53B, U+D53E-D53F, U+D541-D543, U+D545-D54B, U+D54E, U+D550, U+D552-D557, U+D55A-D55B, U+D55D-D55F, U+D561-D564, U+D566-D567, U+D56A, U+D56C, U+D56E-D573, U+D576-D577, U+D579-D57B, U+D57D-D583, U+D586, U+D58A-D58F, U+D591-D5A4, U+D5A6-D5C7, U+D5CA-D5CB, U+D5CD-D5CF, U+D5D1, U+D5D3-D5D7, U+D5DA, U+D5DC, U+D5DE-D5E3, U+D5E6-D5E7, U+D5E9-D5EB, U+D5ED-D5F3, U+D5F6, U+D5F8, U+D5FA-D5FF, U+D602-D603, U+D605-D607, U+D609-D60F, U+D612, U+D616-D61B, U+D61D-D61F, U+D621-D623, U+D625-D62C, U+D62E-D637, U+D63A-D63B, U+D63D-D63F, U+D641-D644, U+D646-D647, U+D64A, U+D64C, U+D64E-D650, U+D652-D653, U+D656-D657, U+D659-D65B, U+D65D-D666, U+D668, U+D66A-D66F, U+D672-D673, U+D675-D682, U+D684, U+D686-D68B, U+D68E-D68F, U+D691-D693, U+D695-D69C, U+D69E, U+D6A0, U+D6A2-D6A7, U+D6A9-D6AB, U+D6AD-D6AF, U+D6B1-D6B8, U+D6BA, U+D6BC-D6C3, U+D6C6-D6C7, U+D6C9-D6CB, U+D6CD-D6D0, U+D6D2-D6D3, U+D6D5-D6D6, U+D6D8, U+D6DA-D6DF, U+D6E1-D6E3, U+D6E5-D6E7, U+D6E9-D6EF, U+D6F1-D6F4, U+D6F6-D6FB, U+D6FE-D6FF, U+D701-D703, U+D705-D710, U+D712-D717, U+D71A-D71B, U+D71D-D71F, U+D721-D727, U+D72A, U+D72C, U+D72E-D733, U+D736-D737, U+D739-D73B, U+D73D-D743, U+D745-D746, U+D748, U+D74A-D74F, U+D752-D753, U+D755, U+D75A-D75F, U+D762, U+D764, U+D766-D768, U+D76A-D76B, U+D76D-D76F, U+D771-D773, U+D775-D77B, U+D77E-D780, U+D782-D787, U+D78A-D78B, U+D78D-D78F, U+D791-D797, U+D79A, U+D79C, U+D79E-D7A3, U+E000, U+E002-E05E, U+E06A-E080, U+E093-E096, U+E0A5-E0E6, U+E0F3-E11C, U+E11E-E12A, U+E131-E147, U+E14E-E164, U+EE01-EE05, U+F000-F057, U+F6C3, U+FE20-FE2D, U+FEFF, U+FF5F-FF60, U+FFA1-FFBE, U+FFC2-FFC7, U+FFCA-FFCF, U+FFD2-FFD7, U+FFDA-FFDC, U+FFE0-FFE1, U+FFE5-FFE6, U+1F10B, U+1F12F-1F149, U+1F150-1F16B, U+1F170-1F189, U+1F850, U+1F852, U+F0000-F0002;
}
/* ★W-PERF3 font-face END */

/* ══════════════════════════════════════════════════════════════════════
   ★★★W-UIX13-A(2026-09-10 · 사장님 "계속 진행") — **표면 토큰 정본**
   (구성안 `docs/PRODUCT_PLAN_WORKROOM_UI.html` §7 · 목업을 브라우저로 보고 옮겨 적었다).

   ★★§0 교정 하나 — **이 제품의 라이트/다크는 전역 두 모드가 아니다.** `theme.js` 가
     사용자가 고른 **섹션 배경색**에서 잉크·보조·강조·패널을 파생해 **섹션마다** 덮어쓴다
     (좌측/중앙/우측이 서로 다른 테마일 수 있다 — 구성안의 두 모드 팔레트에는 없는 축이다).
     ⇒ 구성안의 **뜻**(잉크 2단계·캡션·강조 하나·상태 셋·크루 링 열·그림자 한 단계)을 그대로
     가져오되, **테마를 따라야 하는 것**(잉크·보조·표면·강조)은 이미 있는 섹션 토큰
     (`--text`·`--muted`·`--panel`·`--accent`)에 맡기고, 여기에는 **테마와 무관한 상수**만 둔다.
     그림자·캡션처럼 밝기에 따라 값이 갈리는 둘은 `theme.js` 가 섹션마다 함께 내려 준다
     (`--wk-shadow`·`--wk-shadow-live`·`--wk-caption` — 그것이 이 제품에서 "라이트/다크 둘 다"의
     진짜 모양이다). ★커스텀 속성에 `var()` 를 담아 두지 않는다(W-UIX8 이 값을 치른 함정).
   ══════════════════════════════════════════════════════════════════════ */
:root {
  /* 크루 링 열 색 — 분야 하나에 색 하나(얼굴은 이 링으로 분야를 말한다 · §4). */
  --c-amber:  #F2B84B;
  --c-indigo: #5B6CF0;
  --c-orange: #F28C3B;
  --c-teal:   #2FB8A6;
  --c-blue:   #4C8DFF;
  --c-rose:   #F06A8A;
  --c-violet: #8A6CF0;
  --c-lime:   #7CC44A;
  --c-brown:  #B08968;
  --c-slate:  #7A8394;
  /* 상태 — 라이브 하나만 새 색이다(실패·대기는 기존 --danger·--muted 를 쓴다). */
  --wk-live: #17A34A;
  /* 그림자 **한 단계**(테두리를 대신한다) · 라이브는 초록 글로우 한 겹.
     ★밝은 섹션 기준값이고, 어두운 섹션에서는 theme.js 가 더 깊은 값으로 덮는다. */
  --wk-shadow: 0 1px 2px rgba(23,27,34,.05), 0 6px 18px rgba(23,27,34,.06);
  /* ★W-UIX14-F6 ② — **위로도 지는 그림자**(바닥에 붙어 뜨는 것: 답변 시트).
     같은 한 단계인데 방향만 하나 더 는다 — 선을 안 쓰기로 했으면 위쪽 경계도
     그림자가 말해야 한다(값을 규칙에 박으면 다크가 안 따라온다). */
  --wk-shadow-up: 0 -6px 18px rgba(23,27,34,.07), 0 1px 2px rgba(23,27,34,.05);
  --wk-shadow-live: 0 0 0 4px rgba(23,163,74,.10), 0 8px 22px rgba(23,163,74,.14);
  /* 캡션(푸른 기 회색) — 밝은 섹션 기준값(어두운 섹션은 theme.js 가 덮는다). */
  --wk-caption: #7A8394;
  /* 서피스 — 카드 솔리드 배경. ★★W-UIX14-S1: 여기에 **값을 두지 않는다**.
     `theme.js` 가 섹션 배경에서 파생해 섹션마다 내려 주고(`--wk-shadow` 와 같은 결),
     :root 에 정적값이 남아 있으면 섹션이 걷힌 순간 **다크 패널 위에 흰 카드**가 선다
     (§0-3 에서 부분 저장 상태로 실측했다). 쓰는 자리의 `var(--surface, #FFFFFF)` 폴백이
     theme.js 가 아직 안 돈 첫 페인트의 라이트 기본값을 맡는다. */
  /* 둥글기 — 같은 종류는 같은 값(카드/칩/타일/입력창). */
  --r-card: 12px;
  --r-chip: 999px;
  --r-tile: 10px;
  --r-input: 12px;
  /* 간격 다섯 · 글자 크기 다섯 · 굵기 셋 */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;  --sp-4: 16px;  --sp-5: 24px;
  --fs-cap: 12px; --fs-meta: 13px; --fs-body: 14px; --fs-ti: 15px; --fs-head: 18px;
  --fw-1: 400; --fw-2: 500; --fw-3: 600;
  /* 글꼴 한 쌍 — IBM Plex Sans KR / Plex Mono(로컬·시스템 폴백 · 웹폰트가 못 오면 종전 그대로). */
  --font-sans: "IBM Plex Sans KR", "Pretendard Variable", Pretendard, -apple-system,
    BlinkMacSystemFont, system-ui, "Malgun Gothic", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* ★★W-UIX13-A2 — **얼굴·상태 표정 전용** 이모지 글꼴(본문 이모지는 이 토큰을 안 쓴다).
     윈도우 기본 벌(Segoe UI Emoji)이 납작해 표정이 기호처럼 보이던 자리다. */
  --font-emoji: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
}

:root {
  --bg: #0f172a;
  --panel: #1e293b;
  --panel-2: #273449;
  --text: #e2e8f0;
  --muted: #94a3b8;
  --accent: #38bdf8;
  --accent-2: #22d3ee;
  --border: #334155;
  --error: #f87171;
  --ok: #34d399;
  /* ★86.5(사장님 지시) — 좌측 트리 **항목**의 글자·아이콘 크기. 기준은 [내 업무] 리스트 항목이다.
     ★값을 베껴 쓰지 않고 변수로 둔 이유: 메일 LNB 를 13.5px 로 **하드코딩하면** 다음에 내 업무가
     바뀔 때 다시 어긋난다. 출처가 하나면 한 곳만 고치면 된다(오늘 반복한 원칙). */
  --lnb-item-fs: 13.5px;
  --lnb-item-ic: 16px;
  /* 강조색(마감임박/지연) — 섹션 테마가 밝은 배경이면 theme.js 가 어둡게 덮어쓴다 */
  --soon: #fbbf24;
  --danger: #f87171;
  /* ===== Phase 30.3 글래스모피즘/프리미엄 디테일 =====
     다크 기본값. theme.js 가 밝은 섹션 진입 시 --glass-bg/--hairline 을 라이트용으로 덮어쓴다
     (하얀 바탕에 텍스트 묻힘 방지 — WCAG 대비 사수). */
  --glass-bg: rgba(30, 41, 59, 0.72);
  --glass-blur: 16px;
  --radius: 14px;      /* 표준 라운드(12~16 중앙값) */
  --hairline: rgba(255, 255, 255, 0.08);

  /* ═══ 구간 1-③ — **폼 스타일 토큰**(사장님 요건 ⑤ "네모반듯·클래식 탈피") ═══
     ★★새 토큰을 **신설**한다: 기존 토큰(--radius 등)을 고치면 **전 화면이 함께 바뀐다**.
     이번 범위는 *"이 폼부터"* 이고 기존 화면은 무접촉이어야 하므로, 이름을 갈라 두고
     `.fx-form` **아래에서만** 쓴다(그것이 무접촉을 검사로 증명할 수 있는 유일한 모양).
     ★여기(:root)에는 **색이 아닌 것만** 둔다 — 이유는 바로 아래 `.fx-form` 주석에 있다. */
  --fx-radius: 12px;          /* 필드·카드 라운드(클래식 각진 모서리 탈피) */
  --fx-pill: 999px;           /* 필 버튼 */
  --fx-gap: 9px;
  --fx-pad: 11px;
  --fx-fs: 12.5px;            /* 폼 글자 — 화면보다 한 단계 작게(밀도) */
  --fx-fs-sm: 11.5px;
  /* ★★★2026-08-13 ④(사장님) — **격자 표의 행 키**. 매각 리스트(묶음 표)와 [공제표준값]
     탭의 표 둘이 **같은 키**로 서야 한다는 지시라, 숫자를 **한 곳**에만 둔다(두 곳에 적으면
     언젠가 한쪽만 고쳐진다 — 이 프로젝트가 여러 번 치른 값이다).
     ★값의 출처는 실측이다: 묶음 표 행이 **24.18px**(글자 셀 padding 3px + 줄상자 18.18)
     이었고, [공제표준값]·[잇기] 표는 **19.63px** 이었다(그쪽 글자 셀은 padding 0).
     ★**패딩으로 맞추지 않았다** — 패딩을 주면 25.63px 이 되고 **입력이 셀을 못 채워**
     (99% → 89%) 격자 낯("셀 = 입력")이 깨진다. 그래서 **행 키**로 맞춘다(실측으로 갈랐다).
     ★25px 인 이유: 셋 중 가장 큰 자연 높이(24.18)보다 커야 **셋 다 이 값으로** 선다.
     묶음 표는 24.18 → 25 로 **0.82px** 커진다(눈에 안 띄는 대신 세 표가 정확히 같아진다). */
  --fx-row-h: 25px;
  --fx-shadow: 0 1px 2px rgba(0,0,0,.06);
  /* ★★★2026-08-07(사장님 신고 ①②) — 하단 답변 시트 **상한의 유일한 원천**(vh 숫자).
     ★CSS(`max-height`)와 JS(드래그 상한)가 **이 값 하나**를 읽는다 — 둘이 갈리면 그 사이가
     **죽은 구간**이 되어 끌어도 안 움직이다 뚝 떨어진다(실측으로 그 사고를 확인했다).
     ★값 50 → **75**(사장님 지시 +50%). 그리드가 위에 남는다는 이 축의 전제는 그대로다. */
  --ais-max-vh: 75;
  /* ★③④ — 답변 시트 안 말풍선(질문·답변)의 글자·여백. 화면 기본(16px)보다 **한 단계** 작게
     해 같은 높이에 더 담는다(가독은 유지 · 과하게 줄이지 않는다). 라이트/다크 공통(크기값). */
  --msg-fs: 14.5px;
  --msg-pad-y: 9px;
  --msg-pad-x: 13px;
}

/* ═══ .fx-form — 이 스코프 **안에서만** 위 토큰을 쓴다(기존 셀렉터 무접촉) ═══
   ★★★**색 파생 토큰은 `:root` 에 두면 안 된다**(2026-08-05 실기기 결함 · 사장님 지적).
   커스텀 속성의 `var()` 는 **선언된 그 요소에서** 계산돼 값으로 굳은 뒤 자식에게 상속된다.
   초판은 `:root` 에 `--fx-field-bg: color-mix(… var(--panel-2) …)` 로 두었는데, 그러면
   `--panel-2` 가 **`:root` 의 다크 기본값(#273449)** 으로 먼저 굳는다. `theme.js` 는 그 값을
   **`#canvas` 에 인라인으로** 덮지만 그때는 이미 계산이 끝난 뒤라 **라이트 테마인데 입력칸만
   어두운 회색**으로 남았다 — *"설정만 하고 배선 안 하면 죽은 값"* 의 색 버전이다.
   → 파생을 **여기(사용하는 자리)** 로 내린다. 그러면 `var(--panel-2)` 가 이 요소가 **상속받은**
   값(=캔버스 테마)으로 풀려 라이트/다크 양쪽에서 맞는다. */
.fx-form {
  --fx-field-bg: color-mix(in srgb, var(--panel) 88%, var(--text) 4%);
  --fx-field-bd: color-mix(in srgb, var(--border) 90%, transparent);
  --fx-focus: color-mix(in srgb, var(--accent) 35%, transparent);
  display: flex; flex-direction: column; gap: var(--fx-gap);
  font-size: var(--fx-fs);
}
/* ★★★2026-08-05 — `:not(:where(.fx-grid *))` 로 **격자 안에는 닿지 않게** 한다.
   ★이것이 알약 잔존의 진짜 뿌리였다: 이 규칙은 `:not()` 이 둘이라 특이도 **(0,3,1)** 인데
   격자 규칙 `.fx-form .pq-grid td input` 은 **(0,2,2)** 라 **클래스 열(3>2)에서 이 규칙이
   이겼다** — 격자 규칙을 v347 에 쓴 뒤에도 셀 안 `input` 은 줄곧 알약이었다.
   ★`:where()` 는 특이도가 **0** 이라, 이 한정을 붙여도 이 규칙의 힘은 종전 그대로다
   (기존 화면 무접촉) — **닿는 범위만** 줄어든다. 특이도로 싸워 이기는 대신
   **겹치지 않게 가르는 것**이 다음 사람이 안 넘어지는 모양이다.
   ★★셋을 `:is()` 로 묶지 **않는다**: `:is()` 는 인자 중 **가장 센 것**의 특이도를 갖는다
   → `select`·`textarea` 가 (0,1,1) 에서 `input` 쪽 (0,3,1) 로 **딸려 올라가** 이 폼 밖
   기존 규칙(예: `.lst-box textarea` 의 글자 크기)을 조용히 덮는다. 줄을 갈라 둔다. */
.fx-form input:not([type="file"]):not([type="checkbox"]):not(:where(.fx-grid *)),
.fx-form select:not(:where(.fx-grid *)),
.fx-form textarea:not(:where(.fx-grid *)) {
  border-radius: var(--fx-radius);
  border: 1px solid var(--fx-field-bd);
  background: var(--fx-field-bg);
  color: var(--text);
  padding: 6px 9px;
  font-size: var(--fx-fs);
  box-shadow: var(--fx-shadow);
  transition: border-color .15s ease, box-shadow .15s ease;
}
/* ★포커스 테두리도 같이 가른다 — 격자 안은 **안쪽 띠**(아래 `.fx-grid` 규칙)로 표시한다.
   바깥 링을 셀 안에서 그리면 옆 칸 격자선을 덮어 표가 어긋나 보인다. */
.fx-form input:not(:where(.fx-grid *)):focus,
.fx-form select:not(:where(.fx-grid *)):focus,
.fx-form textarea:not(:where(.fx-grid *)):focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--fx-focus);
}
.fx-form button {
  border-radius: var(--fx-pill);
  border: 1px solid var(--fx-field-bd);
  background: transparent;
  color: var(--text);
  padding: 5px 12px;
  font-size: var(--fx-fs);
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.fx-form button:hover { border-color: var(--accent); }
/* ★주 동작(저장)만 채운다 — 여러 개를 채우면 무엇이 주된 일인지 사라진다. */
.fx-form button.ledger-new { background: var(--accent); border-color: transparent; color: #fff; }
/* ★★2026-08-05 **상시 규율**(사장님: *"왜 자꾸 클래식 버튼을 쓰는지 — 디자인 일관성"*) —
   `.fx-form` 은 **스코프 클래스**라 그 밖(중앙 목록·툴바)에는 안 닿는다. 그래서 스코프 밖에서도
   같은 모양을 쓸 수 있는 **홑 버튼 토큰**을 둔다. 이제 손대는 버튼은 셋 중 하나다:
   `.fx-form` 안 · `.fx-btn`(스코프 밖 단독) · `.pq-chip`(행 안 가벼운 동작).
   ★★색 변수는 **선언한 요소에서 굳는다** — 그래서 `--fx-btn-bd` 를 `:root` 가 아니라
   **`.fx-btn` 자신**에 둔다(v344 에서 배운 그 함정 · 위 `.fx-form` 주석과 같은 이유). */
.fx-btn {
  --fx-btn-bd: color-mix(in srgb, var(--border) 90%, transparent);
  border-radius: var(--fx-pill); border: 1px solid var(--fx-btn-bd);
  background: transparent; color: var(--text);
  padding: 5px 12px; font-size: var(--fx-fs); font-weight: 600; cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.fx-btn:hover { border-color: var(--accent); }
/* ★주 동작만 채운다 — 여러 개를 채우면 무엇이 주된 일인지 사라진다(위와 같은 규율). */
.fx-btn.fx-go { background: var(--accent); border-color: transparent; color: #fff; }
.fx-btn.fx-danger { color: var(--danger, #f87171); }
.fx-btn.fx-danger:hover { border-color: var(--danger, #f87171); }
.fx-btn:disabled { opacity: .45; cursor: default; }
/* ══ ★★2026-08-18 T3-a(사장님 §7-A ② · 결재 D7) — **홑 필드 토큰 `.fx-input`** ══
   `.fx-btn` 이 버튼에 대해 한 일을 **필드**에 대해 한다. fx 필드 규칙은 전부 `.fx-form`
   **스코프 안에만** 살아서, 스코프 밖 화면이 `fx-input` 을 달고도 **브라우저 기본**으로
   렌더됐다 — 클래스는 있는데 규칙이 없는 **유령**이었다("있다≠닿는다"의 CSS 판).
   ★실측(크롬 `getComputedStyle`): `border 2px inset #767676 · radius 0 · bg #fff · pad 1/2`
     — 다크 캔버스 위의 **흰 각진 상자**. 플래너 [할 일] 탭 2칸 + 시세 대조표 3칸이 그랬다.
   ★`app.html:1794` 가 한 번 발견해 **뗐던** 클래스를 T1-b 가 다시 붙였다. 두 번 밟은 자리라
     이번엔 **떼지 않고 세운다** — 스코프 밖에서 쓸 부품이 없는 것이 진짜 원인이었다.
   ★★색 파생은 `:root` 가 아니라 **여기(쓰는 자리)** 에 둔다: `var()` 는 **선언된 요소에서**
     계산돼 값으로 굳으므로, `:root` 에 두면 `--panel` 이 다크 기본값으로 먼저 굳어
     **라이트 테마인데 입력칸만 어둡게** 남는다(v344 함정 · 위 `.fx-form` 주석과 같은 이유).
   ★선언은 `.fx-form` 필드 규칙과 **한 글자도 다르지 않게** 맞춘다 — 두 벌이 되면 같은 폼이
     스코프 안팎에서 다르게 보인다. (특이도 (0,1,0) 이라 `.fx-form`·`.fx-grid` 안에서는
     기존 규칙이 그대로 이긴다 — 안쪽 화면 무접촉.)
   ★달력은 **네이티브 `<input type="date">` 그대로**다(결재 D7). 자체 위젯을 만들지 않는다 —
     앱 전체 날짜 입력 8곳이 전부 네이티브고, 매입 견적의 fx 날짜칸이 그 관례의 실물이다. */
.fx-input {
  --fx-field-bg: color-mix(in srgb, var(--panel) 88%, var(--text) 4%);
  --fx-field-bd: color-mix(in srgb, var(--border) 90%, transparent);
  --fx-focus: color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: var(--fx-radius);
  border: 1px solid var(--fx-field-bd);
  background: var(--fx-field-bg);
  color: var(--text);
  padding: 6px 9px;
  font-size: var(--fx-fs);
  box-shadow: var(--fx-shadow);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.fx-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--fx-focus);
}
/* ★**체크박스 관례는 없었다** — 실측: 앱 전체에 `accent-color` **0회**, 살아 있는 체크박스
   31개가 전부 브라우저 기본색이다(`.set-check` 규칙은 쓰는 마크업이 없는 **죽은 CSS**였다).
   필드가 fx 인데 체크만 회색이면 한 칸 안에 두 벌이 산다.
   ★네이티브를 **대체하지 않는다**: 직접 그리면 키보드 포커스·스페이스 토글·스크린리더
     상태를 우리가 다시 만들어야 한다. `accent-color` 한 줄로 강조색만 맞춘다.
   ★`flex` 는 flex 부모 안에서만 뜻이 있고 밖에서는 무시된다 — 어디에 붙여도 안전하다. */
.fx-check {
  width: 16px; height: 16px; flex: 0 0 auto; cursor: pointer;
  accent-color: var(--accent);
}
/* ★★2026-08-05 구간 1-④ S2 — **fx 배지**(메뉴 알림·행 상태). 모양은 메일 배지 선례를 잇되
   이름을 fx 식구로 둔다 — 새로 다는 표시는 전부 fx 다(사장님 상시 규율).
   ★★색은 **선언한 여기서** 파생한다(`:root` 금지 — v344 에서 값을 치른 그 함정).
   ★`.fx-badge-done` = 다 끝난 것(초록 계열) · 기본 = 아직 하실 일이 남은 것(강조색). */
.fx-badge {
  --fx-badge-bg: var(--accent, #3b82f6);
  margin-left: 6px; padding: 1px 7px; border-radius: var(--fx-pill);
  font-size: 11px; font-weight: 700; line-height: 1.5;
  background: var(--fx-badge-bg); color: #fff; white-space: nowrap; }
.fx-badge.hidden { display: none; }
.fx-badge-done { --fx-badge-bg: var(--ok, #16a34a); }
/* ★목록 행 안에서는 글자 옆에 붙는다(칸 폭을 밀지 않게 여백만 줄인다). */
.ledger-table .fx-badge { margin-left: 4px; }
/* ═══ ★구간 1-⑤ (b)안 — 차수 목록의 진행 막대 · 작업표 스크롤 ═══
   ★막대는 **배지가 말한 수를 그림으로 되풀이**할 뿐이다(새 숫자 0) — 한눈에 어디까지
   왔는지만 보이면 된다. 숫자는 배지가 말한다. */
.fx-prog { display: inline-block; width: 72px; height: 5px; margin-left: 6px;
  border-radius: var(--fx-pill); overflow: hidden; vertical-align: middle;
  background: color-mix(in srgb, var(--border) 70%, transparent); }
.fx-prog i { display: block; height: 100%; background: var(--accent); transition: width .2s ease; }
.as-batches.hidden { display: none; }
/* ★구간 1-⑤ — 작성자 공제 표(견적 폼 안). 46줄이 넘어가므로 **자기 안에서** 스크롤한다. */
.fx-form .pqd-scroll { max-height: 46vh; overflow: auto; }
.pq-ded.hidden, .pqd-body.hidden { display: none; }
/* ★불량 상태는 **읽는 칸**이다 — 입력처럼 보이지 않게 톤을 낮춘다(고칠 수 있다고 읽히면 안 된다). */
.fx-form .pqd-def { font-size: var(--fx-fs-sm); color: var(--muted); }
.as-batches .as-brow { cursor: pointer; }
/* ★센 것을 말하는 줄 — 툴바가 감춰지는 화면이라 **목록 안**에 둔다(말했는데 안 보이면 안 말한 것이다). */
.as-bcap { font-size: 12px; color: var(--muted); margin: 2px 0 6px; }
/* ★★①작업표는 **우측 캔버스 높이를 다 쓴다**(사장님: 아래 여백 과다).
   ★폼을 세로 flex 로 세우고 표에 `flex: 1` 을 줘서 남는 높이를 표가 가져간다 —
   고정 vh 는 캔버스가 커져도 안 따라오고 아래가 비어 보인다. */
.fx-form[data-owner="asset-ws"] { height: 100%; min-height: 0; }
.fx-form .ws-scroll { flex: 1 1 auto; min-height: 240px; overflow: auto; }
/* ★[저장]은 **아래 고정** — 46줄을 끝까지 내려가야 저장할 수 있으면 그건 표가 아니다. */
.fx-form .ws-foot { position: sticky; bottom: 0; z-index: 2; padding-top: 6px;
  background: var(--panel); border-top: 1px solid var(--fx-field-bd); }
/* ★★③칸 폭을 고정하고 넘치면 말줄임 — 행 높이가 들쭉하면 46줄을 훑을 수 없다.
   ★값을 자르는 것이 아니라 **보이는 폭만** 줄인다(전체 값은 `title` 로 확인하신다). */
.fx-form .fx-grid td.ws-sn, .fx-form .fx-grid td.ws-md, .fx-form .fx-grid td.ws-sp {
  max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 3px 5px; }
/* ★★②기본 폭에서 **시리얼·모델명을 20% 축소**(사장님) — 남는 폭은 사양·불량 유형이 쓴다.
   22%→17.6% · 24%→19.2%. ★사장님이 손으로 더 조절하실 수 있다(아래 리사이저). */
.fx-form .fx-grid td.ws-sn { width: 17.6%; }
/* ★2026-08-06 — 시리얼 없는 채널의 순번 표식(`#3/15`). **곁글자**라 코드보다 작고 흐리다:
   식별의 주인은 여전히 우리 자산번호이고, 이것은 *"그중 몇 번째"* 를 거들 뿐이다. */
.fx-form .fx-grid td.ws-sn .ws-seq { margin-left: 5px; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
.fx-form .fx-grid td.ws-md { width: 19.2%; }
.fx-form .fx-grid td.ws-sp { width: 26%; }
/* ═══ ★★①작업표가 높이를 더 쓰게 — 고정 요소를 **줄인다**(v366 후에도 부족하셨다) ═══
   ★프레임 자체는 JS 가 `art-frame-max` 로 키운다(72vh → calc(100vh - 138px)).
   여기서는 그 안의 **고정 요소가 먹는 자리**를 줄여 리스트에 넘긴다. */
.fx-form.ws-form { gap: 4px; }                       /* 기본 9px → 4px */
.fx-form.ws-form .asc-head { margin: 0; padding: 0; }
.fx-form.ws-form .ws-hint { font-size: var(--fx-fs-sm); margin: 0; opacity: .8; }
.fx-form.ws-form .ws-foot { padding-top: 4px; }
/* ═══ ★★②칸 경계를 **끌어서** 폭을 맞춘다(의존성 0) ═══
   ★손잡이는 머리글 오른쪽 경계에 얹는다. `th` 는 아래에서 이미 `position: sticky` 라
   **그 자체가 기준 상자**다(absolute 자식이 여기에 붙는다) — 새 `position` 을 주지 않는다.
   ★손잡이가 글자를 덮지 않게 오른쪽 여백만 준다. */
.fx-form.ws-form .fx-grid thead th { padding-right: 10px; }
.fx-form.ws-form .ws-grip {
  position: absolute; top: 0; right: 0; width: 7px; height: 100%;
  cursor: col-resize; user-select: none; }
.fx-form.ws-form .ws-grip:hover { background: color-mix(in srgb, var(--accent) 45%, transparent); }
/* ★머리글 고정은 **격자 클래스로만** 적는다 — 스크롤 상자 이름(`.ws-scroll`)을 셀 규칙에
   넣으면 *"격자 표 목록을 CSS 에서 뽑는"* 검사가 그 상자를 표로 읽는다(실제로 걸렸다).
   ★sticky 는 스크롤 조상이 있어야 효과가 나므로 다른 격자에는 아무 일도 안 일어난다. */
.fx-form .fx-grid thead th { position: sticky; top: 0; z-index: 1; }
.fx-form .ws-rec { font-size: var(--fx-fs-sm); color: var(--muted); }
/* ★불량 유형은 **여러 개**를 고르는 칸이라 높이를 준다(격자 안이지만 한 줄이 아니다). */
.fx-form .fx-grid td select.ws-code { height: auto; min-height: 46px; }
.fx-form .fx-pill { border-radius: var(--fx-pill); border: 1px dashed var(--fx-field-bd);
  padding: 5px 11px; cursor: pointer; }
.fx-form .ain-top { display: flex; flex-wrap: wrap; gap: var(--fx-gap); }
.fx-form .ain-lab { font-size: var(--fx-fs-sm); }
.fx-form .asc-head { align-items: center; }
.fx-form table { border-collapse: separate; border-spacing: 0 4px; font-size: var(--fx-fs-sm); }
.fx-form th, .fx-form td { font-size: var(--fx-fs-sm); }
/* ★②리스트는 **스프레드시트처럼** — 칸마다 상자를 그리지 않는다(격자가 상자를 대신한다). */
.fx-form .pq-grid { width: 100%; border-collapse: collapse; border-spacing: 0; }
.fx-form .pq-grid th, .fx-form .pq-grid td {
  border: 1px solid var(--fx-field-bd); padding: 0; }
.fx-form .pq-grid th {
  padding: 4px 6px; text-align: left; font-weight: 600;
  background: color-mix(in srgb, var(--panel-2) 60%, transparent); white-space: nowrap; }
/* ═══ ★★★.fx-grid — **격자 셀 안은 무조건 플랫**(2026-08-05 · 사장님 지적 **네 번째**) ═══
   ★★원인은 클래스가 아니라 **특이도**였다. 위 일반 규칙
   `.fx-form input:not([type="file"]):not([type="checkbox"])` 은 `:not()` 이 둘이라 **(0,3,1)**,
   격자 규칙 `.fx-form .pq-grid td input` 은 **(0,2,2)** — 클래스 열이 3>2 라 **일반 규칙이 이긴다.**
   그래서 v347 에 격자 규칙을 쓴 뒤에도 `input` 은 줄곧 알약(`--fx-radius` 12px)이었다.
   `select` 는 짝이 되는 일반 규칙에 `:not()` 이 없어(0,1,1) 격자가 이겼다 —
   ★**한 표 안에서 select 만 플랫이고 input 은 알약**이었던 것이 이 어긋남의 모양이다.
   (v350 은 그 반대로 읽고 select 를 덮었다. 고친 것은 select 뿐이고 input 은 그대로였다.)

   ★★그래서 **표 이름을 열거하는 것을 그만둔다.** 격자 표에는 `.fx-grid` 표식 하나를 달고,
   그 셀 안의 **모든 입력 요소**를 이 한 규칙이 덮는다 — 칸이 새로 생겨도 자동으로 플랫이다.
   ★이 규칙은 특이도가 (0,2,2) 로 **평범하다**. 그래도 되는 이유는 위 일반 규칙이
   `:not(:where(.fx-grid *))` 로 **여기까지 안 오기 때문**이다 — 이긴 것이 아니라 **안 겹친다.**
   (그래서 `.pq-del` 의 `width: auto` 같은 종전 셀 규칙도 그대로 산다.)
   ★체크박스·라디오는 뺀다(대조표 [선택] 칸 — 네이티브 모양이 그 자리의 뜻이다). */
.fx-form .fx-grid :is(td, th) :is(input, select, textarea, button):not(:where([type="checkbox"], [type="radio"])) {
  border: none; border-radius: 0; box-shadow: none; background: transparent;
  color: var(--text); font-size: var(--fx-fs-sm);
  padding: 3px 5px; width: 100%; box-sizing: border-box; }
.fx-form .fx-grid :is(td, th) :is(input, select, textarea):not(:where([type="checkbox"], [type="radio"])):focus {
  outline: none; box-shadow: inset 0 0 0 2px var(--fx-focus); border-radius: 0; }
.fx-form .fx-grid td select { appearance: none; -webkit-appearance: none; cursor: pointer; }
/* ★★⑤수량·단가의 **업다운 스피너 제거** — 표에서는 눌러 올리는 것보다 적어 넣는 것이 빠르고,
   스피너가 칸 폭을 먹어 숫자가 가린다(값은 직접 입력한다). */
.fx-form .pq-grid input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.fx-form .pq-grid input[type="number"]::-webkit-outer-spin-button,
.fx-form .pq-grid input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; appearance: none; margin: 0; }
.fx-form .pq-grid .pq-num input, .fx-form .pq-grid td input.pq-num { text-align: right; }
.fx-form .pq-grid .pq-rn { width: 30px; text-align: center; color: var(--muted);
  padding: 4px 2px; background: color-mix(in srgb, var(--panel-2) 40%, transparent); }
.fx-form .pq-grid .pq-del { width: auto; padding: 2px 6px; color: var(--muted); }
.fx-form .pq-grid .pq-del:hover { color: var(--danger); }
/* ★③파일 고르기 — 네이티브 입력을 감추고 우리 버튼이 연다(모양 통일). */
/* ★★2026-08-05 — 대조표(`.ar-table`)도 격자다. 종전에는 여기에 **같은 선언을 한 벌 더**
   적어 두었는데(v354), 그렇게 표마다 베껴 쓰면 **표가 하나 늘 때마다 잊는다.**
   → 선언은 위 `.fx-grid` **한 곳**에만 두고, 이 표는 그 표식을 단다(`skills.js`).
   ★스코프는 `.fx-form` 안이다 — 대조표를 [검수] 탭에서 여는 다른 갈래는 무접촉. */
.fx-form .ar-table td { padding: 0 4px; }
.fx-form .ar-table td.eq-qty, .fx-form .ar-table td.eq-price,
.fx-form .ar-table th.eq-price { text-align: right; }
.fx-form .lst-tsvbox { margin-top: 6px; }
.fx-form .lst-tsvbox.hidden { display: none; }
.fx-form .lst-tsv { width: 100%; box-sizing: border-box; font-family: monospace; }
.fx-form .skd-hint, .fx-form .skr-note, .fx-form .ain-msg, .fx-form .lst-fmsg,
.fx-form .lst-cap, .fx-form .pq-linknote { font-size: var(--fx-fs-sm); }

/* 섹션 루트에 color 를 명시 → 테마가 --text 를 덮어쓰면 '명시적 color 가 없는' 텍스트
   (브랜드·브리핑 본문 등)도 그 섹션의 글자색을 상속한다(밝은 배경 글자 사라짐 해결). */
.sidebar, .canvas, .chat-area, .modal-card { color: var(--text); }

* { box-sizing: border-box; }
body {
  margin: 0;
  /* ★W-UIX13-A ⑨ — 글꼴은 **토큰 하나**에서 온다(Plex Sans KR → Pretendard → 시스템 폴백). */
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  letter-spacing: -0.003em;
  background: var(--bg);
  color: var(--text);
  /* 모바일 주의: 100vh 는 '주소창 접힌' 큰 뷰포트 기준이라 하단 입력창이 화면 밖으로
     밀린다(실측) → dvh(동적 뷰포트, 주소창 표시분 반영)로 덮어쓰기. 구형 브라우저는 vh 폴백. */
  min-height: 100vh; /* 대화는 브라우저 전체 스크롤 사용 */
  min-height: 100dvh;
}
.hidden { display: none !important; }
.accent { color: var(--accent); }

/* ===== 로그인 ===== */
.login-wrap {
  display: flex; align-items: center; justify-content: center; height: 100vh; height: 100dvh;
}
/*   ★★W-UIX14-S6-A — 로그인 카드가 **공용 카드 결**이 됐다(표면 `--surface` · 테두리 0 ·
     공용 그림자). 폭·패딩은 이 화면 몫이라 그대로 둔다 — 바꾼 것은 **표면의 말**뿐이다. */
/*   ★★W-UIX14-S6-A — 로그인 카드는 **밝은 표면 섬**이다.
     ★★실화면 스삷이 잡은 결함: 표면만 `--surface`(흰색)로 바꾸자 **글자는 다크 토큰**이
     그대로 내려와 로고 워드마크(`currentColor`)가 **흰 카드 위 흰 글자**로 사라졌고 입력칸도
     남색으로 남았다 — S1 이 *"다크 패널 위 흰 카드"* 로 적어 둔 그 어긋남의 반대쪽이다.
     ⇒ 표면을 바꾸는 자리에서 **그 섬의 글자 토큰도 함께** 정한다(카드 안은 전부 밝은 바닥 위다).
     ★종전에는 모달 로그인이 hex 를 손으로 박아(#ffffff/#1f2937/#e5e7eb) **같은 일을 어설프게** 하고 있었다. */
.login-card { --text: #171B24; --muted: #667085; --hairline: rgba(23,27,34,.12);
  --panel-2: #F1F5F9; --border: rgba(23,27,34,.12);
  background: var(--surface, #FFFFFF); color: var(--text); padding: 40px;
  border-radius: var(--r-card, 12px); width: 360px; border: 0;
  box-shadow: 0 0 0 1px rgba(23,27,34,.07),
    var(--wk-shadow, 0 1px 2px rgba(23,27,34,.05), 0 6px 18px rgba(23,27,34,.06)); }
.login-card h1 { margin: 0; font-size: 32px; }
.subtitle { color: var(--muted); margin: 6px 0 24px; font-size: 14px; }
.login-card input, .login-card select.reg-persona {
  width: 100%; padding: 12px 14px; margin-bottom: 12px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text); font-size: 15px;
}
/* 페르소나 드롭다운 — 선택 입력 신호(옅은 톤) */
.login-card select.reg-persona { appearance: auto; }
.login-card button[type=submit], .chat-input button, #login-form button, #register-form button {
  width: 100%; padding: 12px; border: none; border-radius: 8px; cursor: pointer;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #06283d; font-weight: 700; font-size: 15px;
}
.error { color: var(--error); font-size: 13px; margin: 8px 0 0; }
.demo-accounts { margin-top: 22px; font-size: 12px; color: var(--muted); }
.demo-accounts span { display: block; margin-bottom: 8px; }
.demo-accounts code { color: var(--accent-2); }
.auth-toggle { margin-top: 20px; font-size: 13px; color: var(--muted); text-align: center; }
.auth-toggle a { color: var(--accent-2); font-weight: 600; text-decoration: none; }
.auth-toggle a:hover { text-decoration: underline; }
.chip {
  display: inline-block; margin: 3px 4px 0 0; padding: 6px 10px; font-size: 12px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 20px; cursor: pointer;
}
.chip:hover { border-color: var(--accent); }

/* ★UX2 ③ — 로그인 = 현재 데모 화면 위 라이트 모달(사장님 "색상은 밝게"). login-view 마크업/핸들러
   재사용·오버레이(.login-modal)·라이트 카드. 전면 login-view(부트/SSO 콜백)는 이 클래스 없이 기존 그대로. */
.lm-close { display: none; }
#login-view.login-modal {
  position: fixed; inset: 0; z-index: 1200; height: auto;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 23, 42, .5); padding: 20px;
}
/*   ★모달로 뜨는 로그인도 같은 표면이다 — 종전에는 hex 를 손으로 박아(#ffffff/#1f2937/#e5e7eb)
     테마가 안 따라왔다(S3 계약: 위험색·표면색 상수는 걷는다). */
#login-view.login-modal .login-card { position: relative; background: var(--surface, #FFFFFF); color: var(--text);
  border: 0; box-shadow: 0 0 0 1px rgba(23,27,34,.07), 0 24px 70px rgba(0, 0, 0, .28);
  max-width: 380px; width: 100%; }
#login-view.login-modal .subtitle { color: var(--muted); }
/*   ★입력칸은 **안쪽으로 파인 자리**라 `--panel-2` 를 남긴다(S1 규칙 · 지시서 §5). */
#login-view.login-modal input,
#login-view.login-modal select.reg-persona { background: var(--panel-2); color: var(--text); border: 1px solid var(--hairline); }
#login-view.login-modal input::placeholder { color: var(--muted); }
#login-view.login-modal .auth-toggle { color: var(--muted); }
#login-view.login-modal .auth-toggle a { color: var(--accent); }
#login-view.login-modal .google-sso { background: var(--surface, #FFFFFF); color: var(--text); border: 1px solid var(--hairline); }
#login-view.login-modal .sso-divider span { color: var(--muted); background: var(--surface, #FFFFFF); }
#login-view.login-modal .lm-close {
  display: flex; position: absolute; top: 12px; right: 12px; width: 30px; height: 30px;
  align-items: center; justify-content: center; border: none; background: transparent;
  color: #6b7280; cursor: pointer; border-radius: 8px;
}
#login-view.login-modal .lm-close:hover { background: var(--surface-2, rgba(148,163,184,.15)); color: var(--text); }
#login-view.login-modal .lm-close .lucide { width: 18px; height: 18px; }

/* ===== 앱 — 좌 사이드바 + 우 대화 (Claude 웹 패턴) =====
   대화 본문은 브라우저 전체 스크롤을 쓴다(내부 스크롤 박스 아님).
   사이드바는 sticky 로 화면에 고정, 입력창은 하단 sticky. */
/* 3분할 폭은 CSS 변수로(resize.js 가 드래그로 갱신·localStorage 저장) */
.app-wrap { display: flex; flex-direction: row; min-height: 100vh; min-height: 100dvh; --sb-w: 264px; --cv-w: 440px; }

/* --- 사이드바 (페이지 스크롤과 무관하게 화면 고정) --- */
.sidebar {
  width: var(--sb-w); flex: none;
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur));
  border-right: 1px solid var(--hairline); overflow: hidden;
  transition: width .22s ease;
  position: sticky; top: 0; height: 100vh; height: 100dvh; align-self: flex-start;
}
.sb-inner {
  width: var(--sb-w); height: 100%; display: flex; flex-direction: column;
  padding: 16px 14px; gap: 14px;
}
/* ★W-UIX1 ①(2026-09-06 · 사장님) — 데스크톱 접힘 = 완전 숨김이 아니라 **아이콘 레일**(펼침 현상 유지).
   §0 판정: 아이콘 없는 항목(섹션 제목 .sb-title)은 레일에서 라벨을 접고 **얇은 구분선**만 남긴다.
   floating 열기 버튼(☰)은 레일이 대신하므로 숨기고, 레일의 접기 버튼이 **토글**로 왕복한다(sidebar.js).
   모바일(≤900px)은 아래 §596 드로어 규칙이 덮는다(무접촉). */
@media (min-width: 901px) {
  .app-wrap.sb-collapsed .sidebar { width: 60px; border-right: 1px solid var(--border); }
  .app-wrap.sb-collapsed .sb-inner { width: 60px; padding: 16px 0; align-items: center; }
  .app-wrap.sb-collapsed .sb-head { justify-content: center; }
  /* ★W-UIX17 ①(2026-09-13 · 사장님) — 접힘 레일의 토글은 **워키 마크**다(클릭=펼치기).
     마크에 테두리 상자를 두르면 로고가 아니라 버튼으로 읽히므로 테두리·패딩을 벗기고,
     크기는 레일 아이콘 행(40px) 안에 든다(W-UIX4 ① 균등 간격). */
  .sb-toggle.sb-toggle-brand { border: 0; padding: 0; background: transparent; }
  .sb-toggle.sb-toggle-brand svg { width: 26px; height: 26px; display: block; }
  .app-wrap.sb-collapsed #sb-logo { display: none; }
  .app-wrap.sb-collapsed .sb-scroll { width: 100%; }
  .app-wrap.sb-collapsed .sb-navitem span,
  .app-wrap.sb-collapsed #demo-new-chat span,
  .app-wrap.sb-collapsed .sb-title-label,
  .app-wrap.sb-collapsed .mail-unread-badge { display: none; }
  .app-wrap.sb-collapsed .sb-navitem,
  .app-wrap.sb-collapsed #demo-new-chat,
  .app-wrap.sb-collapsed .mail-fold-sum { justify-content: center; padding-left: 0; padding-right: 0; }
  /* ★W-UIX2 ①(2026-09-06 · 사장님) — 레일에서 섹션 헤더를 **아이콘만**으로 보인다
     (라벨은 위에서 숨김 · 접힘 전용 .sb-title-ic 를 켜고 나머지 자식은 접는다 · 펼침 현행 무변). */
  /* ★W-UIX3 ①(2026-09-06 · 사장님) — 레일 구분선 이중선 제거: `.sb-section` 이 이미
     border-top 을 그리므로 헤더(.sb-title)에는 **선을 얹지 않는다**(둘이 인접해 2줄이 됐다). */
  /* ★W-UIX4 ①(2026-09-06 · 사장님 · B) — 접힘 레일은 **균등 간격 아이콘 바**: 모든 아이콘 행
     (nav·섹션 헤더)을 **같은 높이·같은 간격**으로 정돈한다. 펼침 헤더 Y 에 맞추지 않는다
     (내업무 할일트리 자리를 예약해 빈 세로공간을 만들지 않는다 · 사장님 B안). */
  .app-wrap.sb-collapsed .sb-scroll { gap: 4px; }
  .app-wrap.sb-collapsed .sb-navitem,
  .app-wrap.sb-collapsed .sb-title { height: 40px; margin: 0; padding: 0;
    justify-content: center; overflow: hidden; gap: 0; }
  .app-wrap.sb-collapsed .sb-section { padding-top: 0; margin: 0; gap: 4px; }
  .app-wrap.sb-collapsed .sb-title-ic { display: inline-flex; }
  .app-wrap.sb-collapsed .sb-title > :not(.sb-title-ic) { display: none; }
  /* §0 판정(W-UIX2 ①로 갱신) — 섹션은 레일에 **남긴다**(헤더 아이콘 = 워크스페이스 지도).
     다만 세부 트리(내 업무·간편장부·자산·이커머스·가계부)와 하단(의견·로그인)은 60px 에서
     라벨이 삐져 나오므로 **접는다**(자세한 항목은 펴서 본다 · ③ 클릭이 편다 · 실브라우저 삐짐 0). */
  .app-wrap.sb-collapsed .sb-foot,
  .app-wrap.sb-collapsed .task-tree,
  .app-wrap.sb-collapsed .erp-tree,
  .app-wrap.sb-collapsed .sb-fold,
  .app-wrap.sb-collapsed .mail-item,   /* ★W-UIX4 ②(2026-09-06 · 사장님) — 메일 하위 leaf(받은/보낸/휴지통) 아이콘은 레일서 숨긴다(섹션 헤더 아이콘 하나로) */
  .app-wrap.sb-collapsed .tt-add { display: none; }
  /* ★W-UIX2 ① — 하단 계정 행: 레일엔 **설정 아이콘만**(벨·로그아웃·배지 숨김 · 세로 정렬). */
  .app-wrap.sb-collapsed .sb-account { flex-direction: column; gap: 8px; }
  .app-wrap.sb-collapsed .sb-account .noti-wrap,
  .app-wrap.sb-collapsed .sb-account #logout-btn,
  .app-wrap.sb-collapsed .sb-account #user-badge { display: none; }
  .app-wrap.sb-collapsed .sidebar { overflow: hidden; }
  .app-wrap.sb-collapsed .sidebar-open { display: none !important; }
}

/* ★W-UIX4 ③(2026-09-06 · 사장님) — peek(레일 아이콘 클릭 펼침)은 **그 섹션 하위메뉴만** 보인다:
   클릭한 섹션(.sb-peek-open)의 트리만 남기고 **다른 섹션의 트리는 접는다**(헤더는 남아 전환 가능). */
.app-wrap.sb-peek .sb-section:not(.sb-peek-open) .task-tree,
.app-wrap.sb-peek .sb-section:not(.sb-peek-open) .erp-tree,
.app-wrap.sb-peek .sb-section:not(.sb-peek-open) .sb-fold { display: none; }

.sb-head { display: flex; justify-content: space-between; align-items: center; }
.sb-toggle {
  background: transparent; border: 1px solid var(--border); color: var(--muted);
  border-radius: 8px; cursor: pointer; padding: 4px 9px; font-size: 12px;
}
.sb-toggle:hover { color: var(--accent); border-color: var(--accent); }

.sb-newchat {
  width: 100%; padding: 10px; border-radius: 10px; cursor: pointer; font-size: 14px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border);
  text-align: left;
}
.sb-newchat:hover { border-color: var(--accent); color: var(--accent); }

.sb-section { display: flex; flex-direction: column; gap: 8px; min-height: 0;
  border-top: 1px solid var(--border); padding-top: 12px; }   /* 섹션 구분선(내업무·캘린더·메모 위) */
/* 팀 보드 섹션: 제목은 고정, 스크롤은 안쪽 .sb-board 가 담당 (아래 max-height) */
.sb-grow { flex: none; }
/* 내업무가 길어져도 섹션이 서로 겹치지 않도록: 헤드/계정은 고정, 가운데(내비+섹션)만 스크롤.
   섹션은 flex 압축 금지(flex-shrink:0) — 안 그러면 내용이 다음 섹션 제목 위로 겹쳐 보인다. */
.sb-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 14px; scrollbar-width: thin; }
.sb-scroll > * { flex-shrink: 0; }
/* ★★W-UIX20 ①(2026-09-13 · 사장님) — **두 펼침 경로의 폭을 같게.** 상단 [펼치기]로 펴면
   모든 섹션 트리가 서서 내용이 넘치고 스크롤바가 생기는데, 레일의 섹션 아이콘으로 펴면(peek)
   다른 트리가 감춰져 **넘치지 않아 스크롤바가 없다** — 그래서 같은 메뉴가 10px 넓게 서고
   여백이 달라 보였다(실측: nav 226 ↔ 236 · task-lock 208 ↔ 218 · 좌측은 둘 다 14.0).
   ⇒ 스크롤바 자리를 **항상 예약**해 두 경로를 A(상단 펼치기)로 맞춘다.
   ★**펼침에만 건다** — 상시로 주면 접힘 레일의 아이콘 가운데가 30 → 25 로 밀려
   W-UIX4 ①(균등 아이콘 바)의 계약이 깨진다(실브라우저 실측으로 잡았다). */
.app-wrap:not(.sb-collapsed) .sb-scroll { scrollbar-gutter: stable; }

.sb-head, .sb-foot, .sb-account { flex-shrink: 0; }
.sb-scroll::-webkit-scrollbar { width: 5px; }
.sb-scroll::-webkit-scrollbar-track { background: transparent; }
.sb-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,.16); border-radius: 4px; }
.sb-scroll::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.32); }
.sb-title {
  font-size: 15px; font-weight: 700; color: var(--text);   /* 폴리싱 #7 — 좌측 밀도↑ (16→15) */
  letter-spacing: .01em; margin-bottom: 2px;
}
.sb-empty { color: var(--muted); font-size: 13.5px; line-height: 1.7; margin: 2px 0; }

/* 팀 보드 — 필드 박스 안에 칩을 흐름(wrap)으로 나열 */
.sb-board {
  display: flex; flex-wrap: wrap; gap: 6px; align-content: flex-start;
  overflow-y: auto; padding: 10px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
  min-height: 52px; max-height: 34vh;   /* 칩이 많아지면 박스 안에서 스크롤 */
  scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.16) transparent; /* Firefox: 얇게+투명 트랙 */
}
/* 팀 보드 내부 스크롤바 — 투명 트랙 + 최대한 얇은 thumb (WebKit) */
.sb-board::-webkit-scrollbar { width: 4px; }
.sb-board::-webkit-scrollbar-track { background: transparent; }
.sb-board::-webkit-scrollbar-thumb { background: rgba(255,255,255,.16); border-radius: 4px; }
.sb-board::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.32); }
.sb-chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px;
  border-radius: 14px; font-size: 11px; max-width: 100%;
  background: var(--panel); border: 1px solid var(--border);
}
.sb-chip-type { color: var(--accent-2); flex: none; }
.sb-chip-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sb-suggests { display: flex; flex-direction: column; gap: 6px; }
.sb-suggests .suggest { text-align: left; border-radius: 9px; }

.sb-foot { border-top: 1px solid var(--border); padding-top: 12px; margin-top: auto; }
.sb-feedback {
  width: 100%; padding: 12px; border-radius: 10px; cursor: pointer;
  font-size: 14px; font-weight: 400;   /* ★UX8 ⑤ — 볼드 제거(일반 굵기) */
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border);
}
.sb-feedback:hover { border-color: var(--accent); color: var(--accent); }
/* ★UX8 ④ — 의견 보내기 아래 행: [로그인(데모 전용)] … [설정]. 설정은 우측 끝 고정(margin-left:auto)
   → 로그인 사용자(로그인 버튼 비표출)도 설정이 우측에 자연 정렬. */
.sb-foot-row { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.sb-foot-row #settings-btn { margin-left: auto; }
.sb-mini { display: flex; align-items: center; justify-content: center; gap: 7px; padding: 10px; font-size: 13px; }
.sb-mini .ic { width: 17px; height: 17px; flex: none; }

/* 섹션 배경 테마 모달 */
.theme-card { width: 440px; max-width: 92vw; }
/* 테마 스와치 — 흰색 계열이 배경에 묻히지 않도록 음영 컨테이너로 대비 확보(폴리싱 #6) */
.theme-rows { display: flex; flex-direction: column; gap: 14px; margin: 8px 0 4px;
  background: var(--panel-2); padding: 8px; border-radius: 8px; border: 1px solid var(--border); }
.th-row { display: flex; flex-direction: column; gap: 8px; }
.th-label { font-size: 12px; color: var(--muted); }
.th-swatches { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.th-sw {
  width: 26px; height: 26px; border-radius: 8px; cursor: pointer;
  border: 1px solid rgba(255,255,255,.18); padding: 0;
}
/*   ★★W-UIX14-F3 ①(사장님 실기) — 밝은 스와치에서 선택이 **안 보였다**.
     링을 두 겹으로 세운다: 안쪽에 **표면색 1px**(스와치와 링 사이를 띄워 대비를 만든다) ·
     바깥에 **강조색 2px**. 이러면 스와치가 밝든 어둡든 링이 항상 산다.
     ★★그리고 **저장된 것과 고르는 중인 것**을 가른다 — 대기는 **점선**이다
       ([확인] 전에는 아무것도 안 바뀐다는 사실이 화면에도 보여야 한다 · S1 이 세운 계약). */
.th-sw.on { outline: 2px solid var(--accent); outline-offset: 2px;
  box-shadow: 0 0 0 1px var(--surface, #FFFFFF); }
.th-sw.on.th-pending { outline-style: dashed; }
/*   ★피커(🎨) 칸도 **같은 링**이다 — 같은 일을 하는 자리가 다른 표시를 갖지 않는다. */
.th-custom.on { outline: 2px solid var(--accent); outline-offset: 2px;
  box-shadow: 0 0 0 1px var(--surface, #FFFFFF); }
.th-custom.on.th-pending { outline-style: dashed; }
.th-custom {
  display: inline-flex; align-items: center; gap: 2px; cursor: pointer; font-size: 15px;
  border: 1px dashed var(--border); border-radius: 8px; padding: 2px 6px 2px 2px;
}
.th-custom input[type=color] { width: 24px; height: 24px; border: none; background: none; padding: 0; cursor: pointer; }

/* 계정 — 사이드바 최하단 (구분선 포함) */
.sb-account {
  display: flex; align-items: center; gap: 8px;
  border-top: 1px solid var(--border); padding-top: 12px;
}
/* ★86.7(사장님) — 계정 배지를 **원형 아바타**로. 안에는 아이디 첫 글자만 대문자로
   들어간다(문자열은 auth.js 가 만든다). 원형이 되려면 `flex:1`(가로 확장)을 버려야 하고
   가로·세로가 같아야 하므로 고정 치수 + `border-radius:50%` 로 둔다. 색은 `.badge` 토큰 그대로. */
.sb-account .badge {
  flex: none; width: 30px; height: 30px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  overflow: hidden; white-space: nowrap; line-height: 1;
  /* ★86.8 — 글자만 키운다(원은 30px 그대로). 아바타는 글자가 원을 채워야 읽힌다. */
  font-size: 16px; font-weight: 700;
}
/* 설정(아이콘)·로그아웃(텍스트) 버튼을 **동일 높이**로 고정(2026-07-15 — 아이콘 버튼이 더
   크던 것을 정렬). 내용은 중앙 정렬, 높이는 box-sizing 으로 padding 무관 34px 고정.
   ★UX8 ④ — 설정이 .sb-foot-row 로 이동해도 동일 규격 유지(선택자 병기). */
.sb-account .ghost, .sb-foot-row .ghost { flex: none; height: 34px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; }

/* 접힘 시 복귀용 플로팅 ☰ */
.sidebar-open {
  position: fixed; top: 12px; left: 12px; z-index: 70;
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: 10px; padding: 8px 12px; font-size: 15px; cursor: pointer;
}
.sidebar-open:hover { border-color: var(--accent); color: var(--accent); }
.sidebar-backdrop {
  position: fixed; inset: 0; z-index: 55; background: rgba(2, 6, 23, .55);
}

/* --- 우측 대화 영역 (헤더 없음 — 계정은 사이드바 최하단) --- */
.chat-area { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; background: var(--bg); }
.brand { font-size: 20px; font-weight: 700; }
/* WorkI 로고(Constellation) — 테마 반응형 인라인 SVG. 색은 logo.js 가 currentColor/var(--accent)로 처리 */
.wi-logo { display: block; height: auto; width: 100%; }
#login-logo { width: 208px; max-width: 72%; margin: 2px auto 6px; }   /* 로그인 히어로 — 태그라인 포함 */
#sb-logo { width: 114px; }                                            /* 사이드바 헤더 — 워드마크만. ★UX8 ① 92→114(약 24% 확대·접힘 버튼과 간섭 없음) */

/* --- 패널 폭 조절 핸들(드래그) — 0폭이라 틈(어두운 띠)이 없고, 구분선은 섹션 자체의 테마
   테두리(.sidebar border-right / .canvas border-left)가 담당 → 배경/테마색에 자동으로 맞음. --- */
.resizer {
  flex: none; width: 0; cursor: col-resize; background: transparent;
  position: sticky; top: 0; height: 100vh; height: 100dvh; align-self: flex-start; z-index: 6;
  touch-action: none;
}
.resizer::before {   /* 레이아웃을 차지하지 않는 넓은 그랩 영역(seam 위를 ±5px 덮음) */
  content: ""; position: absolute; top: 0; bottom: 0; left: -5px; right: -5px;
}
.resizer::after {    /* 평소엔 숨김, 호버/드래그 시에만 강조선(구분선은 섹션 테두리가 담당) */
  content: ""; position: absolute; top: 0; bottom: 0; left: -1px; width: 2px;
  background: var(--accent); opacity: 0; transition: opacity .15s;
}
.resizer:hover::after, .resizer.dragging::after { opacity: .7; }
.resizer[data-resize="cv"] { display: none; }
.app-wrap.canvas-on .resizer[data-resize="cv"] { display: block; }
.app-wrap.sb-collapsed .resizer[data-resize="sb"] { display: none; }
body.resizing { cursor: col-resize; user-select: none; }
@media (max-width: 1099px) { .resizer { display: none !important; } }

/* 모바일: 사이드바 = 오버레이 드로어 + 입력창 = 하단 고정바(바텀내비 스타일) */
@media (max-width: 900px) {
  .sidebar {
    position: fixed; left: 0; top: 0; bottom: 0; z-index: 60;
    width: 264px; transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: 0 0 50px rgba(0,0,0,.5);
  }
  .app-wrap.sb-mobile-open .sidebar { transform: none; }
  .app-wrap.sb-collapsed .sidebar { width: 264px; border-right: 1px solid var(--border); }
}

/* ===== 좌측 워크스페이스 내비 (WORKSPACE_UI_PLAN — 좌 메뉴) ===== */
.sb-nav { display: flex; flex-direction: column; gap: 4px; }
.sb-navitem {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 12px; border-radius: 9px; cursor: pointer; font-size: 15px; font-weight: 400;
  background: transparent; color: var(--text); border: 1px solid transparent; text-align: left;
}
.sb-navitem .ic { width: 20px; height: 20px; flex: none; color: var(--muted); }
.sb-navitem span { line-height: 1; }
.sb-navitem:hover { background: var(--panel-2); border-color: var(--border); }
.sb-navitem:hover .ic { color: var(--accent); }
/* 공통 인라인 아이콘 */
.ic { display: inline-block; vertical-align: middle; }

/* ===== 우측 작업 캔버스 (3분할의 우 — AI와 같이 만든 산출물 누적) ===== */
.canvas {
  width: 0; flex: none;
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur));
  border-left: 1px solid var(--hairline); overflow: hidden;
  transition: width .22s ease;
  position: sticky; top: 0; height: 100vh; height: 100dvh; align-self: flex-start;
}
.app-wrap.canvas-on .canvas { width: var(--cv-w); }
.cv-inner { width: var(--cv-w); height: 100%; display: flex; flex-direction: column; }
.cv-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px; border-bottom: 1px solid var(--border); flex: none;
}
/* ★W-CV4-B1 — 좁은 폭에서 **탭 줄이 손잡이를 밀지 않는다**: 줄어드는 쪽은 탭이고,
   넘치면 탭 줄 안에서만 민다(`.cv-acts` 는 `flex:none` 이라 언제나 제 크기 · 겹침 0). */
.cv-tabs { display: flex; gap: 4px; flex: 1 1 auto; min-width: 0; overflow-x: auto; }
/* ★머리는 **높이가 흔들리면 안 되는 띠**다 — 전역 얇은 스크롤바(5px)도 여기서는 자리를
   예약해 탭이 넘칠 때만 머리가 54 → 63px 로 튄다(실측). 이 줄에서만 막대를 걷는다
   (대상 좁힘 §13-13 — 전역 규칙은 안 건드린다). 잘린 탭이 곧 '더 있다'는 표시다. */
.cv-tabs { scrollbar-width: none; }
.cv-tabs::-webkit-scrollbar { height: 0; }
.cv-tab {
  padding: 6px 12px; border-radius: 8px; cursor: pointer; font-size: 13px;
  background: transparent; color: var(--muted); border: 1px solid transparent;
  /* ★W-CV4-B1 — 탭 **낱개는 안 줄어든다**: 줄이 좁아지면 줄 안에서 밀릴 뿐이다.
     ★실측이 잡았다 — 줄에 `min-width:0` 만 주자 낱개가 쪼그라들며 글자가 줄바꿈해
       머리 높이가 46px → **156px** 로 부풀었다(탭 8개 · 폭 440). 줄이는 대상을 정하지
       않으면 flex 는 **가장 잘 줄어드는 것**을 줄인다. */
  flex: none; white-space: nowrap;
}
.cv-tab:hover { color: var(--text); }
.cv-tab.active { background: var(--panel-2); color: var(--accent); border-color: var(--border); }
/* ★★W-UIX13-C2 ①(2026-09-10 · 사장님 "구성안대로") — 캔버스 탭 줄은 **텍스트 탭**이다
   (구성안 §5 목업: 아이콘 0 · 알약 0 · 활성 = 잉크 600 + 강조색 밑줄 2px · 비활성 = 캡션색).
   ★대상은 **캔버스 탭 줄 하나**(`.cv-tabs` 안)로 좁힌다 — `.cv-tab` 이라는 이름은 설정 2단
     내비(`.set-nav-item`)도 **함께 쓰고 있어서**, 이름만 보고 전역에 걸면 그 세로 목록이 밑줄
     달린 텍스트로 무너진다(같은 클래스 두 자리 · 실측으로 확인).
   ★한 컴포넌트에 두 모양을 만들지 않는다 — 워크룸만 텍스트 탭으로 두면 [문서]·[할 일] 화면의
     같은 줄이 알약으로 남아 화면마다 다른 탭이 된다. 그래서 이 줄 **전체**를 옮긴다. */
.cv-head { border-bottom: 0; }
.cv-tabs { gap: 14px; }
.cv-tabs .cv-tab {
  padding: 0 0 8px; border: 0; border-radius: 0; background: transparent;
  border-bottom: 2px solid transparent;
  color: var(--wk-caption, var(--muted)); font-size: var(--fs-meta);
}
.cv-tabs .cv-tab:hover { color: var(--text); background: transparent; }
.cv-tabs .cv-tab.active {
  background: transparent; color: var(--text); font-weight: var(--fw-3);
  border-bottom-color: var(--accent);
}
/*   ★수는 라벨 **뒤에 붙는 숫자**다(0 이면 automations.js 가 아무것도 안 적는다). */
.cv-tabs .cv-tab-n { margin-left: 4px; color: inherit; }
/* ★Phase 94 S2-c(규칙 6-3) — 자동 전환을 억제했을 때의 표시. "왔다"는 알리되 자리는 뺏지 않는다.
   ★그 탭을 보는 순간 사라진다(switchTab) — 안 지우면 죽은 표시가 된다. */
.cv-tab-dot::after {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); margin-left: 6px; vertical-align: middle;
}
.cv-close {
  background: transparent; border: 1px solid var(--border); color: var(--muted);
  border-radius: 8px; cursor: pointer; padding: 4px 9px; font-size: 12px;
}
/* ★★W-CV4-B1(2026-09-01 사장님 "세 버튼을 우측 정렬로 나란히") — 손잡이 묶음.
   ★옛 규칙 `#canvas-clear { margin-left:auto }` 를 **걷었다**: W-CV4 ③ 이 그 버튼을 둘로 가른
     뒤로 그 id 는 없는 id 였고(죽은 규칙), 자리를 잡아 주던 손이 사라지자 `.cv-head` 의
     `space-between` 이 네 자식을 폭 전체에 고루 흩뿌렸다.
   ★자리는 **묶음**이 갖는다 — id 에 걸면 그 id 가 갈릴 때 규칙이 죽는다(방금 그랬다).
     손잡이가 하나 더 늘어도 이 한 줄이 계속 오른쪽 끝을 지킨다.
   ★`margin-left:auto` 를 남긴 이유: `.cv-head` 에 셋째 자식이 생겨도 묶음은 끝에 남는다
     (`space-between` 만 믿으면 그때 다시 흩어진다). */
.cv-acts { display: flex; align-items: center; gap: 6px; flex: none; margin-left: auto; }
.cv-close:hover { color: var(--accent); border-color: var(--accent); }
.cv-body { flex: 1; overflow-y: auto; padding: 14px; min-height: 0; }
/* ★W-HITL2b ⓑ — 보일 탭이 0일 때의 빈 상태(사람이 ◧ 로 직접 열었을 때만 선다).
   ★비었을 때 높이를 예약하지 않는다(§4-3) — `hidden` 이면 자리도 없다. */
.cv-blank { color: var(--muted); font-size: 13px; line-height: 1.7; text-align: center;
  padding: 28px 14px; }
.cv-pane { display: flex; flex-direction: column; gap: 12px; }
.cv-empty { color: var(--muted); font-size: 13px; line-height: 1.7; text-align: center; margin: 24px 8px; }
.cv-card { background: var(--surface, #FFFFFF); border: 0; border-radius: 12px; padding: 12px;
  box-shadow: 0 0 0 1px rgba(23,27,34,.07);}
.cv-card-title { font-size: 12.5px; color: var(--muted); margin-bottom: 8px; word-break: break-all; }  /* 폴리싱 #8 */
.cv-doc { display: flex; gap: 8px; align-items: baseline; padding: 5px 0; font-size: 12.5px; }  /* 폴리싱 #8 */
.cv-doc-ref { overflow: hidden; text-overflow: ellipsis; }
/* ★W-HITL1 — [문서] 탭 상단의 결재 카드 자리(정본 §2 R-H). 카드 사이 간격은 패인의
   `gap` 을 못 받으므로(여긴 한 겹 안쪽이다) 여기서 준다. 비면 `.hidden` 으로 사라진다. */
.doc-pending { display: flex; flex-direction: column; gap: 12px; }

/* 접힘 상태에서 캔버스 다시 열기(우상단 플로팅 ◧) */
.canvas-open {
  position: fixed; top: 12px; right: 12px; z-index: 50;
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: 10px; padding: 8px 12px; font-size: 15px; cursor: pointer;
}
.canvas-open:hover { border-color: var(--accent); color: var(--accent); }
/* ★★W-CV1 ① R3 — **복원은 열지 않는다.** 그 대신 "볼 것 있음"을 여기에 점으로 알린다.
   ★모양은 `.cv-tab-dot` 과 **같은 문법**이다(새 표식 언어를 만들지 않는다 · §0 표식 규율).
   ★거는 곳 = `canvas.js _markPeek(true)` · 푸는 곳 = `open()` 이 실제로 열리는 그 한 곳(85.10-b). */
/* ★★W-UIX20 ③(2026-09-13 · 사장님) — **좌측 메뉴의 도착 점.** 다른 메뉴로 넘어가 있는
   동안 답변·문서가 도착하면 그 메뉴/업무 옆에 점이 선다(열면 사라진다 · 새로고침에도 남는다).
   ★모양은 `.cv-tab-dot`·`.canvas-open-dot` 과 **같은 문법**이다(새 표식 언어를 만들지 않는다).
   ★답변/문서는 **색이 아니라 툴팁 문구**로 가른다(색을 늘리면 뜻이 둘이 된다). */
.arr-dot::after {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); margin-left: 6px; vertical-align: middle; flex: none;
}
.canvas-open-dot::after {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); margin-left: 6px; vertical-align: middle;
}

/* 업무 보드 — 상태별 그룹 + 카드 (우 캔버스 '업무' 탭) */
.tk-add { display: flex; gap: 6px; margin-bottom: 12px; }
.tk-add input[type=text] {
  flex: 1; min-width: 0; padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text); font-size: 13px;
}
.tk-add input[type=date] {
  padding: 7px 8px; border-radius: 8px; color-scheme: dark;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text); font-size: 12px;
}
.tk-add button {
  flex: none; padding: 8px 13px; border: none; border-radius: 8px; cursor: pointer;
  background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #06283d; font-weight: 700;
}
.task-board { display: flex; flex-direction: column; gap: 14px; }
.tk-col-head {
  font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em;
  display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
}
.tk-count { background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px; padding: 0 7px; font-size: 11px; }
.tk-col-empty { color: var(--muted); font-size: 12px; margin: 0 0 4px 2px; }
.tk-card { background: var(--surface, #FFFFFF); border: 1px solid var(--border); border-radius: 10px; padding: 10px; margin-bottom: 6px; }
.tk-card.is-done { opacity: .6; }
.tk-card.is-done .tk-title { text-decoration: line-through; }
.tk-top { display: flex; align-items: flex-start; gap: 6px; justify-content: space-between; }
.tk-title { font-size: 13.5px; line-height: 1.4; }
.tk-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.tk-proc { font-size: 11px; color: var(--accent-2); background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 1px 8px; }
.tk-due { font-size: 11px; color: var(--muted); background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 1px 8px; }
.tk-due.soon { color: var(--soon); border-color: var(--soon); }
.tk-due.over { color: var(--danger); border-color: var(--danger); }
/* 계층형 업무 분장(TASK_DELEGATION) — 공개범위/위임 배지 */
/*   ★W-UIX14-S4 A — 공개범위 배지는 **공용 작은 칩**(`.wk-chip.sm`)의 모양을 쓴다.
     ★색 뜻은 그대로다 — 팀/전사는 **상태가 아니라 범위**라 live/wait/fail 톤과 겹치지
     않는다(릴리 Q1). 마크업이 `wk-chip sm` 을 함께 달고 이 규칙은 색과 자리만 준다. */
/*   ★다크 스샷이 잡았다: 공용 칩의 잿빛 채움 위에 파랑·보라 글자를 얹으니 **대비가
     모자랐다**. 배경을 제 색의 옅은 틴트로 바꾸면 라이트·다크 어디서나 읽히고,
     색이 말하는 뜻(범위)도 더 또렷해진다 — 값을 박지 않고 같은 색에서 섞는다. */
.tt-vis { margin-left: 4px; }
.tt-vis.team { color: #2563eb; background: color-mix(in srgb, #2563eb 14%, transparent); }
.tt-vis.company { color: #7c3aed; background: color-mix(in srgb, #7c3aed 14%, transparent); }
.tt-deleg { font-size: 10px; color: var(--muted); margin-left: 4px; }
.tt-deleg.mine { color: var(--soon); font-weight: 600; }
/* (삭제 2026-07-27 사장님 지시) .nudge-badge — 내비 '대시보드' 우측 미결재 카운트.
   알림 표출은 알림 센터(벨)와 좌측 [알림업무] 폴더가 담당하므로 이 표면은 폐지했다. */

/* ══ 알림 센터 (Phase 81.2b) ══════════════════════════════════════════════
   계정 행의 벨 + 위로 열리는 드롭다운. 알림의 유일한 카운터 표면이다(대시보드 숫자 배지 폐지). */
.noti-wrap { position: relative; display: inline-flex; }
.noti-bell { position: relative; }
.noti-badge { position: absolute; top: -3px; right: -3px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 8px; background: var(--danger, #e5484d); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center; pointer-events: none; }
.noti-badge.hidden { display: none; }
/* ★★W-UIX1 ④(1)(2026-09-06 · 사장님 · 릴리 결재) — 작은 알림 모달(재구현 · body 포탈 · 벨 위로 뜸).
   W-CV2-B1 이 걷은 `.noti-panel` 을 다시 세운다(복원 아님 · 좌표는 JS `_positionPanel` 이 fixed 로 준다). */
.noti-panel { position: fixed; z-index: 200; width: 320px; max-width: calc(100vw - 16px);
  max-height: 60vh; display: flex; flex-direction: column; overflow: hidden;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .28); }
.noti-panel.hidden { display: none; }
.np-head { display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px; border-bottom: 1px solid var(--border); flex: none; }
.np-title { font-weight: 700; font-size: 13px; color: var(--text); }
/*   ★W-UIX14-S3 B(W-NH2-DEL) — 옛 알림함 **페이지**의 `.nh-*` 규칙 56줄을 걷었다.
     그 화면은 W-UIX1 ④(2) 에서 폐지됐고 `notihub.js` 도 이 판에서 함께 지웠다 —
     알림의 표면은 **벨 모달 하나**다(아래 `.np-*`). */
.np-allread { font-size: 12px; color: var(--muted); background: transparent; border: none; cursor: pointer; }
.np-allread:hover { color: var(--accent); }
.np-body { overflow-y: auto; }
.np-empty { padding: 24px 12px; text-align: center; color: var(--muted); font-size: 13px; }
.np-row { display: flex; align-items: center; gap: 8px; padding: 10px 12px; cursor: pointer;
  border-bottom: 1px solid var(--border); }
.np-row:last-child { border-bottom: none; }
.np-row:hover { background: var(--panel-2); }
/*   ★★★W-UIX14-F7 ③(2026-09-12 · 사장님 스샷) — **행이 세로로 쪼개져 있었다.**
     ★뿌리는 이름이 아니라 **순서**다: S3-B 가 이 줄을 공용 행(`.wk-row`)에 합류시켰는데,
       그 규칙은 **아코디언 행**용이라 `display: block`(머리 한 줄 + 펼침판)이고 파일에서
       `.np-row` 보다 **뒤에** 산다 — 특이도가 같으면 뒤가 이긴다(이 리포가 여러 번 치른 값).
       그래서 아이콘·제목·시각·화살표가 **한 줄이 아니라 네 줄**로 섰다.
     ⇒ 두 이름을 **함께** 든 규칙 하나로 되돌린다(특이도 0,2,0 · 공용 레시피는 무접촉).
     ★시각은 제목 **뒤에 붙는 캡션**이다(아래로 내려가지 않는다) · 제목은 말줄임. */
.np-row.wk-row { display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border); }
.np-row.wk-row:last-child { border-bottom: none; }
.np-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: row;
  align-items: baseline; gap: 8px; }
.np-time { flex: 0 0 auto; }
/*   ★W-UIX14-F7 ③ — 제목이 남은 자리를 먹고, 넘치면 말줄임한다(시각·화살표를 안 밀어낸다). */
.np-label { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.np-unread .np-label { font-weight: 700; }
.np-time { font-size: 11px; color: var(--muted); }
.np-go { flex: none; color: var(--muted); display: inline-flex; }
.np-go svg { width: 16px; height: 16px; }
.np-row:hover .np-go { color: var(--accent); }
/* 모바일 = 전폭 하단 시트 */
@media (max-width: 760px) {
  .noti-panel { left: 8px !important; right: 8px; bottom: 8px !important; width: auto; max-height: 66vh; }
}

/* 계정 행이 사이드바 최하단이라 패널은 **위로** 열린다.
   ★핫픽스(사장님 실기기 피드백 2026-07-26) — 원래 position:absolute 였는데, 조상
   `aside#sidebar` 가 overflow:hidden(폭 251px)이라 **패널 우측이 잘려** 그 안의
   [모두 읽음] 버튼(실측 left 305~375px)이 화면 밖에 있었다(=버튼이 "없다"고 보인 실인).
   ★fixed 전환만으로는 해결되지 않았다(브라우저 실측): 사이드바가 backdrop-filter:blur(16px)
   를 갖고 있어 **fixed 자손의 컨테이닝 블록**이 되고, 그 overflow 가 그대로 자른다.
   → 최종 해법은 notifications.js portal() 이 패널 노드를 body 로 옮기는 것이고,
   여기서는 fixed 좌표계만 제공한다(좌표는 place() 가 벨 기준 계산·클램프).
   아래 left/bottom 은 JS 실행 이전 폴백값.

   ★테마 정합(2026-07-26 결재 2번) — 이 앱의 테마는 다크/라이트 토글이 아니라 **섹션별
   배경색 피커**(theme.js)이고, 토큰을 `#sidebar`·`.chat-area`·`#canvas` 같은 **섹션 루트에
   인라인**으로 심어 하위로 cascade 시킨다. style.css `:root` 기본값은 다크다.
   → 위 포탈(body 이동)로 패널이 #sidebar 밖으로 나가면서 사이드바의 화이트 토큰 상속이
   끊기고 `:root` 다크로 폴백했다(=v209 에서 패널만 어둡게 보인 원인·내 핫픽스의 회귀).
   해소는 두 갈래이며 둘 다 필요하다:
     ① notifications.js 가 ThemeUI.applyTo(panel) 로 토큰을 패널에 직접 심는다
        (modal.js·share.js·ui_confirm.js 가 쓰는 기존 선례 — 신규 미러링 기구 불필요).
     ② 아래 `color: var(--text)` — 패널 CSS 에 color 선언이 없으면 body(=:root 다크)의
        글자색을 상속해 ① 만으로는 글자만 밝게 남는다(실측 확인).
   ※ 색·배경·보더는 전부 토큰 사용. box-shadow 는 이 코드베이스에 토큰이 없고
     전 구간 rgba 하드코딩이 관례라(예: .dg-node) 기존 값을 그대로 둔다. */
/* ★★W-CV2-B1(2026-09-01) — **종 드롭다운 패널을 걷었다**(`.noti-panel` 계열 73줄 + 모바일 절).
   진입이 알림함 화면 하나로 모이면서(W-CV2 ③) 이 규칙들은 **부르는 곳이 0** 이 됐다.
   ★목록·읽음·전체읽음의 모양은 알림함 화면이 `nh-*` 로 **따로 갖고 있다** — 옮긴 것이
     아니라 **겹쳐 있던 것을 지운** 것이다(클래스 이름이 겹치지 않는 것이 그 증거다).
   ★`.noti-wrap`·`.noti-badge`(위)와 `.noti-highlight`(아래)는 **남는다**: 앞은 종 배지,
     뒤는 알림에서 넘어간 메시지 강조로 `jump()` 가 계속 쓴다. */
/* 알림 클릭 → 해당 넛지 메시지 강조(2.6초 후 자동 해제) */
.noti-highlight { outline: 2px solid var(--accent, #3b82f6); outline-offset: 3px;
  border-radius: 10px; transition: outline-color .3s ease; }

/* ══════════════════════════════════════════════════════════════════════
   🔔 알림함(W-NH2) — 중앙 도구 뷰. 목록 화면이라 **내부만** 스크롤한다.
   ★색·보더는 전부 토큰(사장님 상시 지시 — fx 토큰/클래식 혼재 금지). */
/* ★목록은 **읽는 폭**을 갖는다 — 전폭으로 두면 제목은 왼쪽 끝, 버튼은 오른쪽 끝이라
   1400px 를 눈으로 건너야 한다(실측 후 고침). 메일처럼 2분할이 아니라 한 줄 목록이다. */
/* 추적 중 자동화(읽기 전용) — 알림 목록 위에 얹히는 카드 */
/* 좌측 트리 고정 노드(🔔 알림함) — 업무 행이 아니라 **자리**다(WorkTask 0행) */
.tt-fixed { display: flex; flex-direction: column; }
.tt-fixed .tt-row { display: flex; align-items: center; gap: 6px; }
.tt-fixed-title { flex: 1 1 auto; min-width: 0; text-align: left; cursor: pointer;
  background: transparent; border: 0; color: var(--text); font: inherit; padding: 4px 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-fixed-title:hover { color: var(--accent); }
.tt-fixed-sub .tt-fixed-title { font-size: 12.5px; color: var(--muted); padding-left: 18px; }
.tt-fixed-sub .tt-fixed-title:hover { color: var(--accent); }
.tt-nbadge { flex: 0 0 auto; font-size: 10.5px; font-weight: 700; padding: 0 5px;
  border-radius: 999px; background: var(--danger, #e5484d); color: #fff; }
.tt-nbadge.hidden { display: none; }

/* 다중 캘린더 선택(CALENDAR_FINISHING) */
.cal-list { margin: 8px 0 4px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; }
.cal-list.hidden { display: none; }
.cal-list-h { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.cal-item { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 3px 0; cursor: pointer; }
/* 팀 NAS(SMB) 설정 폼 */
.team-nas { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.team-nas.hidden { display: none; }
.team-nas #team-nas-form { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.team-nas #team-nas-form.hidden { display: none; }
/* ★N-G1 — 입력칸은 `.fx-input` 토큰이 그린다(UI 일관성 지시). 종전의 자체 input 규칙은
   fx 와 값이 달라 같은 모달 안에서 두 가지 입력칸이 보였다 — 그래서 지웠다. */
/* 허용 사용자 목록 · 동작 줄 — 새 색 0(기존 토큰만). */
.team-nas .nas-allow { margin-top: 8px; }
.team-nas .nas-allow-h { font-size: var(--fx-fs-sm, 12px); color: var(--muted); margin-bottom: 4px; }
.team-nas .nas-allow-list { display: flex; flex-wrap: wrap; gap: 8px 14px; }
.team-nas .nas-allow-list label { display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fx-fs, 13px); }
.team-nas .nas-actions { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.team-nas .nas-actions .set-hint { margin: 0; }
.team-nas .nas-ok { color: var(--accent); }
.team-nas .nas-bad { color: var(--danger, #f87171); }
/* 감사(Audit) 대시보드 — 읽기 전용 표 */
.audit-head { display: flex; align-items: center; gap: 8px; padding: 6px 0 10px; }
.audit-list { overflow: auto; }
.audit-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.audit-table th, .audit-table td { text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.audit-table th { color: var(--muted); font-weight: 600; position: sticky; top: 0; background: var(--panel); }
.au-st { font-size: 11px; border-radius: 8px; padding: 1px 7px; border: 1px solid var(--border); }
.au-st.au-read { color: #2563eb; border-color: #93c5fd; }
.au-st.au-denied, .au-st.au-failed { color: var(--danger); border-color: var(--danger); }
.au-st.au-committed, .au-st.au-downloaded { color: var(--soon); border-color: var(--soon); }
/* 동적 웹 대시보드(H) — 격리 iframe 아티팩트 */
.dash-head { display: flex; align-items: center; gap: 8px; padding: 6px 0 10px; }
.dash-title { font-weight: 600; flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* 긴 파일명 한 줄·... 줄임 */
/* ★★★W-CV2 ①(2026-09-01 사장님 지시 "대시보드 하단 여백 없게") — **패인을 채운다.**
   실측(창 844): `.cv-body` 가용 761 인데 패인이 **631** 이라 아래 **130px** 이 비어 있었다.
   원인은 프레임마다 **자기 상수**를 들고 있던 것 — `70vh`·`72vh`·`calc(100vh−138)`·`calc(100vh−178)`
   넷이 같은 자리를 각자 쟀다(W-CV1-B2 가 등재한 부채의 뿌리).
   → 상수를 **전부 없애고** 아래 채움 규칙 하나로 모은다(문서·대시보드·데스크가 같은 규칙).
   ★`.cv-body`(전 패인 공용)는 **안 건드린다**: 그것이 `.cv-inner`(height:100%)의 flex 아이템이라
     높이가 **확정**이고, 그래서 자식의 `height:100%` 가 그 content box 로 해석된다(실측 확인 —
     문서·대시보드·데스크 셋 다 761 로 채워지고 넘침 0). flex 로 바꿀 이유가 없다. */
.dash-frame { /* 높이는 아래 채움 규칙이 정한다 */ }
/* ★★W-CV1 ③(사장님 지시 "상단 타이틀과 문서 사이 여백을 줄여라") — **[문서] 패인에만** 건다.
   ★`.cv-body { padding: 14px }` 는 **전 패인 공용**이라 손대지 않는다: 거기서 줄이면 입력·데스크·
     참고자료까지 함께 눌린다(§13-13 *"줄이는 처방은 대상이 좁아야 한다"*).
   ★실측 — 종전 여백은 `.dash-head` 아래 10px + `.cv-pane` gap 12px = **22px** 였다. 8px 로 줄인다. */
.cv-pane[data-pane="document"] { gap: 4px; }
/* ★★실브라우저가 계획서를 고쳤다 — 여백은 **셋**이었다.
   계획서는 `.dash-head` padding 10 + `.cv-pane` gap 12 = 22 로 셌는데, 실측하니 그 사이에
   **`app.html:3366` 인라인 절의 `margin-bottom: 12px`** 가 하나 더 있었다(스타일 두 곳이
   같은 셀렉터를 나눠 갖고 있어 한쪽만 보면 못 센다). 실제 종전 값은 **24px**(=12+12)이고
   지금은 **4px** 다. ★세는 자리가 둘이면 한 곳만 읽고 수를 적지 않는다. */
.cv-pane[data-pane="document"] .dash-head { padding: 2px 0 4px; margin-bottom: 0; }
/* ══ ★★W-CV3 — 슬라이드 덱(가로 16:9) ══════════════════════════════════════
   사장님 지시: *"PPT 형식으로 요청하면 **가로(슬라이드) 형식**으로 표시 · 아래에 좌우 넘김 버튼."*
   ★넓어진 캔버스(W-CV1 ②)에서 슬라이드가 산다 — 16:9 를 **폭 기준**으로 잡고 남는 높이는 비운다
     (억지로 늘리면 글자가 커져 발표 화면처럼 안 보인다). */
/* ★★W-CV4 ①(2026-09-01 사장님 결재) — 덱이 [문서] → **[데스크]** 로 내려왔다.
   ★종전엔 프레임 자신에 `.dash-slides` 를 걸었는데, [데스크]는 구글시트·견적서·자산 현황이
     번갈아 사는 자리라 **그 클래스가 다음 표면에 남는다**(`art-frame-max` 가 정확히 그 길로
     샌 자리다 — `claimFrame` 주석의 그 사고). → 16:9 무대를 **프레임 안의 노드**로 세운다:
     무대는 내용의 일부라 다음 표면의 `innerHTML = ""` 한 번에 함께 사라진다(누수 구조적 0).
   ★16:9 는 **폭 기준**이고 남는 높이는 비운다(억지로 늘리면 글자가 커져 발표 화면이 안 된다). */
.deck-stage { height: 100%; display: flex; align-items: center; justify-content: center; }
.deck-stage > .dash-iframe {
  width: 100%; height: auto; aspect-ratio: 16 / 9; max-height: 100%;
  border-radius: 10px; background: #0f172a;
}
/* 넘김 크롬 — 프레임 **아래**(부모 소유 · W-CV4 ① 부터 [데스크] 패인 안). 비어 있을 때는 자리도 없다(§4-3). */
.deck-bar { display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 6px 0 2px; flex: none; }
.deck-bar.hidden { display: none; }
.deck-btn { background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 8px; cursor: pointer; padding: 4px 14px; font-size: 14px; line-height: 1.4; }
.deck-btn:hover { border-color: var(--accent); color: var(--accent); }
.deck-btn:disabled { opacity: .45; cursor: default; border-color: var(--border); color: var(--muted); }
.deck-pos { font-size: 12.5px; color: var(--muted); min-width: 54px; text-align: center; }
/*   ★★★W-UIX14-F1 ③(사장님 실기) — **뿌리는 프레임 자신의 흰 배경이었다**(실측:
     `background:#fff` · 다크에서 문서는 제 배경(#0f172a)을 칠하는데 프레임이 흰색이라
     여백·로딩 순간이 **순백으로 튄다**). 테두리도 `--border` 라 다크에서
     `rgba(255,255,255,.12)` = **흰 링**이 됐다 ⇒ 배경은 문서에 맡기고(투명)
     경계는 hairline 링 하나로.
     ★★그리고 이 iframe 은 `sandbox="allow-scripts"`(same-origin 미부여)라
     **`contentDocument` 에 못 닿는다** — `ThemeUI.applyTo(frame)` 선례(assets.js:1829)는
     **같은 출처 div** 의 것이라 이 자리에 못 쓴다(§0 실측). */
.dash-iframe { width: 100%; height: 100%; border: 0; border-radius: 8px;
  box-shadow: 0 0 0 1px var(--hairline); background: transparent; }
/* 아티팩트 듀얼 페인(ARTIFACT_DUAL_PANE) — 격리 iframe. 다크 카드 테마는 view_html 내부에서 자기완결. */
.art-frame { /* 높이는 아래 채움 규칙이 정한다(W-CV2 ①) */ }
/* 구글 시트 — 캔버스 최대 높이 + 스케일 줌 오버플로 봉쇄 */
/* ★W-CV2 ① — 높이는 채움 규칙이 이미 최대다. 이 클래스에 남는 일은 **줌 오버플로 봉쇄** 하나다
   (구글 시트를 스케일로 키울 때 프레임 밖으로 새지 않게). 높이 상수는 걷었다. */
.art-frame-max { overflow: hidden; }
/* ══ ★W-CV2 ① 채움 규칙 — 산출물 패인 **둘에만** 건다 ═════════════════════════
   ★대상 좁힘(§13-13): `[data-pane="document"]`·`[data-pane="artifact"]` 만. [입력]·[참고자료]·
     [검수]·[감사]·[시스템 관리] 패인은 내용만큼 자라야 하므로 무접촉이다.
   ★인쇄 무접촉: `body.print-doc` 절이 `height:auto !important` 로 덮는다(W-CV1 ④). */
#canvas .cv-body > .cv-pane[data-pane="document"],
#canvas .cv-body > .cv-pane[data-pane="artifact"] {
  height: 100%; min-height: 0; box-sizing: border-box;
}
#canvas .cv-pane[data-pane="document"] > #doc-frame,
#canvas .cv-pane[data-pane="artifact"] > #art-frame {
  flex: 1 1 auto; min-height: 0; height: auto;
}
.art-iframe { width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 10px; background: #0f172a; }
.art-zoom { font-size: 12px; color: var(--muted); min-width: 42px; text-align: center; align-self: center; }
/* ===== I. 프리미엄 UI/UX ===== */
/* 공용 글래스모피즘 모달 */
.modal-ov { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
  background: rgba(15, 18, 28, 0.45); backdrop-filter: blur(4px); }
.modal-ov.hidden { display: none; }
.modal-glass { width: min(440px, 92vw); border-radius: 16px; padding: 18px 20px;
  background: color-mix(in srgb, var(--panel) 82%, transparent); border: 0;
  color: var(--text);   /* 배경(좌측 테마)에 맞춰 글자색 — 타이틀/라벨 가독성 */
  backdrop-filter: blur(18px) saturate(1.2); box-shadow: 0 20px 60px rgba(0,0,0,.35); }
.modal-title { color: var(--text); }
.modal-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
/*   ★모달 머리도 굵기를 낮춘다(제목은 크기로 선다). */
.modal-title { font-size: 16px; font-weight: var(--fw-3, 600); }
/*   ★닫기는 글리프가 아니라 라인 아이콘이다(`modal.js` 가 `<i data-lucide="x">` 를 낸다). */
.modal-x { background: none; border: none; color: var(--muted); cursor: pointer;
  display: inline-flex; align-items: center; }
.modal-form { display: flex; flex-direction: column; gap: 8px; }
.modal-l { font-size: 13px; color: var(--muted); margin-top: 4px; }
/* 모달 폼 행 — 라벨↔입력 가로 정렬 + 글자크기 통일(텍스트영역은 세로 스택) */
.modal-form .mf-row { display: flex; align-items: center; gap: 12px; margin-top: 2px; }
.modal-form .mf-row .modal-l { flex: 0 0 84px; margin: 0; font-size: 13px; text-align: left; }
.modal-form .mf-row input, .modal-form .mf-row select, .modal-form .mf-row textarea { flex: 1 1 auto;
  width: auto; min-width: 0; font-size: 13px; }   /* min-width:0 — flex 최소 고유폭이 카드를 밀어내는 것 방지(모바일 잠금해제 모달) */
.modal-form .mf-row:has(textarea) { flex-direction: column; align-items: stretch; gap: 4px; }
/* 세로 스택(textarea 행)에선 라벨의 가로용 flex-basis(84px)가 '높이 84px'로 작용 — 자동 높이로 복원 */
.modal-form .mf-row:has(textarea) .modal-l { flex: 0 0 auto; }
.modal-form .mf-row[hidden] { display: none; }
.modal-form input, .modal-form textarea { padding: 9px 11px; border: 1px solid var(--border);
  border-radius: 9px; background: var(--panel-2); color: var(--text); font: inherit; }
.modal-form input::placeholder, .modal-form textarea::placeholder { color: var(--muted); }
.modal-form textarea { min-height: 144px; resize: vertical; }   /* 메모 등 내용 입력 50% 확대 */
/* 모달 드롭다운 — 앱 공통 select 룩(테마 패널·커스텀 화살표). 브라우저 기본(클래식) 제거 */
.modal-form select { padding: 9px 34px 9px 11px; border: 1px solid var(--border); border-radius: 9px;
  background-color: var(--panel-2); color: var(--text); font: inherit; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; }
.modal-form select:focus { outline: none; border-color: var(--accent); }
.modal-form .modal-actions { margin-top: 10px; display: flex; justify-content: flex-end; }
/*   ★모달 제출은 **주행동**이라 공용 강조 레시피를 그대로 쓴다. */
.modal-form .modal-actions button { padding: 8px 18px; border-radius: 9px; border: 1px solid transparent; cursor: pointer; font-family: inherit;
  font-weight: var(--fw-3, 600);
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d); }
/* 사이드바 타이틀 행(잠금/추가 폼 등 우측 정렬) — .sb-add 퀵추가 버튼 규칙은 UX8 ②로 제거(미참조) */
.sb-title { display: flex; align-items: center; justify-content: space-between; }
/* ★W-UIX2 ① — 섹션 헤더 아이콘은 **접힘 레일 전용**(펼침 현행 무변 · @901 접힘 규칙이 켠다).
   ★특이도: lucide svg 가 `.ic`·`[data-lucide]`(display:inline-block)를 함께 물어 단일 클래스로는
   순서에서 밀린다 — `.sb-title` 를 앞세워(0,2,0) 그 둘을 이긴다(접힘 규칙 0,3,0 은 이걸 다시 이긴다). */
.sb-title .sb-title-ic { display: none; width: 20px; height: 20px; flex: none; color: var(--muted); }
/* 아이콘 버튼(설정 연동 등) */
.icon-btn { width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text); cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; padding: 0; }
.icon-btn svg { width: 17px; height: 17px; }
.icon-btn:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); }
.icon-btn:disabled { opacity: .45; cursor: default; }
/* 개인화 입력 — 50% 폭 + 설명 우측 표시 (.modal-card input width:100% 보다 우선) */
.set-field { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 12px; }
/* 개인화 입력/드롭다운 폭 = '답변 음성' 선택기와 동일(100%, set-body 380px cap — Phase 34.15) */
#settings-modal .set-field input, #settings-modal .set-field select.set-persona { flex: 1 1 100%; width: 100%; margin-bottom: 0; }
#settings-modal .set-field select.set-persona {
  padding: 7px 14px; border-radius: 8px; border: 1px solid var(--border);   /* 폴리싱 #9 — 슬림 */
  background: var(--panel-2); color: var(--text); font-size: 15px;
}
.set-field .set-hint { flex: 1 1 auto; min-width: 0; font-size: 13px; line-height: 1.45;
  color: var(--muted); white-space: normal; }
/* 보안 비밀번호 입력 — 50% 축소 */
.set-panel[data-panel="security"] input { width: 50%; }
/* 메모 캔버스 — 카드 그리드 */
.memo-head { display: flex; align-items: center; gap: 8px; padding: 6px 0 10px; }
/* 메모 카드 — 상단·우측 정렬(캔버스), 카드별 색상 */
/*   ★T3-e — 메모 카드 규칙(.memo-canvas/.memo-card/.memo-colors/.memo-sw…)을 걷었다.
     쓰는 마크업이 사라졌으니 남기면 `.set-check`·`.tk-add` 처럼 **죽은 CSS** 가 된다
     (T3-a 가 그 둘을 실측으로 확인했다 — 죽은 규칙은 다음 사람에게 거짓 단서다).
     ★`.memo-head` 는 **남긴다**: [내 지식] 패인이 같은 이름을 쓴다. */
/* gantt 팀원 필터 */
.gt-filter { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); padding: 4px 0 8px; }
.gt-filter select { padding: 4px 8px; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); color: var(--text); }
/* 설정 — 모달 폐기 → 우측 캔버스 '⚙️ 설정' 탭으로 이식(DOMAIN_PERSONA_UX_PLAN Step 5).
   .cv-body 가 스크롤을 담당하므로 카드는 패인을 채우고 자체 배경/그림자/중앙정렬 없음. */
.set-in-canvas { width: 100%; }
.set-in-canvas .modal-card { width: 100%; max-width: none; min-height: auto;
  border: none; border-radius: 0; box-shadow: none; background: transparent; padding: 0; }
#settings-modal h3 { font-size: 20px; margin: 2px 0 14px; }
/* 단일 페이지 — 섹션을 구분선으로 순서대로 표시(탭 없음) */
#settings-modal .set-panel { max-width: none; border-top: 1px solid var(--border);
  margin-top: 26px; padding-top: 26px; }
#settings-modal .set-panel:first-of-type { border-top: none; margin-top: 4px; padding-top: 0; }
#settings-modal .set-section-title { font-size: 15px; font-weight: 700; color: var(--text);
  margin: 0 0 14px; letter-spacing: -0.01em; }
/* 회원탈퇴 위험구역 */
.set-danger { margin-top: 28px; padding: 18px; border: 1px solid var(--error);
  border-radius: 12px; background: rgba(248, 113, 113, .06); }
.set-danger-label { color: var(--error); }
.btn-danger { margin-top: 10px; padding: 10px 16px; border: none; border-radius: 8px; cursor: pointer;
  background: var(--error); color: #fff; font-weight: 700; font-size: 14px; }
.btn-danger:hover { filter: brightness(1.08); }
.tk-actions { display: flex; gap: 6px; margin-top: 8px; }
.tk-act {
  font-size: 11.5px; padding: 4px 9px; border-radius: 7px; cursor: pointer;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
}
.tk-act:hover { border-color: var(--accent); color: var(--accent); }
.tk-act.del { color: var(--muted); padding: 2px 7px; }
.tk-act.del:hover { color: var(--error); border-color: var(--error); }

/* 경량 간트 (우 캔버스 '간트' 탭) — 막대 %라 캔버스 폭(드래그)에 맞춰 늘어남 */
.gantt-board { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 100%; }
/* 업무스케줄(간트) — 폭에 맞춘 타임라인. 막대 양끝 드래그=시작/마감, 본체 드래그=진행. */
.gantt { position: relative; }
.gt-head { position: relative; height: 16px; margin-bottom: 4px; border-bottom: 1px solid var(--border); }
.gt-tick { position: absolute; transform: translateX(-50%); font-size: 10px; color: var(--muted); top: 0; }
.gt-body { position: relative; display: flex; flex-direction: column; gap: 9px; padding-top: 6px; }
.gt-today { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--accent); opacity: .75; z-index: 2; pointer-events: none; }
.gt-today::after { content: "오늘"; position: absolute; top: -4px; left: 3px; font-size: 9px; color: var(--accent); white-space: nowrap; }
.gt-row { display: flex; flex-direction: column; gap: 3px; }
.gt-name { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); padding-left: calc(var(--d, 0) * 14px); }
.gt-title {
  flex: 1; min-width: 0; background: none; border: none; color: inherit; font: inherit;
  text-align: left; cursor: pointer; padding: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gt-title:hover { color: var(--accent); }
.gt-name.is-done .gt-title { text-decoration: line-through; color: var(--muted); }
.gt-tree { color: var(--muted); opacity: .55; font-size: 12px; margin-right: -2px; }
/* 프로세스(작업지시서·제품출고·부자재입고 …) — 배지, 폰트는 업무 제목과 동일 크기 */
.gt-proc {
  flex: none; font-size: 13px; padding: 0 6px; border-radius: 5px;
  background: color-mix(in srgb, var(--accent-2) 18%, var(--panel-2)); color: var(--accent-2);
}
.gt-track { position: relative; height: 22px; background: var(--panel-2); border-radius: 6px; }
.gt-bar {
  position: absolute; top: 2px; height: 18px; border-radius: 5px; min-width: 14px;
  display: flex; align-items: center; box-shadow: inset 0 0 0 1px rgba(255,255,255,.08); cursor: pointer; touch-action: none;
}
.gt-due { position: relative; z-index: 1; font-size: 10px; color: rgba(255,255,255,.95); padding: 0 6px; white-space: nowrap; overflow: hidden; pointer-events: none; }
.gt-fill { position: absolute; top: 0; left: 0; bottom: 0; background: rgba(255,255,255,.26); border-radius: 5px 0 0 5px; z-index: 0; pointer-events: none; }
.gt-grip, .gt-grip-l { position: absolute; top: -2px; bottom: -2px; width: 12px; z-index: 2; cursor: ew-resize; touch-action: none; }
.gt-grip { right: -4px; }
.gt-grip-l { left: -4px; }
.gt-grip::after, .gt-grip-l::after {
  content: ""; position: absolute; top: 50%; transform: translateY(-50%);
  width: 3px; height: 62%; background: rgba(255,255,255,.85); border-radius: 2px;
}
.gt-grip::after { right: 4px; } .gt-grip-l::after { left: 4px; }
.gt-bar:hover .gt-grip::after, .gt-bar:hover .gt-grip-l::after { background: #fff; }
body.gt-dragging { user-select: none; cursor: ew-resize; }
.gt-bar.s-todo { background: #3b4d63; }
.gt-bar.s-in_progress { background: var(--accent); }
.gt-bar.s-review { background: #d9a441; }
.gt-bar.s-done { background: #3f7a5a; }
.gt-bar.overdue { background: #b3424f; box-shadow: inset 0 0 0 1px var(--error); }
.gt-legend { display: flex; flex-wrap: wrap; gap: 10px; font-size: 11px; color: var(--muted); padding-top: 6px; border-top: 1px solid var(--border); margin-top: 8px; }
.gt-legend i.lg { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 4px; vertical-align: -1px; }
.lg.s-todo { background: #3b4d63; }
.lg.s-in_progress { background: var(--accent); }
.lg.s-review { background: #d9a441; }
.lg.s-done { background: #3f7a5a; }
.lg.overdue { background: #b3424f; }
/* 업무 락(Phase 13 R-E) */
.task-lock { background: none; border: none; cursor: pointer; font-size: 13px; padding: 2px 4px;
  margin-left: 4px; opacity: .7; border-radius: 6px; }
.task-lock:hover { opacity: 1; background: var(--panel-2); }
.task-lock.unlocked { opacity: 1; }
/* 음성 낭독 인터럽트 안내바(Phase 16 R-B) — 낭독 중 화면 탭으로 끊기 */
.voice-speakbar { position: fixed; left: 50%; bottom: 84px; transform: translateX(-50%) translateY(8px);
  white-space: nowrap;   /* 좁은 화면에서 2줄 꺾임 방지 */
  z-index: 1500; padding: 10px 18px; border-radius: 999px; font-size: 13px; font-family: inherit;
  color: var(--text); background: color-mix(in srgb, var(--accent) 18%, var(--panel, #1e293b));
  border: 1px solid var(--accent); box-shadow: 0 8px 24px rgba(0,0,0,.3);
  opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s; cursor: pointer; }
.voice-speakbar:hover { background: color-mix(in srgb, var(--accent) 28%, var(--panel, #1e293b)); }
.voice-speakbar.show { opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; }
/* 통합 관리자(Phase 15) */
.admin-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.admin-sec-title { font-size: 13px; font-weight: 700; color: var(--text); margin: 14px 0 6px; }
/*   ★계측 판 A — AI 사용량 KPI 줄(관리자 전용). 표는 기존 .admin-table 을 그대로 쓴다(새 기구 0). */
.admin-llm-kpi { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
  padding: 8px 10px; margin-bottom: 6px; font-size: 12.5px; color: var(--muted);
  background: var(--panel-2, transparent); border: 1px solid var(--border); border-radius: 10px; }
/*   ★W-ADM3 ① — 중앙 v2 패인 **안에서만** KPI 줄도 상자를 벗는다. 판을 걷었는데 그 안의
     알약만 패널색으로 남으면 그것이 도리어 떠 보인다(상자 하나를 없애고 하나를 남기는 꼴).
     ★바깥(v1 콘솔)의 같은 클래스는 무접촉이다 — 되돌림 스위치가 옛 화면을 그대로 세워야 한다. */
.adm-card .admin-llm-kpi { background: none; border: 0; border-radius: 0;
  padding: 4px 2px 8px; margin-bottom: 0; }
.admin-llm-kpi b { color: var(--text); font-weight: 700; }
.admin-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.admin-table th, .admin-table td { text-align: left; padding: 7px 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.admin-table th { color: var(--muted); font-weight: 600; font-size: 11.5px; }
.admin-table tr.is-blocked { opacity: .55; }
.adm-sub { color: var(--muted); font-size: 11px; margin-top: 2px; }
/*   ★★W-UIX14-S6-A — 관리자 배지 셋이 **공용 칩**이 됐다. 색은 **뜻**으로 남긴다:
     관리자=강조 · 차단=위험 · 비번없음=주의(hex 상수 셋을 걷고 토큰으로). */
.adm-badge { display: inline-flex; align-items: center; gap: 4px; border: 0;
  border-radius: var(--r-chip); padding: 1px 7px; font-size: 10.5px; font-weight: 400;
  background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted); margin-left: 6px; }
.adm-badge.admin { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.adm-badge.blocked { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
.adm-badge.nopw { color: var(--soon, #b7791f); background: color-mix(in srgb, var(--soon, #b7791f) 12%, transparent); }
.adm-acts { white-space: nowrap; }
/*   ★관리자 버튼이 공용 보조 버튼의 결이 됐다(호출부 무접촉). */
.adm-btn { padding: 7px 14px; border: 1px solid var(--hairline); border-radius: 8px;
  cursor: pointer; font-size: 13px; font-weight: 400; font-family: inherit;
  background: transparent; color: var(--muted); margin: 0 2px; }
.adm-btn:hover { border-color: var(--accent); color: var(--accent); }
.adm-btn.danger:hover { border-color: var(--danger); color: var(--danger); }
.admin-feedback { display: flex; flex-direction: column; gap: 8px; }
.adm-fb { border: 1px solid var(--border); border-radius: 9px; padding: 9px 11px; background: var(--panel-2); }
.adm-fb-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.adm-fb-cat { display: inline-flex; align-items: center; gap: 4px; border: 0;
  border-radius: var(--r-chip); padding: 1px 7px; font-size: 10.5px; font-weight: 400;
  background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted); color: var(--accent-2); }
.adm-fb-meta { margin-left: auto; font-size: 11px; color: var(--muted); }
.adm-fb-body { margin-top: 6px; font-size: 12.5px; color: var(--muted); white-space: pre-wrap; }
/* W-N8Q 5 — 조회형 워크플로 행. 버튼줄은 감싸고, 시험 호출 결과는 자기 칸에서만 스크롤한다. */
.adm-n8nq-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.adm-n8nq-out { margin-top: 8px; }
.adm-n8nq-pre { max-height: 220px; overflow: auto; white-space: pre-wrap; word-break: break-all;
  background: var(--panel, #f6f7f9); border-radius: 6px; padding: 8px; font-size: 11.5px; margin: 4px 0 8px; }

/* ══ ★★W-ADM1(2026-08-30) — 관리자 콘솔 v2 ══════════════════════════════════
   중앙 = 카드 그리드(읽기 전용 현황) / 우측 = 그 항목의 상세·조작.
   ★새 부품을 만들지 않았다 — 표는 `.admin-table`, KPI 줄은 `.admin-llm-kpi`,
     버튼·필드는 `.fx-btn`/`.fx-form` 그대로다(§14-1-5 유령 클래스 금지).
     여기 있는 것은 **자리(배치)뿐**이다. */
.adm-console { display: flex; flex-direction: column; height: 100%; min-height: 0; gap: 10px; }
.adm-bar { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
/*   ★★W-ADM2 — **탭 한 줄 + 전체 폭 한 판**(종전 2열 카드 그리드를 대신한다).
     넷을 나란히 두면 표마다 폭이 반쪽이라 열이 눌렸다 — 지금은 활성 탭이 폭을 다 쓴다. */
.adm-dash { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex;
  flex-direction: column; gap: 10px; padding-bottom: 12px; }
/*   ★탭 줄은 접지 않고 **가로로 흐른다**(모바일에서 두 줄로 쌓이면 표가 밀린다). */
.adm-tabs { flex: 0 0 auto; flex-wrap: nowrap; overflow-x: auto; gap: 4px;
  scrollbar-width: thin; -webkit-overflow-scrolling: touch; }
.adm-tabs .cv-tab { flex: 0 0 auto; white-space: nowrap; }
/*   ★★W-ADM3 ①(2026-09-02 사장님) — **판을 걷는다.** 표가 패널색 상자 안에 앉아 있어
     탭 줄과 표 사이에 상자 하나가 더 있는 것처럼 읽혔다. 구분은 **표 자신의 줄과 hover**
     로 충분하다(그 둘은 이미 있다 — 새 어휘 0).
     ★배경만 걷고 테두리를 남기면 **속이 빈 상자**가 되어 더 눈에 띈다 — 상자를 이루는 셋
       (바탕·테두리·모서리)을 함께 걷고, 좌우 여백도 0 으로 두어 표가 탭 줄과 **같은 세로선**
       에서 시작하게 한다.
     ★이 규칙은 **중앙 v2 패인 전용**이다. 우측 상세(`.adm-detail`)와 옛 콘솔(v1)은 무접촉 —
       `ADMIN_CONSOLE_V2=false` 로 되돌리면 옛 화면이 **그대로** 서야 한다(§13-12). */
.adm-card { padding: 0; min-width: 0; }
/*   활성 탭의 본문 — 폭을 다 쓰고, 표가 길면 자기 안에서만 세로로 흐른다. */
.adm-pane { flex: 1 1 auto; min-height: 0; }
.adm-card-h { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.adm-card-h h3 { margin: 0; font-size: 14px; font-weight: 700; color: var(--text); }
/*   ★표는 자기 칸에서만 가로로 흐른다 — 화면 전체가 가로 스크롤되면 그건 결함이다. */
.adm-card-b { overflow-x: auto; }
.adm-card .admin-table tbody tr[data-adm] { cursor: pointer; }
.adm-card .admin-table tbody tr[data-adm]:hover { background: var(--panel, rgba(127, 127, 127, .08)); }
.adm-src { margin: 6px 0 0; }

/*   우측 상세 — 행을 눌렀을 때만 뜬다(빈 채로 열지 않는다). */
.adm-detail { display: flex; flex-direction: column; gap: 4px; }
.adm-d-h { display: flex; align-items: center; gap: 10px; }
.adm-d-h h3 { margin: 0; font-size: 15px; font-weight: 700; color: var(--text); flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; }
.adm-d-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0; }
/*   ★필드 높이·곡률은 `.fx-form` 이 준다 — 여기서는 라벨과의 세로 배치만 정한다(§14-1-2).
     ★★`flex: 1 1 220px` 를 여기 두면 안 된다 — 부모(`.adm-detail`)가 **세로 flex** 라
       그 값이 *"세로로 늘어나라"* 가 되어 필드마다 빈 칸이 크게 벌어진다(실브라우저 1회가
       잡은 자리 · 검사로는 안 잡힌다). 늘어나야 하는 것은 **가로 줄 안에 있을 때뿐**이다. */
.adm-f { display: flex; flex-direction: column; gap: 4px; margin: 8px 0; min-width: 0; flex: 0 0 auto; }
.adm-d-acts .adm-f { flex: 1 1 220px; margin: 0; }
.adm-f > span { font-size: 12px; color: var(--muted); }
.adm-detail .admin-table th { width: 92px; }

/* 구글 SSO(Phase 13 R-A) */
.sso-block { margin-top: 12px; }
.sso-divider { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; margin: 6px 0 10px; }
.sso-divider::before, .sso-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.google-sso { width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px;
  background: #fff; color: #3c4043; border: 1px solid #dadce0; border-radius: 8px; padding: 10px;
  font-size: 14px; font-weight: 600; cursor: pointer; }
.google-sso:hover { background: #f7f8f8; }
.google-sso .g-ic { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border-radius: 50%; background: conic-gradient(#ea4335 0 25%, #fbbc05 0 50%, #34a853 0 75%, #4285f4 0);
  color: #fff; font-weight: 800; font-size: 11px; }
/* 업무 다이어그램(Phase 13 R-D) — 계층 Node-Link */
.dg-wrap { position: relative; }
.dg-svg { position: absolute; left: 0; top: 0; pointer-events: none; overflow: visible; }
.dg-edge { fill: none; stroke: var(--border); stroke-width: 1.6; opacity: .8; }
.dg-node { position: absolute; box-sizing: border-box;
  /*   ★★W-UIX18-B1 — `--surface` 는 **런타임 전용**이다(theme.js 가 섹션에 내려 준다) —
       `:root` 에는 없어서 폴백 없이 쓰면 **선언이 통째로 무효**가 되고 이 노드가
       투명으로 떨어진다(실브라우저 실측으로 잡았다 · W-UIX18 ⑦ 의 `--fg` 와 같은 부류).
       ⇒ 이 파일의 다른 `--surface` 자리와 **같은 모양**으로 받치되, 받치는 값은
       생 hex 가 아니라 **선언된 토큰**이다(그래야 테마가 따라온다). */
  background: var(--surface, var(--panel));
  border: 1px solid var(--border); border-left: 4px solid #3b4d63; border-radius: 9px;
  padding: 8px 10px; box-shadow: 0 2px 8px rgba(0,0,0,.18); display: flex; flex-direction: column; gap: 5px; }
.dg-node.s-in_progress { border-left-color: var(--accent); }
.dg-node.s-review { border-left-color: #d9a441; }
.dg-node.s-done { border-left-color: #3f7a5a; }
.dg-node.overdue { border-left-color: #b3424f; }
.dg-node.is-done .dg-title { text-decoration: line-through; color: var(--muted); }
.dg-node { cursor: grab; }                 /* 카드 드래그=이동 */
.dg-node.dragging { cursor: grabbing; opacity: .85; z-index: 50;
  box-shadow: 0 12px 30px rgba(0,0,0,.4); }
.dg-node.drop-target { outline: 2px dashed var(--accent); outline-offset: 1px; }
.dg-title { cursor: pointer; }             /* 제목은 클릭(대화 열기) */
.dg-top { display: flex; align-items: center; gap: 6px; }
.dg-title { background: none; border: none; padding: 0; color: var(--text); font-weight: 600;
  font-size: 13px; cursor: pointer; text-align: left; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; flex: 1; }
.dg-title:hover { color: var(--accent); }
.dg-sched { font-size: 10px; padding: 1px 6px; border-radius: 8px; flex-shrink: 0; color: #fff; }
.dg-sched.one { background: #4a5a73; }
.dg-sched.rec { background: #5a78b0; }
.dg-sched.cont { background: #9a6fb0; }
.dg-status { margin-left: auto; flex-shrink: 0; font-size: 10px; font-weight: 700; padding: 1px 7px;
  border-radius: 8px; color: #fff; }
.dg-status.todo { background: #3b4d63; }
.dg-status.prog { background: #2f7ab0; }
.dg-status.rev  { background: #d9a441; color: #1a1a1a; }
.dg-status.done { background: #3f7a5a; }
.dg-status.over { background: #b3424f; }
.dg-status.soon { background: #d97a2a; }
.dg-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; font-size: 11px; color: var(--muted); }
.dg-proc { background: var(--panel-2); padding: 0 5px; border-radius: 6px; }
.dg-vis, .dg-deleg { font-size: 10px; padding: 0 5px; border-radius: 6px; background: var(--panel-2); color: var(--muted); }
.dg-vis.team { color: #7fb0e0; } .dg-vis.company { color: #d9a441; }
.dg-gauge { position: relative; height: 14px; border-radius: 7px; background: var(--panel-2);
  overflow: hidden; cursor: ew-resize; touch-action: none; }
/* 세부업무 완료율 자동 계산 게이지 — 드래그 불가(수동 아님) */
.dg-gauge.dg-auto { cursor: default; }
.dg-gauge.dg-auto .dg-fill { opacity: .72; }
.dg-fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--accent); opacity: .55; }
.dg-pct { position: absolute; right: 6px; top: 0; line-height: 14px; font-size: 10px; color: var(--text); }
.dg-dragging { user-select: none; }
.dg-legend { display: flex; flex-wrap: wrap; gap: 10px; font-size: 11px; color: var(--muted);
  padding-top: 6px; border-top: 1px solid var(--border); margin-top: auto; position: sticky; left: 0; bottom: 0;
  background: var(--panel); }
.dg-hint { margin-left: auto; }
.gt-undated-h { font-size: 12.5px; font-weight: 600; color: var(--muted); margin: 12px 0 4px; }
.gt-track2 { padding: 2px 0 4px; }
.gt-schedule {
  font-size: 11.5px; padding: 4px 10px; border-radius: 7px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--accent);
}
.gt-schedule:hover { border-color: var(--accent); }
.gt-hint { color: var(--muted); }

/* 차트를 캔버스로 보냈을 때 말풍선 안내 */
.bot-routed {
  margin-top: 12px; font-size: 12.5px; color: var(--muted);
  background: var(--panel-2); border: 1px dashed var(--border); border-radius: 8px; padding: 8px 10px;
}

/* ===== 대화창 마이크로 카드 (Phase 25.1 — 전표 요약 / CRM Preview / 지표 위젯) ===== */
/* ★W-UIX1 ⑥(2026-09-06 · 사장님) — 카드 스타일 정돈: **채운 배경(클래식) 걷고 테두리+옅은 그림자**.
   배경 var(--panel-2) 를 걷어 대화 흐름에 카드가 얹힌 듯 가볍게(테두리로 경계 · 그림자로 살짝 뜸).
   토큰 기반이라 라이트/다크 자동 적응 · cc-chip 등 내부 요소는 제 배경 유지(구분 필요). */
/* ★★W-UIX13-A ②⑦(2026-09-10 · 구성안 §8) — **확인 카드는 잿빛 상자 하나**다:
   테두리를 걷고(그림자 한 단계) 옅은 면으로 대화 흐름 위에 얹는다(장치 하나면 충분하다). */
/* ★W-UIX14-S1 — 회색 채움을 걷고 **표면 토큰**으로(구분은 링 1px + 그림자가 한다). */
.chat-card {
  margin-top: var(--sp-3); border: 0; border-radius: var(--r-card);
  background: var(--surface, #FFFFFF);
  padding: var(--sp-3) 14px; max-width: 420px;
  box-shadow: 0 0 0 1px rgba(23,27,34,.07), var(--wk-shadow, 0 1px 2px rgba(0,0,0,.10), 0 3px 10px rgba(0,0,0,.06));
}
.chat-card .cc-head { font-size: 14px; margin-bottom: 8px; }
.chat-card .cc-head b { color: var(--text); }
.chat-card .cc-body { display: flex; flex-direction: column; gap: 4px; }
.chat-card .cc-row { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; }
.chat-card .cc-k { color: var(--muted); flex: none; }
.chat-card .cc-v { color: var(--text); font-weight: 600; text-align: right; word-break: break-all; }
.chat-card .cc-recips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.chat-card .cc-chip {
  font-size: 11.5px; color: var(--text); background: var(--panel);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px;
}
.chat-card .cc-chip.cc-more { color: var(--muted); }
.chat-card .cc-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
/* ★★★W-UIX14-S3(2026-09-11 · 사장님) — **카드 버튼도 공용 버튼 한 벌**이다.
   ★마크업의 옛 클래스(`.cc-btn`·`.cc-save`…)는 **그대로 둔다** — 24종을 손으로 고치는 대신
     같은 블록에 **별칭으로 나열**해 같은 옷을 입힌다(배선 무접촉 · 두 벌이 안 생긴다).
   ★규칙(릴리 결재 Q1): **주행동 하나는 `.btn-accent`, 그 밖은 맨 끝의 `.btn-sub`** ·
     주행동이 되돌리기 어려운 것이면 **첫째 + 위험색**(`.btn-danger`).
     ★예외 표(그 자리가 곧 주행동이라 첫째다): `mail-action` 의 삭제 넷
       (`mail_rule_del`·`mail_delcat`·`kn_trash`·`nas_trash`) · crm 최종 일괄 발송. */
.chat-card .cc-btn {
  padding: 7px 14px; border-radius: 8px; border: 1px solid var(--hairline);
  background: transparent; color: var(--muted); cursor: pointer;
  font-size: 13px; font-weight: 400; font-family: inherit;
}
.chat-card .cc-btn:hover { border-color: var(--accent); color: var(--accent); }
/*   1차 액션(저장·발송·상세) = 주행동 한 자리. */
.chat-card .cc-save, .chat-card .cc-approve, .chat-card .cc-detail {
  border: 1px solid transparent; font-weight: var(--fw-3);
  background: var(--btn-bg, var(--accent, #2f81f7)); color: var(--btn-fg, #fff);
}
.chat-card .cc-save:hover, .chat-card .cc-approve:hover, .chat-card .cc-detail:hover {
  filter: brightness(1.06); border-color: transparent; color: var(--btn-fg, #fff); }
/*   ★과금 발송은 **되돌리기 어려운 주행동**이다 — 첫째 자리에 위험색으로 선다.
     ★상수 `#e0533d` 는 걷었다(테마가 안 따라온다) — `--danger` 가 그 색의 주인이다. */
.chat-card-crm_dispatch .cc-approve {
  background: var(--danger); color: #fff; border-color: transparent; }
.chat-card .cc-btn:disabled { opacity: .5; cursor: default; }
/*   ★라벨 앞 라인 아이콘(`UIKit.lineify` 가 끼운다) — 글자와 **한 줄**로 선다. */
.chat-card .cc-btn { display: inline-flex; align-items: center; gap: 6px; }
.chat-card .cc-btn .ic, .chat-card .cc-btn svg { width: 15px; height: 15px; flex: none; }
.chat-card .cc-head .ic, .chat-card .cc-head svg { width: 15px; height: 15px; flex: none; }
.chat-card .cc-head { display: flex; align-items: center; gap: 6px; }
/*   ★★★W-UIX14-F8 ①(2026-09-12 · 사장님 실기 · 구성안 목업) — **확인 카드 소형 변형**.
     의도 확인 · 자동화 등록 확인 · 업무 전환 확인은 **같은 일**을 한다(사람에게 한 번 묻는다)
     ⇒ 모양도 하나다: **머리 한 줄**(무슨 일인지 + 요청/대상 한 줄) · **캡션 한 줄**(요약) ·
     **글자 링크 액션**(알약 버튼 0 — 확인 카드는 대화의 곁말이지 폼이 아니다).
   ★표면·그림자는 공용 카드(`.chat-card`)가 주고, 여기서는 **결만** 정한다(두 벌 금지). */
.chat-card.cc-confirm { max-width: 460px; }
.chat-card.cc-confirm .cc-head { flex-wrap: wrap; gap: 6px; margin-bottom: 0;
  font-size: var(--fs-ti, 15px); font-weight: var(--fw-2, 500); }
/*   ★요청 한 줄은 **잿빛 캡션**이다 — 사람이 쓴 말이라 화면이 크게 되뇌지 않는다. */
.chat-card.cc-confirm .cc-ask { color: var(--wk-caption, var(--muted));
  font-weight: var(--fw-1, 400); font-size: var(--fs-meta, 13px); min-width: 0;
  overflow-wrap: anywhere; }
.chat-card.cc-confirm .cc-sub { margin-top: 6px; font-size: var(--fs-cap, 12px);
  color: var(--wk-caption, var(--muted)); line-height: 1.55; }
.chat-card.cc-confirm .cc-note { margin-top: 8px; font-size: var(--fs-cap, 12px);
  color: var(--wk-caption, var(--muted)); }
.chat-card.cc-confirm .cc-actions { margin-top: 10px; gap: 16px; align-items: center; }
.chat-card.cc-confirm .cc-actions .wk-link { display: inline-flex; align-items: center;
  gap: 5px; font-size: var(--fs-meta, 13px); }
.chat-card.cc-confirm .cc-actions .wk-link .ic,
.chat-card.cc-confirm .cc-actions .wk-link svg { width: 15px; height: 15px; flex: none; }
/*   ★주행동 하나만 강조색이고 나머지는 잿빛이다(S3 의 버튼 규칙을 글자 링크로 옮겨 적는다). */
.chat-card.cc-confirm .cc-go { font-weight: var(--fw-2, 500); }
.chat-card.cc-confirm .cc-alt { color: var(--muted); }
.chat-card.cc-confirm .cc-alt:hover { color: var(--text); }
/*   ★W-UIX14-S3 — 상태 줄은 **칩 한 겹**이다(이모지는 `lineify` 가 라인 아이콘으로 바꾼다).
     ★잿빛이 기본이고 색을 드는 것은 **끝났다/못 했다** 둘뿐이다(색이 많으면 색이 말을 잃는다).
     ★색 상수는 걷었다 — `--wk-live`·`--danger` 가 그 색의 주인이라 테마를 따라온다. */
.chat-card .cc-status {
  margin-top: 9px; font-size: var(--fs-cap); color: var(--muted);
  display: inline-flex; align-items: center; gap: 5px;
  border-radius: var(--r-chip); padding: 2px 9px;
  background: var(--surface-2, rgba(148,163,184,.15)); }
.chat-card .cc-status .ic, .chat-card .cc-status svg { width: 13px; height: 13px; flex: none; }
.chat-card .cc-status.ok { color: var(--wk-live, #17A34A);
  background: color-mix(in srgb, var(--wk-live, #17A34A) 12%, transparent); }
.chat-card .cc-status.err { color: var(--danger, #d9534f);
  background: color-mix(in srgb, var(--danger, #d9534f) 12%, transparent); }
/* 복합기 관리자 자격 카드(W-PSK2) — 두 칸(아이디·비밀번호) 한 줄 · 좁은 폭에선 세로 */
.chat-card.pc-credential .pcc-form { display: flex; gap: 8px; margin: 8px 0 2px; flex-wrap: wrap; }
.chat-card.pc-credential .pcc-form .fx-input { flex: 1 1 140px; min-width: 0; }
/* SVG 도식 호스트(Phase 26.3) — DOMPurify 정화된 SVG 를 데스크/대시보드에 맞춰 표시 */
.svg-host { width: 100%; padding: 10px; box-sizing: border-box; color: var(--text); overflow: auto; }
.svg-host svg { max-width: 100%; height: auto; display: block; margin: 0 auto; }

/* 스킬 자산화 제안(Phase 25.3) — 점선 테두리로 '권유'임을 구분 */
/*   ★W-UIX14-S3 — **스샷이 잡았다**: 카드 여섯 중 이것만 회색이었다(`--panel` 채움 + 점선).
     사장님 신고(회색 카드 0)의 남은 한 자리다 — 표면은 공용 레시피가 주고, *"제안"* 이라는
     뜻은 **점선 링**이 말한다(채움색으로 말하지 않는다). */
.chat-card.skill-suggest { max-width: 460px; border: 0;
  box-shadow: 0 0 0 1px var(--hairline), var(--wk-shadow, 0 1px 2px rgba(23,27,34,.05)); }
/* ★★W-PC5-B5 — `.ss-text` 는 오랫동안 `.chat-card.skill-suggest` **밑에만** 있었다.
   그래서 그 클래스를 빌려 쓴 카드들(자격·기기·판정)의 본문이 **기본 크기로 떨어졌다** —
   `grep` 엔 잡히고 화면엔 안 닿는 그 병(W-PC2-B1 · pc-scan-wait 이 이미 값을 치렀다).
   ⇒ 카드 층에 **바탕 한 줄**을 둔다. 더 좁은 아래 규칙은 그대로 이긴다(캐스케이드 무변). */
.chat-card .ss-text { font-size: 13px; color: var(--text); }
.chat-card.skill-suggest .ss-text { font-size: 13px; color: var(--text); }
.chat-card .ss-dismiss { background: transparent; color: var(--muted); }

/* ===== 위젯형 홈 대시보드 (WORKSPACE_UI_PLAN · M2) ===== */
.dashboard { display: flex; flex-direction: column; gap: 16px; padding: 12px 8px 24px; }
.dash-head h2 { margin: 8px 0 2px; font-size: 24px; }
.dash-sub { margin: 0; color: var(--muted); font-size: 14px; }
.dash-card { background: var(--surface, #FFFFFF); border: 1px solid var(--border); border-radius: 14px; padding: 16px 18px; }
.dc-title {
  font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em;
  margin-bottom: 12px; display: flex; align-items: center; justify-content: space-between;
}
.dc-go { font-size: 11px; color: var(--accent); text-transform: none; letter-spacing: 0; }
.dash-empty { color: var(--muted); font-size: 13px; margin: 4px 0; }

/* 오늘 브리핑 — AI 선제(능동형)의 자리 */
.dash-brief {
  display: flex; gap: 14px; align-items: flex-start;
  background: linear-gradient(135deg, rgba(56,189,248,.10), rgba(34,211,238,.05));
  border-color: var(--accent);
}
.brief-avatar {
  flex: none; width: 44px; height: 44px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700;
  /* 배경 톤에서 파생된 차분한 솔리드(테마와 조화) — 밝은/어두운 배경 모두 어울림 */
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d);
}
.brief-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.brief-msg { font-size: 16px; margin: 4px 0 6px; line-height: 1.5; }
.brief-msg .warn { color: var(--danger); }
.brief-msg .soon { color: var(--soon); }
.brief-hint { font-size: 12px; color: var(--muted); }

.dash-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
/*  ★★W-UIX7 ③(2026-09-08 · 사장님) — 장부(경영현황) 대시보드만 **3열**이고 폭은
    **플래너 캘린더와 같다**(`--chat-bar-max` · 그 규칙을 새로 만들지 않고 그대로 쓴다).
    ★홈 대시보드(`#dash-host` 밖의 `.dash-grid`)는 **무접촉** — 자리로 좁힌다. */
#bizdash-host, #tax-host { max-width: var(--chat-bar-max); margin-inline: auto; }
/*  ★W-UIX9 ③(2026-09-08 · 사장님) — 이커머스 대시보드도 **같은 폭**이다
    (`.tv-sub[data-tv=ecom]` 안의 그리드 — 그 화면은 host id 없이 캔버스 프레임에 그린다). */
.tv-sub[data-tv="ecom"] .b2b-grid { max-width: var(--chat-bar-max); margin-inline: auto; }
/*  ★W-UIX8 ④(2026-09-08 · 사장님) — 세무 요약도 **장부 대시보드와 같은 고정 폭**이다
    (중앙 100% 로 늘어나던 것 · 같은 토큰을 쓰므로 둘이 어긋날 수 없다). */
#bizdash-host .dash-grid, #tax-host .dash-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1100px) { #bizdash-host .dash-grid, #tax-host .dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { #bizdash-host .dash-grid, #tax-host .dash-grid { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .dash-grid { grid-template-columns: 1fr; } }

/* 내 업무 카드 — 클릭 가능 */
.dash-tasks { cursor: pointer; transition: border-color .15s ease; }
.dash-tasks:hover { border-color: var(--accent); }
.dash-stats { display: flex; gap: 8px; }
.dash-stat { flex: 1; text-align: center; background: var(--surface, #FFFFFF); border: 1px solid var(--border); border-radius: 10px; padding: 12px 6px; }
.stat-num { display: block; font-size: 26px; font-weight: 800; line-height: 1.1; }
.stat-num.accent { color: var(--accent); }
.stat-num.warn { color: var(--danger); }
.stat-num.done { color: var(--muted); }
.stat-label { font-size: 11px; color: var(--muted); }

/* 오늘 일정 리스트 */
.dash-list { display: flex; flex-direction: column; gap: 8px; }
.dl-row { display: flex; gap: 10px; align-items: baseline; font-size: 14px; }
.dl-time { flex: none; width: 48px; color: var(--accent-2); font-size: 13px; }
.dl-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/*  W-PC5-B2(2026-09-05) — 설정 → PC 연동 목록: **어느 PC 인지 알아볼 재료**.
    ★★`.dl-row` 는 **대시보드 일정 목록과 같은 이름**이라, 여기 규칙은 전부 `#dl-devices` 안으로
      범위를 좁힌다(그 이름을 건드리면 남의 화면이 조용히 흔들린다 · Phase 92 가 값을 치른 규율).
    ★"모름"은 흐리게 쓰되 **지우지 않는다** — 못 받은 칸이 있다는 사실 자체가 값이다
      (옛 위젯은 호스트명·LAN IP 를 안 보낸다 · 그것은 결함이 아니라 사실이다). */
/*  ★W-PC5-B3 동승 L0(사장님 스크린샷) — **두 줄**: 1줄 이름 + 오른쪽 끝 버튼 · 2줄 값들.
    종전에는 값 줄만 `flex: 1 1 100%` 라 **버튼이 셋째 줄로 따로 떨어져** 지저분했다.
    ★좁은 화면(≤426px)에서는 버튼이 **아래로 떨어지되 값 줄과 겹치지 않는다**(줄바꿈만 허용). */
#dl-devices .dl-row { flex-wrap: wrap; row-gap: 4px; }
#dl-devices .dl-name { font-weight: var(--fw-3, 600); flex: 1 1 auto; min-width: 0; }
#dl-devices .dl-btns { flex: 0 0 auto; margin-left: auto; display: flex; gap: 6px; }
#dl-devices .dl-when { color: var(--muted, #6b7280); font-size: 12px; flex: 1 1 100%; order: 3; }
@media (max-width: 426px) {
  /*  ★좁으면 이름이 한 줄을 다 쓰고 버튼이 그 아래에 선다(값 줄은 `order: 3` 이라 맨 아래). */
  #dl-devices .dl-name { flex: 1 1 100%; }
  #dl-devices .dl-btns { margin-left: 0; order: 2; }
}
.dl-on { color: #16a34a; font-size: 11px; line-height: 1; }
.dl-host { color: var(--muted, #6b7280); font-weight: 400; font-size: 12px; }
.dl-unknown { color: var(--muted, #9ca3af); font-style: italic; }

/* 빠른 시작 칩 */
.dash-suggests { display: flex; flex-wrap: wrap; gap: 8px; }
.dash-chip {
  padding: 8px 13px; border-radius: 20px; cursor: pointer; font-size: 13px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border); text-align: left;
}
.dash-chip:hover { border-color: var(--accent); color: var(--accent); }

/* 좁은 화면(<1100): 캔버스는 우측에서 슬라이드되는 오버레이 시트 */
@media (max-width: 1099px) {
  .canvas {
    position: fixed; right: 0; top: 0; bottom: 0; z-index: 60;
    width: min(440px, 92vw); transform: translateX(100%);
    transition: transform .22s ease; box-shadow: 0 0 50px rgba(0,0,0,.5);
    height: 100vh; height: 100dvh;
  }
  .app-wrap.canvas-on .canvas { width: min(440px, 92vw); transform: none; }
  .cv-inner { width: 100%; }
}

.badge {
  background: var(--panel-2); border: 1px solid var(--border); color: var(--accent-2);
  padding: 5px 12px; border-radius: 20px; font-size: 13px; font-weight: 600;
}
.ghost { background: transparent; border: 1px solid var(--hairline); color: var(--muted);
  padding: 7px 14px; border-radius: 8px; cursor: pointer;
  font-size: 13px; font-weight: 400; font-family: inherit; }
.ghost:hover { color: var(--text); }

/* 본문 — 중앙 정렬 + 가독 폭 제한 (Claude 웹 느낌의 핵심)
   내부 overflow 없음 — 콘텐츠가 자라면 '페이지'가 스크롤된다 */
/* ★대화 영역 기준 폭은 **여기 한 곳**에서 정한다 — 도구 뷰(tv-wide)가 폭 제한을 풀어도
   입력바는 이 값을 그대로 쓰기 때문에(아래 `.chat-main.tv-wide > .chat-input`), 두 곳에
   같은 숫자를 적어 두면 한 쪽만 바뀌는 날이 온다. */
/* ★2026-08-02(사장님 지시) — `--chat-input-inset` 신설: **입력바의 좌우 여백**이자
   **하단 대화 시트의 좌우 여백**이다. 사장님 지적은 *"대화창 폭을 입력창 폭으로 맞춰줘"* 였고,
   실측하니 어긋난 것은 입력 **컨테이너**(시트와 이미 같았다)가 아니라 **보이는 둥근 입력 박스**
   였다 — 그 차이의 정체가 바로 이 여백이다.
   ★시트는 간편장부만이 아니라 메일·이커머스·플래너·자산에서도 뜬다. 숫자를 시트에 박으면
   다른 섹션에서 어긋나므로 **값이 아니라 원천을 공유**한다(`--chat-max`·`--chat-pad` 와 같은 자리). */
/* ★★★W-CV2 ④(2026-09-01 사장님 지시 · 릴리 결재) — **입력창은 도크다.**
   지시: *"상단 여백 0 · 좌우 여백 0 · 도크처럼 떠 있게."*
   ★실측이 원인을 갈랐다: 사장님이 보신 "뜬 여백"은 접힘 바(`.ai-sheet.ais-collapsed`)와의
     **간격이 아니라**(그것은 이미 0 이었다) **입력바 자신의 `padding-top: 12px`** 였다.
   ★`--chat-input-inset` 를 0 으로 두면 `.ai-sheet` 도 함께 전폭이 된다 — 그 변수는 2026-08-02
     사장님 지시로 **일부러 한 원천을 공유**한 것이라(입력 박스와 시트의 좌우 끝을 맞추려고),
     쪼개지 않고 그대로 0 으로 간다(릴리 결재 A). 둘은 여전히 정렬돼 있고, 함께 전폭이 된다. */
.chat-main { --chat-max: 820px; --chat-pad: 16px; --chat-input-inset: 0px;
  --chat-bar-max: calc(var(--chat-max) - var(--chat-pad) * 2);
  flex: 1; display: flex; flex-direction: column; max-width: var(--chat-max); width: 100%;
  margin: 0 auto; padding: var(--chat-pad); }
.messages { flex: 1; padding: 8px; display: flex; flex-direction: column; gap: 16px; }
/* ★★W-WR8-H2 ⑤(2026-09-02 사장님) — 진행 중 대화가 **입력 도크에 가리지 않게**.
   ★실측이 원인을 갈랐다: 도크(`.chat-input`)는 `position: sticky` 이고 **흐름 안에** 있어
     맨 아래에서는 가리지 않는다(문서 바닥에서 도크 위 433 · 마지막 줄 아래 428 — 안 겹친다).
     사장님이 보신 겹침은 **말풍선이 자라는 동안 아무도 스크롤하지 않아서** 생긴 것이다.
     → 진짜 처방은 `chat.js` 의 `afterPaint → scrollToBottom()` 이다.
   ★그래도 자리를 예약하는 이유: 스태거(150ms)로 줄이 서는 동안 스크롤이 **한 프레임 늦으면**
     그 순간 마지막 줄이 도크 밑에 들어간다. 진행 중에만 도크 높이만큼 아래를 비워 둔다.
   ★상시가 아니라 **진행 중에만**인 이유: 도크가 이미 흐름에서 제 높이를 갖고 있어, 늘 예약하면
     끝난 뒤 마지막 답변과 도크 사이에 **빈 띠**가 영구히 남는다(§4-3 은 *상시 존재하는 것만*
     자리를 예약하라고 말한다 — 이 겹침은 상시가 아니다).
   ★높이는 `--chat-dock-h` 하나에서 나온다(`chat.js` 가 실측해 넣는다 · 접힘 바 포함). */
body[data-ct-live] .messages { padding-bottom: var(--chat-dock-h, 96px); }

/* 메시지 버블 */
/* ★★2026-08-07 사장님 신고 ③④ — 글자 **한 단계** 작게 · 질문 카드 **높이 축소**.
   ★실측(수리 전): 글자 16px · 줄간 25.6px(1.6) · 패딩 14/16 · 질문 카드 높이 **54px**.
   ★★줄이는 것은 **여백과 글자 크기**이지 **내용이 아니다** — `max-width`·`white-space`·
   줄바꿈 규칙은 손대지 않는다(잘림 금지). 값은 토큰에서 나온다(하드코딩 0 · 한 곳에서 고친다).
   ★줄간은 1.6 → 1.5 로만 낮춘다(1.4 이하는 한글에서 답답해진다 — 가독 유지). */
.msg { max-width: 90%; padding: var(--msg-pad-y) var(--msg-pad-x); border-radius: 14px;
  font-size: var(--msg-fs); line-height: 1.5; }
/* 질문 말풍선 — 쨍한 강조색 대신 톤온톤(폴리싱 #5). color-mix 미지원 시 panel-2 폴백 */
/*   ★W-UIX14-F3 ⑥(사장님 실기) — 질문 말풍선이 아직 진했다. 강조색 16% → **6%** 로 여리게
     하고 바탕도 표면으로 올린다(글자는 잉크 그대로). 다크는 토큰이 알아서 따라온다. */
/*   ★★W-UIX14-F8 ③(2026-09-12 · 사장님 실기) — **굵기는 걷고 면은 한 단계 진하게.**
     F3 ⑥ 이 16% → 6% 로 내렸는데 이번엔 *"너무 여려 보인다"* 는 반대쪽 신고가 왔다 ⇒
     **11%**(둘 사이) · 글자는 잉크 그대로 400. 자리는 여전히 **한 곳**이라 중앙 대화와
     플로팅 시트가 같은 말풍선을 쓴다(두 벌로 적지 않는다 · 다크는 토큰이 따라온다). */
.msg.user { align-self: flex-end; font-weight: var(--fw-1, 400); color: var(--text);
  background: var(--panel-2);
  background: color-mix(in srgb, var(--accent) 11%, var(--surface, #FFFFFF)); }
/* ★★W-UIX13-A ⑦(2026-09-10 · 구성안 §8) — **세 겹을 한 겹으로.**
   사용자 말 = 채움 하나(테두리 0) · AI 말 = **배경도 테두리도 0**(글자와 얼굴로 구분한다).
   종전에는 말풍선 테두리 + 연한 채움 + 인용 박스가 한 화면에 함께 서서 같은 뜻을 세 번 말했다. */
.msg.bot { align-self: flex-start; background: none; border: 0; width: 100%; max-width: 100%;
  padding-left: 2px; padding-right: 2px; }
/* ★★W-WR8-H2 ④ + **H3 정정**(2026-09-02 사장님) — 사용자 카드·답변 카드도 **한 모서리만
   각지다**(말풍선 꼬리 — 크루 대화의 `.wr-msg` 가 이미 쓰는 그 규칙을 큰 카드에도 그대로 준다).
   ★★자리는 **아래 모서리**다: 사용자는 **우하단** · 답변은 **좌하단**(H3 정정).
     H2 는 위 모서리에 뒀는데, 대화 카드에서 꼬리는 **말이 끝나는 쪽**에 달린다 —
     카드가 세로로 길수록 위 모서리의 각은 꼬리가 아니라 *잘린 귀퉁이*로 읽힌다.
   ★크루 대화 말풍선(`.wr-msg`)은 **무접촉**이다 — 거기 꼬리는 **배지 쪽**(좌상단)이고,
     배지가 줄 맨 위에 서 있으므로 그 자리가 맞다. 같은 어휘가 표면에 따라 다른 모서리에
     붙는 것은 규칙이 둘이어서가 아니라 **가리키는 대상이 다르기 때문**이다.
   ★기존 라운드 규칙(`--radius` 14)과 충돌하지 않는다 — **한 귀퉁이만** 덮어쓴다. */
.msg.user { border-bottom-right-radius: 4px; }
.msg.bot { border-bottom-left-radius: 4px; }
.msg.bot.error { border-color: var(--error); }

.bot-summary { white-space: pre-wrap; }
/* ★W-UIX13-A ⑦ — 답 문장의 **인라인 마크업**(굵게·코드)은 이제 기호가 아니라 **모양**이다. */
.bot-summary strong { font-weight: var(--fw-3); }
.bot-summary code { font-family: var(--font-mono); font-size: .94em;
  background: color-mix(in srgb, var(--text) 8%, transparent); border-radius: 5px; padding: 1px 5px; }
/* 적응형 UI(Phase 42) — structured(보고형): 본문을 음영 카드로 구획해 표/차트 가독성↑ */
/* ★보고형(structured) 본문 — 인용 박스의 **테두리는 걷고** 잿빛 면 하나로 남긴다(한 겹). */
.msg.bot.ui-structured .bot-summary {
  background: color-mix(in srgb, var(--text) 5%, transparent); border: 0;
  border-radius: var(--r-card); padding: var(--sp-3) 14px;
}
/* artifact(기획/문서형): 본문은 짧은 안내로, 실제 산출물은 우측 캔버스로 분할(강조 좌측 바) */
.msg.bot.ui-artifact { border-left: 3px solid #7c3aed; }
.meta-line { font-size: 11px; color: var(--muted); margin-bottom: 8px; }
.meta-line .tag {   /* ★W-UIX13-A ② — 칩도 테두리 0(면 하나로 뜬다) */
  display: inline-block; background: color-mix(in srgb, var(--text) 7%, transparent);
  padding: 2px 8px; border-radius: var(--r-chip); margin-right: 6px; border: 0;
}
.chart-box { margin-top: 14px; background: var(--surface, #FFFFFF); border-radius: 10px; padding: 12px; }

/* 출처 패널 — 항목당 '한 줄 말줄임'(긴 링크가 본문보다 길어지는 것 방지), 클릭=복사 */
.sources { margin-top: 14px; border-top: 1px dashed var(--border); padding-top: 10px; }
.sources h4 { margin: 0 0 8px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.sources-hint { font-weight: 400; text-transform: none; letter-spacing: 0; opacity: .7; }
/* ★★W-WR8-H2 ⑦(2026-09-02 사장님) — 상자(테두리 카드)를 걷고 **줄 항목**으로.
   출처 3장이 답변보다 큰 덩어리가 되어 본문을 밀어냈다(사장님 스크린샷).
   ★걷는 것은 **무게**(테두리·바닥색·패딩)뿐이다 — 표식(웹/DOC/SQL)·제목·클릭=복사는 그대로다.
   ★누를 수 있음은 남긴다(호버에 바닥만 옅게) — "눌릴 수 있는가까지가 부르는 곳"(W-NH3). */
.source-item {
  font-size: 12px; padding: 3px 4px; border-radius: 6px;
  display: flex; align-items: center; gap: 7px;
  white-space: nowrap; overflow: hidden; cursor: pointer;
}
.source-item:hover { background: var(--panel-2); }
.source-item .stype { font-weight: 700; flex: none; }
.source-item .stype.sql { color: var(--accent); }
.source-item .stype.doc { color: var(--ok); }
.source-item .sref {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  color: var(--accent-2);
}
.source-item code { color: var(--accent-2); word-break: break-all; } /* 구형 마크업 호환 */
/* 근거/출처 3건 초과분 접힘 토글 */
.sources-rest[hidden] { display: none; }
.sources-more {
  font-size: 12px; font-weight: 600; color: var(--muted); cursor: pointer;
  background: none; border: 0; padding: 4px 2px; margin-top: 2px;
  font-family: inherit; letter-spacing: .02em;
}
.sources-more:hover { color: var(--accent); }

.typing { color: var(--muted); font-style: italic; }

/* ★★진행 표시 = **애니메이션 점 + 현재 단계 한 줄**(사장님 결정 2026-08-15 · W3 §5).
   종전의 단계 누적 로그(.progress-live/.progress-done/.pt-*)는 **걷어냈다** — 단계별 상세는
   이제 워크룸이 정본 표면이고, 채팅에는 답변만 남는다.
   ★색은 전부 fx/기본 토큰이다(§5-3 — 걷어낸 옛 블록은 #0b1220·#94a3b8 처럼 하드코딩이었고
   라이트 테마에서 제 색을 못 냈다). 새로 쓰는 이 줄부터 토큰만 쓴다. */
/* ══ ★★★W-WR8 — 채팅 안 **크루 대화 블록**(2026-09-01 사장님 결재 부록 B) ═══════════
   정본 표면이 여기다. 말풍선 마크업은 워크룸과 **같은 것**(`.wr-row`)을 쓴다 — 문장 생성기도
   조립부도 한 벌이라(`crewtalk.js`) 얼굴·이름·색·표정이 저절로 같다(결재 1·7항).
   ★여기서 정하는 것은 **자리와 폭**뿐이다(새 어휘 0). */
.msg.bot.crewtalk { background: none; border: none; padding: 2px 2px 4px; }
.crewtalk .ct-rows:empty { display: none; }
/* ★폭 상한 해제(릴리 확정) — 워크룸은 창 폭 420 이라 300px 상한이 맞지만, 채팅 열에서는
   **다른 말풍선과 같은 규칙**(비율)을 따른다. 같은 말풍선이 자리에 따라 두 폭인 것은
   자리에 맞추는 것이지 두 벌이 아니다. */
.crewtalk .ct-rows .wr-col { max-width: 72%; }
.crewtalk .ct-rows .wr-row { margin-bottom: 7px; }
/* ══ ★★W-WR8-H2 ③(2026-09-02 사장님) — 진행 중에는 **최근 5줄**만 세운다 ═══════════
   넘치는 줄은 위에서 하나씩 **접혀 나간다**(지우지 않는다 — 끝나고 펼치면 전부 보여야 한다).
   ★높이는 js 가 실측해 인라인으로 넣는다(`max-height: auto → 0` 은 애니가 안 걸린다).
     여기서 상수를 박으면 그보다 큰 말풍선(카드가 든 줄)이 잘린다.
   ★전이는 **접혀 나가는 줄에만** 건다(`.wr-rolling`) — 모든 줄에 걸면 처음 서는 줄까지
     애니를 타서 등장이 굼떠 보인다. */
.crewtalk .ct-rows .wr-row.wr-rolling {
  overflow: hidden;
  transition: max-height .32s ease, opacity .26s ease, margin-bottom .32s ease;
}
.crewtalk .ct-rows .wr-row.wr-rolled { opacity: 0; margin-bottom: 0; }
/* ★펼치면(접힘 줄 클릭) **전부** 보인다 — 인라인 `max-height:0` 을 여기서 덮는다.
   되돌리는 자바스크립트가 0 인 이유다(상태를 두 곳에서 갖지 않는다). */
.crewtalk.ct-open .ct-rows .wr-row {
  max-height: none !important; opacity: 1 !important; margin-bottom: 7px !important;
}
@media (prefers-reduced-motion: reduce) {
  .crewtalk .ct-rows .wr-row.wr-rolling { transition: none; }
}
/* 진행 한 줄 — 크루가 말을 시작하면 물러난다(같은 사건을 두 표면이 말하지 않는다) */
.crewtalk .ct-line { display: flex; align-items: center; gap: 8px;
  font-size: var(--fx-fs-sm); color: var(--muted); padding: 2px 2px 0; }
.crewtalk.ct-talking .ct-line, .crewtalk.ct-folded .ct-line { display: none; }
/* ★접힘 한 줄 — **사실만**(참여 배지+이름 · 걸린 시간). 설명 문구는 넣지 않는다(결재 3).
   줄 전체가 클릭 영역이고, 누르면 다시 펼쳐진다. */
.crewtalk.ct-folded .ct-rows { display: none; }
.crewtalk.ct-folded.ct-open .ct-rows { display: block; }
.ct-fold { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
  cursor: pointer; padding: 3px 4px; border-radius: 8px; font-size: 12px; color: var(--muted); }
.ct-fold.hidden { display: none; }
.ct-fold:hover { background: var(--panel-2); color: var(--text); }
.ct-who { display: inline-flex; align-items: center; gap: 4px; }
.ct-badge { line-height: 0; flex: none; }
.ct-badge svg { display: block; }
.ct-ms { margin-left: auto; font-variant-numeric: tabular-nums; }
/* ★펼쳐 놓은 동안에는 접힘 줄이 '닫기'가 된다 — 같은 줄이 두 뜻을 갖되 상태가 눈에 보인다 */
.crewtalk.ct-open .ct-fold { background: var(--panel-2); color: var(--text); }

.msg.bot.progress-line {
  display: flex; align-items: center; gap: 8px;
  background: none; border: none; padding: 4px 2px;
  font-size: var(--fx-fs-sm); color: var(--muted);
}
.pl-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 점 세 개가 물결친다 — ★진행 중일 때만 존재하는 요소라 '이벤트 없으면 안 움직인다'와 어긋나지 않는다 */
.pl-dots { display: inline-flex; gap: 3px; flex: none; }
.pl-dots::before, .pl-dots::after, .pl-label::before { content: none; }
.pl-dots i, .msg.bot.progress-line .pl-dots::after { content: ""; }
.pl-dots {
  width: 22px; height: 6px;
  background-image: radial-gradient(circle 3px at 3px 3px, var(--accent) 99%, transparent 0),
                    radial-gradient(circle 3px at 11px 3px, var(--accent) 99%, transparent 0),
                    radial-gradient(circle 3px at 19px 3px, var(--accent) 99%, transparent 0);
  animation: pl-wave 1.1s ease-in-out infinite;
}
@keyframes pl-wave { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
/* 완료 후에도 남는 경우 = ★워크룸을 꺼 두신 분(결재 ⓖ 가) — 점은 멈추고 줄만 남는다 */
.msg.bot.progress-line.done .pl-dots { animation: none; opacity: .45; }
.msg.bot.progress-line.failed { color: var(--error); }
.msg.bot.progress-line.failed .pl-dots { animation: none; opacity: .5; }
/* [과정 보기] — 답변 아래 작은 링크(워크룸이 켜져 있을 때만 붙는다) */
@media (prefers-reduced-motion: reduce) { .pl-dots { animation: none; } }

/* 엑셀 다운로드 버튼 */
.export-line { margin-top: 12px; }
.export-btn {
  padding: 7px 14px; border-radius: 8px; cursor: pointer; font-size: 12px;
  background: var(--panel-2); color: var(--accent-2); border: 1px solid var(--border);
}
.export-btn:hover { border-color: var(--accent); color: var(--accent); }

/* (걷어냄) 답변 후 접힌 "과정 보기" `<details>` — W3 3단계에서 채팅의 완료 요약줄을
   없애면서 부르는 곳이 0이 됐다. 과정은 워크룸에서 본다(★[과정 보기] 링크도 W8 에서 걷었다). */

/* 대화 맥락 패널 (2층 메모리) */
.ctx-panel { margin-top: 12px; border-top: 1px dashed var(--border); padding-top: 10px; font-size: 12px; }
.ctx-line { color: var(--muted); margin-bottom: 6px; }
.ctx-board-title { color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-right: 8px; }
.ctx-board { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.ctx-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border-radius: 20px; font-size: 11px;
  border: 1px solid var(--border); background: var(--panel-2);
}
.ctx-chip.used { color: var(--accent-2); border-color: var(--accent); }
.ctx-chip.board { color: var(--text); }
.ctx-del {
  border: none; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 11px; line-height: 1; padding: 0;
}
.ctx-del:hover { color: var(--accent); }

/* 제안/입력 */
.suggestions { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 8px; }
.suggest {
  background: var(--surface, #FFFFFF); border: 1px solid var(--border); color: var(--text);
  padding: 8px 12px; border-radius: 20px; font-size: 13px; cursor: pointer;
}
.suggest:hover { border-color: var(--accent); }
/* 입력창 — 페이지 스크롤 중에도 하단 고정(sticky) */
.chat-input {
  /* ★★W-CV3-H1(사장님 신고 "아이콘이 너무 하단") — 아래 여백을 **변수 하나**로 뽑는다.
     마이크·스피커는 `.chat-input-field` 의 **형제**라 `position:absolute` 의 포함 블록이
     **바(this)** 다 — 실측: 바 68 = 필드 52 + 아래 여백 16 이라 `top:50%` 가 필드 중심보다
     정확히 **여백의 절반(8px)** 만큼 아래였다. 값을 두 곳에 적으면 언젠가 한쪽만 바뀌므로
     **여기 한 곳**에서 내고 아이콘 규칙이 그것을 읽는다(차이는 필드가 몇 줄이든 pb/2 로 일정). */
  --chat-bar-pb: 16px;
  display: flex; gap: 10px; padding: 0 var(--chat-input-inset) var(--chat-bar-pb);
  position: sticky; bottom: 0; z-index: 20;
  /* ★W-CV2 ④ — 판 배경을 걷는다. 떠 보이는 것은 **필드 자신**이다(아래). */
  background: transparent;
}
/* ★W-CV2 ④ — 도크 본체. 종전에는 보이는 둥근 박스가 `input/textarea` 였고 `.chat-input-field`
   는 투명한 껍데기였다 — 그래서 첨부(＋)·마이크·스피커가 **박스 밖**에 떠 있는 것처럼 보였다.
   이제 껍데기가 도크가 되고 그 안의 입력은 투명해진다(안에 든 것이 한 몸으로 보인다). */
/*   ★★W-UIX14-F7(2026-09-12 · 사장님 실기 · 릴리 판정) — **입력 필드도 표면으로 올린다.**
     F6 은 필드의 채움을 `--panel-2` 로 뒀는데(파인 자리 규칙), 실화면에서 그 회색
     채움 + 짙은 테두리가 사장님이 말씀하신 *"너무 회색"* 의 **몸통**이었다.
   ★★이 자리는 그 규칙의 **명시 예외**다: 대화 입력 필드는 파인 칸이 아니라 **화면의
     주인공**이다(사람이 제일 먼저 보고 제일 자주 쓴다). 그래서 표면(`--surface`)으로
     올리되, *"여기를 누른다"* 는 말은 **hairline 링 1px + 아주 옅은 안쪽 그림자**가
     대신한다(채움으로 파는 대신 결로 판다).
   ★포커스는 **강조색 링**이 말한다(테두리를 두껍게 하면 1px 떨린다).
   ★값은 전부 토큰에서 나온다 — 다크는 theme.js 가 섹션 밝기에서 파생해 따라온다. */
.chat-input-field {
  background: var(--surface, #FFFFFF); border: 0;
  border-radius: 12px;
  box-shadow: 0 0 0 1px var(--hairline),
              inset 0 1px 2px color-mix(in srgb, var(--text, #171B24) 7%, transparent),
              var(--wk-shadow);
}
.chat-input-field:focus-within {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent),
              inset 0 1px 2px color-mix(in srgb, var(--text, #171B24) 5%, transparent),
              var(--wk-shadow);
}
.chat-input-field input::placeholder,
.chat-input-field textarea::placeholder { color: var(--muted); }
/* ★★W-UIX19(2026-09-13 · 사장님 — *"활성화하면 테두리가 검은색"*) — **포커스 링은 파스텔 하나다.**
   §0 실브라우저 실측: 포커스 전에는 `outline-style: none` 인데 포커스가 들어오면
   **브라우저 기본 링**이 선다(`outline: auto` · `outline-color: rgb(16,16,16)` — ★라이트·다크
   **둘 다 검정**이라 다크에서 특히 튄다). 그 위에 필드의 강조색 링이 함께 그려져 **두 겹**이었다.
   ⇒ 안쪽 입력칸의 **기본 링은 걷고**, 포커스 표시는 필드가 이미 그리는 **강조색 45% 링**이 맡는다
     (그 링은 `:focus-within` 이라 **진짜 포커스일 때만** 선다 = 표시가 사라지지 않는다).
   ★★그냥 `outline: none` 으로 끝내지 않는다: 필드 **밖**에 맨몸으로 서는 입력칸(폴백 마크업)은
     가릴 부모가 없으므로 **제 링을 직접** 그린다(`:focus-visible` · 접근성).
   ★색은 토큰에서 섞는다 — 다크는 theme.js 가 섹션 밝기에서 파생해 따라온다(:root 파생 토큰 0). */
.chat-input-field :is(input, textarea):focus,
.chat-input-field :is(input, textarea):focus-visible { outline: none; }
.chat-input > :is(input, textarea):focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
  outline-offset: 2px;
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
.chat-input input, .chat-input textarea {
  flex: 1; padding: 13px 16px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--text); font-size: 15px;
}
/*   ★★★W-UIX14-F8 ②(2026-09-12 · 사장님 실기 — *"대화창이 진한 회색 바탕에 두꺼운 라인
     테두리"*) — **뿌리는 순서였다.** 이 두 규칙은 특이도가 같은데(0,2,1) 위의 일반 규칙이
     **뒤에** 적혀 있어, 필드 안쪽 칸을 투명으로 만들려던 규칙이 **지고 있었다** —
     그래서 흰 필드 안에 `--panel-2` 회색 상자가 1px 테두리를 두르고 앉아 있었다
     (다크 실측 rgb(42,50,68) · border 1px rgba(255,255,255,.12) · 788×51).
   ★W-CV2 ④ 가 세운 계약(*"떠 보이는 것은 필드다"*)은 처음부터 이 순서에 져 있었다.
     자리를 **뒤로** 옮겨 그 계약을 실제로 이기게 한다(값은 한 줄도 안 바꿨다). */
.chat-input-field input, .chat-input-field textarea {
  background: transparent; border: none;
}
/* 멀티라인 입력(2026-07-05) — 폭 초과 자동 줄바꿈 + Shift+Enter 수동 줄바꿈(chat.js).
   내용만큼 자동 성장(JS _growQuery, 최대 ~5줄) 후 내부 스크롤. 수동 리사이즈 금지. */
.chat-input textarea {
  resize: none; overflow-y: auto; line-height: 1.5;
  min-height: 48px; max-height: 140px; font-family: inherit;
}
.chat-input button {
  width: auto; padding: 0 24px;
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d);
}
/* 마이크·스피커 버튼 — 입력필드 1줄 높이(48px = textarea min-height) 고정.
   textarea 가 줄바꿈으로 성장해도 버튼은 안 늘어나고 입력창 아랫줄에 붙는다(flex-end). */
/* ★W-CV3-H1 — `align-self: flex-end` 를 걷었다: 두 아이콘은 **모든 폭에서** `position:absolute`
   라(≥761 · ≤760 각각의 절) 흐름 밖이고, 그래서 이 선언은 **한 번도 값을 한 적이 없다**(죽은 배선).
   높이도 아래 절들이 34/36px 로 덮으므로 여기서는 자리만 남긴다. */
.chat-input .icon-btn { height: 48px; }

/* ★마이크·스피커를 **입력창 안으로**(사장님 지시 2026-07-29 · 데스크톱).
   그동안 데스크톱에서만 둘이 입력창 **밖에** 별도 사각 버튼으로 서 있어서, 같은 화면인데
   모바일(이미 입력창 내부 아이콘)과 모양이 달랐다. **모바일 규칙을 그대로 데스크톱에 편다**
   — 새 기구를 만들지 않는다(≤760px 블록의 것과 같은 형태·같은 자리).
   ★`border`/`background` 를 **transparent 로 두되 지우지는 않는다** — 켜짐(.on)·청취 중
   (.listening)·대기 신호(body.voice-working)가 그 두 속성으로 상태를 칠하기 때문이다
   (border 를 0 으로 없애면 그 상태들의 테두리 색이 조용히 죽는다). */
@media (min-width: 761px) {
  .chat-input #mic-btn, .chat-input #speak-btn {
    /* ★W-CV3-H1 — 포함 블록은 **바**이고 바에는 아래 여백만 있다 → 바 중심은 필드 중심보다
       `pb/2` 아래다. 그만큼 올려 **필드 세로 중앙**에 고정한다(줄 수가 늘어도 차이는 일정). */
    position: absolute; top: calc(50% - var(--chat-bar-pb) / 2); transform: translateY(-50%);
    width: 34px; height: 34px; padding: 0; border-color: transparent;
    background: transparent; color: var(--muted); border-radius: 50%;
  }
  .chat-input #speak-btn { right: 12px; }
  .chat-input #mic-btn { right: 52px; }
  .chat-input #mic-btn:hover, .chat-input #speak-btn:hover { background: var(--panel); }
  /* 아이콘 두 개가 앉을 자리 확보 — 긴 문장이 아이콘 밑으로 들어가지 않게 */
  .chat-input-field input, .chat-input-field textarea { padding-right: 92px; }
}

/* 파일 첨부(+) — 입력창 '내부' 왼쪽 아이콘(별도 박스가 아니라 인풋 안에 오버레이) */
.chat-input-field { position: relative; flex: 1; display: flex; }
.chat-input-field input, .chat-input-field textarea { padding-left: 44px; }   /* + 아이콘 자리 확보 */
/* type=search 전환(비밀번호 자동완성 오분류 차단)에 따른 웹킷 기본 ✕/돋보기 장식 제거 */
#query::-webkit-search-cancel-button, #query::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
/* Ghost Text 넛지(Phase 73 Step 1) — 다음 예상 지시 제안 placeholder 는 액센트 톤(정적 안내와 구분) */
#query.has-ghost::placeholder { color: var(--accent, #6b7cff); opacity: .72; font-style: italic; }
/* 사규 각인 제안 칩(Phase 73 Step 2) — 섹션 배지(절대 규칙/선호 포맷/처리 순서) */
.rule-suggest .rs-sec { margin: 4px 0 2px; font-size: 12px; color: var(--muted); }
.chat-input-field .attach-inline {
  position: absolute; left: 7px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; padding: 0; margin: 0; border: none; border-radius: 8px;
  background: transparent; color: var(--muted); cursor: pointer;
  font-size: 24px; font-weight: 400; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color .12s, background .12s;
}
.chat-input-field .attach-inline:hover { color: var(--accent); background: var(--panel); }

/* ===== 음성 인터페이스 — 받아쓰기(마이크) / 음성답변 토글(스피커) ===== */
.icon-btn {
  width: 46px; padding: 0; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 1;
  border-radius: 10px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--muted); cursor: pointer;
  transition: color .12s, border-color .12s, background .12s;
}
.icon-btn:hover { border-color: var(--accent); color: var(--accent); }

/* 마이크 — 대기(텍스트 입력) 상태: 차분한 윤곽선(muted).
   인식 중(녹음) 상태: 빨강 배경 채움 + 펄스 → 대기와 확연히 다른 표시 */
#mic-btn.listening {
  color: #fff; border-color: #ef4444; background: #ef4444;
  animation: mic-pulse 1.1s ease-in-out infinite;
}
@keyframes mic-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, .5); }
  50%      { box-shadow: 0 0 0 7px rgba(239, 68, 68, 0); }
}

/* 인식 중 파형 막대(5개) — 마이크 윤곽선과 형태 자체가 달라 즉시 구분된다 */
.eq { display: inline-flex; align-items: center; gap: 2px; height: 18px; }
.eq i {
  width: 3px; height: 6px; border-radius: 2px; background: currentColor;
  animation: eq-bounce .9s ease-in-out infinite;
}
.eq i:nth-child(2) { animation-delay: .15s; }
.eq i:nth-child(3) { animation-delay: .30s; }
.eq i:nth-child(4) { animation-delay: .45s; }
.eq i:nth-child(5) { animation-delay: .60s; }
@keyframes eq-bounce {
  0%, 100% { height: 5px; }
  50%      { height: 17px; }
}

/* 스피커 — 음성답변 켜짐: accent 채움 + 흰색 아이콘(어두운 배경서 확실히 보이게),
   꺼짐은 muted 윤곽선 */
#speak-btn.on {
  border-color: var(--btn-bg, var(--accent)); color: var(--btn-fg, #fff); background: var(--btn-bg, var(--accent));
}

/* 마이크 = 음성 대화 모드 ON(비청취 시): 채움으로 '모드 켜짐'을 표시(중앙 테마 파생색) */
#mic-btn.on {
  border-color: var(--btn-bg, var(--accent)); color: var(--btn-fg, #fff); background: var(--btn-bg, var(--accent));
}
/* 음성 대화 모드일 때 입력칸 — 음성 중심임을 시각적으로 표시 */
.voice-mode .chat-input input, .voice-mode .chat-input textarea {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--panel-2));
}
/* 비언어 대기 신호(2026-07-21) — 도구(웹검색 등) 실행 중: 마이크를 청색 펄스로(listening 적색과 구분).
   ★말(추임새) 없이 화면으로만 '검색/작업 중'을 알린다(입력창 '🔎 …중…' 텍스트가 1순위·이건 보강).
   gh variable VOICE_WAIT_SIGNAL=0 으로 즉시 끔(서버 ready.wait_signal→FE). aria-live 미사용(SR 방해 방지). */
body.voice-working #mic-btn {
  border-color: var(--accent); color: #fff; background: var(--accent);
  animation: mic-work 1.2s ease-in-out infinite;
}
@keyframes mic-work {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 0%, transparent); }
}

/* 답변 음성 선택기 — 사이드바 하단 */
/* 답변 음성 — 설정 모달 안의 선택 필드 */
.set-voice select {
  width: 100%; margin-top: 6px; padding: 9px 11px; font-size: 14px;
  border-radius: 8px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--text); cursor: pointer;
}

/* 음성 침묵 게이지 — 인식 중 표시. 채워질수록 곧 전송, 말하면 0으로 리셋 */
.voice-gauge { padding: 6px 10px 2px; display: flex; flex-direction: column; gap: 5px; }
.voice-gauge .vg-track {
  height: 5px; border-radius: 4px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border);
}
.voice-gauge .vg-fill {
  height: 100%; width: 0%; border-radius: 4px;
  background: var(--accent);
  transition: width .12s linear, background .2s;
}
/* 임계 근접(곧 전송) — 주황 경고 */
.voice-gauge.near .vg-fill { background: #f59e0b; }
.voice-gauge .vg-hint { font-size: 12px; color: var(--muted); }
.voice-gauge.near .vg-hint { color: #f59e0b; }

/* 모바일: 입력창 = 하단 고정바(바텀내비 스타일).
   ※ 반드시 위의 .chat-input(sticky)·.voice-gauge 기본 규칙 '뒤'에 둘 것 —
   같은 특이도라 앞에 두면 cascade 에서 기본 규칙이 이겨 무효화된다(실측). */
@media (max-width: 900px) {
  /* 답변이 길어져도 입력창은 항상 화면 하단에 떠 있고, 답변은 그 위로 스크롤.
     (sticky 는 모바일 주소창/키보드 변동에서 밀리는 실측 — fixed 로 격상) */
  .chat-input {
    position: fixed; left: 0; right: 0; bottom: 0;
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border);
  }
  /* ★2026-08-02 — 좁은 화면에서는 입력바가 **뷰포트 고정 전폭**이고 시트도(≤760) 전폭이다.
     둘이 같은 흐름에 있지 않아 좌우 여백으로 맞출 대상이 아니므로 **원천을 0 으로 돌린다.**
     ★시트 규칙을 따로 덮어쓰지 않는 이유: 푸는 자리를 늘리지 않는다 — 값 하나만 바꾸면
     시트도 입력바도 함께 따라온다(정본 규칙 4-4 = 모바일은 전폭 바텀시트). */
  .chat-main { --chat-input-inset: 0px; }
  .chat-main { padding-bottom: 86px; }  /* 고정바에 마지막 답변이 가리지 않게 */
  /* 침묵 게이지도 고정바 바로 위에 띄움(본문 흐름에 두면 바에 가려짐) */
  .voice-gauge {
    position: fixed; left: 0; right: 0;
    bottom: calc(64px + env(safe-area-inset-bottom));
    z-index: 50; background: var(--bg); padding: 6px 12px; margin: 0;
  }
}

/* 음성 일시 알림(마이크 권한 거부 등) — 대화창을 더럽히지 않는 토스트 */
.voice-toast {
  position: fixed; left: 50%; bottom: 92px; transform: translateX(-50%);
  z-index: 200; max-width: calc(100vw - 32px);
  padding: 10px 16px; border-radius: 10px;
  background: rgba(2, 6, 23, .92); color: var(--text);
  border: 1px solid var(--border); font-size: 13px;
  box-shadow: 0 8px 30px rgba(0,0,0,.45);
}

/* ===== 상단바 소개 링크 ===== */
.brand-box { display: flex; align-items: baseline; gap: 14px; }
.back-link { color: var(--muted); font-size: 13px; text-decoration: none; }
.back-link:hover { color: var(--accent); }

/* ===== 의견 보내기 모달 ===== */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(2, 6, 23, .55);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
}
.modal-card {
  background: var(--surface, #FFFFFF);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  border: 0; border-radius: var(--radius);
  padding: 26px 28px; width: 440px; max-width: calc(100vw - 32px);
  box-shadow: 0 20px 60px rgba(0,0,0,.5);

  /*   ★W-UIX14-S6-B — 모달 넷의 판도 공용 표면이다(테두리 0) · `theme.js MODAL_SELS` 는 무접촉. */
}
.modal-card h3 { margin: 0 0 4px; font-size: 18px; }
.modal-sub { color: var(--muted); font-size: 13px; margin: 0 0 16px; }
.modal-card select, .modal-card input, .modal-card textarea {
  width: 100%; padding: 11px 13px; margin-bottom: 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
  font-size: 14px; font-family: inherit; resize: vertical;
}
/* 폴리싱 #9 — 설정 탭(캔버스) 폼 컨트롤 슬림화: 상하 패딩·간격 축소 */
/* ★스위치는 제외한다(86.7). 이 규칙은 ID 선택자라 `input.switch` 를 이기고,
   `margin-bottom:8px` 가 붙으면 `align-items:center` 가 **마진 박스**를 가운데 맞추어
   스위치가 글자보다 **4px 위로** 뜨다(계측: 중심차 -4.0px). 입력칸용 규칙이므로
   스위치에는 애초 해당되지 않는 것이 맞다. */
#settings-modal input:not(.switch), #settings-modal select, #settings-modal textarea {
  padding-top: 7px; padding-bottom: 7px; margin-bottom: 8px;
}
/* ★86.6 — 브라우저 자동입력 배경. 크롬은 자동입력된 칸에 **내부 흰색을 강제**해
   테마 배경(var(--panel-2))을 덮는다 — 그래서 [아이디]만 하얀게 보였다(그 칸만 채워졌다).
   background 로는 덮이지 않아 inset box-shadow 로 가린다(표준 기법). 아이디 하나가 아니라
   **자동입력되는 모든 칸**이 같은 원인이므로 전역으로 건다(로그인 폼 포함). */
input:-webkit-autofill, input:-webkit-autofill:hover,
input:-webkit-autofill:focus, input:-webkit-autofill:active {
  -webkit-box-shadow: inset 0 0 0 1000px var(--panel-2) !important;
  -webkit-text-fill-color: var(--text) !important;
  caret-color: var(--text);
  transition: background-color 100000s ease-in-out 0s;   /* 지연 전환으로 재칠하기 방지 */
}
/* ★86.7(사장님) — 설정 모달의 담기 버튼들을 [＋ 파일 추가](`.cal-today`) 결으로 통일한다.
   새 스타일을 만들지 않고 **그 버튼과 같은 레시피**를 쓴다.
   ★★W-UIX14-S4 A — 기준 버튼이 바뀌었으므로 **여기도 따라간다**: `.cal-today` 가 이제
     공용 보조 버튼(`.btn-sub` · 채움 없음 · hairline)이라, 옛 `--panel-2` 채움을 남겨 두면
     *"같은 결"* 이라는 이 규칙의 뜻이 그 자리에서 거짓이 된다(회색 채움도 되살아난다).
   ★설정 모달 안으로만 좁힌다 — `.modal-actions` 는 다른 모달도 쓰므로 전역으로 건드리면
   지시하지 않은 화면까지 바뀐다. */
#settings-modal .modal-actions button[type=submit],
#settings-modal .modal-actions .btn-accent {
  background: transparent; border: 1px solid var(--hairline); color: var(--muted);
  border-radius: 7px; padding: 5px 11px; font-size: 13px; font-weight: 400; filter: none;
}
#settings-modal .modal-actions button[type=submit]:hover,
#settings-modal .modal-actions .btn-accent:hover { border-color: var(--accent); color: var(--accent); }
/*   ★W-UIX14-S1-B1 — 보조 버튼도 그 자리에서는 형제와 **같은 크기**다(채움만 없다). */
#settings-modal .modal-actions .btn-sub { border-radius: 7px; padding: 5px 11px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 4px; }
/* ★86.7 — `.btn-accent` 에 **기본 형상**을 준다. 지금까지는 `.modal-actions` 안에서만
   규칙이 있어, 그 밖에 놓인 버튼([Gmail 연결] 등)은 **브라우저 기본 흰 버튼**으로
   남아 테마와 겉돌았다(계측 rgb(240,240,240)). 색은 토큰만 쓴다. */
.btn-accent { padding: 7px 14px; border: 1px solid transparent; border-radius: 8px; cursor: pointer;
  font-size: 13px; font-weight: 600; font-family: inherit;
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d); }
.btn-accent:hover { filter: brightness(1.06); }
.btn-accent:disabled { opacity: .55; cursor: not-allowed; filter: none; }
/* ★★W-UIX14-S1-B1(2026-09-11 · 사장님 실기) — **공용 보조 버튼 `.btn-sub`**.
   클래스 없는 `<button>` 은 브라우저 기본 **각진 회색 버튼**으로 남아 테마와 겉돈다
   ([취소]가 그랬다). 주 버튼과 **같은 모양**이되 채움이 없다 — 되돌리는 손잡이는
   앞에 나서지 않는다([취소]·[닫기] 부류).
   ★새 버튼은 공용 라운드 클래스만 쓴다. 클래스 없는 버튼이 새로 생기는 길은
     ratchet R6 이 막는다(수 기준선 · 양방향). */
/*   ★★W-UIX14-S4 A — 플래너·캔버스 크롬의 보조 버튼 **열넷**(`.cal-nav`/`.cal-today`)이
     이 레시피의 별칭이 됐다. 호출부 14 자리는 **무접촉**이다(마크업을 안 고친다) —
     이름이 캘린더의 것이지만 실제로 쓰는 자리는 문서·지식·데스크·감사·관리자 크롬이고,
     전부 *"주행동이 아닌 보조 조작"* 이라 한 모양이 맞다(§0-① 실측). */
.btn-sub, .cal-nav, .cal-today { padding: 7px 14px; border: 1px solid var(--hairline); border-radius: 8px;
  cursor: pointer; font-size: 13px; font-weight: 400; font-family: inherit;
  background: transparent; color: var(--muted); }
.btn-sub:hover, .cal-nav:hover, .cal-today:hover { border-color: var(--accent); color: var(--accent); }
.btn-sub:disabled, .cal-nav:disabled, .cal-today:disabled { opacity: .55; cursor: not-allowed; }
/*   ★W-UIX14-S4 A — 되돌리기 어려운 **보조** 손잡이(삭제). 앞에 나서지 않되 색으로 말한다. */
.btn-sub.danger { color: var(--danger, #d64545); }
.btn-sub.danger:hover { border-color: var(--danger, #d64545); color: var(--danger, #d64545); }
.modal-actions button[type=submit], .modal-actions .btn-accent {
  width: auto; padding: 9px 22px; border: none; border-radius: 8px; cursor: pointer;
  /* 테마 적용 시 theme.js 가 --btn-bg/--btn-fg(배경의 톤 파생)로 덮어써 튀지 않게 — 미설정 시 기본 그라데이션 */
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d); font-weight: 700; font-size: 14px;
}
.fb-result { font-size: 13px; color: var(--ok); margin: 12px 0 0; }

/* (★UX8 ② — 사이드바 '오늘 일정' 위젯 .sch-* 규칙 제거: schedule.js 위젯 삭제로 미참조.
   플래너 월간 캘린더는 .cal-* 별도 규칙.) */

/* 좌측 '캘린더' 제목 — 월간 캔버스 탭 열기 */
.sb-title-link { cursor: pointer; display: flex; align-items: center; justify-content: space-between; }
.sb-title-link:hover { color: var(--text); }
.sb-cv-hint { font-size: 10.5px; font-weight: 400; color: var(--accent-2); }

/* 월간 캘린더(캔버스 탭) — Google Calendar 스타일 */
.cal-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.cal-title { font-weight: 700; font-size: 16px; min-width: 100px; text-align: center; }
/*   ★W-UIX14-S4 A — 채움·각진 모양은 `.btn-sub` 별칭으로 옮겼다(위). 여기 남는 것은
     **이 자리에서만 뜻이 있는 것**뿐이다. ★`#art-open` 은 `<a>` 라 밑줄·링크색이
     남으므로 한 줄이 더 필요하다(§0-① · 버튼만 있다고 읽으면 그 하나가 튄다). */
.cal-today { margin-left: auto; }
a.cal-today { text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }
/* 데스크 시트 선택기(Phase 7 — 작업할 시트 선택) */
.art-sheet-sel {
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 7px; padding: 4px 8px; font-size: 12.5px; max-width: 180px;
}
/* [💾 로컬에 덮어쓰고 종료] — 지식보관소 파일 동기화(Phase 8). 눈에 띄게. */
.art-local-save {
  background: var(--accent); color: #fff; border: none; border-radius: 8px;
  padding: 6px 12px; font-size: 12.5px; font-weight: 700; cursor: pointer;
}
.art-local-save:disabled { opacity: .6; cursor: default; }
/* 문서 A4 페이퍼 뷰(Phase 9) — 회색 배경 위 진짜 종이(Word/아래아한글 느낌)
   ★★W-CV1 ③(2026-09-01 사장님 지시) — **그 연출을 걷었다.** Word 의 "회색 바탕 위 종이"는
     전체 화면을 쓰는 편집기의 문법이고, 폭 1/3짜리 캔버스 안에서는 **두꺼운 어두운 액자**로
     보인다(사장님 스크린샷). 대시보드(`.dash-frame`)와 같은 문법으로 바꾼다 —
     **패널 톤 배경 + 1px 라인 경계** 하나. 페이지 구분은 종이 자신의 라인이 맡는다.
   ★인쇄 층은 이 판으로 안 변한다 — `@media print` 의 `body.print-doc #doc-frame` 이
     배경·테두리·라운드를 도로 걷는다(화면 연출이 종이로 새지 않게 · 짝으로 고쳤다).
   ★높이 상수 188 → 178: **실측으로 골랐다**(눈대중 금지). 크롬에서 상수를 4px 씩 바꿔 가며
     `.cv-body` 의 세로 스크롤을 쟀더니 176 에서 2px, 178 에서 **0** 이었다 —
     종전(188)은 그 자리에서 26px 이 넘쳐 있었다. 즉 이 판은 문서 높이를 10px 늘리면서
     넘침도 함께 없앤다. ★이 상수는 뷰포트 높이와 무관하다(넘치는 쪽이 전부 고정 px 라
     100vh 가 양쪽에서 상쇄된다) — 그래서 상수 하나로 맞출 수 있다.
     ★매직 넘버라는 사실 자체는 남는다(별건 W-CV1-B2 = flex 화). */
.doc-frame {
  overflow: auto; padding: 8px;   /* ★W-CV2 ① — 높이 상수 제거(채움 규칙이 정한다) */
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  display: flex; flex-direction: column; align-items: center; gap: 10px;   /* 페이지 가운데 정렬(좌우 여백 대칭) + 장 사이 숨 */
}
/* 수동 발송 공유 바(Phase 36) — 문서 탭 하단 상시. AI 초안 → 사용자 기기에서 수동 발송 */
.doc-share {
  display: flex; gap: 10px; justify-content: center; align-items: center; height: 50px;
  padding: 0 12px env(safe-area-inset-bottom); background: var(--panel-2);
  border-top: 1px solid var(--border);
}
.doc-share-btn {
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 999px; cursor: pointer; padding: 8px 16px; font-size: 13px;
}
.doc-share-btn:hover { filter: brightness(1.15); }
/* 공유 접점 확장(Phase 36.2) — 말풍선/카드/그리드 공용 미니 버튼 + 빠른 보내기 모달 */
.share-line { display: flex; gap: 6px; margin-top: 8px; }
/* ★W5-④ — 답변 **글 끝**에 붙는 공유 배지. 카드 바깥 줄이 아니라 문장이 끝나는 그 자리다.
   `.share-line` 은 카드 하단용 블록 줄이라 그대로 쓰면 줄바꿈이 생긴다 — 글 안에 있을 때만
   눕힌다(같은 부품·같은 핸들러, 배치만 다르다). */
.bot-summary .share-line { display: inline-flex; margin: 0 0 0 6px; vertical-align: middle; }
/* 업무 스킬 각인/제안(Phase 35) */
.skill-seed-line { margin-top: 8px; }
.skill-seed-btn {
  background: var(--panel-2); border: 1px dashed var(--border); color: var(--text);
  border-radius: 999px; cursor: pointer; padding: 4px 12px; font-size: 12px;
}
.skill-seed-btn:hover { filter: brightness(1.12); border-style: solid; }
.skill-seed-done { font-size: 12px; color: var(--muted); }
.chat-card.skill-offer { border-left: 3px solid var(--accent); }
/* 프리미엄 웹 문서 공유 카드(Phase 39) */
.chat-card.webdoc-card { border-left: 3px solid #7c3aed; }
/* 계획 다음 단계 카드(Phase 40) */
.chat-card.next-step { border-left: 3px solid var(--accent-2, #22d3ee); }
.next-step .ns-goal { font-weight: 700; color: var(--accent); }
.next-step .ns-rem { color: var(--muted); font-size: 12px; }
/* 계획 정지 카드(Phase 49) — 오케스트레이터 ASK_USER */
.chat-card.plan-pause { border-left: 3px solid #f59e0b; }
.plan-pause .pp-pos { color: var(--muted); font-size: 12px; font-weight: 400; }
/* 시험 스캔 미도착 카드(W-PSK2-B2 · **규칙은 W-PC2-B1 에서 붙였다**) — 사람이 무언가를 해 주기를
   기다리는 카드라 계획 정지(plan-pause)와 같은 계열(호박색 왼쪽 선)로 세운다.
   ★★왜 따로 적는가: 이 카드는 남의 카드 클래스(`.ss-text`·`.pp-pos`)를 빌려 쓰고 있었는데 그 둘은
   각각 `.chat-card.skill-suggest`·`.plan-pause` 밑으로 **범위가 잡혀** 있어 한 줄도 안 닿았다
   (style.css:2007 의 W6 ② 와 같은 병 · 그때는 버튼이, 이번엔 본문·보조문이 기본 스타일로 떨어졌다).
   ★색은 새로 만들지 않는다 — 이미 있는 토큰(--soon)을 쓴다. 밝은 섹션에서는 theme.js 가 덮어쓴다. */
.chat-card.pc-scan-wait { border-left: 3px solid var(--soon, #fbbf24); }
.chat-card.pc-scan-wait .psw-text { font-size: 13px; color: var(--text); }
.chat-card.pc-scan-wait .psw-waited { color: var(--muted); font-size: 12px; font-weight: 400; }
.chat-card.pc-scan-wait .psw-note { font-size: 11.5px; color: var(--muted); margin-top: 8px; }
/* 모바일 수동 오픈 버튼(Phase 34 잔여) — 열람형 아티팩트는 탭해야 풀스크린 캔버스 */
/* ★W6 ② — [문서 열기]/[결과 열기]가 **너무 튀었다**(사장님 지적). 원인은 색 선택이 아니라
   **스타일이 아예 안 닿은 것**이다: 이 버튼은 `.bot-routed` 안에 사는데 카드 버튼 규칙은
   `.chat-card .cc-btn` 으로 **범위가 잡혀** 있어 걸리지 않았고, 그래서 **브라우저 기본 버튼**
   (흰 바탕 `rgb(240,240,240)` · 검은 테두리 · Arial)으로 떨어졌다.
   실측 = 카드 바닥 대비 **11.01:1** — 어두운 카드 위의 흰 덩어리였다.
   ★처방 = 새 색 발명 0. 카드 바닥(`--panel-2`)에서 **한 단계만** 올린 `--panel` 로 낮춰
   "눌리는 것"임은 남기고 시선은 뺏지 않는다. 글자 대비는 접근성 몫이라 낮추지 않는다. */
.artifact-open-btn {
  display: block; margin-top: 8px;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--fx-pill, 999px);
  padding: 5px 12px; font-size: var(--fx-fs-sm); font-family: inherit; cursor: pointer;
}
.artifact-open-btn:hover { border-color: var(--accent); }
/* SOP 선제안 칩(Phase 46) — 고속경로 승인 카드 */
.chat-card.skill-chip { border-left: 3px solid #a78bfa; }
.skill-chip .sc-n { color: var(--muted); font-size: 12px; }
.skill-chip .sc-steps { margin: 6px 0 2px; padding-left: 20px; }
.skill-chip .sc-steps li { font-size: 12.5px; color: var(--muted); line-height: 1.5; }
/* 업무 스킬 관리 대시보드(Phase 46 — 우측 캔버스) */
.skd-wrap { padding: 14px; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; }
.skd-title { font-size: 16px; font-weight: 800; }
.skd-hint, .skd-empty { font-size: 12.5px; color: var(--muted); }
.skd-item { background: var(--surface, #FFFFFF); border: 0;
  border-radius: var(--radius, 12px); padding: 10px 12px;
  box-shadow: 0 0 0 1px rgba(23,27,34,.07);}
.skd-head { display: flex; align-items: center; gap: 8px; }
.skd-head b { flex: 1; font-size: 13.5px; }
.skd-vis { font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 2px 6px; }
.skd-del { background: none; border: none; cursor: pointer; font-size: 14px; }
.skd-text { font-size: 12.5px; color: var(--text); margin-top: 6px; white-space: pre-wrap; }
.skd-steps { margin: 6px 0 0; padding-left: 20px; }
.skd-steps li { font-size: 12px; color: var(--muted); line-height: 1.5; }
.skd-nosteps { font-size: 11.5px; color: var(--muted); margin-top: 6px; font-style: italic; }
.sop-canvas-btn { align-self: flex-start; background: var(--panel-2); border: 1px solid var(--border);
  color: var(--text); border-radius: 999px; cursor: pointer; padding: 4px 12px; font-size: 12px;
  margin-bottom: 8px; }
.sop-canvas-btn:hover { filter: brightness(1.12); }
/*   ★★W-UIX16-F5 ③ — **연결이 안 될 때 서는 한 줄.** 데모로 떨어지지 않고 여기 머문다
     (로그인은 그대로다). 새 부품을 만들지 않고 공용 표면·버튼 토큰만 쓴다. */
.boot-retry { position: fixed; inset: 0; z-index: 9999; display: flex; align-items: center;
  justify-content: center; background: var(--bg, #F5F6F8); }
.boot-retry.hidden { display: none; }
.boot-retry-in { max-width: 340px; text-align: center; padding: 24px 22px;
  background: var(--surface, #FFFFFF); border-radius: var(--r-card, 12px);
  box-shadow: 0 0 0 1px var(--hairline), var(--wk-shadow); }
.boot-retry-in b { display: block; font-size: 15px; color: var(--text); margin-bottom: 6px; }
.boot-retry-in p { font-size: 12.5px; color: var(--muted); line-height: 1.5; margin: 0 0 14px; }

/* ===== SOP 스토어 + 듀얼 모드 캔버스(Phase 58) ===== */
.skill-store { display: flex; flex-direction: column; gap: 8px; padding: 2px 0; }
.sk-group-title { font-size: 11px; font-weight: 700; color: var(--muted); margin: 4px 0 2px;
  text-transform: none; letter-spacing: 0.02em; }
.skill-item { display: flex; align-items: center; gap: 6px; width: 100%; text-align: left;
  background: none; border: none; color: var(--text); cursor: pointer; padding: 5px 6px;
  border-radius: 8px; font-size: 12.5px; }
.skill-item:hover { background: var(--panel-2); }
.skill-item .sk-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* LNB 메뉴 선택 색 고정(2026-07-21·내 업무 tt-selected 정합) — 간편장부·이커머스·SOP 스킬 공용.
   hover=배경(transient)·선택(active)=accent 글자+굵게(유지). 내 업무 '.tt-node.tt-selected .tt-title' 와 동일 톤. */
/* ★83.2-c — 메일 LNB 두 항목(받은/보낸)도 같은 단일 표식을 쓴다(별도 활성 기구를 만들지 않는다). */
.erp-item.lnb-active, .b2c-item.lnb-active, .skill-item.lnb-active,
.mail-item.lnb-active { color: var(--accent); font-weight: 700; }
.erp-item.lnb-active [data-lucide], .erp-item.lnb-active svg { opacity: 1; }   /* 선택 시 아이콘도 또렷 */
/* SOP 스킬 항목 = '내 업무' 트리 노드 정합(2026-07-21·LNB-1): 그룹(내 스킬/공유/프리미엄) 아래 들여쓰기 + 좌측 가이드선.
   오프셋(margin-left 6 + ::before left 3 = 가이드선 9)은 간편장부 .erp-fold>.erp-item·내 업무 .tt-node d1 과 동일(헤드리스 실측 정합). */
.skill-store .skill-item { position: relative; margin-left: 6px; padding-left: 16px; }
.skill-store .skill-item::before { content: ""; position: absolute; left: 3px; top: -1px; bottom: -1px;
  border-left: 1px solid var(--border); opacity: .55; }
.sk-badge { font-size: 10.5px; color: var(--muted); border: 0;
  background: var(--surface-2, rgba(148,163,184,.15));
  border-radius: var(--r-chip); padding: 1px 7px; white-space: nowrap; }
.sk-on { color: var(--accent); font-size: 11px; }
.skill-pane, .cv-skill-pane { height: 100%; overflow-y: auto; }
.skc-wrap, .skr-wrap { padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.skc-head { display: flex; align-items: center; gap: 10px; }
.skc-title { flex: 1; font-size: 15px; font-weight: 800; }
.skc-use { display: flex; align-items: center; gap: 8px; font-size: 12.5px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 4px 12px; }
/* ★공용 스위치(86.6) — 체크박스 모양을 스위치로. 새로 만든 것이 아니라
   이미 둘로 복사돼 있던 형상(.skc-use input · .ar-apply-tgl)을 **정의 하나로** 모은 것이다.
   설정 모달의 체크박스가 여기 합류한다(세 번째 복사본을 만들지 않는다). */
/* ★선택자를 `input.switch` 로 둔 이유: `.modal-card input`(0,1,1)이 width:100%·radius:8px 를
   주고 있어 `.switch`(0,1,0) 로는 **질다**(계측에서 폭 100%·둥글기 8px 으로 나왔다).
   전에는 `.set-toggle input`(0,2,0)이 막고 있었다 — 그걸 지우면서 드러난 것이다. */
input.switch, .skc-use input, .ar-apply-tgl { appearance: none; -webkit-appearance: none;
  width: 34px; height: 19px; min-width: 34px; margin: 0; padding: 0; border: none;
  border-radius: 999px; background: var(--border);
  position: relative; cursor: pointer; transition: background .15s ease; flex: none; outline: none; }
input.switch:checked, .skc-use input:checked, .ar-apply-tgl:checked { background: var(--accent); }
input.switch::after, .skc-use input::after, .ar-apply-tgl::after { content: ""; position: absolute;
  top: 2px; left: 2px; width: 15px; height: 15px; border-radius: 50%; background: #fff;
  transition: left .15s ease; box-shadow: 0 1px 2px rgba(0,0,0,.3); }
input.switch:checked::after, .skc-use input:checked::after, .ar-apply-tgl:checked::after { left: 17px; }
input.switch:disabled { opacity: .5; cursor: not-allowed; }
.skc-meta { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.skc-meta select { font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 2px 6px; }
.skc-ro { font-style: italic; }
.skc-goal { font-size: 12.5px; color: var(--text); }
.skc-sec { font-size: 12px; font-weight: 700; color: var(--muted); margin-top: 4px; }
/* 명세(Spec) 카드(Phase 63) — 읽기 우선. 서버 s.spec 렌더(FE 파싱 없음, SSOT) */
/*   ★W-UIX16-F4 ① — 카드가 **폭을 채운다**(좌우가 남아 내용이 가운데로 몰리던 자리). */
.skc-spec { padding: 12px; display: flex; flex-direction: column; gap: 8px; width: 100%; }
.skc-spec-goal { font-size: 13px; font-weight: 700; color: var(--text); }
.skc-spec-row { display: flex; gap: 8px; font-size: 12.5px; }
.skc-spec-k { flex: none; width: 58px; color: var(--muted); font-weight: 600; }
.skc-spec-v { display: flex; flex-wrap: wrap; gap: 4px; align-items: baseline; }
.skc-spec-flow { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
.skc-spec-flow li { color: var(--text); line-height: 1.5; }
/*   ★W-UIX14-S4 B — 칩은 공용 한 벌이다. ★§0 정정: 이 화면의 '칩 13종' 중 넷
     (`.skc-tag`·`.skc-src`·`.skc-lim`·`.skc-cond`)은 **select/input** 이라 칩이 아니다 —
     입력칸을 칩으로 바꾸면 어디를 누를지 말하지 않는 화면이 된다(S1 T3b 의 규율). */
.skc-chip { border: 0; border-radius: var(--r-chip); padding: 2px 8px; font-size: 12px;
  color: var(--muted); background: var(--surface-2, rgba(148,163,184,.15)); }
.skc-chip em { color: var(--muted); font-style: normal; }
.skc-req { color: var(--danger, #e5484d); }
.skc-dim { color: var(--muted); font-size: 12px; }
.skc-ctrl { font-size: 11px; font-weight: 600; border-radius: 6px; padding: 0 5px; }
.skc-ctrl-for { color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.skc-ctrl-if { color: #d08700; background: color-mix(in srgb, #d08700 14%, transparent); }
.skc-spec-none { font-size: 12px; color: var(--muted); }
.skc-edit { display: flex; flex-direction: column; gap: 8px; padding-top: 4px;
  border-top: 1px dashed var(--border); }
.skc-out { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.skc-out input { flex: 1; font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px; }

/* ── 순서도(Flowchart) 다이어그램(Phase 64) — 읽기 전용·자체 SVG·세로 폭포수 ── */
.skc-spec-flowhdr { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
/*   ★★W-UIX14-S4 B — 흐름 보기 전환은 **캔버스 탭 줄과 같은 텍스트 탭**이다
     (구성안 §5: 아이콘 0 · 알약 0 · 활성 = 잉크 + 강조색 밑줄 2px). 종전에는 제 알약
     토글이라 같은 화면 안에서 탭이 두 모양이었다. */
.skc-flow-toggle { display: inline-flex; gap: 4px; }
.skc-flowtab { font-size: 12px; padding: 4px 10px; border: 0; border-bottom: 2px solid transparent;
  background: transparent; color: var(--muted); cursor: pointer; font-family: inherit; }
.skc-flowtab:hover { color: var(--text); }
.skc-flowtab.active { color: var(--text); border-bottom-color: var(--accent); }
/*   ★★★W-UIX16-F4 ①(2026-09-12 사장님 실기) — 순서도와 목록을 **나란히** 세운다.
     둘은 같은 것의 두 읽는 법이라, 하나를 보려고 다른 하나를 지울 이유가 없었다(토글 폐기).
   ★좁아지면 **위아래**로 내린다 — 칸이 좁은 채 둘을 밀어 넣으면 둘 다 못 읽는다.
     캔버스는 폭이 사람 손에 달려 있어 화면 폭이 아니라 **제 폭**으로 판정해야 한다
     ⇒ 컨테이너 쿼리(`container-type: inline-size`). 지원 안 하는 브라우저는 **1열**로
     떨어지고 그것은 좁은 화면과 같은 그림이라 안전하다(못 쓰면 나빠지지 않는다). */
/*   ★★컨테이너는 **조상**이어야 한다 — `container-type` 을 재려는 요소 자신에게 걸면
     그 요소는 제 컨테이너를 못 본다(실브라우저가 잡았다: 폭 816px 인데 1열이었다).
     그래서 명세 카드(`.skc-spec`)가 컨테이너가 되고 `.skc-flow` 가 그것을 묻는다. */
.skc-spec { container-type: inline-size; }
.skc-flow { display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr); }
@container (min-width: 520px) {
  .skc-flow { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); align-items: start; }
}
/*   두 칸 모두 **카드**다 — 공용 표면 + 그림자(선만으로는 도형이 종이 위에 안 뜬다 · 사장님). */
/*   ★모양은 공용 레시피(`.wk-card`)가 준다 — 여기서는 **이 자리의 것**만 적는다
     (R4 가 잡았다: 배경+그림자+둥글기를 여기서 또 적으면 그것이 곧 전속 카드다). */
/*   ★★실화면이 잡았다 — `.wk-card` 에 합류하면 그 레시피(`padding: 12px 14px`)가 **파일에서
     뒤에 오므로** 여기 적은 패딩·들여쓰기를 이긴다(특이도 동률이면 뒤가 이긴다).
     ⇒ 한 겹 올려 이 자리의 것을 지킨다(`.skc-flow` 아래로). */
.skc-flow .skc-flow-card { padding: 12px; min-width: 0; overflow-x: auto; }
.skc-flow-card.hidden { display: none; }
/*   ★W-UIX16-F5 ①(사장님 실기) — 번호가 카드 벽에 붙어 있었다. 카드 패딩(12) 위에
     **번호가 설 자리**를 준다(마커가 바깥으로 나가지 않게 `inside` 로 세운다). */
.skc-flow .skc-flow-list { margin: 0; padding-left: 22px; list-style-position: outside; }
.skc-flow .skc-flow-list li { padding-left: 2px; }
/*   ★★★W-UIX16 A(2026-09-12 사장님) — **순서도 노드가 튀던 자리.**
     뿌리는 S1 이다: 공용 카드 표면을 `--surface` 로 올릴 때 순서도만 `--panel-2` 로 남아
     흰 카드 위에 **회색 상자**가 떴다(F1 ① 자동화 펼침 본문과 **같은 부류**).
     ⇒ 노드는 `.wk-card` 의 결을 따른다: 표면 + hairline 링 + 그림자 0.
   ★★거짓 경로의 주황(`#d08700` 아홉 자리)은 **지우지 않는다** — 그것은 색이 아니라
     *"이 길은 조건이 틀렸을 때"* 라는 **뜻**이고, 지우면 분기가 본선과 같아 보인다.
     대신 **토큰 한 칸**에 모아 다크에서도 같은 뜻으로 읽히게 한다(정의 1 · 사용처 0 hex). */
:root { --fc-branch: #d08700; }
:root:not([data-theme="light"]) { --fc-branch: #e0a458; }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) { --fc-branch: #d08700; } }
:root[data-theme="dark"] { --fc-branch: #e0a458; }
.fc { position: relative; width: 100%; padding: 2px 0; }
/* 블록 트리 모드(Phase 3b-2b) — 좌측 정렬 + depth 들여쓰기 + 좌측 블록 가이드(브래킷). 복잡 화살표 없음. */
.fc-col-tree { align-items: flex-start; gap: 12px; overflow-x: auto; }
.fc-col-tree .fc-node { align-self: flex-start; }
.fc-indent { border-left: 2px solid color-mix(in srgb, var(--fc-branch) 45%, transparent); padding-left: 8px; }
.fc-false-note { margin-top: 4px; font-size: 10px; color: var(--fc-branch); text-align: center; }
.fc-wires { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: visible; }
.fc-col { position: relative; z-index: 1; display: flex; flex-direction: column;
  align-items: center; gap: 22px; padding: 4px 34px; }
.fc-node { position: relative; max-width: 100%; box-sizing: border-box; font-size: 12px; }
/*   시작·종료 = **잿빛 알약**(표면 위에 한 겹 · 채움으로 튀지 않는다). */
.fc-cap { padding: 6px 16px; border-radius: 999px; background: var(--surface, #FFFFFF);
  box-shadow: 0 0 0 1px var(--hairline), var(--wk-shadow); border: 0; color: var(--muted);
  font-weight: var(--fw-3, 600); text-align: center; }
.fc-start { border-color: var(--accent); color: var(--accent); }
.fc-end { color: var(--muted); }
/*   단계 카드 = 공용 카드 결(표면 + 링 · 그림자 0). 번호 원(강조색)이 순서를 말한다. */
.fc-step { min-width: 172px; max-width: 260px; background: var(--surface, #FFFFFF);
  box-shadow: 0 0 0 1px var(--hairline), var(--wk-shadow); border: 0; border-radius: 10px; padding: 8px 12px; }
.fc-step-in { display: flex; gap: 8px; align-items: baseline; }
.fc-no { flex: none; width: 18px; height: 18px; line-height: 18px; text-align: center;
  border-radius: 50%; background: var(--accent); color: #fff; font-size: 11px; font-weight: 700; }
.fc-step-txt { color: var(--text); line-height: 1.45; }
.fc-loop-badge { margin-top: 6px; font-size: 10.5px; color: var(--accent); display: inline-block;
  background: color-mix(in srgb, var(--accent) 12%, transparent); border-radius: 6px; padding: 1px 6px; }
/* else 분기(Phase 3b-1) — '아니면' 대체 경로 뱃지(거짓 화살표 톤 #d08700 정합) */
.fc-else-badge { margin-top: 6px; font-size: 10.5px; color: var(--fc-branch); display: inline-block;
  background: color-mix(in srgb, var(--fc-branch) 12%, transparent); border-radius: 6px; padding: 1px 6px; }
/*   입력·산출물(평행사변형) = 강조색 **6% 틴트**(표면 위 · 종전 8%+panel-2 보다 여리게). */
.fc-io { transform: skewX(-11deg); box-shadow: 0 0 0 1px var(--hairline), var(--wk-shadow); border: 0;
  border-radius: 4px; padding: 7px 14px; max-width: 280px;
  background: color-mix(in srgb, var(--accent) 6%, var(--surface, #FFFFFF)); }
.fc-io-in { transform: skewX(11deg); display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.fc-io-ic { font-size: 12px; }
.fc-chip { background: var(--surface, #FFFFFF); box-shadow: 0 0 0 1px var(--hairline); border: 0; border-radius: 999px;
  padding: 0 7px; font-size: 11px; color: var(--text); }
.fc-chip em { color: var(--muted); font-style: normal; }
.fc-req { color: var(--danger, #e5484d); }
/*   조건(마름모) — 분기색은 **뜻**이라 그대로, 채움만 표면으로. */
.fc-if { max-width: 300px; text-align: center; padding: 15px 36px;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  background: color-mix(in srgb, var(--fc-branch) 14%, var(--surface, #FFFFFF)); }
.fc-if-in { display: flex; flex-direction: column; align-items: center; gap: 1px; }
.fc-if-q { font-size: 10px; font-weight: var(--fw-3, 600); color: var(--fc-branch); }
.fc-if-txt { font-size: 11.5px; color: var(--text); line-height: 1.3; }
.fc-wire { stroke: var(--hairline); stroke-width: 1.5; }
.fc-arrowhead { fill: var(--muted); }
.fc-wire-skip { stroke: var(--fc-branch); stroke-dasharray: 4 3; }
.fc-wire-loop { stroke: var(--accent); stroke-dasharray: 4 3; }
.fc-wlabel text { font-size: 10px; fill: var(--muted); }
.fc-wlabel.fc-yes text { fill: var(--accent); }
.fc-wlabel.fc-no text { fill: var(--fc-branch); }

.skc-step { padding: 8px 10px; display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }
/* else/블록 피커(Phase 3c) — 중첩 depth 들여쓰기 좌측 가이드 + 블록 경계 표시 + 짝 안내/경고 */
/*   ★블록 경계는 **뜻이 있는 선**이라 남긴다(장식 테두리가 아니다 · 카드는 테두리 0). */
.skc-step.skc-nested { box-shadow: inset 2px 0 0 color-mix(in srgb, #d08700 45%, transparent),
    0 0 0 1px rgba(23,27,34,.07),
    var(--wk-shadow, 0 1px 2px rgba(23,27,34,.05), 0 6px 18px rgba(23,27,34,.06)); }
.skc-marker { font-size: 11px; color: var(--muted); font-style: italic; }
.skc-block-hint { font-size: 11px; margin: 2px 0 6px; }
.skc-block-hint .skc-warn { color: var(--danger, #e5484d); margin-right: 8px; }
.skc-block-hint .skc-hint { color: var(--muted); }
.skc-step-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; }
.skc-step-head b { font-size: 12px; }
/* 프로그래머블 스킬(Phase 1) — 단계 재배열 드래그 핸들·삭제·목표 입력·데이터소스 배지. var(--*) 정합. */
.skc-drag { cursor: grab; color: var(--muted); font-size: 14px; line-height: 1; user-select: none;
  padding: 0 2px; }
.skc-drag:active { cursor: grabbing; }
.skc-step.skc-dragover { border-color: var(--accent); }
.skc-step-del { margin-left: auto; background: transparent; border: none; color: var(--muted);
  cursor: pointer; font-size: 13px; padding: 2px 4px; }
.skc-step-del:hover { color: var(--danger, #e5534b); }
/*   ★채움이 생기자 **늘어나는 것**이 드러났다(스샷이 잡았다): 부모 `.skc-step` 이
     flex-column 이라 자식이 줄 폭으로 stretch 된다 — 테두리만 있던 시절에는 안 보였다.
     ⇒ 칩은 제 글자만큼만 차지한다(`align-self` + `inline-flex`). */
.skc-ds-badge { font-size: 10.5px; color: var(--accent); border: 0;
  display: inline-flex; align-items: center; gap: 4px; align-self: flex-start;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: var(--r-chip); padding: 1px 7px; }
.skc-goal { width: 100%; font-size: 12.5px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 5px 8px; }
/* 데이터 소스 드롭다운(Phase 2c) — 단계별 안정 참조 결합. var(--*) 정합·select 수준. */
.skc-ds { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 4px; font-size: 12px; }
.skc-ds-lbl { color: var(--muted); font-size: 11.5px; }
.skc-ds-kind, .skc-ds-pick, .skc-ds-var, .skc-ds-q, .skc-ds-ext {
  font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 2px 6px; }
.skc-ds-q { width: 120px; }
.skc-ds-body { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.skc-ds-cur { color: var(--accent); font-size: 11px; }
.skc-tag, .skc-src { font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 2px 6px; }
.skc-for, .skc-if { display: inline-flex; align-items: center; gap: 4px; font-size: 12px;
  color: var(--muted); }
.skc-lim { width: 52px; font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 2px 6px; }
.skc-cond { min-width: 180px; font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 3px 8px; }
.skc-label { width: 100%; font-size: 12.5px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 9px; }
.skc-param { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
.skc-param input[type="text"] { font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 4px 8px; }
.skp-name { width: 90px; } .skp-hint { flex: 1; min-width: 110px; } .skp-example { width: 100px; }
.skp-kind { font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 3px 6px; }
.skp-req { display: inline-flex; align-items: center; gap: 3px; font-size: 11.5px; color: var(--muted); }
.skp-del { background: none; border: none; cursor: pointer; font-size: 13px; }
.skc-actions { display: flex; gap: 8px; margin-top: 6px; }
/*   ★★W-UIX14-S4 B — SOP 버튼 **서른아홉**이 공용 부품과 같은 레시피로 선다
     (`.skc-btn` = 보조 · `.skc-primary` = 주행동 하나 · `.skc-danger` = 되돌리기 어려운 것).
     ★마크업 무접촉 — 39 자리를 손으로 고치면 다음에 생기는 버튼이 또 새 모양을 갖는다.
     ★알약(999px)에서 공용 8px 로: 구성안의 손잡이는 한 모양이다. */
/*   ★W-UIX14-S5-3 — 이커머스 버튼 마흔다섯이 같은 레시피를 쓴다(마크업 무접촉). */
.skc-btn, .eco-btn, .eco-card-btns button, .eal-go, .eal-no, .eco-del { padding: 7px 14px; border: 1px solid var(--hairline); border-radius: 8px;
  cursor: pointer; font-size: 13px; font-weight: 400; font-family: inherit;
  background: transparent; color: var(--muted); }
.skc-btn:hover { border-color: var(--accent); color: var(--accent); }
.skc-btn:disabled { opacity: .55; cursor: not-allowed; }
.skc-primary, .eco-save, .eal-yes { border-color: transparent; color: var(--btn-fg, #fff); font-weight: 400;
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2))); }
.skc-primary:hover { filter: brightness(1.06); border-color: transparent; color: var(--btn-fg, #fff); }
.skc-danger, .eco-del { color: var(--danger, #d64545); }
.skc-danger:hover, .eco-del:hover { border-color: var(--danger, #d64545);
  color: var(--danger, #d64545); }
.skc-text { font-size: 12.5px; color: var(--text); white-space: pre-wrap; }
.skr-field { display: flex; flex-direction: column; gap: 4px; }
.skr-field label { font-size: 12.5px; font-weight: 700; }
.skr-hint { font-weight: 400; color: var(--muted); }
.skr-field input[type="text"], .skr-field select { font-size: 13px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 10px; padding: 8px 11px; }
.skr-drop { border: 1.5px dashed var(--border); border-radius: 10px; padding: 16px 12px;
  font-size: 12.5px; color: var(--muted); text-align: center; cursor: pointer; }
.skr-drop-hover { border-color: var(--accent); color: var(--text); }
.skr-drop-ok { border-style: solid; border-color: var(--accent); color: var(--text); }
.skr-run { align-self: flex-start; margin-top: 4px; }
.skr-note { font-size: 11.5px; color: var(--muted); }
/* 드라이런 프리뷰(Phase 3a-2) — 실행 전 참조 해소 표 + 상태 칩. var(--*)만·라이트/다크 정합 */
.skr-preview { padding: 12px 13px; display: flex; flex-direction: column; gap: 9px; margin-top: 6px; }
.skc-refbox { margin-top: 6px; }
/* ★W-ORDEV1-B4 S1 — «OR 편차 검토» 명세 아래 회사 기준표 넷(새 토큰 0 · 기존 카드 결 그대로) */
.skc-orstd { padding: 12px; display: flex; flex-direction: column; gap: 8px; width: 100%; }
.skc-orstd-body { display: flex; flex-direction: column; gap: 8px; }
.skc-orstd-r { font-size: 12.5px; color: var(--text); display: flex; flex-direction: column; gap: 2px; }
.skc-orstd-r .skc-dim { font-size: 12px; color: var(--muted); }
.skc-orstd-def { font-size: 12px; color: var(--soon); display: flex;
  flex-wrap: wrap; align-items: center; gap: 4px; }
.skc-orstd-act { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.skc-orstd-up { cursor: pointer; }
.skc-orstd-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.skc-orstd-ver { margin-left: auto; font-size: 11.5px; color: var(--muted); }
/* ★공용 텍스트 탭(W-ORDEV1-B5 ①) — 캔버스 탭과 같은 결: 테두리 0 · 고른 것은 잉크+강조색 밑줄 */
.wk-tabs { display: flex; gap: 2px; flex-wrap: wrap; }
.wk-tab { background: transparent; border: 0; cursor: pointer; padding: 5px 10px;
  font-size: 12.5px; color: var(--muted); border-radius: var(--r-chip) var(--r-chip) 0 0; }
.wk-tab:hover { color: var(--text); }
.wk-tab.is-on { color: var(--text); font-weight: 500;
  box-shadow: inset 0 -2px 0 var(--accent); }
.skc-orstd-gridwrap { overflow-x: auto; }
.skc-orstd-grid { border-collapse: collapse; font-size: 12px; width: 100%; }
.skc-orstd-grid th, .skc-orstd-grid td { padding: 3px 8px; text-align: right; white-space: nowrap;
  box-shadow: inset 0 -1px 0 var(--border); }
.skc-orstd-grid thead th { color: var(--muted); font-weight: 500; }
.skc-orstd-grid tbody th { text-align: left; font-weight: 400; color: var(--text); }
.skc-orstd-card { padding: 10px; display: flex; flex-direction: column; gap: 6px; }
.skc-orstd-go { display: flex; gap: 6px; margin-top: 4px; }
.skdr-head { font-size: 13px; font-weight: 600; color: var(--text); }
.skdr-note { font-size: 12.5px; color: var(--muted); }
.skdr-warn { font-size: 12px; color: var(--text); background: color-mix(in srgb, var(--danger) 10%, transparent);
  border: 1px solid var(--danger, #d9534f); border-radius: 9px; padding: 8px 10px; }
.skdr-tablewrap { overflow-x: auto; }
.skdr-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.skdr-table th, .skdr-table td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border);
  white-space: nowrap; }
.skdr-table th { color: var(--muted); font-weight: 600; }
.skdr-table td.skdr-name { color: var(--muted); }
.skdr-bar { display: flex; gap: 8px; justify-content: flex-end; }
/*   ★참조 점검 칩 — 뜻(확인·끊김·확인불가)은 그대로, 모양은 공용 칩 결로. */
.skchip { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 400;
  border-radius: var(--r-chip); padding: 2px 9px; border: 0; white-space: nowrap;
  background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted); }
.skchip-ok { color: var(--wk-live, #17A34A); }
.skchip-bad { color: var(--danger, #d9534f); }
.skchip-unk { color: var(--muted); }
.skchip-na { color: var(--muted); opacity: .8; }

/* ══ 워키 스킬 — 화면 골격(2026-09-11 W-UIX14-S4 B 에서 app.html 인라인에서 이사) ══
   ★★W-UIX16 A(2026-09-12) — 중앙은 **카드 그리드 하나**다(상세는 우측 캔버스 [스킬] 탭).
     2단 격자(`.skills-two`)·상세 칸(`.skills-detail`)·좁은 폭 규칙 넷을 **함께 걷었다** —
     켜는 자리가 사라진 규칙을 남기면 다음 사람이 *"여기 뭔가 있었나"* 를 되짚는다(죽은 규칙 0).
     ★상세의 옷(`.skill-pane`)은 캔버스 패인이 그대로 쓴다(그 이름을 08-05 이사 때 남겨 두었다). */
.skills-store-host { height: 100%; overflow-y: auto; padding: 16px 18px; }
.skcard-group { margin-bottom: 22px; }
.skcard-group-title { font-size: 13px; font-weight: 400; color: var(--muted);
  letter-spacing: .02em; margin: 0 2px 10px; }
.skcard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.skcard { display: block; text-align: left; width: 100%; padding: 14px; cursor: pointer; }
.skcard-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
/* ★W-UIX18 ⑥(2026-09-13 · 사장님) — 카드 제목 한 단계 축소(15 → 14px). 카드 안의 제목은
   화면 제목이 아니라 **목록의 한 줄**이라 한 단계 낮은 것이 맞다(스킬 카드 전속 한 줄 ·
   공용 토큰은 안 건드린다 — 건드리면 이 화면 밖 제목이 함께 줄어든다). */
.skcard-name { font-weight: 500; font-size: 14px; margin-right: auto; }
/*   ★W-UIX14-S4 B — 배지·[사용 중] 도 공용 칩 결로(채움 없는 회색 알약을 새로 만들지 않는다). */
.skcard-badge { font-size: 11px; padding: 2px 7px; border-radius: var(--r-chip); border: 0;
  background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted); }
.skcard-badge .sk-ai-ic { width: 12px; height: 12px; vertical-align: -1px; }
/* ★W-UIX27 — 스킬의 얼굴(에이전트 아바타)이 이름 앞에 선다: 줄 안에 얌전히 맞춘다. */
.skcard-name .av, .skc-title .av, .skd-head .av { vertical-align: -4px; margin-right: 2px; }
.skcard-prem { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.skcard-steps { font-size: 11px; color: var(--muted); }
.skcard-on { font-size: 11px; color: var(--wk-live, #17A34A); font-weight: 400; }
/*   ★★W-UIX16 B — **아직 안 켠 PC 스킬**의 [켜기] 칩(PC 유지보수 홈에서만 단다 · 주행동 하나).
     ★공용 카드는 무변이다 — `cardHtml` 이 `offLabel` 을 받았을 때만 이 칩이 선다. */
.skcard-off { font-size: 11px; font-weight: var(--fw-2, 500); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface, #FFFFFF));
  border-radius: var(--r-chip, 999px); padding: 1px 8px; }
/*   ★기기 상태 줄 — 어느 PC 가 켜져 있는지 **맨 위 한 줄**이 말한다(그 다음이 카드다). */
.skr-dev { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 2px 0 12px; }
.skr-dev .wk-chip { margin-left: 0; }
.skr-dev .wk-chip.is-on { color: var(--wk-live, #17A34A);
  background: color-mix(in srgb, var(--wk-live, #17A34A) 10%, var(--surface, #FFFFFF)); }
.skr-dev .wk-chip.is-off { color: var(--muted);
  background: var(--surface-2, rgba(148,163,184,.15)); }
.skr-seen { font-size: 11.5px; color: var(--muted); }
.skr-asleep { color: var(--muted); }
/*   ★꺼져 있으면 카드가 **흐려진다** — 없어지지 않는다(무엇이 있는지는 보여야 한다). */
.pccare-home.is-asleep .skcard-grid { opacity: .55; }
.skcard-goal { margin-top: 8px; font-size: 12.5px; color: var(--muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/*   ★W-UIX10 ③ — 목록 보기의 단계 글자를 스킬 카드 글자와 같은 크기로(숫자를 새로 만들지 않는다). */
.skc-spec-flow li { font-size: 12.5px; }

.sk-click { cursor: pointer; }
.sk-click:hover { filter: brightness(1.08); }
/* 다이어그램 간소화(Phase 62 재지시) — 노드의 세부 업무 드롭다운 토글 */
.dg-toggle { background: var(--panel); border: 1px solid var(--border); color: var(--muted);
  border-radius: 999px; cursor: pointer; padding: 1px 9px; font-size: 10.5px;
  white-space: nowrap; }
.dg-toggle:hover { color: var(--text); border-color: var(--accent); }
.sk-ai-ic { width: 14px; height: 14px; vertical-align: -2px; }   /* 프리미엄 = 워키 AI 아이콘 */
/* 스토어 진입 시 우측 캔버스 스킬 탭만 표시(58-2 후속) — 다른 탭 오픈/닫기 시 자동 해제 */
/* ★2026-08-05 — `.skill-solo`(스킬 단독 모드) 규칙을 걷었다: 스킬 상세가 [내 업무] 로
   내려가면서 이 클래스를 **거는 곳이 사라졌다**(죽은 규칙 0). */
/* ⚡실행 드롭다운(2026-07-13) — 활성 스킬을 탭 대신 드롭다운 1개로 나열(넘침 방지).
   .cv-tab 필(pill) 톤과 맞춘 컴팩트 select. 스토어 단독(설정) 모드에서는 숨김(실행은 내 업무 한정). */
/*   ★★W-UIX16-F4 ②(사장님 실기) — 탭 줄에서 **이것만 알약**이었다. 부품은 한 벌이라
     `.cv-tab` 의 결을 그대로 입는다(채움 0 · 테두리 0 · 활성은 잉크 + 강조색 밑줄).
   ★고르는 방식은 안 바꾼다 — 여럿 중 하나를 고르는 자리라 드롭다운 그대로다. */
.cv-skill-select { max-width: 220px; cursor: pointer; appearance: none;
  padding-right: 22px; background-image: none; }
.cv-skill-select:not([value=""]):not(:invalid) { color: var(--text); }
.cv-skill-select:hover { color: var(--text); }

/* 번역 대조표 검수 폼(Phase 58-3) — 캔버스 일회성 뷰 */
.ar-wrap { padding: 14px; display: flex; flex-direction: column; gap: 10px; height: 100%; }
.ar-scroll { flex: 1; overflow: auto; border: 1px solid var(--border); border-radius: 10px; }
.ar-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.ar-table th { position: sticky; top: 0; background: var(--panel-2); color: var(--muted);
  font-weight: 700; padding: 6px 8px; text-align: left; border-bottom: 1px solid var(--border); }
.ar-table td { padding: 5px 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.ar-pg { color: var(--muted); width: 28px; }
.ar-origin { color: var(--muted); white-space: nowrap; }
/* ★W-TRANS1-T7 — 번역 칸 옆 확인 표식(사유는 툴팁) */
.ar-flag { color: var(--c-amber); display: inline-flex; vertical-align: middle; cursor: help; }
.ar-flag svg { width: 13px; height: 13px; }
.ar-auto { color: var(--muted); font-size: 11px; }
.ar-fix { width: 130px; font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 3px 7px; }
.ar-apply-tgl { vertical-align: middle; }   /* 형상은 공용 .switch 정의가 준다(86.6) */
.ar-submit { align-self: flex-start; }
/* ★W-TRANS1-T10 ④⑤ — 제목 줄 = 제목 · [✅ 만들기] · [그림 포함] (표 아래 버튼은 걷었다) */
.ar-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ar-head .skc-title { flex: 1 1 auto; min-width: 0; }
.ar-head .ar-submit { align-self: center; }
.ar-pics { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); cursor: pointer; }
/* 장비 추출 검수 카드(Phase 66) — ar-table 상속, 단가 인풋만 ar-fix 재사용 */
.eq-price { width: 100px; font-size: 12px; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 3px 7px; }
.eq-use { width: 40px; text-align: center; }
.eq-note { color: var(--muted); }
.eq-submit { align-self: flex-start; }
/* 구글 연동 안내 모달(확인되지 않은 앱 통과법) */
.gconsent { display: flex; flex-direction: column; gap: 12px; }
.gc-lead { margin: 0; font-size: 14px; color: var(--text); line-height: 1.6; }
.gc-steps { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 9px; }
.gc-steps li { font-size: 13.5px; color: var(--text); line-height: 1.55; }
.gc-steps li b { color: var(--accent); }
.gc-note { margin: 0; font-size: 12.5px; color: var(--muted); }
.gc-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 4px; }
.gc-actions button { border-radius: 9px; padding: 9px 15px; font: inherit; font-size: 13.5px; cursor: pointer; border: 1px solid var(--border); }
.gc-cancel { background: transparent; color: var(--muted); border-color: var(--hairline); }
.gc-go { border-color: transparent; font-weight: var(--fw-3, 600);
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d); }
.gc-go:hover { filter: brightness(1.08); }
.webdoc-url {
  font-size: 12px; color: var(--muted); background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 7px; padding: 6px 9px; margin: 8px 0 2px; word-break: break-all;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
/* 업무 스킬 관리 대시보드(설정 > 업무 스킬) */
.sop-list { display: flex; flex-direction: column; gap: 10px; }
.sop-item { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; background: var(--surface, #FFFFFF); }
.sop-head { display: flex; align-items: center; gap: 8px; }
.sop-cat { flex: 1 1 auto; min-width: 0; }
.sop-vis { font-size: 12px; padding: 3px 4px; border-radius: 7px; border: 1px solid var(--border);
  width: 84px; flex: 0 0 84px;   /* 폭 축소(2026-07-05 지시) — 제목 공간 확보 */
  background: var(--panel); color: var(--text); }
/* 삭제 = Lucide 라인 아이콘(캔버스/사이드바 아이콘 테마 통일 — 2026-07-05 지시) */
.sop-del { background: none; border: none; cursor: pointer; padding: 4px; border-radius: 8px;
  color: var(--muted); display: inline-flex; align-items: center; }
.sop-del svg { width: 16px; height: 16px; }
.sop-del:hover { color: #ef4444; background: var(--panel); }
.sop-cat { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }  /* 제목만 1줄 */
.sop-text { margin-top: 6px; font-size: 13px; color: var(--muted); white-space: pre-wrap; word-break: break-word; }
.share-mini {
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 999px; cursor: pointer; padding: 3px 10px; font-size: 12px; line-height: 1.5;
}
.share-mini:hover { filter: brightness(1.15); }
.crm-my-sms, .crm-my-kakao, .inv-share {
  background: none; border: none; cursor: pointer; font-size: 13px; padding: 1px 3px; line-height: 1;
}
.crm-my { white-space: nowrap; }
#share-composer {
  position: fixed; inset: 0; z-index: 3000; background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center; padding: 18px;
}
.share-comp-box {
  width: min(480px, 100%); background: var(--panel); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px 16px calc(14px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 10px;
}
.share-comp-head { display: flex; align-items: center; justify-content: space-between; color: var(--text); }
.share-comp-x { background: none; border: none; color: var(--text); font-size: 20px; cursor: pointer; padding: 0 4px; }
.share-comp-text {
  width: 100%; box-sizing: border-box; resize: vertical; font-size: 16px;   /* iOS 자동 줌 방지 16px */
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 8px; padding: 9px 11px;
}
.share-comp-actions { display: flex; gap: 8px; justify-content: flex-end; }
/* 문자 발송은 모바일 전용 — 데스크톱(>760px)은 sms 계열 버튼 일괄 숨김 */
/* ★W5-④ — `.share-line-sms`(문자만 담은 줄)도 여기서 함께 숨긴다. 안 그러면 데스크톱에서
   **자식이 전부 숨겨진 빈 줄**이 남아 답변 밑에 8px 여백만 생긴다(숨기는 규칙은 버튼에만
   걸려 있었고, 줄을 쪼개면서 새로 닿은 자리다). 세는 규칙과 지우는 규칙을 같이 둔다. */
@media (min-width: 761px) {
  #doc-share-sms, .share-mini-sms,
  .crm-my-sms, .inv-share[data-kind="sms"], .share-line-sms { display: none; }
}
/* ★★W-CV1 ③ — 액자의 나머지 절반이 여기 있었다: `box-shadow rgba(0,0,0,.45)`.
   종이는 흰 바탕·검정 글씨 그대로 두고(다크 테마에서도 종이는 종이다 — 기획 확정),
   **떠 있는 그림자만** 가는 라인으로 바꾼다. 장이 여럿일 때 그 라인이 곧 페이지 구분선이다. */
/*   ★W-UIX14-F1 ③ — 같은 병이 **마크다운 종이**에도 있었다: 테두리가 `--border` 라
     다크에서 흰 링이 됐다. 종이는 **흰색 그대로**(기획 확정)이고 둘레만 hairline 링으로.
     ★표 경계(`.a4-page th/td`)는 **남긴다** — 걷으면 표가 표가 아니다(S3 §0-7 판정). */
.a4-page { width: min(210mm, 100%); flex-shrink: 0; min-height: 297mm; padding: 10mm; margin: 0;
  background: #fff; color: #111827; box-shadow: 0 0 0 1px var(--hairline);
  border: 0; box-sizing: border-box; font-size: 11pt; line-height: 1.65;
  word-break: break-word; }
.a4-page h1 { font-size: 20pt; margin: 0 0 12px; }
.a4-page h2 { font-size: 15pt; margin: 18px 0 8px; }
.a4-page h3 { font-size: 12.5pt; margin: 14px 0 6px; }
.a4-page p { margin: 8px 0; }
.a4-page ul, .a4-page ol { margin: 8px 0; padding-left: 22px; }
/* ★W-EDU-E1-N-B4 — 할 일 줄(- [ ])은 글머리 점 없이 체크 칸만 */
.a4-page li:has(> input[type="checkbox"]) { list-style: none; margin-left: -18px; }
.a4-page table { border-collapse: collapse; width: 100%; margin: 10px 0; }
/*   ★W-UIX14-S3 — 이 테두리는 **표 경계**라 남긴다(§0-7 판정): 걷으면 표가
     표가 아니다. 축의 '테두리를 걷는다' 는 카드·패널의 바깥선을 말한다. */
.a4-page th, .a4-page td { border: 1px solid #cbd5e1; padding: 5px 9px; }
.a4-page code { background: #f1f5f9; border-radius: 4px; padding: 1px 5px; }
.a4-page pre { background: #f1f5f9; border-radius: 8px; padding: 12px;
  white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; }
.a4-page pre code { background: none; padding: 0; }
.a4-page blockquote { border-left: 3px solid #cbd5e1; margin: 8px 0; padding: 2px 12px; color: #475569; }
/* 한 장에 흡수된 ---(페이지 나눔 후보) — 얇은 섹션 구분선으로 표시(canvas.js 그리디 채움) */
.a4-page hr.doc-sep { border: 0; border-top: 1px solid #e2e8f0; margin: 16px 0; }
@media print {
  /* 인쇄/PDF = 문서만. ★ 이전엔 body * { visibility:hidden } 로 숨겼으나 visibility 는
     레이아웃 공간을 그대로 차지 → 숨긴 채팅/사이드바(화면 높이만큼)가 빈 페이지를 만들었다
     (2026-07-16 실기기: flex 고친 뒤에도 1페이지→2페이지 잔여). 문서 외 전부 display:none 으로
     흐름에서 완전히 제거하고, 문서만 정상 블록 흐름의 유일 콘텐츠로 흘린다. */
  /* ★★W-CV1 ④ — **인쇄 주체가 그때 선언한다.** 이 절은 이제 `body.print-doc` 아래에서만 산다.
     종전에는 이 절도, 매입견적 시트의 절(app.html)도 **둘 다 전역**이라 서로의 화면을 죽였다:
     이 절의 `display:none` 이 [입력] 패인을 지워 **견적 시트 인쇄가 빈 페이지**였고, 저쪽의
     `body * { visibility:hidden }` 이 문서를 지워 **문서 인쇄도 빈 페이지**였다(사장님 신고).
     ★실측(2026-09-01): 문서·견적·Ctrl+P **네 칸 모두** 빈 페이지였다 — 이 앱은 어떤 경로로도
     인쇄가 되지 않았다. 두 절이 다른 속성(display/visibility)을 만져 덮어쓰기가 아니라
     **합쳐졌기** 때문이다. 그래서 이기고 지는 문제가 아니라 **둘 다 걷어야** 했다.
     ★거는 곳·푸는 곳은 `canvas.js printAs()` 하나다(85.10-b 짝). */
  /* ★이 한 줄만 **일부러 스코프 밖**에 둔다 — 어느 쪽을 인쇄하든 뿌리의 100vh·스크롤 잠금은
     풀어야 한다(종이에는 뷰포트가 없다). `:has()` 같은 새 셀렉터를 들이지 않는 값도 있다. */
  html, body { height: auto !important; overflow: visible !important; background: #fff; }
  body.print-doc > *:not(#app-view),
  body.print-doc #app-view > *:not(#canvas),
  body.print-doc #canvas .cv-head,
  body.print-doc #canvas .cv-body > .cv-pane:not([data-pane="document"]),
  body.print-doc .cv-pane[data-pane="document"] > *:not(#doc-frame) { display: none !important; }
  /* 남은 조상 체인 — 100vh/flex/슬라이드 포지션·패딩을 정상화(문서가 유일 콘텐츠로 흐르게) */
  /* ★★★W-CV1-H1(2026-09-01 사장님 실기 신고 · 실제 PDF 로 재현) — **종이에는 화면 연출이 없다.**
     증상: 문서 내용이 끝난 자리에 **전폭 가로선 + 아래로 번지는 음영**이 찍혔다.
     원인: `@media (max-width: 1099px) { .canvas { box-shadow: 0 0 50px rgba(0,0,0,.5) } }` —
     **모바일 오버레이 캔버스의 그림자**다. 화면에서는 안 걸리는데 종이에서는 걸린다:
     ★★**인쇄할 때 미디어쿼리의 뷰포트는 화면 폭이 아니라 용지 폭**(A4 ≈ 794px)이다.
     그래서 좁은 화면 절이 **전부 함께 켜진다**. 이 절은 그 사실을 몰라 position·width·transform 만
     `!important` 로 덮고 **장식 속성은 안 덮었다** — 덮이지 않은 그림자가 그대로 종이에 나갔다.
     ★지난 판이 이것을 못 잡은 이유도 같다: 캐스케이드를 들어올려 판정할 때 창이 1745px 이라
     그 절이 애초에 안 걸렸다(자가 실제 인쇄 조건이 아니었다). 이번엔 headless `--print-to-pdf`
     산출물을 눈으로 보고 이분해서 잡았다.
     → 이 층은 **종이다**: 화면 장식(그림자·필터·외곽선)을 여기서 전부 걷는다. */
  body.print-doc #app-view, body.print-doc #canvas, body.print-doc .cv-inner,
  body.print-doc .cv-body, body.print-doc .cv-pane[data-pane="document"] {
    display: block !important; position: static !important; transform: none !important;
    height: auto !important; min-height: 0 !important; max-height: none !important;
    width: auto !important; flex: none !important; overflow: visible !important;
    padding: 0 !important; margin: 0 !important; background: #fff !important; border: 0 !important;
    box-shadow: none !important; outline: none !important;
    filter: none !important; backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
  }
  /* .doc-frame flex(column+gap+center) → block: 브라우저는 flex 안에서 page-break 를 제대로
     분할 못 해 한 장이 여러 장으로 번진다. gap 0·정상 흐름으로.
     ★W-CV1 ③ 짝 — 화면에서 새로 준 라인 액자(border·radius·패널 배경)를 **종이에서 걷는다**.
       화면 연출이 종이로 새면 A4 마다 테두리가 찍힌다(액자를 없애러 와서 액자를 만드는 꼴). */
  body.print-doc #doc-frame { display: block !important; gap: 0 !important; align-items: stretch;
    height: auto !important; max-height: none !important; overflow: visible !important;
    padding: 0 !important; background: #fff !important;
    border: 0 !important; border-radius: 0 !important;
    box-shadow: none !important; outline: none !important; filter: none !important; }
  /* min-height 297mm 금지(용지에 297mm 강제=반올림 1px 초과로 빈 장). 내용만큼·분할은 break 규칙. */
  body.print-doc .a4-page { box-shadow: none !important; margin: 0; width: 210mm; min-height: auto;
    border: 0 !important; outline: none !important; filter: none !important;
    page-break-after: always; }
  body.print-doc .a4-page:last-child { page-break-after: auto; }
  /* ★W-UIX26(2026-09-18 · 사장님 스샷) — 표는 페이지 사이에서 **행 단위로** 나뉜다:
     표를 통째로 한 덩어리로 두면 큰 표가 다음 장으로 밀려 앞 장이 비어 보인다.
     행 하나는 쪼개지 않고(avoid), 이어지는 장에는 머리 행을 다시 세운다. */
  body.print-doc table { page-break-inside: auto !important; break-inside: auto !important; }
  body.print-doc tr { page-break-inside: avoid; break-inside: avoid; }
  body.print-doc thead { display: table-header-group; }
  body.print-doc tfoot { display: table-footer-group; }
  @page { size: A4; margin: 0; }
}
/* ===== Phase 10 — 내 도구 중앙 인라인 뷰(플래너·환경설정) + 홈 통합 업무스케줄 ===== */
/* 홈 업무스케줄(Gantt) — 항상 표출 + max-height·내부 스크롤(R5: 홈 세로 과확장 방지) */
/* 홈 업무스케줄 — #dashboard(좌우 8px 패딩)와 폭 정렬(오늘의 브리핑 카드와 동일 너비) */
/* 업무 다이어그램(플로워) 영역 — 브리핑 카드 제거분만큼 확대(홈 가용 높이 채움) */
.gantt-home { margin: 0 0 12px; padding: 0 8px; flex: 1 1 auto; min-height: 0; display: flex; }
.gh-body { flex: 1 1 auto; display: flex; flex-direction: column; max-height: min(64vh, 720px);
  overflow: auto; border: 1px solid var(--border); border-radius: 12px; padding: 8px; background: var(--surface, #FFFFFF); }
/* 다이어그램 높이 채움 체인 — ToolView 가 옮기는 건 .cv-pane(래퍼)이므로 그 중간 단계까지 flex 전파.
   → #gantt-board 가 .gh-body 높이를 채우고, 범례(margin-top:auto)가 창 하단에 고정된다. */
#tv-gantt-host > .cv-pane { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 100%; }
#tv-gantt-host .gantt-board { flex: 1 1 auto; }
/* 중앙 도구 뷰(채팅과 같은 톤) — chat-main 폭 안에서 대화창 자리에 인라인 */
.tool-view { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.tv-bar { display: flex; align-items: center; gap: 10px; padding: 2px 2px 12px;
  border-bottom: 1px solid var(--border); margin-bottom: 12px; }
.tv-back { background: var(--panel-2); border: 0; color: var(--text);
  border-radius: 8px; padding: 6px 12px; font-size: 13px; cursor: pointer; }
.tv-back:hover { border-color: var(--accent); color: var(--accent); }
.tv-title { font-size: 16px; font-weight: 700; white-space: nowrap; }
/* ★★2026-08-12 ④(사장님) — 타이틀 옆 "지금 무엇을 열고 있나" 슬롯(지금은 입찰 회차).
   ★§4-3 — **비어 있으면 자리를 아예 안 차지한다**(회차를 안 연 화면에서 높이 예약 0).
   ★긴 파일명 대비: 슬롯이 **줄어드는 쪽**(`min-width:0`)이고 제목 줄은 넘치면 말줄임이다 —
   v425 ① 에서 버튼이 행 끝까지 밀렸던 것과 같은 부류라, 여기서는 **타이틀이 밀리지 않게**
   슬롯에만 shrink 를 준다(타이틀은 nowrap). */
.tv-slot:empty { display: none; }
/* ★★★2026-08-12 ①②(사장님) — **발화 자리**(`say()` 63곳의 목적지). 종전 `.ledger-bar` 줄이
   사라지면서 여기로 왔다. ★§4-3 — **뜰 때만 자리를 갖는다**(빈 줄 예약 0).
   ★★**타이틀 줄 안이 아니라 그 아래 전폭 줄**이다 — 실측이 설계를 고쳤다: 공제 반영 발화가
   **500자**였다(못 센 표현·근사 후보·가치 판정까지 실린다). 타이틀 줄에 끼우면 회차 제목
   두 줄과 폭을 나눠 갖다가 **잘리고**, 그러면 서버가 센 값이 죽는다(*"410대에 적었어요
   (합 12,439,000원)"*) — v423 ④ 에서 근거 폭 가둠을 걷어낸 것과 **같은 부류**(정보 자름 0).
   ★글자 크기는 **`.tv-*` 식구 관례**(평문 px)를 따른다 — `--fx-*` 는 fx 폼 식구의 토큰이라
   이 자리에서 쓰면 스코프 계약이 샌다(기존 검사 `test_u7_new_tokens_are_scoped…` 가 잡는다.
   `--muted`·`--border`·`--accent`·`--panel-2` 는 fx 가 아니라 기본 토큰이라 그대로 쓴다). */
.tv-note:empty { display: none; }
.tv-note { font-size: 12px; line-height: 1.5; color: var(--muted); white-space: normal;
  padding: 8px 10px; margin-bottom: 10px; border-left: 2px solid var(--accent);
  background: var(--panel-2); border-radius: 6px; }
/* ★타이틀 자리 버튼 — 입찰 작업에서 화면 이름 대신 선다(둘 중 하나 · `_syncBar` 가 가른다). */
.tv-bar > .bid-pick, .tv-bar > .bid-back { flex: 0 0 auto; }

/* ★★★2026-08-12 ③(사장님) — **표 칼럼 폭 드래그 핸들**(`colresize.js`).
   ★열 머리 오른쪽 경계에 **보이지 않는 손잡이**를 얹는다 — 새 아이콘을 만들지 않고
   커서(`col-resize`)가 "끌 수 있다"를 말한다(v423 ④ 어포던스 판단과 같은 결).
   ★끌기 쉬우려면 얇은 선보다 **잡을 폭**이 필요하다(6px) — 그래도 셀 내용은 안 가린다.
   ★색은 fx 토큰(하드코딩 0) · hover/드래그 중에만 선이 보인다. */
.bid-table th, .bid-rtable th { position: relative; }
.cr-h { position: absolute; top: 0; right: -3px; width: 6px; height: 100%;
  cursor: col-resize; user-select: none; z-index: 2; }
.cr-h::after { content: ""; position: absolute; top: 15%; left: 2px;
  width: 2px; height: 70%; background: transparent; border-radius: 2px; }
.cr-h:hover::after, .cr-h.dragging::after { background: var(--accent); }
/* ★드래그 중에는 문서 전체가 같은 커서를 쓰고 글자 선택이 안 잡힌다(끌다 텍스트가
   블록 선택되면 끌기가 끊긴다 — `resize.js` 의 `.resizing` 과 같은 형태). */
body.col-resizing { cursor: col-resize; user-select: none; }
.tv-slot { flex: 0 1 auto; min-width: 0; padding-left: 10px;
  border-left: 1px solid var(--border); line-height: 1.25; }
.tv-slot .bid-h-t { max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; display: block; }
.tv-slot .bid-h-s { white-space: normal; }
.tv-body { flex: 1; overflow-y: auto; min-height: 0; }
.tv-sub { width: 100%; }
/* 플래너 — 중앙 영역 전체 폭 사용(820px 제한 해제). 좌 캘린더 : 우 메모 = 3:2 */
.chat-main.tv-wide { max-width: none; }
/* ★도구 뷰에서도 **입력바 폭은 대화 상태와 같다**(사장님 지시 2026-07-29).
   `tv-wide` 는 도구 본문(메일 2분할·플래너 3:2)이 넓어야 해서 넣은 것인데, 입력바까지 함께
   늘어나 플래너·메일에 들어갈 때마다 하단 대화창이 788px → 1655px 로 벌어졌다(실측).
   ★푸는 자리는 `tv-wide` 가 아니라 **입력바 하나**다 — 도구 본문의 넓은 폭은 그대로 두고
   입력바만 기준 폭으로 되돌린다(둘은 넓어야 할 이유가 서로 다르다).
   모바일(≤760px)은 입력바가 `position:fixed` 전폭 고정이라 이 규칙 밖에 둔다. */
@media (min-width: 761px) {
  .chat-main.tv-wide > .chat-input {
    max-width: var(--chat-bar-max);
    width: 100%; margin-left: auto; margin-right: auto;
  }
  /* ★2026-08-02(사장님 지시) — 시트도 **같은 기준 폭**을 따른다.
     ★실측으로 잡은 함정: 간편장부에서 8px 만 맞추고 끝냈다면 **플래너·메일에서는 전혀 안 맞았다**
     (시트 279~1895 vs 입력박스 701~1473 — 한쪽 420px 씩 어긋났다). `tv-wide` 는 도구 본문만
     넓히고 입력바는 기준 폭으로 되돌리는데, 시트는 그 되돌림을 안 받고 있었다.
     ★그래서 폭의 원천도 하나로 묶는다(`--chat-bar-max`) — 시트는 거기서 **좌우 여백만큼 더**
     좁다(=보이는 입력 박스와 같은 폭). 숫자를 두 번 적지 않는다.
     ※`width: 100%` 가 필요하다: 세로 flex 항목에 auto 마진을 주면 stretch 가 풀려
       **내용 폭으로 쪼그라든다**(실측 — 114px 까지 줄었다). */
  .chat-main.tv-wide > .ai-sheet {
    max-width: calc(var(--chat-bar-max) - var(--chat-input-inset) * 2);
    width: 100%; margin-left: auto; margin-right: auto;
  }
}
/*   ★T4-g(사장님 지시) — 플래너 = **캘린더 + 할 일** 2단. 5:5 비율로 분할 배치(1fr 1fr) */
/* ★W-PLN2(2026-09-02 사장님) — **한 칸**이다(중앙은 캘린더만 · 할 일은 우측 [할 일] 탭).
   ★격자를 걷지 않고 1열로 두는 이유: 아래 폭 규칙(`--chat-bar-max`)과 모바일 블록이 이
     선택자에 걸려 있고, 다음에 무엇이 돌아올 때 자리를 다시 만들 필요가 없다. */
.planner-grid { display: grid; grid-template-columns: 1fr; gap: 16px; align-items: start; }
/* ★★W-PLN1 ②(2026-09-02 사장님) — 플래너 페이지 폭을 **대시보드와 같게**.
   플래너는 `tv-wide`(폭 제한 해제)라 캘린더가 창 끝까지 늘어났다 — 홈(대시보드)에서 넘어오면
   같은 앱인데 페이지 폭이 갑자기 바뀐다.
   ★새 상수를 만들지 않는다: `--chat-bar-max` 는 *"`.chat-main` 안의 내용 폭"* 을 뜻하는 **이미
     있는 파생값**이고(`--chat-max` − `--chat-pad`×2), 입력 도크·답변 시트가 쓰는 그 값이다.
     숫자를 여기 다시 적으면 언젠가 한쪽만 바뀐다(2026-08-02 이 값을 한 원천으로 모은 이유).
   ★`tv-wide` 자체는 건드리지 않는다 — 그것은 **다른 화면들**(메일 2분할·알림함·관리자)의 것이다.
     여기서 되돌리는 것은 **플래너의 내용 폭**뿐이다. */
.chat-main.tv-wide .planner-grid { max-width: var(--chat-bar-max); margin-inline: auto; }
.planner-col { min-width: 0; }
/*   ★★모바일(1열)에서는 **할 일이 위**다(릴리 즉답 ② · T1-b 와 순서가 다르다).
     근거: 할 일의 존재 이유가 *"전화 받고 바로 적는 즉시 기록"* 이라, 폰에서는 **빠른 추가·확인**이
     캘린더 열람보다 잦다. T1-b 때는 할 일이 '업무의 다른 창'이라 그 근거가 없었다. */
@media (max-width: 760px) {
  .planner-grid { grid-template-columns: 1fr; }
  /* ★W-PLN2 — `.planner-todo` 가 사라져 이 줄은 **죽은 규칙**이 됐다(중앙은 캘린더만).
     죽은 규칙을 남기면 다음 사람이 그 자리를 찾는다(§4-1) — 함께 걷는다. */
}
/* 내 지식(개인 파일 DnD) — 환경설정에 통합(Phase 10). 드롭존이 보이는 박스가 되도록 스타일 보강 */
.kn-drop { border: 1.5px dashed var(--border); border-radius: 12px; padding: 18px 14px; margin-top: 4px;
  text-align: center; color: var(--muted); font-size: 13px; line-height: 1.7; cursor: pointer;
  background: var(--panel-2); transition: border-color .15s, background .15s, color .15s; }
.kn-drop:hover, .kn-drop.drag { border-color: var(--accent); color: var(--text); }
.kn-drop small { display: block; margin-top: 4px; font-size: 11.5px; opacity: .8; }
.kn-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.kn-item { display: flex; align-items: center; gap: 8px; padding: 7px 10px;
  background: var(--surface, #FFFFFF); border: 1px solid var(--border); border-radius: 9px; font-size: 12.5px; }
.kn-item.busy { opacity: .5; }
.kn-item .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.kn-item .nm:hover { color: var(--accent); text-decoration: underline; }   /* 클릭=내려받기 어포던스(2026-07-15) */
.kn-item .vis { font-size: 10.5px; color: var(--muted); border: 1px solid var(--border); border-radius: 8px; padding: 0 6px; }
.kn-item .del { margin-left: auto; background: none; border: none; color: var(--muted); cursor: pointer; font-size: 13px; }
.kn-item .del:hover { color: var(--danger); }
.kn-toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%) translateY(20px);
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 10px 16px;
  font-size: 13px; color: var(--text); box-shadow: 0 4px 16px rgba(0,0,0,.3); opacity: 0;
  transition: opacity .2s, transform .2s; z-index: 3000; pointer-events: none; }
.kn-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* ★T1(2026-08-13) — Phase 13 '설정 저장' 토스트(`.wc-toast` 상단중앙)를 **걷어냈다**.
   사장님 결재: "토스트에 설정저장은 필요없어."
   ★걷어낸 진짜 이유는 이름 충돌이다 — 같은 `.wc-toast` 를 Phase 33.4 **전역 토스트**
   (`toast.js` · 우하단 · app.html 인라인 style)가 쓴다. 인라인이 뒤라 같은 특이도에서 이기지만
   **캐스케이드는 속성 단위**여서, 전역 토스트가 선언하지 않는 `position/top/left/transform/
   opacity/pointer-events` 를 여기 값이 그대로 먹였다 → 전역 토스트가 우하단 host 를 벗어나
   상단중앙에서 `opacity:0`·`pointer-events:none` 으로 **죽어 있었다**(실브라우저 재현 완료:
   `left:720px`·`top:18px`·`opacity:0`·클릭 미도달).
   ★이름 충돌은 **제거로** 푼다(가장 짧은 증명). 설정 저장 피드백은 `#set-result` 인라인 문구가
   맡는다(`settings.js`). 되살아난 전역 토스트 규격은 `app.html` 의 `.wc-toast-host` 블록이 정본. */
/* 저장 결과 인라인 문구 — 실패는 색으로도 갈린다(토스트가 맡던 성공/오류 구분을 여기가 받는다) */
.fb-result.err { color: var(--danger); }
/* 음성 기능 사용 토글(개인화) */
.set-voice-toggle { margin: 10px 0 4px; }
.set-check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13.5px; }
.set-check input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; }
/* 설정 저장 결과 모달(성공/실패 안내) */
.set-result-modal { text-align: center; padding: 8px 4px 4px; }
.set-result-modal .srm-icon { font-size: 34px; line-height: 1; margin-bottom: 10px; }
.set-result-modal .srm-msg { font-size: 14px; line-height: 1.6; color: var(--text); margin: 0 0 16px; word-break: break-word; }
.set-result-modal .modal-actions { display: flex; justify-content: center; }
.set-result-modal .modal-actions button { padding: 8px 28px; }
/* 개인 이메일 다중 계정(Phase 12) */
.email-list { display: flex; flex-direction: column; gap: 6px; margin: 6px 0 10px; }
.ec-item { display: flex; align-items: center; gap: 8px; padding: 7px 10px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 9px; font-size: 12.5px; }
.ec-item .ec-default { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); font-size: 11.5px; white-space: nowrap; }
.ec-item .ec-prov { font-size: 10.5px; color: var(--muted); border: 1px solid var(--border); border-radius: 8px; padding: 0 6px; }
.ec-item .ec-addr { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ec-item .ec-del { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 13px; }
/* ★86.8 — 계정 행의 [재연결]/[연결 테스트]는 **오늘 테마 정합을 맞춘 `.btn-accent`** 를
   그대로 쓴다(새 스타일 0). 행이 12.5px 로 좀은다 뿐이라 **크기만** 줄인다 — 색·모서리는 그대로. */
.ec-item .btn-accent { display: inline-flex; align-items: center; gap: 5px; flex: none;
  padding: 3px 9px; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.ec-item .btn-accent svg { width: 13px; height: 13px; }
.ec-item .ec-del:hover { color: var(--danger); }
/* ★86.4 메일 연결 3갈래(Gmail / MS365 / 개인메일) — 사장님 "너무 산만함"에 대한 답.
   .ec-item 과 같은 형상을 쓴다(같은 탭 안에서 카드가 두 모양이면 그게 또 산만함이다).
   .is-off = 아직 지원하지 않는 경로. ★버튼을 두지 않고 사유만 적는다 — 눌러도 안 되는 버튼보다
   "아직 안 된다"는 한 줄이 정직하다. */
.mailconn-opt { display: flex; align-items: center; gap: 8px; padding: 8px 10px; margin: 6px 0;
  background: var(--panel); border: 1px solid var(--border); border-radius: 9px; font-size: 12.5px; }
.mailconn-opt .mailconn-name { display: inline-flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.mailconn-opt .mailconn-name svg { width: 15px; height: 15px; }
.mailconn-opt.is-off { opacity: .62; }
.mailconn-opt .btn-accent { white-space: nowrap; }
/* 학습된 기억(KG) 테이블 — 설정 패널 폰트 표준(.set-* 정합)·삭제 ✕(ec-del 정합). var(--*) 만. */
.kg-table { width: 100%; border-collapse: collapse; margin-top: 6px; font-size: 13px; color: var(--text); }
/*   ★표 머리는 **옅은 톤 + 가는 밑줄**이다(S5-3 이 장부·자산·이커머스에 세운 그 결). */
.kg-table th { text-align: left; font-size: 12px; font-weight: 400; color: var(--muted);
  padding: 4px 8px; border-bottom: 1px solid var(--hairline); }
.kg-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.kg-table .kg-td-ent { font-weight: var(--fw-3, 600); white-space: nowrap; }
.kg-table .kg-td-val { color: var(--text); word-break: break-word; }
.kg-table .kg-td-del { width: 28px; text-align: right; }
.kg-table .kg-del { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 13px; line-height: 1; }
.kg-table .kg-del:hover { color: var(--danger); }
/* HITL 결재카드 — 발송 예정 계정(From) 강조(R-E 오발송 방지) */
.pa-from { margin: 4px 0 8px; padding: 6px 10px; border-radius: 8px; font-size: 12.5px;
  background: color-mix(in srgb, var(--accent) 12%, transparent); border: 1px solid var(--accent); }
/* AI 연동 모달 트리거 시 해당 설정 섹션 강조(Phase 11) */
.set-flash { animation: setFlash 1.6s ease; border-radius: 10px; }
@keyframes setFlash {
  0%, 100% { background: transparent; }
  20%, 60% { background: color-mix(in srgb, var(--accent) 16%, transparent); }
}
/* 연속 격자(공유 1px 라인) */
.cal-grid {
  display: grid; grid-template-columns: repeat(7, 1fr);
  border-top: 1px solid var(--border); border-left: 1px solid var(--border); border-radius: 8px; overflow: hidden;
}
/* ★★W-UIX14-S1-B1(사장님 실기) — **캘린더 칸 톤**(스샷: 달 안은 순백이라 바탕과 이질감 ·
   달 밖·요일 머리는 `--panel-2` 라 짙은 회색으로 튄다).
   ⇒ 달 안 = 바탕보다 **한 단계만** 밝게(흰색 아님) · 달 밖·요일 머리 = **바탕과 같은 톤**.
   ★세 값이 전부 `--surface`·`--bg` 에서 섞여 나오므로 다크는 **같은 식으로 자동**이다.
   ★칸 경계선(`--border`)은 그대로 둔다 — 격자를 읽는 선이다. */
.cal-dow {
  text-align: center; font-size: 11px; font-weight: 700; letter-spacing: .3px;
  color: var(--muted); padding: 6px 0; background: var(--bg);
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
}
.cal-dow.sun { color: #e2557b; }
.cal-dow.sat { color: #4ea1ff; }
.cal-cell {
  min-height: 96px; background: color-mix(in srgb, var(--surface, #FFFFFF) 50%, var(--bg));
  padding: 4px 5px 6px;
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 3px; overflow: hidden;
}
.cal-cell.out { background: var(--bg); }
/* ★W-UIX1 ⑦(2026-09-06 · 사장님) — 일정 있는 칸은 accent 옅은 틴트로 구분(이벤트 유무 한눈에).
   color-mix 로 테마색에 얹어 라이트/다크 자동 적응 · 달 밖(out) 칸은 틴트 안 준다(위 규칙이 이긴다). */
.cal-cell.has-ev { background: color-mix(in srgb, var(--accent) 9%,
    color-mix(in srgb, var(--surface, #FFFFFF) 50%, var(--bg))); }
.cal-cell.has-ev.out { background: var(--bg); }
.cal-cell.out .num { color: var(--muted); opacity: .55; }
.cal-cell.sat .num { color: #4ea1ff; }
/* ★★W-UIX17 ②(2026-09-13 · 사장님) — 공휴일·명절은 **일요일과 같은 톤**이다.
   ★색은 새로 만들지 않는다 — 일요일이 이미 쓰는 그 선언에 **선택자만 합류**시킨다
     (정의가 둘이 되면 언젠가 한쪽만 고쳐져 같은 빨강이 두 빨강이 된다).
   ★★그리고 **자리가 계약이다**: 토요일 규칙 **뒤**에 온다. 셋은 특이도가 같아(0,3,0) 순서가
     이기고 지는데, 앞에 두면 **토요일에 걸린 공휴일**(2026-10-03 개천절)이 파랗게 떨어진다
     — 실브라우저가 그 한 칸을 잡았다(값이 아니라 순서였다 · F7 ③·F8 ② 와 같은 부류). */
.cal-cell.sun .num,
.cal-cell.cal-hd .num,
.cal-cell.cal-hd .cal-hol { color: #e2557b; }
/* 이름 한 줄 — 넘치면 말줄임(칸 폭이 좁아도 격자가 안 밀린다). */
/* ★W-UIX24 ②(사장님) — 휴일 이름은 **등록된 일정 글자(.cal-ev.timed)와 같은** 크기·굵기·톤이다.
   색만 다르다(쉬는 날 빨강 · 기념일 옅은 강조 — 위·아래 규칙 그대로). */
.cal-hol { font-size: 12px; line-height: 1.4; padding: 0 2px; font-weight: 400; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 기념일(쉬는 날 아님) — 옅은 강조 톤이고 **날짜 숫자는 안 건드린다**(빨강은 쉬는 날의 말이다). */
.cal-cell.cal-an .cal-hol { color: color-mix(in srgb, var(--accent) 65%, var(--muted)); }
.cal-cell.out .cal-hol { opacity: .5; }
.cal-dnum { text-align: center; }
.cal-dnum .num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px; font-size: 12px; font-weight: 600; line-height: 1;
}
.cal-dnum .num.today { background: #1a73e8; color: #fff !important; border-radius: 999px; }
.cal-evs { display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
/* 종일 일정 — 채워진 알약(내부=파랑 / 구글=그린) */
.cal-ev.allday {
  font-size: 12px; line-height: 1.5; padding: 1px 7px; border-radius: 5px;   /* ★W-UIX20 ② — 일정 글자 +1px(사장님) */
  background: #1a73e8; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-ev.allday.g { background: #0b8043; }
/* 시간 일정 — 점 + 시각 + 제목(채움 없음) */
.cal-ev.timed {
  display: flex; align-items: center; gap: 5px; font-size: 12px; line-height: 1.4;   /* ★W-UIX20 ② — +1px */
  padding: 0 2px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-ev.timed .dot { width: 7px; height: 7px; border-radius: 50%; background: #1a73e8; flex: none; }
.cal-ev.timed.g .dot { background: #0b8043; }
.sch-loc { flex: none; }
.sch-memo { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sch-add { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.sch-add-row { display: flex; gap: 6px; }
.sch-add input[type=text] {
  flex: 1; min-width: 0; padding: 7px 9px; border-radius: 8px; font-size: 12px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
}
.sch-add input[type=time] {
  flex: none; width: 78px; padding: 6px; border-radius: 8px; font-size: 12px; color-scheme: dark;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
}
.sch-add button {
  flex: none; width: 34px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--accent); cursor: pointer; font-size: 16px;
}
.sch-add button:hover { border-color: var(--accent); }

/* 설정 모달 — 라벨/힌트/구분선 */
.set-label { display: block; font-size: 13px; font-weight: 600; margin: 2px 0 6px; }
.set-hint { font-weight: 400; color: var(--muted); font-size: 12px; }
.set-divider { border: none; border-top: 1px solid var(--border); margin: 18px 0 16px; }
#settings-btn { padding: 0 12px; line-height: 1; font-size: 18px; }   /* 높이는 .sb-foot-row .ghost(34px) — UX8 ④ 로그인 행 정렬 */

/* 설정 — 단일 페이지(탭 제거). 섹션 흐름 배치이므로 패널 고정 높이 없음(페이지 전체 스크롤). */
.set-footer { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px; }

/* 외부 서비스 연동(OAuth) 행 */
.oauth-row { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.oauth-name { font-size: 14px; font-weight: 600; display: inline-flex; align-items: center; gap: 7px; }
.oauth-name svg { width: 17px; height: 17px; color: var(--muted); flex: none; }   /* 라인 아이콘(사이드바 톤) */
/* 구글 심사 전 연동 경고 — 외부 서비스 연동 라벨 아래 상시 안내 */
.oauth-warn {
  display: flex; gap: 9px; align-items: flex-start; margin: 8px 0 4px;
  padding: 10px 12px; border-radius: 10px; font-size: 12.5px; line-height: 1.55;
  color: var(--text); background: color-mix(in srgb, var(--soon, #f59e0b) 12%, var(--panel-2));
  border: 1px solid color-mix(in srgb, var(--soon, #f59e0b) 38%, var(--border));
}
.oauth-warn svg { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--soon, #f59e0b); }
.oauth-warn b { color: var(--text); font-weight: 700; }
/* ★86.5 — "연결됨" 표시 **단일 형상**(WorkCrew.connBadge 가 만드는 유일한 마크업).
   아이콘은 사슬(link/unlink) — 상태를 말하고, 조작(plug-zap/unplug)과 **다른 글리프**를 쓴다.
   ★색은 var(--ok) 하나만 쓰고 미연결은 무채색이다(문제일 때만 눈에 띄는 86.1 배지 규칙 정합). */
.conn-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--muted); }
.conn-badge svg { width: 14px; height: 14px; flex: none; }
.conn-badge.on { color: var(--ok, #2ea043); }
.oauth-status { font-size: 12px; color: var(--muted); margin-left: auto; }
.oauth-status.on { color: var(--ok, #2ea043); }
.oauth-row.disabled { opacity: .5; }
.oauth-row.disabled .oauth-status { font-style: italic; }
/* 서비스 바로가기 배지 — 타이틀 옆 외부링크 아이콘(새 탭에서 해당 서비스 열기) */
.oauth-go {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 6px; margin-left: 6px;
  color: var(--muted); border: 1px solid var(--border); text-decoration: none;
  transition: color .15s ease, border-color .15s ease, background .15s ease, transform .15s ease;
}
.oauth-go svg { pointer-events: none; display: block; }
.oauth-go:hover { color: var(--accent); border-color: var(--accent); background: var(--panel-2); transform: translateY(-1px); }
/* 연동 버튼 — 텍스트 → 아이콘 + 세련된 필(pill) 버튼(각진 그라데이션 폐기) */
.oauth-btn {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--muted);
  cursor: pointer;
  transition: transform .15s ease, background .15s ease, color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.oauth-btn svg { pointer-events: none; display: block; }
.oauth-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0, 0, 0, .18); }
.oauth-btn.connect { color: var(--accent); }
.oauth-btn.connect:hover:not(:disabled) {
  border-color: var(--accent); background: var(--panel-2);
  background: color-mix(in srgb, var(--accent) 14%, var(--panel-2));
}
.oauth-btn.disconnect { color: var(--error, #f87171); }
.oauth-btn.disconnect:hover:not(:disabled) {
  border-color: var(--error, #f87171); background: var(--panel-2);
  background: color-mix(in srgb, var(--error, #f87171) 14%, var(--panel-2));
}
.oauth-btn:disabled, .oauth-btn.muted { color: var(--muted); opacity: .5; cursor: default; }
/* 개인 이메일(IMAP/SMTP) 폼 */
.set-label.ec-head { margin-top: 16px; }
.email-config { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.email-config input, .email-config select { padding: 8px 10px; border: 1px solid var(--border);
  border-radius: 9px; background: var(--panel-2); color: var(--text);
  font-size: 12px; }   /* Phase 12 — 입력필드 기본 글자크기 축소 */
.email-config input::placeholder { font-size: 12px; }
.email-config .ec-row { display: flex; gap: 8px; }
.email-config .ec-row input:first-child { flex: 1 1 auto; }
.email-config .ec-row input:last-child { flex: 0 0 90px; }
.email-config .modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }

/* ── 능동형 넛지(2.2) — AI가 먼저 보낸 알림 메시지 ── */
.msg.bot.nudge {
  border: 1px solid var(--soon, #d29922);
  border-left: 4px solid var(--soon, #d29922);
  background: color-mix(in srgb, var(--soon, #d29922) 8%, var(--panel-2));
  border-radius: 12px; padding: 10px 12px;
}
.nudge-head { display: flex; align-items: center; gap: 8px; font-size: 13px; margin-bottom: 6px; }
.nudge-sub { color: var(--muted); font-weight: 400; font-size: 12px; }
.nudge-actions { display: flex; gap: 8px; margin-top: 10px; }
.nudge-actions button { padding: 6px 12px; font-size: 13px; }
.nudge-resolved { margin-top: 8px; font-size: 12px; color: var(--muted); font-weight: 600; }
.msg.bot.nudge.nudge-ack { opacity: .7; }

/* ── 범용 워크스페이스: HITL 결재 카드 + Thread (R1/R2) ── */
/*   ★★W-UIX14-F1 ②(사장님 실기) — 시트 머리 타이틀이 **알약 + 아이콘**이라 무거웠다.
     간결하게: 채움 0 · 아이콘 0 · **제목 500 + 캡션 12px 잿빛** 한 줄 · 시트 본문과는
     **hairline 한 줄**로 나눈다(상자가 아니라 머리다).
     ★라벨 표(`_SECTIONS[*].label`)는 **무접촉** — 화면의 모양만 바꾼다. */
.thread-chip { align-self: stretch; margin: 2px 0 10px; padding: 0 2px 8px;
  background: transparent; border: 0; border-bottom: 1px solid var(--hairline);
  border-radius: 0; color: var(--muted); font-size: 12px; line-height: 1.4; }
.thread-chip b { font-weight: var(--fw-3, 600); font-size: 13.5px; color: var(--text); }
/*   ★캡션은 제목 뒤에 **가운뎃점**으로 붙는다(줄을 늘리지 않는다). */
.thread-chip .tc-sub { color: var(--muted); }

/* ★★W-AUTO2-S2-F ④(2026-09-09 · 사장님) — 결재 카드가 **다른 카드와 같은 글자**로 선다.
   종전엔 제목이 12.5px 흐린 글씨(`.cv-card-title` 기본)라 대화창 카드(14px 본문색)와
   크기·장평이 어긋나 읽기 나빴다 ⇒ 카드 층의 값(`.chat-card .cc-head` 계열)에 맞춘다.
   ★장평은 **normal 로 못 박는다** — 부모(패인·표)에서 자간이 흘러들어오면 글자가 벌어진다. */
.cv-pending .cv-card-title { display: flex; align-items: baseline; gap: 8px;
  font-size: 14px; font-weight: 600; color: var(--text); letter-spacing: normal;
  line-height: 1.5; margin-bottom: 6px; word-break: keep-all; }
.cv-pending .pa-when { margin-left: auto; font-size: 11.5px; font-weight: 500;
  color: var(--muted); letter-spacing: normal; white-space: nowrap;
  font-variant-numeric: tabular-nums; }   /* ★숫자 폭 고정 — 카드마다 시각이 흔들리지 않게 */
.cv-pending .pa-summary, .cv-pending .pa-composed { letter-spacing: normal; line-height: 1.5; }
.cv-pending .pa-target { letter-spacing: normal; }
/* ★★W-UIX13-C L0 ①(2026-09-10 · 릴리) — 테두리 0 · **그림자 한 단계**로 띄운다(구성안 §7).
   강조는 제목 앞 **아이콘 색**이 맡는다(기다리는 중=주황 · 끝난 카드=흐림). */
.cv-pending { border: 0;
  box-shadow: var(--wk-shadow, 0 1px 2px rgba(0,0,0,.10), 0 6px 18px rgba(0,0,0,.06)); }
.cv-pending .pa-ic { width: 16px; height: 16px; flex: 0 0 auto; align-self: center;
  color: var(--soon, #d29922); }
.cv-pending.committed { opacity: .85; }
.cv-pending.committed .pa-ic { color: var(--muted); }
.pa-target { font-family: ui-monospace, monospace; font-size: 12px; color: var(--muted); margin: 2px 0 6px; word-break: break-all; }
.pa-summary { font-size: 13px; margin-bottom: 8px; }
.pa-diff { margin: 6px 0; }
.pa-diff .pa-h { font-size: 11px; font-weight: 700; color: var(--muted); margin-bottom: 2px; }
.pa-diff pre {
  max-height: 160px; overflow: auto; margin: 0; padding: 8px 10px;
  background: rgba(127,127,127,.10); border: 1px solid var(--border);
  border-radius: 8px; font-size: 12px; white-space: pre-wrap; word-break: break-word;
}
.pa-actions { display: flex; gap: 8px; margin-top: 10px; }
.pa-btn { padding: 7px 14px; border-radius: 8px; border: 0; cursor: pointer; font-size: 13px; font-weight: 600; }
.pa-btn.commit { background: var(--accent, #2f81f7); color: #fff; border-color: transparent; }
.pa-btn.cancel { background: transparent; color: var(--text); }
.pa-btn:disabled { opacity: .5; cursor: default; }
/* ★★W-CV4 ④(릴리 결재 조건 ㉡) — '작성창 반영' 된 카드의 종결 표기.
   [발송] 버튼 줄을 **대신한다**(자리를 그대로 물려받는다) — 버튼이 사라졌다는 사실이
   눈에 보여야 사람이 "아직 누를 수 있다"고 믿지 않는다(그게 중복 발송의 실제 경로다). */
.pa-composed { display: flex; align-items: center; gap: 6px; margin-top: 10px;
  padding: 7px 10px; border-radius: 8px; font-size: 13px; font-weight: 600;
  color: var(--ok, #2ea043); background: rgba(46, 160, 67, .10);
  border: 1px solid rgba(46, 160, 67, .35); }
.pa-btn.tocompose { background: transparent; color: var(--accent, #2f81f7);
  border-color: var(--accent, #2f81f7); }
.pa-status { margin-top: 8px; font-size: 13px; color: var(--soon, #d29922); }
.pa-status.hidden { display: none; }
.tk-open { background: none; border: none; padding: 0; color: var(--text); font: inherit; text-align: left; cursor: pointer; text-decoration: none; }
.tk-open:hover { text-decoration: underline; }

/* ── 분석 카드 내장: 엑셀 버튼 + 근거/출처 (우 캔버스 분석 탭) ── */
.cv-export { margin-top: 10px; }
.cv-export-btn { width: 100%; }
.cv-srcs { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.cv-srcs-h { font-size: 12px; font-weight: 600; color: var(--muted); margin-bottom: 6px; }
.cv-srcs .cv-doc { font-size: 12px; }

/* ── 좌측 '내 업무' 트리 (2·3단계 계층) ── */
/* 자율 실행 유형 마커 — ⏰ 루틴 / ⚡ 상시 */
.tt-sched { font-size: 11px; }
.tt-sched i[data-lucide], .tt-sched svg.lucide { width: 13px; height: 13px; vertical-align: -2px; }
.tt-sched.routine { color: var(--accent-2); }          /* 반복(루틴) */
.tt-sched.event { color: var(--soon, #f59e0b); }       /* 상시(이벤트) */
.tt-sched.once { color: var(--muted); }                /* 단건(예약 1회) */
/* 트리 드래그&드롭 이동(잠금 해제 시) */
.tt-node[draggable="true"] > .tt-row { cursor: grab; }
.tt-node.tt-dragging { opacity: .5; }
.tt-node.tt-drop > .tt-row { outline: 2px dashed var(--accent); outline-offset: -2px; border-radius: 7px; }
/* 형제 순서변경(드래그) — 위/아래 삽입선. inside(=하위로)는 outline 으로 구분. */
.tt-node.tt-drop-before > .tt-row { box-shadow: inset 0 3px 0 var(--accent); border-radius: 7px; }
.tt-node.tt-drop-after  > .tt-row { box-shadow: inset 0 -3px 0 var(--accent); border-radius: 7px; }
/* 최상위로 이동 드롭존 — 목록 '맨 아래'. 평소 숨김, 드래그 중에만 표시.
   ※ 맨 끝(노드들 뒤)에 두므로 display 토글해도 위쪽 노드(드래그 소스)가 안 밀려 드래그가 유지되고,
     어떤 업무 노드도 가리지 않는다. */
/* ※ display 토글은 리플로우로 드래그를 취소시키므로 금지. 항상 흐름에 두고 opacity 로만 표시/숨김
   (opacity 는 레이아웃 변화가 없어 드래그가 끊기지 않는다). 평소 투명, 드래그 중 노출. */
.tt-rootzone { display: block; opacity: 0; pointer-events: none; margin: 8px 0 2px; padding: 8px 10px;
  font-size: 11px; color: var(--accent); text-align: center; border: 1px dashed var(--accent);
  border-radius: 8px; background: color-mix(in srgb, var(--accent) 14%, var(--panel));
  transition: opacity .12s; }
.task-tree.tt-dnd .tt-rootzone { opacity: 1; pointer-events: auto; }
.tt-rootzone.tt-drop-rz { border-style: solid;
  background: color-mix(in srgb, var(--accent) 30%, var(--panel)); }
/* 6하원칙(6W1H) 배지 — 업무 노드 하단 칩(산출물/일정유형/트리거/참조) */
.tt-w6 { display: flex; flex-wrap: wrap; gap: 4px; margin: 1px 0 4px calc(var(--d, 0) * 18px + 26px); }
.tk-w6 { font-size: 10.5px; padding: 1px 6px; border-radius: 6px; background: var(--panel-2);
  border: 1px solid var(--border); color: var(--muted); white-space: nowrap; }
/* AI가 적용한 노하우(SOP) 투명 노출 — 챗 답변 하단 */
.msg-sop { margin-top: 6px; padding: 7px 10px; border-radius: 8px; font-size: 12px;
  background: color-mix(in srgb, var(--accent) 8%, var(--panel-2)); border: 1px solid var(--border);
  color: var(--muted); }
.msg-sop b { color: var(--text); }
/* ★★W-PC5-B5 — '적용한 노하우' 는 **3줄에서 접힌다**(2026-09-05 사장님 신고).
   서버는 이제 이름만 내려주지만, **이미 저장된 옛 응답**에는 절차문 원문이 실려 있다.
   그 대화를 다시 열어도 주입문이 통째로 펼쳐지지 않도록 **화면에서도 한 번 더** 막는다. */
.msg-sop .sop-body.clamp {
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.msg-sop .sop-more {
  margin-top: 4px; padding: 0; border: 0; background: none; cursor: pointer;
  font-size: 11.5px; color: var(--accent); text-decoration: underline;
}
/* PC 판정·화면 진단 카드(W-PC5-B5) — 판정 한 줄 + [고치기] 버튼. 카드 뼈대는 .chat-card 공용. */
.chat-card.pc-health .pch-list { margin-top: 6px; display: flex; flex-direction: column; gap: 6px; }
.chat-card.pc-health .pch-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 6px 8px; border-radius: 8px; background: var(--panel-2); border: 1px solid var(--border);
}
.chat-card.pc-health .pch-body { flex: 1 1 auto; min-width: 0; }
.chat-card.pc-health .pch-msg { font-size: 12.5px; color: var(--text); word-break: break-word; }
.chat-card.pc-health .pch-note { margin-top: 2px; font-size: 11px; color: var(--muted); }
.chat-card.pc-health .pch-act { flex: 0 0 auto; }
.chat-card.pc-health .pch-sev {
  flex: 0 0 auto; width: 8px; height: 8px; margin-top: 5px; border-radius: 50%;
  background: var(--muted);
}
.chat-card.pc-health .pch-sev.pch-high { background: #e5484d; }
.chat-card.pc-health .pch-sev.pch-medium { background: #f5a524; }
.chat-card.pc-health .pch-foot { margin-top: 6px; font-size: 11px; color: var(--muted); }
/* ★W-TRADE1 — 거래소 연결 안내 카드(단계 · 보안 공지) */
.trade-card .tc-lines { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; font-size: 13px; }
.trade-card .tc-notices { margin-top: 8px; padding: 6px 8px; border-radius: 8px; background: color-mix(in srgb, var(--accent) 8%, transparent); }
.trade-card .tc-notice { font-size: 12px; font-weight: 500; }
.trade-order .tc-rows { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin-top: 6px; font-size: 13px; }
.trade-order .tc-row { display: contents; }
.trade-order .tc-k { color: var(--wk-caption, var(--muted)); }
.au-trade { margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: color-mix(in srgb, var(--accent) 8%, transparent); font-size: 13px; }
.au-trade-h, .au-trade-m { color: var(--wk-caption, var(--muted)); font-size: 12px; margin-top: 2px; }
.au-trade-f { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }
.au-trade-amt { width: 110px; }
.au-trade-slot { margin-top: 8px; font-size: 13px; }
/* 기본 PC 배지·체크(W-PC5-B4) — 목록의 배지는 이름 옆, 카드의 체크는 버튼 아래. */
#dl-devices .dl-def {
  margin-left: 6px; padding: 1px 6px; border-radius: 6px; font-size: 10.5px;
  background: color-mix(in srgb, var(--accent) 18%, var(--panel-2));
  border: 1px solid var(--border); color: var(--text); vertical-align: middle;
}
.chat-card .pcd-def {
  display: flex; align-items: center; gap: 6px; margin-top: 8px;
  font-size: 12px; color: var(--muted); cursor: pointer;
}
.chat-card .pcd-def input { margin: 0; }
.chat-card.pc-device .pch-note { margin-top: 2px; font-size: 11px; color: var(--muted); }
.chat-card.pc-health .pch-causes { margin: 6px 0 0 16px; padding: 0; font-size: 12px; color: var(--muted); }

/* '＋ 새 업무' 입력 — 제목행에서 남은 폭을 채워 사이드바 폭(리사이즈)에 따라 늘고 줄어듦 */
/* 좁은 화면 대응(폴리싱 #2) — '내 업무' 라벨은 고정, 입력란이 줄어들며 가변 */
.sb-title-label { flex-shrink: 0; white-space: nowrap; }
.tt-add { display: block; flex: 1 1 min-content; min-width: 0; margin-left: 8px; }
.tt-add #tt-new {
  width: 100%; padding: 8px 10px; font-size: 14px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px; color: var(--text);
}
.task-tree { display: flex; flex-direction: column; gap: 1px; overflow-y: auto; }
.tt-node { padding-left: calc(var(--d, 0) * 18px); position: relative; }
/* 하위 노드 가이드 라인 — 들여쓰기 시작점에 세로선으로 상·하위 구분 */
.tt-node:not([style*="--d:0"])::before {
  content: ""; position: absolute; left: calc(var(--d, 0) * 18px - 9px); top: 0; bottom: 0;
  border-left: 1px solid var(--border);
}
/* 최상위(1단계) 제목 — 과한 굵기 제거(폴리싱 #3). 선택 상태만 강조로 구분 */
.tt-node[style*="--d:0"] > .tt-row > .tt-title { font-weight: 400; }
.tt-row { display: flex; align-items: center; gap: 4px; padding: 5px 3px; border-radius: 6px; }
.tt-row:hover { background: var(--panel-2); }
.tt-caret {
  flex: none; width: 22px; height: 22px; display: inline-flex; align-items: center;
  justify-content: center; background: none; border: none; color: var(--muted); cursor: pointer; padding: 0;
}
.tt-leaf { cursor: default; }
.tt-ic { width: var(--lnb-item-ic); height: var(--lnb-item-ic); display: block; }
.tt-caret:not(.tt-leaf):hover .tt-ic { color: var(--accent); }
.tt-caret:not(.tt-leaf) .tt-ic { color: var(--accent-2); }   /* 폴더(하위 있음) 강조 */
.tt-leaf .tt-ic { color: var(--muted); opacity: .75; }        /* 문서(하위 없음) */
.tt-title {
  flex: 1; min-width: 0; text-align: left; background: none; border: none; color: var(--text);
  font: inherit; font-size: var(--lnb-item-fs); cursor: pointer; padding: 1px 2px;   /* 폴리싱 #7 (15→13.5) · ★86.5 변수화(메일 LNB 와 공유하는 단일 출처) */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tt-title:hover { color: var(--accent); }
/* 선택(열어둔) 업무 — 글자색을 선택 상태로 유지 */
.tt-node.tt-selected > .tt-row .tt-title { color: var(--accent); font-weight: 700; }
.tt-node.is-done > .tt-row .tt-title { text-decoration: line-through; color: var(--muted); }
/*   ★★W-UIX14-S4 A — 여기 있던 `.tt-state` 넷을 **지웠다**: 규칙은 있는데 그 클래스를
     그리는 마크업이 `frontend/js`·`app.html` 전수에 **0 건**이었다(§0-③ 실측).
     업무 상태는 줄의 `title=` 툴팁으로만 보인다 — 상태를 화면에 새로 세우는 것은
     이 판의 일이 아니다(릴리 Q1 · 홈·자동화가 이미 상태를 보여 준다 · 트리엔 안 세운다). */
.tt-due { flex: none; font-size: 12px; padding: 2px 7px; border-radius: 9px; color: var(--muted); }
.tt-due.soon { color: var(--soon, #d29922); }
.tt-due.over { color: var(--danger, #f85149); }
.tt-acts { flex: none; display: none; gap: 2px; }
.tt-row:hover .tt-acts { display: flex; }
.tt-row:hover .tk-due { display: none; }   /* 마우스 온 시 d-day/지연 배지 숨김(액션 버튼에 자리 양보) */
.tt-a {
  width: 24px; height: 24px; background: none; border: none; color: var(--muted);
  cursor: pointer; border-radius: 5px; font-size: 14px; padding: 0;
}
.tt-a:hover { background: var(--border); color: var(--text); }
.tt-input {
  width: 100%; padding: 5px 8px; font-size: 14px; color: var(--text);   /* 폴리싱 #9 — 슬림 */
  background: var(--panel-2); border: 1px solid var(--accent); border-radius: 6px;
}
.tt-addrow { padding-left: 20px; }

/* 지난 대화 요약 배너 (업무 thread 재방문) */
/*   ★★W-UIX14-F2(사장님 실기 · 릴리 결재) — 요약 배너가 **회색 채움 + 사방 테두리**라
     튀었다(다크에서는 그 테두리가 흰 링이 되는 그 부류다 · F1 ③ 과 같은 씨앗).
     ⇒ 채움은 표면에서 바탕 쪽으로 **한 단계**(F1 ① 과 같은 결) · 사방 테두리 0 · hairline 링.
     ★★**왼쪽 강조 띠(3px)는 살린다** — 그것은 모양이 아니라 **뜻**이다: *이것은 지난 대화의
       요약이지 지금 대화가 아니다* 를 말하는 **유일한 표식**이다(릴리 판정 · 권고안 승인).
     ★강조색은 **띠에만** 둔다 — 머리 글자까지 강조색이면 색이 '행동 하나' 규칙을 흉내 낸다. */
.thread-summary {
  align-self: stretch; margin: 2px 0 10px; padding: 10px 14px;
  background: color-mix(in srgb, var(--surface, #FFFFFF) 70%, var(--bg, #F5F6F8));
  border: 0; border-left: 3px solid var(--accent);
  box-shadow: 0 0 0 1px var(--hairline); border-radius: 8px;
  font-size: 13.5px; line-height: 1.6; color: var(--text);
}
/*   ★실측: `--fw-3` 은 **600** 이고 500 은 `--fw-2` 다(style.css:67) — 릴리 지시가 500 이라
     토큰을 바꿔 집는다(폴백 숫자도 그 토큰의 값과 같게 적는다). */
.thread-summary .ts-h { display: inline-flex; align-items: center; gap: 5px;
  font-weight: var(--fw-2, 500); color: var(--text); margin-right: 6px; }
.thread-summary .ts-h .ic, .thread-summary .ts-h svg { width: 15px; height: 15px; flex: none; }


/* ================================================================
   Phase 30 — 프리미엄 디테일(아이콘·마이크로 인터랙션·라운드)
   레이아웃 골격 불변. 질감/전환만 보강.
   ================================================================ */

/* Lucide 아이콘: <i data-lucide> → <svg class="lucide"> 로 치환됨.
   기존 .ic/.tt-ic 사이징 규칙과 공존(클래스 병합). 얇은 스트로크 통일. */
.lucide { stroke-width: 1.75; }
[data-lucide] { display: inline-block; vertical-align: middle; }   /* createIcons 이전 FOUC 최소화 */
.ic, .sb-navitem .ic, svg.lucide.ic { width: 20px; height: 20px; }
.cv-close .lucide, .sb-toggle .lucide, #set-close .lucide { width: 16px; height: 16px; }
.erp-item .lucide, .b2c-item .lucide { width: 16px; height: 16px; flex: none; opacity: .85; }
.oauth-go .lucide { width: 13px; height: 13px; }
/* ★G5 Stage 1 — 라인 아이콘 스윕: 버튼/배지 컨텍스트 사이징(currentColor 자동·라이트/다크 정합). */
.sidebar-open .lucide { width: 18px; height: 18px; }
.cv-tab .lucide, .cal-today .lucide, .doc-share-btn .lucide,
#bnav-more-sheet button .lucide { width: 15px; height: 15px; }
.tt-a .lucide { width: 14px; height: 14px; }
.tk-w6 .lucide { width: 12px; height: 12px; }
.ctx-del .lucide { width: 12px; height: 12px; }
/* ★G5 Stage 2 — 간편장부·견적·b2b·설정 버튼/배지 사이징(currentColor 자동). */
.ledger-badge .lucide { width: 14px; height: 14px; }
.ledger-del .lucide, .ql-del .lucide, .kg-del .lucide, .ec-del .lucide, .crm-my .lucide { width: 13px; height: 13px; }
.qf-toolbar .lucide, .b2b-form-actions .lucide, .b2b-receipt-btn .lucide,
.b2b-xlsx-btn .lucide, .crm-send .lucide, .b2c-mini .lucide,
.set-label .lucide, .kg-head .lucide { width: 14px; height: 14px; }

/* 사이드바 메뉴 아이템 아이콘 정렬(이모지→Lucide 통일 후 간격) */
.erp-item, .b2c-item {
  display: flex; align-items: center; gap: 9px;
}

/* 마이크로 인터랙션 — 색 점프 대신 은은한 밝기 변화 + 부드러운 전환 */
.sb-navitem, .sb-newchat, .sb-toggle, .cv-close, .cv-tab,
.erp-item, .b2c-item, .b2c-item, .sidebar-open, .canvas-open, .ghost {
  transition: background .18s ease, border-color .18s ease, color .18s ease, filter .18s ease, transform .12s ease;
}
.sb-navitem:hover, .erp-item:hover, .b2c-item:hover { filter: brightness(1.08); }
.sb-navitem:active, .erp-item:active, .b2c-item:active, .cv-tab:active { transform: translateY(.5px); }

/* 부드러운 라운드 통일(딱딱한 8px 완화) — 주요 카드/메뉴/입력 */
.sb-newchat, .cv-card, .erp-item, .b2c-item, .sb-navitem { border-radius: var(--radius); }

/* 캔버스/사이드바 헤더 헤어라인 정합(글래스 위 은은한 구분선) */
.cv-head { border-bottom-color: var(--hairline); }
.sb-section { border-top-color: var(--hairline); }

/* ══ ★T4 할 일 — 카드 보드 + 모달 (UI 정본 `docs/todo_t4_*.png`) ═══════════════
   ★색·라운드·글자는 **전부 fx 토큰**이다(새 값 0). 카드/행/모달의 **형태만** 신설인데,
     정본 모양이 기존 어느 부품과도 다르기 때문이다(T3-a 가 세운 `.fx-input`·`.fx-check` 는
     그대로 쓴다 — 그게 T3 에서 가장 오래 남는 산출물이다).
   ★T4-g — 플래너 우측 칸(1열 스택). */
.td-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 20px; padding-top: 5px; }
/*   ★T4-g — **2열 그리드 배치** (사장님 지시: 각 카드가 50% 너비 차지, 높이는 가변 확장). */
/*  ★★W-UIX7 ①(2026-09-08 · 사장님) — **열 수는 컨테이너 폭이 정한다.**
    캔버스 경계선을 드래그해 넓히면 2열이 **3열**(더 넓으면 그 이상)이 되고, 좁히면
    1~2열로 돌아온다. ★캔버스 폭 손잡이(W-CV1 66vw·드래그)는 **무접촉**이다 —
    여기서 고치는 것은 *그 안에서 카드를 어떻게 늘어놓는가*뿐이다(미디어 쿼리가 아니라
    `auto-fill` 이라 **화면 폭이 아니라 이 자리의 폭**을 따른다 = 드래그가 곧바로 먹는다).
    ★최소 **300px** — 실측으로 정했다: 이 폭이라야 캔버스를 넓혔을 때 **3열**이 되고
      (1,160px 컨테이너 = 3열 · 840px = 2열 · 560px = 1열), 260px 로 두면 같은 자리에서
      **4열**이 되어 카드 안 항목이 좁아진다(사장님 지시는 3열이다). */
.td-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 12px; align-items: start; }
.td-card { display: flex; flex-direction: column; gap: 8px; min-width: 0;
  padding: 12px 12px 8px; background: var(--surface, #FFFFFF); border: 1px solid var(--border);
  border-radius: var(--fx-radius); transition: transform 0.15s ease, border-color 0.15s ease; }
/*   ★드래그 앤 드롭 시각 피드백 */
.td-card.dragging { opacity: 0.45; }
.td-card.dragover { border: 1px dashed var(--accent) !important; background: color-mix(in srgb, var(--accent) 5%, transparent) !important; }
.td-card-h { display: flex; align-items: center; gap: 8px; }
.td-card-grip { flex: 0 0 auto; color: var(--muted); cursor: grab; display: inline-flex; align-items: center; justify-content: center; opacity: 0.55; transition: opacity 0.15s ease, color 0.15s ease; font-size: 13.5px; line-height: 1; user-select: none; padding: 0 3px; font-weight: bold; }
.td-card-grip:hover { opacity: 1; color: var(--text); }
.td-card-grip:active { cursor: grabbing; }
.td-card-t { flex: 1; min-width: 0; margin: 0; font-size: 14.5px; font-weight: 600;
  color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.td-cardmenu, .td-more { flex: 0 0 auto; padding: 0 3px; border: none; background: transparent;
  color: var(--muted); font-size: 14px; line-height: 1; cursor: pointer; }
.td-cardmenu:hover, .td-more:hover { color: var(--accent); }
/*   ★[⋯] 는 **행 안**에 있다. */
/*   ★W-UIX14-S4 A — 글리프 `⋮` 를 걷었다(버튼이 lucide `more-vertical` 을 직접 든다).
     ::after 에는 아이콘 요소를 넣을 수 없어 **마크업으로 옮기는 것**이 유일한 길이다. */
.td-add { align-self: flex-start; display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 0; border: none; background: transparent; color: var(--accent);
  font-size: var(--fx-fs); font-weight: 600; cursor: pointer; }
.td-rows { display: flex; flex-direction: column; }
.td-row { display: flex; flex-direction: column; padding: 7px 2px; cursor: pointer;
  border-top: 1px solid color-mix(in srgb, var(--border) 60%, transparent); position: relative; }
.td-row:first-child { border-top: none; }
.td-row-summary { display: flex; align-items: flex-start; gap: 9px; width: 100%; }
.td-row-detail { display: none; padding: 6px 4px 8px 30px; font-size: var(--fx-fs-sm); color: var(--muted);
  border-top: 1px dashed color-mix(in srgb, var(--border) 20%, transparent); word-break: break-all; width: 100%; }
.td-row-detail.open { display: block; }
.td-row-desc { line-height: 1.45; font-size: 13px; color: var(--muted); }
.td-row-desc.empty { font-style: italic; opacity: 0.65; }
/*   ★세련된 커스텀 체크박스 스타일링 (사장님 지시) */
.td-chk-wrap { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.td-row input[type="checkbox"].td-chk { position: absolute; opacity: 0; width: 0; height: 0; }
.td-chk-custom { display: inline-block; width: 14.5px; height: 14.5px; border: 1.5px solid var(--muted);
  border-radius: 4.5px; background: transparent; transition: background-color 0.15s ease, border-color 0.15s ease;
  position: relative; flex-shrink: 0; margin-top: 2px; }
.td-row:hover .td-chk-custom { border-color: var(--text); }
.td-row input[type="checkbox"].td-chk:checked + .td-chk-custom { background-color: var(--accent); border-color: var(--accent); }
.td-row input[type="checkbox"].td-chk:checked + .td-chk-custom::after { content: ""; position: absolute;
  left: 4.5px; top: 1px; width: 3.5px; height: 7px; border: solid white; border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg); }
.td-t { flex: 1; min-width: 0; font-size: var(--fx-fs); color: var(--text); line-height: 1.45;
  word-break: break-word; overflow: hidden; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.td-row.done .td-t { text-decoration: line-through; color: var(--muted); }
.td-due { flex: 0 0 auto; font-size: var(--fx-fs-sm); color: var(--muted); }
.td-due.today { color: var(--accent); }
.td-due.late { color: var(--danger); font-weight: 600; }
/*   ★완료됨 토글 — 클릭으로 접고 펼친다(기본 접힘). 화살표가 상태를 말한다. */
.td-donehead { margin-top: 10px; font-size: var(--fx-fs-sm); color: var(--muted);
  cursor: pointer; user-select: none; display: flex; align-items: center; gap: 4px; }
/*   ★W-UIX14-S4 A — 글리프 `▸` 를 걷었다(머리가 lucide `chevron-right` 를 직접 든다).
     회전(열림 표시)은 그 아이콘에 그대로 건다 — 여는 규칙의 이름은 유지한다. */
.td-donehead > .ic { width: 13px; height: 13px; transition: transform .15s ease; }
.td-donehead.open > .ic { transform: rotate(90deg); }
.td-done-wrap { display: none; }
.td-done-wrap.open { display: block; }
.td-empty, .td-empty-all { color: var(--muted); font-size: var(--fx-fs); margin: 6px 2px; }
.td-shared { flex: 0 0 auto; }

/*   모달 — 정본 배치 그대로(제목 밑줄 · 날짜+시간 · 종일 · 설명 · 목록 · 저장).
     ★★T4-k(사장님 지시) — 배경을 **중앙 캔버스와 같은 색**으로 바꿨다(종전 = 좌측메뉴 계열).
       중앙 캔버스(`.chat-area`)가 실제로 칠하는 토큰이 `--bg` 다(theme.js 가 center 섹션에
       `--bg = 섹션색` 을 얹는다) — 그래서 여기도 `--bg` 를 쓴다. 추측이 아니라 실측이다.
     ★`!important` 3개(v477)를 걷었다: 앱에 로드되는 스타일시트는 `style.css` **하나뿐**이고
       `.td-modal` 배경을 덮는 규칙도 없다 — 막을 것이 없는데 박혀 있었다. 진짜 원인은
       "덮어씌움"이 아니라 **토큰이 안 닿는 것**이었다(모달이 body 에 붙어 섹션 테마 밖이다).
       그 뿌리는 `todo_cards.js` 의 `inheritCanvasTheme()` 가 고친다.
     ★blur 도 걷었다 — `--bg` 는 항상 불투명이라 backdrop-filter 가 **하는 일이 없다**(inert). */
.td-modal-back { position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; padding: 16px;
  background: rgba(2, 6, 23, .55); }
/*   ★W-UIX14-S4 A — 표면은 공용 토큰 하나(`--surface`)다. 종전 `--bg` 는 **바탕**이라
     카드와 모달이 같은 화면에서 다른 흰색으로 섰다(S1 이 세운 표면/바탕 구분). */
.td-modal { position: relative; width: 100%; max-width: 520px;
  padding: 0; background: var(--surface, #FFFFFF);
  border: 1px solid var(--border); border-radius: 16px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .35); max-height: 92vh; overflow-y: auto; }
/*   ★닫기 버튼을 모달 상단 헤더로 분리 — 제목 필드와 겹치지 않게(사장님 스크린샷 피드백). */
.td-modal-head { display: flex; justify-content: flex-end; padding: 10px 12px 0; }
/*   ★★T4-j — 선택자를 `.td-modal .td-x`(0-2-0) 로 올린다. 종전 `.td-x`(0-1-0) 는
     **`.fx-form button`(0-1-1) 에 지고 있었다** — 모달이 `.td-modal fx-form` 이라
     닫기 ✕ 에 알약 테두리가 둘러쳐졌다("있다≠닿는다"의 CSS 판 · 규칙은 있었는데 안 닿았다).
     ★사장님 스크린샷 두 장이 서로 다른 이유가 이것이다: [할 일] 모달은 kai 가 인라인 스타일로
     덮어 **맨 ✕**, [목록 설정] 모달은 안 덮어 **동그라미**. 둘을 맨 ✕ 로 맞춘다. */
.td-modal .td-x { border: none; background: transparent;
  color: var(--muted); font-size: 15px; cursor: pointer; padding: 2px 4px; }
.td-modal .td-x:hover { color: var(--text); border-color: transparent; }
.td-modal-body { padding: 4px 22px 20px; display: flex; flex-direction: column; gap: 6px; }
/*   ★제목 필드 높이 조절 — padding과 font-size를 키움(사장님 지시). */
.td-title { border: none; border-bottom: 1px solid var(--border); background: transparent;
  color: var(--text); font-size: 18.5px; padding: 16px 4px; margin: 0 0 12px; width: 100%; }
.td-title:focus { outline: none; border-bottom-color: var(--accent); }
/*   ★T4-j — 제목이 아이콘 열 안으로 들어왔다. `width:100%` 를 그대로 두면 아이콘+간격만큼
     넘친다(T4-b 가 316px 에서 값을 치른 그 자리) — 좁아지면 눌리게 `flex`+`min-width:0`. */
.td-title-line { margin-bottom: 12px; }
.td-title-line .td-title { flex: 1 1 auto; min-width: 0; width: auto; margin: 0; }
.td-line { display: flex; align-items: center; gap: 10px; }
.td-line.td-ind { padding-left: 26px; }
.td-ic { flex: 0 0 16px; width: 16px; height: 16px; color: var(--muted); vertical-align: middle; }
/*   ★할 일 추가 아이콘 크기 축소 (사장님 지시) */
.td-add-plus { font-size: 10.5px; font-weight: bold; margin-right: 1px; display: inline-flex; align-items: center; }
.td-date { flex: 0 1 140px; min-width: 0; }
.td-time { flex: 0 1 110px; min-width: 0; }
.td-desc { flex: 1; min-width: 0; resize: vertical; }
.td-list { flex: 0 1 180px; min-width: 0; }
.td-chk-l { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fx-fs);
  color: var(--text); cursor: pointer; }
.td-trace { margin: 4px 0 0; font-size: var(--fx-fs-sm); color: var(--muted); }

/* ===== Phase 34.1 — 모바일(≤760px): Bottom Nav 5탭 + 풀스크린 캔버스 + iOS 대응 ===== */
.bottom-nav { display: none; }
@media (max-width: 760px) {
  /* 할 일 목록 모바일에서는 1열 그리드 */
  .td-cards { grid-template-columns: 1fr; }

  /* 좌측 상단 ☰ = 드로어 열기 버튼(웹과 동일 배치, Phase 34.10) — 드로어 열림 중엔
     sidebar.js 가 자동 숨김(드로어 자체 ◀ 가 닫기 담당 = 열기/닫기 쌍) */

  /* 하단 탭 바 — 글래스 + iOS 홈바 safe-area */
  .bottom-nav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
    background: var(--glass-bg, var(--panel));
    backdrop-filter: blur(var(--glass-blur, 14px)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur, 14px)) saturate(140%);
    border-top: 1px solid var(--hairline, var(--border));
    padding: 6px max(6px, env(safe-area-inset-right))
             calc(6px + env(safe-area-inset-bottom))
             max(6px, env(safe-area-inset-left));
  }
  .bnav-item {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
    background: none; border: 0; padding: 5px 0; cursor: pointer;
    color: var(--muted); font-size: 10.5px; font-weight: 600; font-family: inherit;
  }
  .bnav-item svg { width: 21px; height: 21px; }
  .bnav-item.active { color: var(--accent); }

  /* 키보드 표시 중(텍스트 입력 포커스, mobile_nav.js kb-open) — 탭 바 숨김 +
     채팅 입력바를 바닥으로 내려 키보드 바로 위에 밀착 */
  body.kb-open .bottom-nav { display: none; }
  body.kb-open .chat-input { bottom: env(safe-area-inset-bottom); }

  /* 채팅 입력바 = 탭 바 위 고정(fixed — sticky 겹침 문제 해소, Phase 34.11).
     본문은 입력바+탭 바 높이만큼 하단 여백 확보 → 마지막 말풍선이 가려지지 않는다 */
  .chat-input {
    position: fixed; left: 0; right: 0;
    bottom: calc(58px + env(safe-area-inset-bottom));
    padding: 8px 10px; gap: 6px; z-index: 65;
    background: transparent; border-top: 0;   /* 바 배경 완전 투명 — 입력 필드만 떠 있는 느낌(Phase 34.14) */
    pointer-events: none;                     /* 투명 영역은 터치 통과(뒤 말풍선 스크롤 가능) */
  }
  .chat-input .chat-input-field, .chat-input #mic-btn, .chat-input #speak-btn { pointer-events: auto; }
  .chat-input .chat-input-field input, .chat-input .chat-input-field textarea {
    background: var(--panel); border-color: var(--border);
    box-shadow: 0 6px 22px rgba(0, 0, 0, .30);   /* 부유감 */
    border-radius: 24px;   /* 멀티라인 성장 시에도 알약 느낌 유지(999px 는 2줄+에서 왜곡) */
  }
  .chat-main { padding-bottom: calc(142px + env(safe-area-inset-bottom)); }

  /* 마이크·스피커 = 입력창 내부 우측 아이콘(별도 큰 버튼 폐지, Phase 34.11) */
  .chat-input #mic-btn, .chat-input #speak-btn {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 36px; height: 36px; padding: 0; border: 0; background: transparent;
    color: var(--muted); display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
  }
  .chat-input #speak-btn { right: 16px; }
  .chat-input #mic-btn { right: 54px; }
  .chat-input #mic-btn.hidden, .chat-input #speak-btn.hidden { display: none; }
  .chat-input .chat-input-field input { padding-right: 92px; }

  /* 설정 모달 — 좌측 네비 폭 최소화 + 카드 여백 축소(본문 공간 확보, Phase 34.11).
     app.html 인라인 규칙(#settings-modal .set-nav, 뒤 로드)보다 특이성을 올려 관통 */
  body > #settings-modal.set-in-canvas.open .modal-card { padding: 16px 12px; }   /* 열림 시 body 직속 승격 — 인라인(22/26px)보다 특이성 우위 */
  /* ★★W-ENT2 — **자리를 옮겼으면 꾸미던 규칙도 함께 옮긴다.** 이 세 줄은 좌측이 *탭 목록*
     이던 시절 값이라, 2단이 되면서 전부 뜻이 어긋났다(좁은 폭 실측이 잡았다):
       ① 84px 은 짧은 탭 이름 기준이었다 — 이제 좌측은 **대분류**라 *"함께 쓰기"·"내 데이터"* 가
          **두 줄로 갈렸다**(37 → 56px). 대분류가 한 줄로 서는 폭으로 올린다.
       ② `.set-nav-item` 은 이제 **우측 탭**이다 — 좌측에 주려던 컴팩트 패딩이 엉뚱한 층에
          걸려 `.cv-tab` 모양을 흐렸다. 대상을 `.set-group` 으로 옮긴다.
       ③ 본문 좌패딩은 `.set-main` 이 든다 — 옛 대상은 **죽은 규칙**이라 지운다. */
  #settings-modal.set-in-canvas .set-layout .set-nav { flex: 0 0 96px; }
  #settings-modal.set-in-canvas .set-layout .set-group { padding: 8px 6px; font-size: 12px; }
  #settings-modal.set-in-canvas .set-layout .set-main { padding-left: 12px; }
  /* 좁은 폭에서는 탭 낱개도 조금 눕힌다(줄이 넘치면 `.set-tabs` 가 가로로 민다 — 잘림 0). */
  #settings-modal.set-in-canvas .set-layout .set-tabs .cv-tab { padding: 6px 9px; font-size: 12px; }

  /* 우측 캔버스 = 화면 100% 풀스크린 슬라이드-인(스와이프 백은 mobile_nav.js) */
  .canvas, .app-wrap.canvas-on .canvas { width: 100vw; }

  /* iOS 포커스 자동 줌 방지 — 입력류 전부 16px 보장 */
  input, select, textarea { font-size: 16px !important; }

  /* (34.15: 일정 뷰에서도 대화창 표시 — 34.6 의 입력바 숨김 철회. 키보드 문제는
     34.13 자동 포커스 금지로 이미 해소) */

  /* 연동 탭(설정) — 좁은 폰에서 이름/상태 줄바꿈으로 라인이 틀어지던 문제(Phase 34.15):
     이름 1줄 말줄임 + 상태 축소 nowrap + 버튼 소형화로 한 줄 정렬 유지 */
  .oauth-row { gap: 6px; }
  .oauth-name { flex: 1 1 auto; min-width: 0; font-size: 12.5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .oauth-status { flex: none; font-size: 10.5px; white-space: nowrap; margin-left: 0; }
  .oauth-go { margin-left: 0; width: 20px; height: 20px; }
  .oauth-btn { width: 30px; height: 30px; border-radius: 9px; }
}
/* 더보기 액션 시트(모바일 하단 탭, Phase 34.11) — 설정/앱 설치/로그아웃 */
#bnav-more-sheet {
  position: fixed; right: 10px; bottom: calc(66px + env(safe-area-inset-bottom));
  z-index: 75; display: flex; flex-direction: column; min-width: 168px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 12px 36px rgba(0,0,0,.35); overflow: hidden;
  animation: bnav-sheet-in .16s ease;
}
@keyframes bnav-sheet-in { from { opacity: 0; transform: translateY(8px); } }
#bnav-more-sheet button {
  background: none; border: 0; text-align: left; cursor: pointer;
  padding: 13px 16px; font-size: 14.5px; font-family: inherit; color: var(--text);
  border-bottom: 1px solid var(--hairline, var(--border));
}
#bnav-more-sheet button:last-child { border-bottom: 0; }
#bnav-more-sheet button:active { background: var(--panel-2); }

/* 워키앱 설치 가이드 시트(pwa.js — 설치 프롬프트 불가 환경의 플랫폼별 단계 안내) */
#pwa-guide {
  position: fixed; inset: 0; z-index: 3000; display: flex;
  align-items: flex-end; justify-content: center;
  background: rgba(8, 14, 28, .55); backdrop-filter: blur(2px);
}
.pwa-guide-box {
  width: min(440px, 100vw);
  padding: 20px 20px calc(18px + env(safe-area-inset-bottom));
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 18px 18px 0 0; box-shadow: 0 -12px 36px rgba(0,0,0,.35);
  animation: bnav-sheet-in .16s ease;
}
.pwa-guide-title { font-size: 15.5px; font-weight: 700; color: var(--text); }
.pwa-guide-steps { margin: 12px 0 4px; padding-left: 22px; color: var(--text); font-size: 14px; line-height: 1.65; }
.pwa-guide-steps li { margin: 6px 0; }
.pwa-guide-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }
.pwa-guide-actions button {
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
  font-family: inherit; font-size: 13.5px; padding: 9px 16px; border-radius: 10px; cursor: pointer;
}
.pwa-guide-actions .pwa-guide-close {
  background: var(--accent, #38bdf8); border-color: transparent; color: #06121f; font-weight: 700;
}
@media (min-width: 761px) {
  #pwa-guide { align-items: center; }
  .pwa-guide-box { border-radius: 18px; }
}

/* (워키앱 설치는 하단 '더보기' 액션 시트로 이동 — 설정 모달 버튼 폐지, Phase 34.12) */
@media (max-width: 760px) {

  /* 모바일 영수증 2버튼(34.3) — 데스크톱에선 카메라 버튼 숨김 */
  .b2b-receipt-cam-btn { display: inline-block; }
}
@media (min-width: 761px) {
  .b2b-receipt-cam-btn { display: none; }
}

/* ★★★2026-08-08 입찰 **작업면**(S3) — 구현계획서 §3-ⓐ.
   ★전부 fx 토큰이다(하드코딩 색·글꼴 0 · 라이트/다크 둘 다) — 08-05 사장님 상시 지시. */
/* ★ledger-table 은 셀 nowrap 계약이라 좁은 창에서 넘친다 — 스크롤은 표 안에서(.bid-folds 와 동형). */
.bid-rounds { padding: 8px 0; overflow-x: auto; }
/* ★.bid-row(카드 나열)의 잔존 규칙은 걷었다 — v418 이 표로 바꾼 뒤 마크업에서 이미 죽은 이름. */
/* ★2026-08-12 ④ — `.bid-head`(작업면 안 자리)는 걷었다. 회차 제목·요약은 상단 타이틀
   옆 슬롯(`#tv-slot`)으로 갔다 — 정의만 남은 규칙은 거짓 신호다(유령 클래스 교훈). */
/* ★제목만 한 단계 크게 — 토큰에 lg 가 없으므로 **있는 토큰의 배수**로 낸다
   (없는 토큰 이름을 쓰면 브라우저가 조용히 무시해 크기가 상속값이 된다). */
.bid-h-t { font-weight: 600; font-size: calc(var(--fx-fs) * 1.15); color: var(--text);
           display: flex; align-items: baseline; gap: 8px; }
/* ★2026-08-12 후속 ① — 제목 옆 [회차 목록] 자리(`.bid-h-r`)는 **걷었다**. 버튼이 상단
   바로 옮겨 가면서(`_syncBar`) 이 감싸개는 쓰는 곳이 없어졌다 — 정의만 남은 규칙은
   다음 사람에게 "여기 무언가 있다"는 거짓 신호다(유령 클래스 교훈 · v419). */
.bid-h-s { font-size: var(--fx-fs-sm); color: var(--muted); margin-top: 4px; }
/* ★③ — 버튼이 아닌 표면(목표 select)의 앞 번호 라벨. 그룹 라벨과 같은 낯이되 번호가
   붙는 자리라 본문 색이다(그룹 라벨은 muted — 둘이 구별돼야 한다). */
.bid-n { font-size: var(--fx-fs-sm); font-weight: 600; color: var(--text);
         white-space: nowrap; }
.bid-tools { gap: 6px; flex-wrap: wrap; }
/* ★2026-08-12 ① 부수 실측 — 우측 캔버스가 열려 중앙이 좁아지면 버튼 **글자가 세로로**
   접혔다(입찰 작업에 우측이 처음 생기며 드러난 조합). 버튼은 통째로 줄바꿈한다(글자는 아니고). */
.bid-tools button { white-space: nowrap; }
/* ★표가 넓다 — **가로 스크롤은 표 안에서**(본문이 옆으로 밀리지 않게). */
.bid-folds { overflow-x: auto; }
/* ═══ ★★2026-08-11 후속 ⓒ·ⓓ(사장님) — 작업면이 `.fx-form` **스코프 안**으로 들어왔다 ═══
   묶음 표 = [매입 견적] 입력양식과 **같은 그리드 부품**(`pq-grid fx-grid` · 선언은 그 한 곳),
   목표 입력줄 = 같은 fx 필드 규칙. 여기는 **그 부품 위의 입찰 전용 보정**만 남긴다.
   ★`.fx-form` 의 `display:flex` 는 `.hidden`(전역) 과 특이도가 같아 소스 순서에 따라
   숨김이 조용히 풀린다 — 명시 규칙으로 못박는다(pquote `.lst-tsvbox.hidden` 과 같은 선례). */
.bid-work.hidden { display: none; }
/* ★2026-08-11 ⓒ — 모델명·사양 분리 + 근거 칼럼으로 표가 더 넓어졌다(920). */
.bid-table { width: 100%; min-width: 920px; }
.bid-table td, .bid-table th { vertical-align: middle; }
/* ★2026-08-11 재설계 — 머리글이 좁은 폭에서 세로로 접히지 않게(상/태 두 줄 방지).
   [이 묶음 적용]도 같은 이유(버튼 글자가 두 줄이 되면 행 높이가 다시 들쭉인다). */
.bid-table th { white-space: nowrap; }
.bid-table .num { text-align: right; }
.bid-m { font-size: var(--fx-fs); color: var(--text); }
.bid-sp { font-size: var(--fx-fs-sm); }
/* ★근거(2026-08-11 ⓒ) — 서버 발화 그대로라 길다. 작은 글씨(fx 토큰만).
   ★2026-08-12 ④(사장님) — 폭 가둠(max-width 360)을 걷었다: 근거는 ⓘ 접힘 행(colspan 전폭)에
   사는데 이 가둠이 전폭 행을 360px 로 다시 좁혀 2줄 내용이 4줄로 접히고 있었다.
   행이 이미 표 전폭이라 재배분은 가둠을 걷는 것으로 족하다(정보 자름 0). */
.bid-table .bid-basis { font-size: var(--fx-fs-sm); color: var(--muted); }
/* ★그리드 셀 보정 — pq-grid 는 "셀 = 입력"이 전제라 td 패딩이 0 이다. 이 표는 글자 셀이
   많으므로 격자 입력과 **같은 패딩**(3px 5px)을 글자 셀에 주고, 입력·버튼 셀만 0 으로 되돌린다
   (안 그러면 글자가 격자선에 붙는다 — 매입 견적 양식과 같은 낯을 유지하는 최소 보정). */
.fx-form .bid-table td { padding: 3px 5px; }
.fx-form .bid-table td.bid-pc, .fx-form .bid-table td.bid-ac,
.fx-form .bid-table td.bid-ic { padding: 0; }
/* ★입찰가 칸 — 폭은 **셀**에 고정한다(격자 규칙이 입력 폭을 100% 로 채우므로 입력이 아니라
   셀이 폭을 정한다).
   ★셀은 **table-cell 그대로** 둔다(`display:flex` 를 `td` 에 걸면 셀이 table-cell 을 잃어
   고정 레이아웃·colgroup 과 싸운다).

   ★★★2026-08-13 ①-부수(개발자 실측) — **여기 있던 규칙은 죽어 있었다.**
   바로 위 주석이 한 번 닫힌 뒤 설명 두 줄이 더 이어지고 **종결자가 한 번 더** 있었다.
   그 짝 없는 종결자부터가 CSS 파서에겐 **선택자의 시작**이라, 뒤따르는
   `.bid-pc` 블록(width 225px …)이 그 잘못된 규칙에 통째로 먹혀 **버려졌다**.
   → 08-12 에 *"실측으로 225px 로 정했다"* 고 적은 그 폭은 **한 번도 적용된 적이 없다**
   (칸은 내용 기준 자동 폭으로 서 있었다). 파일 전수로 짝 없는 종결자는 이 한 곳뿐이었다.
   ★교훈 둘: **주석은 닫힌 뒤에 이어 쓰면 안 된다**(설명이 늘면 새 주석을 연다) ·
   ★**설명에 종결자를 글자로 적으면 그 자리에서 주석이 닫힌다** — 이 주석을 쓰다가
   똑같은 실수를 세 번 냈고 검사가 바로 잡았다(그래서 여기 그 기호가 한 번도 안 나온다).

   ★★★2026-08-13 ②(사장님) — 입력과 곁말을 **두 칸으로** 갈랐다(머리는 `colspan=2`).
   한 칸에 둘이 있으면 폭을 나눠 줄 수 없어, 칼럼 폭을 끌어도 어느 쪽을 넓히는 것인지
   말할 수 없었다. 이제 앞 칸이 입력, 뒤 칸이 범위다.
   ★기본 폭 = 입력 105 + 범위 120 = **225px**(종전 한 칸에 주려던 그 합을 그대로 나눴다.
   범위 최장 `1,102,000~1,109,000원` = 114px + 좌우 여백).
   ★★이것은 **기본 폭**일 뿐이다 — 사장님이 끌어 저장하신 폭이 있으면 `colresize` 가
   그것을 입힌다(사람 손이 기본값을 이긴다). */
.fx-form .bid-table td.bid-pc { width: 105px; }
.fx-form .bid-table td.bid-rc { width: 120px; padding: 3px 5px; white-space: nowrap; }
.fx-form .bid-table td.bid-rc .bid-sp { white-space: nowrap; }
/* ★병합 머리 — 두 칸을 덮으므로 **가운데**가 그 이름의 자리다(지시 ②). */
.fx-form .bid-table th.bid-pch { text-align: center; }
/* ★★2026-08-13 ④(사장님) — **세 표의 행 키를 하나로**(묶음 표 · 공제 표준값 · 잇기).
   ★`height` 는 표 셀에서 **최소**로 동작한다 — 내용이 더 크면(2줄 모델명 등) 그대로 늘어난다.
   숫자는 `--fx-row-h` 한 곳에만 있다(위 토큰 주석에 출처와 고른 이유를 적어 두었다). */
.fx-form .bid-table tbody tr > td,
.fx-form .pqstd-map tbody tr > td { height: var(--fx-row-h); }
/* ★★★2026-08-13 ④(사장님 결재 = 거르기) — [공제표준값] 탭의 **분류 탭**.
   부품은 입찰 작업의 그것 그대로다(`bid-cats` 줄 · `bid-cat` 버튼 · 켜진 것은 `fx-go`) —
   새 색·새 규칙 0. **여기서 바꾸는 것은 크기뿐**이고, 그 이유는 자리다:

   ★★폭 실측(우측 캔버스 **300px** · 분류 11개[전체+GROUPS 6+목록 밖 4] 기준):
     · 그대로 두면 **5줄 · 182px** — 표를 밀어내고 스크롤이 늘어난다.
     · 글자를 **이미 있는 작은 토큰**(`--fx-fs-sm`)으로 내리고 패딩·간격을 줄이면
       **3줄 · 85px**(가장 넓은 버튼 118px 로 한 줄에 든다).
     → **97px(53%) 를 되찾았다.** 잘라 낸 것은 없다 — 분류는 **11개 전부** 그대로 뜬다.
   ★새 글자 크기를 만들지 않았다(표 안에서 이미 쓰는 그 토큰이다). */
.fx-form .pqstd-cats { gap: 4px; }
.fx-form .pqstd-cats .bid-cat { font-size: var(--fx-fs-sm); padding: 2px 7px; }
/* ★[이 묶음 적용]·ⓘ — 격자 안 버튼은 플랫(fx-grid 규칙)이라, 눌리는 것임을 색이 말한다
   (pq-del 과 같은 부류 · 커서는 `.fx-form button` 이 이미 준다). */
.fx-form .bid-table .bid-setfold { color: var(--accent); white-space: nowrap; }
.fx-form .bid-table .bid-info { color: var(--accent); }
/* ★작업면 안 읽기 표([나온 표현]·AI 후보)는 [매입 견적] 목록 부품(`ledger-table`)을 그대로
   쓴다 — `.fx-form table` 의 separate/간격이 그 부품의 collapse 계약을 덮지 않게 되돌린다. */
.fx-form .ledger-table { border-collapse: collapse; border-spacing: 0; }
.bid-more { display: block; width: 100%; margin: 10px 0; }

/* ★★2026-08-11 재설계(사장님 스크린샷 신고 · 산만함 해소) — 전부 fx 토큰(하드코딩 색 0).
   ⓒ 작업 순서 그룹: 라벨+세로 구분선으로 1 리스트→2 가격→3 공제·확정→4 마감이 눈에 선다. */
.bid-grp { display: inline-flex; align-items: center; gap: 6px;
           padding-right: 10px; border-right: 1px solid var(--border); }
.bid-tools .bid-grp:last-child, .bid-tools2 .bid-grp:last-child { border-right: 0; }
.bid-grp-l { font-size: var(--fx-fs-sm); font-weight: 600; color: var(--muted);
             white-space: nowrap; }
/* ★보조(필터·표현 보기)는 우측 보조 자리다 — 주 흐름과 섞이지 않게 민다. */
.bid-aux { margin-left: auto; }
/* ★가격 그룹의 목표 입력 둘 — 폭을 가둬 툴바 한 줄이 유지되게 한다. */
.bid-tools .bid-goal-v { width: 90px; }
.bid-tools .bid-goal-t { width: 140px; }
/* ⓐ·ⓒ 분류 탭 — 데이터 파생(대수 병기). ★켜진 탭은 **기존 `fx-go`** 를 그대로 입는다 —
   새 색 규칙 0(여기 hex 를 두면 아래 토큰 검사(test_bidding_s3)가 바로 잡는다). */
.bid-cats { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 0 2px; }
/* ⓒ 회차 공통 사유 승격 한 줄(없으면 hidden — §4-3 상시 예약 비대상). */
.bid-note { font-size: var(--fx-fs-sm); padding: 4px 2px; }
/* ⓒ 근거 ⓘ 칼럼 — 접힘 행은 위 행의 부록이라 경계선을 죽여 붙여 보인다.
   ★pq-grid 의 셀 테두리 규칙(0,2,1)이 이기지 못하게 그리드 스코프로 말한다. */
.bid-ic { text-align: center; width: 44px; }
.fx-form .bid-table tr.bid-detail td { border-top: 0; }
/* ★★2026-08-11 묶음 펼침(결재) — 대당 행은 위 묶음 행의 부록이다(경계선 죽임 · ⓘ 접힘과
   같은 부류). 강조는 **서버 판정**(heavy·special)을 그대로 입는다 — 전부 fx 토큰. */
.fx-form .bid-table tr.bid-udetail td { border-top: 0; }
/* ★2026-08-12 ②(사장님) — 묶음 행은 행 전체가 펼침 입구다(눌리는 것임을 커서가 말한다).
   입력칸·버튼은 제 커서를 갖고 있어 그대로 이긴다(이벤트도 위임 핸들러가 가른다).
   ★★후속 ④ — ▸ 버튼을 뗀 뒤 *"누를 수 있다"* 를 말하는 것이 커서 하나뿐이라, **행 hover**
   를 어포던스로 세운다(새 아이콘을 만들지 않는다는 지시 · 사장님 판단 요청분). 펼쳐진
   묶음은 `.bid-on` 으로 계속 눌러 둔 낯을 유지한다 — 아래 대당 행과 한 덩이로 보인다.
   ★hover 배경은 **앱 관례**를 그대로 쓴다(`--panel-2` — 위 `.sb-navitem:hover` 주석이
   세운 규칙). 새 색을 만들지 않는다(하드코딩 0 — 토큰 검사가 잡는다). */
.fx-form .bid-table tbody tr[data-i] { cursor: pointer; }
.fx-form .bid-table tbody tr[data-i]:hover > td { background: var(--panel-2); }
.fx-form .bid-table tbody tr[data-i].bid-on > td { background: var(--panel-2); }
.bid-utable { margin: 2px 0 8px; }
.bid-uheavy { color: var(--danger); font-weight: 600; }
.bid-uspec { display: inline-block; margin-left: 6px; padding: 0 6px;
             border: 1px solid var(--border); border-radius: 8px;
             font-size: var(--fx-fs-sm); color: var(--accent); white-space: nowrap; }
.bid-utable .bid-up { width: 100px; text-align: right; }
.bid-utable .bid-uapply { color: var(--accent); white-space: nowrap; }
/* ⓓ 회차 목록 표 — 행 전체가 입구다(카드 나열 폐기).
   ★후속 ⓐ — 표·행·hover·빈 문구 전부 [매입 견적] 목록 부품(`ledger-table`·`ledger-row`·
   `ledger-empty`)을 그대로 쓴다(전용 hover 규칙은 걷었다 — 부품이 이미 갖고 있다). */
/* ★2026-08-12 ①(사장님) — 파일명 굵기를 뗐다(표 안에서 한 칸만 굵으면 그 칸이 제목처럼
   읽힌다 — 여기 값들은 서로 대등하다). 색만 본문 토큰으로 남는다. */
.bid-r-t { color: var(--text); }
.bid-r-seq { white-space: nowrap; }

/* ★★2026-08-08 사장님 지시 ① — [공제표준값] 화면이 **표 둘**을 담는다(입찰 공제표 · 검수 25종).
   두 표 사이를 눈으로 갈라 준다. ★전부 fx 토큰(하드코딩 색·글꼴 0). */
.pqstd-form .pqstd-sep { margin-top: 18px; padding-top: 14px;
                         border-top: 1px solid var(--border); }
/* ★분류·부위 칸은 짧다 — 금액 칸이 밀리지 않게 폭을 준다(표가 흔들리지 않는다). */
.pqstd-form .pqstd-map .pqd-w-cat { width: 116px; }
.pqstd-form .pqstd-map input { width: 100%; }

/* ===================================================================
   에이전트 워크룸 — 떠 있는 창 (W1-a 골격 · 2026-08-15)
   기획 = docs/PHASE_AGENT_WORKROOM_PLAN.md §4 · 계획서 = docs/IMPL_PLAN_WORKROOM_W1.md §6
   ★전부 토큰(하드코딩 색 0) · CDN 0 · 새 색 발명 0.
   ★z=90 — 사이드바/캔버스/모바일 바(6~75) 위, 모든 모달(100~3000)과 토스트(9999) 아래.
     실측 근거는 계획서 §6-1 전수표. **토스트를 가리지 않는다**(기획 §4-3).
   ★자리는 인라인 style(left/bottom)이 정한다 — workroom.js 가 기기별로 기억한다.
   =================================================================== */
.wr-root {
  position: fixed; z-index: 90; width: 420px; max-width: calc(100vw - 16px);
  display: flex; flex-direction: column;
  font-size: var(--fx-fs); color: var(--text);
}
.wr-root.dragging { user-select: none; }
body.wr-dragging { cursor: grabbing; user-select: none; }

/* 접힌 바 = 상시 상태등(기획 §4-1). 펼침이면 숨는다. */
.wr-bar {
  display: flex; align-items: center; gap: 8px; cursor: grab;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--fx-radius); padding: 9px 11px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
}
.wr-root.dragging .wr-bar { cursor: grabbing; }
.wr-root.open .wr-bar { display: none; }
.wr-dot { color: var(--ok); font-size: 9px; flex-shrink: 0; line-height: 1; }
.wr-bar-text {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fx-fs-sm); color: var(--muted);
}

/* 펼친 패널 — 폭 고정 · 대화는 안에서만 스크롤(기획 §4-3) */
.wr-panel {
  display: none; flex-direction: column;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--fx-radius); overflow: hidden;
  box-shadow: 0 10px 32px rgba(0, 0, 0, .26);
}
.wr-root.open .wr-panel { display: flex; }
/* ★제목줄 **전체**가 손잡이다(사장님 지시 2026-08-17 · W11-2).
   2026-08-15 에는 ⠿·제목 글자만 손잡이였고 나머지는 접기 클릭 자리였는데, 실제로 써 보시니
   옮기려면 글자를 조준해야 했다. 이제 접힌 바(.wr-bar)와 **같은 계약**이다 — 어디를 잡아도 끌린다.
   ★끌기와 클릭은 여전히 한 표면에 산다: js 가 이동 임계(DRAG_SLOP=5px)로 가른다
   (임계 미만 = 접기 · 임계 이상 = 끌기). 커서도 .wr-bar 와 같게 grab 으로 맞춘다. */
.wr-head {
  display: flex; align-items: center; gap: 8px; cursor: grab;
  padding: 8px 10px; border-bottom: 1px solid var(--border);
  background: var(--panel-2);
}
.wr-root.dragging .wr-head { cursor: grabbing; }
.wr-grip { color: var(--muted); font-size: 12px; line-height: 1; }
.wr-title { font-size: var(--fx-fs); font-weight: 600; }
/* 제목줄의 남은 폭 — ⌄ 를 오른쪽 끝으로 민다(여기도 손잡이다 · 커서는 .wr-head 가 준다) */
.wr-headrest { flex: 1; align-self: stretch; }
.wr-btn {
  border: none; background: transparent; color: var(--muted); cursor: pointer;
  font-size: 12px; line-height: 1; padding: 3px 5px; border-radius: 7px; flex-shrink: 0;
}
.wr-btn:hover { color: var(--text); background: var(--panel-2); }
.wr-bar .wr-btn:hover { background: var(--bg); }
/* ★접기(⌄) 광학 정렬 — 사장님 4차 피드백 "너무 아래로 치우침".
   실측(실렌더 · canvas 잉크 계측): ⌄(U+2304)는 **잉크가 베이스라인 아래에 몰려 있다**
   (ascent 1px · descent 3px · Pretendard 에 없어 Arial 로 떨어진다). 그래서 flex 가 **박스**를
   정확히 가운데 두어도 **눈에 보이는 글자**는 제목보다 아래에 앉는다 — 박스 정렬과 광학 정렬은
   다른 것이다. 계측값 = 제목 글자 잉크 중심 대비 **+5.35px**.
   ★처방은 박스가 아니라 **잉크**를 옮긴다: 위 여백을 걷어 글자를 3px 올리고, 걷은 만큼 아래
   여백으로 돌려주어 **버튼 높이 18px 를 그대로 유지**한다(제목줄 높이가 흔들리지 않는다 —
   정본 §4-3 "상시 존재하는 것의 높이는 예약된다"). 남은 2px 는 relative 로 올린다.
   결과 실측 = **+5.35px → +0.35px**. ⌃(펼치기)는 반대로 잉크가 위에 몰려 있어 건드리지 않는다. */
.wr-fold { padding: 0 5px 6px; position: relative; top: -2px; }

/* 대화 영역 — 340px 안에서만 스크롤한다(창 높이가 내용 따라 흔들리지 않게) */
.wr-body { max-height: 340px; overflow-y: auto; overflow-x: hidden; padding: 10px 12px; }

/* ★새로고침 복원 경계(W7 · 결재 A-ⓓ) — **지금 일어나는 일과 기록을 섞지 않는다.**
   말풍선은 `HH:MM` 만 찍어서, 경계가 없으면 어제 줄이 오늘 것으로 읽힌다(날짜는 js 가 병기). */
.wr-sep {
  text-align: center; color: var(--muted); font-size: var(--fx-fs-sm);
  padding: 6px 0 10px; opacity: .8;
}
/* 빈 상태 — 기획 §3-3 "지금 아무 일도 없다를 정직하게 말한다" */
.wr-empty { padding: 14px 4px; text-align: center; color: var(--muted); }
.wr-empty p { margin: 0 0 6px; }
.wr-empty-sub { font-size: var(--fx-fs-sm); line-height: 1.55; opacity: .85; }

/* 모바일 — 떠다니지 않고 하단 고정 시트(기획 §4-3). 드래그는 js 가 막는다. */
@media (max-width: 760px) {
  .wr-root {
    left: 0 !important; right: 0; bottom: calc(66px + env(safe-area-inset-bottom)) !important;
    width: 100%; max-width: 100%;
  }
  .wr-bar { border-radius: 0; border-left: none; border-right: none; }
  .wr-panel { border-radius: 0; border-left: none; border-right: none; }
  .wr-body { max-height: 46vh; }
}

/* ── 워크룸 작업 대화(W1-b) — 말풍선·아바타·표정 ─────────────────────────
   ★우측 = 지휘자(사용자의 대리인) · 좌측 = 일꾼. **사용자 말풍선은 없다**(정본 규칙 4-5 경계).
   ★아바타는 말풍선 **바깥**에 선다(기획 §4-2). 전부 토큰 · 새 색 0. */
.wr-row { display: flex; align-items: flex-start; gap: 7px; margin: 0 0 9px; }
/* ★W-WR8-H1 ② — `.wr-right` 는 **더 이상 서지 않는다**(모든 줄이 좌측). 규칙을 남겨 두면
   다음 사람이 "오른쪽 줄이 있나 보다" 하고 그 길을 따라간다 — 함께 걷는다(죽은 규칙 금지). */
.wr-av { flex-shrink: 0; line-height: 0; margin-top: 2px; }
.wr-face { display: block; }
.wr-col { min-width: 0; max-width: 300px; }

.wr-meta { font-size: 10.5px; color: var(--muted); margin: 0 3px 3px; }
/* ★★★W-WR8-H2 ②(2026-09-02 사장님) — 말풍선 바탕을 **그 캐릭터 색**에 맞춘다.
   ★색은 여기 없다 — `workroom_faces.js` 의 정본 로스터가 `--wr-tone` 으로 내려 준다
     (여덟 색을 CSS 에 다시 적으면 두 벌이 되고, 언젠가 한쪽만 바뀐다).
   ★섞는 상대는 `var(--panel-2)` 다 — `theme.js` 가 테마마다 덮어쓰는 토큰이라
     **라이트/다크가 저절로 갈린다**(§1483 의 그 교훈: 파생은 쓰는 자리에서 한다).
   ★글자는 `var(--text)` 그대로다 — 14% 만 섞으므로 대비는 판 바탕과 사실상 같다.
   ★톤을 못 받으면(정본 미적재) 종전 `--panel-2` 로 떨어진다(조용히 깨지지 않는다). */
.wr-msg {
  background: var(--panel-2);
  background: color-mix(in srgb, var(--wr-tone, transparent) 14%, var(--panel-2));
  border: 1px solid var(--border);
  border-color: color-mix(in srgb, var(--wr-tone, var(--border)) 26%, var(--border));
  border-radius: var(--fx-radius); padding: 7px 10px;
  font-size: var(--fx-fs); line-height: 1.5; text-align: left;
  word-break: break-word; overflow-wrap: anywhere;
}
/* 지휘자 말풍선만 살짝 다른 바닥 — 좌우 구분이 색이 아니라 **자리**로 먼저 읽히게 약하게만 */
/* ★★W-WR8-H1 ②④(사장님 실기 2026-09-01) — **지휘자도 좌측**이고, 말풍선은 배지 쪽
   한 모서리만 각지다(말풍선 꼬리). 우측은 사용자 말풍선의 자리이고 크루 대화에는 사용자가
   없다 — 좌우로 갈라 두니 *"오른쪽은 나인가"* 가 헷갈렸다.
   ★색조는 그대로 지휘자의 것이다(`.wr-crew` = 종전 `.wr-right` 의 그 값) — 자리만 옮겼다.
   ★접힘 줄(`.ct-fold`)은 무접촉(결재). */
/* ★지휘자는 단색이 아니라 **브랜드 그라데**다(배지가 그렇다 — H2 ② 릴리 확정).
   두 색 모두 정본이 내려 준다(`--wr-tone`/`--wr-tone2`). */
.wr-row.wr-crew .wr-msg {
  background: color-mix(in srgb, var(--accent) 12%, var(--panel-2));
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--wr-tone, var(--accent)) 15%, var(--panel-2)),
    color-mix(in srgb, var(--wr-tone2, var(--accent-2)) 15%, var(--panel-2)));
}
.wr-msg { border-top-left-radius: 4px; }
.wr-meta .wr-name { font-weight: 600; }

/* ★★생각 중 = **링이 호가 되어 배지 둘레를 돈다**(W5.1 · 사장님 지시 *"이모티콘을 동그랗게
   그리면서 생각을 표시"*). 종전의 링 위 점 3개는 폐기 — 한 상태에 표현은 하나다.
   ★**이미 있던 링 하나가 모양만 바꾼다** — 새 도형 0. 그래서 정지↔생각 전환에 자리 이동이 없다.
   ★둘레 = 2π × 22.4 = **140.7**. `36 105`(≈ 1/4 호)가 "도는 것"으로 읽히는 최소치였다.
   ★`transform-box: fill-box` 는 **방어로 둔다.** 정본에 기록된 함정(W3 배지 애니에서 눈이
   2.2px 미끄러진 그 자리)을 이 링에서도 재 봤는데 — ★**이 도형에서는 물지 않았다.**
   링이 viewBox 중심(24,24)과 **동심**이라 `fill-box` 든 `view-box` 든 원점이 같은 점이 된다
   (회전각 0·90·180·270 에서 경계 상자 이동 **0.0px** 실측). 함정은 **중심에서 벗어난 도형**의
   것이다. 그래도 fill-box 를 남기는 이유는, 나중에 반지름·중심이 바뀌면 그때부터 물기 때문이다.
   ★레이아웃 비용 0 — `transform` 과 `stroke-*` 만 건드린다(리플로우 없음).
   ★**이벤트가 있을 때만** 이 클래스가 붙는다(js) — 여기서 도는 것이 가짜 장식이 아니다(§3-1). */
/* 트랙 = **같은 링을 흐리게** 한 장. 호가 도는 동안에도 지휘자의 정체 표식(강조 링)이 남는다
   — 호 하나만 돌리면 링의 3/4 이 사라져 26px 실제 크기에서 배지가 링을 잃는다(실렌더 비교). */
.wr-ring-track { opacity: .28; }
.wr-ring-think {
  stroke-dasharray: 36 105; stroke-linecap: round;
  transform-box: fill-box; transform-origin: 50% 50%;
  animation: wr-ring-spin 1.15s linear infinite;
}
@keyframes wr-ring-spin { to { transform: rotate(360deg); } }
/* ★움직임을 줄이는 설정 — 애니만 끄고 **호는 남긴다**(정지 표기). 링을 통째로 되돌리면
   '생각 중'이라는 사실 자체가 사라진다 — 줄이는 것은 움직임이지 정보가 아니다. */
@media (prefers-reduced-motion: reduce) { .wr-ring-think { animation: none; } }

/* ★"입력 중…" — 도구가 **실제로 도는 동안**에만 화면에 있다(기획 §5-5). 이벤트가 없으면
   이 줄 자체가 생기지 않으므로, 여기 애니메이션은 가짜 움직임이 아니다(§3-1).
   보고가 도착하면 이 줄이 **그 자리에서** 보고로 바뀐다(새 줄을 만들지 않는다). */
.wr-msg.wr-typing { color: var(--muted); font-style: italic;
                    animation: wr-breathe 1.4s ease-in-out infinite; }
@keyframes wr-breathe { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .wr-msg.wr-typing { animation: none; opacity: .8; } }

/* ★생각 줄(W5-①) — 전처리 4종이 **지휘자 말풍선**으로 올라왔다(사장님 5차 결정).
   ★줄 수는 줄이지 않는다(사장님이 고르신 값이다). 대신 **읽는 무게**를 낮춰 본 대화
   (도구 보고·결재 카드)와 위계를 가른다 — 기획 §6-3 *"일할 땐 프로답게"* 의 처방이다:
   ① 바닥색을 걷고 **점선 테두리**만 남긴다(말풍선이되 '아직 결과가 아닌 것'으로 읽힌다)
   ② 글자를 작게·흐리게 (`--fx-fs-sm` · `--muted`)
   ③ 기울임 — `.wr-typing` 이 이미 쓰는 **같은 부류의 신호**라 새 어휘를 만들지 않는다.
   ★애니메이션은 걸지 않는다 — 움직이는 것은 아바타의 생각 점 3개 하나뿐이다(§3-1). */
.wr-row.wr-crew .wr-msg.wr-think-msg {   /* ★H1 ② — 자리만 좌측으로, 신호는 그대로 */
  background: transparent; border: 1px dashed var(--border);
  color: var(--muted); font-size: var(--fx-fs-sm); font-style: italic;
}

/* ── 워크룸 결재 카드·손잡이(W2) — 말풍선 **안**에 산다 ───────────────────
   ★[승인]·[되돌리기]·[열기]가 워크룸 안에 있는 것이 기획 §4-2 다. 전부 fx 토큰. */
.wr-card { margin-top: 7px; }
.wr-card-detail {
  font-size: var(--fx-fs-sm); line-height: 1.55; color: var(--muted);
  white-space: pre-wrap; word-break: break-word;
  border-left: 2px solid var(--border); padding-left: 8px; margin-bottom: 7px;
}
.wr-card-acts { display: flex; gap: 6px; flex-wrap: wrap; }
.wr-cbtn {
  border: 1px solid var(--fx-btn-bd, var(--border)); background: var(--panel);
  color: var(--text); cursor: pointer; font-size: var(--fx-fs-sm); font-family: inherit;
  padding: 5px 11px; border-radius: var(--fx-pill);
}
.wr-cbtn:hover:not(:disabled) { border-color: var(--accent); }
.wr-cbtn:disabled { opacity: .5; cursor: default; }
/* 주 동작(정리하기·열기) — 색은 강조 토큰에서만 온다(새 색 0) */
.wr-cbtn-go { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.wr-card-st { display: block; margin-top: 6px; font-size: var(--fx-fs-sm); color: var(--muted); }

/* ── 워크룸 W3 — '생각 중' 한 줄 · 집중 배지 애니 ───────────────────────────
   ★둘 다 **진짜 이벤트가 켜고 끈다**(기획 §3-1) — 타이머로 도는 장식이 아니다. */
.wr-busy {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--fx-fs-sm); color: var(--muted); padding: 4px 2px 2px;
}
/* ★물결 점 3개(W9 ① · 사장님 지시). 종전엔 `::after` 가 `···` 를 **한 덩어리**로 찍어
   셋이 **동시에** 깜빡였다 — 한 요소라 위상차를 줄 수 없었다. js 가 점을 셋으로 세우고
   여기서 **지연만** 달리 주면 물결이 된다. ★keyframe 은 **하나**다(새 애니 어휘 0 —
   개수가 는 것이 아니라 `wr-busy-dots` 를 `wr-wave` 로 **바꾼** 것이다).
   ★이벤트가 있을 때만 이 줄 자체가 그려지므로 가짜 장식이 아니다(기획 §3-1). */
.wr-dots { display: inline-flex; align-items: center; gap: 3px; margin-left: 1px; }
.wr-dots i {
  width: 3px; height: 3px; border-radius: 50%; background: currentColor;
  animation: wr-wave 1.2s ease-in-out infinite;
}
.wr-dots i:nth-child(2) { animation-delay: .16s; }
.wr-dots i:nth-child(3) { animation-delay: .32s; }
@keyframes wr-wave {
  0%, 100% { opacity: .25; transform: translateY(0); }
  50%      { opacity: 1;   transform: translateY(-2px); }
}

/* ★집중 = 도구가 **실제로 도는 동안만** 배지가 미세하게 커진다(결재 ⓗ ②).
   ★①눈 깜빡임(무한 루프)은 기각됐다 — 이벤트와 무관하게 도는 장식이라 §3-1 정면 위반이다.
   ★③흔들림도 기각(표정 변화로 충분 · §6-3 의인화 수위).
   ★transform 은 부모 <svg> 에 건다 — SVG **자식**에 걸 때는 `transform-box: fill-box` 가
     없으면 원점이 뷰포트 기준이라 그 도형이 제자리를 벗어난다(실측: 눈이 2.2px 미끄러짐). */
.wr-av[data-mood="focus"] svg { animation: wr-focus-pulse 1.6s ease-in-out infinite; }
@keyframes wr-focus-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.07); } }
@media (prefers-reduced-motion: reduce) {
  .wr-av[data-mood="focus"] svg { animation: none; }
  .wr-dots i { animation: none; opacity: .8; transform: none; }
}

/* ── T1-b Todo(개인 표면) — ★전부 fx 토큰(클래식 잔존 금지 규율) ─────────────── */
/*   ★T4-c — T3 의 할 일 규칙(.todo-*)을 전부 걷었다. 그 화면이 사라졌으니 남기면
     `.set-check`·`.tk-add` 처럼 **죽은 CSS** 가 된다(T3-a 가 실측으로 확인한 그것).
     할 일의 모양은 아래 `.td-*`(카드 보드)가 갖는다. */
/* ══ ★T4 할 일 — 카드 보드 + 모달 (UI 정본 `docs/todo_t4_*.png`) ═══════════════
   ★색·라운드·글자는 **전부 fx 토큰**이다(새 값 0). 카드/행/모달의 **형태만** 신설인데,
     정본 모양이 기존 어느 부품과도 다르기 때문이다(T3-a 가 세운 `.fx-input`·`.fx-check` 는
     그대로 쓴다 — 그게 T3 에서 가장 오래 남는 산출물이다).
   ★T4-g — 플래너 우측 칸(1열 스택). */

/*   ★T4-g — **1열 스택**(구글 Tasks 사이드바 동형). 종전 2열 그리드는 중앙 전체 폭의 것이었다. */


/*   ★[⋯] 는 **행 안**에 있다. 쉴 때 폭을 거의 안 먹어야 제목이 산다(T3-c 가 행마다 선택기를
     달았다가 제목 폭 82px 을 잃고 버린 자리 — 같은 실수를 반복하지 않는다). */






/*   모달 — 정본 배치 그대로(제목 밑줄 · 날짜+시간 · 종일 · 설명 · 목록 · 저장).
     ★[반복]은 **안 그린다**(결재 T-5): 구글 API 에 반복이 없고 앱에 인스턴스 생성 엔진도
       없어서 띄우면 눌러도 아무 일이 없다. 칸만 서버에 있다.
     ★배경색을 좌측메뉴와 동일한 var(--glass-bg) 및 backdrop-filter 효과로 맞춰 일체감 제공. */

.td-foot { display: flex; justify-content: flex-end; align-items: center; gap: 8px; }

/*   카드메뉴 모달 — 목록카드 ⋮ 클릭 시 뜨는 수정 모달(제목변경·공유·삭제). */
.td-cardmenu-modal { position: relative; width: 100%; max-width: 340px;
  background: var(--surface, #FFFFFF);
  border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, .35); overflow: hidden; }
.td-cardmenu-modal h4 { margin: 0; padding: 14px 16px 10px; font-size: 14px; font-weight: 600;
  color: var(--text); border-bottom: 1px solid var(--border); }
/*   ★★T4-j — 여기 있던 카드메뉴 **행 목록**(`.td-cm-list`·이름 변경/공유/삭제 3줄)을 걷었다.
     그 화면이 [목록 설정] 통합 모달로 바뀌어 부르는 곳이 없어졌다(죽은 규칙을 남기지 않는다).
     ★껍데기(`.td-cardmenu-modal`) 자체는 **살아 있다** — 새 목록 만들기 입력 모달(T4-i)이 쓴다. */

/*   ══ ★T4-j [목록 설정] 통합 모달 — kai 실물 대조 이식 ══
     이름·공유를 한 화면에서 고치고 [적용]으로 **한 번에** 저장한다(사장님 스크린샷 정본).
     ★부품은 kai 규칙을 그대로 가져왔다 — 양 리포에서 같은 것이 같게 보여야 한다. */
.td-switch { position: relative; display: inline-block; width: 34px; height: 20px; flex: 0 0 auto; }
.td-switch input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: pointer; }
.td-slider { position: absolute; inset: 0; border-radius: 999px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border);
  transition: background .18s, border-color .18s; }
.td-slider::before { content: ""; position: absolute; top: 2px; left: 2px;
  width: 14px; height: 14px; border-radius: 50%; background: var(--muted);
  transition: transform .18s, background .18s; }
.td-switch input:checked + .td-slider { background: var(--accent); border-color: var(--accent); }
.td-switch input:checked + .td-slider::before { transform: translateX(14px); background: var(--panel); }
.td-switch input:disabled + .td-slider { opacity: .5; cursor: not-allowed; }
.td-switch input:focus-visible + .td-slider { outline: 2px solid var(--accent); outline-offset: 2px; }
/*   목록 설정 모달의 라벨 줄 — 인라인으로 흩어져 있던 것을 규칙 한 곳으로. */
.td-lbl { font-size: var(--fx-fs-sm); color: var(--muted); }
.td-name-line { margin-bottom: 12px; }
.td-name-line .td-lbl { width: 70px; flex: 0 0 70px; }
.td-name-line .td-menu-title { flex: 1; min-width: 0; }
.td-switch-line { margin-bottom: 16px; justify-content: space-between; }
.td-menu-modal-t { margin: 0 0 14px; font-size: 16px; font-weight: 600; color: var(--text); }
/*   ★[목록 삭제]는 왼쪽 끝(`margin-right:auto`)·[적용]은 오른쪽 — 스크린샷 배치가 정본이다. */
.td-menu-foot { display: flex; justify-content: flex-end; gap: 8px;
  border-top: 1px solid var(--border); padding-top: 12px; }

/*   ★T4-c — 여기 있던 T3 할 일 규칙(`.todo-secs/-sec/-add/-list/-row/-t/-due/-chk`)과
     폰 폭 미디어쿼리를 걷었다. 그 화면(`todo.js`·플래너 우측 칸)이 사라졌으므로 남기면
     **죽은 CSS** 다 — T3-a 가 `.set-check`·`.tk-add` 로 실측해 확인한 그 부류다.
     ★그 판이 실측으로 정한 400px 경계값도 함께 간다(그 폼이 없으니 잴 것이 없다).
     할 일의 모양은 위 `.td-*`(카드 보드)가 갖는다. */

/* ══ ★★W-DEL1-b 탈퇴 유예 — 배너(취소 표면 ①)·설정 탭 상태(②) ══
   ★되돌리는 길이 **눈에 안 보이면 없는 것과 같다** — 그래서 배너는 화면 맨 위에 상시 뜬다.
   신청이 없으면 `.hidden` 이라 평소 화면에는 아무 영향이 없다. */
.del-banner { position: sticky; top: 0; z-index: 200; display: flex; align-items: center;
  justify-content: center; gap: 12px; flex-wrap: wrap;
  padding: 9px 14px; font-size: var(--fx-fs, 12.5px);
  background: color-mix(in srgb, var(--danger, #f87171) 16%, var(--panel));
  color: var(--text); border-bottom: 1px solid var(--danger, #f87171); }
.del-banner.hidden { display: none; }
.del-banner-t { line-height: 1.5; }
/* 설정 > 회원탈퇴 탭의 신청 상태 줄 — 배너와 같은 말을 하되 화면 안에 있다. */
.del-pending { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin: 10px 0; padding: 10px 12px; border-radius: var(--fx-radius, 12px);
  background: color-mix(in srgb, var(--danger, #f87171) 12%, transparent);
  border: 1px solid var(--danger, #f87171); font-size: var(--fx-fs, 12.5px); color: var(--text); }

/* ══ ★★M3 ①ⓐ 메일 결재카드(대화창판) — 사용자가 누를 버튼은 보고 있는 화면에 있어야 한다.
   ★모양은 옆 카드(`.chat-card`·각인 제안)와 같은 계열을 쓴다 — 새 부품 0. */
.chat-card.mail-action .ma-detail { margin-top: 4px; font-size: var(--fx-fs-sm, 11.5px);
  color: var(--muted); line-height: 1.5; white-space: pre-line; }
.chat-card.mail-action .ma-diff { margin-top: 4px; font-size: var(--fx-fs, 12.5px);
  color: var(--text); line-height: 1.6; }

/* ★모델 없이 처리(Mock 강등) — 0 이 아니면 눈에 띄어야 한다. 화면이 멀쩡해 보이는 것이
   바로 이 지표의 위험이라, 숫자가 서면 색으로 말한다(계측 판 A · 2026-08-26).
   ★`--fx-*` 가 아니라 `--danger` 를 쓴다: fx 토큰은 **fx 식구 셀렉터 안에서만** 쓰는 것이
   규칙이고(`test_u7` 가 그 자리를 지킨다 — 실제로 나를 잡았다), admin 층은 `--muted`·`--text`
   처럼 **공용 토큰**을 쓰는 것이 이 파일의 관례다. */
.admin-llm-warn { color: var(--danger, #e5484d); font-weight: 600; }

/* ★★W-MYWORK 단계 1 — 📄 문서 폴더 목록. 새 색을 만들지 않는다(기존 카드 팔레트 재사용). */
.docs-list { display: flex; flex-direction: column; gap: 8px; padding: 4px 2px 12px; }
/*   ★★W-UIX14-S4 A — **죽은 규칙 다섯을 지웠다**(`.docs-row`·`:hover`·`.docs-row-h`·
     `.docs-badge`·`.docs-meta`): 옛 카드형 목록의 것이고 마크업 전수에 **0 건**이다.
     ★그러나 `.docs-list`·`.docs-ic`·`.docs-ti`·`.docs-empty` 는 **살아 있다** —
     `.docs-list` 는 우측 [참고자료] 패인(`app.html` · `canvas.js` 가 그린다)이고
     나머지 셋은 📄 문서 표가 쓴다. 지시서가 함께 지우라 한 셋 중 하나가 이것이었다. */
.docs-ic { flex: 0 0 auto; }
.docs-ti { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.docs-empty { font-size: 13px; color: var(--muted, #8aa0bd); padding: 12px 2px; }

/* ★★W-MYWORK 단계 2 — 내 업무 **꼬리 고정 항목**(📄 문서 · 🖥 PC 유지보수)과 흐린 상태.
   ★흐림은 "죽은 손잡이"가 아니라 **상태 표시**다 — 왜 그런지는 title 이 말하고, 누르면
   켜는 자리로 보낸다(행을 만들지 않는다 · 릴리 Q2). */
.tt-fixed { margin-top: 2px; }
.tt-fixed .tt-caret { font-size: 13px; line-height: 1; }
.tt-dim { opacity: .45; }
.tt-dim .tt-title { cursor: help; }
#automation-nav.tt-dim { opacity: .45; }

/* ★★W-MYWORK 단계 3 — ⚙️ 자동화 탭 카드. 새 색을 만들지 않는다(기존 카드 팔레트 재사용). */
/*   ★W-UIX13-C2 ② — 카드 사이 **10**(구성안 §5 목업 `.cards{gap:10px}`). */
/*   ★W-UIX13-C3 — 우측 캔버스 여백 14px 확보(목업 `.cards{padding:12px 14px}`). */
.au-list { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px; }
.au-h { font-size: 12px; color: var(--muted, #8aa0bd); text-transform: none;
  letter-spacing: .3px; margin: 8px 0 2px; font-weight: 700; }
/* /* ★★W-UIX13-C3(구성안 §5 목업 원안 일치) — 카드는 **순백색 솔리드 서피스**(다크: 서피스 패널색)와
   부드러운 그림자로 배경 위에 뜬다. 테두리 0.
   ★W-UIX13-C4 — 카드는 마우스 오버 인터랙션 없이 정갈한 서피스를 유지한다.
   작동중(live)일 때만 초록 글로우로 상태를 알리고, 기본·지켜보는 중은 일반 그림자색을 유지한다. */
/* ★★★W-UIX14-S1(2026-09-11 · 사장님 "회색 카드 배경의 고리타분함을 지우고 깔끔하게") —
   **공용 카드는 `.wk-card` 하나다.** 자동화 화면이 이미 입고 있던 옷(`.au-card`)을 그대로
   승격하고, 1세대 공용 카드 `.fx-card` 의 규칙을 **이 레시피로 교체**한다.
   ⇒ `.fx-card` 를 입던 6 파일(dashboard·todo_cards·skills·ecom_dashboard·b2b_tax·bizdash)이
     **마크업 한 줄 안 고치고** 함께 바뀐다.
   ★바뀌는 둘: 테두리 1px → **0**(구분은 표면 대비 + 링 1px + 그림자가 한다) ·
     `translateY(-3px)` 호버 들썩임 **삭제**(사장님 Q1 · C5 와 같은 결 — 마우스가 지날 때마다
     글이 흔들리면 읽기를 방해한다).
   ★세 이름을 **한 블록**에 나열한다(별칭) — 두 벌로 적으면 언젠가 한쪽만 고쳐진다. */
/*   ★W-UIX14-S4 B — SOP 의 판 셋(명세·단계·미리보기)이 여기 합류했다. 레시피를 베껴
     오면 ratchet R4 가 *"화면이 제 카드를 새로 그렸다"* 고 잡는다 — 그리고 그것이 맞다.
     ★padding 은 판마다 달라 각자 준다(아래) — 여기서 주는 것은 **표면**이다. */
/*   ★W-UIX14-S5-1 — 장부·세무·가계부의 판 넷이 합류했다. 표면·테두리·그림자는
     여기 한 자리에서만 나온다(각자 베끼면 고칠 곳이 넷이 된다). */
/* ══════════════════════════════════════════════════════════════════════════
   W-UIX14 축 마감(2026-09-12) — **별칭 목록**: 이 이름들은 새 부품이 아니라
   공용 레시피를 **빌려 쓰는 이름**이다. 다음 사람이 "왜 이 클래스는 규칙이 없지?" 로
   헤매지 않도록 한 자리에 적는다. ★고치려면 **공용 쪽**을 고쳐라 — 그러면 전부 따라온다.

   카드(.wk-card) ← .au-card .fx-card .skc-spec .skc-step .skr-preview .tax-card
                    .tax-metric .bk-card .bk-pin-card .as-scrap-panel .asc-card
                    .onb-card .eco-card .eco-home-card .eco-det-sec
   타일(.wk-tile) ← .tile
   줄(.wk-row)    ← .af-row · (결만 빌림) .onb-step · #dl-devices .dl-row
   칩(.wk-chip)   ← .au-chip · (결만 빌림) .onb-req .onb-soon .ec-badge .adm-badge
                    .adm-fb-cat .mr-tags .as-pre
   보조 버튼(.btn-sub) ← .cal-nav .cal-today · (결만 빌림) .onb-btn .adm-btn .ghost
                        #demo-hero .demo-chip .mrc-btn .mu-btn .mail-search-remote
   주행동(.btn-accent) ← (결만 빌림) .onb-primary .gc-go .mail-new .ad-save
                        .as-finalize .confirm-yes .modal-actions button

   ★"결만 빌림" = 선택자 목록에 합류한 것이 아니라 **같은 값을 제 규칙에 적은 것**이다.
     합류(목록에 이름을 더하는 것)가 더 낫고, 패딩·폭이 그 화면 몫이라 못 합칠 때만 빌린다.
   ══════════════════════════════════════════════════════════════════════════ */
.wk-card, .au-card, .fx-card, .skc-spec, .skc-step, .skr-preview,
/*   ★W-UIX14-S5-2 — 자산의 판 셋(폐기 패널·스캔 카드·검수 상세)이 합류했다. */
.tax-card, .tax-metric, .bk-card, .bk-pin-card,
/*   ★★W-UIX14-S5-3 — 이커머스 카드 넷이 합류했다. ★그중 `.eco-home-card` 는 **자산 화면이
     빌려 쓰는 타일**이기도 하다(요약 다섯) — 여기서 흰 표면이 되면 **두 화면이 함께** 바뀐다
     (릴리 실화면 지적 ①). 같은 것을 두 벌로 만들지 않는 것이 그래서 값을 한다. */
.as-scrap-panel, .asc-card,
/*   ★W-UIX14-S6-A — 온보딩 카드가 합류했다(입구·설정·관리자 판에서 유일한 카드 자리). */
.onb-card,
/*   ★W-CODEX-RED8 — 회의록 검수 카드가 합류했다(09-16 외주 판이 제 테두리·그림자를 따로 적었다). */
.rec-review,
.eco-card, .eco-home-card, .eco-det-sec { border: 0; border-radius: var(--r-card, 12px); padding: 12px 14px;
  background: var(--surface, #FFFFFF); color: var(--text);
  box-shadow: 0 0 0 1px rgba(23,27,34,.07), var(--wk-shadow, 0 1px 2px rgba(23,27,34,.05), 0 6px 18px rgba(23,27,34,.06)); }
/* ★★W-UIX13-C4 — 카드 내 볼드 제거 (타이틀 500, 오늘·본문·버튼 400으로 가볍고 정갈하게) */
.au-card b, .au-card strong, .au-card .au-today, .au-card button { font-weight: 400; }
.au-card2 { cursor: pointer; }
.au-r1 { display: flex; align-items: center; gap: var(--sp-2); }
/* ★W-UIX18 ④(2026-09-13 · 사장님) — 예약된 작업 카드의 제목이 **자동화 카드 제목과 같은 크기**다.
   종전에는 이 자리만 `--fs-ti`(15px)를 따로 들어 같은 화면 안에서 제목이 두 크기였다(실측
   15px ↔ 13.5px) ⇒ 크기·굵기 선언을 **걷어** 공용 `.au-ti` 한 줄이 정하게 한다(부품 규칙 하나).
   ★남긴 것은 **자리 규칙**뿐이다(한 줄 말줄임 — 이 카드에만 필요한 것). */
.au-r1 .au-ti { flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.au-r2 { margin-top: 4px; font-size: var(--fs-cap); color: var(--muted);
  font-variant-numeric: tabular-nums; }
/*   ★W-UIX13-C4 — 2줄 '오늘 N/상한' 볼드 제거 */
.au-today { color: var(--text); font-weight: 400; }
.au-more { margin-top: var(--sp-2); }
.au-more.hidden { display: none; }
.au-cells { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: baseline; }
.au-cell { display: flex; gap: 5px; align-items: baseline; font-size: var(--fs-meta); }
.au-cell-k { color: var(--wk-caption, var(--muted)); font-size: var(--fs-cap); }
.au-cell-v { color: var(--text); }
/* ★액션은 **마우스를 올려야** 나타난다(정보가 먼저 · 손잡이는 그다음 · 구성안 §9).
   ★손이 없는 기기(터치)에서는 **늘 보인다** — 감출 수 없는 자리에서 감추지 않는다. */
.au-acts { opacity: 0; transition: opacity .15s ease; }
/*   ★W-UIX13-C2 ② — **라이브·펼친 카드는 손잡이가 항상 보인다**(목업 §5): 지금 도는 일을
     멈추려는 사람이 마우스를 어디에 올려야 할지 찾게 두지 않는다. 나머지는 hover 그대로. */
.au-card:hover .au-acts, .au-card.au-open .au-acts, .au-card:focus-within .au-acts,
.au-card.au-card-live .au-acts { opacity: 1; }
@media (hover: none) { .au-acts { opacity: 1; } }
/*   ★실브라우저가 잡았다: 아이콘이 붙은 손잡이는 **한 줄**이어야 한다(기본 흐름이면 아이콘이
     글자 위로 접힌다). 자리는 셋 — 카드 액션·갤러리 [만들기]·펼친 결과의 버튼들. */
.au-acts .au-link, .au-card .au-link, .af-panel .au-link, .af-acts .au-link {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: inherit; font-weight: 400; }
.au-acts .ic, .au-acts svg, .au-card .au-link .ic, .au-card .au-link svg,
.af-panel .au-link .ic, .af-panel .au-link svg { width: 15px; height: 15px; flex: none; }
.au-act-tx { font-size: var(--fs-meta); font-family: inherit; font-weight: 400; }
/* ★★W-UIX13-A ④ — 얼굴 = **표정 이모지 + 색 링**(링이 곧 분야다 · 색 이름은 서버 표가 준다). */
/* ★★★W-UIX13-A3(2026-09-10 · 사장님 "아바타는 이대로 이식") — 얼굴은 **SVG 아바타**다.
   ★규칙은 구성안 v3.1 §4 의 것을 그대로 옮겼다(크기 넷 · 라이브 펄스 · 꺼짐 흑백).
   ★몸통·표정·소품이 `currentColor` 를 쓰므로 **색은 `--c` 하나**가 정한다(분야 = 링 색 토큰).
   ★`.face` 는 그 아바타를 감싸는 **한 자리**의 이름으로 남는다(부르는 곳이 하나여야 갈아 끼운다). */
.av { width: 48px; height: 48px; display: inline-block; vertical-align: middle; flex: none;
  color: var(--c, var(--c-slate)); border-radius: 50%; }
.av.md { width: 28px; height: 28px; }
.av.sm { width: 20px; height: 20px; }
.av.lg { width: 64px; height: 64px; }
.av.live { animation: avpulse 1.6s ease-in-out infinite; }
@keyframes avpulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--wk-live, #17A34A) 45%, transparent); }
  50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--wk-live, #17A34A) 0%, transparent); }
}
.av.off { filter: grayscale(1); opacity: .45; }
@media (prefers-reduced-motion: reduce) { .av.live { animation: none; } }
/*   ★이모지 얼굴(A2)은 **폴백**으로만 남는다 — SVG 를 못 쓰는 자리(메일 본문·푸시)가 그것을 쓴다. */
.face-emoji { flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 999px; font-size: 18px; line-height: 1;
  font-family: var(--font-emoji);
  background: color-mix(in srgb, var(--c-slate) 8%, transparent);
  box-shadow: inset 0 0 0 2.5px var(--c-slate); }
/* ★★상태 칩 = **표정 + 두세 글자**(테두리 0 · 라이브만 색과 움직임). */
/*   ★W-UIX14-S1 — 공용 칩(`.wk-chip`). 치환(17종 → 1)은 S3 다 · 여기서는 **정의만**. */
.wk-chip, .au-chip { margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 5px;
  border-radius: var(--r-chip); padding: 2px 8px; font-size: 12px;
  font-weight: 400;
  color: var(--muted); background: var(--surface-2, rgba(148,163,184,.15)); }
.au-chip-tx { font-size: 12px; font-weight: 400; }
.wk-chip.au-live, .au-chip.au-live { color: var(--wk-live, #17A34A);
  background: color-mix(in srgb, var(--wk-live, #17A34A) 12%, transparent); }
.wk-chip.au-wait, .au-chip.au-wait { color: var(--soon, #b7791f);
  background: color-mix(in srgb, var(--soon, #b7791f) 12%, transparent); }
/* ★★공용 **선택 카드 부품**(W-ORDEV1-B4 S2) — 고른 것은 **채운 칩**, 안 고른 것은 **테두리 칩**.
     글리프(circle/circle-dot · square/square-check)는 라인 아이콘이라 문자 이모지 0 을 지킨다. */
.wk-choice { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.wk-choice-k { font-size: 12px; color: var(--muted); }
/*   ★★W-UIX28(2026-09-19 · 사장님 스샷) — **타원 배지를 걷는다.** 선택지는 «체크박스 + 글자» 다:
     테두리도 둥근 감쌈도 없고, 간격은 **여백만으로** 준다(배지처럼 보이면 무엇이 눌리는 것인지가
     흐려지고, 같은 줄에 배지가 여럿이면 화면이 알약밭이 된다).
     고른 것 = 체크 네모 + 강조색 글자 · 안 고른 것 = 빈 네모 + 보통 글자. */
.wk-opt { display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  padding: 2px 2px; margin-right: 6px; font-size: 12.5px; line-height: 1.4;
  color: var(--text); background: transparent; border: 0; box-shadow: none; }
.wk-opt svg { width: 14px; height: 14px; }
.wk-opt:hover { color: var(--accent); }
/*   ★W-ORDEV1-B6 ① — 고른 것은 **체크와 글자 강조**로만 말한다(배경 채움 0 · 사장님 실기). */
/*   ★굵기는 토큰으로(자 `bold_600_700` 을 올리지 않는다 — 강조는 색과 체크가 이미 한다). */
.wk-opt.is-on { color: var(--accent); background: transparent; font-weight: var(--fw-2, 500);
  box-shadow: none; }
.wk-opt-tx { font-size: 12.5px; }
.wk-opt-note { font-size: 11px; opacity: .75; }
.wk-choice-src { font-size: 11px; color: var(--muted); font-style: italic; }
/*   ★W-UIX14-S4 A — **작은 칩**(줄 안에 서는 배지). 공개범위 배지가 첫 사용처다. */
.wk-chip.sm { margin-left: 0; font-size: 10.5px; padding: 1px 7px; gap: 4px; }
.wk-chip.au-fail, .au-chip.au-fail { color: var(--danger, #d64545);
  background: color-mix(in srgb, var(--danger, #d64545) 12%, transparent); }
/*   ★W-UIX14-S1 — 옛 `#auto-list .au-card.fx-card { border: 0 }` 은 **죽은 규칙**이 됐다:
     이제 레시피 자신이 테두리 0 이다(위 `.wk-card` 블록). */
.au-card-h { display: flex; gap: 8px; align-items: center; }
.au-ti { font-size: 13.5px; color: var(--text, #eaf1fb); font-weight: 500; }
.au-badge { margin-left: auto; font-size: 11.5px; font-weight: 400;
  border: 0; border-radius: var(--r-chip, 999px); padding: 2px 8px;
  color: var(--wk-live, #17A34A);
  background: color-mix(in srgb, var(--wk-live, #17A34A) 12%, transparent);
  white-space: nowrap; }

/* ★★W-UIX13-C4 — 배지 상태별 테두리 링 및 그림자 색상:
   ★사장님 지시(2026-09-10): 기본-지켜보는중 일때는 일반 그림자색 유지.
   작동중(live)일 때만 해당 색(초록 글로우)으로 그림자색 변경. 카드 마우스 호버 인터랙션 삭제. */
.au-card-live {
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--wk-live, #17A34A) 40%, transparent),
              0 0 0 4px color-mix(in srgb, var(--wk-live, #17A34A) 10%, transparent),
              0 8px 22px color-mix(in srgb, var(--wk-live, #17A34A) 14%, transparent);
  animation: au-glow 2.2s ease-in-out infinite; }
.au-card.au-st-live {
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--wk-live, #17A34A) 40%, transparent),
              0 0 0 4px color-mix(in srgb, var(--wk-live, #17A34A) 10%, transparent),
              0 8px 22px color-mix(in srgb, var(--wk-live, #17A34A) 14%, transparent);
  animation: au-glow 2.2s ease-in-out infinite; }
/*   ★★W-UIX14-F7 ①(2026-09-12 · 사장님 실기) — **차례를 기다리는 것도 살아 있다.**
     구성안 규칙: 움직이는 것은 **라이브와 대기 둘뿐**이고 나머지(성공·실패·멈춤)는 정적이다.
     ★대기는 라이브보다 **옅고 느리다** — 같은 결의 글로우지만 색은 `--soon`(마감임박과
       같은 뜻의 색 · 테마가 따라온다)이고 주기가 길다. 두 상태가 같은 세기로 뛰면
       *"지금 일하는 것"* 이 어느 것인지 화면이 말하지 못한다. */
.au-card.au-st-wait {
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--soon, #b45309) 26%, transparent),
              0 0 0 4px color-mix(in srgb, var(--soon, #b45309) 7%, transparent),
              0 8px 22px color-mix(in srgb, var(--soon, #b45309) 9%, transparent);
  animation: au-glow-wait 3.6s ease-in-out infinite; }
@keyframes au-glow-wait {
  0%, 100% {
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--soon, #b45309) 22%, transparent),
                0 0 0 4px color-mix(in srgb, var(--soon, #b45309) 6%, transparent),
                0 8px 22px color-mix(in srgb, var(--soon, #b45309) 8%, transparent);
  }
  50% {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--soon, #b45309) 34%, transparent),
                0 0 0 6px color-mix(in srgb, var(--soon, #b45309) 10%, transparent),
                0 10px 26px color-mix(in srgb, var(--soon, #b45309) 12%, transparent);
  }
}
@keyframes au-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@keyframes au-glow {
  0%, 100% {
    box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--wk-live, #17A34A) 35%, transparent),
                0 0 0 4px color-mix(in srgb, var(--wk-live, #17A34A) 10%, transparent),
                0 8px 22px color-mix(in srgb, var(--wk-live, #17A34A) 14%, transparent);
  }
  50% {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--wk-live, #17A34A) 55%, transparent),
                0 0 0 6px color-mix(in srgb, var(--wk-live, #17A34A) 16%, transparent),
                0 10px 26px color-mix(in srgb, var(--wk-live, #17A34A) 20%, transparent);
  }
}

/* 갤러리/목록 카드 사용중 상태 (호버 인터랙션 없이 정갈한 링만 유지) */
.au-card.au-on, .au-card.au-st-on {
  opacity: 1;
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--wk-live, #17A34A) 30%, transparent),
              0 0 0 4px color-mix(in srgb, var(--wk-live, #17A34A) 6%, transparent),
              0 6px 18px color-mix(in srgb, var(--wk-live, #17A34A) 8%, transparent); }
/* ★결과·사유 한 줄 — 문장은 서버가 만든다(여기서는 자리만 준다). */
.au-run { font-size: 12px; color: var(--text, #dbe6f3); margin-top: 5px; }
/*   ★W-UIX12-C — 옛 `::before` 점(●/○)은 걷었다: 상태는 이제 **서버가 준 이모지**가 든다
     (점과 이모지가 함께 서면 같은 말을 두 번 한다). 움직임 끄기는 아래 한 자리로 모았다. */
.au-what { font-size: 12.5px; color: var(--text, #dbe6f3); margin-top: 5px; }
.au-ex { font-size: 11.5px; color: var(--muted, #8aa0bd); margin-top: 3px; }
.au-meta { font-size: 11.5px; color: var(--muted, #8aa0bd); margin-top: 4px; }
.au-empty { font-size: 12.5px; color: var(--muted, #8aa0bd); padding: 6px 2px; }
.au-go { margin-top: 8px; font-size: 12px; padding: 4px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: transparent;
  color: var(--text, #dbe6f3); cursor: pointer; font-family: inherit; font-weight: 400; }

/* ★★W-MYWORK-B3 ④ — '예약된 작업' 아래 **구분선**, 그 밑은 **카드 2열**(제목 없음).
   ★좁아지면 1열로 접힌다 — 이 판이 고치려는 것은 배치이지 가로 스크롤을 만드는 것이 아니다. */
.au-div { border-top: 1px solid var(--border); margin: 12px 0 10px; height: 0; }
/* ★W-MYWORK-B4 ⑤ — 카드 안 버튼 두 개([끄기]·[삭제])가 **줄바꿈으로 겹치지 않게** 한 줄로. */
.au-btns { display: flex; gap: 6px; flex-wrap: wrap; }
.au-btns .au-go { margin-top: 8px; }
.au-del { color: var(--muted, #8aa0bd); }
.au-del:hover { color: var(--danger, #e5484d); border-color: var(--danger, #e5484d); }
/*  ★W-UIX8 ②(2026-09-08 · 사장님) — 자동화 카드도 **할일과 같은 배치**:
    카드 최소 폭 300px 고정 · 자리가 넓어지면 열이 는다(캔버스 드래그가 곧바로 먹는다). */
.au-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 8px; }
@media (max-width: 720px) { .au-grid { grid-template-columns: 1fr; } }

/* ★★W-MYWORK-B3 ② — 📄 문서 = **표**(날짜 · 문서 제목 · 업무 구분 · 문서 형식).
   ★넓은 칸은 제목뿐이다 — 나머지는 내용 폭에 맞춰 고정해 표가 흔들리지 않게 한다. */
.mydocs { width: 100%; border-collapse: collapse; font-size: 13px; }
.mydocs thead th { text-align: left; font-size: 11.5px; font-weight: 700;
  color: var(--muted, #8aa0bd); padding: 6px 10px; border-bottom: 1px solid var(--border);
  white-space: nowrap; }
.mydocs th.md-ti { width: 100%; }
.mydocs.md-empty thead { display: none; }          /* 빈 목록에 머리줄만 서 있지 않게 */
.mydocs-row { cursor: pointer; }
.mydocs-row:hover td { background: var(--panel, #131a26); }
.mydocs-row:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: -2px; }
.mydocs td { padding: 8px 10px; border-bottom: 1px solid var(--border);
  vertical-align: middle; color: var(--text, #eaf1fb); }
.mydocs td.md-when, .mydocs td.md-kind { white-space: nowrap; color: var(--muted, #8aa0bd);
  font-size: 12px; }
.mydocs td.md-ti { display: table-cell; }
/* ★W-UIX17 ④(2026-09-13 · 사장님) — 목록 제목은 **굵지 않다**. 굵기는 상태를 말하는
   수단이고(F7 의 안 읽은 줄), 이 목록에는 그런 상태가 없다(§0 실측: 모든 제목이 600 이라
   가르는 것이 없었다 — 그래서 점 배지도 만들지 않았다. 없는 상태를 새로 그리지 않는다). */
.mydocs td.md-ti .docs-ti { display: inline; white-space: normal; }
.mydocs td.md-ti .docs-ic { margin-right: 6px; }
/*  ★★W-DOCDEL(2026-09-08 · 사장님 결정) — 옛 **'이전 버전' 배지 자리**다. 목록이 이제
    **최신 한 줄만** 세우므로 그 배지는 부르는 곳이 0 이 됐고, 그 자리에 서는 것은
    **폐기 안내**뿐이다(언제 사라지는지 + 되돌릴 손잡이).
    ★W-UIX14-S4 A 정정: 그때 *"다른 화면에서 쓰는 공용 배지"* 라 적었지만 실측하면
      `.docs-badge` 는 **어디에서도 안 그려진다** — 규칙과 함께 그 문장도 걷었다. */
.mydocs td.md-ti .md-gone-note { margin-left: 6px; flex: 0 0 auto; font-size: 11px;
  color: var(--muted, #8aa0bd); white-space: nowrap; }
/*  ★폐기된 줄 — **흐리게**. 지워진 것이 아니라 *"지워질 것"* 이라, 읽히되 뒤로 물러선다. */
.mydocs tr.md-gone { opacity: .55; }
.mydocs tr.md-gone td.md-ti .docs-ti { text-decoration: line-through; }
.mydocs tr.md-gone { cursor: default; }
/*  ★손잡이 칸 — 🗑 / [복구]. 좁고, 오른쪽 끝이며, 줄 클릭을 삼키지 않는다(리스너가 막는다). */
.mydocs td.md-act, .mydocs th.md-act { width: 44px; text-align: right; white-space: nowrap; }
.mydocs td.md-act .md-del { color: var(--muted, #8aa0bd); font-size: 13px; }
.mydocs td.md-act .md-del:hover { color: var(--danger, #e5484d); }
/* ★★W-UIX12 A3(2026-09-10 · 사장님) — 좌측 ⚙️ 자동화 줄의 배지 둘.
   ⓐ 라이브(●) = 지금 실행 중·대기 중인 자동화가 있다(펄스) ⓑ 결과 = 안 읽은 자동화 결과 수.
   ★수는 **서버가 센다**(`GET /automations` 의 summary) — 화면은 받아 적는다.
   ★접힘 레일에서는 라벨이 없으니 배지를 **점 하나**로 줄인다(수는 title 이 든다). */
.auto-badge { margin-left: auto; flex: none; font-size: 11px; line-height: 1; border-radius: 999px; }
.auto-badge.auto-live { width: 8px; height: 8px; background: var(--accent, #2563eb);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent, #2563eb) 60%, transparent);
  animation: autoLivePulse 1.6s ease-out infinite; }
.auto-badge.auto-unread { min-width: 17px; height: 17px; padding: 0 5px; display: inline-flex;
  align-items: center; justify-content: center; font-weight: 700;
  /*   ★배경색은 **선언한 여기서** 파생한다(fx 배지 규율 · `:root` 에 var() 를 담으면 그 자리
       값으로 굳는다 — W-UIX8 이 값을 치른 함정). 글자색만 `white` 인 이유: 이 배지는 **양쪽
       테마에서 같은 빨강 판** 위에 서므로 테마가 갈릴 자리가 아니다(벨 배지와 같은 결). */
  --auto-badge-bg: var(--danger, #e5484d);
  color: white; background: var(--auto-badge-bg); }
/*   두 배지가 함께 서면 라이브 점이 먼저(자동 마진은 앞선 하나만) */
.auto-badge.auto-live + .auto-badge.auto-unread { margin-left: 6px; }
@keyframes autoLivePulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent, #2563eb) 55%, transparent); }
  70%  { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent, #2563eb) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent, #2563eb) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .auto-badge.auto-live { animation: none; } }
/*   접힘 레일 — 라벨이 접히므로 배지는 아이콘 오른쪽 위 작은 점으로 */
.app-wrap.sb-collapsed #automation-nav { position: relative; }
/*   ★실브라우저가 잡았다: 레일은 `.sb-navitem span` 을 통째로 숨긴다(라벨을 접는 규칙) — 배지도
     span 이라 함께 사라졌다(w:0·h:0 실측). ⇒ 배지만 되살린다(라벨은 그대로 접힌 채). */
.app-wrap.sb-collapsed .sb-navitem span.auto-badge { display: inline-flex; }
.app-wrap.sb-collapsed .auto-badge { position: absolute; top: 6px; right: 10px; margin: 0; }
.app-wrap.sb-collapsed .auto-badge.auto-unread { min-width: 8px; width: 8px; height: 8px;
  padding: 0; font-size: 0; }
.app-wrap.sb-collapsed .auto-badge.auto-live + .auto-badge.auto-unread { right: 20px; }

/* ★★W-UIX12 A2 — 손잡이가 **아이콘**이 됐다(trash-2 · rotate-ccw). 글자 대신 그림이라 크기·정렬을
   여기서 정한다(레일·설정 아이콘과 같은 18px 결). ★[복구]는 위험한 손잡이가 아니라 되돌리는
   손잡이라 hover 색이 accent 다(빨강은 지우는 쪽에만). */
.mydocs td.md-act .md-ic-btn { display: inline-flex; align-items: center; justify-content: center;
  padding: 4px; line-height: 0; }
.mydocs td.md-act .md-ic-btn .ic, .mydocs td.md-act .md-ic-btn svg { width: 16px; height: 16px; }
.mydocs td.md-act .md-restore { color: var(--muted, #8aa0bd); }
.mydocs td.md-act .md-restore:hover { color: var(--accent, #2563eb); }
/*  ★★W-UIX10 ④-c(2026-09-08 · 사장님) — 업무 구분은 **배지가 아니라 글자**다(누를 수 없는
    칸에 알약 모양을 두면 눌러 보라는 헛된 신호가 된다). 칸의 표면만 남기고 테두리는 걷었다.
    ★`.md-chip` 규칙은 **부르는 곳이 0** 이 되어 지웠다(죽은 규칙을 남기면 다음 사람이 찾는다). */
.mydocs td.md-task { max-width: 180px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 12px; color: var(--muted, #8aa0bd); }

/* ★★W-MYWORK-B3 ③ — ⚙️ 자동화 페이지 중앙(자동화 알림 · 시간대별 최신순). */
/* ★W-UIX2 ⑥(2026-09-06 · 사장님 버그) — 자동화 페이지 중앙 알림 리스트 스크롤 수리.
   `body.ais-capped .tv-body{overflow:hidden}`(②판)이 컬럼에 천장을 주므로, 스크롤은 **이 리스트 내부**가
   맡아야 한다(mail·noti 선례 동형). `overflow-y:auto`·`min-height:0`(flex 자식이 콘텐츠보다 작아지게) 없이는
   넘쳐도 스크롤바가 안 생긴다(스크롤 불가의 뿌리). */
.autofeed { display: flex; flex-direction: column; gap: 2px; padding: 4px 2px 12px;
  overflow-y: auto; min-height: 0; flex: 1 1 auto; }   /* ★W-AUTOREG-B2 ③ — 천장 준 부모(.tv-sub) 안에서 남는 높이를 채워 스크롤 */
/* ★W-AUTOREG-B2 ④(2026-09-07 · 사장님) — 알림 구분선: **날짜 경계 = 실선**(날짜 머리 위에 그린다) ·
   **같은 날짜 내 = 점선**(af-row 아래선). 루프가 날짜가 바뀔 때만 .af-day 머리를 낸다(automations.js). */
/* ★★W-UIX13-B ③(구성안 §5) — 날짜는 **잿빛 캡션 하나**다(실선·점선 규칙은 걷었다 —
   같은 뜻을 선과 글자로 두 번 말하지 않는다). */
.af-day { font-size: var(--fs-cap); font-weight: var(--fw-2); color: var(--wk-caption, var(--muted));
  margin: var(--sp-4) 0 var(--sp-2); padding-top: 0; border-top: 0; }
.autofeed .af-day:first-child { margin-top: 2px; }
/* ★★W-UIX13-C — 우측 탭의 **수**(0 이면 아무것도 안 적는다) · 시트 머리의 담당 · 말풍선 얼굴. */
.cv-tab-n { font-variant-numeric: tabular-nums; font-weight: var(--fw-3); }
#ais-who { display: inline-flex; align-items: center; gap: 6px; }
.ais-who-tx { font-size: var(--fs-meta); }
.msg.bot .msg-face { float: left; margin: 2px 8px 0 0; }
/* ══════════════════════════════════════════════════════════════════════
   ★★★W-UIX14-S2(2026-09-11 · 사장님) — **에이전트 홈**의 배치.
   ★여기 있는 것은 **자리**뿐이다(`.home-*` 는 배치만) — 카드·행·칩의 모양은 전부
     `.wk-*` 에서 온다(부품 단일성 가드 R4 가 그것을 잰다).
   ══════════════════════════════════════════════════════════════════════ */
.home-sec { margin: var(--sp-5) 0 0; }
.home-sec.hidden { display: none; }
.home-sec-h { display: flex; align-items: baseline; gap: var(--sp-2);
  font-size: var(--fs-ti); font-weight: var(--fw-2); color: var(--text);
  margin: 0 2px var(--sp-2); }
.home-sec-h .wk-link, .home-sec-h .au-link { margin-left: auto; }
/*   ★데이터가 있는 사용자는 ④ 가 **한 줄**로 접힌다(머리만 남고 카드는 사라진다). */
.home-folded #home-start-list { display: none; }
/*   ★시작 카드 — 라인 아이콘 + 한 문장(두 줄을 넘기지 않는다). */
#home-start-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--sp-2); padding: 0; }
.home-ask { display: flex; align-items: center; gap: var(--sp-2); width: 100%;
  text-align: left; cursor: pointer; font-family: inherit; }
.home-ask .ic, .home-ask svg { width: 16px; height: 16px; flex: none;
  color: var(--wk-caption, var(--muted)); }
.home-ask-tx { font-size: var(--fs-meta); color: var(--text); }
/*   ★결재 — **0 이면 자리가 통째로 없다**(빈 카드·"없음" 0). */
.home-appr { display: flex; flex-direction: column; gap: var(--sp-2); margin: var(--sp-4) 0 0; }
.home-appr.hidden { display: none; }
/*   ★처음 사용자 띠 — 세 칸 한 줄(좁으면 접힌다) · 닫을 수 있다. */
.home-intro { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--sp-4);
  margin: var(--sp-4) 0 0; padding: 12px 14px; border: 0; border-radius: var(--r-card);
  background: var(--surface, #FFFFFF);
  box-shadow: 0 0 0 1px rgba(23,27,34,.07), var(--wk-shadow, 0 1px 2px rgba(23,27,34,.05)); }
.home-intro.hidden { display: none; }
.home-intro-c { display: flex; gap: var(--sp-2); align-items: flex-start; flex: 1 1 220px; min-width: 0; }
.home-intro-c .ic, .home-intro-c svg { width: 18px; height: 18px; flex: none;
  color: var(--accent); margin-top: 1px; }
.home-intro-t { font-size: var(--fs-meta); color: var(--text); }
.home-intro-s { font-size: var(--fs-cap); color: var(--wk-caption, var(--muted)); margin-top: 2px; }
.home-intro-x { flex: none; align-self: flex-start; }
/*   ★홈 스트림은 자동화 화면과 **같은 행 부품**이다 — 여기서는 천장만 준다(최근 10). */
#home-feed { padding: 0; }
/* ★★W-UIX17 ③(2026-09-13 · 사장님 실기) — 스트림이 길어지면 **잘리고 스크롤도 없었다**.
   §0 실측(실서버·실로그인 · 1440x900 · 알림 10줄): `body.ais-capped .chat-area` 가 화면에
   천장을 주는데(규칙 4-6) 그 아래에서 **스크롤을 맡는 자리가 없어** #dashboard 가 1,129px 로
   자라 아래 245px 이 잘렸고 페이지 스크롤도 0 이었다(`#home-feed{overflow:visible}` 이
   *'천장만 준다'* 는 주석과 함께 스크롤을 꺼 두고 있었다 — 그 천장은 **개수**(최근 10)였지
   높이가 아니었다).
   ⇒ 자동화 리스트(W-UIX2 ⑥)와 **같은 사슬**을 홈에도 세운다: 천장을 가진 부모(#dashboard) →
   남는 높이를 먹는 섹션(#home-stream) → 스크롤하는 리스트(#home-feed).
   ★`min-height: 0` 이 빠지면 flex 자식이 제 내용보다 작아지지 않아 **스크롤바가 안 생긴다**
     (그것이 이 부류 결함의 뿌리다 · 메일·자동화가 이미 치른 값).
   ★천장이 없는 자리(대화 seat=chat 등)는 종전 그대로다 — 규칙을 `body.ais-capped` 안으로 좁힌다. */
body.ais-capped #dashboard { flex: 1 1 auto; min-height: 0; }
body.ais-capped #home-stream { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
body.ais-capped #home-feed { flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; }

/*   ★첫 화면 숫자 타일 — 큰 수 하나 + 잿빛 한 줄(구성안 §6 데모 1). */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--sp-2); margin: var(--sp-3) 0; }
/*   ★W-UIX14-S1 — 공용 숫자 타일(`.wk-tile`) · 회색 반투명 채움을 **표면**으로 걷었다. */
/*   ★W-UIX14-F3 ⑤ — 홈의 시작 카드는 **체험 화면 칩처럼 가볍게**(누르면 그 말로 시작하는
     손잡이다 · 무거운 카드가 아니다). 자동화 화면의 같은 카드는 무접촉 — 이 자리만 좁힌다. */
#home-start-list .au-card { box-shadow: 0 0 0 1px var(--hairline); padding: 9px 12px; }
/* ★W-UIX24 ①(사장님) — 펼친 시작 카드는 **오른쪽→왼쪽으로 흐르는 한 줄**(같은 열 두 벌 · 0→-50% 이 한 바퀴 · B1 방향 뒤집음).
   ★마우스를 올리면 멈추고, 움직임 줄이기 설정이면 서서 한 벌만 보인다. 접힘(.home-folded)은 종전 그대로. */
#home-start-list.home-marquee { display: block; overflow: hidden; padding: 2px 0; }
/* ★W-UIX24-B1 — 접기가 안 먹던 뿌리: 위 규칙(1,1,0)이 `.home-folded #home-start-list{display:none}`(1,1,0)보다
   **뒤에** 와서 접혀도 block 이 이겼다. 접힘 쪽을 한 단계 높여 순서와 무관하게 이긴다. */
.home-folded #home-start-list.home-marquee { display: none; }
.home-marquee-track { display: flex; gap: var(--sp-2); width: max-content;
  animation: home-marquee var(--mq-dur, 42s) linear infinite; }
.home-marquee-track > * { flex: 0 0 240px; }
#home-start-list.home-marquee:hover .home-marquee-track,
#home-start-list.home-marquee:focus-within .home-marquee-track { animation-play-state: paused; }
@keyframes home-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }   /* ★B1 — 오른쪽→왼쪽 */
@media (prefers-reduced-motion: reduce) {
  .home-marquee-track { animation: none; flex-wrap: wrap; width: auto; }
  .home-marquee-clone { display: none; }
}
#home-start-list .au-card:hover { border-color: var(--accent); }

.wk-tile, .tile { display: block; text-align: left; border: 0; border-radius: var(--r-tile);
  padding: var(--sp-3) 14px; background: var(--surface, #FFFFFF);
  box-shadow: 0 0 0 1px rgba(23,27,34,.07), var(--wk-shadow, 0 1px 2px rgba(0,0,0,.10), 0 6px 18px rgba(0,0,0,.06));
  color: var(--text); font-family: inherit; }
.tile-cap { display: flex; align-items: center; gap: 5px; font-size: var(--fs-cap);
  color: var(--wk-caption, var(--muted)); }
.tile-cap .ic, .tile-cap svg { width: 14px; height: 14px; }
.tile-num { font-size: 26px; font-weight: var(--fw-3); line-height: 1.15; margin-top: 4px;
  font-variant-numeric: tabular-nums; }
.tile-sub { font-size: var(--fs-cap); color: var(--wk-caption, var(--muted)); margin-top: 2px; }
.tile-faces { display: flex; align-items: center; gap: 4px; margin-top: 6px; flex-wrap: wrap; }
/* ★W-UIX31 ③④ — 타일 안 줄(지금 일하는 워키 · 완료) — 점은 좌측 메뉴와 같은 `.arr-dot` */
.tile-line { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%;
  margin-top: 6px; padding: 0; border: 0; background: none; color: var(--text); font: inherit; text-align: left; }
button.tile-line { cursor: pointer; }
button.tile-line:hover .tile-line-main { color: var(--accent); }
.tile-line-main { font-size: 13px; font-weight: var(--fw-2, 600); line-height: 1.3; }
.tile-line-sub { font-size: var(--fs-cap); color: var(--wk-caption, var(--muted)); }
.tile-line.is-idle .tile-line-main { font-weight: 400; color: var(--wk-caption, var(--muted)); }
/* ★W-UIX35(사장님 정정) — 자동화 에이전트 줄: **카드의 그 얼굴**(같은 컴포넌트 · 상태는 얼굴 색·움직임으로만) +
   «일정 + 제목» + 줄 끝 «오늘 n번 알림». 새 그림·새 색 0 — 얼굴은 크기만 줄 높이에 맞춘다. */
.tile-line.is-agent { flex-direction: row; align-items: center; gap: 8px; }
.tile-line.is-agent .tile-line-main { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tile-agent-face { flex: none; display: inline-flex; }
/* ★W-UIX37 — 작업 중 줄: 얼굴 + 글 기둥(아래 줄은 얼굴 폭만큼 들여 맞는다) */
.tile-line.has-face { flex-direction: row; align-items: flex-start; gap: 8px; }
.tile-line-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.tile-agent-state { flex: none; font-size: var(--fs-cap); color: var(--wk-caption, var(--muted)); white-space: nowrap; }
.tile-line.is-more .tile-line-main { font-weight: 400; color: var(--wk-caption, var(--muted)); }
/* ★W-STREAM1 후속 ① — 실패 줄: 파란 점 대신 주의 표식(경고 색은 기존 토큰 · 번역 대조표 ⚠ 와 같은 색) */
.tile-line.is-fail .tile-line-main { display: inline-flex; align-items: center; gap: 4px; color: var(--c-amber); }
.tile-line.is-fail .tile-line-main svg, .tile-line.is-fail .tile-line-main .ic { width: 13px; height: 13px; }
/* ★★W-UIX13-B ① — **크루 띠**: 지금 누가 무엇을 하고 있는지 한 줄(가로 스크롤). */
/* ★★W-UIX13-C2 ③(2026-09-10 · 사장님 실기 "배지 윗부분이 잘린다") — **띠 안에 위쪽 자리를 준다**.
   뿌리는 `overflow-x: auto` 다: 한 축만 스크롤로 만들 수 없어(CSS 계산) 이 띠는 **세로로도**
   스크롤 컨테이너가 되고, 그러면 라이브 아바타의 펄스(`.av.live` 의 `box-shadow: 0 0 0 7px`)가
   **패딩 박스 밖**이라 잘린다. 실측(수리 전): 띠 위끝 67 · 아바타 위끝 73 ⇒ 글로우 위끝 **66**
   = 컨테이너보다 1px 위 → 매 박동마다 halo 윗부분이 썰렸다.
   ★그래서 고치는 것은 헤더가 아니라 **띠의 안쪽 여백**이다(헤더는 이미 12px 아래에 띠를 둔다 —
   실측 헤더 아래끝 55 ↔ 띠 위끝 67). 8px 이면 7px 글로우가 온전히 들어온다. */
.crew-strip { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) 0 var(--sp-3); }
.crew-strip.hidden { display: none; }
.crew-cap { flex: none; font-size: var(--fs-cap); color: var(--wk-caption, var(--muted));
  margin-right: 2px; white-space: nowrap; }
.crew { flex: none; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 0; border-radius: var(--r-chip); padding: 4px 10px 4px 5px;
  background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text);
  font-size: var(--fs-meta); font-family: inherit; white-space: nowrap; }
.crew:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.crew-live { background: color-mix(in srgb, var(--wk-live, #17A34A) 12%, transparent); }
.crew-tx { font-variant-numeric: tabular-nums; }
/* ★★W-UIX13-B ② — **보고 행**: 시각(모노) · 잿빛 캡션(얼굴·보고·이름) · 굵은 한 줄 요약. */
.af-report .af-cap { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; }
.af-cap-tx { font-size: var(--fs-cap); color: var(--wk-caption, var(--muted)); }
.af-cap-last { font-size: var(--fs-cap); color: var(--wk-caption, var(--muted)); }
.af-x { font-size: var(--fs-cap); font-weight: var(--fw-3); color: var(--text);
  background: color-mix(in srgb, var(--text) 8%, transparent);
  border-radius: var(--r-chip); padding: 0 7px; }
/* ★★W-UIX18 ①(2026-09-13 · 사장님) — **읽은 줄은 굵지 않다.** 굵기는 '아직 안 봤다'는
   말이고(F7 의 알림 줄·W-UIX17 ④ 의 문서 목록과 같은 규칙), 종전에는 보고 줄이 읽음·안읽음
   가리지 않고 전부 500 이라 그 말이 아무것도 가리키지 않았다.
   ★판정은 **서버가 준 읽음 값**을 화면이 이미 붙여 둔 `af-unread` 하나다(새 쿼리 0 · 새 상태 0).
   ★이 규칙은 자동화 페이지와 홈 스트림이 **같은 렌더러**를 쓰므로 한 자리로 둘 다 바뀐다. */
.af-report .af-lead { font-size: var(--fs-body); font-weight: var(--fw-1); color: var(--text);
  white-space: normal; }
.af-report.af-unread .af-lead { font-weight: var(--fw-2); }
.af-caret { display: inline-flex; align-items: center; gap: 3px; }
/*   ★W-UIX14-S1 — `.af-caret-tx` 는 **죽은 규칙**이었다(C6 가 JS 에서 걷었다 · 실측 0건). */
/* ★산출물 타일 — 보고 행 **아래**에 붙는다(라인 아이콘 · 종류 · 시각 · 열기). */
.art-tiles { display: flex; flex-direction: column; gap: 6px; margin: var(--sp-2) 0 2px 46px; }
/* ★W-UIX14-S1 — 회색 채움을 걷고 **표면 토큰**으로(구분은 링 1px + 그림자가 한다). */
.art { display: flex; align-items: center; gap: var(--sp-2); padding: 8px 10px;
  border-radius: var(--r-tile); background: var(--surface, #FFFFFF);
  box-shadow: 0 0 0 1px rgba(23,27,34,.07); }
.art .ic, .art svg { width: 16px; height: 16px; flex: none; color: var(--wk-caption, var(--muted)); }
.art-mid { flex: 1 1 auto; min-width: 0; }
.art-ti { font-size: var(--fs-meta); color: var(--text); }
.art-sub { font-size: var(--fs-cap); color: var(--wk-caption, var(--muted)); }
.art-go { flex: none; }
/* ★묶음을 펼치면 **시각 목록**이 선다(각 줄을 누르면 그 자리에서 본문이 열린다). */
.af-sub-row { display: grid; grid-template-columns: 48px 1fr; gap: 6px 10px; cursor: pointer;
  padding: 6px 2px; }
.af-sub-tx { font-size: var(--fs-meta); color: var(--text); }
.af-sub-row .af-md { grid-column: 2; }
.af-md.hidden { display: none; }
/* ★★W-UIX12 B2(2026-09-10 · 사장님) — 행이 **아코디언**이 됐다: 머리(af-head) 한 줄 +
   펼침판(af-panel). 그래서 행 자신은 **세로**로 쌓고 가로 배치는 머리가 맡는다. */
/*   ★W-UIX14-S1 — 공용 목록 행(`.wk-row`) · 1줄 + 펼침. 치환은 S3~. */
.wk-row, .af-row { display: block; width: 100%; text-align: left;
  background: transparent; border: 0; border-bottom: 1px dotted var(--border);
  padding: 8px 6px; cursor: pointer; color: inherit; }
.af-head { display: flex; gap: 10px; align-items: flex-start; }
/*  ★W-UIX29-B1 — [결과 보기]로 내려온 행을 **1.5초만** 짚어 준다(스크롤만 하면 어느 줄인지
    모른다). 색은 **있는 토큰**(--accent · --fx-focus)으로 — 테마를 그대로 따라간다.
    애니메이션은 한 번이고 끝난다(상시 도는 것은 소음이다). */
.af-row.af-flash { animation: af-flash 1.5s ease-out 1; }
@keyframes af-flash {
  0%   { box-shadow: 0 0 0 2px var(--accent); background: var(--fx-focus); }
  70%  { box-shadow: 0 0 0 2px var(--accent); background: var(--fx-focus); }
  100% { box-shadow: none; background: transparent; }
}

.af-row:last-child { border-bottom: 0; }   /* 마지막 줄 뒤엔 점선 없음 */
.af-row.af-go { cursor: pointer; }
.af-row.af-go:hover { background: var(--panel, #131a26); }
/* ★★W-MYWORK-B5 ③(사장님) — 갈 곳이 없는 알림 줄은 **정보 표시**다: 손잡이처럼 보이지 않는다
   (커서·호버 없음). 눌러도 아무 일이 없는 것을 **보이는 것으로도** 말한다. */
.af-row.af-plain { cursor: default; }
/* ★W-UIX12 B2 — 펼침 손잡이(캐럿)와 펼침판. 펼치면 캐럿이 돈다(열렸다는 것을 **보이게**). */
.af-caret { flex: 0 0 auto; color: var(--muted, #8aa0bd); font-size: 11px; padding-top: 2px;
  transition: transform .15s ease; }
/*   ★실브라우저가 잡았다: 캐럿 **전체**를 돌리면 '펼치기' 글자까지 거꾸로 선다 —
     도는 것은 **화살표뿐**이고 글자는 상태를 말한다(펼치기 ↔ 접기). */
.af-row.af-open > .af-head .af-caret { color: var(--accent, #6aa9ff); }
.af-row.af-open > .af-head .af-caret .ic,
.af-row.af-open > .af-head .af-caret svg { transform: rotate(180deg); }
.af-row.af-open { background: var(--panel, #131a26); border-radius: 8px; }
/*   ★★W-UIX14-F1 ①(사장님 실기) — 펼침판이 **회색 채움 + 짙은 테두리**라 튀었다.
     S1 §0-2 가 `--panel-2` 를 *"안쪽으로 파인 자리"* 로 남겼는데, 이 자리는 파인 곳이
     아니라 **한 단계 안쪽 표면**이다(줄을 펼치면 그 줄의 본문이 이어진다).
     ⇒ 표면에서 바탕 쪽으로 한 단계(70%) · 테두리 0 · **hairline 링**만. */
/*   ★★W-UIX14-F6 ①(2026-09-12 · 사장님 실기) — **아직 튄다**(연한 청회색 채움).
     F1 ① 이 회색 채움을 걷고 surface 70% + 링으로 바꿨는데, 리스트 배경과의 차이가
     여전히 눈에 띄었다 ⇒ 차이를 **아주 옅게**(surface 92%) 두고, 경계는 링이 아니라
     **그림자 한 단계**(`--wk-shadow`)가 말한다(그 토큰은 섹션 밝기에서 파생돼 다크가
     따라온다 — 링은 hairline 한 색이라 두 테마에서 같은 세기로 보였다). */
.af-panel { margin: 6px 0 2px 0; padding: 10px 12px; border-radius: 8px; border: 0;
  background: color-mix(in srgb, var(--surface, #FFFFFF) 92%, var(--bg, #F5F6F8));
  box-shadow: var(--wk-shadow); }
.af-panel.hidden { display: none; }
/*   본문은 **마크다운 그대로**(문서 뷰와 같은 렌더러) — 좁은 칸이라 표·코드는 가로 스크롤. */
.af-md { font-size: 13px; line-height: 1.62; color: var(--text, #eaf1fb); overflow-wrap: anywhere; }
.af-md > :first-child { margin-top: 0; }
.af-md > :last-child { margin-bottom: 0; }
.af-md h1, .af-md h2, .af-md h3 { font-size: 14.5px; margin: 10px 0 6px; }
.af-md ul, .af-md ol { padding-left: 18px; }
.af-md pre { overflow-x: auto; }
.af-md table { display: block; overflow-x: auto; border-collapse: collapse; }
.af-md td, .af-md th { border: 1px solid var(--border); padding: 4px 8px; }
.af-md-empty { font-size: 12.5px; color: var(--muted, #8aa0bd); }
.af-acts { margin-top: 8px; display: flex; gap: 10px; flex-wrap: wrap; }
/* ★★W-UIX12-C — **이모지 그대로가 얼굴이다**: 원·테두리·링을 걷고 이모지를 크게 둔다.
   그 옆에는 **분야**만 선다(이름은 걷었다 — 사장님 실기). */
.au-agent { display: flex; gap: 7px; align-items: center; min-width: 0; }
.au-ava { flex: none; font-size: 22px; line-height: 1; background: none; border: 0; padding: 0; }
.au-who-f { font-size: 11px; color: var(--muted, #8aa0bd); white-space: nowrap; }
.au-role { font-size: 12px; color: var(--muted, #8aa0bd); margin-top: 2px; }
.au-live-line { font-size: 12px; color: var(--accent, #6aa9ff); margin-top: 4px;
  font-variant-numeric: tabular-nums; }
.au-jump { margin-top: 2px; }
/* ★움직임을 원치 않는 사람에게는 **아무것도 움직이지 않는다**(상태는 이모지+글자가 이미 말한다). */
@media (prefers-reduced-motion: reduce) {
  .au-card-live, .au-badge-st.au-live .au-badge-ic,
  /*   ★W-UIX14-F7 ① — 새로 움직이게 된 **대기**도 여기 함께 선다(짝을 빠뜨리지 않는다). */
  .au-card.au-st-wait, .au-card.au-st-live,
  .au-card-live, .av.live { animation: none; }
}
.af-time { flex: 0 0 auto; font-size: var(--fs-cap); color: var(--wk-caption, var(--muted));
  padding-top: 2px; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.af-body { flex: 1 1 auto; min-width: 0; }
/*   ★★W-UIX14-F7 ②(2026-09-12 · 사장님 실기) — **읽은 것과 안 읽은 것이 한눈에 갈려야 한다.**
     읽은 줄은 볼드를 벗고(400) 안 읽은 줄만 **한 단계**(500) 진하다 — 700 은 제목이
     아니라 경고처럼 읽혔다. 판정은 그대로 기존 읽음 표식(`.af-unread` · `_markRead` 가
     붙이고 뗀다)이라 **새 상태를 만들지 않았다**. */
.af-ti { font-size: 13px; color: var(--text, #eaf1fb); font-weight: var(--fw-1, 400); }
.af-row.af-unread .af-ti { font-weight: var(--fw-2, 500); }
.af-pv { font-size: 11.5px; color: var(--muted, #8aa0bd); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/*  ★★W-UIX10 ②-a(2026-09-08 · 사장님) — 자리가 바뀌었으니 **무게도 바뀐다**: 첫 줄은 내용
    (`af-lead`)이고 둘째 줄은 분류(`af-sub`)다. 크기·색을 새로 만들지 않고 **둘을 맞바꾼다**
    (13px/본문색 ↔ 11.5px/흐린색) — 그래야 훑을 때 종목·방향이 먼저 읽힌다. */
.af-pv.af-lead { font-size: 13px; color: var(--text, #eaf1fb); margin-top: 0; }
/*   ★W-UIX14-F7 ② — 첫 줄(내용)도 제목과 **같은 한 단계**다(두 줄이 서로 다른 무게로
     뛰면 어느 것이 제목인지 흐려진다). */
.af-row.af-unread .af-pv.af-lead { font-weight: var(--fw-2, 500); }
.af-ti.af-sub { font-size: 11.5px; color: var(--muted, #8aa0bd); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.af-row.af-unread .af-ti.af-sub { font-weight: 400; }
.au-go:hover { border-color: var(--accent, #3b82f6); }
/*  ★★W-AUTO2-S1(2026-09-09 · 사장님) — 자동화 카드의 **네 칸 한 줄**(정본 §3).
    ★칸은 줄바꿈으로 접힌다(좁은 화면에서 가로 스크롤을 만들지 않는다).
    ★등급 배지 색은 뜻이다: 읽기=조용함 · 초안=강조색 · 승인 실행=경고색(돈·발송이 걸린다). */
.au-cells { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px;
  margin-top: 6px; font-size: 11.5px; color: var(--muted, #8aa0bd); }
.au-cell { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.au-grade, .au-paused { flex: 0 0 auto; font-size: 10.5px; font-weight: 700;
  border-radius: 999px; padding: 1px 8px; border: 1px solid var(--hairline); }
.au-grade-read { color: var(--muted, #8aa0bd); }
.au-grade-draft { color: var(--accent, #3b82f6);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.au-grade-act { color: var(--soon);
  border-color: color-mix(in srgb, var(--soon) 45%, transparent); }
.au-paused { color: var(--danger, #e5484d);
  border-color: color-mix(in srgb, var(--danger, #e5484d) 45%, transparent); }
/*  ★★W-AUTO2-S2-B(2026-09-09) — `act` **승인 대기** 줄. 돈·발송이 걸린 자리라 카드 안에서
    **한 겹 들어가** 보이게 한다(그냥 줄로 두면 나머지 정보와 같은 무게가 된다). */
/*   ★★W-UIX13-C2 ②(구성안 §5 `.approve`) — **강조색 12% 채움 · 테두리 0**. 종전 주황 테두리는
     이 축이 걷어낸 그 신호(테두리)를 이 자리에만 남겨 둔 것이었다. */
.au-approve { margin-top: 8px; padding: 10px 12px; border-radius: 10px; border: 0;
  background: color-mix(in srgb, var(--accent) 12%, transparent); }
.au-approve-t { font-size: var(--fs-meta); font-weight: var(--fw-2); color: var(--text); }
.au-approve-p { margin-top: 4px; font-size: 11.5px; color: var(--text, #eaf1fb);
  line-height: 1.45; white-space: pre-wrap; }
.au-approve .au-btns { margin-top: 6px; }


/* ══════════════════════════════════════════════════════════════════════════
   장부 · 가계부 · 세무 — 화면 규칙(2026-09-11 W-UIX14-S5-1 에서 app.html 인라인에서 이사)
   ★인라인 `<style>` 은 이 파일보다 **늦게 로드돼 이긴다** — 그래서 옮긴 것을 파일 **맨 끝**에
     둔다(그 자리를 유지해야 값이 안 바뀐다). ★이사에서는 값을 한 글자도 안 고쳤다 ·
     부품 수렴(카드·버튼·칩·탭)은 이 블록을 **고치는 다음 단계**에서 한다.
   ★줄 구간이 아니라 **규칙 단위**로 옮겼다 — 구간마다 자산·이커머스 규칙이 섞여 있어
     통째로 옮기면 남의 것을 끌고 온다(실측).
   ══════════════════════════════════════════════════════════════════════════ */

    /* 세무 요약(Phase 31.4) — 면책 배너 상단 고정(닫기 불가) */
    .tax-disclaimer{position:sticky;top:0;z-index:2;background:rgba(251,191,36,.14);color:var(--soon,#d97706);
      border:1px solid rgba(251,191,36,.4);border-radius:8px;padding:8px 12px;font-size:12px;font-weight:600;margin:0 0 12px;line-height:1.5}
    .tax-period{margin-left:auto;display:inline-flex;gap:6px}
    .tax-period select{padding:5px 8px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font-size:12px}
.tax-card { padding:14px 16px;margin:0 0 14px }
.tax-card-title { font-size:13px;font-weight:500;color:var(--text);margin:0 0 10px }
    .tax-metrics{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 12px}
.tax-metric { flex:1;min-width:110px;padding:9px 12px }
    .tax-metric span{display:block;font-size:11.5px;color:var(--muted);margin:0 0 3px}
    .tax-metric b{font-size:15px;color:var(--text)}
/*   ★강조 칸의 채움은 **뜻이 있다**(색이 '이것을 보라'고 말한다) — 남기되 공용 12% 로. */
.tax-metric.tax-hl { background:color-mix(in srgb, var(--accent) 12%, var(--surface, #fff)) }
    .tax-metric.tax-hl b{color:var(--accent)}
    .tax-bar-row{display:flex;align-items:center;gap:10px;margin:6px 0;font-size:12px}
    .tax-bar-label{width:64px;color:var(--muted);flex-shrink:0}
    .tax-bar-track{flex:1;height:10px;background:var(--border);border-radius:999px;overflow:hidden}
    .tax-bar-fill{display:block;height:100%;border-radius:999px}
    .tax-bar-fill.b-sales{background:var(--accent)}
    .tax-bar-fill.b-purchase{background:#fb923c}
    .tax-bar-val{width:110px;text-align:right;color:var(--text);font-weight:600;flex-shrink:0}
    .tax-empty{padding:28px 16px;text-align:center;color:var(--muted);font-size:13px}
    /* ★반제 버튼 — [삭제] 옆(같은 성격의 결정이라 나란히). 못 할 때는 이유를 함께 낸다. */
    .ledger-rev { margin-top: 6px; }
    .ledger-rev[disabled] { opacity: 0.5; cursor: not-allowed; }
    .ledger-revwhy { font-size: 12px; opacity: 0.85; margin: 4px 0 0; }
    /* 거래처 상세 폼(Phase 27.2) */
    .b2c-form{padding:12px 14px;color:var(--text);font-size:13px}
/*   ★★W-UIX14-S5-1 — 가계부 [입력]/[내역]은 **하나만 고르는 자리**라 캔버스와 같은
     텍스트 탭이다(밑줄 2px · 알약 0 · 감싸는 줄 테두리도 걷는다).
     ★규칙(릴리 결재): 하나만 고르면 탭 · 여럿이 동시에 켜지면 토글. */
.b2c-tabs { display:flex;gap:4px;margin-bottom:12px }
    .b2c-tab{padding:7px 14px;border:none;background:transparent;color:var(--muted);cursor:pointer;font-size:13px;font-weight:600;border-bottom:2px solid transparent}
    .b2c-tab.active{color:var(--text);border-bottom-color:var(--accent,#2f81f7)}
    .b2c-field{display:flex;align-items:center;gap:8px;margin-bottom:8px}
    .b2c-field>label{flex:0 0 96px;color:var(--muted);font-size:12.5px;text-align:right}
    .b2c-field input[type=text],.b2c-field input[type=number],.b2c-field input[type=date],.b2c-field textarea,.b2c-field select{flex:1;min-width:0;box-sizing:border-box;padding:6px 9px;border:1px solid var(--border);border-radius:7px;background:var(--panel);color:var(--text);font-size:13px}
    .b2c-field input:focus,.b2c-field textarea:focus,.b2c-field select:focus{outline:none;border-color:var(--accent)}
    .b2c-field input:disabled{background:var(--panel-2);color:var(--muted);opacity:.7}
    /* 날짜 입력 — 테마 정합(네이티브 흰 박스 이질감 제거). color-scheme 로 달력 팝업·아이콘이 테마 따라감 */
    .b2c-field input[type=date]{color-scheme:light dark;font-family:inherit}
    .b2c-field input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.5);cursor:pointer;opacity:.8}
    .b2c-field input[type=date]::-webkit-calendar-picker-indicator:hover{opacity:1}
    .b2c-row2{display:flex;gap:10px}
    .b2c-row2>.b2c-field{flex:1}
    .b2c-inline{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
    .b2c-radio,.b2c-check{display:inline-flex;align-items:center;gap:5px;cursor:pointer;font-size:12.5px;white-space:nowrap}
    .b2c-req{color:var(--danger)}   /* ★W-UIX14-S5-4 — 이사를 타고 들어온 위험색 상수(S3 계약: 테마가 따라온다) */
.b2c-mini { padding:5px 9px;border:1px solid var(--hairline);border-radius:7px;background:transparent;color:var(--muted);cursor:pointer;font-size:12px;white-space:nowrap }
    .b2c-mini:hover{border-color:var(--accent)}
    /* Phase 31.1 — 폼 페이지 타이틀 + 구분선 */
    .b2c-formtitle{font-size:16px;font-weight:700;color:var(--text);margin:2px 0 14px;padding-bottom:10px;border-bottom:1px solid var(--border)}
.b2c-divider { border-top:1px solid var(--hairline);margin:14px 0 }
    .b2c-sub{display:flex;align-items:center;justify-content:space-between;margin:12px 0 6px;font-weight:600}
    .b2c-sub-act{display:flex;gap:6px}
    .b2c-ct{width:100%;border-collapse:collapse;font-size:12px}
/*   ★★4면 박스를 **하단선 하나**로: 표 안에 격자를 다 그리면 글자보다 선이 먼저 읽힌다.
     경계 자체는 남긴다(표라는 사실은 선이 말한다 · 지시서 §7). */
.b2c-ct th,.b2c-ct td { border:0;border-bottom:1px solid var(--hairline);padding:4px 6px;text-align:left }
.b2c-ct th { color:var(--muted);font-weight:400 }
    .b2c-ct input[type=text]{width:100%;box-sizing:border-box;border:none;background:transparent;color:var(--text);font-size:12px}
    .b2c-ct input[type=text]:focus{outline:1px solid var(--accent)}
    .b2c-actions{display:flex;align-items:center;gap:8px;margin-top:14px;padding-top:12px;border-top:1px solid var(--border)}
/*   ★★W-UIX14-S5-1 — 가계부 버튼은 **공용 보조 버튼의 별칭**이다(마크업 무접촉).
     주행동 하나만 채우고(`.primary`), 되돌리기 어려운 것은 **색으로만** 말한다. */
.b2c-btn { padding: 7px 14px; border: 1px solid var(--hairline); border-radius: 8px;
  cursor: pointer; font-size: 13px; font-weight: 400; font-family: inherit;
  background: transparent; color: var(--muted); }
.b2c-btn.primary { border-color: transparent; color: var(--btn-fg, #fff); font-weight: 400;
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2))); }
.b2c-btn.ghost { background: transparent; color: var(--muted); }
.b2c-btn.danger { background: transparent; color: var(--danger, #d64545); border-color: var(--hairline); }
.b2c-btn.danger:hover { background: transparent; color: var(--danger, #d64545); border-color: var(--danger, #d64545); }
    .b2c-msg{font-size:12px;color:var(--muted)}
    /* 회사정보 모달(Phase 28) — 라벨 우측정렬로 짧은 라벨(종목/팩스)의 과한 공백 축소 + 업로드/미리보기 */
    #company-form .b2c-field>label{flex-basis:88px;text-align:right}
    /* 개인 가계부(Phase 29) — 대시보드·요약카드·파이·PIN */
    .bk-dash{padding:12px 14px;color:var(--text);font-size:13px}
    .bk-dash-head{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
    .bk-dash-tools{display:inline-flex;align-items:center;gap:8px}
    .bk-month{padding:6px 8px;border-radius:8px;background:var(--panel-2);border:1px solid var(--border);color:var(--text);font-size:12.5px}
    .bk-eye{font-size:14px;line-height:1}
    .bk-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:14px 0}
.bk-card { padding:12px;text-align:center }
    .bk-card span{display:block;font-size:11.5px;color:var(--muted);margin-bottom:4px}
.bk-card b { font-size:15px;font-weight:500 }
    .bk-card.income b{color:#22a06b}
    .bk-card.expense b{color:#e5534b}
    .bk-card.balance b{color:var(--accent,#2f81f7)}
    .bk-legend{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin:10px 0 2px}
    .bk-legend.hidden{display:none}
    .bk-leg{font-size:11.5px;font-weight:700;color:#10233a;padding:3px 10px;border-radius:999px;white-space:nowrap}
    .bk-pie-box{height:220px;margin:6px 0 14px}
    .bk-pie-box.hidden{display:none}
    .bk-list-h{font-size:12px;font-weight:700;color:var(--muted);margin:6px 0}
    .bk-table tbody tr:hover{background:var(--panel-2)}
/*   ★★칩 모양은 공용, **색 뜻은 유지**한다: 수입/지출/이체는 상태가 아니라
     **돈의 방향**이라 live/wait/fail 톤으로 바꾸면 뜻이 달라진다(채움만 12% 규칙으로). */
.bk-type { display:inline-flex;align-items:center;gap:4px;padding:2px 8px;
  border-radius:var(--r-chip);font-size:12px;font-weight:400;
  background:var(--surface-2, rgba(148,163,184,.15));color:var(--muted) }
.bk-type.income { background:color-mix(in srgb,#22a06b 12%,transparent);color:#22a06b }
.bk-type.expense { background:color-mix(in srgb,#e5534b 12%,transparent);color:#e5534b }
.bk-type.transfer { background:var(--surface-2, rgba(148,163,184,.15));color:var(--muted) }
.bk-pin-card { max-width:320px;text-align:center;padding:16px 18px }
    .bk-pin-input{width:160px;margin:8px auto 0;display:block;text-align:center;letter-spacing:.4em;
      font-size:20px;padding:10px;border-radius:10px;background:var(--panel-2);border:1px solid var(--border);color:var(--text)}
    .erp-item,.b2c-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border:0;border-radius:8px;
      background:transparent;color:var(--text);font-size:13px;text-align:left;cursor:pointer}
    .erp-item:hover,.b2c-item:hover{background:var(--panel-2)}
    /* 시트가 떠 있는 동안 그리드가 시트에 가리지 않게 중앙 아래쪽 여백 확보 */
    body.ais-open .ledger-body { padding-bottom: 4px }
    /*  ★W-UIX9 ① — 할일 항목이 **줄로 돌아가** 이 간격 규칙은 쓰이지 않는다(걷었다).
        파스텔 host 는 이제 **홈 [내 업무] 숫자 카드 한 자리**에만 남는다. */
    .ledger-bar .bi-account { padding: 5px 8px; border-radius: 6px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; font-size: 13px; }
    /* ── 공용 확인 게이트(Phase D) — 네이티브 confirm 수렴. 앵커 바(.confirm-bar) + 중앙(.confirm-ov). ── */
    /*   기존 .fd-confirm(accent)/.ledger-confirm·.exp-confirm(danger red) 을 흡수·값 승계. */
    /* width:100% = 옛 .fd-confirm 값 승계 — .fd-actions(flex-wrap) 안에서 자기 줄로 내려오게(필수). */
    .confirm-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; width: 100%; color: var(--text);
      margin-top: 8px; padding: 8px; border: 1px solid var(--accent, #3b82f6); border-radius: 8px; font-size: 13px; }
    /* 세무 요약(78-2) — .dash-* 재사용 + 기간 바/그룹 제목/면책 배너. */
    .tax-bar { display: flex; gap: 8px; margin-bottom: 12px; }
    .tax-bar select { padding: 5px 8px; border-radius: 6px; border: 1px solid var(--border, #2a2f3a);
      background: var(--panel-2, rgba(255,255,255,0.04)); color: inherit; }
    .tax-group-title { font-size: 13px; font-weight: 700; opacity: .85; margin: 16px 0 8px; }
    .tax-disclaimer { margin-top: 18px; padding: 10px 12px; border-radius: 10px; font-size: 12px;
      opacity: .8; border: 1px dashed var(--border, #2a2f3a); background: var(--panel-2, rgba(255,255,255,0.03)); }
    .ledger-shell { display: flex; flex-direction: column; height: 100%; min-height: 0; }
    /* 기초정보(75-2) 검색/유형 바 — .ledger-* 셸 재사용 + 입력 위젯. */
    .ledger-bar .bi-search, .ledger-bar .bi-type { padding: 5px 8px; border-radius: 6px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; font-size: 13px; }
    .ledger-bar .bi-search { min-width: 160px; }
    .ledger-table td.bi-ref { white-space: nowrap; opacity: 0.9; }
    /* 자금(75-4a) 미수/미지급 토글 + 수금 Detail(우측 캔버스) + 인앱 확인 게이트. */
    .ledger-bar .fk-kind { padding: 5px 12px; border-radius: 999px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .ledger-bar .fk-kind.fk-active { background: var(--accent, #3b82f6); color: #fff; border-color: transparent; }
    /* 자산 원장(75-4b) 상태 필터 + 검수/매각 Detail(우측 캔버스) + 인앱 확인 게이트. */
    .ledger-bar .as-status { padding: 4px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
/*   ★★W-UIX14-S5-2(릴리 Q1 결재) — 이 셋은 **탭이 아니라 토글**이다: 여럿이 동시에
     켜지는 **필터**라 `.cv-tabs` 로 그리면 *'하나만 고르는 것'* 처럼 보여 뜻이 바뀐다.
     ⇒ 모양은 보조 버튼, 켜짐은 **강조색 테두리·글자**로 말한다(채움 없음).
     ★규칙(릴리 결재): 하나만 고르면 탭 · 여럿이면 토글. */
.ledger-bar .as-status.as-active { background: transparent; color: var(--accent, #3b82f6);
      border-color: var(--accent, #3b82f6); }
    /* ★★2026-08-25 G-P9 ⓐ·ⓒ — 상태·품목 셀렉트를 **옆 칩·스위치와 같은 키·같은 곡률**로.
       `.fx-input` 토큰이 색·테두리·포커스를 이미 그린다(유령 클래스 아님 · style.css:177).
       여기서는 **줄에 앉히는 것**만 한다: 알약형 곡률 + 같은 글자 크기 + 세로 정렬. */
    .ledger-bar .as-status-sel, .ledger-bar .as-tmpl { border-radius: 999px; font-size: 12px;
      padding: 4px 10px; cursor: pointer; max-width: 180px; }
    /* ★★G-P12 ⓑ(사장님 신고 · 정본 §14-1 2항) — 스위치 라벨이 이웃 필드보다 **위로 떠 있었다**.
       원인은 `.fx-switchlab` 이 기본 `align-items: center` 를 쓰면서도 줄 안에서 **자기 높이만큼만**
       차지해, 셀렉트(padding 4/10 + 테두리)보다 낮은 상자가 위쪽에 붙은 것이다.
       → 줄의 모든 손잡이에 **같은 최소 높이**를 주고 세로 가운데로 모은다(높이 = 셀렉트 기준). */
    .ledger-bar { align-items: center; }
    .ledger-bar .as-swlab { font-size: 12px; color: inherit; display: inline-flex;
      align-items: center; gap: 6px; min-height: 28px; }
    .ledger-bar .as-status-sel, .ledger-bar .as-tmpl,
    .ledger-bar .as-merge, .ledger-bar .as-label, .ledger-bar .as-scanbtn,
    .ledger-bar .as-intake, .ledger-bar .as-sale { min-height: 28px; }
    .ledger-bar .as-preincl { padding: 4px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
.ledger-bar .as-preincl.as-active { background: transparent; color: var(--accent, #3b82f6);
      border-color: var(--accent, #3b82f6); }
    .ledger-bar .as-lineage { padding: 4px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px dashed var(--hairline); background: transparent; color: inherit; }
.ledger-bar .as-lineage.as-active { background: transparent; color: var(--accent, #3b82f6);
      border-style: solid; border-color: var(--accent, #3b82f6); }
    .ledger-bar .as-merge, .ledger-bar .as-label { padding: 4px 10px; border-radius: 8px; cursor: pointer;
      font-size: 12px; border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .ledger-bar .as-merge:disabled { opacity: 0.45; cursor: not-allowed; }
    /* ★라벨 인쇄(91-C-b) — 확인 바(.as-confirm)와 결과 문구를 그리드 껍데기 안에 둔다. */
    .ledger-shell .as-msg { font-size: 12px; opacity: 0.9; margin: 6px 2px 0; }
    /* ★위치(91-C-2a) — 스캔 패널과 같은 형태를 재사용한다(세 번째 스타일을 만들지 않는다). */
    .ledger-bar .as-locset, .ledger-bar .as-locmgr, .ledger-bar .as-ship,
    .ledger-bar .as-scrap, .ledger-bar .as-count { padding: 4px 10px; border-radius: 8px;
      cursor: pointer; font-size: 12px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; }
    .ledger-bar .as-locset:disabled, .ledger-bar .as-ship:disabled { opacity: 0.45; cursor: not-allowed; }
    /* ★행 안 칩은 서로 붙지 않게 — 종전 마크업의 공백 하나에 기대고 있었다. */
    .ledger-table td .pq-chip + .pq-chip { margin-left: 4px; }
    /* ★★③⑵ 행 자체가 누르는 것이다 — **누를 수 있다는 것을 모양이 말한다**(§13-8).
       누를 수 없어 보이는 것을 누르시게 하면 그 기능은 없는 것과 같다. */
    .ledger-table tr.pq-row { cursor: pointer; }
    .ledger-table tr.pq-row:hover td { background: color-mix(in srgb, var(--accent) 8%, transparent); }
    /* ★스캔(91-C-c) — 카메라와 손 입력을 **나란히**. 좁은 화면(현장 폰)에서는 세로로 쌓인다. */
    .ledger-bar .as-scanbtn { padding: 4px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    /* ★자산 추적 단위(Phase 91-B) — 묶음(로트) 수량 배지 + 낱개 분리 바. 배지는 **필수 요건**이다
       (없으면 사용자가 1행 N점을 1점으로 읽는다). 등급 열은 .ledger-table 기본 스타일을 쓴다. */
    .as-badge-lot { border-color: #b45309; color: #d97706; font-weight: 600; }
    .ledger-bar { display: flex; align-items: center; gap: 10px; padding: 8px 12px;
      border-bottom: 1px solid var(--border, #2a2f3a); flex: 0 0 auto; }
/*   ★장부 크롬의 [새로…] 아홉 자리는 **보조 조작**이다(주행동은 표 안에서 일어난다). */
.ledger-bar .ledger-new { padding: 7px 14px; border-radius: 8px; cursor: pointer; border: 1px solid var(--hairline);
      background: transparent; color: var(--muted); font-size: 13px; font-weight: 400;
      font-family: inherit; }
    /* 기간 바(75-1b→★UX10 ② 단일 행 재편) — 월별 ◀▶ + 구분/키워드 필터. from~to 입력 폐지.
       버튼류는 압축 금지(내부 줄바꿈 방지) — 폭이 모자라면 검색 입력(.lf-q)만 줄어든다. */
    .ledger-bar > button, .ledger-bar > select, .ledger-period { white-space: nowrap; flex: none; }
    .ledger-period { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
    .ledger-period button { padding: 4px 8px; border-radius: 6px; cursor: pointer;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .ledger-period .lp-label { min-width: 74px; text-align: center; font-weight: 600; }
    .ledger-bar .lf-type { padding: 5px 8px; border-radius: 6px; font-size: 13px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .ledger-bar .lf-q { padding: 5px 8px; border-radius: 6px; font-size: 13px; min-width: 110px;
      flex: 0 1 190px; border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .ledger-bar .lp-apply { padding: 5px 10px; border-radius: 6px; cursor: pointer;
      background: var(--accent, #3b82f6); color: #fff; border: none; }
.ledger-bar .lp-all { padding: 5px 10px; border-radius: 6px; cursor: pointer; border: 1px solid var(--hairline);
      background: transparent; color: var(--muted); font-size: 12.5px; }
    .ledger-summary { margin-left: auto; font-size: 12px; opacity: 0.85; min-width: 0;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    /* 중앙 레이어 전체를 그리드가 사용(75-1b — 좌우 분할 폐지, 컬럼 잘림 해소). 폼은 우측 캔버스. */
    .ledger-body { flex: 1 1 auto; min-height: 0; padding: 12px; overflow: hidden; }
    .ledger-grid-host { height: 100%; overflow: auto; }
    .ledger-table { width: 100%; border-collapse: collapse; font-size: 13px; }
/*   ★표 경계는 **뜻이 있는 선**이라 남긴다 — 값만 공용 hairline 으로. */
.ledger-table th, .ledger-table td { padding: 6px 8px; border-bottom: 1px solid var(--hairline); text-align: left;
      white-space: nowrap; }
    .ledger-table th.num, .ledger-table td.num { text-align: right; }
    .ledger-table th.ledger-sortable { cursor: pointer; user-select: none; }
    /* ★UX10 ③ — 리스트 타이틀 행 가독성(간편장부 공통): 헤더 배경(패널 톤·라이트/다크 변수)+
       스크롤 시 상단 고정(sticky)+정렬 라인 아이콘(arrow-up-down/-up/-down·활성=강조색). */
/*   ★★W-UIX14-S5-3(릴리 실화면 지적 ②) — 표 머리가 **짙은 회색 띠**였다(`--panel-2`).
     머리는 유지하되 **톤을 낮춘다**: 옅은 표면 + 하단 hairline — 머리는 '여기가 열 이름'
     이라고만 말하면 되고, 숫자보다 먼저 읽히면 안 된다.
     ★이 한 자리가 **장부·자산·이커머스 셋**의 표를 함께 바꾼다(같은 셸을 쓴다). */
.ledger-table thead th, .quote-table thead th { background: var(--surface-2, rgba(148,163,184,.12));
      border-bottom: 1px solid var(--hairline);
      color: var(--muted); font-weight: 400;
      position: sticky; top: 0; z-index: 1; }
    .ledger-sortable .lucide, .quote-sortable .lucide {
      width: 12px; height: 12px; margin-left: 4px; vertical-align: -2px; opacity: .45; }
    .ledger-desc { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
    .ledger-badge { text-align: center; }
    /* created_by 배지(협업 '누가 입력'·Stage 3a) — 자기="나"·타인=이름·PII 비노출. */
    .ledger-cby { font-size: 11px; color: var(--muted); white-space: nowrap; }
    .ledger-row { cursor: pointer; }
    /* ★★2026-08-07 — `--hover` 는 **이 코드베이스에 정의된 적이 없는 토큰**이라(style.css:696
       이 이미 적발해 둔 그것) 여기도 늘 하드코딩 흰색 폴백으로 떨어져 **라이트 테마에서
       거의 안 보였다**. 사장님이 *"마우스 온 상태처럼"* 을 기준으로 말씀하셨으므로 그 기준부터
       양쪽 테마에서 성립해야 한다 → 토큰 파생으로 교체(`--text` 는 theme.js 가 테마마다 덮는다). */
    .ledger-row:hover { background: color-mix(in srgb, var(--text) 10%, transparent); }
    /* ★★★사장님 소건(2026-08-07) — **지금 우측에 열려 있는 서류의 행**을 계속 표시한다.
       ★hover 와 **같은 톤**이되 지속되고, 왼쪽 띠로 *"열려 있다"* 를 hover 와 가른다
       (둘이 겹치면 더 진해져 그때도 읽힌다 — 겹침이 표시를 지우지 않는다).
       ★색은 `--accent` 파생이라 라이트·다크를 **저절로** 따른다(값 박기 0). */
    .ledger-row.is-open { background: color-mix(in srgb, var(--accent) 14%, transparent);
      box-shadow: inset 3px 0 0 var(--accent); }
    .ledger-row.is-open:hover { background: color-mix(in srgb, var(--accent) 24%, transparent); }
    .ledger-row.ledger-hi { animation: ledgerHi 2.4s ease-out; }
    .ledger-empty { padding: 24px; text-align: center; opacity: 0.7; }
    .ledger-del { margin-top: 10px; width: 100%; padding: 8px; border-radius: 8px; cursor: pointer;
      border: 1px solid #b91c1c; background: transparent; color: #ef4444; }

/*   ★이 질의는 자산 규칙과 **함께 살던** 블록이다 — 장부 것만 빼 왔다(자산 몫은 S5-2 에서). */
/* 모바일(≤760px): 폼은 우측 캔버스가 오버레이(풀스크린)로 처리 = 리스트↔폼 스택 자연 성립. */
    @media (max-width: 760px) {
      .ledger-bar { flex-wrap: wrap; }
      .ledger-summary { margin-left: 0; width: 100%; }
}

/*  ★W-UIX9 ②(2026-09-08 · 사장님) — 세무 통계 카드는 **장부 KPI 와 같은 크기**다:
같은 `.dash-card` 규칙(패딩·라운드)을 타게 하고, 카드가 **격자 칸**이 되었으니
옛 세로 여백(`margin: 0 0 14px`)만 푼다(크기 규칙을 새로 적지 않는다). */
#tax-host .tax-card { margin: 0; }


/* ══════════════════════════════════════════════════════════════════════════
   자산 · 검수 · 스캔 — 화면 규칙(2026-09-11 W-UIX14-S5-2 에서 app.html 인라인에서 이사)
   ★인라인 `<style>` 은 이 파일보다 **늦게 로드돼 이긴다** — 그래서 옮긴 것을 파일 **맨 끝**에
     둔다(그 자리를 유지해야 값이 안 바뀐다). ★이사에서는 값을 한 글자도 안 고쳤다 ·
     부품 수렴(카드·버튼·칩·탭)은 이 블록을 **고치는 다음 단계**에서 한다.
   ★줄 구간이 아니라 **규칙 단위**로 옮겼다 — 구간마다 남의 모듈 규칙이 섞여 있어
     통째로 옮기면 남의 것을 끌고 온다(실측).
   ══════════════════════════════════════════════════════════════════════════ */

    .as-orders.hidden { display: none; }
    .as-orders { margin: 4px 2px 8px; }
    /* ★재고 현황(UI 일괄 조정) — 카드 3묶음(상태별·위치별·밖에 나가 있는 것). */
    .as-stockview.hidden { display: none; }
    .as-stockview { padding: 4px 2px 8px; }
    .as-svsec { font-size: 12px; font-weight: 600; margin: 10px 2px 4px; }
    .as-svrow { display: flex; gap: 8px; align-items: center; justify-content: space-between;
      font-size: 12px; padding: 4px 2px; border-bottom: 1px solid var(--border, #2a2f3a); }
    .as-svrow:last-child { border-bottom: none; }
    .as-svkpi { display: flex; gap: 12px; flex-wrap: wrap; font-size: 13px; margin: 4px 2px 8px; }
    .as-svkpi b { font-size: 16px; }
    .as-svnote { font-size: 12px; opacity: 0.85; margin: 4px 2px; }
    /* ★G-P6 ⓑ(사장님 지시 2026-08-25) — 글 나열 → **통계 카드 + 접힌 리스트**.
       카드는 이커머스 대시보드의 `.eco-home-cards/.eco-home-card` 를 **그대로** 쓴다(새 카드 CSS 0).
       여기 있는 것은 접힘 한 축뿐이고, 색·간격은 전부 기존 토큰이다. */
    /* ★G-P10 — 현황 내역이 우측 [데스크] 프레임 안에 살 때의 여백(중앙에 있을 때와 같은 조판). */
    .as-svdesk { padding: 4px 10px 10px; }
    .as-svdesk .as-svfold:first-child { border-top: none; }
/*   ★접이줄 경계는 **뜻이 있는 선**이라 남긴다(값만 공용 hairline 으로). */
.as-svfold { margin: 8px 2px 0; border-top: 1px solid var(--hairline); }
.as-svfold > summary { cursor: pointer; font-size: 12px; font-weight: 400; padding: 8px 2px; list-style: none; }
    .as-svfold > summary::-webkit-details-marker { display: none; }
/*   ★★`::before` 에는 요소를 넣을 수 없어 **아이콘을 못 쓴다**(S4 에서 같은 자리를
     마크업으로 옮겼지만 여기는 `<summary>` 의 기본 표식 자리라 그 길이 없다).
     ⇒ 이모지가 아닌 **홑화살괄호(› ⌄)** 로 바꾼다 — 못 바꾼 것을 바꾼 척하지 않는다. */
.as-svfold > summary::before { content: "\203A "; opacity: .7; }
.as-svfold[open] > summary::before { content: "\2304 "; opacity: .7; }
    /* ★처리방안 집계 띠([검수·판정]) — 현황 띠와 **같은 조판**을 쓴다(새 CSS 축 0).
       ★`flex-wrap: wrap` 이 모바일 대응 전부다: 칸이 좁아지면 줄로 접힌다(가로 스크롤 없음).
       고정 폭·고정 열을 두지 않는 것이 좁은 화면에서 정직하다(Phase 97 ㉴ 와 같은 판단). */
    .as-dspband.hidden { display: none; }
    .as-dspband { display: flex; gap: 10px; flex-wrap: wrap; align-items: baseline;
      font-size: 13px; margin: 6px 2px 8px; }
    .as-dspband .dsp-i { display: inline-flex; gap: 4px; align-items: baseline; }
    .as-dspband .dsp-i b { font-size: 15px; }
    /* ★미판정은 **약하게 쓰지 않는다** — 남은 일이라 오히려 눈에 띄어야 한다. */
    .as-dspband .dsp-todo b { color: var(--soon); }
    .as-dspband .dsp-note { flex: 1 1 100%; font-size: 12px; opacity: 0.85; }
    /* ★선입고 배지 — 목록에서 "우리 물건"과 "아직 확정 안 한 물건"을 가른다(폐기 대기와 같은 축). */
    /* ★검수 귀속·방식 — 항목 위 한 줄(폼을 밀지 않는다). 좁으면 접힌다. */
    .ad-attr { display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
      font-size: 12px; margin: 4px 0 6px; }
    .ad-attr .ad-attrnote { flex: 1 1 100%; opacity: 0.85; }
/*   ★'선입고' 칩 — **상태색은 뜻이 있다**(아직 입고 전이라는 표시). 채움만 공용 12~14% 로. */
.as-pre { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; padding: 2px 8px;
      border-radius: var(--r-chip); background: color-mix(in srgb, var(--soon, #d29922) 14%, transparent);
      color: var(--soon, #d29922); }
    .asset-detail, .asset-sale { padding: 4px 2px; font-size: 13px; }
.asset-detail .ad-title, .asset-sale .ad-title { font-weight: 500; font-size: 15px; margin-bottom: 8px; }
.asset-detail .ad-sec { font-weight: 400; opacity: 0.85; margin: 6px 0; }
    .asset-detail .ad-item { display: flex; gap: 6px; margin-bottom: 6px; }
    .asset-detail .ad-item .ad-label { flex: 1 1 auto; }
    .asset-detail input, .asset-sale input { padding: 5px 8px; border-radius: 6px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .asset-detail input.num, .asset-sale input.num { text-align: right; }
    .asset-detail .ad-item .ad-ded { width: 96px; }
/*   ★★W-UIX14-S5-2 — 자산 화면의 버튼 쉰하나가 **공용 보조 버튼의 별칭**이다
     (마크업 무접촉). 주행동은 아래에서 **하나만** 채운다. */
.asset-detail button, .asset-sale button { margin-top: 8px; margin-right: 6px; padding: 7px 14px; border-radius: 8px; cursor: pointer;
      border: 1px solid var(--hairline); background: transparent; color: var(--muted);
      font-size: 13px; font-weight: 400; font-family: inherit; }
/*   ★주행동 — 저장·최종 확정. 한 화면에 하나다. */
.asset-detail .ad-save, .asset-sale .as-finalize { border-color: transparent; color: var(--btn-fg, #fff); font-weight: 400;
      background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2))); }
    /* ★G-P11 — 마진 줄. 셀렉트는 G-P9 의 라운드 필드와 **같은 모양**(새 축 0). */
    .asset-sale .as-marginbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
      margin: 6px 0 8px; font-size: 12px; }
    .asset-sale .as-margin { border-radius: 999px; font-size: 12px; padding: 4px 10px; cursor: pointer; }
    .asset-sale .as-marginmsg { font-size: 12px; }
    .asset-sale .as-client { width: 100%; margin-top: 8px; }
    .asset-sale .as-price { width: 96px; }
    .asset-detail .ad-msg, .asset-sale .as-msg { margin-top: 8px; font-size: 12px; opacity: 0.9; }
    .asset-sale .as-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
      margin-top: 8px; padding: 8px; border: 1px solid var(--accent, #3b82f6); border-radius: 8px; }
.asset-sale .as-confirm .as-yes { border-color: transparent; color: var(--btn-fg, #fff);
      background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2))); }
    /* ★자산 계보(Phase 91-A) — 그리드 트리 배지 + 분해/병합 화면 + 사전 경고 카드.
       확인 게이트(.as-confirm)는 매각 선례를 그대로 재사용한다(세 번째 스타일을 만들지 않는다). */
    /* ★검수 자리의 시리얼 — 실물 대조용(서류에는 안 뜬다). */
    .ad-serial { font-size: 12.5px; margin: 4px 0 6px; padding: 4px 8px; border-radius: 8px;
      background: rgba(127,127,127,0.10); }
    /* ★밖에 나가 있는 개체 — 위치 칸이 비는 대신 사실을 말한다(미지정과 구분). */
    .as-out { display: inline-block; padding: 1px 6px; border-radius: 999px; font-size: 11px;
      border: 1px solid var(--accent, #3b82f6); white-space: nowrap; }
    /* ★폐기(91-D-1) — 승인 대기 목록과 배지. 스캔·위치 패널과 같은 형태를 재사용한다. */
    /* ★입고 등록 폼 — 넓으면 한 줄, 좁으면 쌓인다(모바일 폭 고려 · 93열을 재현하지 않는다). */
    .as-intake-panel { border: 1px solid var(--border, #2a2f3a); border-radius: 10px;
      padding: 10px; margin: 4px 2px 8px; }
    .as-intake-panel.hidden { display: none; }
    .ain-top { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0; }
    .ain-lab { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px;
      color: var(--muted); flex: 1 1 160px; min-width: 0; }
    /* ★★★2026-08-07 사장님 신고 — **입력 줄이 같은 격자에 앉는 것을 구조로 보장한다.**
       ★글꼴·gap 을 맞춰도 [선입고] 라벨 자리에는 **스위치(16px)** 가 앉아 텍스트 라벨보다
       근본적으로 크다 — 값을 맞추는 것만으로는 다음에 또 어긋난다(스위치 크기가 바뀌면 재발).
       ★★그래서 **입력을 칸 바닥에 붙인다**: 칸(`.ain-lab`)들은 flex 로 늘어나 **높이가 이미
       같으므로**(실측 53px 동일), 바닥 기준이면 라벨 줄 높이가 무엇이든 입력 줄이 **한 선**에
       앉는다. 라벨은 각자 자기 높이대로 위에 놓인다(내용을 줄이지 않는다).
       ★상단 줄에만 건다 — 아래쪽 `.ain-lab`(메모 등)은 자기 줄이라 무접촉이다. */
    .ain-top > .ain-lab { justify-content: flex-end; }
    /* ★배포 후 실측에서 남은 3px — [거래처] 칸만 바닥이 164(다른 칸 167)였다. 원인은
       빈 힌트(`.pq-clienthint`)가 **높이 0 인데 `gap` 3px 은 먹는** 것이다(flex 는 빈 자식에도
       간격을 준다). ★정본 §4-3 그대로 — **상시 존재하는 것만 높이를 예약한다**: 힌트는 값이
       있을 때만 나타나므로, 비어 있으면 자리를 아예 안 차지하게 한다(`:empty`). */
    .ain-lab .pq-clienthint:empty { display: none; }
    .ain-lab input, .ain-lab select { min-width: 0; }
    /* ★★2026-08-07 사장님 신고 — [데스크] 헤더와 표 사이가 [입력] 탭보다 벌어져 보였다.
       ★실측: `.sd-form` 은 `.fx-form` 을 통해 **flex column · gap 9px** 인데, 그 위에
       `.asc-head` 가 **`margin-bottom: 8px`**(gap 이 없던 시절의 것)을 들고 있어 둘이 **더해졌다**
       (헤더 바닥 144 → 안내줄 161 = **17px** · 8+9 와 정확히 일치).
       → 간격의 주인은 **gap 하나**다(margin 은 중복이라 0). 그러면 [입력] 탭의 폼과 **같은 규칙**
       으로 정렬된다(거기 첫 요소는 `.asc-head` 를 안 써서 중복이 없었다).
       ★안내줄(`.skd-hint`)은 **상시 존재**하므로 지우지 않는다(정본 §4-3 — 없애는 것은 중복 여백뿐). */
    .sd-form .asc-head { margin-bottom: 0; }
    /* ★★2026-08-07 사장님 신고 ① — 양식 이름 줄: **라벨·입력·[저장]이 한 줄**.
       종전엔 `.ain-lab`(세로 라벨)이라 입력이 전폭을 먹고 버튼이 다음 줄로 밀렸다.
       ★폭은 예약하되 좁은 화면에서는 줄어든다(고정 폭을 박지 않는다). 값은 fx 토큰 파생. */
    .fx-form .sd-tplbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
    /* ★②2026-08-05 밤(사장님 스크린샷) — **빈 발화 자리는 자리를 안 먹는다.** 폼은 flex 라
       빈 메시지 div 도 아이템이라 gap 두 번 + 마진으로 **빈 띠**가 생겼다 — 종전엔 연결 안내가
       그 자리를 채워 가려져 있었고, v376 소멸로 드러났다(pq-docacts:empty 선례 동형 · §4-3 정합). */
    .fx-form .ain-msg:empty { display: none; }
    .ain-rule { font-size: 11.5px; line-height: 1.5; color: var(--muted); }
    .ain-rule.on { color: var(--accent, #6aa9ff); }
    /* ★Phase 102-ⓑ — 리스트 붙여넣기 상자(두 폼 공용). 평소엔 접혀 있어 **자리를 예약하지
       않는다**(규칙 §4-3 은 상시 존재하는 것만 높이를 예약한다). */
    .ain-list-open { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 4px 0; }
    /* ★fx 스위치 — 체크박스가 아니라 **켜짐이 확연한** 토글(사장님 지시). */
    /* ★★2026-08-05(사장님 실기기) — 스위치와 라벨이 **두 줄로 떨어져** 있었다.
       원인: 부모 `.ain-lab` 이 `display:flex; flex-direction:column`(위 라벨·아래 입력칸이
       그 자리의 기본 모양이다)인데, 여기서는 `gap` 만 주고 **방향을 안 뒤집었다** —
       ★`gap` 은 간격만 정하지 **줄을 나란히 놓아 주지 않는다.**
       → 스위치 라벨은 **한 행**이다: 스위치 바로 옆에 글자가 온다. */
    /* ★⑤2026-08-05(사장님) — 잡히는 영역은 **스위치와 글자만**. `.ain-lab` 의 `flex:1 1 160px`
       를 물려받아 빈 자리까지 라벨이 늘어나 있었고, 그 빈 데를 눌러도 스위치가 켜졌다. */
    /* ★★★2026-08-06 즉시 수리(사장님 스크린샷 — 스위치와 "선입고"가 겹쳐 보였다).
       ★원인 한 줄: v383 이 라벨을 쪼개며 `.ain-lab` 을 벗겼는데, **`display: flex` 는 그
       클래스가 주던 것**이었다. 이 규칙은 방향·정렬·간격만 적고 `display` 를 스스로 말한
       적이 없어, 라벨이 `inline` 이 되는 순간 아래 넷이 **전부 죽은 선언**이 됐다:
       `flex-direction`·`align-items`·`gap`·`flex` — 간격 0 + 베이스라인 정렬이라 28px
       스위치 위로 글자가 파고들어 "입고"만 보였다.
       ★★교훈(정본과 같은 결): *"방향과 간격은 `display` 없이는 죽은 선언이다"* — v378 이
       *"gap 은 줄을 나란히 놓아 주지 않는다"* 로 적은 그 자리의 다음 판본이다.
       → **규칙이 자기 display 를 든다**(남의 클래스에 얹히지 않는다 · `inline-flex` 라
       잡히는 영역은 스위치와 글자만 — 결재 ⑤ 계약 그대로). */
    .fx-switchlab { display: inline-flex; flex-direction: row; align-items: center; gap: 6px;
      flex: 0 0 auto; align-self: flex-start; line-height: 1.4; }
    /* ★④2026-08-05(사장님) — 합계 자리는 **미리 예약**한다. 숫자가 자라며 폭이 변하면
       `.ain-foot` 이 줄을 다시 접어 [저장(초안)]이 다음 줄로 밀렸다(흔들리는 화면). */
    .fx-form .ain-foot .pq-sum { min-width: 23ch; text-align: right; white-space: nowrap; }
    /* ★입고일 칸 — 라벨 자리에 스위치가 앉고 날짜 칸은 그 아래(=.ain-lab 의 세로 모양 그대로). */
    /* ★★★2026-08-07 사장님 신고 — **[견적일] 과 [선입고] 의 날짜 칸 세로 라인이 안 맞았다.**
       ★실측: 네 칸의 **컨테이너는 전부 top 127 로 같았다**(격자는 맞았다). 어긋난 것은 그 안이다 —
       입력 칸 top 이 거래처·견적일·양식 **144** 인데 입고일만 **149**(+5px).
       분해하면 ⑴선입고 라벨줄 **17.5px** vs 다른 라벨 **14px**(글꼴 12.5 vs 토큰 11.5)
       ⑵`gap` **4px** vs **3px** — 합쳐 5px 이다.
       ★★바로 아래 주석이 *"다른 라벨과 **같은 글꼴**"* 이라고 적어 두었는데 **값이 박혀 있어**
       실제로는 달랐다(`--fx-fs-sm` 은 11.5px). 뜻과 값이 갈린 자리다 → **토큰으로 되돌린다**. */
    .pq-prefield { display: flex; flex-direction: column; gap: 3px; }
    /* ★다른 라벨(거래처·견적일·양식)과 **같은 글꼴·같은 색**으로 보인다 — 그 값들도
       `.ain-lab` 이 주던 것이라 클래스를 벗는 순간 함께 사라졌다(같은 뿌리).
       ★글꼴은 **그 뿌리와 같은 토큰**을 쓴다(값 박기 0 — 박으면 토큰이 바뀔 때 또 어긋난다). */
    .pq-prefield .fx-switchlab { font-size: var(--fx-fs-sm); color: var(--muted); }
    /* ★행 표는 **자기 안에서** 가로로 스크롤한다 — 페이지가 옆으로 밀리지 않게. */
    .ain-rows { overflow-x: auto; }
    .ain-rows table { width: 100%; min-width: 520px; border-collapse: collapse; }
    .ain-rows th, .ain-rows td { padding: 4px; text-align: left; font-size: 13px; }
    .ain-rows input { width: 100%; min-width: 60px; box-sizing: border-box; }
    .ain-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 6px; }
    .ain-sum { margin-left: auto; font-weight: 700; }
    .ain-msg { margin-top: 6px; font-size: 13px; line-height: 1.6; }
    @media (max-width: 700px) { .ain-lab { flex: 1 1 100%; } .ain-sum { margin-left: 0; } }
.as-scrap-panel { padding: 10px; margin: 8px 2px; }
    .as-scrap-panel.hidden { display: none; }
    .as-pend { display: inline-block; padding: 1px 6px; border-radius: 999px; font-size: 11px;
      border: 1px dashed var(--border, #2a2f3a); white-space: nowrap; }
    /* ★실사(91-D-2) — 폐기 승인 패널과 같은 형태를 재사용한다(새 조형 0). */
    .as-count-panel { border: 1px solid var(--border, #2a2f3a); border-radius: 10px; padding: 10px;
      margin: 8px 2px; }
    .as-count-panel.hidden { display: none; }
    .acn-start, .acn-input { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
    .acn-start select, .acn-input input { padding: 4px 8px; border-radius: 8px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .acn-input input { flex: 1 1 180px; min-width: 0; }
    .as-count-panel button { padding: 3px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
    .acn-live.hidden, .acn-start.hidden { display: none; }
    .acn-head2 { font-size: 12px; margin: 8px 0 6px; }
    .acn-report { font-size: 12px; margin-top: 8px; }
    .acn-grp { margin-top: 8px; }
    .acn-grp > b { display: block; margin-bottom: 4px; }
    .acn-row { padding: 5px 0; border-bottom: 1px solid var(--border, #2a2f3a);
      display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
    .acn-row:last-child { border-bottom: none; }
    .acn-row .acn-lbl { flex: 1 1 160px; }
    .acn-msg { font-size: 12px; opacity: 0.9; margin-top: 8px; }
    .acn-note { font-size: 12px; opacity: 0.85; margin: 4px 0; }
    .ad-scrapbox { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 4px 0; }
    /* ★백로그 #6·#10 — 좁은 화면에서 눌리던 입력 줄. 같은 증상이라 규칙 하나로 함께 푼다:
       칸이 모자라면 **아래로 접힌다**(가로로 찌그러지지 않는다). */
    .as-confirm { flex-wrap: wrap; }
    .as-confirm .as-shipreason { flex: 0 1 auto; }
    .as-confirm .as-shipto { flex: 1 1 180px; min-width: 0; }
    .ad-scrapbox .ad-scrapreason { flex: 1 1 180px; min-width: 0; }
    .ad-scrapbox input[type="file"] { flex: 1 1 200px; min-width: 0; }
    .ad-scrapbox input[type="text"] { flex: 1 1 160px; min-width: 0; padding: 4px 8px;
      border-radius: 8px; border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .as-loc { border: 1px solid var(--border, #2a2f3a); border-radius: 10px; padding: 10px;
      margin: 8px 2px; }
    .as-loc.hidden { display: none; }
    .al-form .al-add, .asc-head .al-print { padding: 5px 10px; border-radius: 8px; cursor: pointer;
      font-size: 12px; border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
    .ad-locbox { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 4px 0; }
    .ad-locbox select { padding: 4px 8px; border-radius: 8px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; font-size: 12px; }
    .ad-moves { font-size: 11px; opacity: 0.8; margin-top: 4px; }
    .as-scan { border: 1px solid var(--border, #2a2f3a); border-radius: 10px; padding: 10px;
      margin: 8px 2px; }
    .as-scan.hidden { display: none; }
    .asc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 13px; }
    .asc-head button { margin-left: auto; padding: 3px 9px; border-radius: 8px; font-size: 12px;
      border: 1px solid var(--hairline); background: transparent; color: var(--muted); cursor: pointer; }
    .asc-head .asc-close { margin-left: 0; }
    .asc-body { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-start; }
    .asc-video { width: 260px; max-width: 100%; border-radius: 8px; background: #000; }
    .asc-manual { display: flex; flex-direction: column; gap: 6px; min-width: 220px; }
    .asc-lab { font-size: 12px; opacity: 0.8; }
    .asc-code { padding: 6px 8px; border-radius: 8px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; }
    .asc-find { padding: 5px 10px; border-radius: 8px; cursor: pointer;
      border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
    .asc-msg { font-size: 12px; opacity: 0.9; margin-top: 8px; }
.asc-card { margin-top: 8px; padding: 10px; }
.asc-title { font-weight: 400; margin-bottom: 4px; }
    .asc-st { opacity: 0.7; font-weight: 400; font-size: 12px; }
    .asc-line { font-size: 12px; opacity: 0.9; margin: 3px 0; }
    .asc-note { font-size: 12px; margin: 6px 0; opacity: 0.95; }
    .asc-acts { margin-top: 8px; display: flex; gap: 6px; flex-wrap: wrap; }
    .asc-acts button, .asc-jump, .asc-undo { padding: 4px 10px; border-radius: 8px; cursor: pointer;
      font-size: 12px; border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .asc-moved { margin-top: 6px; }
    .asc-locpick { padding: 3px 8px; border-radius: 8px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; font-size: 12px; }
    .as-tree .as-selcell { width: 30px; text-align: center; }
    .as-tree tr.as-gone td { opacity: 0.55; }
    .as-tree .as-tw { opacity: 0.45; margin-right: 4px; }
    .as-badge { display: inline-block; margin-left: 5px; padding: 1px 6px; border-radius: 999px;
      font-size: 11px; border: 1px solid var(--border, #2a2f3a); opacity: 0.85; white-space: nowrap; }
    .as-badge-k { border-color: var(--accent, #3b82f6); }
    .asset-detail .ad-cost { font-size: 12px; opacity: 0.85; margin-bottom: 6px; }
    .asset-detail .ad-lin, .asset-split .ad-lin { font-size: 12px; opacity: 0.9; margin: 3px 0;
      line-height: 1.5; }
    .asset-detail .ad-note { opacity: 0.7; }
    /* ★Phase 95 ⓐ — [검수·판정] 안내줄. 목록 위 한 줄로만 둔다(패널이 아니다 — 목록을
       아래로 밀지 않는다 · 91 백로그 #3 이 값을 치른 자리). */
    .as-inspect-hint, .as-work-hint, .as-merge-moved-hint {
      font-size: 12px; opacity: 0.85; padding: 6px 8px; margin-bottom: 6px;
      border-left: 2px solid var(--accent, #3b82f6); line-height: 1.5; }
    /* ★Phase 95 ⓑ — 제외 안내(§13-9): 화면이 **무엇을 세고 무엇을 뺐는지** 말하는 줄.
       숫자를 숨기지도, 두 숫자를 섞지도 않는다. */
    .as-scope-note { font-size: 12px; opacity: 0.75; padding: 2px 8px 6px; line-height: 1.5; }
    /* ★Phase 95 ⓒ — 작업 기록 줄(우측 Detail). 한 줄에 내용·금액·연결 상태·동작. */
    .asset-detail .ad-wrow { display: flex; justify-content: space-between; align-items: center;
      gap: 8px; font-size: 12px; padding: 3px 0; line-height: 1.5; }
    .asset-detail .ad-wacts { display: flex; gap: 4px; flex: 0 0 auto; }
    .asset-detail .ad-wacts button { margin: 0; font-size: 11px; padding: 2px 6px; }
    .asset-detail .ad-acts { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
    .asset-detail .ad-acts button { margin: 0; }
    .asset-detail .ad-dismantle { border-color: var(--accent, #3b82f6); }
    .asset-split { padding: 4px 2px; font-size: 13px; }
    .asset-split .ad-title { font-weight: 700; font-size: 15px; margin-bottom: 8px; }
    .asset-split .as-part { display: flex; gap: 6px; margin-bottom: 6px; }
    .asset-split .as-pname { flex: 1 1 auto; min-width: 0; }
    .asset-split .as-pcost { width: 104px; flex: 0 0 auto; }
    /* ★91-C-d 수량 칸 — 원가 앞에 좁게. 좁은 화면에서는 아래 미디어쿼리가 원가와 같이 늘어난다. */
    .asset-split .as-pqty { width: 62px; flex: 0 0 auto; }
    .asset-split input { padding: 5px 8px; border-radius: 6px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .asset-split input.num { text-align: right; }
    .asset-split .as-mname, .asset-split .as-mcode { width: 100%; margin-top: 6px; }
    .asset-split button { margin-top: 8px; margin-right: 6px; padding: 6px 12px; border-radius: 8px;
      cursor: pointer; border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .asset-split .as-go { background: var(--accent, #3b82f6); color: #fff; border-color: transparent; }
    .asset-split .as-tot { margin-top: 8px; font-size: 12px; font-weight: 600; opacity: 0.9; }
    .asset-split .as-msg { margin-top: 8px; font-size: 12px; opacity: 0.9; line-height: 1.55; }
    /* ★되돌릴 수 없게 되는 조건 — 실행 버튼 **위에** 둔다(누르기 전에 읽히도록). */
    .asset-split .as-warn { margin-top: 10px; padding: 8px 10px; border-radius: 8px;
      border: 1px solid #b45309; background: rgba(180, 83, 9, 0.08); }
    .asset-split .as-warn-h { font-size: 12px; font-weight: 700; margin-bottom: 4px; }
    .asset-split .as-warn ul { margin: 0; padding-left: 18px; font-size: 12px; line-height: 1.6; }
    .asset-split .as-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
      margin-top: 8px; padding: 8px; border: 1px solid var(--accent, #3b82f6); border-radius: 8px; }
    .asset-split .as-confirm .as-yes { background: var(--accent, #3b82f6); color: #fff; border: none; }
    .asset-detail .as-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
      margin-top: 8px; padding: 8px; border: 1px solid var(--accent, #3b82f6); border-radius: 8px; }
    .asset-detail .as-confirm .as-yes { background: var(--accent, #3b82f6); color: #fff; border: none; }
    .as-tree tr.as-lot td { background: rgba(180, 83, 9, 0.05); }
    .asset-detail .ad-split { border-color: #b45309; }
    .asset-detail .as-splitbar .as-splitn { width: 76px; }
    /* ★등급 입력(Phase 91-C · C-a) — 값 목록은 서버 SSOT. 선택 목록이 없으면 자유 입력. */
    .asset-detail .ad-grade { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
    .asset-detail .ad-gsel, .asset-detail .ad-gtext { padding: 5px 8px; border-radius: 6px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .asset-detail .ad-gtext { width: 130px; }
    .asset-detail .ad-gsave { margin-top: 0; }
    .asset-detail .ad-grade .ad-note { flex: 1 1 100%; margin-top: 2px; }
    /* 모바일(≤760px): 폼은 우측 캔버스가 오버레이(풀스크린)로 처리 = 리스트↔폼 스택 자연 성립. */
    @media (max-width: 760px) {
      /* ★계보 화면은 **현장에서 스마트폰으로** 본다(Phase 91-A). 좁은 폭에서 우선순위가 낮은 열을
         접고, 분해 입력은 한 줄에 다 들어가지 않으므로 금액을 아래로 내린다. QR 스캔은 C 단계라 없다. */
      /* ★91-B 로 등급 열이 5번째에 들어와 뒤 열 번호가 하나씩 밀렸다 — 접는 대상은 그대로
         '사양'(4)과 '입력한 사람'이다. 번호를 안 고치면 엉뚱한 열이 사라진다.
         ★91-C-2a 로 '위치' 열이 또 들어와 '입력'이 **9번**이 됐다(백로그 #2). 그동안 좁은
         화면에서는 **'상태'(8)가 사라지고 '입력한 사람'이 남아** 있었다 — 우선순위가 뒤집힌
         채였다. 헤더는 9열이다: 체크·자산코드·모델·사양·등급·위치·매입가·상태·입력. */
      .as-tree th:nth-child(4), .as-tree td:nth-child(4),   /* 사양 */
      .as-tree th:nth-child(9), .as-tree td:nth-child(9) { display: none; }  /* 입력한 사람 */
      .as-tree .as-selcell { width: 34px; }
      .as-tree .as-sel { width: 20px; height: 20px; }       /* 손가락 타깃 확보 */
      .asset-split .as-part { flex-wrap: wrap; }
      .asset-split .as-pname { flex: 1 1 100%; }
      .asset-split .as-pcost { flex: 1 1 auto; width: auto; }
      .asset-split .as-pqty { flex: 0 0 68px; width: auto; }
      .asset-split button, .asset-detail .ad-acts button { min-height: 38px; }
      .asset-split .as-confirm button, .asset-detail .as-confirm button { flex: 1 1 auto; min-height: 38px; }}


/* ══════════════════════════════════════════════════════════════════════════
   이커머스(주문·상품·문의·배송·자산연결) — 화면 규칙(2026-09-11 W-UIX14-S5-3 이사)
   ★인라인 `<style>` 은 이 파일보다 **늦게 로드돼 이긴다** — 그래서 옮긴 것을 파일 **맨 끝**에
     둔다(그 자리를 유지해야 값이 안 바뀐다). ★이사에서는 값을 한 글자도 안 고쳤다 ·
     부품 수렴(카드·버튼·칩·탭)은 이 블록을 **고치는 다음 단계**에서 한다.
   ★줄 구간이 아니라 **규칙 단위**로 옮겼다 — 구간마다 남의 모듈 규칙이 섞여 있어
     통째로 옮기면 남의 것을 끌고 온다(실측).
   ══════════════════════════════════════════════════════════════════════════ */

    /* ★재고 연결(Phase 91-E-1) — 개체 → 마켓 단품. 기존 eco-* 조형을 그대로 쓴다. */
    .eal-notice { font-size: 12px; opacity: 0.95; margin: 8px 2px; line-height: 1.5; }
    .eal-bar { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 8px 2px; }
    .eal-bar select { padding: 4px 8px; border-radius: 8px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; max-width: 260px; }
    .eal-sec { font-size: 12px; font-weight: 600; margin: 12px 2px 4px; }
    .eal-list { font-size: 12px; }
    .eal-row { display: flex; gap: 8px; align-items: center; justify-content: space-between;
      flex-wrap: wrap; padding: 5px 2px; border-bottom: 1px solid var(--border, #2a2f3a); }
    .eal-row:last-child { border-bottom: none; }
    .eal-row label { display: flex; gap: 6px; align-items: center; flex: 1 1 240px; }
.eal-tag { font-size:11px;padding:2px 8px;border-radius:var(--r-chip);border:0;
  background:var(--surface-2, rgba(148,163,184,.15));color:var(--muted) }
    .eal-why { font-size: 11px; opacity: 0.85; }
    .eal-dot { display: inline-block; width: 13px; }
    .eal-msg { font-size: 12px; margin: 6px 2px; line-height: 1.5; }
    .eal-count { font-size: 12px; opacity: 0.9; }
    /* ★E-2 주문 확정 — 후보 상자와 확인 게이트(기존 as-confirm 형태 재사용). */
    .eal-pickbox:empty { display: none; }
    .eal-pickbox { margin: 4px 0 8px 12px; padding: 6px 8px; border-left: 2px solid var(--border, #2a2f3a); }
    .eal-fee { display: inline-flex; gap: 4px; align-items: center; font-size: 12px; }
    .eal-feein { width: 72px; padding: 3px 6px; border-radius: 8px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .eal-gate { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px;
      padding: 8px; border-radius: 8px; border: 1px solid var(--accent, #3b82f6); font-size: 12px; }
    /* 이커머스 관리(Phase 32) — 상태배지·연동카드·옵션빌더 */
    .eco-head-btns{margin-left:auto;display:inline-flex;gap:8px;align-items:center}
    .eco-head-btns select,.eco-in{padding:6px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font-size:12.5px}
    .eco-badges{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 10px}
/*   ★★W-UIX14-S5-3 — 주문 상태 띠는 **하나만 고르는 자리**다(전체/신규/준비중/발송…)
     ⇒ 릴리 결재 규칙대로 **탭**(텍스트+밑줄)이다. 자산 툴바가 토글인 것과 반대로 보이지만
     같은 규칙에서 나온다: 하나만 고르면 탭 · 여럿이면 토글. */
.eco-st-badge { padding:5px 11px;border:0;border-bottom:2px solid transparent;background:transparent;
  color:var(--muted);cursor:pointer;font-size:12.5px;font-family:inherit }
    .eco-st-badge b{margin-left:3px}
.eco-st-badge.active { color:var(--text);border-bottom-color:var(--accent) }
.eco-st-badge:not(.active):hover { color:var(--text) }
    .eco-actions{display:flex;gap:8px;align-items:center;margin:0 0 10px;flex-wrap:wrap}
    .eco-hint{font-size:12px;color:var(--muted);margin:0 0 10px}
    .eco-st{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11.5px;font-weight:600}
    .eco-st.st-new{background:rgba(99,102,241,.15);color:var(--accent)}
    .eco-st.st-conf{background:rgba(52,211,153,.15);color:var(--ok,#34d399)}
    .eco-st.st-ready{background:rgba(251,191,36,.15);color:var(--soon,#fbbf24)}
    .eco-st.st-ship{background:rgba(148,163,184,.2);color:var(--muted)}
    .eco-st.st-claim{background:rgba(248,113,113,.15);color:var(--danger,#f87171)}
    .eco-st.st-done{background:rgba(148,163,184,.15);color:var(--muted)}
    .eco-claim{color:var(--danger,#f87171)}
    .eco-ono{font-size:11.5px;color:var(--muted)}
    .eco-prow{cursor:pointer}
.eco-card { padding:14px 16px;margin:0 0 12px }
    .eco-card-h{display:flex;align-items:center;gap:10px;margin:0 0 4px}
.eco-badge { padding:2px 8px;border-radius:var(--r-chip);font-size:12px;font-weight:400;
  background:var(--surface-2, rgba(148,163,184,.15));color:var(--muted) }
/*   ★'켜짐'은 **살아 있다는 상태**라 공용 live 색을 쓴다(뜻이 맞는 자리에만 색을 준다). */
.eco-badge.on { background:color-mix(in srgb, var(--wk-live, #17A34A) 12%, transparent);
  color:var(--wk-live, #17A34A) }
    .eco-card-hint{font-size:11.5px;color:var(--muted);margin:0 0 10px}
    .eco-card-form{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
    .eco-card-form .eco-in{min-width:180px;flex:1}
    .eco-card-btns{display:flex;gap:6px}
    .eco-msg{font-size:12px}
    .eco-msg.ok{color:var(--ok,#34d399)}
    .eco-msg.err{color:var(--danger,#f87171)}
    .eco-optbuild{border:1px dashed var(--border);border-radius:12px;padding:12px 14px;margin:12px 0}
    .eco-optbuild-h{font-size:13px;font-weight:700;color:var(--text);margin:0 0 8px}
    .eco-optaxes{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 10px}
    .eco-optaxes .eco-in{flex:1;min-width:130px}
    .eco-opt-table .eco-in{width:100%;min-width:60px;padding:4px 6px}
    .eco-home-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin:0 0 12px}
    /* ★Phase 92 P1 — 우측 상세(주문·송장). 목록은 중앙 전폭, 고치는 일은 여기서. */
    .eco-det .eco-det-info{display:grid;gap:6px;margin:0 0 4px}
    .eco-det-info>div{display:flex;gap:8px;font-size:12.5px;align-items:baseline}
    .eco-det-info>div>span{color:var(--muted);min-width:74px;flex:0 0 auto}
/*   ★구역 나눔 선은 **뜻이 있는 선**이라 남긴다(값만 공용 hairline 으로). */
.eco-det-sec { margin:14px 0 6px;font-size:12px;color:var(--muted);border-top:1px solid var(--hairline);padding-top:10px }
    .eco-det-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
    .eco-det-msg{margin-top:10px;font-size:12px;color:var(--muted);white-space:pre-line}
    .eco-sku-none{color:var(--muted)}
.eco-home-card { padding:16px 14px }
/*   ★읽는 판은 흔들리지 않는다(호버 이동 0 · S1 규율). */
.eco-home-card:hover { transform:none }
    .eco-home-label{display:block;font-size:12px;color:var(--muted);margin:0 0 6px}
    .eco-home-val{font-size:20px;color:var(--text)}
    .eco-home-val small{font-size:12px;color:var(--muted);margin-left:2px}
    /* LNB ERP/아웃바운드 트리 */
    .erp-tree{display:flex;flex-direction:column;gap:2px;padding:2px 0}
    /* 간편장부 — '내 업무'(.task-tree) 폴더/트리 정합(Phase 78-3→79 일관성·CSS+마크업만). 그룹=폴더
       (네이티브 접기·folder/folder-open 아이콘=내 업무 차용), 항목=트리 노드(들여쓰기+가이드 라인).
       ★세로선(좌측 컬러 바) 삭제(사장님 지시). 공통/특화 구분=폴더 아이콘 색(공통 accent/특화 teal)
       +특화 텍스트 배지(색만 의존 금지). 게이트 훅 .erp-group[data-scope=special]·data-erp·순서·기능 불변. */
    .erp-group{margin-top:6px;padding-left:0}   /* 세로선(3px) 제거. ★padding-left 12→0(2026-07-21·LNB-1): 그룹/항목/가이드선 전체를 '내 업무'(.task-tree) 좌측 기준에 정합(좌측 공백 제거·헤드리스 실측 Δ가이드선 0). */
    .erp-group:first-child{margin-top:2px}
    .erp-fold>summary{list-style:none}                 /* 네이티브 디스클로저 마커 제거(자체 캐럿) */
    .erp-fold>summary::-webkit-details-marker{display:none}
    /* 이커머스 대시보드 — 카드 상단(아이콘+라벨) · 섹션 제목 */
    .eco-home-top { display: flex; align-items: center; gap: 8px; margin: 0 0 6px }
    .eco-home-top .eco-home-label { margin: 0 }
    .eco-dash-sec { margin: 16px 0 8px; font-size: 12px; color: var(--muted);
      border-top: 1px solid var(--border); padding-top: 12px }

    /* ★Phase 92 P2 — 색을 **기본 규칙**으로 올린다. 종전엔 `[data-scope]` 가 붙은 그룹에만 색이
       걸려 있어서, 이커머스 소분류처럼 **모듈 스코프가 없는 그룹**은 색을 못 받았다.
       ★`data-scope="common"` 을 붙여 맞추는 방법도 있었지만 그건 거짓말이다(이커머스는 공통이
       아니다) — 표시 규칙을 고칠 자리에서 고친다. 아래 두 스코프 규칙은 같은 값이라 무해하게 존치. */
    .erp-group-title{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--text);
      letter-spacing:.02em;padding:4px 6px;opacity:.9;text-transform:none;cursor:pointer;border-radius:6px}
    .erp-fold>summary.erp-group-title:hover{background:var(--panel-2)}
    /* 폴더 아이콘(내 업무 .tt-ic 16px 정합) — details[open] 로 folder↔folder-open 전환. 색=currentColor(그룹 색 상속). */
    .erp-group-title .erp-fold-ic{width:16px;height:16px;flex:none;display:inline-flex;align-items:center}
    /* 접힘=folder / 펼침([open])=folder-open. ★[open] 시 folder-open 을 다시 표시(안 그러면 둘 다 숨김=아이콘 0). */
    .erp-fold>summary .erp-fold-open{display:none}
    .erp-fold[open]>summary .erp-fold-closed{display:none}
    .erp-fold[open]>summary .erp-fold-open{display:inline-flex}
    /* 트리 노드(항목) — 들여쓰기 + 좌측 가이드 라인(상·하위 구분·.tt-node::before 정합). */
    .erp-fold>.erp-item{position:relative;margin-left:6px;padding:5px 8px 5px 16px;border-radius:6px;font-size:13.5px}   /* margin 8→6(LNB-1): 가이드선을 '내 업무' d1 좌측선과 정확 정합 */
    .erp-fold>.erp-item::before{content:"";position:absolute;left:3px;top:-1px;bottom:-1px;
      border-left:1px solid var(--border);opacity:.55}
    .erp-group .erp-item [data-lucide],.erp-group .erp-item svg{width:16px;height:16px;flex:0 0 16px;opacity:.85}
    /* 무채색화(2026-07-21·사장님 지시) — 제목·폴더 아이콘(currentColor 상속) 색을 '내 업무' 트리 텍스트와
       동일 토큰(var(--text))으로. 청색/틸 제거. 공통/특화 구분은 색이 아니라 '특화' 텍스트 배지가 담당(존치).
       ★셀렉터/구조/배지 불변(색 값만 변경) — 게이트 훅 data-scope·data-erp·순서·modules.js 무접촉. */
    .erp-group[data-scope="common"] .erp-group-title{color:var(--text)}
    .erp-group[data-scope="special"] .erp-group-title{color:var(--text)}
    /* 배지 — 텍스트 라벨(색만 의존 금지·WCAG AA 지향). 병합=중립·특화=틸·신규=블루. */
    .erp-badge{margin-left:auto;font-size:9px;font-weight:700;padding:1px 6px;border-radius:999px;
      line-height:1.5;white-space:nowrap}
    .erp-badge-merge{background:color-mix(in srgb, #94a3b8 12%, transparent);color:#94a3b8}
    .erp-badge-special{margin-left:6px;background:color-mix(in srgb, #14b8a6 12%, transparent);color:#14b8a6}
    .erp-badge-new{background:color-mix(in srgb, #60a5fa 12%, transparent);color:#60a5fa}
    /*  ★W-UIX14-S1 — `.eco-home-card`(위의 `background: var(--panel)` · 테두리 1px · 호버 이동)가
        공용 레시피보다 세다 ⇒ **이 자리에서 셋을 함께 걷는다**(마크업은 무접촉). */
    .eco-home-card.fx-card { background: var(--surface, #FFFFFF); border: 0; }
.eco-home-card.fx-card:hover { transform: none; border-color: transparent; }

/*  ★W-UIX9 ③ — 이커머스 카드도 **같은 최소 폭·자동 열**(할일·자동화와 같은 결). */
.tv-sub[data-tv="ecom"] .eco-home-cards
  { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }


/* ══════════════════════════════════════════════════════════════════════════
   메일(받은편지함·상세·분류·되돌리기) — 화면 규칙(2026-09-11 W-UIX14-S5-4 이사)
   ★인라인 `<style>` 은 이 파일보다 **늦게 로드돼 이긴다** — 그래서 옮긴 것을 파일 **맨 끝**에
     둔다(그 자리를 유지해야 값이 안 바뀐다). ★이사에서는 값을 한 글자도 안 고쳤다 ·
     부품 수렴(카드·버튼·칩·탭)은 이 블록을 **고치는 다음 단계**에서 한다.
   ★줄 구간이 아니라 **규칙 단위**로 옮겼다 — 구간마다 남의 모듈 규칙이 섞여 있어
     통째로 옮기면 남의 것을 끌고 온다(실측).
   ══════════════════════════════════════════════════════════════════════════ */

    .mail-shell { display: flex; flex-direction: column; height: 100%; min-height: 0; }
    /* ★W-NH2 알림함 — 메일과 **같은 부류**(목록 화면)라 같은 규칙을 건다: 컬럼에 천장을 주고
       스크롤은 목록 내부(`.nh-body`)가 맡는다. 규칙을 새로 만들지 않고 위 선례를 그대로 쓴다. */
    /* ★W-UIX1 ④(2)(2026-09-06) — 알림함 페이지 폐지: noti 뷰의 높이 규칙
       높이 규칙을 걷었다(그 뷰가 더 이상 없다). 알림은 벨 → 작은 모달(`.noti-panel`)이다. */
    .mail-bar { display: flex; align-items: center; gap: 6px; padding: 8px 12px; flex-wrap: wrap;
      border-bottom: 1px solid var(--border, #2a2f3a); }
/*   ★★W-UIX14-S5-4(릴리 Q3 결재) — 메일 필터는 **하나만 고르는 자리**다([전체]/[안 읽음]/
     [중요]) ⇒ 캔버스와 같은 **텍스트 탭**(밑줄 2px · 알약 0).
     ★자산 툴바는 여럿이 켜지므로 토글이었다(S5-2) — 같은 규칙의 반대쪽이다. */
.mail-bar .mail-filter { padding: 5px 12px; cursor: pointer; font-size: 12.5px; border: 0;
      border-bottom: 2px solid transparent; background: transparent; color: var(--muted);
      font-family: inherit; }
    /* ★86.8 — [새 편지]가 [전체]와 **같은 하늘색**이 되도록 선택자에 합류시킨다(사장님).
       색을 새로 정하지 않는다 — 같은 선언을 공유하면 다음에 강조색이 바뀌어도 함께 따라간다. */
    .mail-bar .mail-filter.is-on { background: transparent; color: var(--text);
      border-bottom-color: var(--accent); }
    .mail-bar .mail-filter:hover { color: var(--text); }
    /*   ★[새 편지]는 이 화면의 **주행동**이다 — 하나만 채운다. */
    .mail-bar .mail-new { border: 1px solid transparent; border-radius: 8px; padding: 7px 14px;
      font-size: 13px; font-weight: 400; font-family: inherit; cursor: pointer;
      color: var(--btn-fg, #fff);
      background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2))); }
    /* ★86.4 — 상태는 **맨 뒤**에 있고 평상시엔 빈 문자열이다. `margin-left:auto` 는 유지하지만
       앞이 아니라 **뒤**에 있으므로 조작 컨트롤을 밀어내지 않는다(빈 span 은 자리를 먹지 않는다). */
    .mail-bar .mail-status { font-size: 12px; color: var(--muted, #94a3b8); margin-left: auto; }
    /* 필터는 받은편지함 전용 축 — 보낸함에서는 JS 가 이 클래스로 숨긴다(83.2-b/c 공통). */
    .mail-bar .mail-filter.hidden { display: none; }
    /* ★84.1 H1 — 읽음 동기화 권한 재연결 안내. **경고가 아니라 안내**다(기존 기능은 정상 동작).
       색을 위험(적색)으로 쓰지 않고 무채색+강조 테두리로만 둔다 — 고장으로 오인시키지 않기 위해서다. */
    .mail-reconnect { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
      padding: 8px 12px; font-size: 12.5px; color: var(--muted, #94a3b8);
      border-bottom: 1px solid var(--border, #2a2f3a); }
    .mail-reconnect .mrc-btn { padding: 5px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--accent, #3b82f6); background: transparent; color: var(--accent, #3b82f6); }
    /* ★84.2 [실행 취소] 스낵바 — 되돌릴 수 있다는 사실을 그 자리에서 알린다(결재 G5). */
    .mail-undo { position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
      display: flex; align-items: center; gap: 12px; padding: 9px 14px; border-radius: 10px;
      font-size: 12.5px; z-index: 40; color: var(--text, #e2e8f0);
      background: var(--panel-2, #1e293b); border: 1px solid var(--border, #2a2f3a);
      box-shadow: 0 6px 20px rgba(0,0,0,.28); }
    .mail-undo .mu-btn { padding: 4px 10px; border-radius: 7px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--accent, #3b82f6); background: transparent; color: var(--accent, #3b82f6); }
    /* 하위 폴더 항목도 `sb-navitem mail-item` 이라 위 규칙이 이미 크기를 준다 — 여기서 다시
       지정하면 같은 사실을 두 곳에 적는 것이다(들여쓰기만 남긴다). */
    .mail-folder-list .mail-item { padding-left: 30px; }
    /* ★Phase 94 S5-b — 이 배지는 이제 **표식이 아니라 토글**이다. 종전 `opacity:0`(hover 전용)은
       보여 주기만 할 때는 맞았지만, 조작 지점이 되면 **잡을 수 있는 줄을 모른다**
       (93 C2-b: "되는데 아무도 안 쓰면 안 되는 것과 같다" — 기능이 아니라 생김새가 문제였다).
       ★손이 필요한 상태(수집 꺼짐)는 **항상 보이고**, 정상 상태(수집중)는 옅게 둔다 —
       행동으로 이어지는 것만 눈에 띄게(86.1 배지 규율과 같은 저울). */
    .mail-folder-list .mf-sub { margin-left: auto; font-size: 10.5px; opacity: .95;
      padding: 1px 6px; border-radius: 999px; border: 1px solid var(--border);
      color: var(--muted); cursor: pointer; white-space: nowrap; }
    .mail-folder-list .mf-sub.on { opacity: .35; border-color: transparent; }
    .mail-folder-list .mail-item:hover .mf-sub { opacity: 1; }
    .mail-folder-list .mf-sub:hover { border-color: var(--accent); color: var(--accent); }
    .mail-folder-list .mf-empty { padding: 6px 12px 6px 30px; font-size: 12px;
      color: var(--muted, #94a3b8); }
    .mail-category-list .mail-item { padding-left: 30px; }
    /* 개수 배지 — 수집 축의 `.mf-sub` 와 달리 **누르는 것이 아니다**(표식일 뿐이라 커서도 기본). */
    .mail-category-list .mc-count { margin-left: auto; font-size: 10.5px; opacity: .55;
      color: var(--muted); white-space: nowrap; }
    /* ★빈 상태 — 시드가 0이라 처음엔 반드시 여기를 지난다. **빈 표를 그리지 않고**
       무엇을 하면 되는지 말한다(정본: 없는 것을 빈 표로 그리지 마라). */
    .mail-category-list .mc-empty { padding: 6px 12px 8px 30px; font-size: 12px;
      color: var(--muted, #94a3b8); line-height: 1.5; }
    .mail-category-list .mc-add, .mail-category-list .mc-empty .mc-link {
      background: none; border: 0; padding: 0; color: var(--accent); cursor: pointer;
      font-size: 12px; text-decoration: underline; }
    .mail-category-list .mc-add { display: block; padding: 6px 12px 6px 30px; }
    /* 분류를 보고 있을 때의 안내 줄(=조작 자리). `.mail-trunc` 모양을 그대로 쓴다(새 부품 0). */
    .mail-catbar { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
    .mail-catbar .mc-link { background: none; border: 0; padding: 0; color: var(--accent);
      cursor: pointer; font-size: 12px; text-decoration: underline; }
    /* ★[분류하기]는 [옮기기]와 **나란히 서지만 다른 일**이다 — 폭·모양은 같게 두고
       (같은 종류의 컨트롤이므로) 구분은 **낱말**이 한다. */
    /* ★★M3-f ①(사장님: *"배경색만 찐하다"*) — 실측한 원인: 이 줄의 **다른 컨트롤은 전부
       `background: transparent`** 다(`.md-actions button` · `.mail-bar .mail-q`).
       M3 에서 `.fx-input` 을 입히면서 `--fx-field-bg`(채운 색)까지 따라와 **혼자 진해졌다**.
       ★모양(라운드·테두리)은 fx 그대로 두고 **배경만** 이웃과 맞춘다 — 색을 새로 정하지 않고
       옆 필드가 쓰는 값을 그대로 쓴다(라이트/다크 모두 이웃과 같이 움직인다). */
    .md-classify { max-width: 190px; background: transparent; }
    /* ★F2-2 규칙판 — 분류를 보고 있을 때만 목록 위에 선다(`.mail-trunc` 모양 재사용·새 부품 0). */
    .mail-rulebox { display: flex; flex-direction: column; gap: 5px; }
    .mail-rulebox .mr-head { color: var(--muted, #94a3b8); }
    .mail-rulebox .mr-row { display: flex; gap: 8px; align-items: baseline; }
    .mail-rulebox .mr-row.off { opacity: .5; }          /* 꺼진 규칙 — 있지만 안 돈다 */
    /* ★지금 보고 있는 분류의 규칙 — 전역 목록에서 내 것을 찾을 수 있게(순서는 전역이다). */
    .mail-rulebox .mr-row.mine .mr-what { font-weight: 600; }
    .mail-rulebox .mr-what { min-width: 0; }
    .mail-rulebox .mc-link[disabled] { opacity: .3; cursor: default; text-decoration: none; }
    /* ★F3 최근 정리(되돌릴 수 있는 것) — 규칙 목록과 한 판 안에 있되 한 줄 띄워 가른다. */
    .mail-rulebox .mr-undohead { margin-top: 6px; padding-top: 6px;
      border-top: 1px solid var(--border, #2a2f3a); }
    .mail-rulebox .mr-undo .mr-what { color: var(--muted, #94a3b8); }
    .mail-rulebox .mr-new { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
    /* ★★M2-f ④(사장님 스크린샷) — 이 폼만 **모양 규칙이 없어** 브라우저 기본(각진 셀렉트·
       네모 버튼)으로 떴다. 여기서 크기만 정하고 **모양은 fx 토큰에 맡긴다**(`.fx-input`).
       ★padding 을 2px 로 눌러 두면 fx 의 라운드가 찌그러진다 — fx 기본값을 살리고 글자만 줄인다. */
    .mail-rulebox .mr-field, .mail-rulebox .mr-value { font-size: 12px; }
    .mail-rulebox .mr-value { max-width: 220px; }
    /* [규칙 추가]는 이 판의 주 동작이라 채운 버튼(fx-go)이다 — 크기만 목록에 맞춘다. */
    .mail-rulebox .mr-new .fx-btn { font-size: 12px; padding: 5px 12px; }
    .mail-rulebox .mc-link { background: none; border: 0; padding: 0; color: var(--accent);
      cursor: pointer; font-size: 12px; text-decoration: underline; }
    /* 절단 안내 — 목록 상단(조용한 절단 금지·L3) */
    .mail-trunc { padding: 7px 12px; font-size: 12px; color: var(--muted, #94a3b8);
      border-bottom: 1px solid var(--border, #2a2f3a); }
    /* ★86.7 — [새 편지]는 이 화면의 **주요 동작**이다. 나머지 버튼과 같은 모양이면
       뭐부터 해야 하는지가 보이지 않는다. 색은 **토큰만** 쓴다(하드코딩 금지). */
    .mail-bar .mail-new { padding: 5px 10px; border-radius: 8px; cursor: pointer;
      font-size: 12px; border: 1px solid transparent; font-weight: 600; }
    .mail-bar .mail-new:hover { filter: brightness(1.06); }
    .mail-body { display: flex; flex: 1; min-height: 0; overflow: hidden; }
    /* ★83.1-b(사장님 실기기 피드백) — 목록은 **컴팩트 고정폭**, 본문이 잔여 전폭을 갖는다.
       340px 은 목록이 과점유해 HTML 본문 가독 폭이 부족했다(메일 클라이언트 관례는 280px 내외).
       고정폭이라 창을 키우면 늘어난 폭은 전부 본문 몫이 된다. 모바일(≤760)은 아래에서 100% 로
       덮어써 기존 목록↔상세 전환 동작이 그대로 유지된다(변경은 데스크톱 분할 비율만). */
    /* ★85.2 — 폭은 이제 **사용자가 정한다**. 280px 은 이제 "고정"이 아니라 **기본값**이고,
       실제 값은 JS 가 `--mail-list-w` 로 넣는다(저장된 선택이 없으면 이 기본값 그대로). */
    .mail-list { width: var(--mail-list-w, 280px); flex: none; overflow-y: auto;
      border-right: 1px solid var(--border, #2a2f3a); }
    /* ★85.1(사장님 지시) — 목록 열 **전용** 얇은 스크롤바. 전역 스크롤바는 건드리지 않는다
       (다른 화면 전부에 파급되고 되돌릴 때 반경을 알 수 없다).
       ★기본은 거의 투명하되 **완전히 지우지는 않는다** — 아예 안 보이면 "더 아래에 메일이 있다"는
       사실까지 사라진다. hover·스크롤 중에만 옅게 드러낸다(완전 투명을 원하면 hover 규칙 1줄 제거).
       ★색은 `currentColor` 기반이라 다크/라이트가 자동으로 맞는다(하드코딩 금지 — 07-21 무채색화 정합). */
    .mail-list { scrollbar-width: thin; scrollbar-color: transparent transparent; }   /* Firefox */
    .mail-list:hover, .mail-list:focus-within { scrollbar-color: color-mix(in srgb, currentColor 28%, transparent) transparent; }
    .mail-list::-webkit-scrollbar { width: 6px; }
    .mail-list::-webkit-scrollbar-track { background: transparent; }
    .mail-list::-webkit-scrollbar-thumb { background: transparent; border-radius: 999px; }
    .mail-list:hover::-webkit-scrollbar-thumb,
    .mail-list:focus-within::-webkit-scrollbar-thumb { background: color-mix(in srgb, currentColor 28%, transparent); }
    /* ★85.2 — 리사이저 핸들. 히트 영역은 6px(본문 클릭을 가로채지 않는 최소치)이고 **보이는 선은
       기존 목록 테두리**다(새 선을 하나 더 긋지 않는다). 모바일에서는 아래 미디어쿼리가 숨긴다. */
    .mail-resizer { flex: none; width: 6px; margin-left: -3px; margin-right: -3px; z-index: 2;
      cursor: col-resize; background: transparent; }
    /* ★85.10 ④ — 드래그는 **동작한다**(계측: 280→370px). 사장님이 못 쓰신 이유는 ①문서 전체가
       스크롤되어 레이아웃이 어긋났고 ②핸들이 쉬는 상태에서 **보이지 않아** 있는 줄 몰랐던 것이다.
       ①은 위 높이 교정으로 사라졌고, ②는 **넓히지 않고 눈에 띄게** 한다 — 히트 영역은 6px 그대로
       두고(본문 클릭을 가로채지 않는 최소치) hover 대비를 올리고 드래그 중에는 더 진하게. */
    .mail-resizer:hover { background: color-mix(in srgb, currentColor 35%, transparent); }
    .mail-body.mr-drag .mail-resizer { background: color-mix(in srgb, currentColor 55%, transparent); }
    .mail-body.mr-drag { cursor: col-resize; user-select: none; }
    /* 상세는 세로 flex — 헤더/액션/첨부는 고정 높이, 본문 호스트가 남는 공간을 전부 먹는다.
       ★HTML 본문 iframe 은 sandbox="" 라 스크립트가 없어 높이 자동 맞춤(postMessage)이 불가하다.
       그래서 '내용에 맞춰 늘리는' 대신 **영역을 채우고 iframe 자체 스크롤**로 읽게 한다(83.1-a). */
    .mail-detail { flex: 1; display: flex; flex-direction: column; overflow: hidden;
      padding: 18px 22px; min-width: 0; }
    .mail-detail .md-bodyhost { flex: 1; min-height: 0; display: flex; flex-direction: column;
      overflow-y: auto; }
    .mail-detail .md-note { flex: none; margin-top: 8px; font-size: 12px; color: var(--muted, #94a3b8); }
    .mail-row { display: block; width: 100%; text-align: left; padding: 9px 12px; cursor: pointer;
      border: 0; border-bottom: 1px solid var(--border, #2a2f3a); background: transparent;
      color: var(--text, #e2e8f0); font: inherit; }
.mail-row:hover { background: var(--surface-2, rgba(148,163,184,.18)); }
/*   ★★W-UIX14-S5-4 — 안 읽음은 **상태**다. 종전에는 강조색 8% 틴트라 줄 전체가 파랗게
     물들어 *'선택된 줄'* 처럼 보였다(선택은 따로 있다: `.is-sel` 의 외곽선) ⇒ 잿빛 표면 톤으로.
     안 읽음의 **진짜 표시는 굵기와 배지**다 — 색은 거들 뿐이다. */
.mail-row.is-unread { background: var(--surface-2, rgba(148,163,184,.12)); }
    .mail-row.is-sel { outline: 2px solid var(--accent, #3b82f6); outline-offset: -2px; }
    /* ★말줄임 정합(83.1-b) — flex 아이템의 기본 min-width:auto 는 '콘텐츠보다 작아지지 않기'라
       overflow:hidden 만으로는 줄어들지 않는다. 좁아진 폭에서 발신자가 안 줄어들어 시각(mr-date)을
       바깥으로 밀어내던 원인이 이것이다. 컨테이너와 신축 아이템 양쪽에 min-width:0 을 줘야 말줄임이
       실제로 작동한다. */
    .mail-row .mr-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
    /* 읽음/안읽음 구분(사장님 지시 2026-07-27) — 발신자 볼드는 **미읽음 한정**(제목 :is-unread
       규칙과 동형). 읽음 행은 굵기만 일반으로 내리고 색은 낮추지 않는다(회색으로 죽어 보이지 않게).
       배경 틴트(.is-unread)·선택 아웃라인(.is-sel)은 무접촉. */
    .mail-row .mr-from { font-size: 13px; flex: 1; min-width: 0; overflow: hidden;
      text-overflow: ellipsis; white-space: nowrap; }
.mail-row.is-unread .mr-from { font-weight: 500; }
    .mail-row .mr-date { font-size: 11.5px; color: var(--muted, #94a3b8); flex: none;
      white-space: nowrap; }
    .mail-row .mr-subj { font-size: 13px; margin-top: 3px; overflow: hidden; text-overflow: ellipsis;
      white-space: nowrap; }
.mail-row.is-unread .mr-subj { font-weight: 500; }
/*   ★분류 꼬리표는 공용 작은 칩이다(다른 화면의 배지와 한 벌). */
.mail-row .mr-tags { display: inline-flex; align-items: center; gap: 4px; font-size: 11px;
      padding: 1px 7px; border-radius: var(--r-chip); margin-top: 2px;
      background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted); }
    .mail-empty { color: var(--muted, #94a3b8); font-size: 13px; padding: 12px 0; }
    /* 수신 계정 배지(83.2-a Q3) — provider 1글자. ★계정이 2개 이상일 때만 JS 가 붙인다(1계정=노이즈).
       같은 provider 가 둘이면 글자가 같으므로 색(계정 순서 팔레트 3색)과 툴팁(전체 주소)이 구분 축이다.
       무채색 기조(07-21 LNB 지시)를 지켜 채도는 낮게 — 색은 구분 축이지 강조 축이 아니다. */
    .mail-row .mr-acct { flex: none; font-size: 10px; font-weight: 700; line-height: 1;
      padding: 2px 4px; border-radius: 4px; margin-right: 5px; border: 1px solid var(--border, #2a2f3a);
      color: var(--muted, #94a3b8); }
    .mail-row .mr-acct.acct-c0 { color: #94a3b8; }
    .mail-row .mr-acct.acct-c1 { color: #7dd3fc; }
    .mail-row .mr-acct.acct-c2 { color: #86efac; }
    /* 작성창(회신·새 편지) — 신규 모달 0. 상세 영역을 그대로 쓴다(모바일 목록↔상세 전환 계승). */
    .mail-compose { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
    .mail-compose .mc-title { font-size: 16px; font-weight: 800; }
    .mail-compose .mc-field { display: flex; flex-direction: column; gap: 4px; }
    .mail-compose .mc-label { font-size: 11.5px; color: var(--muted, #94a3b8); }
    .mail-compose input, .mail-compose select, .mail-compose textarea {
      width: 100%; padding: 7px 9px; border-radius: 8px; font-size: 13px; font-family: inherit;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .mail-compose textarea { resize: vertical; line-height: 1.6; }
    /* ★회신의 보내는 계정은 **입력이 아니라 표시**다(결재 E1) — 바꿀 수 있는 컨트롤을 두지 않는다. */
    .mail-compose .mc-from-fixed { display: flex; align-items: center; gap: 8px; padding: 7px 9px;
      border-radius: 8px; font-size: 13px; border: 1px dashed var(--border, #2a2f3a); }
    .mail-compose .mc-note { font-size: 11px; color: var(--muted, #94a3b8); }
    .mail-compose .mc-actions { display: flex; align-items: center; gap: 8px; margin-top: 2px; }
    .mail-compose .mc-actions button { padding: 6px 14px; border-radius: 8px; cursor: pointer;
      font-size: 12.5px; border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .mail-compose .mc-msg { font-size: 12px; color: var(--muted, #94a3b8); }
    .mail-compose .mc-hint { font-size: 11.5px; color: var(--muted, #94a3b8); margin: 0; }
    .mail-compose button:disabled { opacity: .6; cursor: default; }
    /* 세로 flex 안에서 헤더/액션/첨부는 줄어들면 안 된다(기본 flex-shrink:1 + overflow:hidden 이면
       본문 iframe 이 커질 때 제목·첨부 줄이 찌그러진다). flex:none 으로 고정. */
    .mail-detail .md-subject { flex: none; font-size: 17px; font-weight: 800; margin-bottom: 6px; }
    .mail-detail .md-meta { flex: none; font-size: 12.5px; color: var(--muted, #94a3b8); margin-bottom: 12px; }
    .mail-detail .md-body { white-space: pre-wrap; word-break: break-word; font-size: 13.5px;
      line-height: 1.65; }
    .mail-detail .md-actions { flex: none; display: flex; gap: 6px; flex-wrap: wrap; margin: 12px 0; }
    /* ★86.8(사장님) — 데스크탑에서는 목록이 **항상 왼쪽에 보이므로** [← 목록]이 할 일이 없다.
       ★모바일(≤760)은 목록↔본문 **전환** 구조라 이 버튼이 **유일한 복귀 수단**이다 → 아래 760 블록에서
       되살린다. 넓은 폭 → 좁은 폭 순서를 지킨다(뒤집히면 모바일에서 숨김이 이겨 갇힌다). */
    .mail-detail .md-actions [data-mail-act="back"] { display: none; }
    .mail-detail .md-actions button { padding: 5px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    /* ★85.4 — 폴더 이동 선택. 액션 줄의 버튼들과 같은 결로 둔다(새 시각 언어를 만들지 않는다). */
    /* ★85.5 — 전달 작성창의 첨부 미동반 안내(조용한 누락 금지). 경고가 아니라 **사실 고지**라
       색을 세게 쓰지 않는다 — 겁주는 것이 목적이 아니다. */
    .mail-compose .mc-warn { display: block; margin: 2px 0 8px; }
    /* ★85.7 첨부 버튼 — 링크처럼 보이되 버튼이다(토큰이 헤더라 href 직링크를 못 쓴다). */
    /* ★85.8 검색 — 상단 바 안에서 다른 버튼과 같은 결(새 시각 언어를 만들지 않는다). */
    .mail-bar .mail-q { flex: 1; min-width: 120px; max-width: 260px; padding: 5px 10px;
      border-radius: 8px; font-size: 12px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; }
    .mail-bar .mail-search-remote { padding: 5px 10px; border-radius: 8px; cursor: pointer;
      font-size: 12px; border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
    /* 검색 범위 안내 — ★"무엇을 뒤졌는지"를 말하는 줄. 결과가 0건일 때 특히 중요하다. */
    .mail-scope { padding: 6px 12px; font-size: 11.5px; color: var(--muted, #94a3b8);
      border-bottom: 1px solid var(--border, #2a2f3a); }
    /* ★88.1 [AI로 읽기] — 받기(다운로드)와 **다른 일**이므로 모양도 다르게 둔다.
       강조색은 쓰되 토큰만 쓴다(색 하드코딩 금지). */
    .mail-detail .md-att-ai { margin-right: 6px; padding: 3px 8px; border-radius: 7px; cursor: pointer;
      font-size: 12px; border: 1px solid var(--accent, #3b82f6); background: transparent;
      color: var(--accent, #3b82f6); }
    .mail-detail .md-att-ai:hover { background: var(--accent, #3b82f6); color: #fff; }
    .mail-detail .md-att { margin-right: 6px; padding: 3px 8px; border-radius: 7px; cursor: pointer;
      font-size: 12px; border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .mail-detail .md-attnote { color: var(--muted, #94a3b8); font-size: 11.5px; }
    .mail-detail .md-move { padding: 5px 8px; border-radius: 8px; font-size: 12px; cursor: pointer;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .mail-detail .md-attach { flex: none; margin-top: 14px; font-size: 12.5px; color: var(--muted, #94a3b8); }
    /* HTML 본문 격리 프레임(기본 표시·83.1-a) — sandbox="" 전면 차단. 높이는 남는 영역을 채우고
       넘치는 분량은 프레임 내부 스크롤로(자동 리사이즈는 스크립트가 필요해 구조적으로 불가).
       min-height 는 상세 영역이 짧을 때의 하한(짜부라짐 방지). */
    .mail-detail .md-html { width: 100%; flex: 1; min-height: 360px; border: 1px solid var(--border, #2a2f3a);
      border-radius: 8px; background: #fff; }
    /* 좁은 데스크톱·태블릿(≤1200) — 사이드바(약 250px)까지 감안하면 목록 280px 는 본문을 다시 좁힌다.
       ★이 블록은 반드시 아래 ≤760 블록보다 **앞에** 둔다(동일 특이도는 소스 순서로 결정 — 뒤에 두면
       모바일에서 width:100% 를 덮어써 목록↔상세 전환이 깨진다. v156 온보딩에서 겪은 부류의 결함). */
    @media (max-width: 1200px) {
      .mail-list { width: var(--mail-list-w, 240px); }   /* ★기본값만 좁힌다(사용자 선택은 유지) */
    }
    @media (max-width: 760px) {
      /* ★85.2 — 이 폭에서는 목록↔상세 **전환** 구조라 리사이저가 의미가 없다(폭이 100% 다).
         핸들을 남겨 두면 화면만 먹고 오작동의 여지가 된다 → 숨긴다. */
      .mail-list { width: 100%; border-right: none; }
      .mail-resizer { display: none; }
      .mail-body[data-mv="detail"] .mail-list { display: none; }
      .mail-body[data-mv="list"] .mail-detail { display: none; }
      /* ★86.8 — 이 폭에서는 목록이 **가려지므로** [← 목록]이 유일한 복귀 수단이다. 반드시 되살린다. */
      .mail-detail .md-actions [data-mail-act="back"] { display: inline-block; }
    }
    .mail-unread-badge { margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: 11px;
      font-weight: 700; background: var(--accent, #3b82f6); color: #fff; }


/* ══════════════════════════════════════════════════════════════════════════
   입구(로그인·체험)·온보딩·설정 — 화면 규칙(2026-09-12 W-UIX14-S6-A 이사)
   ★인라인 `<style>` 은 이 파일보다 **늦게 로드돼 이긴다** — 그래서 옮긴 것을 파일 **맨 끝**에
     둔다(그 자리를 유지해야 값이 안 바뀐다). 이사에서는 값을 한 글자도 안 고쳤다 ·
     부품 수렴(카드·버튼·칩·타일)은 이 블록을 **고치는 다음 단계**에서 했다.
   ★줄 구간이 아니라 **규칙 단위**로 옮겼다 — 인라인 한 블록 안에 다른 화면 규칙이 섞여
     있어(설정 블록 240 중 설정은 47) 통째로 옮기면 남의 것을 끌고 온다(실측).
   ★`.dl-row` 는 **대시보드 일정 목록과 이름이 같다** — 그래서 `#dl-devices` 로 좁힌 것만 집었다.
   ══════════════════════════════════════════════════════════════════════════ */
.boot-pending #login-view, .boot-authed #login-view:not(.login-modal) { display: none; }   /* 래퍼는 레이아웃에서 사라진다(부모 flex 그대로) */
    .boot-authed [data-demo-static] { display: none !important; }
    /* ★W-UIX11 ④ — 자바스크립트가 꺼진 PC 에 서는 얇은 안내 띠(종전의 큰 블록을 대신한다).
       체험 껍데기 **안** 상단이라 로그인 폼 위에 서던 자리는 사라졌다. */
    .ns-strip { padding: 9px 14px; font-size: 13px; line-height: 1.55; text-align: center;
      color: var(--muted, #667085); background: var(--panel-2, #171326);
      border-bottom: 1px solid var(--border); }
    .ns-strip a { color: var(--accent, #2563eb); }
    .ns-strip .ns-seo { display: block; font-size: 12px; opacity: .8; margin-top: 3px; }
    /* ★UX4 A — 게스트 로그인 버튼: 사이드바 '의견 보내기' 바로 아래 인라인(정상 흐름·position:fixed 폐지=기기 무관 렌더).
       로그인 사용자(비-demo) 무영향. ★UX8 ③ 아이콘 log-in(라인 언어)·⑤ 볼드 제거·④ .sb-foot-row 배치(마진은 행이 담당). */
    /* ★D4/UX7 — 데모(세션·정적 폴백) 양쪽에서 하단 로그인 버튼 노출. ★UX7 ⑤ 플레인(배지/배경 제거·아이콘+"로그인" 텍스트만). */
    .demo-login-btn { display: none; }
    :is(.demo-mode, .demo-session) .demo-login-btn {
      display: inline-flex; align-items: center; gap: 7px;
      margin: 0; padding: 6px 4px; cursor: pointer;
      font-size: 13px; font-weight: 400; color: var(--text, #cbd5e1);
      background: transparent; border: 0;
    }
    :is(.demo-mode, .demo-session) .demo-login-btn:hover { color: var(--accent, #2563eb); }
    :is(.demo-mode, .demo-session) .demo-login-btn .ic { width: 18px; height: 18px; flex: none; background: transparent; }
    :is(.demo-mode, .demo-session) .demo-login-btn .ic svg, :is(.demo-mode, .demo-session) .demo-login-btn .lucide { width: 18px; height: 18px; opacity: .9; }
    .demo-mode .sb-navitem[data-tool="onboarding"] { display: none; }  /* '시작하기' 숨김(로그인 후에만) */
    /* ★G2 Q3 — SOP 스토어는 게스트 숨김(공개 스킬 무인증 열람은 API 신설 필요 = 금지·별도 단계). */
    .demo-mode #sop-store { display: none; }
    /* ★Phase 83.1 — 메일은 데모/게스트에게 구조적으로 숨긴다(실제 메일 표면을 공용 데모 계정에
       주지 않는다). 서버도 require_not_demo 로 403 — FE 는 표면 정리용 1겹(정본은 서버). */
    :is(.demo-mode, .demo-session) #mail-section { display: none !important; }
    /* ★G2 — [＋ 새 대화] 앵커: 게스트 전용(로그인 사용자는 업무별 스레드 정책상 부재 — 재도입 아님). */
    #demo-new-chat { display: none; }
    .demo-mode #demo-new-chat {
      display: flex; align-items: center; gap: 6px; width: calc(100% - 20px);
      margin: 8px 10px 4px; padding: 9px 12px; border-radius: 10px; cursor: pointer;
      font-size: 13.5px; font-weight: 600; color: var(--text, #e2e8f0);
      background: var(--panel-2, rgba(255,255,255,.04)); border: 1px solid var(--border, #334155);
    }
    .demo-mode #demo-new-chat:hover { border-color: var(--accent, #2563eb); }
    /* ★G2 — [워키에 대하여] 게스트 메뉴 엔트리(뷰 본체는 G3 — 여기선 /about 새 탭). */
    /* ★UX5 ① — [워키에 대하여]: 데모 세션·정적 폴백 양쪽 표시(공유 게이트). 클릭=about 캔버스(G3 iframe·tv-wide). 로그인 사용자 무접촉. */
    #demo-about { display: none; }
    :is(.demo-mode, .demo-session) #demo-about { display: flex; }
    /* ★UX7 ②-1 — 데모(세션·정적 폴백) 양쪽 설정 버튼 노출(좌측 필수 3종 = about·로그인·설정). 계정 탭만 비활성(settings.js).
       ★로그아웃은 데모 계속 숨김(토큰 폐기→재발급 루프 회피·실계정 전환은 [로그인] 버튼). 실사용자(비-demo)는 설정·로그아웃 그대로. */
    :is(.demo-mode, .demo-session) #logout-btn { display: none; }
    /* ★82.2 §5-A — 가입 폐쇄 서버 신호(no-registration·auth.js demo_disabled 분기에서만 부여):
       로그인 카드의 회원가입 토글·SSO 진입점 숨김(CSS 게이트·요소/핸들러 무삭제). 계정=OWNER 초대 흐름.
       cloud(데모 on)=클래스 미부여=무변경. 초대 수락 폼(#invite-form)은 무접촉(온프렘 계정 정본 경로). */
    .no-registration #to-register, .no-registration #register-form,
    .no-registration #sso-block { display: none !important; }
    /* ★UX8 ④ — 설정이 .sb-foot-row 로 이동해 데모의 계정 행(.sb-account)은 배지·로그아웃 모두 숨김 = 빈
       구분선만 남으므로 행 자체를 숨김. 실사용자(비-demo)는 배지+로그아웃 행 그대로. */
    :is(.demo-mode, .demo-session) .sb-account { display: none; }
    /* ★UX7 ⑥ — 데모(비로그인)는 내 업무 잠금 항상 해제 → 트리 헤더 자물쇠 버튼 제거(수정 자유·tasks.js isUnlocked 동조). 로그인 사용자 무접촉. */
    :is(.demo-mode, .demo-session) #task-lock-btn { display: none; }
    /* ★UX5 ② — 설정 모달 데모 비활성 탭(프로필·멤버 관리·회원탈퇴): 회색·커서 차단·툴팁. 클릭 무효는 settings.js. */
    /* ★86.1 계정 상태 배지 — **행동으로 이어지는 것만** 띄운다(정상은 배지 없음).
       색은 토큰 기반(하드코딩 금지·테마 정합). */
/*   ★메일 계정 배지가 다른 화면 칩과 한 벌이 됐다(테두리 0 · 표면 톤). */
.ec-badge { display: inline-flex; align-items: center; gap: 4px; border: 0;
  border-radius: var(--r-chip); padding: 1px 7px; font-size: 10.5px; font-weight: 400;
  background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted); margin-left: 6px; white-space: nowrap; }
.ec-badge.ec-warn { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
    #settings-modal .set-nav-item.set-demo-off { opacity: .45; cursor: not-allowed; }
    #settings-modal .set-nav-item.set-demo-off:hover { background: transparent; }
    /* 배지 숨김(데모 세션 badge='demo·대표' 대신 상단 공유 고지로 상태 전달). 실사용자(비-demo)는 그대로. */
    :is(.demo-mode, .demo-session) #user-badge { display: none; }
    /* ★D4 — 데모 세션 상단 공유 고지(은은한 1줄·.chat-main[flex column] 상단=UX3 스트립 레이아웃 교훈 준수). */
    /* ★UX7 — 상단 공유 고지: 데모(세션·정적 폴백) 양쪽 동일 표시(혼합 제거). '데모 계정' 표현 제거·체험 공간 톤. */
    #demo-session-notice { display: none; }
    :is(.demo-mode, .demo-session) #demo-session-notice {
      display: block; margin: 0; padding: 7px 14px; text-align: center;
      font-size: 12px; color: var(--muted, #667085); background: var(--panel-2);
      border-bottom: 1px solid var(--border, #334155);
    }
    /* ★G3b — [구글시트 데스크] 캔버스 iframe(공개 시트·읽기 전용). URL 미확정 시 안내 문구. */
    #demo-sheets { display: none; }
    .demo-mode #demo-sheets { display: flex; }
    /* ★G2 — 첫 화면 인사말 + 예시 프롬프트 칩(게스트 전용·데모챗 전송). */
    /* ★★W-UIX13-C ②(2026-09-10) — 체험 숫자 타일은 **체험 셀의 것**이다.
       정적본 자체는 `.boot-authed [data-demo-static]` 가 이미 숨긴다(③) — 다만 그
       그릇(`#demo-tiles`)은 제 규칙이 없어 **빈 칸으로** 남고, 도구 화면(tv-open)에서도
       안 접혔다. `#demo-hero` 와 **같은 짝**을 적어 자리를 맞춘다.
       로그인 사용자의 타일은 `#dash-tiles`(대시보드)가 따로 맡는다. */
    #demo-tiles { display: none; }
    .demo-mode #demo-tiles { display: grid; max-width: 720px; margin: 18px auto 0; padding: 0 16px; }
    body.tv-open #demo-tiles { display: none !important; }
    #demo-hero { display: none; }
    .demo-mode #demo-hero { display: block; max-width: 720px; margin: 18px auto 6px; padding: 0 16px; }
    /* ★G3 — 도구 뷰(간편장부·about 등)가 열리면 인사말+칩을 숨겨 겹침 방지. tv-open 은 <body>·demo-mode 는
       <html> 이라 한 요소로 못 묶으므로 body.tv-open 으로 건다(hero 는 demo 에서만 표출되니 안전).
       관찰자 인라인 display 를 이기려 !important. tv 닫히면 규칙 해제 → 관찰자 상태로 복귀. G2 ERP 뷰도 개선. */
    body.tv-open #demo-hero { display: none !important; }
/*   ★굵기 800 은 이 판에서 걷는다 — 인사는 크기로 서지 굵기로 서지 않는다. */
#demo-hero .dh-greet { font-size: 20px; font-weight: var(--fw-3, 600); color: var(--text); margin-bottom: 4px; }
#demo-hero .dh-sub { font-size: 13.5px; color: var(--muted); margin-bottom: 14px; }
    #demo-hero .dh-chips { display: flex; flex-wrap: wrap; gap: 8px; }
/*   ★★체험 제안 칩은 **누르면 그 말로 시작하는 손잡이**다 — 칩이 아니라 보조 버튼의 결이다.
     알약(999px)도 걷었다: 손잡이는 화면마다 다른 모양을 갖지 않는다(S5-2 에서 세운 규칙). */
#demo-hero .demo-chip { padding: 7px 14px; border: 1px solid var(--hairline); border-radius: 8px;
  cursor: pointer; font-size: 13px; font-weight: 400; font-family: inherit;
  background: transparent; color: var(--muted); color: var(--text); }
    #demo-hero .demo-chip:hover { border-color: var(--accent, #2563eb); }
    /* 설정 — 고급 기능 그룹(다른 섹션처럼 구분선 선명) */
    .set-adv-group{margin-top:20px;padding-top:16px;border-top:1px solid var(--border)}
    .set-b2b{margin-top:12px}
    .set-toggle{display:flex;align-items:center;gap:8px;margin-top:6px;font-size:13px;cursor:pointer}
    /* 설정 — 중앙캔버스 → 모달 오버레이 전환 */
    #settings-modal.set-in-canvas{display:none}
    #settings-modal.set-in-canvas.open{position:fixed;inset:0;z-index:1200;display:flex;
      align-items:flex-start;justify-content:center;background:rgba(0,0,0,.55);
      overflow-y:auto;padding:40px 16px}
    #settings-modal.set-in-canvas.open .modal-card{position:relative;width:100%;max-width:720px;
      max-height:none;margin:auto;background:var(--panel);color:var(--text);border:1px solid var(--border);
      border-radius:16px;box-shadow:0 24px 70px rgba(0,0,0,.5);padding:22px 26px 26px}
    /* 모달 내부면(네비/본문)도 좌측 사이드바와 동일 배경(--panel)으로 통일 */
    #settings-modal.set-in-canvas.open .set-nav,
    #settings-modal.set-in-canvas.open .set-body{background:var(--panel)}
    /* 설정 좌측 메뉴 탭(이미지 참조) */
    #settings-modal .set-layout{display:flex;align-items:stretch}
    /* ★W-ENT1 2단계 — 묶음 머리 여섯이 붙으면서 목록이 본문보다 길어졌다. 종전에는 nav 에 높이
       규칙이 없어 **모달이 목록만큼 늘어나** 마지막 묶음([함께 쓰기])이 화면 밖으로 밀렸다
       (실브라우저 실측). 본문과 **같은 높이 규칙**을 주고 넘치면 목록만 구른다 — 새 값 0(짝을 맞춘다). */
    #settings-modal .set-nav{flex:0 0 160px;display:flex;flex-direction:column;gap:2px;
      padding:6px 14px 8px 0;border-right:1px solid var(--border);
      height:min(560px,64vh);overflow-y:auto}
    #settings-modal .set-nav-head{font-size:12px;font-weight:700;color:var(--muted);
      padding:0 10px 10px;letter-spacing:.02em}
    /* 모달 제목 — 좌측 맨 위. */
    #settings-modal .set-nav-head.set-nav-title{font-size:14px;color:var(--text)}
    /* ★★W-ENT2 — 좌측은 **대분류**다. W-ENT1 의 탭 스타일을 그대로 물려받되(새 색·새 모양 0)
       이름만 `.set-group` 으로 갈랐다 — 같은 이름이 두 층을 가리키면 언젠가 한쪽이 조용히 죽는다. */
    #settings-modal .set-group{text-align:left;padding:9px 12px;border:0;border-radius:9px;
      background:transparent;color:var(--text);font-size:13.5px;cursor:pointer}
#settings-modal .set-group:hover { background: var(--surface-2, rgba(148,163,184,.12)); }
/*   ★고른 대분류는 **표면 톤 + 강조 글자**로 말한다(굵기 700 은 걷었다). */
#settings-modal .set-group.active { background: var(--surface-2, rgba(148,163,184,.18)); color: var(--accent);
  font-weight: var(--fw-3, 600); }
    /* ★우측 탭 줄 — 부품은 `.cv-tab` 그대로다(W-ADM2 선례). 줄만 이 화면 몫으로 좁힌다. */
    #settings-modal .set-main{flex:1;min-width:0;padding-left:24px;display:flex;flex-direction:column;
      height:min(560px,64vh)}
    /*   ★W-UIX14-F3 ②(사장님 실기) — 탭 이름이 붙어 보였다. 탭 부품은 **한 벌**이라
         캔버스 `.cv-tabs` 의 기본 간격(14px)에 맞춘다(좁은 폭도 같이). */
    #settings-modal .set-tabs{flex:0 0 auto;flex-wrap:nowrap;overflow-x:auto;gap:14px;
      padding-bottom:10px;border-bottom:1px solid var(--border);margin-bottom:14px}
    #settings-modal .set-tabs .cv-tab{flex:0 0 auto;white-space:nowrap}
    /* ★다른 대분류의 탭은 내려둔다 — 게이트의 `hidden` 과 **다른 표식**이다
       (한 표식이 두 뜻을 겸하면 뜻을 바꾸는 순간 한쪽이 조용히 어긋난다). */
    #settings-modal .set-tabs .set-off-group{display:none}
    /* ★W-ENT1 3단계 — 사용량. 색은 전부 기존 토큰(새 색 0). 게이지 한 줄 + 30일 막대. */
    #usage-host .ug-row{display:flex;align-items:baseline;gap:8px;margin:2px 0 6px}
    #usage-host .ug-big{font-size:20px;font-weight:800;color:var(--text)}
    #usage-host .ug-bar{height:10px;border-radius:999px;background:var(--panel-2);overflow:hidden}
    #usage-host .ug-fill{height:100%;border-radius:999px;background:var(--accent)}
    /* 한도를 넘긴 상태는 **색이 먼저 말한다** — 막지는 않는다(소프트 기준선이다). */
    #usage-host .ug-fill.over{background:var(--danger,#e5484d)}
    #usage-host .ug-basis{margin-top:6px}
    #usage-host .ug-spark{display:flex;align-items:flex-end;gap:2px;height:56px;margin-top:12px}
    #usage-host .ug-spark i{flex:1 1 0;min-width:2px;background:var(--panel-2);border-radius:2px 2px 0 0}
    #usage-host .ug-spark i.on{background:var(--accent);opacity:.75}
    #usage-host .ug-sub{display:flex;justify-content:space-between;margin-top:4px}
    #usage-host .ug-backends{margin-top:14px;display:flex;flex-direction:column;gap:4px}
    /*   ★★W-UIX14-S6-A 이사가 드러낸 자리 — 이 규칙은 폼 전용 토큰(--fx-fs)을 빌려 쓰고
         있었다. 인라인에 살던 동안은 그 사실을 재는 자(test_seg1_3::u7)가 **못 봤다**
         (그 자는 style.css 만 읽는다). 값은 같게 두고(12.5px) 남의 식구 토큰만 뗀다. */
    #usage-host .ug-be{display:flex;gap:8px;font-size:12.5px}
    #usage-host .ug-be b{min-width:96px}
    /* 데스크톱 연결(P5-c) — 색·모양은 전부 기존 토큰. 새 색을 만들지 않는다. */
    #desktop-link-section .dl-actions{display:flex;align-items:center;gap:10px;margin:6px 0}
    #desktop-link-section .dl-code{font-family:ui-monospace,Consolas,monospace;font-size:18px;
      font-weight:700;letter-spacing:2px;color:var(--accent)}
    #desktop-link-section .dl-devices{margin-top:10px;display:flex;flex-direction:column;gap:6px}
    /*   ★이사가 드러낸 자리 둘 — 폼 전용 토큰을 빌려 쓰고 있었다(값은 같게 두고 뗀다).
         인라인에 살던 동안은 재는 자가 못 봤다(그 자는 style.css 만 읽는다). */
    #desktop-link-section .dl-row{display:flex;align-items:center;gap:8px;font-size:12.5px}
    #desktop-link-section .dl-name{font-weight:600}
    #desktop-link-section .dl-when{color:var(--muted);font-size:12px}
    #desktop-link-section .dl-row .fx-btn{margin-left:auto}
    /* 다운로드 줄(WD1) — 기존 토큰만 쓴다(새 색 0). */
    #desktop-link-section .dl-download{display:flex;align-items:center;gap:10px;margin-top:14px}
    #desktop-link-section .dl-smartscreen{margin-top:6px;line-height:1.5}
    #desktop-link-section .dl-download a.fx-btn{text-decoration:none;display:inline-block}
    /* 본문 높이 '고정' — 탭(좌측 메뉴)마다 내용 길이가 달라도 모달 높이 불변. 넘치면 본문만 스크롤.
       큰 모니터에서 과대해지지 않도록 px 상한(min)으로 컴팩트하게. */
    /* ★W-ENT2 — 높이·좌패딩은 `.set-main` 이 든다. 본문은 **탭 줄 밑 남은 자리**를
       먹고 거기서만 굴러야 탭 줄이 같이 밀려 올라가지 않는다(탭은 항상 보여야 한다). */
    #settings-modal .set-body{flex:1 1 auto;min-height:0;overflow-y:auto}
    #settings-modal .set-body .set-panel{display:none;border-top:none;margin-top:0;padding-top:0}
    #settings-modal .set-body .set-panel.active{display:block}
    #settings-modal .set-body .set-section-title{margin-top:0}
    /* ★직급 드롭다운이 행을 다 먹어 [이양]·[내보내기]가 모달 밖으로 밀렸다(86.6).
       원인은 `.mbr-role-sel` 이 아니라 아래 공통 규칙이다 —
       `#settings-modal .set-body select{max-width:380px;width:100%}` 이 **더 구체적**이라
       `flex:none` 과 맞물려 "줄지 않는 100% 폭"이 됐다. 같은 무게로 되돌린다. */
    #settings-modal .set-body select.mbr-role-sel{width:auto;max-width:96px;min-width:0}
    /* 입력란 — 데스크탑 과대 방지(좁은 폭·작은 패딩) */
    #settings-modal .set-body input:not([type=checkbox]):not([type=radio]),
    #settings-modal .set-body select,
    #settings-modal .set-body textarea{max-width:380px;width:100%;box-sizing:border-box;
      padding:8px 10px;font-size:13px;border-radius:8px;background:var(--panel-2);
      border:1px solid var(--border);color:var(--text)}
        .ns-strip { position: fixed; top: 0; left: 0; right: 0; z-index: 9999; }
    /* 가이드 온보딩 OS(ⓐ) — 좌 게이지+체크리스트 / 우 상세. 자체 포함(오프라인). */
    .onboarding-host { display: flex; height: 100%; }
    .onb-side { width: 288px; flex: none; border-right: 1px solid var(--border, #2a2f3a);
      padding: 18px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }
    .onb-main { flex: 1; overflow-y: auto; padding: 22px 26px; }
    /* 모바일 상세 '닫기' — 데스크탑 숨김(2단 동시표출이라 불요). 톤=.onb-btn 상속(상세 다른 버튼과 정합).
       모바일 표출 override 는 아래 @media 에서(소스순서로 승리). */
    .onb-back { display: none; }
    /* 모바일(≤760·앱 표준 브레이크포인트) — 리스트↔상세 탭 전환. data-mv 로 한쪽만 표출·세로 구분선 제거·전체폭.
       ★이 @media 는 반드시 기본 .onb-* 규칙 "뒤"에 둔다 — 동일 특이도 override 는 소스 순서로 결정되므로,
       앞에 두면 기본 .onb-back{display:none}·.onb-side{border-right:1px}가 뒤에서 덮어써 모바일 뒤로가기 미표출·
       세로 구분선 잔존 결함이 재발한다(v156 결함의 근본 원인). 데스크톱(2단)은 이 @media 밖이라 무회귀. */
    @media (max-width: 760px) {
      .onb-side { width: 100%; border-right: none; border-bottom: none; max-height: none; }
      .onb-main { width: 100%; }
      .onboarding-host[data-mv="detail"] .onb-side { display: none; }
      .onboarding-host[data-mv="list"] .onb-main { display: none; }
      .onboarding-host[data-mv="detail"] .onb-main { animation: onbSlideIn .2s ease; }   /* 리스트→상세 슬라이드 */
      /* 상세 '닫기' — 내용 하단·좌측 정렬(detail 뒤 배치). sticky 헤더 폐지(앱 상단바 겹침·스와이프 충돌 제거). */
      .onb-back { display: inline-flex; align-items: center; align-self: flex-start; margin-top: 8px; }
    }
    .onb-gauge-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.onb-gauge-pct { font-size: 26px; font-weight: var(--fw-3, 600); color: var(--accent); }
    .onb-gauge-lbl { font-size: 12.5px; color: var(--muted); }
/*   ★게이지는 **자체 부품으로 유지**한다(지시서 판정) — 안쪽으로 파인 자리라 `--panel-2`. */
.onb-bar { height: 8px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
    .onb-bar-fill { height: 100%; background: var(--accent); border-radius: 999px; transition: width .3s; }
    .onb-checklist { display: flex; flex-direction: column; gap: 6px; }
/*   ★★체크리스트 줄이 **공용 줄(`.wk-row`) 결**이 됐다 — 줄마다 테두리 상자를 두르면
     목록이 카드의 목록처럼 보인다(줄은 줄이다). */
.onb-step { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 9px 6px; cursor: pointer; font-size: 14px; color: inherit;
  background: transparent; border: 0; border-bottom: 1px dotted var(--border); }
.onb-step:hover { background: var(--surface-2, rgba(148,163,184,.12)); }
.onb-step.onb-sel { background: var(--surface-2, rgba(148,163,184,.18)); }
    .onb-ic { width: 22px; height: 22px; flex: none; display: inline-flex; align-items: center;
      justify-content: center; border-radius: 999px; font-size: 12px; font-weight: 700;
      background: var(--panel, #0f131a); border: 1px solid var(--border, #2a2f3a); color: var(--muted); }
.onb-done .onb-ic { background: var(--accent); color: var(--btn-fg, #fff); border-color: transparent; }
    .onb-step-lbl { flex: 1; }
/*   ★'필수'·'준비 중'은 **상태 칩**이다(다른 화면 칩과 한 벌 · 뜻 색은 유지). */
.onb-req { display: inline-flex; align-items: center; gap: 4px; border: 0;
  border-radius: var(--r-chip); padding: 1px 7px; font-size: 10.5px; font-weight: 400;
  background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent); }
    .onb-dismiss { margin-top: auto; background: transparent; border: none; color: var(--muted);
      font-size: 12.5px; cursor: pointer; padding: 8px; text-align: left; }
    .onb-dismiss:hover { color: var(--text); }
    .onb-detail-wrap h2 { font-size: 20px; margin: 0 0 6px; display: flex; align-items: center; gap: 8px; }
    .onb-desc { color: var(--muted); font-size: 13.5px; line-height: 1.5; margin: 0 0 16px; }
/*   ★표면·테두리·그림자는 **공용 레시피**가 준다(위 목록에 합류) — 여기엔 이 화면 몫만 남는다. */
.onb-card { margin-bottom: 14px; }
.onb-card-h { font-weight: var(--fw-3, 600); font-size: 15px; margin-bottom: 6px;
  display: flex; align-items: center; gap: 8px; }
    .onb-hint { color: var(--muted); font-size: 12.5px; margin: 0 0 12px; line-height: 1.45; }
    .onb-ok { font-size: 12px; color: var(--accent); font-weight: 700; }
    .onb-todo { font-size: 12px; color: var(--muted); }
/*   ★온보딩 버튼이 공용 보조 버튼의 결이 됐다(주행동만 채운다 — 바로 아래). */
.onb-btn { padding: 7px 14px; border: 1px solid var(--hairline); border-radius: 8px;
  cursor: pointer; font-size: 13px; font-weight: 400; font-family: inherit;
  background: transparent; color: var(--muted); }
/*   ★주행동 하나만 채운다(공용 `.btn-accent` 와 같은 레시피). */
.onb-btn.onb-primary { border-color: transparent; font-weight: var(--fw-3, 600);
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d); }
    .onb-btn.onb-primary:disabled { opacity: .55; cursor: default; }
.onb-btn.onb-ghost { background: transparent; color: var(--muted); }
    .onb-actions { display: flex; gap: 8px; }
    /* ⓑ 인라인 폼(이메일·캘린더) + Keep 자리표시 */
    .onb-form { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
    .onb-flabel { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--muted); }
    /*   ★W-EDU-E0(2026-09-12) — "무엇을 하시나요?" 라디오 셋. 새 부품을 만들지 않고
         **폼 라벨의 결**을 그대로 빌린다(테두리 0 · 채움 0 · 글자와 점 하나). */
    .onb-profile { border: 0; padding: 0; margin: 0; }
    .onb-profile legend { padding: 0; font-size: 12.5px; color: var(--muted); }
    .onb-radio { display: flex; align-items: center; gap: 8px; padding: 6px 0;
      font-size: var(--fs-meta, 13px); color: var(--text); cursor: pointer; }
    .onb-radio input { accent-color: var(--accent); }
    .onb-input { padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border, #2a2f3a);
      background: var(--panel, #0f131a); color: var(--text); font-size: 13px; }
    /* '내 업무' 축 — 제안 편집 트리(카테고리+하위·[+추가]/[✕삭제]/이름편집). var(--*)만. */
    .onb-mw-desc { width: 100%; resize: vertical; font-family: inherit; margin-bottom: 10px; }
    .onb-mw-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 10px; }
.onb-mw-cat { border: 1px solid var(--hairline); border-radius: 10px; padding: 10px;
  background: var(--surface, #FFFFFF); }
    .onb-mw-cat-top { display: flex; align-items: center; gap: 8px; }
.onb-mw-cat-name { flex: 1; font-weight: var(--fw-3, 600); }
    .onb-mw-tasks { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 2px; padding-left: 12px;
      border-left: 2px solid var(--border, #2a2f3a); }
    .onb-mw-task { display: flex; align-items: center; gap: 8px; }
    .onb-mw-task-name { flex: 1; }
    .onb-mw-x { flex: none; width: 26px; height: 26px; border-radius: 7px; cursor: pointer;
      background: transparent; border: 1px solid var(--border, #2a2f3a); color: var(--muted); font-size: 12px; }
.onb-mw-x:hover { color: var(--danger); border-color: var(--danger); }
    .onb-mw-add { align-self: flex-start; background: transparent; border: 1px dashed var(--border, #2a2f3a);
      color: var(--muted); border-radius: 8px; padding: 5px 10px; font-size: 12.5px; cursor: pointer; }
.onb-mw-add:hover { color: var(--accent); border-color: var(--accent); }
    .onb-list { display: flex; flex-direction: column; gap: 6px; }
    .onb-list-row { display: flex; align-items: center; gap: 8px; font-size: 13px; }
    .onb-list-row label { flex: 1; display: flex; align-items: center; gap: 6px; }
    .onb-del { background: transparent; border: none; cursor: pointer; font-size: 13px; opacity: .7; }
    .onb-del:hover { opacity: 1; }
    .onb-cal-item { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 3px 0; }
    .onb-step.onb-disabled { cursor: default; opacity: .55; }
.onb-step.onb-disabled:hover { background: transparent; }
.onb-soon { display: inline-flex; align-items: center; gap: 4px; border: 0;
  border-radius: var(--r-chip); padding: 1px 7px; font-size: 10.5px; font-weight: 400;
  background: var(--surface-2, rgba(148,163,184,.15)); color: var(--muted); }


/* ══════════════════════════════════════════════════════════════════════════
   확인창(.confirm-*) — 화면 규칙(2026-09-12 W-UIX14-S6-B 이사)
   ★인라인 `<style>` 은 이 파일보다 **늦게 로드돼 이긴다** — 그래서 옮긴 것을 파일 **맨 끝**에
     둔다(그 자리를 유지해야 값이 안 바뀐다). 이사에서는 값을 한 글자도 안 고쳤다 ·
     부품 수렴(카드·버튼·칩·타일)은 이 블록을 **고치는 다음 단계**에서 했다.
   ★줄 구간이 아니라 **규칙 단위**로 옮겼다 — 인라인 한 블록 안에 다른 화면 규칙이 섞여
     있어(설정 블록 240 중 설정은 47) 통째로 옮기면 남의 것을 끌고 온다(실측).
   ★`.dl-row` 는 **대시보드 일정 목록과 이름이 같다** — 그래서 `#dl-devices` 로 좁힌 것만 집었다.
   ══════════════════════════════════════════════════════════════════════════ */

    .confirm-bar .cf-q { font-weight: 500; }
    .confirm-bar .cf-detail { width: 100%; font-size: 12px; opacity: 0.8; }
/*   ★★W-UIX14-S6-B — 확인창의 hex 열여섯을 걷었다. 위험(#b91c1c)·외부(#2563eb)는
     **뜻**이라 색을 지우지 않고 **토큰**으로 옮겼다 — 테마가 따라오게 하려는 것이지
     의미를 없애려는 것이 아니다(S3 계약). */
.confirm-bar .cf-err { width: 100%; font-size: 12px; color: var(--danger); }
    .confirm-bar .cf-btns { display: inline-flex; gap: 8px; margin-left: auto; }
.confirm-bar .confirm-yes { padding: 4px 10px; border-radius: 6px; border: 1px solid transparent; cursor: pointer; font-family: inherit;
  font-weight: var(--fw-3, 600);
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d); }
.confirm-bar .confirm-no { padding: 4px 10px; border-radius: 6px; cursor: pointer; font-family: inherit; font-weight: 400;
  border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
.confirm-bar[data-kind="danger"] { border-color: var(--danger); }
.confirm-bar[data-kind="danger"] .confirm-yes { background: var(--danger); color: #fff; }
.confirm-bar[data-kind="external"] { border-color: var(--accent); }
.confirm-bar[data-kind="external"] .confirm-yes { background: var(--accent); color: #fff; }
    /* 중앙 모드: 전용 오버레이(z-index 1400) — #settings-modal(1200)·중첩 Modal(1300) 위. */
    .confirm-ov { position: fixed; inset: 0; z-index: 1400; display: flex; align-items: center;
      justify-content: center; background: rgba(15, 18, 28, 0.45); backdrop-filter: blur(4px); }
    .confirm-ov.hidden { display: none; }
    /* ★color=var(--text)(옛 inherit — body 상속색이라 --panel 과 대비 미보장→제목/본문 안 보임). --text/--panel
       은 테마 대비쌍 → .cf-q(제목)·.cf-detail(본문)·.confirm-no(취소) 일괄 상속·라이트/다크·전 kind 가독. */
    .confirm-card { background: var(--surface, #FFFFFF); color: var(--text); border: 0;
      border-radius: 14px; padding: 20px; width: calc(100% - 40px); max-width: 420px;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}
.confirm-card .cf-body .cf-q { display: block; font-weight: var(--fw-3, 600); font-size: 15px; line-height: 1.5; }
    .confirm-card .cf-body .cf-detail { display: block; margin-top: 8px; font-size: 13px; opacity: 0.82; line-height: 1.5; }
.confirm-card .cf-err2 { margin-top: 10px; font-size: 12px; color: var(--danger); }
    .confirm-card .cf-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.confirm-card .confirm-yes { padding: 7px 16px; border-radius: 8px; border: 1px solid transparent; cursor: pointer; font-family: inherit;
  font-weight: var(--fw-3, 600);
  background: var(--btn-bg, linear-gradient(135deg, var(--accent), var(--accent-2)));
  color: var(--btn-fg, #06283d); }
.confirm-card .confirm-no { padding: 7px 16px; border-radius: 8px; cursor: pointer; font-family: inherit; font-weight: 400;
  border: 1px solid var(--hairline); background: transparent; color: var(--muted); }
.confirm-card[data-kind="danger"] .confirm-yes { background: var(--danger); color: #fff; }
.confirm-card[data-kind="external"] .confirm-yes { background: var(--accent); color: #fff; }


/* ══════════════════════════════════════════════════════════════════════
   ★★W-UIX15-INL A(견적+B2B) — `app.html` 인라인에서 **그대로** 옮겨 왔다(값 무변).
   ★인라인 `<style>` 은 이 파일보다 **뒤에** 로드됐다 — 그래서 **파일 끝**에 붙여야
     원래의 캐스케이드 순서가 지켜진다(앞에 넣으면 이기던 규칙이 진다).
   ★app.html 안에서의 **상대 순서**도 그대로다(위 블록이 위에 온다).
   ══════════════════════════════════════════════════════════════════════ */
    /* ★F-1 [설정>정리] — fx 토큰만 쓴다(클래식 버튼 금지 · 디자인 일관성 상시 지시). */
    .cl-store{margin-top:4px}
    .cl-store + .cl-store{margin-top:20px;padding-top:16px;border-top:1px solid var(--border)}
    .cl-store-head{display:flex;align-items:center;gap:10px;margin-bottom:6px}
    .cl-store-name{font-size:13.5px;font-weight:700;color:var(--text,#e2e8f0);flex:1}
    .cl-list{display:flex;flex-direction:column;gap:8px;margin-top:10px}
    .cl-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;
      background:var(--panel-2);border:1px solid var(--border)}
    .cl-main{flex:1;min-width:0}
    .cl-when{font-size:12.5px;color:var(--text,#e2e8f0)}
    .cl-said{color:var(--muted);font-size:12px}
    .cl-names{margin-top:3px;font-size:11.5px;color:var(--muted);overflow:hidden;
      text-overflow:ellipsis;white-space:nowrap}
    .cl-acts{display:flex;gap:6px;flex:none}
    .cl-acts button{font-size:12px;padding:5px 10px;border-radius:8px;cursor:pointer;
      border:1px solid var(--border);background:var(--panel);color:var(--text,#e2e8f0)}
    .cl-acts .cl-purge{border-color:rgba(251,113,133,.5);color:#fb7185;background:transparent}
    /* B2B 하이브리드 UI(Phase 21) — 전표 폼·목록 그리드 (테마 변수 정합) */
    .b2b-form,.b2b-grid{padding:14px 16px;color:var(--text);font-size:13px}
    .b2b-form-title,.b2b-grid-title{font-size:15px;font-weight:700;margin:0 0 12px;color:var(--text)}
    /* 영수증 업로드(Phase 31.3) */
    .b2b-form-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
    .b2b-form-head .b2b-form-title{margin:0}
    .b2b-receipt-btn{padding:6px 12px;border-radius:8px;border:1px solid var(--accent,#2f81f7);background:transparent;color:var(--accent,#2f81f7);cursor:pointer;font-size:12.5px;font-weight:600;white-space:nowrap}
    .b2b-receipt-btn:hover{background:var(--accent,#2f81f7);color:#fff}
    .b2b-field{display:flex;align-items:center;gap:10px;margin-bottom:10px}
    .b2b-field label{flex:0 0 72px;color:var(--muted);font-size:12px}
    .b2b-field input,.b2b-field select,.crm-msg{flex:1;width:100%;box-sizing:border-box;
      padding:8px 10px;border-radius:8px;font-size:13px;
      border:1px solid var(--border);background:var(--panel-2);color:var(--text)}
    .b2b-field input:focus,.b2b-field select:focus,.crm-msg:focus{outline:none;border-color:var(--accent)}
    .b2b-field input[readonly]{opacity:.6}
    .b2b-form-actions{margin-top:14px;display:flex;align-items:center;gap:12px}
    .b2b-save{padding:8px 16px;border:0;border-radius:8px;background:var(--accent);color:#0b1220;
      font-weight:700;cursor:pointer}
    .b2b-save:disabled{opacity:.5;cursor:default}
    .b2b-form-msg{font-size:12px;color:var(--accent)}
    .b2b-grid-scroll{overflow:auto;overflow-x:auto;max-height:100%}
    /* 칼럼이 많으면 컨테이너를 넘어 확장 → 우측 캔버스 안에서 좌우 가로 스크롤(Phase 25.2 결재) */
    .b2b-table{width:auto;min-width:100%;border-collapse:collapse;font-size:12px}
    .b2b-table th,.b2b-table td{padding:6px 8px;border-bottom:1px solid var(--border);text-align:left;white-space:nowrap}
    .b2b-table th{color:var(--muted);font-weight:600;position:sticky;top:0;background:var(--panel)}
    .b2b-table .ta-r{text-align:right}
    .b2b-table tfoot td{font-weight:700;color:var(--accent)}
    .b2b-empty{text-align:center;color:var(--muted);padding:18px}
    /* 그리드 헤더(제목 + 추가 버튼) · 행 클릭(거래처 수정 진입, Phase 27.2) */
    .b2b-grid-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 10px}
    .b2b-grid-head .b2b-grid-title{margin:0}
    .b2b-add-btn{padding:6px 12px;border-radius:8px;border:1px solid transparent;background:var(--accent,#2f81f7);color:#fff;cursor:pointer;font-size:12.5px;font-weight:600;white-space:nowrap}
    .b2b-row-click{cursor:pointer}
    .b2b-row-click:hover td{background:var(--panel-2)}
    /* 미수/수금 관리(Phase 31.1) */
    .rcv-tabs{display:flex;align-items:center;gap:8px;margin:0 0 8px;flex-wrap:wrap}
    .rcv-tab{padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:transparent;color:var(--muted);cursor:pointer;font-size:12.5px;font-weight:600;transition:all .15s ease}
    .rcv-tab.active{background:var(--accent);color:#fff;border-color:transparent}
    .rcv-tab:not(.active):hover{color:var(--text);border-color:var(--accent)}
    .rcv-overdue{margin-left:auto;display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--muted);cursor:pointer}
    .rcv-summary{font-size:13px;color:var(--muted);margin:0 0 10px}
    .rcv-summary b{color:var(--accent);font-size:15px;margin:0 3px}
    .b2b-table .ta-c{text-align:center}
    .rcv-settled{width:88px;padding:3px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font-size:12px;text-align:right}
    .rcv-settled:focus{outline:none;border-color:var(--accent)}
    .rcv-bal{font-weight:700;color:var(--text)}
    .rcv-ag{display:inline-block;padding:1px 7px;border-radius:999px;font-size:11px;font-weight:600}
    .rcv-ag.ag-ok{background:rgba(52,211,153,.15);color:var(--ok,#34d399)}
    .rcv-ag.ag-warn{background:rgba(251,191,36,.15);color:var(--soon,#fbbf24)}
    .rcv-ag.ag-soon{background:rgba(249,115,22,.15);color:#fb923c}
    .rcv-ag.ag-over{background:rgba(248,113,113,.15);color:var(--danger,#f87171)}
    /* 청구서/명세서 발행(Phase 31.2) */
    .inv-ctl{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:0 0 12px}
    .inv-ctl select{padding:6px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font-size:12.5px}
    .inv-ctl .inv-send{background:var(--ok,#34d399)}
    .inv-frame{width:100%;height:440px;border:1px solid var(--border);border-radius:10px;background:#fff;margin:0 0 14px}
    .inv-logs-h{font-size:13px;font-weight:600;color:var(--text);margin:6px 0 8px}
    .inv-ok{color:var(--ok,#34d399);font-weight:600;font-size:12px}
    .inv-wait{color:var(--muted);font-size:12px}
    .inv-logs a{color:var(--accent);text-decoration:none}
    .inv-logs a:hover{text-decoration:underline}
    .inq-list{max-height:280px}
    .inq-row{cursor:pointer}
    .inq-row.inq-focus{outline:1px solid var(--accent);outline-offset:-1px}
    .inq-detail{margin-top:12px}
    .inq-content{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:10px 12px;font-size:12.5px;color:var(--text);margin:0 0 10px;white-space:pre-wrap}
    .inq-answer{width:100%;box-sizing:border-box;margin:0 0 10px;resize:vertical;line-height:1.5}
    /* 아주 넓은 화면에서 글자 칸이 늘어지지 않게 — 숫자·상태 칸은 그대로 두고 **글자 칸만** 다스린다. */
    body[data-tv-layout] .b2b-table td:not(.ta-r):not(.ta-c) { max-width: 340px; }
    /* 멤버 관리(B2B 협업 Stage 1c) — 초대 폼/링크/목록. 설정 톤 재사용. */
    .mbr-link{margin:10px 0 4px}
    .mbr-link-row{display:flex;gap:6px;align-items:center;max-width:420px}
    .mbr-link-row input{flex:1;min-width:0}
    .mbr-copy{flex:none;padding:6px 12px;border-radius:8px;border:1px solid var(--border,#2a2f3a);
      background:var(--panel-2,rgba(255,255,255,.04));color:inherit;cursor:pointer}
    .mbr-section-title{font-size:12px;font-weight:700;color:var(--muted);margin:16px 0 6px}
    .mbr-list{display:flex;flex-direction:column;gap:4px}
    .mbr-row{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:8px;
      background:var(--panel-2,rgba(255,255,255,.03))}
    .mbr-row.mbr-off{opacity:.5}
    .mbr-name{flex:1;min-width:0;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .mbr-name .mbr-sub{color:var(--muted);font-size:11px}
    .mbr-badge{flex:none;font-size:10px;font-weight:700;padding:2px 8px;border-radius:999px;
      background:rgba(59,130,246,.18);color:#60a5fa}
    .mbr-sub{flex:none;color:var(--muted);font-size:11px}
    .mbr-remove{flex:none;font-size:11px;padding:3px 9px;border-radius:8px;cursor:pointer;
      border:1px solid var(--error,#f87171);background:transparent;color:var(--error,#f87171)}
    .mbr-remove:hover{background:var(--error,#f87171);color:#fff}
    .mbr-role-sel{flex:none;font-size:11px;padding:2px 6px;border-radius:7px;
      border:1px solid var(--border,#2a2f3a);background:var(--panel-2,rgba(255,255,255,.04));color:inherit}
    .mbr-transfer{border-color:var(--accent,#3b82f6);color:var(--accent,#3b82f6)}
    .mbr-transfer:hover{background:var(--accent,#3b82f6);color:#fff}
    .pq-note { font-size: 12.5px; line-height: 1.7; color: var(--muted); margin: 2px 2px 8px; }
    .pq-form { border: 1px solid var(--border, #2a2f3a); border-radius: 10px; padding: 10px;
      margin: 0 2px 10px; }
    .pq-form.hidden { display: none; }
    /* ★연결 표식 — 공제 제목줄의 극소형 사실 한 조각("· 입고 #N"). */
    .pqd-batch { font-size: 11.5px; font-weight: 400; color: var(--muted); }
    .pq-sheet.hidden { display: none; }
    .pq-sheet { border: 1px solid var(--border, #2a2f3a); border-radius: 10px; padding: 12px;
      margin: 6px 0 10px; }
    .pq-sheet .pqs-scroll { overflow-x: auto; }
    .pq-sheet table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
    .pq-sheet th, .pq-sheet td { border: 1px solid var(--border, #2a2f3a); padding: 4px 6px; }
    .pq-sheet th { background: rgba(127,127,127,0.12); white-space: nowrap; }
    .pq-sheet td.num, .pq-sheet th.num { text-align: right; }
    .pq-sheet .pqs-sub td { font-weight: 600; background: rgba(127,127,127,0.07); }
    .pq-sheet .pqs-foot { margin-top: 8px; font-size: 12.5px; line-height: 1.8; }
    .pq-badge { font-size: 11.5px; padding: 1px 6px; border-radius: 999px;
      border: 1px solid var(--border, #2a2f3a); }
    /* ★2026-08-05 — 목록 칩([수정]·[확인]). 행 안에서 **가벼운 동작**임을 모양으로 말한다. */
    .pq-chip { border-radius: 999px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: var(--text); padding: 2px 10px; font-size: 11.5px;
      font-weight: 600; cursor: pointer; }
    .pq-chip:hover { border-color: var(--accent); }
    /* ★★⑤2026-08-05(사장님 지시) — 행 안 동작 버튼([발행]·[확정]·[취소]·[삭제])을
       **[수정]·[확인] 칩과 한 식구로** 만든다. 종전엔 이것들만 클래식(각진 기본 버튼)이라
       한 줄에 두 세대의 모양이 섞여 있었다. ★주 동작만 채운다(발행·확정) — 되돌리는 쪽은
       테두리만(취소), 지우는 쪽은 글자색으로 말한다(삭제). */
    .pq-chip.pq-chip-go { background: var(--accent); border-color: transparent; color: #fff; }
    .pq-chip.pq-chip-danger { color: var(--danger, #f87171); }
    .pq-chip.pq-chip-danger:hover { border-color: var(--danger, #f87171); }
    /* ★★★2026-08-05(사장님 재설계 ③⑴) — **상태 다섯을 다 말한다.** 종전엔 작성중만 적어
       나머지 넷이 전부 빈칸이었다(빈칸은 "상태 없음"과 구분되지 않는다).
       ★색은 **뜻으로** 가른다: 아직 내 것(작성중)=강조 · 오간 것(발행·확정)=평범 ·
       끝난 것(입고완료)=성공 · 물린 것(취소)=흐림. 색은 전부 테마 변수에서 파생한다. */
    .pq-badge.pq-st-draft { border-color: var(--accent); color: var(--accent); }
    .pq-badge.pq-st-issued { border-color: var(--accent-2, var(--accent)); }
    .pq-badge.pq-st-confirmed { border-color: var(--accent); font-weight: 600; }
    .pq-badge.pq-st-received { border-color: var(--ok, #34d399); color: var(--ok, #34d399); }
    .pq-badge.pq-st-canceled { opacity: .55; text-decoration: line-through; }
    /* ★★2026-08-05 밤 실측 수리(사장님 스크린샷 2회차) — margin 밀기가 화면에서 안 서서
       **두 칸 구조**로 바꿨다: 바가 전체 폭을 차지하고 소속이 구조로 갈린다.
       좌 칸=제목+동작(매트릭스 노출) · 우 칸=[엑셀 내려받기][인쇄][닫기] 문면 순서 ·
       우 칸은 화면 우측 끝에 붙는다(space-between). 전 상태 공통. */
    .pq-sheet .pqs-bar { display: flex; justify-content: space-between;
      align-items: flex-start; gap: 8px; width: 100%; }
    .pq-sheet .pqs-left, .pq-sheet .pqs-right { display: flex; align-items: center;
      gap: 6px; flex-wrap: wrap; }
    .pq-sheet .pqs-right { flex: 0 0 auto; }
    /* ★①표준값 관리(어휘 `default_deduction`) — 공제 표 아래 접이식 표. */
    /* ★①밤 — 표준값이 탭으로 승격되며 접이식 상자(.pqd-vbox)는 소멸. 스크롤 상자만 남는다. */
    .pqd-vscroll { max-height: 60vh; overflow: auto; }
    /* ★구간 1-③ — 대조표가 [입력] 탭 안에서 폼과 자리를 바꾼다(탭 이동 0). */
    .pq-review { margin: 6px 0; }
    .pq-review.hidden { display: none; }
    .pq-backform { margin-bottom: 6px; }
    .quote-shell { display: flex; flex-direction: column; height: 100%; min-height: 0; }
    .quote-bar { display: flex; align-items: center; gap: 10px; padding: 8px 12px;
      border-bottom: 1px solid var(--border, #2a2f3a); flex: 0 0 auto; flex-wrap: wrap; }
    .quote-bar .quote-new { padding: 6px 12px; border-radius: 8px; cursor: pointer;
      border: 1px solid var(--border, #2a2f3a); background: var(--accent, #3b82f6); color: #fff; font-weight: 600; }
    .quote-filter { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
    .quote-filter .qf-status { padding: 4px 10px; border-radius: 999px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .quote-filter .qf-status.qf-active { background: var(--accent, #3b82f6); color: #fff; border-color: transparent; }
    .quote-summary { margin-left: auto; font-size: 12px; opacity: 0.85; }
    .quote-body { flex: 1 1 auto; min-height: 0; padding: 12px; overflow: hidden; }
    .quote-grid-host { height: 100%; overflow: auto; }
    .quote-table { width: 100%; border-collapse: collapse; font-size: 13px; }
    .quote-table th, .quote-table td { padding: 6px 8px; border-bottom: 1px solid var(--border, #2a2f3a);
      text-align: left; white-space: nowrap; }
    .quote-table th.num, .quote-table td.num { text-align: right; }
    .quote-table th.quote-sortable { cursor: pointer; user-select: none; }
    .quote-title { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
    .quote-row { cursor: pointer; }
    .quote-row:hover { background: var(--panel-2); }
    .quote-row.quote-hi { animation: quoteHi 2.4s ease-out; }
    .quote-empty { padding: 24px; text-align: center; opacity: 0.7; }
    /* 상태 배지 */
    .quote-badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; }
    .quote-badge.qb-draft { background: rgba(148,163,184,0.2); color: #94a3b8; }
    .quote-badge.qb-issued { background: rgba(59,130,246,0.18); color: #60a5fa; }
    .quote-badge.qb-won { background: rgba(34,197,94,0.18); color: #4ade80; }
    .quote-badge.qb-lost { background: rgba(239,68,68,0.18); color: #f87171; }
    /* 라인 편집 폼(우측 캔버스) — 계산기 제로 */
    .quote-form { display: flex; flex-direction: column; gap: 12px; padding: 4px 2px; font-size: 13px; }
    .qf-titlebar { display: flex; align-items: center; gap: 8px; }
    .qf-name { font-weight: 700; font-size: 15px; }
    .qf-fields { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
    .qf-in { padding: 6px 8px; border-radius: 8px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; }
    .qf-fields .qf-in { flex: 1 1 140px; }
    .qf-fields .qf-vat { flex: 0 0 auto; }
    .qf-prefill { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 8px;
      border: 1px dashed var(--border, #2a2f3a); border-radius: 8px; }
    .qf-prefill .qf-lbl { font-weight: 600; opacity: 0.8; }
    .qf-prefill .qf-margin { width: 60px; padding: 4px 6px; border-radius: 6px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; text-align: right; }
    .qf-prefill .qt-prefill { padding: 5px 10px; border-radius: 8px; cursor: pointer;
      border: 1px solid var(--accent, #3b82f6); background: transparent; color: inherit; }
    .qf-prefill-note { font-size: 12px; opacity: 0.8; }
    .ql-table { width: 100%; border-collapse: collapse; }
    .ql-table th { text-align: left; font-size: 11px; opacity: 0.7; padding: 2px 4px; }
    .ql-table th.num { text-align: right; }
    .ql-table td { padding: 2px 3px; vertical-align: top; }
    .ql-in { width: 100%; padding: 4px 6px; border-radius: 6px; box-sizing: border-box;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .ql-in.num { text-align: right; }
    .ql-xs { min-width: 44px; }
    .ql-price { min-width: 72px; }
    .ql-actions { white-space: nowrap; }
    .ql-actions button { padding: 3px 6px; border-radius: 6px; cursor: pointer; font-size: 11px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .ql-note { font-size: 11px; opacity: 0.85; white-space: normal; max-width: 180px; }
    .ql-add { margin-top: 6px; padding: 5px 10px; border-radius: 8px; cursor: pointer;
      border: 1px dashed var(--border, #2a2f3a); background: transparent; color: inherit; }
    .qf-totals { padding: 8px; border-radius: 8px; background: var(--panel-2, rgba(255,255,255,0.04));
      font-size: 13px; }
    .qf-totals .qt-hint { opacity: 0.7; }
    .qf-toolbar { display: flex; gap: 6px; flex-wrap: wrap; }
    .qf-toolbar button { padding: 6px 12px; border-radius: 8px; cursor: pointer;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .qf-toolbar .qt-primary { background: var(--accent, #3b82f6); color: #fff; border-color: transparent; }
    .qf-toolbar .qt-delete { border-color: #b91c1c; color: #ef4444; }
    .qf-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px;
      border: 1px solid var(--accent, #3b82f6); border-radius: 8px; font-size: 13px; }
    .qf-confirm .qf-yes { padding: 4px 10px; border-radius: 6px; border: none; cursor: pointer;
      background: var(--accent, #3b82f6); color: #fff; }
    .qf-confirm .qf-no { padding: 4px 10px; border-radius: 6px; cursor: pointer;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .qf-msg { font-size: 12px; min-height: 16px; }
    .qf-msg.qf-ok { color: #4ade80; }
    .qf-msg.qf-err { color: #f87171; }
    .qf-msg a { color: var(--accent, #60a5fa); word-break: break-all; }


/* ══════════════════════════════════════════════════════════════════════
   ★★W-UIX15-INL B(대화·시트·토스트 + 폼·시트) — `app.html` 인라인에서 **그대로** 옮겨 왔다(값 무변).
   ★A 와 같은 자리·같은 이유다: 인라인 `<style>` 은 이 파일보다 **뒤에** 로드됐으므로
     **파일 끝**(A 묶음 다음)에 붙여야 원래의 캐스케이드가 지켜진다.
   ★app.html 안에서의 **상대 순서**도 그대로다 — 아래 `.fx-switch-sm` 주석이 말하는
     *"같은 특정도에서는 나중에 적은 것이 이긴다"* 가 그래서 여기서도 성립한다.
   ★주인은 **첫 선택자의 첫 클래스**다(`.ais-body > .messages` 는 시트의 규칙이다).
   ══════════════════════════════════════════════════════════════════════ */

    /* 전역 토스트(Phase 33.4) — 백그라운드 작업 완료/실패 알림(우하단 스택) */
    .wc-toast-host{position:fixed;right:18px;bottom:18px;z-index:9999;display:flex;flex-direction:column;gap:8px;max-width:340px}
    /* ★T5 — 보이는 것(opacity)은 **여기서** 정해지고, 애니메이션은 얹히지 않는다. 아래 주석 참조. */
    .wc-toast{display:flex;align-items:center;gap:8px;background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:11px 13px;box-shadow:0 6px 24px rgba(0,0,0,.18);font-size:12.5px;color:var(--text);opacity:1;animation:wc-toast-in .2s ease}
    .wc-toast.clickable{cursor:pointer}
    .wc-toast.clickable:hover{border-color:var(--accent)}
    .wc-toast.out{opacity:0;transform:translateY(6px);transition:all .25s ease}
    .wc-toast-icon{flex-shrink:0}
    .wc-toast-body{flex:1;line-height:1.45}
    .wc-toast-close{border:none;background:transparent;color:var(--muted);cursor:pointer;font-size:12px;padding:2px}
    /* ★T2 — 동시 3건을 넘긴 분량("외 N건" 한 줄). 클릭 없음(목적지가 서로 달라 하나로 못 보낸다). */
    .wc-toast-more{text-align:center;font-size:11.5px;color:var(--muted);background:var(--panel);border:1px dashed var(--border);border-radius:10px;padding:5px 11px;opacity:1;animation:wc-toast-in .2s ease}
    /* ★★T5 — **가시성을 애니메이션에서 분리한다**(등장 효과는 곁들임, 보이는 것이 본질).
       예전에는 `from{opacity:0}` 이라, 애니메이션이 **한 프레임도 못 돌면 투명한 채로 남았다**.
       그 일은 실제로 일어난다: 백그라운드 탭(또는 다른 창에 가린 창)은 프레임을 **한 장도**
       그리지 않는다 — 실측 23초 동안 0장, animation currentTime 은 0 에 머물렀다.
       이제 keyframes 는 **transform 만** 움직인다. 얼어도 제자리(8px 아래)일 뿐 보인다. */
    @keyframes wc-toast-in{from{transform:translateY(8px)}to{transform:none}}

    /* ══ ★Phase 93 C1 — 하단 AI 답변 시트 ═══════════════════════════════════════
       ★중앙 영역 **하단**에만 산다: 그리드는 위에 그대로 보이고, 우측 캔버스(폼·요약)는
       덮지 않는다 — 제안을 보면서 폼에 들어가는 **동시성**이 이 설계의 이유다. */
    /* ★2026-08-02(사장님 지시) — *"대화창 폭을 입력창 폭으로 맞춰줘"*.
       시트 좌우 끝을 **보이는 입력 박스**의 좌우 끝에 맞춘다. 값을 여기 적지 않고
       입력바가 쓰는 그 원천(`--chat-input-inset`)을 **함께 쓴다** — 시트는 메일·이커머스·
       플래너·자산에서도 뜨는데 숫자를 박으면 그 화면들에서 어긋난다.
       ★좁은 화면에서는 그 원천이 0 이라 전폭이 그대로다(규칙 4-4). */
    /* ★★★2026-08-07 사장님 신고 ①② — **둘은 같은 원인이었다.**
       ★실측: 그립을 끌면 inline height 는 **연속으로** 바뀌는데(57.50→56.49→55.48→…) 화면 높이는
       **497px 에 멈춰 있다가**(dy 10~80 전부 497) 50vh 아래로 내려가는 순간 **461 로 뚝 떨어졌다**
       (-36px). 원인은 스냅도 스로틀도 아니라 **`max-height: 50vh`** 였다 — JS 는 25~75vh 로
       움직이는데 CSS 가 50 에서 막아 **50~75 구간(범위의 1/3)이 죽은 구간**이 됐고, 거기서
       아무리 끌어도 화면이 안 움직이다 경계를 넘는 순간 따라붙어 *"칸 단위로 뚝뚝"* 으로 보였다.
       ★★그래서 상한의 **원천을 하나**로 만든다(`--ais-max-vh`) — CSS 와 JS 가 같은 값을 읽으면
       죽은 구간이 **구조적으로 생길 수 없다**. 값은 여기서만 고친다(하드코딩 0 · 각자 셈 금지).
       ★②상한 +50% = 50 × 1.5 = **75vh**. JS 의 기존 MAX 가 이미 75 라 **그 값과 만난다**
       (그리드가 위에 남는다는 이 축의 전제도 그대로 — 화면 밖으로 나가지 않는다). */
    .ai-sheet { position: sticky; bottom: 0; z-index: 5; display: flex; flex-direction: column;
      height: 40vh; max-height: calc(var(--ais-max-vh) * 1vh); min-height: 0;
      margin-inline: var(--chat-input-inset);
      /* ★★W-UIX14-F6 ②(2026-09-12 · 사장님 실기) — **배경이 너무 회색**이었다.
         시트는 대화 영역 위에 **뜬 카드**이지 파인 판이 아니다 ⇒ 채움은 `--surface`
         (그 섹션의 카드 표면 · theme.js 가 섹션 밝기에서 파생 = 다크가 따라온다).
         ★경계는 **선이 아니라 그림자**다 — 테두리를 걷고 위아래 그림자 한 벌로 띄운다
         (`--wk-shadow-up`: 위쪽 = 도크와 시트 사이의 경계 · 아래쪽 = 종전 값의 역할).
         ★**집는 띠(`.ais-grip`)의 선은 그대로 둔다** — 그것은 장식이 아니라 *"여기를
         잡는다"* 는 말이다(2026-08-02·03 사장님 지시 · 그 선을 겨냥한 자리가 곧 잡히는
         자리라 시트 윗변의 색을 일부러 지웠던 그 구조를, 이제 테두리 0 이 대신한다). */
      background: var(--surface, #FFFFFF); border: 0;
      border-radius: 14px 14px 0 0; box-shadow: var(--wk-shadow-up); overflow: hidden }
    .ai-sheet.hidden { display: none }
    /* ★C1-d — 접힘: 시트는 남되 **얇은 바 한 줄**이 된다(입력바 위). 이력은 그대로 살아 있다. */
    .ais-peek { display: none }
    .ai-sheet.ais-collapsed { height: auto !important; max-height: none; min-height: 0 }
    .ai-sheet.ais-collapsed .ais-head, .ai-sheet.ais-collapsed .ais-body { display: none }
    .ai-sheet.ais-collapsed .ais-peek { display: flex; align-items: center; gap: 8px;
      width: 100%; padding: 7px 12px; background: transparent; border: none; cursor: pointer;
      color: var(--muted); font-size: 12.5px; text-align: left }
    .ai-sheet.ais-collapsed .ais-peek:hover { color: var(--text) }
    .ais-peek-text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
    .ais-peek-caret { flex: 0 0 auto; opacity: .75; display: inline-flex; align-items: center }
    .ais-peek-caret [data-lucide], .ais-peek-caret svg { width: 15px; height: 15px }
    .ais-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px;
      border-bottom: 1px solid var(--border); flex: 0 0 auto }
    /* ★C2-b ④ — 드래그 조절. **전폭 띠 + 가운데 알약**(표준 바텀시트 잡이).
       종전 40x5px 조각은 구분선처럼 보여 아무도 잡지 않았다 — 기능이 아니라 **발견성**이 문제였다. */
    /* ★2026-08-02 후속(사장님 지시) — **펼침도 띠가 아니라 선**이다.
       종전 알약(44×5)은 C2-b 가 *"드래그가 되는데 아무도 안 쓴다"* 로 값을 치르고 넣은 것이라
       가볍게 지우지 않았다 — 사장님이 **닫힘과 같은 모양**을 지시하셨고, 남는 신호(ns-resize
       커서 · hover 선 강조 · title 안내)가 스플리터의 표준 어포던스라 판단해 진행한다.
       ★높이 16px 은 **그대로 둔다**: 지시는 *모양*(선)이고, 펼침은 높이 조절을 실제로 쓰는
       자리라 집는 여유가 닫힘보다 더 필요하다(닫힘 10px 은 바를 낮추라는 별도 지시였다).
       ★선은 **그립 자신의 윗변**이다 — 겨냥한 자리와 잡히는 자리를 하나로 만든다. */
    /* ★2026-08-03(사장님 지시) — *"경계선이 아직 선이 아니고 띠로 되어있다"*.
       ★우리가 잰 것은 **테두리 두께**(1px)였고 사장님이 보신 것은 **칠해진 면적**이었다 —
       둘 다 사실이다. 그립은 배경이 투명이라 시트의 회색이 그대로 비치는데, 그립이 **자기 줄**을
       차지하니 선 아래에 **글자 없는 회색 면**(닫힘 10 · 펼침 16px)이 남아 띠로 읽혔다.
       ★띠를 **지우지 않는다**(그러면 잡을 곳이 없어진다) — **흐름 밖으로 내어 아래 내용 위에
       겹치게** 둔다. 보이는 것은 선 하나뿐이고 집는 영역은 그대로다.
       ★`top: 0` 이라 **선이 곧 시트의 윗변**이고, 겨냥한 자리가 잡히는 자리라는 계약도 유지된다. */
    .ais-grip { display: flex; align-items: center; justify-content: center;
      position: absolute; top: 0; left: 0; right: 0; z-index: 1;
      height: 16px; cursor: ns-resize; touch-action: none; background: transparent;
      border-top: 1px solid var(--border) }
    /* ★겹치면 그 밑의 조작이 가려진다 — 머리줄 아이콘(비우기·접기)을 그립 **위로** 올린다.
       특히 `ais-wipe` 는 되돌릴 수 없는 쓰기의 게이트를 여는 버튼이라 반쯤 안 눌리면 안 된다. */
    .ais-head .ais-icon { position: relative; z-index: 2 }
    /* ★알약은 폐기 — 두 상태 모두. 한쪽에만 남겨 두면 언젠가 조용히 되살아나 다시 띠가 된다. */
    .ais-grip-pill { display: none }
    /* ★hover 는 **남은 선**에 건다(두께를 바꾸면 1px 떨린다 — 색 + 그림자로 두껍게 보이게). */
    .ais-grip:hover { background: transparent; border-top-color: var(--accent);
      box-shadow: inset 0 1px 0 var(--accent) }
    /* ★2026-08-02(사장님 지시) — **닫힘 상태의 그립은 "띠"가 아니라 "경계선"이다.**
       닫힌 바가 16(그립)+33(요지줄)+1(테두리)=50px 라 높다는 지적. 그립을 줄여 낮춘다.
       ★단 *"경계선으로만"* 을 문자 그대로 1~2px 로 만들면 **마우스로 못 잡는다** —
       고친 게 아니라 없앤 것이 된다. → **보이는 선은 2px · 집는 영역은 10px** 로 가른다
       (OS 창 가장자리 4~6px · 일반 스플리터 6~8px 보다 여유 있게 잡았다).
       ★펼침 상태의 알약(44x5)은 **그대로 둔다** — C2-b 가 값을 치른 발견성이다
       (*"잡는 곳은 잡아 보이게 생겨야 한다"*). 얇게 만드는 것은 **닫혔을 때뿐**이다.
       ※펼치는 길은 이것 하나가 아니다 — 요지줄(`.ais-peek`) 클릭으로도 펴진다. */
    /* ★2026-08-02 후속(사장님 지적) — *"드레그 하는 부분(경계선)이 이중으로 표시됨"*.
       실측: 시트 윗변(border-top 1px)과 전폭 알약(2px)이 **같은 색으로 5px 떨어져** 있었다.
       각각은 옳았는데 **함께 보니 두 줄**이었다. → 알약을 지우고 **선을 하나만** 남긴다.
       ★남기는 선은 시트 윗변이 아니라 **집는 띠 자신의 윗변**이다. 시트 윗변은 띠보다 **위**라
       사장님이 그 선을 겨냥하면 **집는 영역 밖**을 누르게 된다 — 겨냥한 자리와 잡히는 자리를
       맞추는 대신 **하나로 만든다**(시트 윗변은 색만 지워 높이는 그대로 44px 유지).
       ★hover 신호는 알약에 걸려 있었다 — 알약을 지우면 반응이 사라지므로 **남은 선으로 옮긴다**.
       두께를 바꾸면 1px 떨리므로 **색으로** 알리고, 두꺼워 보이게는 그림자로(레이아웃 무영향).
       ★그리고 닫힘에서는 밴드 전체를 칠하던 기존 hover 를 **덮는다** — 10px 통칠은 지금 만드는
       "가는 경계선"과 정반대로 읽힌다(펼침 상태의 그 규칙은 **그대로 둔다**). */
    /* ★닫힘은 이제 **높이만** 다르다(선·hover 는 위 base 가 준다 — 같은 일을 두 벌로 적지 않는다).
       10px 인 이유는 종전 그대로: 닫힌 바를 낮추라는 사장님 지시(보이는 선 1px / 집는 영역 10px). */
    .ai-sheet.ais-collapsed .ais-grip { height: 10px }
    /* ★펼침 상태의 머리줄은 **누르면 접힌다**(사장님 지시) — 누를 수 있게 생겨야 한다.
       ※버튼 커서 규칙은 **덧붙이지 않는다** — 아이콘 규칙이 이미 pointer 를 갖고 있다.
         (한 번 덧붙였다가 선재 검사가 잡았다: 후손 선택자가 원래 선택자를 **부분문자열로
          포함**해, 그 검사가 내 규칙을 원본으로 착각했다. 죽은 CSS 도 함께 아꼈다.
          ★그 설명을 여기 쓰면서 선택자를 그대로 옮겨 적었더니 **또 걸렸다** — 검사가 보는
          글자는 주석도 포함한다. 인용하지 말고 풀어 쓴다.) */
    .ais-head { cursor: pointer }
    body.ais-dragging { user-select: none; cursor: ns-resize }
    body.ais-dragging .ai-sheet { transition: none }
    /* ★제목이 남은 자리를 다 먹는다 — 조작 요소는 **DOM 순서대로 오른쪽 끝에** 쌓인다.
       특정 버튼에 `margin-left: auto` 를 걸어 오른쪽으로 밀던 종전 방식은 조작 요소가 하나 늘면
       그 자리가 어긋난다(실제로 접기 아이콘이 제목 바로 옆에 붙어 있었다). */
    .ais-title { font-size: 12.5px; color: var(--muted); margin-left: 4px; flex: 1 1 auto }
    /* ★C2-c ② — 접기 아이콘은 **버튼 옷을 벗는다**(테두리·배경 없음 · hover 시 색만).
       머리줄 오른쪽 끝에 놓이되, 조작 요소가 늘면 새 요소는 이 아이콘 **왼쪽**에 붙는다
       (아이콘이 마지막 자식이므로 순서만 지키면 된다). */
    .ais-icon { background: none; border: none; padding: 2px; line-height: 0; cursor: pointer;
      color: var(--muted); display: inline-flex; align-items: center; transition: color .12s ease }
    .ais-icon:hover { color: var(--accent) }
    .ais-icon [data-lucide], .ais-icon svg { width: 16px; height: 16px }
    /* 시트 본문 = 옮겨 온 #messages 가 여기서 스크롤한다(노드는 하나뿐이다) */
    .ais-body { flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex }
    /* ★2026-08-02(사장님 지시) — **펼친 시트는 덮는다**(행을 차지하지 않는다).
       사장님: *"ai답변을 펼치면 그 양옆에 메일리스트나 메일 본문이 가려짐"*.
       ★실측으로 전제가 뒤집힌 자리다: 가리는 것이 `.chat-area` 의 칠인 줄 알았는데, 재어 보니
       **메일 영역과 시트가 정확히 맞닿아 겹침이 0** 이었다(메일 t52~b491 · 시트 t491~b889).
       시트가 flex 열의 **한 행을 통째로** 차지하고 콘텐츠가 그 위로 줄어든 것이라, 칠을 걷어도
       그 자리엔 **애초에 메일이 없다.** → 행 밖으로 낸다.
       ★규칙 4-3 해석(아키텍트 판정): *"시트가 차지한 높이는 빼 준다"* 의 근거는 *"접힘 바 높이를
       빼지 않으면 마지막 줄이 가려진다"* 이고 그 근거는 **상시 존재하는 것**에만 성립한다 —
       접힘 바는 상시라 **공간을 예약**하고(아래 규칙 무접촉), 펼친 시트는 사용자가 직접 연
       **일시적인 것**이라 **덮는다**.
       ★`bottom` 에 숫자를 박지 않는다: 입력바 높이는 화면·글꼴에 따라 달라진다. 시트 geometry 의
       주인(`chat.js`)이 재서 `--ais-bottom` 으로 넘긴다.
       ★데스크톱 미디어에 가둔다 — 모바일은 **이미** 고정 바텀시트(규칙 4-4)인데 이 선택자가
       특이도가 높아 그대로 두면 그것을 덮어쓴다. */
    @media (min-width: 761px) {
      /* ★2026-08-03 교정 — `left/right: 0` 이었는데 절대 배치는 **패딩 박스** 기준이라
         `.chat-main` 의 좌우 패딩(`--chat-pad`)만큼 시트가 **더 넓어졌다**(실측: split 에서
         시트 263~1901 vs 입력박스 279~1885 = 좌우 16px 초과).
         ★8/2 에 맞춘 *"시트 폭 = 입력 박스 폭"* 계약을 **내 오버레이 커밋이 깨뜨린 것**이다 —
         이 건을 재다가 발견했다. 같은 원천(`--chat-pad`)만큼 들여 콘텐츠 상자에 맞춘다. */
      body.ais-open .ai-sheet { position: absolute; bottom: var(--ais-bottom, 0px);
        left: var(--chat-pad); right: var(--chat-pad); z-index: 15 }
    }
    /* ★뒤 콘텐츠가 살아 있으므로 **스크롤이 새지 않게** 막는다 — 시트 안에서 끝까지 굴린 뒤에도
       휠이 계속 돌면 뒤 목록이 따라 움직인다(답변을 읽다가 화면이 흔들린다). */
    .ais-body > .messages { overscroll-behavior: contain }
    /* ★W-AUTOREG-B3 ⓒ(2026-09-07 · 사장님) — 마지막 답변이 하단 입력 도크에 가리지 않게 **입력창
       높이만큼** 바닥 여백을 상시 예약한다(`--chat-dock-h` = chat.js 가 실측 · W-UIX1 ② 선례).
       종전엔 `body[data-ct-live]`(턴 진행 중)에만 예약돼 턴이 끝나면 마지막 답변이 도크 밑으로 숨었다. */
    /* ★`--chat-dock-h` 가 초기 0 으로 굳는 경우(입력바 hidden→표시 전환을 ResizeObserver 가 놓침)를
       대비해 **최소 72px** 를 `max()` 로 깐다(입력 도크 실높이 ≈ 68px · 정상 측정 시엔 실높이가 이긴다). */
    .ais-body > .messages { flex: 1; overflow-y: auto; padding: 10px 12px max(var(--chat-dock-h, 96px), 72px) }
    /* ★C2-b ⑤ — 시트 안에서는 근거/출처 영역을 감춘다(사장님 지시). ★일반 대화의 출처 표시는
       **무접촉**이다 — 환각억제 표면은 정본이고, 여기서는 좁은 시트의 가독을 위해 **가리기만** 한다
       (지우는 것이 아니라 이 자리에서만 접는 것 · 전체 대화로 가면 그대로 보인다). */
    .ais-body .sources { display: none }
    @media (max-width: 760px) {                  /* 모바일 = 바텀시트(높이 조절 핸들 없음) */
      .ai-sheet { position: fixed; left: 0; right: 0; bottom: 0; height: 55vh; max-height: 70vh;
        border-radius: 16px 16px 0 0; z-index: 60 }
      .ais-grip { display: none }        /* 모바일은 바텀시트 고정 높이 — 잡이를 아예 안 보인다 */
    }
    /* 컨텍스트 요약(우측 기본 콘텐츠) */
    .ctx-sum { font-size: 13px; line-height: 1.6 }
    .ctx-h { font-size: 14px; font-weight: 700; margin: 0 0 10px }
    .ctx-none { color: var(--muted); font-size: 12.5px }
    .ctx-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0 0 4px }
    .ctx-kpi { border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; background: var(--panel) }
    .ctx-kpi span { display: block; font-size: 11px; color: var(--muted) }
    .ctx-kpi b { font-size: 15px }
    .ctx-sec { margin: 14px 0 6px; font-size: 11.5px; color: var(--muted);
      border-top: 1px solid var(--border); padding-top: 10px }
    .ctx-dist { display: flex; flex-direction: column; gap: 4px }
    .ctx-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px }
    .ctx-row span { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
    .ctx-note { margin: 12px 0 0; font-size: 11px; color: var(--muted) }

    /* ★W-UIX14-S1 — 옛 `.dash-host .fx-card{color-mix(text 5%)}` 오버라이드는 걷었다.
       회색의 진짜 출처는 아래 `.dash-host .dash-card` 라 **거기를 고친다**(한 자리). */
    .fx-card-host { background: color-mix(in srgb, var(--accent) 9%, transparent); }
    /*  ★W-UIX14-S1 — 안쪽 카드도 **표면**이다: 파스텔 host(위) 위에 흰 타일이 서면 두 겹의
        경계가 오히려 또렷하다(채움색으로 구분하지 않는다). 호버 이동·첫 자식 윗선은 걷었다
        (레시피가 테두리 0 이라 *"줄이 두 겹"* 이 생길 자리가 없다). */
    .fx-card-host .fx-card { background: var(--surface, #FFFFFF);
      box-shadow: 0 0 0 1px rgba(23,27,34,.07), 0 1px 2px rgba(0,0,0,.08), 0 4px 12px rgba(0,0,0,.08); }
    /* 경비/지출 폼(76-4·우측 캔버스) + 인앱 확인 게이트. */
    .exp-form { display: flex; flex-direction: column; gap: 4px; padding: 4px 2px; font-size: 13px; }
    .exp-form .exp-title { font-weight: 700; font-size: 15px; margin-bottom: 8px; }
    .exp-form .exp-lbl { font-size: 12px; opacity: .75; margin-top: 6px; }
    .exp-form .exp-hint { font-size: 11px; opacity: .65; margin-top: 6px; line-height: 1.5;
      padding: 6px 8px; border-radius: 8px; background: rgba(127,127,127,.08); }
    .exp-form .exp-in { padding: 6px 8px; border-radius: 8px; border: 1px solid var(--border, #2a2f3a);
      background: transparent; color: inherit; }
    .exp-form .exp-in.num { text-align: right; }
    .exp-form .exp-actions { display: flex; gap: 6px; margin-top: 12px; }
    .exp-form .exp-actions button { padding: 6px 12px; border-radius: 8px; cursor: pointer;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .exp-form .exp-save { background: var(--accent, #3b82f6); color: #fff; border-color: transparent; }
    .exp-form .exp-del { border-color: #b91c1c; color: #ef4444; }
    .exp-form .exp-msg { margin-top: 8px; font-size: 12px; opacity: .9; }
    /* ── 메일(Phase 83.1·읽기 전용) — 좌 목록 / 우 상세. 앱 테마 토큰만 사용(하드코딩 색 금지:
       v210 테마 회귀 교훈). 모바일은 상세 전환(≤760)에서 목록을 감춘다. ── */
    /* ★85.10(사장님 지적·릴리 계측) — **메일 화면만 뷰포트에 가둔다.**
       증상: 목록을 스크롤하면 **상단 헤더와 본문이 같이 움직였다**. 원인은 목록이 아니라
       **위 컬럼에 상한이 없다**는 것이었다 — `.chat-area` 는 `min-height:100vh`(바닥만 있고 천장이
       없다)라 콘텐츠가 길어지면 컬럼이 통째로 자라고, 그러면 목록에 `overflow-y:auto` 가 있어도
       **넘칠 것이 없어** 스크롤이 문서에 생긴다. 계측: 목록 1605px == scrollHeight(내부 스크롤 0),
       문서 1808px > 창 937px.
       ★그리고 이것이 **85.1 얇은 스크롤바가 안 보이던 이유**이기도 하다 — 스크롤이 안 생기니
       그릴 대상이 없었다. **두 증상이 한 원인이다.**
       ★대화 화면은 문서가 자라는 것이 정상이므로 **메일일 때만** 건다(body[data-tv="mail"]).
       ★`min-height:0` 이 세 곳에 필요하다: flex 자식은 이것이 없으면 **콘텐츠보다 작아지지 않아**
       천장을 만들어도 넘치지 않는다 — 83.1-b 에서 `min-width:0` 으로 겪은 것과 **같은 부류의 축 문제**
       (그때는 가로, 이번은 세로). */
    /* ★★W-UIX1 ②(2026-09-06 · 사장님 · 릴리 결재) — **하단 시트를 쓰는 화면은 컬럼에 천장을 준다.**
       85.10(mail)·W-NH2(noti)에만 있던 이 캡을 **공통 클래스 `body.ais-capped`** 로 넓혀 시트 쓰는 전
       메뉴(간편장부 계열·자산·이커머스·플래너·자동화·문서)에 적용한다 — 페이지 스크롤을 없애
       §0 버그(A: .ai-sheet z5 ↔ .chat-input z20 이 bottom:0 에서 겹쳐 입력창이 대화창을 덮음 ·
       B: min-height:100vh 천장 없어 .tv-body 내부 스크롤 무력화)를 함께 해소한다.
       ★`ais-capped` 는 `mountMessages()` 단일 관문이 건다(collapsed/sheet=on · chat/hidden=off).
       ★mail 은 seat=sheet 라 mountMessages 를 지나 ais-capped 를 받으므로 여기로 통합(중복 제거).
          noti 는 섹션이 아니라(_SECTIONS 밖) ais-capped 를 안 받으므로 아래 data-tv 규칙을 **유지**한다. */
    body.ais-capped .chat-area { height: 100dvh; min-height: 0; overflow: hidden; }
    body.ais-capped .chat-main { min-height: 0; }
    body.ais-capped .tv-body { overflow: hidden; }
    .fx-form .sd-tplbar .sd-tpllab { flex: 0 0 auto; font-size: var(--fx-fs-sm); color: var(--muted); }
    .fx-form .sd-tplbar .sd-tplname { flex: 0 1 260px; min-width: 0; }
    .fx-form .sd-tplbar .sd-tplgo { flex: 0 0 auto; }
    /* ★그 헤더를 접고 나니 **6px** 이 남았다(실측: 입력 31 · 데스크 25). 출처는 [입력] 탭 첫
       콘텐츠(`.pq-sheet`)가 가진 `margin-top: 6px` 이고 `.sd-form` 에는 그것이 없었다.
       ★사장님 지시가 *"입력탭의 상단여백만큼"* 이므로 **데스크를 입력에 맞춘다**(같은 값). */
    .sd-form { margin-top: 6px; }
    .sd-form .sd-scroll { overflow: auto; max-height: 70vh; }
    .sd-form table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
    .sd-form th, .sd-form td { padding: 4px 6px; }
    .sd-form td.num, .sd-form th.num { text-align: right; }
    /* ★★③⑶ 서류 동작 줄 — 우측 표면(폼) 안. 저장줄과 **한 칸 떼어** 둔다: 저장은 되돌릴 수
       있고 이쪽은 아니다(발행·삭제). 무게가 다르면 자리도 붙이지 않는다. */
    .fx-form .pq-docacts { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px;
      padding-top: 8px; border-top: 1px dashed var(--fx-field-bd); }
    .fx-form .pq-docacts:empty { display: none; }
    .lst-cap { font-size: 11.5px; color: var(--muted); }
    .lst-box { border: 1px dashed var(--border, #2a2f3a); border-radius: 8px; padding: 8px;
      margin-bottom: 6px; }
    .lst-box.hidden { display: none; }
    .lst-box textarea { width: 100%; box-sizing: border-box; font-size: 13px; }
    .lst-foot { display: flex; align-items: center; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
    .lst-foot .lst-img { flex: 1 1 180px; min-width: 0; }
    .lst-msg { font-size: 11.5px; color: var(--muted); }
    /* ★③2026-08-05(사장님) — 수량은 두세 자리 숫자다. 칸을 좁게 예약해 다른 칸에 폭을 돌려준다. */
    .fx-form .pq-grid th.pq-w-qty { width: 52px; }
    /* ★★2026-08-07 공제합계 축(사장님 지시 · 릴리 결재 Q1) — **읽기 전용 칸**이다.
       입력 상자를 그리지 않는다(손 입력 칸 증가 0) — 그래서 셀 자체가 값을 말하고, 다른
       입력 칸과 **다른 낯**이어야 눌러도 안 고쳐진다는 것이 눈에 보인다(muted + 우측 정렬).
       ★색·간격은 전부 fx 토큰에서 파생한다(클래식 값 박기 금지 — 08-05 상시 지시). */
    .fx-form .pq-grid th.pq-w-ded { width: 92px; }
    .fx-form .pq-grid td.pq-dedcell { text-align: right; color: var(--muted);
      white-space: nowrap; padding: 0 6px; }
    /* ★Q8 — 옛 줄(단가에 공제가 이미 흡수된 줄) 표식은 **표시 층에서만**. 데이터 칸
       (`inspect_note`)은 건드리지 않는다(표식 하나가 두 뜻이 되면 조용히 갈린다). */
    .fx-form .pq-grid td.pq-dedcell .pq-dedold { display: inline-block; margin-left: 4px;
      padding: 0 4px; border-radius: 999px; font-size: 10.5px; line-height: 1.6;
      /* ★★W-UIX18 ⑦(2026-09-13 · kai 개발자 역보고 · 워키·kai 공통) — `--fg` 는 **어디에도
         선언이 없는 이름**이었다(전수 실측: style.css·app.html·js 의 setProperty 어디에도 없다).
         폴백도 없어 `color` 가 **무효**로 떨어졌고, 그 칩의 글자색은 상속에 맡겨져 있었다.
         ⇒ 섹션 테마가 내려 주는 **잉크 토큰 `--text`** 로(theme.js 가 밝기에서 파생한다). */
      background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--text); }
    .fx-form .fx-grid tr.ws-hit td { background: color-mix(in srgb, var(--accent) 18%, transparent); }
    /* ★③④2026-08-05(사장님) — 금액 칸은 좁게 예약하고, 그만큼 글 칸(불량 상태·불량 유형)이
       넓어진다(표는 width:100% 라 남는 폭이 글 칸으로 간다). */
    .fx-form .pq-grid th.pqd-w-amt { width: 96px; }
    .fx-form .pq-grid th.pqd-w-def { width: 34%; }
    .fx-form .pq-grid th.pqd-w-cat { width: 90px; }
    /* ★2026-08-06 ③(사장님) — 맨 우측 삭제 칸은 **아이콘 하나 폭**이다(머리글 글자 0).
       종전엔 폭 예약이 없어 남는 폭을 나눠 먹어 글 칸을 좁혔다. */
    .fx-form .pq-grid th.pqd-w-del { width: 26px; }
    .fx-form .pq-grid th.pqd-w-del, .fx-form .pq-grid td.pqd-c-del { padding-left: 0;
      padding-right: 0; text-align: center; }
    .fx-form .pq-grid .pqd-vdel { padding: 0 2px; }
    /* ★2026-08-06 — 스위치는 **줄지 않는다**(찌그러짐의 다른 절반): 글자가 길거나 자리가
       좁아도 폭·높이를 내주지 않는다. */
    .fx-switch { position: relative; display: inline-block; width: 40px; height: 22px;
      flex: 0 0 auto; }
    .fx-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0;
      cursor: pointer; z-index: 2; }
    .fx-switch i { position: absolute; inset: 0; border-radius: 999px; transition: background .15s;
      background: color-mix(in srgb, var(--border) 70%, transparent); }
    .fx-switch i::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px;
      height: 16px; border-radius: 50%; background: #fff; transition: transform .15s;
      box-shadow: 0 1px 2px rgba(0,0,0,.25); }
    .fx-switch input:checked + i { background: var(--accent); }
    .fx-switch input:checked + i::after { transform: translateX(18px); }
    /* ★★★2026-08-06 즉시 수리(사장님 스크린샷 2회차 — 켠 스위치가 "선입고" 글자를 덮었다).
       ★원인은 치수가 아니라 **순서**였다: 작은 스위치 규칙을 위 일반 규칙보다 **먼저** 뒀는데
       특정도가 **같아서 뒤엣것이 이긴다**(`.fx-switch i::after` 가 `.fx-switch-sm i::after` 를
       덮었다). 그래서 28px 트랙에 **16px 노브가 18px 이동** = 2+18+16 = 36 > 28 →
       노브가 트랙 밖으로 4px 넘어가 글자 위에 얹혔다.
       ★★교훈: **같은 특정도에서는 나중에 적은 것이 이긴다** — 덮어쓰려면 **뒤에** 적어야 한다.
       (선언만 읽는 검사는 이 부류를 못 잡는다 → 검사도 순서를 재게 고쳤다.)
       ★그래서 작은 스위치는 **일반 규칙 다음**에 온다. 값은 그대로: 2+12+12 = 26 ≤ 28. */
    .fx-switch-sm { width: 28px; height: 16px; flex: 0 0 auto; }
    .fx-switch-sm i::after { top: 2px; left: 2px; width: 12px; height: 12px; }
    .fx-switch-sm input:checked + i::after { transform: translateX(12px); }
    /* ★구간 1-① — 파일 입구·대량 행 도구. 대조표가 8,000줄이어도 화면이 버텨야 한다. */
    .lst-file { display: flex; align-items: center; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
    .lst-filelab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; }
    .lst-fmsg { font-size: 11.5px; color: var(--muted); }

/* ══════════════════════════════════════════════════════════════════════
   ★★★W-UIX15-INL C(그 밖 전부 · 축 마감) — `app.html` 인라인에서 **그대로** 옮겨 왔다(값 무변).
   ★A(견적+B2B) · B(대화·시트·토스트+폼·시트) 다음이 이 묶음이고, 이것으로 인라인 규칙은
     **604 → 2** 가 된다. 남은 둘은 옮기면 **뜻이 뒤집히는** 것들이다:
       ⓐ `[data-demo-static]` = 스크립트가 0줄일 때 굽힌 체험 샘플을 받치는 부트 폴백(W-UIX11 ③)
       ⓑ `<noscript>` 안 `#app-view{padding-top}` = 스크립트가 도는 브라우저에는 **아예 없다**
         (여기로 옮기면 모든 브라우저에 걸려 빈 여백이 생긴다)
   ★자리는 여전히 **파일 끝**이다(인라인이 이 파일 뒤에 로드됐으므로) · 세 묶음의 상대 순서 보존.
   ══════════════════════════════════════════════════════════════════════ */

    /* ★G3 — [워키에 대하여] 캔버스 iframe(전면·자체 스크롤·랜딩 원본 격리). */
    .tv-sub[data-tv="about"] { height: 100%; }
    #about-frame { width: 100%; height: 100%; border: 0; display: block; }
    .tv-sub[data-tv="sheets"] { height: 100%; }
    #sheets-frame { width: 100%; height: 100%; border: 0; display: block; }
    #sheets-msg { max-width: 460px; margin: 48px auto; padding: 0 20px; text-align: center;
      font-size: 14px; line-height: 1.7; color: var(--muted, #667085); }

    .kn-drop{border:2px dashed var(--border,#334155);border-radius:12px;padding:26px 18px;margin:10px 0;
      text-align:center;color:var(--muted,#94a3b8);font-size:13.5px;cursor:pointer;transition:border-color .2s,background .2s}
    .kn-drop small{opacity:.8}
    .kn-drop.drag{border-color:#22d3ee;background:rgba(34,211,238,.08);color:var(--text,#e2e8f0)}
    .kn-list{display:flex;flex-direction:column;gap:8px}
    .kn-item .fld{font-size:11px;color:var(--muted);flex:none}
    /* ★W-UIX14-S1 — 회색 채움을 걷고 **표면 토큰**으로.
       ★★검사가 잡았다: style.css 의 `.kn-item` 을 고쳤는데 화면은 안 바뀌었다 —
         **이 인라인 규칙이 뒤에 있어 이긴다**(같은 이름을 두 곳에 적으면 조용히 한쪽만 고쳐진다). */
    .kn-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;
      background:var(--surface,#FFFFFF);border:0;
      box-shadow:0 0 0 1px rgba(23,27,34,.07);font-size:13px}
    .kn-item .nm{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .kn-item .vis{font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:5px;
      background:rgba(56,189,248,.15);color:#38bdf8;flex:none}
    .kn-item .del{background:none;border:none;color:#fb7185;cursor:pointer;font-size:15px;flex:none}
    .kn-item.busy{opacity:.6}
    .kn-toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:999;
      background:rgba(20,30,52,.92);border:1px solid rgba(150,180,230,.2);color:#eaf0fb;
      padding:11px 18px;border-radius:10px;font-size:13.5px;box-shadow:0 10px 30px rgba(0,0,0,.4);
      opacity:0;transition:opacity .3s,transform .3s}
    .kn-toast.show{opacity:1;transform:translateX(-50%) translateY(-4px)}
    /* 업로드 진행 모달 — 큰 파일 색인 중 표시(사용자 요청). 설정 모달(1200)·토스트(2000)보다 위 */
    .kn-uploading{position:fixed;inset:0;z-index:3000;display:flex;align-items:center;justify-content:center;
      background:rgba(8,14,28,.55);backdrop-filter:blur(2px)}
    .kn-uploading.hidden{display:none}
    .kn-up-box{min-width:260px;max-width:80vw;text-align:center;padding:26px 30px;border-radius:14px;
      background:var(--panel,#0f1830);border:1px solid rgba(150,180,230,.22);box-shadow:0 18px 50px rgba(0,0,0,.5)}
    .kn-up-spin{width:34px;height:34px;margin:0 auto 14px;border-radius:50%;
      border:3px solid rgba(150,180,230,.25);border-top-color:#38bdf8;animation:kn-spin .8s linear infinite}
    @keyframes kn-spin{to{transform:rotate(360deg)}}
    .kn-up-title{font-size:15px;font-weight:700;color:var(--text,#e2e8f0)}
    .kn-up-text{margin-top:6px;font-size:13px;color:#38bdf8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .kn-up-hint{margin-top:8px;font-size:12px;color:var(--muted,#94a3b8)}
    .crm-msg{margin-top:4px;resize:vertical}
    .sku-cands{display:flex;flex-direction:column;gap:6px;margin:6px 0}
    .sku-cand{text-align:left}
    #company-form .company-upload{flex:1;display:flex;align-items:center;gap:10px;min-width:0}
    #company-form .company-file{font-size:12px;color:var(--text);max-width:62%}
    #company-form .company-img{height:40px;width:auto;border:1px solid var(--border);border-radius:6px;background:#fff;padding:2px}
    /* 폴더 헤더(그룹) — .tt-row 톤 + 폴더 아이콘(내 업무 차용·접힘 folder / 펼침 folder-open). 클릭=네이티브 접기. */
    /* ★C2 — 프리필 배지: 채워진 값이 **AI 제안**임을 폼에서 말한다(값은 고칠 수 있다). */
    .pf-badge { margin-left: 8px; font-size: 10.5px; font-weight: 700; padding: 2px 8px;
      border-radius: 999px; background: rgba(108,92,231,.14); color: #6C5CE7; white-space: nowrap }
    .cc-btn.cc-apply { background: var(--accent); color: #fff; border-color: transparent }
    /* ★2026-08-03(사장님 지시) — `full` 화면(우측 캔버스가 없는 현황형)의 입력/대화창을
       **플래너와 같은 고정 폭**으로. 사장님은 네 화면을 지목하셨지만(간편장부 대시보드·세무 요약 ·
       이커머스 대시보드·매출현황) **공통점은 이름이 아니라 축**이다 — 전부 `data-tv-layout="full"`.
       이름으로 넷만 고치면 `full` 이 늘 때 또 어긋난다.
       ★숫자를 새로 박지 않는다 — 폭 통일 때 세운 **단일 원천**(`--chat-bar-max`·
       `--chat-input-inset`)을 `tv-wide` 와 **그대로 공유**한다.
       ★모바일 제외: 입력바가 뷰포트 고정 전폭이라 이 규칙 밖이다(`tv-wide` 와 같은 판단). */
    @media (min-width: 761px) {
      body[data-tv-layout="full"] .chat-main > .chat-input {
        max-width: var(--chat-bar-max); width: 100%; margin-left: auto; margin-right: auto }
      body[data-tv-layout="full"] .chat-main > .ai-sheet {
        max-width: calc(var(--chat-bar-max) - var(--chat-input-inset) * 2);
        width: 100%; margin-left: auto; margin-right: auto }
    }
    /* ★★W-UIX15-INL B — **펼친 시트가 행을 차지하지 않고 덮는다**는 그 규칙
       (`body.ais-open .ai-sheet`)은 `style.css` 로 옮겼다(사연·실측은 그 자리에 그대로).
       여기 남은 것은 그 절대 배치의 **기준점** 한 줄이다. */
    @media (min-width: 761px) {
      /* 절대 배치의 기준점 — 이 화면은 페이지 스크롤이 없어(뷰포트 높이 고정) 바닥이 곧 보이는 바닥이다. */
      .chat-main { position: relative }
    }

    /* ══ ★Phase 92-B2 — 대시보드 카드 위계(아이콘 + 색 톤) ═══════════════════════
       ★장식이 아니라 **위계**다: 주 지표(.dash-card-value)는 그대로 크고, 아이콘은 성격을
       가르는 표식이며, 증감은 **방향에만** 색을 쓴다. 카드 골격(테두리·패딩)은 손대지 않았다.
       ★색을 뜻의 유일한 전달자로 쓰지 않는다 — 증감엔 ▲▼ 기호가 함께 붙는다. */
    .dash-card-top { display: flex; align-items: center; gap: 8px }
    .dash-ic { width: 26px; height: 26px; border-radius: 8px; flex: 0 0 26px;
      display: inline-flex; align-items: center; justify-content: center; background: var(--panel-2) }
    .dash-ic [data-lucide], .dash-ic svg { width: 15px; height: 15px }
    .dash-ic.ic-sales   { background: rgba(108,92,231,.14); color: #6C5CE7 }
    .dash-ic.ic-purchase{ background: rgba(24,182,201,.14); color: #18B6C9 }
    .dash-ic.ic-warn    { background: rgba(245,158,11,.14); color: #F59E0B }
    .dash-ic.ic-tax     { background: rgba(59,130,246,.14); color: #3B82F6 }
    .dash-ic.ic-income  { background: rgba(52,211,153,.14); color: #34D399 }
    .dash-ic.ic-stock   { background: rgba(148,163,184,.18); color: #94A3B8 }
    .dash-delta { margin-top: 6px; font-size: 11px; color: var(--muted) }
    .dash-delta span { opacity: .75 }
    .dash-delta.d-up { color: #34D399 }
    .dash-delta.d-down { color: #f87171 }

    /* ══ ★Phase 92-B1 — 화면 배분(중앙 100% + 우측 상시) ══════════════════════════
       ★표식은 `body[data-tv-layout]` 하나뿐이고 그 값을 정하는 곳은 `toolview.js` 의 `_LAYOUT`
       단일 원천이다. CSS 는 **어느 화면인지 모른 채** 배분만 집행한다(화면이 늘어도 여기는 그대로). */
    body[data-tv-layout] .chat-main { max-width: none; }
    /* 목록 화면에서 우측은 **상시**다 — 닫는 버튼을 두면 "닫았는데 다시 열린다"가 된다.
       ★챗 산출물 캔버스의 닫기는 그대로 둔다(성격이 다르다 · 그건 사용자가 부른 산출물이다). */
    body[data-tv-layout="split"] #canvas-close { display: none; }
    /* ★설정 모달의 체크박스는 전부 공용 스위치(.switch)다(86.6) — 크기는 그쪽이 준다. */
    /* LNB 대분류 아코디언 — 제목 클릭 토글(화살표 아이콘 없음), 좌측정렬 */
    .sb-title{cursor:pointer}
    .sb-section.sb-collapsed > :not(.sb-title){display:none}
    .sb-section.sb-collapsed.sb-grow{flex:0 0 auto}
    #set-close{position:absolute;top:14px;right:16px;width:32px;height:32px;line-height:1;
      border:0;border-radius:9px;background:transparent;color:var(--muted);font-size:18px;cursor:pointer;z-index:2}
    #set-close:hover{background:var(--panel-2);color:var(--text)}

    .tv-sub[data-tv="ledger"], .tv-sub[data-tv="clients"], .tv-sub[data-tv="items"],
    .tv-sub[data-tv="funds"], .tv-sub[data-tv="assets"], .tv-sub[data-tv="market"],
    .tv-sub[data-tv="bizdash"], .tv-sub[data-tv="expenses"],
    .tv-sub[data-tv="invoices"], .tv-sub[data-tv="tax"],
    .tv-sub[data-tv="ecom"],   /* ★Phase 92 — 빠뜨리면 셸 높이가 0 이라 그리드가 안 보인다 */
    .tv-sub[data-tv="skills"], .tv-sub[data-tv="onboarding"],
    /* ★W-ADM1 — 관리자 콘솔도 셸 높이가 필요하다(빠뜨리면 카드 그리드가 0 높이다 · 92 선례) */
    .tv-sub[data-tv="admin"] { height: 100%; }
    @keyframes onbSlideIn { from { transform: translateX(22px); opacity: .35; } to { transform: translateX(0); opacity: 1; } }
    /*   ★★W-UIX14-S4 B — SOP 스토어 전용 규칙을 `style.css` 의 `.skc-*` 블록 옆으로
         옮겼다(인라인 `<style>` 은 style.css 를 **늦게 로드돼 이긴다** — 같은 이름이
         두 곳에 있으면 어느 쪽이 이길지 파일 순서가 정한다). ★함께 있던 공용 정의
         (`.wk-link`/`.au-link`/`.au-btns`)는 **두고 왔다**: SOP 만의 것이 아니다. */
    /* ★★W-UIX6 ②(2026-09-08 · 사장님) — **공용 카드 표면 `.fx-card`**.
       배경 위에 **투명하게 떠 있는** 카드(반투명 배경·옅은 테두리·부드러운 그림자) +
       hover 시 살짝 떠오른다. 1단계는 **SOP 스토어 스킬 카드에만** 붙이고, 2단계에서
       자동화·대시보드·할일 카드가 **같은 클래스**를 쓴다(그래서 지금 공용으로 만든다).
       ★새 색을 만들지 않는다 — `--glass-bg`·`--hairline`·`--radius` 재사용이라
       `theme.js` 가 밝은 섹션에서 덮어쓰는 라이트 값이 **그대로 따라온다**(다크/라이트 자동). */
    /*  ★★W-UIX8 ①③(2026-09-08 · 사장님 스샷) — **배경을 여기서 섞는다.**
        ★뿌리(실측): `:root` 에서 `--fx-nest-bg: color-mix(… var(--accent) … var(--panel))` 로
          **미리 섞어** 두면 CSS 가 그 자리에서 **:root 다크 값으로 치환해 굳힌다** —
          실제로 라이트 페이지의 모든 자리에서 `color-mix(in srgb, #38bdf8 8%, #1e293b)`
          (다크 리터럴)이 읽혔다. `--panel`·`--text` 는 라이트로 잘 덮여 있었는데도 그랬다.
          ⇒ **커스텀 속성에 var() 를 담아 두지 말고, 쓰는 규칙에서 직접 섞는다**(그때 그 요소의
          토큰으로 해석된다 = 라이트/다크 자동).
        ★그리고 `--glass-bg` 는 **라이트에서 불투명**이다(theme.js 가 밝은 배경엔 그 색 자체를
          준다) — 그래서 장부 KPI 카드가 '불투명 패널색'으로 보였다(③의 뿌리도 같은 자리).
          ⇒ 바탕을 **글자색에서 섞어** 만든다: 라이트면 옅은 회색, 다크면 옅은 흰빛 —
          **양쪽 다 진짜 반투명**이라 자리 배경 위에 뜬다. */
    /* ★★★W-UIX14-S1(2026-09-11) — **`.fx-card` 의 정본은 여기가 아니다.**
       공용 카드 레시피는 `css/style.css` 의 `.wk-card, .au-card, .fx-card` 한 블록이다
       (자동화 화면이 입던 옷을 승격 · 표면 `--surface` · 테두리 0 · 호버 들썩임 0).
       ★여기 있던 반투명 회색 채움 + 1px 테두리 + `translateY(-3px)` 호버가 사장님이 말한
         "회색 카드의 고리타분함"이었다 — 그래서 **규칙을 옮긴 것이 아니라 걷었다**. */
    /* ★★W-UIX7 ②(2026-09-08 · 사장님) — **카드 속 카드**의 규칙(여기 한 곳).
       바깥(품는) 카드 = **파스텔 배경**(안쪽이 떠 보이게 톤을 낮춘다) ·
       안쪽 카드 = 그대로 `.fx-card`(반투명·그림자). 두 겹이 같은 표면이면 경계가 사라진다.
       ★새 색은 **토큰 둘**뿐이고, 둘 다 기존 토큰에서 **색을 섞어** 만든다 —
         그래서 `theme.js` 가 밝은 섹션에서 덮어쓰면 **파스텔도 함께 밝아진다**(라이트/다크 자동). */
    /*  ★★W-UIX8 ③ 실측 — `.dash-host .dash-card { background: var(--panel-2) }`(특이도 0,2,0)가
        `.fx-card`(0,1,0)를 **이기고 있었다** — 장부·세무 카드만 불투명 패널색이던 뿌리다.
        ★★수를 **맞추기만 하면 안 됐다**: 같은 (0,2,0)이면 **뒤에 적힌 쪽**이 이기는데
          그 규칙이 더 뒤였다(실측: 장부만 계속 불투명) ⇒ `.dash-card.fx-card`(0,3,0)로
          한 겹 더 올린다. 값은 위와 **같은 식**이라 두 벌이 되지 않는다. */
    /* ★★W-UIX10 ②-b·③(2026-09-08 · 사장님) — **카드 안 손잡이는 글자 링크**로 보인다.
       ★요소는 `<button>` 그대로 두고 **표면만** 링크로 만든다(키보드·읽어 주기·배선 무접촉).
       ★밑줄은 hover 에서만 — 평소엔 강조색 글자 하나라 카드가 조용하다. */
    /*  ★W-UIX14-S1 — 공용 글자 링크(`.wk-link`) · 치환은 S3~(여기서는 정의만). */
    .wk-link, .au-link, .skc-textlink {
      background: transparent; border: 0; padding: 0; margin: 0;
      color: var(--accent); font-size: 12.5px; font-weight: 400; line-height: 1.4;
      cursor: pointer; text-decoration: none;
    }
    .wk-link:hover, .au-link:hover, .skc-textlink:hover { text-decoration: underline; }
    .wk-link:focus-visible, .au-link:focus-visible, .skc-textlink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
    .au-del.au-link { color: var(--muted); }        /* 삭제는 앞에 나서지 않는다 */
    .au-del.au-link:hover { color: var(--danger, #e5484d); }
    /*  ★글자 링크가 여럿이면 사이를 벌린다(버튼 여백이 사라졌으므로 행이 대신 준다). */
    .au-btns { display: flex; gap: 14px; align-items: center; }
    /* ★W-UIX14-S1 — 옛 `.skc-spec.fx-card:hover { transform: none }` 은 **죽은 규칙**이 됐다:
       W-UIX10 ③ 이 이 카드 한 자리에만 준 규율(*"읽는 판은 흔들리지 않는다"*)이 이제
       **공용 레시피의 규율**이다(전 화면 호버 이동 0 · 사장님 Q1). */
    /* ★★W-UIX9 ④(2026-09-08 · 사장님) — **접힘 레일 아이콘에 말풍선 툴팁**.
       ★★말풍선은 **아이콘 안에 못 그린다**: 접힘 레일은 `.sb-title{overflow:hidden}` ·
         `.sidebar{overflow:hidden}` · `.sb-scroll{overflow-y:auto}` **세 겹으로 잘린다**
         (실브라우저가 잡았다 — `::after` 판은 아무것도 안 보였다). ⇒ 말풍선은 **body 에
         떠 있는 칸 하나**이고 `sidebar.js` 가 아이콘 자리에 맞춰 띄운다(`position: fixed`).
       ★색은 그 아이콘이 쥔 토큰을 그대로 물려받는다(`theme.js` 가 `#sidebar` 에 인라인으로
         걸어 body 까진 안 내려온다 — 라이트/다크가 함께 맞는다).
       ★문면은 화면에 이미 있는 이름(`data-tip`) · 클릭 동작 무접촉(`pointer-events: none`). */
    .sb-tip {
      position: fixed; z-index: 4000; pointer-events: none; white-space: nowrap;
      padding: 5px 9px; border-radius: 8px; font-size: 12.5px; line-height: 1.2;
      color: var(--text); background: var(--panel);
      border: 1px solid var(--hairline);
      box-shadow: 0 2px 6px rgba(0,0,0,.16), 0 8px 20px rgba(0,0,0,.16);
      opacity: 0; transform: translateY(-50%); transition: opacity .12s ease;
    }
    .sb-tip.on { opacity: 1; }
    @media (prefers-reduced-motion: reduce) { .sb-tip { transition: none; } }
    /* 경영 현황 대시보드(76-3) — KPI 카드 그리드 + 스파크라인. */
    .dash-host { height: 100%; overflow: auto; padding: 16px; }
    .dash-head { font-size: 15px; font-weight: 700; margin-bottom: 12px; }
    .dash-head .dash-hint { font-size: 12px; font-weight: 400; opacity: .7; margin-left: 6px; }
    /* ★.dash-host 로 스코프 한정(2026-07-21·v157): 이 KPI 그리드/카드 규칙은 경영현황(#bizdash-host)·
       세무(#tax-host) 전용인데 클래스명(.dash-grid/.dash-card)이 B2C 홈(#dashboard.dashboard·dashboard.js)과
       충돌 → 인라인 <style>가 style.css(홈 1fr 1fr·padding 16px 18px)보다 늦게 로드돼 홈을 덮어썼음
       (auto-fill minmax(180px)=카드 2개가 좌측 180px로 몰림·padding 축소). 홈은 .dash-host 밖이라 이제
       style.css 홈 규칙(1fr 1fr) 복원. KPI 대시보드는 .dash-host 안이라 외형 무변경. */
    .dash-host .dash-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }
    /*   ★W-UIX14-S1 — 표면·테두리는 공용 레시피가 준다(회색 채움·1px 테두리 삭제). */
    .dash-host .dash-card { padding: 12px 14px; border-radius: 12px; border: 0;
      background: var(--surface, #FFFFFF); }
    .dash-card-label { font-size: 12px; opacity: .8; }
    .dash-card-value { font-size: 20px; font-weight: 700; margin-top: 4px; }
    .dash-card-sub { font-size: 11px; opacity: .65; margin-top: 2px; }
    /* ★UX10 ① — 경영정보 차트 목업 카드(자체 SVG·정적 예시 데이터). (구 .dash-chart(Chart.js)·
       .dash-feed-*(최근 활동) 규칙은 섹션 삭제로 제거.) 텍스트=currentColor 상속=라이트/다크 자동. */
    .dash-chart-title { font-size: 13px; font-weight: 600; opacity: .85; margin-bottom: 8px; }
    .dash-mock-grid { margin-top: 18px; display: grid; gap: 12px;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
    .dash-chart-card { border: 1px solid var(--border, #2a2f3a); border-radius: 12px; padding: 12px 14px;
      background: var(--panel-2, rgba(255,255,255,0.03)); }
    .dash-chart-card svg { width: 100%; height: auto; display: block; }
    .dash-sample-badge { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
      font-size: 10.5px; font-weight: 400; color: var(--muted); border: 1px dashed var(--border, #2a2f3a); }
    .dash-legend { display: flex; flex-wrap: wrap; gap: 12px; align-items: center;
      margin-top: 6px; font-size: 11.5px; color: var(--muted); }
    .dash-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px;
      margin-right: 4px; vertical-align: -1px; }
    .dash-legend-unit { margin-left: auto; opacity: .75; }
    /* ★UX11 ① — 실사용자 빈 테넌트 정직한 빈 상태(목업 대체 금지) */
    .dash-chart-empty { padding: 28px 8px; text-align: center; font-size: 12.5px; color: var(--muted); }
    .dash-card.dash-neg .dash-card-value { color: #f87171; }
    .dash-card.dash-pos .dash-card-value { color: #34d399; }   /* 스크롤은 리스트 내부가 맡는다 */
    .tv-sub[data-tv="mail"] { height: 100%; min-height: 0; }
    /* ★W-AUTOREG-B2 ③(2026-09-07 · 사장님 실기) — 자동화 알림 리스트 스크롤. `.autofeed` 는 이미
       overflow-y/min-height:0 을 갖지만, 부모 `.tv-sub[data-tv="automation"]` 에 **천장이 없어**
       자식이 무한정 늘어 스크롤이 안 생겼다(메일이 이미 하는 그 규칙이 자동화엔 빠져 있었다). */
    .tv-sub[data-tv="automation"] { display: flex; flex-direction: column; height: 100%; min-height: 0; }
    .tv-sub[data-tv="mail"] { position: relative; }   /* 스낵바 기준 컨테이너 */
    /* ★84.5-c 사용자 폴더 — 기본 접힘. 폴더가 10개여도 접힌 상태의 높이는 summary 1줄이다. */
    #mail-folders > summary { list-style: none; cursor: pointer; }
    #mail-folders > summary::-webkit-details-marker { display: none; }
    /* ★84.5-f 의 규칙(`#mail-folders[open] + #mail-folder-pinned{display:none}`)은 **삭제**했다 —
       84.5-g 에서 고정 표시 영역 자체를 없앴기 때문이다. 겹침을 감추는 규칙보다 **겹칠 수 있는
       영역을 두지 않는 것**이 근본이다(84.5-f 는 증상을, 84.5-g 는 원인을 없앤다). */
    /* ★86.5(사장님 지시) — 좌측 메일 섹션 글자 크기를 **[내 업무] 리스트 항목**에 맞춘다.
       실측 격차: 메일 상위 항목 `.sb-navitem` **15px** · 하위 폴더 **13px** · 내 업무 항목 **13.5px**
       = 한 사이드바 안에 **세 가지 크기**가 있었다. 셋을 하나(`--lnb-item-fs`)로 모은다.
       ★대상은 **메일 섹션 안으로만** 좁힌다 — `.sb-navitem` 은 홈·대화 등 사이드바 전체가 쓰는
       클래스라 전역으로 건드리면 지시하지 않은 메뉴까지 바뀐다(사장님 지시 대상은 메일 섹션이다).
       ★하위 폴더까지 포함(사장님 명시) — 내 업무는 깊이가 달라도 항목 글자 크기가 같으므로
       대응 단계끼리 맞추면 상위·하위가 같은 값이 된다. 들여쓰기(30px)는 지시 밖이라 유지. */
    #mail-section .sb-navitem { font-size: var(--lnb-item-fs); }
    #mail-section .sb-navitem .ic { width: var(--lnb-item-ic); height: var(--lnb-item-ic); }
    /* ★★F2 [분류] 절 — **[메일함] 절과 같은 모양**을 쓴다(새 부품 0 · 들여쓰기·크기 동일).
       ★같은 모양인데 **다른 축**이라는 사실은 생김새가 아니라 **낱말**이 말한다:
       위는 [메일함]/[옮기기](실계정이 바뀐다) · 아래는 [분류]/[분류하기](워키 안에서만).
       ★모양까지 다르게 만들면 "왜 다르지"가 새 질문이 된다 — 다른 것은 하는 일뿐이다. */
    #mail-categories > summary { list-style: none; cursor: pointer; }
    #mail-categories > summary::-webkit-details-marker { display: none; }
    .md-primary { background: var(--accent, #3b82f6) !important; color: #fff !important;
      border-color: transparent !important; }
    .funds-detail { padding: 4px 2px; font-size: 13px; }
    .funds-detail .fd-title { font-weight: 700; font-size: 15px; margin-bottom: 8px; }
    .funds-detail .fd-actions { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
    .funds-detail .fd-amt { width: 96px; padding: 4px 6px; border-radius: 6px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; text-align: right; }
    .funds-detail .fd-actions button { padding: 4px 8px; border-radius: 6px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .funds-detail .fd-msg { margin-top: 8px; font-size: 12px; opacity: 0.85; }
    /* ★산출물 시트 — 이렌컴 양식(화면). 좁은 화면에서는 표만 가로로 흐르게 둔다. */
    /* ★엑셀 데스크 ⓐ — 금액 열 자리 꼬리(우측 정렬 · money_col 손잡이의 화면 사상). */
    .pqs-foot-right { text-align: right; }
    /* ★★★2026-08-07 사장님 신고 ②(재신고 — B-6 이 못 닫은 그 자리) — **빈 헤더가 자리를
       차지하고 있었다.** 실측: [입력] 탭은 탭 줄 하단→첫 콘텐츠 **31px** 인데 [데스크]는
       **65px** 였고, 차이 34px 의 출처는 `#art-head`(높이 16 + margin-bottom 12)였다 —
       데스크는 그 헤더를 **하나도 쓰지 않는다**(보이는 자식 0 · 제목 span 은 빈 채).
       ★정본 §4-3 그대로: **상시 존재하는 것만 높이를 예약한다.** 판정은 **내용**이다
       (v384 — 표식이 아니라 내용을 본다): 보이는 자식이 하나도 없을 때만 접는다.
       ★반증 확인(실브라우저): 제목이 차 있으면 이 선택자는 **매치되지 않는다**(false). */
    #art-head:not(:has(> *:not(.hidden):not(:empty))) { display: none; }
    /* ★★인쇄 — 프로젝트 최초의 `@media print` 다. 종이에는 **그 서류만** 나가야 한다:
       사이드바·툴바·목록·편집 폼은 화면의 것이지 서류의 것이 아니다.
       ★★W-CV1 ④(2026-09-01) — 이 절은 이제 `body.print-pq` 아래에서만 산다.
         종전에는 `body *` 가 **전역**이라, 문서를 인쇄하면 화면에 `.pq-sheet` 가 없어
         **아무것도 visible 하지 않아 빈 페이지**가 나갔다(사장님 신고). 그리고 그 반대도
         참이었다 — style.css 의 문서 절이 [입력] 패인을 `display:none` 해서 **이 시트 인쇄도
         빈 페이지**였다. 두 절은 다른 속성(visibility/display)을 만져 **덮어쓰기가 아니라
         합쳐졌고**, 그래서 넷 중 초록이 하나도 없었다(Ctrl+P 포함 · 실측).
       ★거는 곳·푸는 곳은 `canvas.js printAs()` 하나다 — 여기 규칙을 다시 적지 않는다. */
    @media print {
      body.print-pq * { visibility: hidden; }
      body.print-pq .pq-sheet, body.print-pq .pq-sheet * { visibility: visible; }
      body.print-pq .pq-sheet { position: absolute; left: 0; top: 0; width: 100%; border: none; padding: 0; }
      body.print-pq .pq-sheet .pqs-noprint { display: none; }
      body.print-pq .pq-sheet .pqs-scroll { overflow: visible; }
      body.print-pq .pq-sheet thead { display: table-header-group; }   /* 장 넘어가면 머리 반복 */
      body.print-pq .pq-sheet tr { break-inside: avoid; }
    }
    /* ★②검수 작업표 시리얼 스캔 점프 — 입력 한 칸 + 찾은 줄 잠깐 밝히기. */
    .ws-scanbar { display: flex; gap: 8px; align-items: center; margin: 2px 0 6px; }
    .ws-scanbar .ws-scan { flex: 0 1 280px; min-width: 0; }
    .lr-tools { display: flex; align-items: center; gap: 6px; margin: 6px 0; flex-wrap: wrap; }
    .lr-tools .lr-q { flex: 1 1 160px; min-width: 0; }
    .lr-stat { font-size: 12px; color: var(--muted); margin-bottom: 4px; }
    .lr-pager { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
    .asp-list { font-size: 12px; }
    .asp-row { padding: 6px 0; border-bottom: 1px solid var(--border, #2a2f3a); }
    .asp-row:last-child { border-bottom: none; }
    .asp-photos img { height: 64px; border-radius: 6px; margin: 4px 4px 0 0; }
    .asp-row button { padding: 3px 10px; border-radius: 8px; cursor: pointer; font-size: 12px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; }
    .asp-msg { font-size: 12px; opacity: 0.9; margin-top: 8px; }
    .al-form { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
    .al-form input, .al-form select { padding: 5px 8px; border-radius: 8px;
      border: 1px solid var(--border, #2a2f3a); background: transparent; color: inherit; font-size: 12px; }
    .al-form .al-code { width: 140px; }
    .al-form .al-label { flex: 1 1 180px; min-width: 0; }
    .al-list { margin-top: 8px; font-size: 12px; }
    .al-row { display: flex; gap: 8px; padding: 3px 0; opacity: 0.95; }
    .al-row.al-shelf { padding-left: 16px; }
    .al-row .al-n { min-width: 120px; }
    .al-row .al-p { opacity: 0.7; }
    .al-msg { font-size: 12px; opacity: 0.9; margin-top: 8px; }
    th.sort-on .lucide { opacity: 1; color: var(--accent, #3b82f6); }
    @keyframes ledgerHi { 0% { background: var(--accent, #3b82f6); } 100% { background: transparent; } }

    .tv-sub[data-tv="quote"] { height: 100%; }
    @keyframes quoteHi { 0% { background: var(--accent, #3b82f6); } 100% { background: transparent; } }


/* ══ ★★W-EDU-E1-a(2026-09-14 · 릴리 결재) — 🎙 회의 녹음(수집 단) ══
   ★표는 문서 목록(`.mydocs`)을 **그대로 빌린다** — 같은 결의 목록이 화면마다 다르게
     보이면 사람은 두 화면을 배워야 한다(디자인 일관성 규율).
   ★색은 전부 토큰이다(고정색 0 · 테마가 끝까지 따라온다 · v670 이 값을 치른 자리). */
.rec-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 4px 0 10px; }
.rec-head .rec-title { flex: 1 1 220px; min-width: 0; }
.rec-quota { font-size: 12px; color: var(--muted, #8aa0bd); padding: 0 0 10px; }
/*  ★예산이 다 떨어졌을 때 — **빨강이 아니라** 강조색 한 겹(거절이 아니라 안내다). */
.rec-quota.rec-quota-out { color: var(--accent); }
.rec-live { display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
  color: var(--text); font-variant-numeric: tabular-nums; }
.rec-live .rec-dot { width: 8px; height: 8px; border-radius: 50%;
  background: var(--danger, #f87171); animation: recPulse 1.4s ease-in-out infinite; }
@keyframes recPulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
/* ★W-EDU-E1-e — 다른 업무로 옮겨도 녹음이 살아 있음을 좌측 문 하나가 말한다.
   녹음 화면의 점(.rec-dot)과 같은 토큰·동작을 써서 두 상태가 다른 뜻을 만들지 않는다. */
#recording-nav { position: relative; }
#recording-nav.rec-nav-live::after { content: ""; width: 8px; height: 8px; margin-left: auto;
  border-radius: 50%; background: var(--danger, #f87171); animation: recPulse 1.4s ease-in-out infinite; }
.app-wrap.sb-collapsed #recording-nav.rec-nav-live::after { position: absolute; top: 6px; right: 10px; margin: 0; }
@media (prefers-reduced-motion: reduce) {
  .rec-live .rec-dot, #recording-nav.rec-nav-live::after { animation: none; }
}
.rec-page-title { display: flex; align-items: center; gap: 8px; margin: 2px 0 14px; font-size: 18px; font-weight: 500; }
.rec-page-title .ic { width: 19px; height: 19px; color: var(--accent); }
.rec-page-title small { margin-left: 4px; font-size: 12px; font-weight: 400; color: var(--muted); }
.rec-minutes-ready { cursor: pointer; text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }
.rec-minutes-badge { display: inline-block; margin: 0 0 0 6px; padding: 2px 6px; border-radius: 10px;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); font-size: 11px; white-space: nowrap; }
@media (max-width: 620px) { .rec-page-title { align-items: flex-start; flex-wrap: wrap; } .rec-page-title small { flex-basis: 100%; margin-left: 27px; } }
.mydocs td.rec-when, .mydocs td.rec-len, .mydocs td.rec-st {
  white-space: nowrap; color: var(--muted, #8aa0bd); font-size: 12px; }
.mydocs th.rec-ti { width: 100%; }
.mydocs td.rec-ti { color: var(--text, #eaf1fb); }
.mydocs td.rec-act, .mydocs th.rec-act { min-width: 238px; text-align: left; white-space: nowrap; }
/* 표 셀은 table-cell로 남겨야 행 경계가 유지된다. 행동 링크만 간격을 둔다. */
.mydocs td.rec-act .wk-link + .wk-link { margin-left: 12px; }
.mydocs td.rec-act .rec-sum { margin-right: 0; }
.rec-days { color: var(--muted, #8aa0bd); }
.rec-empty { padding: 14px 2px; font-size: 13px; color: var(--muted, #8aa0bd); }
.rec-review { margin: 0 0 12px; padding: 16px; }
/* ★W-EDU-E1-N-B1(사장님 실기) — 검수 화면 아래 버튼이 밀려 사라지고 스크롤이 안 됐다: `body.ais-capped .tv-body`
   가 overflow:hidden 이라 이 화면이 **제 천장**을 가져야 한다(W-AUTOREG-B2 ③ 자동화 · 메일 선례) +
   하단 입력 도크 높이만큼 바닥을 비운다(W-AUTOREG-B3 선례). */
.tv-sub[data-tv="recording"] { height: 100%; min-height: 0; overflow-y: auto;
  padding-bottom: max(var(--chat-dock-h, 72px), 72px); }
.rec-review-head, .rec-review-actions { display:flex; align-items:center; gap:8px; justify-content:space-between; margin-bottom:8px; }
.rec-review-note { margin: 0 0 10px; color: var(--muted); font-size: 12px; }
.rec-review label { display:block; margin:10px 0 5px; color:var(--muted); font-size:12px; }
.rec-review textarea { width:100%; min-height:110px; resize:vertical; padding:9px; font-family:inherit; line-height:1.5; }
.rec-review-original { opacity:.72; }
.rec-review-actions { justify-content:flex-start; margin-top:14px; padding-top:12px; }
.rec-meeting-meta { display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:10px; margin:14px 0 2px; padding:12px; border-radius:10px; background:color-mix(in srgb, var(--surface, #fff) 88%, var(--accent) 12%); }
.rec-meeting-meta label { margin:0; color:var(--muted); }
.rec-meeting-meta input { display:block; width:100%; margin-top:5px; }
.rec-glossary { display:grid; grid-template-columns: 1fr 1fr auto; gap:7px; margin-top:14px; padding-top:12px; }
.rec-glossary strong, .rec-glossary-list { grid-column:1 / -1; }
.rec-glossary-list { display:flex; gap:6px; flex-wrap:wrap; }
.rec-glossary-list span { display:inline-flex; gap:5px; align-items:center; padding:3px 7px; border-radius:8px; background:color-mix(in srgb, var(--accent) 10%, transparent); font-size:12px; }
.rec-glossary-list .wk-link { font-size:15px; line-height:12px; }
/*  ★폰 1급(426px) — 이름 칸이 줄을 독차지하고 버튼 둘이 그 아래 나란히 선다. */
@media (max-width: 480px) {
  .mydocs td.rec-act { min-width: 0; white-space:normal; }
  .mydocs td.rec-act .wk-link + .wk-link { margin-left: 8px; }
  .rec-meeting-meta { grid-template-columns:1fr; }
  .rec-head { gap: 6px; }
  .rec-head .rec-title { flex: 1 1 100%; }
}

/* ★W-MOB1 B②(2026-09-29 · 사장님 모바일 신고 «상하좌우가 흐리다») — 모바일(≤900px)에서만.
   실측(폭 420): 화면 밖에 붙어 있는 **닫힌** 좌측 드로어(-264px)·우측 캔버스(+420px)가 `box-shadow: 0 0 50px rgba(0,0,0,.5)`
   와 blur 를 그대로 지녀 50px 번짐이 좌우 가장자리로 스며들었다 · 하단 탭바는 유리 흐림(blur 16px)이었다.
   → 닫혀 있을 때는 그림자·블러를 끈다(열리면 종전 그대로) · 탭바는 불투명 바탕. 데스크톱 무접촉. */
@media (max-width: 900px) {
  .app-wrap:not(.sb-mobile-open) .sidebar,
  .app-wrap:not(.canvas-on) .canvas {
    box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .bottom-nav { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--panel, #fff); }
}

/* ★W-MOB2 ②④(2026-09-29 · 사장님 모바일 실기) — 모바일(≤900)에서만.
   ② 메일 목록 «제목·보낸사람 검색» · 본문 «분류에 넣기» 는 같은 줄 버튼(12px)과 같은 크기로. 전역 «입력류 16px»(iOS 포커스
      확대 방지) 규칙을 이 둘만 이긴다 — 확대 방지는 iOS 한정 viewport maximum-scale=1 이 대신한다(app.html head).
   ④ 🖥 PC 유지보수 메뉴는 숨긴다(위젯 PC 기능이 없는 환경). 데스크톱 무접촉. */
@media (max-width: 900px) {
  .mail-bar .mail-q, .md-actions .md-classify, select.md-classify { font-size: 12px !important; }
  #pc-care-nav { display: none !important; }
}

/* ★W-MOB2-B1 — 모바일 종료 확인은 **화면 중앙**(토스트 아님 · 2초). 누르는 것을 막지 않는다(pointer-events: none). */
#wk-exit-confirm { position: fixed; inset: 0; z-index: 9999; display: none; align-items: center;
  justify-content: center; pointer-events: none; }
#wk-exit-confirm.on { display: flex; }
#wk-exit-confirm .wk-exit-card { background: var(--panel, #fff); color: var(--text, #111);
  border-radius: 14px; padding: 16px 22px;   /* 테두리 대신 그림자(W-UIX14 래칫 — 1px 테두리·600/700 굵기는 늘리지 않는다) */
  font-size: 15px; font-weight: var(--fw-3, 600); box-shadow: 0 0 0 1px var(--hairline, rgba(0,0,0,.08)), 0 8px 30px rgba(0,0,0,.25); }

/* ★W-CREW1 C2 — 비서 방(워크룸 안) */
.wr-crew { margin-top: 4px; background: color-mix(in srgb, var(--accent) 4%, transparent); display: flex; flex-direction: column; min-height: 0; }
.wr-crew-head { font-size: 12px; font-weight: var(--fw-2); padding: 6px 10px 2px; color: var(--wk-caption, var(--muted)); }
.wr-crew-list { max-height: 260px; overflow-y: auto; padding: 4px 10px; display: flex; flex-direction: column; gap: 6px; }
.wr-crew-row { display: block; font-size: 13px; line-height: 1.45; max-width: 92%; }
.wr-crew-row.wr-crew-me { align-self: flex-end; background: color-mix(in srgb, var(--accent) 12%, transparent); padding: 4px 8px; border-radius: 8px; }
.wr-crew-row.wr-k-crew_q .wr-crew-text { font-weight: var(--fw-2); }
.wr-crew-tag { display: block; font-size: 11px; color: var(--accent); margin-bottom: 2px; }
.wr-crew-acts { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.wr-crew-btn { font-size: 12px; padding: 2px 8px; border-radius: 6px; border: 0; background: color-mix(in srgb, var(--accent) 10%, transparent); color: inherit; cursor: pointer; }
.wr-crew-form { display: flex; gap: 6px; padding: 6px 10px 8px; }
.wr-crew-input { flex: 1; min-width: 0; font-size: 13px; padding: 6px 8px; border-radius: 6px; border: 0; background: color-mix(in srgb, var(--accent) 6%, transparent); color: inherit; }
.wr-crew-send { font-size: 12px; padding: 4px 10px; border-radius: 6px; border: 0; background: var(--accent); color: #fff; cursor: pointer; }
.wr-crew-err { color: var(--danger, var(--accent)); }
.wr-crew-note { font-size: 12px; color: var(--wk-caption, var(--muted)); margin-top: 2px; }
/* ★W-CREW2 M3 — 메일 답장 카드(초안 펼쳐 고치기) */
.wr-crew-mail { margin-top: 4px; }
.wr-crew-draft { display: block; width: 100%; box-sizing: border-box; margin-top: 4px; font: inherit; font-size: 13px; line-height: 1.5;
  padding: 6px 8px; border-radius: 6px; border: 0; resize: vertical; background: color-mix(in srgb, var(--accent) 6%, transparent); color: inherit; }
.wr-crew-why { display: block; width: 100%; box-sizing: border-box; margin-top: 4px; }
.wr-crew-why.hidden { display: none; }
/* ★W-CREW2-B1 (1) — 메일 카드의 [캘린더에 등록] 줄(날짜·시각·제목 미리 채움) */
.wr-crew-ev { display: flex; align-items: center; gap: 4px; margin-top: 6px; cursor: pointer; }
.wr-crew-ev-row { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.wr-crew-ev-row .wr-crew-ev-f { flex: 1 1 110px; min-width: 0; }
/* ★W-SEC2 ③ — 2단계 인증(설정 · 프로필) */
.mfa-qr svg { width: 180px; height: 180px; background: #fff; border-radius: 6px; }
.mfa-codes { font-family: var(--font-mono); font-size: 14px; line-height: 1.7; padding: 8px 12px; background: color-mix(in srgb, var(--accent) 6%, transparent); border-radius: 6px; }
.mfa-input { display: block; margin: 6px 0; }
/* ★W-SEC2 ② — 로그인된 기기 한 줄(설정 · 프로필) */
.sess-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 0; font-size: 13px; }
.sess-text { min-width: 0; overflow-wrap: anywhere; }
/* ★W-CREW1-B1(f) — 비서 방 흐름 안의 진행 대화(CrewTalk 이 그리는 `.wr-row` 를 그대로 담는다 · 폭만 연다) */
.wr-crew-row.wr-crew-live { max-width: 100%; }
.crew-nav-badge { margin-left: auto; font-size: 11px; min-width: 16px; text-align: center; border-radius: 8px; background: var(--accent); color: #fff; padding: 0 4px; }
@media (max-width: 760px) { .wr-root.wr-full.open { left: 0 !important; right: 0; top: 0; bottom: 0 !important; width: auto; }
  .wr-root.wr-full.open .wr-crew-list { max-height: none; flex: 1; } }

