genetics-mcp 2.14.0 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/bin/aarch64-apple-darwin/gcell +0 -0
  2. package/bin/aarch64-unknown-linux-musl/gcell +0 -0
  3. package/bin/manifest.json +4 -4
  4. package/bin/x86_64-apple-darwin/gcell +0 -0
  5. package/bin/x86_64-unknown-linux-musl/gcell +0 -0
  6. package/genetics.mjs +202 -9
  7. package/package.json +1 -1
  8. package/skills/gazette-report/README.md +71 -0
  9. package/skills/gazette-report/SKILL.md +479 -0
  10. package/skills/gazette-report/scripts/boundary.py +97 -0
  11. package/skills/gazette-report/scripts/contentdiff.sh +36 -0
  12. package/skills/gazette-report/scripts/cssaudit.sh +78 -0
  13. package/skills/gazette-report/scripts/extract.sh +84 -0
  14. package/skills/gazette-report/scripts/flexcheck.mjs +28 -0
  15. package/skills/gazette-report/scripts/fontchk.mjs +62 -0
  16. package/skills/gazette-report/scripts/kcheck.mjs +146 -0
  17. package/skills/gazette-report/scripts/package.json +5 -0
  18. package/skills/gazette-report/scripts/pdfcheck.sh +34 -0
  19. package/skills/gazette-report/scripts/read.mjs +85 -0
  20. package/skills/gazette-report/scripts/sentbreak.py +142 -0
  21. package/skills/gazette-report/scripts/tone.mjs +172 -0
  22. package/skills/gazette-report/scripts/tone.test.mjs +118 -0
  23. package/skills/gazette-report/scripts/typesurvey.mjs +48 -0
  24. package/skills/gazette-report/template/README.md +89 -0
  25. package/skills/gazette-report/template/gazette.css +2120 -0
  26. package/skills/gazette-report/template/skeleton.html +477 -0
  27. package/skills/genetics-cell-id/SKILL.md +9 -7
  28. package/skills/genetics-report/SKILL.md +53 -6
  29. package/skills/genetics-report/assets/example/cases-briefing.json +32 -0
  30. package/skills/genetics-report/assets/example/report-briefing.json +271 -0
  31. package/skills/genetics-report/assets/example/report.json +1 -1
  32. package/skills/genetics-report/references/content-pipeline.md +20 -0
  33. package/skills/genetics-report/references/lim-portal-format.md +100 -7
  34. package/skills/genetics-report/references/process.md +11 -0
@@ -0,0 +1,2120 @@
1
+ /* gazette.css — 관보(정부간행물) 문서 문법 조판 뼈대
2
+ gazette-report 스킬 · 추출 원본: FI-soft/report-v2 (8종 검사를 통과한 구현)
3
+ ※ 손으로 고치지 마라. 원본을 고치고 scripts/extract.sh 를 다시 돌린다.
4
+
5
+ 담는 것 — 문서 무관한 것만:
6
+ 조판 3체계(활자·굵기·간격) · 가구(표지·이력·차례·활용법·요약·간지·부록·판권지)
7
+ 두 단 본문(여백 주석 단) · 위치 브레드크럼 머리띠 · 측면 색인 레일
8
+ 표 4괘선 · 확인 강도 표식(●◐○─) · ※ 각주 · 인쇄 페이지 문법
9
+
10
+ 고칠 것은 셋뿐:
11
+ 1. 장 색 [data-chapter] · PART 색 [data-part-no]
12
+ — 팔레트를 베끼지 말고 **그 문서가 이미 쓰는 상태색**에서 뽑아라
13
+ 2. --wide (문서 폭) · --marg (여백 주석 단 폭)
14
+ 3. @page 마진 박스의 러닝 푸터 문구
15
+
16
+ 외부 의존: Pretendard GOV 웹폰트 하나. JS 라이브러리 0개.
17
+ 상호작용(처리 표시·머리띠 추적·진입 모션)은 문서마다 다르므로 여기 없다 —
18
+ skeleton.html 의 「스크립트 계약」 주석 참조.
19
+ */
20
+
21
+ /* guidebook.css — report-v2 · KRDS 테마 + 관보 문서 문법 + ux-story 행동 설계
22
+ SSOT: 이 폴더 전용. lim-report.css / build.py 와 공유하지 않는다.
23
+
24
+ ── 문서 문법 (행안부·KISA 『소프트웨어 개발보안 가이드』 구조 이식) ──
25
+ 표지(한 면) · 차례 · 절 간지 · 우측 세로 색인 · 표 캡션 칩 · 판권지
26
+ 인쇄에서는 @page 로 진짜 페이지가 된다. 17절 참조.
27
+
28
+ ── 정보 위계 (ux-story 4단계 결정) ──────────────────────────
29
+ 독자(FI-soft 웹·서버 담당)의 몫 → Primary #256EF4
30
+ 그중 가장 시급한 한 건 → Danger #DE3412
31
+ 서버가 준비돼야 풀리는 것 → Warning #FFB114
32
+ 우리가 이미 끝낸 것 → 중립 회색
33
+ 처리 표시된 것 → 가라앉힘 (opacity·grayscale)
34
+
35
+ ── 컨텍스트 축 ─────────────────────────────────────────────
36
+ 진행 상태 · 긴급도 · 시간 · 환경 · 읽기 위치 */
37
+
38
+ /* ══ 1. KRDS 토큰 ════════════════════════════════════════════ */
39
+ :root {
40
+ --krds-primary: #256ef4;
41
+ --krds-primary-hover: #0b50d0;
42
+ --krds-primary-deep: #083891;
43
+ --krds-primary-surface: #ecf2fe;
44
+ --krds-primary-line: #b1cefb;
45
+
46
+ --krds-success: #228738;
47
+ --krds-success-deep: #17692b;
48
+ --krds-success-surface: #eaf6ec;
49
+ --krds-success-line: #a9d6b4;
50
+
51
+ --krds-warning: #ffb114;
52
+ --krds-warning-text: #8a5c00;
53
+ --krds-warning-surface: #fff8e9;
54
+ --krds-warning-line: #f0d69a;
55
+
56
+ --krds-danger: #de3412;
57
+ --krds-danger-text: #b5250a;
58
+ --krds-danger-surface: #fdefec;
59
+ --krds-danger-line: #f4b8ab;
60
+
61
+ --krds-info: #0b78cb;
62
+ --krds-info-surface: #e8f4fd;
63
+ --krds-info-line: #a8d5f2;
64
+
65
+ --krds-canvas: #ffffff;
66
+ --krds-surface: #f4f5f6;
67
+ --krds-surface-deep: #e9ebee;
68
+ --krds-text: #1e2124;
69
+ --krds-text-subtle: #464c53;
70
+ --krds-text-muted: #6d7882;
71
+ --krds-border: #b1b8be;
72
+ --krds-border-strong: #58616a;
73
+ --krds-divider: #e6e8ea;
74
+
75
+ /* ── 반경: 문서는 각(角)이다 ──────────────────────────────
76
+ KRDS 4/6/8px 반경 계약을 이 산출물에서는 쓰지 않는다. 근거 넷:
77
+ ① KRDS 는 정부 「웹 서비스 UI」 표준이며 인쇄물 조판 규격이 없다.
78
+ 이 문서의 최종 형태는 A4 21쪽 PDF 다.
79
+ ② 원전(행안부·KISA 가이드)은 KRDS 와 발행 주체가 같고 반경이 0 이다.
80
+ ③ 반경이 화면/인쇄 이원화의 원인이다 — border-radius 는 overflow:hidden 과
81
+ 짝인데, overflow:hidden 은 monolithic 후보(css-break-3 §4.1)라 쪽 넘김에서
82
+ 요소를 잘라낸다. 반경 0 이면 @media print 의 되돌림 규칙 8개가 소멸한다.
83
+ ④ 색·대비 AA·포커스 규격은 KRDS 계약 그대로다. 깨는 것은 반경 하나뿐.
84
+ 이름은 유지한다 — 되돌림은 값 네 개 복원. */
85
+ --r-sm: 0;
86
+ --r-md: 0;
87
+ --r-lg: 0;
88
+ --r-pill: 0;
89
+ --r-ui: 2px; /* 컨트롤·포커스 링 전용. 0 이면 포커스 링 두 겹이 모서리에서 뾰족해진다 */
90
+
91
+ /* ── 굵기 3종 ───────────────────────────────────────────
92
+ 굵기는 위계를 나르는 신호다. 종류가 많으면 신호가 죽는다.
93
+ 500 은 Pretendard 에서 400 과 구분이 안 되고, 800 은 700 과 겹친다.
94
+ 굵게 쓸 수 있는 것: 제목 · 라벨 · 좌표 번호 · 수치 · 강조 · 기호. 그뿐. */
95
+ --w-light: 300; /* 표제 부제 — 표지 2행 · 간지 로마숫자 */
96
+ --w-body: 400; /* 본문 · 표 셀 값 · 설명 */
97
+ --w-bold: 700; /* 제목 · 라벨 · 번호 · 수치 · 강조 */
98
+
99
+ /* ── 활자 스케일 1.2 (Minor Third) · 본문 17px 기준 ───────── */
100
+ /* 14px 미만은 쓰지 않는다. 한글 판독 하한이고, 그 아래는 「작아서 넣은 것」이 된다.
101
+ 그래서 최소 등급은 하나 — 라벨·칩·표 머리·각주·범례·여백 주석이 모두 여기. */
102
+ --t-sm: 14px; --lh-sm: 1.7; /* 부속 — 라벨·칩·표 머리·각주·여백 주석 */
103
+ --t-base: 17px; --lh-base: 1.75; /* 모든 문단 */
104
+ --t-md: 20px; --lh-md: 1.4; /* 건 제목 · 요약면 제목 */
105
+ --t-lg: 24px; --lh-lg: 1.35; /* 가구 제목(차례·부록·판권지) */
106
+ --t-xl: 29px; --lh-xl: 1.3; /* 절 제목 */
107
+ --t-2xl: 35px; --lh-2xl: 1.25; /* PART 제목 · 수치 */
108
+ /* 표제(題字) register — 본문 스케일 밖. 표지 대제목·간지 로마숫자 전용 */
109
+ --t-d1: 42px; --t-d2: 51px; --t-d3: 61px; --lh-d: 1.1;
110
+
111
+ /* ── 간격 격자 4px ────────────────────────────────────────
112
+ 8px 기각: 12px 칩 + 8px 여백 = 28px 로 --topbar 2단(32px/단)에 안 들어간다. */
113
+ --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px;
114
+ --s6: 24px; --s8: 32px; --s12: 48px; --s16: 64px;
115
+
116
+ /* clamp 는 min·max 를 둘 다 격자값으로 고정한다 —
117
+ --wide 고정폭과 인쇄에서 최종 조판은 언제나 max = 격자값 */
118
+ --pad-lg: clamp(24px, 4vw, 48px); /* 전면 패널 */
119
+ --pad-md: clamp(16px, 2.4vw, 24px); /* 그 외 */
120
+
121
+ /* ── 괘선 3종 · 관보 표 문법 ──────────────────────────────
122
+ 표의 좌·우 바깥 테두리는 없다. 세로선은 라벨-값 양식표에만. */
123
+ /* 두께 3종. style 을 포함해야 한다 — `border-top: 2px` 만 쓰면 style 이 없어 선이 안 그려진다. */
124
+ --rule-thin: 1px solid;
125
+ --rule-mid: 2px solid;
126
+ --rule-thick: 4px solid;
127
+
128
+ --rule-edge: 2px solid var(--krds-text); /* 표 위 · 표 맨 아래 */
129
+ --rule-head: 1px solid var(--krds-border-strong); /* 헤더 아래 */
130
+ --rule-row: 1px solid var(--krds-divider); /* 행 사이 */
131
+
132
+ --font: "Pretendard GOV", "Pretendard", -apple-system, BlinkMacSystemFont,
133
+ "Apple SD Gothic Neo", "Noto Sans KR", sans-serif;
134
+ --focus: 0 0 0 2px #fff, 0 0 0 5px var(--krds-primary);
135
+
136
+ --wide: 1080px;
137
+ /* 한글 자폭은 Pretendard 에서 1em 이 아니라 0.8625em 이다(실측).
138
+ 44em 은 44자가 아니라 51자가 된다 — 라틴 기준 토큰을 그대로 쓰면 글줄이 길어진다.
139
+ 37em × 0.8625 ≈ 43자. 한글 적정은 35~45자. */
140
+ --measure: 37em;
141
+ --pad: 24px;
142
+ --topbar: 64px;
143
+ --marg: 240px; /* 주석 단 글줄 19자 — 관보 가이드의 여백 단은 12~19자 */
144
+ --rail: 0px; /* 가로 탭 스트립 폐지 — 브레드크럼 머리띠가 대신한다 */
145
+ --rail-side: 48px;
146
+ --marg-gap: var(--s8);
147
+
148
+ color-scheme: light only;
149
+ }
150
+
151
+ /* ══ 1-2. 장 색 ═══════════════════════════════════════════════
152
+ PDF 의 파스텔 팔레트를 옮겨오지 않는다.
153
+ 이 문서가 이미 본문에서 쓰고 있는 상태색을 장 정체성으로 승격한다.
154
+ 그래야 04절의 초록 `.tag--live` 태그가 04장 색과 저절로 이어진다.
155
+
156
+ 01 독자 몫 Primary DESIGN.md 제1계약 그대로 — 진짜 Primary 는 여기뿐
157
+ 02 요지 딥네이비 01 의 배경 = 같은 계열 더 깊은 쪽
158
+ 03 한눈에 진회색 모든 절로 흩어지는 허브 — 특정 상태에 속하지 않음
159
+ 04 끝난 것 Success `.tag--live`(실기기 확인함) 가 이미 쓰는 색
160
+ 05 서버 대기 Warning 계열 `.tag--wait` · `tr.open` 이 이미 쓰는 색
161
+ 면은 노랑(#FFF8E9), 글자 면은 #8A5C00
162
+ — 노랑 #FFB114 위의 흰 글자는 대비 1.8 로 미달
163
+ 06 미확인 연회색 판단 보류에는 색을 주지 않는다 */
164
+
165
+ [data-chapter="01"] { --ch: #256ef4; --ch-deep: #083891; --ch-surf: #ecf2fe; --ch-line: #b1cefb; }
166
+ [data-chapter="02"] { --ch: #083891; --ch-deep: #06265f; --ch-surf: #e9eef8; --ch-line: #b6c4dd; }
167
+ [data-chapter="03"] { --ch: #58616a; --ch-deep: #3d444b; --ch-surf: #eff1f3; --ch-line: #c9ced3; }
168
+ [data-chapter="04"] { --ch: #228738; --ch-deep: #17692b; --ch-surf: #eaf6ec; --ch-line: #a9d6b4; }
169
+ [data-chapter="05"] { --ch: #8a5c00; --ch-deep: #6b4700; --ch-surf: #fff8e9; --ch-line: #f0d69a; }
170
+ [data-chapter="06"] { --ch: #68727b; --ch-deep: #464c53; --ch-surf: #f4f5f6; --ch-line: #d5d9dd; }
171
+
172
+ /* ══ 1-3. PART 층위 ═══════════════════════════════════════════
173
+ PDF 는 PART > Chapter > 절 > 항 4단이다. 이 문서를 절 6개로 납작하게
174
+ 펴 놓으면 「먼저 읽을 것 / 경과 / 남은 것」이라는 독자의 실제 읽기 순서가 사라진다.
175
+
176
+ PART I 요청 01절 — 독자 몫. Primary (01 과 같은 색)
177
+ PART II 경과 02·03·04절 — 기록·사실. 흑연 (색을 주지 않는다)
178
+ PART III 잔여 05·06절 — 대기·미결. 황갈 (05 의 색 계열) */
179
+
180
+ [data-part-no="1"] { --pt: #256ef4; --pt-deep: #083891; --pt-surf: #ecf2fe; }
181
+ [data-part-no="2"] { --pt: #3d444b; --pt-deep: #1e2124; --pt-surf: #eff1f3; }
182
+ [data-part-no="3"] { --pt: #8a5c00; --pt-deep: #6b4700; --pt-surf: #fff8e9; }
183
+ [data-part-no="apx"] { --pt: #59496b; --pt-deep: #3f3550; --pt-surf: #f1eef6; }
184
+
185
+ /* 06절은 확정된 것이 아니라 유보다. 이 문서가 이미 쓰는 파선 문법
186
+ (`.tag--soon` 준비되면 확인)을 빌려 채우지 않고 테두리만 준다.
187
+ 03절의 진회색과도 이것으로 확실히 갈린다. */
188
+ [data-chapter="06"] .toc__no,
189
+ [data-chapter="06"] .part__count {
190
+ background: var(--krds-canvas); color: var(--ch-deep);
191
+ border: 1px dashed var(--ch); font-weight: var(--w-bold);
192
+ }
193
+
194
+ .part[data-chapter="06"] .part__head { border-left-style: dashed; }
195
+ .part[data-chapter="06"] .part__no { border-right-style: dashed; }
196
+
197
+ /* ══ 2. 기반 ══════════════════════════════════════════════════ */
198
+ *, *::before, *::after { box-sizing: border-box; }
199
+
200
+ html { scroll-behavior: smooth; }
201
+
202
+ body {
203
+ margin: 0;
204
+ font-family: var(--font);
205
+ font-size: var(--t-base);
206
+ line-height: 1.5;
207
+ color: var(--krds-text);
208
+ background: var(--krds-canvas);
209
+ -webkit-font-smoothing: antialiased;
210
+ word-break: keep-all;
211
+ overflow-wrap: break-word;
212
+ }
213
+
214
+ h1, h2, h3 { letter-spacing: -0.02em; }
215
+
216
+ .sr {
217
+ position: absolute; width: 1px; height: 1px; margin: -1px;
218
+ overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
219
+ }
220
+
221
+ a { color: inherit; text-underline-offset: 3px; }
222
+
223
+ a:focus-visible, button:focus-visible {
224
+ outline: none;
225
+ box-shadow: var(--focus);
226
+ border-radius: var(--r-ui);
227
+ }
228
+
229
+ .skip {
230
+ position: absolute; left: 16px; top: -100px; z-index: 500;
231
+ padding: var(--s3) var(--s4); border-radius: var(--r-ui);
232
+ background: var(--krds-primary); color: #fff;
233
+ font-weight: var(--w-bold); text-decoration: none;
234
+ }
235
+
236
+ .skip:focus { top: 14px; }
237
+
238
+ /* 본문 상호참조 — KRDS 텍스트 링크 */
239
+ .ref {
240
+ color: var(--krds-primary-hover);
241
+ font-weight: var(--w-body); /* 밑줄이 이미 신호다 — 본문 119군데가 굵으면 문단이 얼룩진다 */
242
+ text-decoration: underline;
243
+ text-decoration-thickness: 1px;
244
+ text-decoration-color: var(--krds-primary-line);
245
+ }
246
+
247
+ .ref:hover { text-decoration-thickness: 2px; text-decoration-color: currentColor; }
248
+
249
+ /* ══ 3. 러닝 헤더 = 위치 브레드크럼 ═══════════════════════════
250
+ 관보 가이드의 머리띠 문법. 브랜드 바가 아니라 「지금 어디인가」를
251
+ PART · Chapter 두 계층에서 동시에 알려 주는 좌표계다.
252
+ 그래서 매 쪽(=매 스크롤 위치)에 있어야 한다. */
253
+ .topbar {
254
+ position: sticky; top: 0; z-index: 200;
255
+ display: grid; grid-template-rows: 1fr 1fr;
256
+ height: var(--topbar);
257
+ background: var(--krds-canvas);
258
+ font-size: var(--t-sm);
259
+ }
260
+
261
+ .crumb {
262
+ display: flex; align-items: center; gap: var(--s2);
263
+ max-width: var(--wide); width: 100%; margin: 0 auto; padding: 0 var(--pad);
264
+ min-width: 0;
265
+ }
266
+
267
+ .crumb + .crumb { border-top: 1px solid var(--krds-divider); }
268
+
269
+ .crumb__k {
270
+ flex: 0 0 auto; width: 5.8em;
271
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.08em;
272
+ color: var(--krds-text-muted); text-transform: uppercase;
273
+ white-space: nowrap;
274
+ }
275
+
276
+ .crumb__row {
277
+ display: flex; align-items: center; gap: var(--s1);
278
+ margin: 0; padding: 0; list-style: none;
279
+ }
280
+
281
+ .crumb__row li { display: inline-flex; align-items: center; }
282
+
283
+ /* 칸 하나 = 한 PART / 한 Chapter. 현재 것만 채운다 */
284
+ .crumb__c {
285
+ display: inline-flex; align-items: center; justify-content: center;
286
+ min-width: 19px; height: 19px; padding: 0 var(--s1);
287
+ border: 1px solid var(--krds-border);
288
+ background: var(--krds-canvas); color: var(--krds-text-muted);
289
+ font-size: var(--t-sm); font-weight: var(--w-bold); line-height: var(--lh-sm);
290
+ font-variant-numeric: tabular-nums; text-decoration: none;
291
+ transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
292
+ }
293
+
294
+ .crumb__c:hover { background: var(--krds-surface); color: var(--krds-text); }
295
+
296
+ .crumb__row--part .crumb__c { min-width: 24px; letter-spacing: 0.04em; }
297
+
298
+ .crumb__c.is-on {
299
+ background: var(--pt, var(--ch, var(--krds-primary)));
300
+ border-color: var(--pt, var(--ch, var(--krds-primary)));
301
+ color: #fff;
302
+ }
303
+
304
+ /* 잔여 건수를 번호 칸과 같은 행에 두지 않는다.
305
+ 칸(19px·굵게·tabular-nums)과 배지(17px·굵게·tabular-nums)는 모양이 사실상 같아서
306
+ 「1 6 2 3 4 5 6」 — 여섯 절 사이에 낀 일곱 번째 절로 읽힌다.
307
+ 숫자만 있는 표식은 숫자 행 옆에 두지 않는다. 낱말로 감싸 우측 판독부로 옮긴다. */
308
+ .crumb__rem {
309
+ flex: 0 0 auto; padding-left: var(--s3); margin-left: var(--s3);
310
+ border-left: 1px solid var(--krds-divider);
311
+ font-size: var(--t-sm); line-height: var(--lh-sm);
312
+ color: var(--krds-text-muted); white-space: nowrap;
313
+ }
314
+
315
+ .crumb__rem[hidden] { display: none; }
316
+
317
+ .crumb__badge { font-weight: var(--w-bold); color: var(--krds-primary-deep); font-variant-numeric: tabular-nums; }
318
+
319
+ .crumb__now {
320
+ flex: 1 1 auto; min-width: 0; text-align: right;
321
+ color: var(--krds-text-subtle);
322
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
323
+ }
324
+
325
+ .crumb--part .crumb__now { font-weight: var(--w-bold); color: var(--pt-deep, var(--krds-text)); }
326
+
327
+ /* 관보 머리띠의 우측 끝은 「쪽번호」다 — 문서 안 어디인지를 알려 주는 앵커.
328
+ 화면에는 쪽이 없으므로 절 위치(N / 6)로 옮긴다. 날짜는 표지·이력·판권지의 몫. */
329
+ .crumb__pos {
330
+ flex: 0 0 auto; padding-left: var(--s3); margin-left: var(--s3);
331
+ border-left: 1px solid var(--krds-divider);
332
+ font-size: var(--t-sm); color: var(--krds-text-muted);
333
+ font-variant-numeric: tabular-nums; white-space: nowrap;
334
+ }
335
+
336
+ .crumb__pos b {
337
+ font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-text);
338
+ margin-right: 0;
339
+ }
340
+
341
+ @media (max-width: 700px) {
342
+ .crumb__k { width: auto; font-size: var(--t-sm); }
343
+ .crumb__now, .crumb__rem { display: none; }
344
+ .crumb { gap: var(--s2); }
345
+ }
346
+
347
+ /* 관보 머리띠 아래의 색 괘선. 웹의 진행률 막대가 아니라 머리띠의 밑선으로 읽히게 한다. */
348
+ .progress {
349
+ position: sticky; top: var(--topbar); z-index: 199;
350
+ height: 2px; background: var(--krds-border); pointer-events: none;
351
+ }
352
+
353
+ .progress__fill {
354
+ display: block; height: 100%; width: 0%;
355
+ background: var(--krds-primary); transition: width 0.15s linear;
356
+ }
357
+
358
+ .rail { display: none; } /* ≥1280px 에서만 세로 색인으로 되살아난다 */
359
+
360
+ .rail__tabs {
361
+ display: flex; overflow-x: auto; scrollbar-width: none;
362
+ max-width: var(--wide); margin: 0 auto; padding: 0 var(--pad);
363
+ }
364
+
365
+ .rail__tabs::-webkit-scrollbar { display: none; }
366
+
367
+ /* KRDS 탭 — 활성은 primary 글자 + 하단 2px */
368
+ .rail__tab {
369
+ flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--s2);
370
+ height: var(--rail); padding: 0 var(--s4);
371
+ font-size: var(--t-sm); color: var(--krds-text-subtle);
372
+ text-decoration: none; white-space: nowrap;
373
+ border-bottom: 2px solid transparent;
374
+ transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
375
+ }
376
+
377
+ .rail__tab b { font-weight: var(--w-bold); font-variant-numeric: tabular-nums; color: var(--krds-text-muted); }
378
+ .rail__tab:hover { background: var(--krds-surface); color: var(--krds-text); }
379
+
380
+ .rail__tab.is-active {
381
+ color: var(--krds-primary); font-weight: var(--w-bold);
382
+ border-bottom-color: var(--krds-primary);
383
+ }
384
+
385
+ .rail__tab.is-active b { color: var(--krds-primary); }
386
+
387
+ /* 남은 건수 배지 — 진행 상태 축 */
388
+ .rail__badge {
389
+ display: inline-flex; align-items: center; justify-content: center;
390
+ min-width: 20px; height: 20px; padding: 0 var(--s2);
391
+ border-radius: var(--r-pill);
392
+ background: var(--krds-primary); color: #fff;
393
+ font-size: var(--t-sm); font-weight: var(--w-bold); font-variant-numeric: tabular-nums;
394
+ }
395
+
396
+ .rail__badge[hidden] { display: none; }
397
+
398
+ .rail__badge.is-bump { animation: bump 0.2s ease-out; }
399
+
400
+ @keyframes bump { 50% { transform: scale(1.18); } }
401
+
402
+ /* ── 우측 세로 색인 레일 — 관보의 책등 색인 ──
403
+ 넓은 화면에서만. 같은 마크업을 방향만 돌려 쓴다.
404
+ 좁은 화면에서 세로 탭은 폭이 없으므로 위의 가로 스트립을 그대로 둔다. */
405
+ @media (min-width: 1280px) {
406
+ .rail {
407
+ display: block;
408
+ position: fixed; top: 50%; right: 0; left: auto;
409
+ transform: translateY(-50%);
410
+ max-height: calc(100vh - 80px);
411
+ overflow-y: auto; scrollbar-width: none;
412
+ background: none; border-bottom: none;
413
+ }
414
+
415
+ .rail::-webkit-scrollbar { display: none; }
416
+
417
+ .rail__tabs {
418
+ display: block; overflow: visible;
419
+ max-width: none; margin: 0; padding: 0;
420
+ }
421
+
422
+ .rail__tab {
423
+ display: flex; align-items: center; justify-content: flex-start;
424
+ gap: var(--s2);
425
+ writing-mode: vertical-rl;
426
+ width: var(--rail-side); height: auto; min-height: 92px;
427
+ margin: 0 0 var(--s1) auto; padding: var(--s3) 0 var(--s3);
428
+ background: transparent;
429
+ border-top: var(--rule-thin); border-top-color: var(--krds-divider);
430
+ font-size: var(--t-sm); letter-spacing: 0.01em;
431
+ transition: background 0.15s ease, color 0.15s ease, width 0.15s ease;
432
+ }
433
+
434
+ /* 세로쓰기에서 숫자는 눕는다. 두 자리를 한 글자처럼 세운다 (타테추요코) */
435
+ .rail__tab b {
436
+ color: var(--krds-text-muted);
437
+ text-combine-upright: all;
438
+ -webkit-text-combine: horizontal;
439
+ }
440
+ .rail__tab:hover { width: calc(var(--rail-side) + 5px); background: var(--krds-surface-deep); }
441
+
442
+ /* 현재 장은 그 장의 색으로 채운다 */
443
+ .rail__tab.is-active {
444
+ width: calc(var(--rail-side) + 8px);
445
+ background: var(--ch); color: #fff;
446
+ border-color: var(--ch);
447
+ }
448
+
449
+ .rail__tab.is-active b { color: #fff; }
450
+
451
+ .rail__badge {
452
+ writing-mode: horizontal-tb;
453
+ min-width: 19px; height: 19px; font-size: var(--t-sm);
454
+ }
455
+
456
+ .rail__tab.is-active .rail__badge { background: #fff; color: var(--ch-deep); }
457
+
458
+ /* 레일이 위에 없으므로 착지 여백·표지 높이에서 그 높이를 뺀다 */
459
+ .cover { min-height: calc(100vh - var(--topbar) - 56px); }
460
+ .part { scroll-margin-top: calc(var(--topbar) + var(--s4)); }
461
+ .ask, .sheet { scroll-margin-top: calc(var(--topbar) + var(--s6)); }
462
+ }
463
+
464
+ /* ══ 4. 문서 그릇 ═════════════════════════════════════════════ */
465
+ .doc { max-width: var(--wide); margin: 0 auto; padding: 0 var(--pad) var(--s16); }
466
+
467
+ /* ══ 5. 알림 배너 — 긴급도 × 진행 상태 ═══════════════════════ */
468
+ /* 요약면 안의 「현황」 줄. 표지 위에 떠 있는 웹 토스트는 관보 문법에 없고,
469
+ 이 문서는 같은 말을 이미 01-1 카드 · 02절 시급 박스 · 잔여 배지에서 한다.
470
+ 상태가 바뀌는 한 줄이므로 요약면이 있을 자리다. */
471
+ .notice {
472
+ display: flex; align-items: flex-start; gap: var(--s3);
473
+ margin: 0; padding: var(--s3) var(--s4);
474
+ border: 0; border-bottom: var(--rule-thin); border-bottom-color: var(--krds-divider);
475
+ border-left: var(--rule-thick); border-left-color: transparent;
476
+ transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
477
+ }
478
+
479
+ @keyframes notice-in {
480
+ from { opacity: 0; transform: translateY(-6px); }
481
+ to { opacity: 1; transform: translateY(0); }
482
+ }
483
+
484
+ .notice__mark {
485
+ flex: 0 0 auto; display: inline-flex;
486
+ align-items: center; justify-content: center;
487
+ width: 22px; height: 22px; border-radius: 50%;
488
+ font-size: var(--t-sm); font-weight: var(--w-bold); color: #fff;
489
+ transition: background 0.3s ease;
490
+ }
491
+
492
+ .notice__text { margin: 0; max-width: var(--measure); font-size: var(--t-base); line-height: var(--lh-base); }
493
+
494
+ .notice[data-state="critical"] {
495
+ background: var(--krds-danger-surface);
496
+ border-color: var(--krds-danger-line); border-left-color: var(--krds-danger);
497
+ color: var(--krds-danger-text);
498
+ }
499
+ .notice[data-state="critical"] .notice__mark { background: var(--krds-danger); }
500
+
501
+ .notice[data-state="info"] {
502
+ background: var(--krds-info-surface);
503
+ border-color: var(--krds-info-line); border-left-color: var(--krds-info);
504
+ color: #0a5d9e;
505
+ }
506
+ .notice[data-state="info"] .notice__mark { background: var(--krds-info); }
507
+ .notice[data-state="info"] .notice__mark::after { content: "i"; }
508
+ .notice[data-state="info"] .notice__mark { font-style: italic; }
509
+
510
+ .notice[data-state="success"] {
511
+ background: var(--krds-success-surface);
512
+ border-color: var(--krds-success-line); border-left-color: var(--krds-success);
513
+ color: var(--krds-success-deep);
514
+ }
515
+ .notice[data-state="success"] .notice__mark { background: var(--krds-success); }
516
+
517
+ .notice[data-state="info"] .notice__mark,
518
+ .notice[data-state="success"] .notice__mark { font-size: 0; }
519
+ .notice[data-state="info"] .notice__mark::before { content: "i"; font-size: var(--t-sm); font-style: italic; }
520
+ .notice[data-state="success"] .notice__mark::before { content: "\2713"; font-size: var(--t-sm); }
521
+
522
+ /* ══ 6. 표지 — 한 면을 통째로 쓴다 (관보 세로 스택) ══════════
523
+ 번호 박스 → 대제목 2행 → 괘선 노드 → 도해 → 메타 → 발행처
524
+ 그림 파일은 쓰지 않는다. 괘선·노드는 전부 CSS. */
525
+ .cover {
526
+ /* 머리(auto) · 표제 마당(1fr — 남는 높이를 전부 먹는다) · 메타(auto) · 발행처(auto).
527
+ 가운데 빈 마당은 관보 표지의 문법이다. 선으로 닫지 않는다 — 여백 자체가 마감이다. */
528
+ display: grid; grid-template-rows: auto 1fr auto auto;
529
+ min-height: calc(100vh - var(--topbar) - 56px);
530
+ margin: var(--s6) 0 0;
531
+ border-top: var(--rule-thick); border-top-color: var(--krds-primary-deep);
532
+ border-bottom: var(--rule-thin); border-bottom-color: var(--krds-border);
533
+ background: var(--krds-canvas);
534
+ }
535
+
536
+ /* 표지 머리 — 좌: 발간등록번호 상자 / 우: 고객사 마크.
537
+ 관보 표지의 우상단은 발행 주체의 마크 자리다. 로고를 못 받으면 비워 두지 말고
538
+ 고객사명을 활자로 세운다 — 빈 자리는 「받을 것을 못 받은 문서」로 읽힌다. */
539
+ .cover__top {
540
+ display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s6);
541
+ padding: var(--pad-lg) var(--pad-lg) 0;
542
+ }
543
+
544
+ /* 발간등록번호 박스 — 관보 표지 좌상단 */
545
+ .cover__docno {
546
+ flex: 0 0 auto;
547
+ border: 1px solid var(--krds-border-strong);
548
+ border-radius: var(--r-sm);
549
+ font-variant-numeric: tabular-nums;
550
+ }
551
+
552
+ .cover__dk {
553
+ display: block; padding: var(--s1) var(--s3) var(--s1);
554
+ background: var(--krds-surface);
555
+ border-bottom: 1px solid var(--krds-border-strong);
556
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.06em;
557
+ color: var(--krds-text-subtle); text-align: center;
558
+ }
559
+
560
+ .cover__dv {
561
+ display: block; padding: var(--s2) var(--s3);
562
+ font-size: var(--t-sm); font-weight: var(--w-bold); text-align: center;
563
+ }
564
+
565
+ /* 로고를 받았을 때. 비트맵이든 SVG 든 높이만 묶고 폭은 원본비로 둔다 */
566
+ .cover__logo { flex: 0 0 auto; max-height: 52px; max-width: 40%; width: auto; height: auto; }
567
+
568
+ .cover__org {
569
+ flex: 0 1 auto; min-width: 0; margin: 0; text-align: right;
570
+ border-bottom: var(--rule-mid); border-bottom-color: var(--krds-primary-deep);
571
+ padding-bottom: var(--s2);
572
+ }
573
+
574
+ .cover__ork {
575
+ display: block; margin-bottom: var(--s1);
576
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.14em;
577
+ color: var(--krds-text-muted);
578
+ }
579
+
580
+ .cover__orn {
581
+ display: block;
582
+ font-size: var(--t-md); line-height: var(--lh-md); font-weight: var(--w-bold);
583
+ letter-spacing: -0.02em; color: var(--krds-primary-deep);
584
+ }
585
+
586
+ @media (max-width: 560px) {
587
+ .cover__top { flex-direction: column; gap: var(--s4); }
588
+ .cover__org { text-align: left; }
589
+ }
590
+
591
+ .cover__key { align-self: start; padding: var(--pad-lg) var(--pad-lg) 0; }
592
+
593
+ .cover__kicker {
594
+ margin: 0 0 var(--s4); font-size: var(--t-sm); font-weight: var(--w-bold);
595
+ letter-spacing: 0.04em; color: var(--krds-text-muted);
596
+ }
597
+
598
+ /* 1행 굵은 남색 + 2행 가는 글자 — 관보 대제목 문법 */
599
+ .cover__title { margin: 0; line-height: 1.16; }
600
+
601
+ .cover__t1 {
602
+ display: block;
603
+ font-size: var(--t-d2); line-height: var(--lh-d); font-weight: var(--w-bold);
604
+ letter-spacing: -0.035em; color: var(--krds-primary-deep);
605
+ }
606
+
607
+ .cover__t2 {
608
+ display: block; margin-top: 0;
609
+ font-size: var(--t-d1); line-height: var(--lh-d); font-weight: var(--w-light);
610
+ letter-spacing: -0.02em; color: var(--krds-text-subtle);
611
+ }
612
+
613
+ .cover__lead {
614
+ margin: var(--s6) 0 0; max-width: 40ch;
615
+ font-size: var(--t-base); line-height: var(--lh-base); color: var(--krds-text-subtle);
616
+ }
617
+
618
+ .cover__meta {
619
+ display: grid; grid-template-columns: repeat(4, 1fr);
620
+ margin: 0; padding: 0; list-style: none;
621
+ border-top: 1px solid var(--krds-border);
622
+ }
623
+
624
+ @media (max-width: 880px) { .cover__meta { grid-template-columns: 1fr 1fr; } }
625
+ @media (max-width: 520px) { .cover__meta { grid-template-columns: 1fr; } }
626
+
627
+ .cover__meta li { padding: var(--s4) var(--s4); border-right: 1px solid var(--krds-divider); }
628
+ .cover__meta li:last-child { border-right: none; }
629
+
630
+ @media (max-width: 880px) {
631
+ .cover__meta li { border-bottom: 1px solid var(--krds-divider); }
632
+ .cover__meta li:nth-child(2n) { border-right: none; }
633
+ .cover__meta li:nth-last-child(-n + 2) { border-bottom: none; }
634
+ }
635
+
636
+ @media (max-width: 520px) {
637
+ .cover__meta li { border-right: none; }
638
+ .cover__meta li:last-child { border-bottom: none; }
639
+ }
640
+
641
+ .cover__mk { display: block; font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-text-muted); }
642
+ .cover__mv { display: block; font-size: var(--t-base); line-height: var(--lh-base); }
643
+
644
+ /* 하단 발행기관 스트립 — 관보 표지 맨 아래 */
645
+ .cover__issuer {
646
+ display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4);
647
+ margin: 0; padding: var(--s4) var(--pad-lg);
648
+ background: var(--krds-primary-deep); color: #fff;
649
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.01em;
650
+ }
651
+
652
+ .cover__issuer span + span::before {
653
+ content: ""; display: inline-block;
654
+ width: 4px; height: 4px; margin-right: var(--s4); vertical-align: 3px;
655
+ border-radius: 50%; background: rgba(255, 255, 255, 0.55);
656
+ }
657
+
658
+ .cover__issuer em { font-style: normal; margin-left: auto; font-weight: var(--w-body); opacity: 0.82; }
659
+
660
+ /* 시간 축 — 7일이 지나야 나타난다 */
661
+
662
+ /* ══ 5-2. PART 간지 ═══════════════════════════════════════════
663
+ 전면 색 패널 + 사선 해칭 + 반투명 원 무리. 그림 파일은 쓰지 않는다. */
664
+ .pt {
665
+ margin: var(--s16) 0 0;
666
+ scroll-margin-top: calc(var(--topbar) + var(--s4));
667
+ }
668
+
669
+ .pt__panel {
670
+ position: relative; isolation: isolate;
671
+ padding: var(--pad-lg) var(--pad-lg) var(--pad-lg);
672
+ /* 반투명 원 5겹은 웹 히어로 배경이지 관보 간지가 아니다. 사선 해칭 한 겹만 남긴다. */
673
+ background:
674
+ repeating-linear-gradient(135deg, transparent 0 7px, rgba(255, 255, 255, 0.055) 7px 8px),
675
+ var(--pt);
676
+ color: #fff;
677
+ }
678
+
679
+ .pt__label {
680
+ margin: 0; font-size: var(--t-sm); font-weight: var(--w-bold);
681
+ letter-spacing: 0.22em; text-transform: uppercase;
682
+ color: rgba(255, 255, 255, 0.78);
683
+ }
684
+
685
+ .pt__no {
686
+ display: block; margin: 0 0 0;
687
+ font-size: var(--t-d3); font-weight: var(--w-light);
688
+ letter-spacing: 0.06em; line-height: 1;
689
+ color: rgba(255, 255, 255, 0.92);
690
+ }
691
+
692
+ .pt__title {
693
+ margin: var(--s2) 0 0; padding-top: var(--s4);
694
+ border-top: 2px solid rgba(255, 255, 255, 0.55);
695
+ font-size: var(--t-2xl); font-weight: var(--w-bold); line-height: var(--lh-2xl);
696
+ }
697
+
698
+ .pt__lede {
699
+ margin: var(--s2) 0 0; max-width: 34ch;
700
+ font-size: var(--t-base); line-height: var(--lh-base); color: rgba(255, 255, 255, 0.95);
701
+ }
702
+
703
+ .pt__grid {
704
+ display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
705
+ gap: var(--pad-lg);
706
+ margin: var(--pad-md) 0 0;
707
+ }
708
+
709
+ @media (max-width: 780px) { .pt__grid { grid-template-columns: 1fr; gap: var(--s6); } }
710
+
711
+ .pt__list {
712
+ display: grid; gap: var(--s2); align-content: start;
713
+ margin: 0; padding: 0; list-style: none;
714
+ }
715
+
716
+ /* 이 PART 가 답하는 질문 — 각 절 여백 단의 Why 를 그대로 모은 것.
717
+ 간지 오른쪽을 장식으로 채우지 않고 「무엇을 알게 되는가」로 채운다. */
718
+ .pt__ask { align-content: start; }
719
+
720
+ .pt__askk {
721
+ margin: 0 0 var(--s2); padding-bottom: var(--s2);
722
+ border-bottom: 1px solid rgba(255, 255, 255, 0.32);
723
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.06em;
724
+ color: rgba(255, 255, 255, 0.82);
725
+ }
726
+
727
+ .pt__askl { display: grid; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
728
+
729
+ .pt__askl li {
730
+ position: relative; padding-left: var(--s6);
731
+ max-width: 28ch;
732
+ font-size: var(--t-base); line-height: var(--lh-base); color: #fff;
733
+ }
734
+
735
+ /* 간지 원 무리에 뜻을 넣는다 — 빈 원은 장식이지만 표식은 안내다 */
736
+ .pt__icons {
737
+ display: none; /* 관보 간지에 아이콘은 없다. 마크업은 aria-hidden 이라 남겨 둔다 */
738
+ }
739
+
740
+ .pt__ic {
741
+ display: inline-flex; align-items: center; justify-content: center;
742
+ width: clamp(38px, 4.4vw, 50px); height: clamp(38px, 4.4vw, 50px);
743
+ border-radius: 50%;
744
+ border: 1px solid rgba(255, 255, 255, 0.42);
745
+ background: rgba(0, 0, 0, 0.18); /* 흰색을 얹으면 면이 밝아져 흰 획이 죽는다 */
746
+ color: #fff;
747
+ }
748
+
749
+ .pt__ic svg { width: 52%; height: 52%; }
750
+
751
+ @media (max-width: 620px) { .pt__icons { position: static; margin-top: var(--s6); } }
752
+
753
+ .pt__askl li::before {
754
+ content: "?"; position: absolute; left: 0; top: 1px;
755
+ display: inline-flex; align-items: center; justify-content: center;
756
+ width: 15px; height: 15px; border-radius: 50%;
757
+ background: rgba(255, 255, 255, 0.22);
758
+ font-size: var(--t-sm); font-weight: var(--w-bold);
759
+ }
760
+
761
+ .pt__list a {
762
+ display: inline-flex; align-items: baseline; gap: var(--s2);
763
+ font-size: var(--t-base); color: #fff; text-decoration: none;
764
+ }
765
+
766
+ .pt__list b {
767
+ padding: var(--s1) var(--s2); border-radius: var(--r-sm);
768
+ background: rgba(0, 0, 0, 0.26); /* 흰색을 얹으면 면이 밝아져 흰 글자가 죽는다 */
769
+ font-size: var(--t-sm); font-weight: var(--w-bold); white-space: nowrap;
770
+ }
771
+
772
+ .pt__list a:hover span { text-decoration: underline; text-underline-offset: 3px; }
773
+
774
+ /* ══ 6-2. 차례 ════════════════════════════════════════════════
775
+ 관보 CONTENTS. 쪽번호 대신 건수를 오른쪽에 둔다 —
776
+ target-counter() 는 어느 브라우저에서도 안 되고,
777
+ 웹 문서에서 독자에게 쓸모 있는 건 「몇 쪽」이 아니라 「몇 건」이다. */
778
+ .toc {
779
+ margin: var(--s8) 0 0; padding: 0;
780
+ background: var(--krds-canvas);
781
+ }
782
+
783
+ .toc__h {
784
+ display: flex; align-items: baseline; gap: var(--s3);
785
+ margin: 0 var(--pad-md) var(--s1);
786
+ padding-bottom: var(--s3);
787
+ border-bottom: 2px solid var(--krds-border-strong);
788
+ font-size: var(--t-lg); font-weight: var(--w-bold);
789
+ }
790
+
791
+ .toc__en {
792
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.18em;
793
+ color: var(--krds-text-muted);
794
+ }
795
+
796
+ .toc__parts, .toc__list { margin: 0; padding: 0; list-style: none; }
797
+ .toc__part + .toc__part { margin-top: var(--s2); }
798
+
799
+ /* PART 밴드 — 차례에서 세 덩어리를 갈라 놓는다 */
800
+ .toc__band {
801
+ display: flex; align-items: baseline; gap: var(--s3);
802
+ margin: 0 var(--pad-md);
803
+ padding: var(--s3) var(--s4);
804
+ background: var(--pt); color: #fff;
805
+ border-radius: var(--r-sm);
806
+ text-decoration: none;
807
+ }
808
+
809
+ .toc__pk {
810
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.18em;
811
+ color: rgba(255, 255, 255, 0.78);
812
+ }
813
+
814
+ .toc__pn {
815
+ font-size: var(--t-md); font-weight: var(--w-light); letter-spacing: 0.06em;
816
+ color: rgba(255, 255, 255, 0.95);
817
+ }
818
+
819
+ .toc__pt { font-size: var(--t-base); font-weight: var(--w-bold); }
820
+
821
+ .toc__pc {
822
+ margin-left: auto; font-size: var(--t-sm);
823
+ color: rgba(255, 255, 255, 0.82); font-variant-numeric: tabular-nums;
824
+ }
825
+
826
+ .toc__link {
827
+ display: grid; grid-template-columns: auto auto 1fr auto;
828
+ align-items: baseline; gap: var(--s1) var(--s4);
829
+ padding: var(--s4) var(--pad-md);
830
+ border-bottom: 1px solid var(--krds-divider);
831
+ text-decoration: none;
832
+ transition: background 0.15s ease;
833
+ }
834
+
835
+ .toc__part:last-child .toc__row:last-child .toc__link { border-bottom: none; }
836
+ .toc__link:hover { background: var(--ch-surf); }
837
+
838
+ /* 좌측 장 칩 — 장 색 채움 */
839
+ .toc__no {
840
+ grid-row: 1 / 3; align-self: start;
841
+ display: inline-flex; align-items: center;
842
+ min-width: 3.6em; padding: 0 0 0 var(--s2);
843
+ border-left: var(--rule-mid); border-left-color: var(--ch);
844
+ color: var(--ch-deep);
845
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.01em;
846
+ white-space: nowrap;
847
+ }
848
+
849
+ .toc__title {
850
+ grid-column: 2; grid-row: 1;
851
+ font-size: var(--t-base); font-weight: var(--w-bold); line-height: var(--lh-base);
852
+ color: var(--ch-deep);
853
+ }
854
+
855
+ /* 점선 리더 — 제목과 건수를 잇는다. 차례를 차례로 만드는 것 */
856
+ .toc__dots {
857
+ grid-column: 3; grid-row: 1;
858
+ align-self: baseline; min-width: 24px; height: 0;
859
+ border-bottom: 1px dotted var(--krds-border);
860
+ transform: translateY(-4px);
861
+ }
862
+
863
+ /* 하위 항목 — 관보 차례는 절 아래 항목을 개별 행으로 세우고 각각 리더를 단다.
864
+ 한 줄로 이어 붙이면 목록이 아니라 설명문이 된다. */
865
+ .toc__subs {
866
+ margin: 0 0 var(--s3); padding: 0 var(--pad-md) 0
867
+ calc(var(--pad-md) + 3.6em + var(--s4));
868
+ list-style: none;
869
+ }
870
+
871
+ .toc__subs a {
872
+ display: grid; grid-template-columns: 5.4em 1fr;
873
+ align-items: baseline; gap: 0 var(--s2);
874
+ padding: var(--s1) 0;
875
+ color: var(--krds-text-subtle); text-decoration: none;
876
+ font-size: var(--t-sm); line-height: var(--lh-sm);
877
+ }
878
+
879
+ .toc__subs a:hover span { text-decoration: underline; text-underline-offset: 3px; }
880
+ .toc__subs a:hover { color: var(--ch-deep); }
881
+
882
+ .toc__subs b {
883
+ font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-text-muted);
884
+ font-variant-numeric: tabular-nums; white-space: nowrap;
885
+ }
886
+
887
+ .toc__subs a:hover b { color: var(--ch); }
888
+
889
+ .toc__subs span { min-width: 0; }
890
+
891
+ .toc__d { display: none; }
892
+
893
+ @media (max-width: 560px) {
894
+ .toc__subs { padding-left: calc(var(--pad-md) + var(--s3)); }
895
+ .toc__subs a { grid-template-columns: 4.8em 1fr; }
896
+ }
897
+
898
+ .toc__count {
899
+ grid-column: 4; grid-row: 1;
900
+ font-size: var(--t-sm); color: var(--krds-text-subtle);
901
+ font-variant-numeric: tabular-nums; white-space: nowrap;
902
+ }
903
+
904
+ /* 크기를 올리지 않는다 — 「6건」은 한 낱말이다. 숫자만 키우면 낱말 가운데 이음매가 생긴다.
905
+ 강조는 굵기와 색으로 충분하다. */
906
+ .toc__count b { font-weight: var(--w-bold); color: var(--ch-deep); }
907
+
908
+ @media (max-width: 560px) {
909
+ .toc__link { grid-template-columns: auto 1fr auto; }
910
+ .toc__dots { display: none; }
911
+ .toc__count { grid-column: 3; grid-row: 1; }
912
+ .toc__sub { grid-column: 2 / -1; }
913
+ }
914
+
915
+ /* ══ 6-3. 표·그림 캡션 칩 ═════════════════════════════════════
916
+ 관보 문법: 번호 칩 + 굵은 제목이 표 「위」에 온다.
917
+ 번호는 CSS counter 가 아니라 실제 텍스트로 적는다 —
918
+ 생성 콘텐츠는 aria-labelledby 접근명에 안정적으로 들어가지 않는다. */
919
+ .tabnum {
920
+ display: inline-block; margin-right: var(--s2); padding: var(--s1) var(--s2);
921
+ border-radius: var(--r-sm);
922
+ background: var(--krds-border-strong); color: #fff;
923
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.02em;
924
+ font-variant-numeric: tabular-nums; white-space: nowrap;
925
+ vertical-align: 2px;
926
+ }
927
+
928
+ /* ══ 6-1. 제·개정 이력 ═══════════════════════════════════════
929
+ 관보 간행물은 표지 바로 뒤에 이력을 둔다. 회차 문서라는 사실을
930
+ 문서 스스로 밝히는 장치. */
931
+ .hist {
932
+ display: grid; grid-template-columns: auto 1fr;
933
+ gap: 0 var(--pad-md);
934
+ margin: var(--s8) 0 0; padding: 0;
935
+ }
936
+
937
+ .hist__h {
938
+ grid-row: 1 / 3; align-self: start;
939
+ margin: 0; padding-right: var(--pad-md);
940
+ border-right: 2px solid var(--krds-primary-line);
941
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.02em;
942
+ color: var(--krds-primary-deep); white-space: nowrap;
943
+ }
944
+
945
+ .hist__t {
946
+ width: 100%; border-collapse: collapse; font-size: var(--t-sm);
947
+ border-top: var(--rule-edge);
948
+ }
949
+
950
+ .hist__t th {
951
+ padding: var(--s2) var(--s4) var(--s2) 0; text-align: left; white-space: nowrap;
952
+ font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-text-subtle);
953
+ border-bottom: var(--rule-head);
954
+ }
955
+
956
+ .hist__t td {
957
+ padding: var(--s3) var(--s4) var(--s3) 0; text-align: left; vertical-align: top;
958
+ line-height: var(--lh-sm); color: var(--krds-text);
959
+ border-bottom: var(--rule-row);
960
+ }
961
+
962
+ .hist__t tbody tr:last-child td { border-bottom: var(--rule-edge); }
963
+
964
+ /* 표 셀의 max-width 는 표 레이아웃이 무시한다 — 안쪽 인라인 블록으로 잡아야 한다 */
965
+ .hist__c { display: inline-block; max-width: var(--measure); }
966
+
967
+ .hist__n {
968
+ color: var(--krds-text); font-weight: var(--w-bold);
969
+ font-variant-numeric: tabular-nums;
970
+ }
971
+
972
+ @media (max-width: 560px) {
973
+ .hist { grid-template-columns: 1fr; }
974
+ .hist__h { grid-row: auto; padding: 0 0 var(--s2); border-right: none; border-bottom: 2px solid var(--krds-primary-line); margin-bottom: var(--s3); }
975
+ }
976
+
977
+ /* ══ 6-1-2. 이 문서 읽는 법 (UTILIZE GUIDE) ══════════════════
978
+ 관보 가이드의 활용법 면. 좌측 질문 라벨 단 + 우측 ▶ 지시.
979
+ 차례가 「무엇이 있는가」라면 이것은 「어떻게 읽는가」다. */
980
+ .guide {
981
+ margin: var(--s8) 0 0;
982
+ background: var(--krds-canvas);
983
+ }
984
+
985
+ .guide__h {
986
+ display: flex; align-items: baseline; gap: var(--s3);
987
+ margin: 0 0 var(--s2); padding: 0 0 var(--s3);
988
+ border-bottom: var(--rule-mid); border-bottom-color: var(--krds-border-strong);
989
+ font-size: var(--t-md); font-weight: var(--w-bold);
990
+ }
991
+
992
+ .guide__en {
993
+ margin-left: auto; font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.16em;
994
+ color: var(--krds-text-subtle);
995
+ }
996
+
997
+ .guide__l { margin: 0; padding: 0; }
998
+
999
+ .guide__row {
1000
+ display: grid; grid-template-columns: 12.5em minmax(0, 1fr);
1001
+ gap: 0 var(--pad-md);
1002
+ padding: var(--s4) var(--pad-md);
1003
+ border-bottom: 1px solid var(--krds-divider);
1004
+ }
1005
+
1006
+ .guide__l > .guide__row:last-child { border-bottom: none; }
1007
+
1008
+ .guide__q {
1009
+ margin: 0; padding-right: var(--pad-md);
1010
+ border-right: 2px solid var(--krds-border);
1011
+ /* 이 칸은 「질문 문장」이지 어깨 라벨이 아니다. 답(17px)의 표제이므로 답보다 작으면 안 된다. */
1012
+ font-size: var(--t-base); font-weight: var(--w-bold); line-height: var(--lh-base);
1013
+ color: var(--krds-text-subtle);
1014
+ }
1015
+
1016
+ .guide__a { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--s2); }
1017
+
1018
+ .guide__a li {
1019
+ position: relative; padding-left: var(--s4);
1020
+ max-width: var(--measure);
1021
+ font-size: var(--t-base); line-height: var(--lh-base); color: var(--krds-text);
1022
+ }
1023
+
1024
+ /* ▶ 지시 마커 — 관보 활용법 면의 화살표 */
1025
+ .guide__a li::before {
1026
+ content: ""; position: absolute; left: 0; top: 0.62em;
1027
+ width: 0; height: 0;
1028
+ border: 4px solid transparent;
1029
+ border-left: 6px solid var(--krds-primary); border-right-width: 0;
1030
+ }
1031
+
1032
+ @media (max-width: 620px) {
1033
+ .guide__row { grid-template-columns: 1fr; gap: var(--s2); }
1034
+ .guide__q { padding: 0 0 var(--s2); border-right: none; border-bottom: 2px solid var(--krds-border); }
1035
+ }
1036
+
1037
+ /* ══ 6-4. ※ 각주 ═════════════════════════════════════════════
1038
+ 관보 문법: 표·그림 아래에 한정 조건을 ※ 로 단다.
1039
+ 본문에 섞어 쓰면 한정이 주장처럼 읽힌다. */
1040
+ /* ── 문장 한 줄 — 한글 문서는 마침표에서 줄을 바꾼다 ──────────────────────────
1041
+ 문장을 이어 붙인 한글 문단은 기계가 쓴 글처럼 읽힌다. 한글 보고서의 기본은
1042
+ 「한 문장 한 줄」이다.
1043
+
1044
+ 줄만 바꾸면 부족하다 — 실측: 문장의 26%(여백 주석 단은 54%)가 글줄 폭을 넘어 접힌다.
1045
+ 접히면 둘째 줄과 다음 문장의 첫 줄이 같은 자리에서 시작해 구별할 수 없다.
1046
+ 그래서 문장마다 블록으로 세우고 **이어지는 줄만 1em 내어쓴다** — 한 문장이 한 덩어리다.
1047
+
1048
+ text-indent 의 each-line 은 쓰지 않는다. Chrome 은 CSS.supports 에 true 를
1049
+ 돌려주고 계산값도 `-17px each-line` 으로 보여 주면서 **렌더에서는 무시한다**(실측). */
1050
+ .sn { display: block; padding-left: 1em; text-indent: -1em; }
1051
+
1052
+ .note {
1053
+ position: relative;
1054
+ margin: var(--s3) 0 0; padding-left: 1.5em;
1055
+ max-width: calc(var(--measure) + 1.5em);
1056
+ font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--krds-text-subtle);
1057
+ }
1058
+
1059
+ /* flex 로 하면 안의 <a> 가 별도 flex 항목이 되어 문장이 토막 난다.
1060
+ ※ 는 행잉 인덴트로 매단다 — 관보 각주도 이 방식이다. */
1061
+ .note::before {
1062
+ content: "\203B"; position: absolute; left: 0; top: 0;
1063
+ color: var(--krds-text-muted); font-weight: var(--w-bold);
1064
+ }
1065
+
1066
+ .note + .note { margin-top: var(--s1); }
1067
+ .note b, .figcap b { white-space: nowrap; }
1068
+ .note--in { margin-left: var(--s4); margin-right: var(--s4); }
1069
+
1070
+ /* ══ 6-5. 확인 강도 표식 ══════════════════════════════════════
1071
+ ●실기기 ◐시뮬레이터 ○산출물 —미확인.
1072
+ 본문의 `.tag--live`(초록) `.tag--data`(파랑) `.tag--soon`(회색 파선)과
1073
+ 같은 색을 쓴다 — 표 3-1 과 표 3-2 가 같은 말을 하게 하려는 것. */
1074
+ .dot {
1075
+ display: inline-block; flex: 0 0 auto;
1076
+ width: 13px; height: 13px; margin-right: var(--s2);
1077
+ border-radius: 50%; vertical-align: -1px;
1078
+ border: 2px solid currentColor;
1079
+ }
1080
+
1081
+ .dot--full { background: currentColor; color: var(--krds-success); }
1082
+ .dot--half {
1083
+ color: var(--krds-info);
1084
+ background: linear-gradient(90deg, currentColor 0 50%, transparent 50% 100%);
1085
+ }
1086
+ .dot--open { color: var(--krds-border-strong); background: transparent; }
1087
+ .dot--none {
1088
+ width: 12px; height: 0; margin-right: var(--s2);
1089
+ border: none; border-top: 2px solid currentColor; border-radius: 0;
1090
+ color: var(--krds-text-muted); vertical-align: 4px;
1091
+ }
1092
+
1093
+ /* th 안에 들어가면 굵기 700 을 물려받는다. 같은 표식이 자리에 따라 두 굵기로 보이면
1094
+ 표식이 아니라 강조로 읽힌다 — 굵기를 못 박는다. */
1095
+ .lvl { display: inline-flex; align-items: center; white-space: nowrap; font-weight: var(--w-body); }
1096
+ .lvl--full { color: var(--krds-success-deep); }
1097
+ .lvl--half { color: #0a5d9e; }
1098
+ .lvl--open { color: var(--krds-text-subtle); }
1099
+ .lvl--none { color: var(--krds-text-muted); }
1100
+ .lvl .dot { margin-right: var(--s2); }
1101
+
1102
+ /* 표 밴드 안의 범례 */
1103
+ .legend {
1104
+ display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s4);
1105
+ margin-left: auto; font-size: var(--t-sm); font-weight: var(--w-body);
1106
+ }
1107
+
1108
+ .legend__i { display: inline-flex; align-items: center; color: rgba(255, 255, 255, 0.94); }
1109
+ .legend__i .dot { width: 11px; height: 11px; margin-right: var(--s2); border-width: 2px; }
1110
+ .legend .dot--full { color: #fff; }
1111
+ .legend .dot--half { color: #fff; }
1112
+ .legend .dot--open { color: rgba(255, 255, 255, 0.85); }
1113
+ .legend .dot--none { color: rgba(255, 255, 255, 0.72); }
1114
+ .legend .dot--none { width: 10px; margin-right: var(--s2); }
1115
+
1116
+ @media (max-width: 720px) { .legend { margin-left: 0; width: 100%; } }
1117
+
1118
+ /* ══ 7. 요약면 ════════════════════════════════════════════════ */
1119
+ .sum {
1120
+ margin: var(--s8) 0 0;
1121
+ background: var(--krds-canvas);
1122
+ }
1123
+
1124
+ .sum__h {
1125
+ display: flex; align-items: baseline; gap: var(--s3);
1126
+ margin: 0 0 var(--s2); padding: 0 0 var(--s3);
1127
+ border-bottom: var(--rule-mid); border-bottom-color: var(--krds-border-strong);
1128
+ color: var(--krds-text);
1129
+ font-size: var(--t-md); font-weight: var(--w-bold);
1130
+ }
1131
+
1132
+ .sum__h span {
1133
+ margin-left: auto; font-size: var(--t-sm); font-weight: var(--w-body);
1134
+ color: var(--krds-text-subtle); font-variant-numeric: tabular-nums;
1135
+ }
1136
+
1137
+ /* 일곱 건의 상태 분포 — 숫자만으로는 비율이 안 잡힌다 */
1138
+ .sum__bar {
1139
+ display: flex; margin: var(--s4) 0 0;
1140
+ border-top: var(--rule-thin); border-top-color: var(--krds-border);
1141
+ border-bottom: var(--rule-thin); border-bottom-color: var(--krds-border);
1142
+ }
1143
+
1144
+ .sum__seg {
1145
+ display: flex; align-items: center; gap: var(--s2);
1146
+ width: var(--w); min-width: 0; padding: var(--s3) var(--s4);
1147
+ font-size: var(--t-sm); white-space: nowrap; overflow: hidden;
1148
+ }
1149
+
1150
+ .sum__seg b { font-size: var(--t-md); font-variant-numeric: tabular-nums; }
1151
+
1152
+ .sum__seg--done { background: var(--krds-surface); color: var(--krds-text-subtle); }
1153
+ .sum__seg--wait {
1154
+ background: var(--krds-warning-surface); color: var(--krds-warning-text);
1155
+ border-left: 3px solid var(--krds-warning); /* 두 구간의 실제 경계다 */
1156
+ }
1157
+
1158
+ .sum .note { margin: var(--s3) 0 var(--s4); }
1159
+
1160
+ /* ══ 7-2. 수치 세 칸 — 첫 칸이 독자 몫 ═══════════════════════ */
1161
+ .tally {
1162
+ display: grid; grid-template-columns: repeat(3, 1fr);
1163
+ margin: var(--s4) 0 0; padding: 0; list-style: none;
1164
+ border-top: var(--rule-head); border-bottom: var(--rule-edge);
1165
+ }
1166
+
1167
+ @media (max-width: 720px) { .tally { grid-template-columns: 1fr; } }
1168
+
1169
+ .tally__cell {
1170
+ display: flex; flex-direction: column;
1171
+ padding: var(--s6) var(--s6) var(--s4); border-right: 1px solid var(--krds-border);
1172
+ }
1173
+
1174
+ .tally__cell:last-child { border-right: none; }
1175
+
1176
+ @media (max-width: 720px) {
1177
+ .tally__cell { border-right: none; border-bottom: 1px solid var(--krds-border); }
1178
+ .tally__cell:last-child { border-bottom: none; }
1179
+ }
1180
+
1181
+ .tally__cell--you {
1182
+ background: var(--krds-primary-surface);
1183
+ transition: background 0.3s ease;
1184
+ }
1185
+
1186
+ /* 진행 상태 축 — 다 끝나면 강조를 거둔다 */
1187
+ .tally__cell--you.is-clearedall { background: var(--krds-success-surface); }
1188
+
1189
+ .tally__n {
1190
+ margin: 0; font-size: var(--t-2xl); font-weight: var(--w-bold); line-height: var(--lh-2xl);
1191
+ letter-spacing: -0.03em; font-variant-numeric: tabular-nums;
1192
+ }
1193
+
1194
+ /* 자식 결합자여야 한다 — 자손이면 .roll 안의 .roll__d 까지 17px 로 줄어든다 */
1195
+ .tally__n > span:not(.roll) { margin-left: var(--s1); font-size: var(--t-base); font-weight: var(--w-body); letter-spacing: 0; }
1196
+
1197
+ .tally__cell--you .tally__n { color: var(--krds-primary-deep); }
1198
+ .tally__cell--you.is-clearedall .tally__n { color: var(--krds-success-deep); }
1199
+
1200
+ .tally__l { margin: var(--s2) 0 0; font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--krds-text-muted); }
1201
+ .tally__cell--you .tally__l { color: var(--krds-primary-hover); font-weight: var(--w-bold); }
1202
+ .tally__cell--you.is-clearedall .tally__l { color: var(--krds-success-deep); }
1203
+
1204
+ .tally__go {
1205
+ margin-top: var(--s3); align-self: flex-start;
1206
+ font-size: var(--t-sm); font-weight: var(--w-bold);
1207
+ color: var(--krds-primary-hover);
1208
+ text-decoration: underline; text-underline-offset: 4px;
1209
+ }
1210
+
1211
+ .tally__go::after { content: " →"; }
1212
+
1213
+ /* 숫자 롤 [Key-path B-3] */
1214
+
1215
+ /* ══ 8. 절 — 머리는 간지다 ═══════════════════════════════════
1216
+ PDF 는 간지(전면 파스텔)와 절 밴드를 둘 다 쓴다. 한 장 안에 절이
1217
+ 여럿이라서다. 이 문서는 절 = 장이므로 하나로 합친다.
1218
+ 장 색은 [data-chapter] 가 --ch / --ch-deep / --ch-surf / --ch-line 으로 준다. */
1219
+ .part {
1220
+ margin-top: var(--s16);
1221
+ scroll-margin-top: calc(var(--topbar) + var(--rail) + var(--s4));
1222
+ }
1223
+
1224
+ .part__head {
1225
+ display: flex; align-items: stretch; gap: var(--pad-md);
1226
+ margin-bottom: var(--s8);
1227
+ padding: var(--pad-md);
1228
+ background: var(--ch-surf);
1229
+ border-left: var(--rule-thick); border-left-color: var(--ch);
1230
+ }
1231
+
1232
+ /* 「제N절」 + 세로 괘선 — 관보 간지의 왼쪽 기둥 */
1233
+ .part__no {
1234
+ flex: 0 0 auto;
1235
+ display: flex; align-items: flex-start;
1236
+ padding-right: var(--pad-md);
1237
+ border-right: 2px solid var(--ch);
1238
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.02em;
1239
+ color: var(--ch-deep); white-space: nowrap;
1240
+ }
1241
+
1242
+ .part__main { flex: 1 1 auto; min-width: 0; }
1243
+
1244
+ .part__line {
1245
+ display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s4);
1246
+ }
1247
+
1248
+ .part__title {
1249
+ flex: 1 1 auto; margin: 0;
1250
+ font-size: var(--t-xl); font-weight: var(--w-bold); line-height: var(--lh-xl);
1251
+ color: var(--ch-deep);
1252
+ }
1253
+
1254
+ .part__count {
1255
+ flex: 0 0 auto;
1256
+ color: var(--ch-deep);
1257
+ font-size: var(--t-sm); font-weight: var(--w-bold);
1258
+ }
1259
+
1260
+ .part__lede {
1261
+ margin: var(--s4) 0 0; max-width: var(--measure);
1262
+ font-size: var(--t-base); line-height: var(--lh-base); color: var(--ch-deep);
1263
+ }
1264
+
1265
+ @media (max-width: 560px) {
1266
+ .part__head { flex-direction: column; gap: var(--s4); }
1267
+ .part__no {
1268
+ padding: 0 0 var(--s3); border-right: none;
1269
+ border-bottom: 2px solid var(--ch);
1270
+ }
1271
+ }
1272
+
1273
+ /* ══ 8-2. 두 단 본문 — 좌측 여백 주석 단 ══════════════════════
1274
+ 이 문서가 「카드 목록」이 아니라 「안내서」로 읽히게 하는 장치.
1275
+ 관보 가이드는 모든 본문 쪽에 ? Why / Key Point / Advice 를 여백에 둔다.
1276
+ 내용은 독자가 실제로 던지는 질문이어야 한다 — 장식이면 넣지 않는 게 낫다.
1277
+
1278
+ 화면에서는 sticky 로 절을 읽는 내내 따라온다(쪽이 없으니 쪽마다 반복할 수 없다).
1279
+ 900px 미만에서는 본문 위 가로 띠로 접힌다. */
1280
+ .part__grid {
1281
+ display: grid; grid-template-columns: var(--marg) minmax(0, 1fr);
1282
+ gap: clamp(var(--s6), 3vw, var(--marg-gap)); align-items: start;
1283
+ }
1284
+
1285
+ .part__body { min-width: 0; }
1286
+
1287
+ .marg { display: grid; gap: var(--s4); position: sticky; top: calc(var(--topbar) + 22px); }
1288
+
1289
+ .marg__b {
1290
+ padding-left: var(--s3);
1291
+ border-left: 3px solid var(--ch-line);
1292
+ }
1293
+
1294
+ .marg__k {
1295
+ display: flex; align-items: center; gap: var(--s2);
1296
+ margin: 0 0 var(--s1);
1297
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.03em;
1298
+ color: var(--ch-deep);
1299
+ }
1300
+
1301
+ /* 배너의 원형 표식(!,i,✓) 문법을 그대로 빌린다 — 같은 뜻엔 같은 장치 */
1302
+ .marg__i {
1303
+ flex: 0 0 auto; display: inline-flex;
1304
+ align-items: center; justify-content: center;
1305
+ width: 18px; height: 18px; border-radius: 50%;
1306
+ background: var(--ch); color: #fff;
1307
+ font-size: var(--t-sm); font-weight: var(--w-bold); line-height: var(--lh-sm);
1308
+ }
1309
+
1310
+ .marg__b--adv .marg__i { background: var(--krds-text-muted); }
1311
+ .marg__b--adv .marg__k { color: var(--krds-text-subtle); }
1312
+ .marg__b--adv { border-left-color: var(--krds-border); }
1313
+
1314
+ .marg__t {
1315
+ margin: 0; font-size: var(--t-sm); line-height: var(--lh-sm);
1316
+ color: var(--krds-text-subtle);
1317
+ }
1318
+
1319
+ .marg__b--why .marg__t { font-weight: var(--w-bold); color: var(--ch-deep); }
1320
+
1321
+ @media (max-width: 900px) {
1322
+ .part__grid { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
1323
+ .marg {
1324
+ position: static;
1325
+ grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
1326
+ gap: var(--s4) var(--s6);
1327
+ padding: var(--s4) 0;
1328
+ border-top: var(--rule-mid); border-top-color: var(--ch);
1329
+ border-bottom: var(--rule-thin); border-bottom-color: var(--krds-divider);
1330
+ }
1331
+ .marg__b { padding-left: var(--s3); }
1332
+ }
1333
+
1334
+ /* ══ 9. 01절 — 독자 몫 ═══════════════════════════════════════ */
1335
+ .asks { display: grid; margin: 0; padding: 0; list-style: none; }
1336
+
1337
+ .ask {
1338
+ padding-top: var(--s4);
1339
+ border-top: var(--rule-mid); border-top-color: var(--krds-primary);
1340
+ background: var(--krds-canvas);
1341
+ scroll-margin-top: calc(var(--topbar) + var(--rail) + var(--s6));
1342
+ transition: border-color 0.3s ease-out;
1343
+ }
1344
+
1345
+ .ask__head {
1346
+ display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s3);
1347
+ padding: 0 0 var(--s3);
1348
+ border-bottom: var(--rule-thin); border-bottom-color: var(--krds-divider);
1349
+ transition: background 0.3s ease-out, border-color 0.3s ease-out;
1350
+ }
1351
+
1352
+ .ask.is-urgent { border-color: var(--krds-danger-line); }
1353
+ .ask.is-urgent .ask__head {
1354
+ margin: calc(var(--s4) * -1) calc(var(--s4) * -1) 0;
1355
+ padding: var(--s3) var(--s4);
1356
+ background: var(--krds-danger-surface);
1357
+ border-bottom-color: var(--krds-danger-line);
1358
+ }
1359
+
1360
+ .ask__no {
1361
+ flex: 0 0 auto; padding: var(--s1) var(--s2); border-radius: var(--r-sm);
1362
+ background: var(--krds-primary); color: #fff;
1363
+ font-size: var(--t-sm); font-weight: var(--w-bold); font-variant-numeric: tabular-nums;
1364
+ }
1365
+
1366
+ .ask.is-urgent .ask__no { background: var(--krds-danger); }
1367
+
1368
+ .ask__title {
1369
+ flex: 1 1 240px; margin: 0;
1370
+ font-size: var(--t-md); font-weight: var(--w-bold); line-height: var(--lh-md);
1371
+ }
1372
+
1373
+ .ask__flag {
1374
+ flex: 0 0 auto; padding: var(--s1) var(--s2); border-radius: var(--r-sm);
1375
+ background: var(--krds-danger); color: #fff;
1376
+ font-size: var(--t-sm); font-weight: var(--w-bold);
1377
+ }
1378
+
1379
+ .ask__ref {
1380
+ flex: 0 0 auto;
1381
+ color: var(--krds-primary-hover);
1382
+ font-size: var(--t-sm); font-weight: var(--w-bold); white-space: nowrap;
1383
+ text-decoration: underline; text-underline-offset: 3px;
1384
+ text-decoration-color: var(--krds-primary-line);
1385
+ }
1386
+
1387
+ .ask__ref:hover { text-decoration-color: currentColor; text-decoration-thickness: 2px; }
1388
+
1389
+ /* 「처리함」 컨트롤 — 스크립트가 있을 때만 삽입된다 */
1390
+ .ask__check {
1391
+ flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--s2);
1392
+ margin-left: auto; padding: var(--s1) var(--s3) var(--s1) var(--s2);
1393
+ border: 1px solid var(--krds-border); border-radius: var(--r-ui);
1394
+ background: var(--krds-canvas); color: var(--krds-text-subtle);
1395
+ font-family: inherit; font-size: var(--t-sm); font-weight: var(--w-bold);
1396
+ cursor: pointer;
1397
+ transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
1398
+ }
1399
+
1400
+ .ask__check:hover { border-color: var(--krds-primary); color: var(--krds-primary-hover); }
1401
+
1402
+ .ask__box {
1403
+ width: 17px; height: 17px; border-radius: var(--r-sm);
1404
+ border: 2px solid var(--krds-border-strong);
1405
+ background: var(--krds-canvas);
1406
+ display: inline-flex; align-items: center; justify-content: center;
1407
+ transition: background 0.2s ease, border-color 0.2s ease;
1408
+ }
1409
+
1410
+ .ask__box::after {
1411
+ content: "\2713"; color: #fff; font-size: var(--t-sm); font-weight: var(--w-bold);
1412
+ opacity: 0; transform: scale(0.6);
1413
+ }
1414
+
1415
+ .ask__check[aria-pressed="true"] {
1416
+ background: var(--krds-success-surface);
1417
+ border-color: var(--krds-success);
1418
+ color: var(--krds-success-deep);
1419
+ }
1420
+
1421
+ .ask__check[aria-pressed="true"] .ask__box {
1422
+ background: var(--krds-success); border-color: var(--krds-success);
1423
+ animation: check-pop 0.26s cubic-bezier(0.34, 1.5, 0.64, 1);
1424
+ }
1425
+
1426
+ .ask__check[aria-pressed="true"] .ask__box::after {
1427
+ opacity: 1; transform: scale(1);
1428
+ transition: opacity 0.15s ease-out 0.06s, transform 0.15s ease-out 0.06s;
1429
+ }
1430
+
1431
+ @keyframes check-pop { from { transform: scale(0.6); } to { transform: scale(1); } }
1432
+
1433
+ /* 처리 표시된 카드는 「흐려지는」 것이 아니라 「강조를 내려놓는」 것이다.
1434
+ opacity·grayscale 로 죽이면 글자 대비가 무너진다 — 실측 2.26~3.61 (기준 4.5).
1435
+ 색을 중립으로 내리고 번호 칩만 완료색으로 바꾼다. 글자는 그대로 읽힌다. */
1436
+ .ask.is-cleared {
1437
+ border-color: var(--krds-border);
1438
+ transition: border-color 0.2s ease-in;
1439
+ }
1440
+
1441
+ .ask.is-cleared .ask__head {
1442
+ background: var(--krds-surface);
1443
+ border-bottom-color: var(--krds-border);
1444
+ transition: background 0.2s ease-in, border-color 0.2s ease-in;
1445
+ }
1446
+
1447
+ .ask.is-cleared .ask__no {
1448
+ background: var(--krds-success); color: #fff;
1449
+ transition: background 0.2s ease-in;
1450
+ }
1451
+
1452
+ .ask.is-cleared .ask__title { color: var(--krds-text-subtle); }
1453
+ .ask.is-cleared .ask__flag { background: var(--krds-border-strong); }
1454
+
1455
+ /* 읽으라고 쓴 글은 본문 색으로 조판한다. 보조 회색은 캡션·라벨의 몫이다. */
1456
+ .ask__body {
1457
+ margin: 0; padding: var(--s3) 0 var(--s6);
1458
+ max-width: var(--measure);
1459
+ font-size: var(--t-base); line-height: var(--lh-base);
1460
+ color: var(--krds-text);
1461
+ }
1462
+
1463
+ /* ══ 10. 02절 — 요지 ═════════════════════════════════════════ */
1464
+ .gist {
1465
+ display: grid; margin: 0; padding: 0; list-style: none;
1466
+ border-top: var(--rule-edge); border-bottom: var(--rule-edge);
1467
+ }
1468
+
1469
+ .gist__item { padding: var(--s6) 0; border-bottom: var(--rule-row); }
1470
+ .gist__item:last-child { border-bottom: none; }
1471
+
1472
+ .gist__lead {
1473
+ margin: 0 0 var(--s2); max-width: var(--measure);
1474
+ font-size: var(--t-base); font-weight: var(--w-bold); line-height: var(--lh-base);
1475
+ }
1476
+
1477
+ .gist__body { margin: 0; max-width: var(--measure); font-size: var(--t-base); line-height: var(--lh-base); color: var(--krds-text); }
1478
+
1479
+ /* KRDS Critical 배너 */
1480
+ .urgent {
1481
+ margin: var(--s6) 0 0; padding: var(--s4) var(--s6);
1482
+ background: var(--krds-danger-surface);
1483
+ border-left: var(--rule-thick); border-left-color: var(--krds-danger);
1484
+ }
1485
+
1486
+ .urgent__k { margin: 0 0 var(--s2); font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-danger-text); }
1487
+ .urgent__t { margin: 0; max-width: var(--measure); font-size: var(--t-base); line-height: var(--lh-base); }
1488
+ .urgent strong { color: var(--krds-danger-text); }
1489
+
1490
+ /* ══ 11. 03절 — 일곱 건 한눈에 ═══════════════════════════════ */
1491
+ /* 감싸개는 상자가 아니다 — 가로 스크롤 기능만 남긴다.
1492
+ 구조는 표 자신의 4괘선(위 굵은 줄 / 헤더 아래 / 행 사이 / 맨 아래 굵은 줄)이 만든다. */
1493
+ .board-wrap { overflow-x: auto; }
1494
+
1495
+ .board { width: 100%; min-width: 640px; border-collapse: collapse; font-size: var(--t-sm); }
1496
+
1497
+ /* 관보 캡션: 전폭 색 밴드가 표 「위」에 얹힌다. 칩보다 훨씬 세다. */
1498
+ .board__cap { padding: 0; text-align: left; }
1499
+
1500
+ .board__band {
1501
+ display: flex; align-items: center; gap: var(--s2);
1502
+ padding: var(--s3) var(--s4);
1503
+ background: var(--ch); color: #fff;
1504
+ /* 색 밴드가 「표 위 굵은 줄」을 겸한다 */
1505
+ font-size: var(--t-base); font-weight: var(--w-bold);
1506
+ }
1507
+
1508
+ .board__band .tabnum {
1509
+ margin: 0; background: rgba(0, 0, 0, 0.24); color: #fff;
1510
+ vertical-align: baseline;
1511
+ }
1512
+
1513
+ .board__caphint {
1514
+ display: block; padding: var(--s3) 0; max-width: var(--measure);
1515
+ border-bottom: var(--rule-row);
1516
+ font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--krds-text-subtle);
1517
+ }
1518
+
1519
+ .board thead th {
1520
+ padding: var(--s3) var(--s4); text-align: left;
1521
+ font-size: var(--t-sm); font-weight: var(--w-bold);
1522
+ background: var(--krds-surface); color: var(--krds-text-subtle);
1523
+ border-bottom: var(--rule-head); white-space: nowrap;
1524
+ }
1525
+
1526
+ .board tbody th, .board tbody td {
1527
+ padding: var(--s3) var(--s4); text-align: left; font-weight: var(--w-body);
1528
+ line-height: var(--lh-sm);
1529
+ border-bottom: var(--rule-row);
1530
+ }
1531
+
1532
+ /* 맨 아래 굵은 줄 — 이게 없으면 표가 「표」가 아니라 「목록」으로 읽힌다 */
1533
+ .board tbody tr:last-child th, .board tbody tr:last-child td { border-bottom: var(--rule-edge); }
1534
+
1535
+ /* 행 그룹 — 관보 매트릭스는 왼쪽 열을 병합해 묶는다.
1536
+ 병합 셀은 좁은 화면에서 무너지므로 구분 행으로 옮겨 같은 효과를 낸다. */
1537
+ .board tbody tr.grp th {
1538
+ padding: var(--s2) var(--s4);
1539
+ background: var(--krds-surface-deep); color: var(--krds-text-subtle);
1540
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.02em;
1541
+ border-top: var(--rule-head); border-bottom: var(--rule-head);
1542
+ }
1543
+
1544
+ .board tbody tr.grp:hover { background: none; }
1545
+ .board tbody tr.grp th span { float: right; font-weight: var(--w-body); color: var(--krds-text-muted); }
1546
+ .board tbody tr:hover { background: var(--krds-surface); }
1547
+ .board tbody th { font-weight: var(--w-body); }
1548
+ .board__ref { font-variant-numeric: tabular-nums; white-space: nowrap; }
1549
+
1550
+ @media (max-width: 719px) {
1551
+ .board-wrap { overflow-x: visible; }
1552
+ .board, .board tbody { display: block; min-width: 0; }
1553
+ .board thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
1554
+ .board__cap { display: block; }
1555
+ .board tbody tr {
1556
+ display: grid; grid-template-columns: 1fr auto; align-items: center;
1557
+ gap: var(--s2) var(--s2); padding: var(--s4) 0; border-bottom: var(--rule-row);
1558
+ }
1559
+ .board tbody tr:last-child { border-bottom: var(--rule-edge); }
1560
+ .board tbody th, .board tbody td { display: block; padding: 0; border-bottom: none !important; }
1561
+ .board tbody th { grid-column: 1 / -1; font-weight: var(--w-bold); }
1562
+ .board__ref { grid-column: 2; grid-row: 2 / 4; justify-self: end; }
1563
+
1564
+ /* 매트릭스는 열 이름이 값의 뜻이다 — thead 가 숨으면 라벨을 셀에 붙여야 한다 */
1565
+ .board--mx tbody tr { grid-template-columns: 1fr 1fr; gap: var(--s2); }
1566
+ .board--mx tbody th { grid-column: 1 / -1; }
1567
+ .board--mx tbody td::before {
1568
+ content: attr(data-k); display: block; margin-bottom: var(--s1);
1569
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.03em;
1570
+ color: var(--krds-text-muted);
1571
+ }
1572
+ }
1573
+
1574
+ /* ══ 12. 상태 표식 ════════════════════════════════════════════ */
1575
+ /* 칩(면 + 테두리)이 아니라 기호 + 색 글자다.
1576
+ 표 3-2·부록 2 의 확인 강도 표식(●◐○─)과 같은 체계로 수렴시킨다 —
1577
+ 같은 문서 안에서 같은 뜻을 두 문법으로 말하지 않는다. */
1578
+ .tag {
1579
+ display: inline-flex; align-items: baseline; gap: var(--s1);
1580
+ font-size: var(--t-sm); white-space: nowrap; /* 표 셀의 「값」이다 — .lvl 과 같은 등급 */
1581
+ }
1582
+
1583
+ .tag::before { font-weight: var(--w-body); }
1584
+
1585
+ .tag--done { color: var(--krds-text-subtle); }
1586
+ .tag--done::before { content: "\25A0"; } /* 끝남 */
1587
+
1588
+ .tag--wait { color: var(--krds-warning-text); }
1589
+ .tag--wait::before { content: "\25A1"; } /* 대기 */
1590
+
1591
+ .tag--live { color: var(--krds-success-deep); }
1592
+ .tag--live::before { content: "\25CF"; color: var(--krds-success); } /* 실기기 */
1593
+
1594
+ .tag--data { color: #0a5d9e; }
1595
+ .tag--data::before { content: "\25D0"; color: var(--krds-info); } /* 산출물 */
1596
+
1597
+ .tag--soon { color: var(--krds-text-subtle); font-weight: var(--w-body); }
1598
+ .tag--soon::before { content: "\2014"; color: var(--krds-text-muted); } /* 미확인 */
1599
+
1600
+ /* ══ 13. 04·05절 — 건 필드표 ═════════════════════════════════ */
1601
+ .sheets { display: grid; gap: var(--s8); }
1602
+
1603
+ /* 건은 카드가 아니라 「제목 + 표」다. 상자를 없애고 표 4괘선이 구조를 맡는다. */
1604
+ .sheet {
1605
+ scroll-margin-top: calc(var(--topbar) + var(--rail) + var(--s6));
1606
+ }
1607
+
1608
+ .sheet__head {
1609
+ display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s3);
1610
+ padding: 0 0 var(--s3);
1611
+ border-bottom: var(--rule-edge); /* 표 위 굵은 줄 */
1612
+ }
1613
+
1614
+ /* 건 번호는 그 절의 장 색을 단다 — 본문에서도 장이 어디인지 읽힌다 */
1615
+ .sheet__no {
1616
+ flex: 0 0 auto; padding: var(--s1) var(--s2); border-radius: var(--r-sm);
1617
+ background: var(--ch, var(--krds-border-strong)); color: #fff;
1618
+ font-size: var(--t-sm); font-weight: var(--w-bold); font-variant-numeric: tabular-nums;
1619
+ }
1620
+
1621
+ .sheet__title { flex: 1 1 240px; margin: 0; font-size: var(--t-md); font-weight: var(--w-bold); line-height: var(--lh-md); }
1622
+
1623
+ .sheet__grid { width: 100%; border-collapse: collapse; }
1624
+
1625
+ .sheet__grid th, .sheet__grid td {
1626
+ padding: var(--s3) var(--s4); text-align: left; vertical-align: top;
1627
+ border-bottom: var(--rule-row);
1628
+ }
1629
+
1630
+ .sheet__grid th:first-child { padding-left: 0; }
1631
+ .sheet__grid td:last-child { padding-right: 0; }
1632
+
1633
+ /* 맨 아래 굵은 줄 */
1634
+ .sheet__grid tr:last-child th, .sheet__grid tr:last-child td { border-bottom: var(--rule-edge); }
1635
+
1636
+ .sheet__grid th {
1637
+ width: 8.5em; min-width: 96px;
1638
+ font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-text-subtle);
1639
+ border-right: var(--rule-row); white-space: nowrap; /* 라벨-값 양식표의 열 구분선 */
1640
+ }
1641
+
1642
+ .sheet__grid td p { margin: 0; max-width: var(--measure); font-size: var(--t-base); line-height: var(--lh-base); color: var(--krds-text); }
1643
+
1644
+ /* 「미결」은 앞의 네 행과 종류가 다른 행이다 — 앞은 기술(記述), 이건 요구다.
1645
+ inset box-shadow 로 띠를 그리거나 한쪽 보더 색만 땜질하지 않는다.
1646
+ 성격이 다른 행은 실제 가로 괘선으로 가른다(관보 표의 기본 문법). */
1647
+ .sheet__grid tr.open > * {
1648
+ background: var(--krds-warning-surface);
1649
+ border-top: var(--rule-mid); border-top-color: var(--krds-warning);
1650
+ }
1651
+
1652
+ .sheet__grid tr.open th { color: var(--krds-warning-text); }
1653
+
1654
+ @media (max-width: 680px) {
1655
+ .sheet__grid, .sheet__grid tbody, .sheet__grid tr,
1656
+ .sheet__grid th, .sheet__grid td { display: block; width: auto; }
1657
+ .sheet__grid th { padding: var(--s3) 0 0; border-right: none; border-bottom: none; }
1658
+ .sheet__grid tr.open > * { border-top: none; }
1659
+ .sheet__grid tr.open th { border-top: var(--rule-mid); border-top-color: var(--krds-warning); }
1660
+ .sheet__grid td { padding: var(--s1) 0 var(--s3); }
1661
+ .sheet__grid tr:last-child td { border-bottom: var(--rule-edge); }
1662
+ }
1663
+
1664
+ /* ══ 13-2. 의존 흐름도 ═══════════════════════════════════════
1665
+ 「서버가 할 일 → 앱은 이미 준비됨 → 그러면 이렇게 된다」.
1666
+ 글로 세 번 반복해 설명하던 것을 한 번에 보이게 한다. */
1667
+ .figcap {
1668
+ margin: 0 0 var(--s2); max-width: var(--measure);
1669
+ font-size: var(--t-base); font-weight: var(--w-bold); line-height: var(--lh-base); color: var(--krds-text);
1670
+ }
1671
+
1672
+ .fignum {
1673
+ display: inline; margin-right: var(--s2);
1674
+ /* 「그림 5-1」은 「표 3-1」(.tabnum)과 같은 역할 — 캡션 앞머리 번호.
1675
+ 크기를 적지 않으면 캡션(17px)을 상속해 표 번호(14px)와 어긋난다. */
1676
+ font-size: var(--t-sm);
1677
+ color: var(--krds-text);
1678
+ font-weight: var(--w-bold); letter-spacing: 0.02em;
1679
+ font-variant-numeric: tabular-nums; white-space: nowrap;
1680
+ }
1681
+
1682
+ .flow { margin: 0; }
1683
+
1684
+ .flow__wrap {
1685
+ border-top: var(--rule-edge);
1686
+ overflow-x: auto; overflow-y: hidden;
1687
+ }
1688
+
1689
+ .flow__head, .flow__row {
1690
+ display: grid;
1691
+ grid-template-columns: 4.6em minmax(180px, 1fr) minmax(170px, 0.92fr) minmax(180px, 1.05fr);
1692
+ min-width: 660px;
1693
+ }
1694
+
1695
+ .flow__head {
1696
+ background: var(--krds-surface);
1697
+ border-bottom: 1px solid var(--krds-border);
1698
+ }
1699
+
1700
+ .flow__hk {
1701
+ padding: var(--s2) var(--s4);
1702
+ border-left: 1px solid var(--krds-divider);
1703
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.02em;
1704
+ color: var(--krds-text-subtle); white-space: nowrap;
1705
+ }
1706
+
1707
+ .flow__hk:first-child { border-left: none; }
1708
+ .flow__hk--out { color: var(--ch-deep); }
1709
+
1710
+ .flow__rows { margin: 0; padding: 0; list-style: none; }
1711
+ .flow__row { border-bottom: 1px solid var(--krds-divider); }
1712
+ .flow__row:last-child { border-bottom: none; }
1713
+
1714
+ .flow__no {
1715
+ display: flex; align-items: center; justify-content: center;
1716
+ padding: var(--s4) var(--s2);
1717
+ background: var(--ch-surf); color: var(--ch-deep);
1718
+ font-size: var(--t-sm); font-weight: var(--w-bold); font-variant-numeric: tabular-nums;
1719
+ }
1720
+
1721
+ .flow__c {
1722
+ position: relative;
1723
+ padding: var(--s4) var(--s4);
1724
+ border-left: 1px solid var(--krds-divider);
1725
+ font-size: var(--t-sm); line-height: var(--lh-sm);
1726
+ }
1727
+
1728
+ /* 단계 사이 화살표 */
1729
+ .flow__c--srv::after, .flow__c--app::after {
1730
+ content: ""; position: absolute; right: -1px; top: 50%; z-index: 2;
1731
+ transform: translate(50%, -50%);
1732
+ width: 0; height: 0;
1733
+ border: 6px solid transparent;
1734
+ border-left: 8px solid var(--ch); border-right-width: 0;
1735
+ }
1736
+
1737
+ .flow__c--srv { background: var(--krds-warning-surface); color: var(--krds-warning-text); font-weight: var(--w-bold); }
1738
+ .flow__c--app { color: var(--krds-text-subtle); }
1739
+ .flow__c--out { color: var(--krds-text); }
1740
+
1741
+ .flow__c small {
1742
+ display: block; margin-top: var(--s1);
1743
+ font-size: var(--t-sm); font-weight: var(--w-body); line-height: var(--lh-sm); color: var(--krds-text-subtle);
1744
+ }
1745
+
1746
+ /* 경로·기술 문자열은 본문 활자로 읽히면 안 된다 — 끊어 읽을 자리도 다르다 */
1747
+ .path {
1748
+ padding: 0 var(--s1);
1749
+ background: rgba(30, 33, 36, 0.07);
1750
+ font-family: ui-monospace, SFMono-Regular, Menlo, "Consolas", monospace;
1751
+ font-size: var(--t-sm); overflow-wrap: anywhere;
1752
+ color: var(--krds-text);
1753
+ }
1754
+
1755
+ /* 좁은 화면: 가로 3단을 세로 3단으로 접는다.
1756
+ .flow__c 는 <span> 이므로 반드시 다시 블록화해야 한다 —
1757
+ grid 가 풀리면 인라인으로 되돌아가 서로 겹친다. */
1758
+ @media (max-width: 700px) {
1759
+ .flow__wrap { overflow-x: visible; border: none; }
1760
+ .flow__head { display: none; }
1761
+
1762
+ .flow__row {
1763
+ display: block; min-width: 0;
1764
+ padding: var(--s4) 0 var(--s6);
1765
+ border-bottom: 1px solid var(--krds-divider);
1766
+ }
1767
+
1768
+ .flow__no {
1769
+ display: block; padding: 0 0 var(--s3);
1770
+ background: none; text-align: left; font-size: var(--t-sm);
1771
+ }
1772
+
1773
+ .flow__c {
1774
+ display: block; position: relative;
1775
+ margin: 0 0 var(--s6); padding: var(--s2) 0 var(--s2) var(--s3);
1776
+ border-left: var(--rule-mid); border-left-color: var(--krds-border);
1777
+ }
1778
+
1779
+ .flow__c::before {
1780
+ content: attr(data-k); display: block; margin-bottom: var(--s1);
1781
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.04em;
1782
+ color: var(--krds-text-muted);
1783
+ }
1784
+
1785
+ .flow__c--srv { border-left-color: var(--krds-warning); }
1786
+ .flow__c--srv::before { color: var(--krds-warning-text); }
1787
+ .flow__c--out { margin-bottom: 0; border-left-color: var(--ch); }
1788
+
1789
+ .flow__c--srv::after, .flow__c--app::after {
1790
+ left: 50%; right: auto; top: auto; bottom: -18px;
1791
+ transform: translateX(-50%);
1792
+ border: 7px solid transparent;
1793
+ border-top: 9px solid var(--ch); border-bottom-width: 0; border-left-width: 7px;
1794
+ }
1795
+ }
1796
+
1797
+ /* ══ 14. 06절 — 확인하지 못한 것 ═════════════════════════════ */
1798
+ .limit {
1799
+ padding: var(--s4) var(--s6);
1800
+ background: var(--krds-warning-surface);
1801
+ border-left: var(--rule-thick); border-left-color: var(--krds-warning);
1802
+ }
1803
+
1804
+ .limit__k { margin: 0 0 var(--s2); font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-warning-text); }
1805
+ .limit__list { display: grid; gap: var(--s2); margin: 0; padding-left: 1.15em; }
1806
+ .limit__list li { max-width: var(--measure); font-size: var(--t-base); line-height: var(--lh-base); }
1807
+
1808
+ /* ══ 14-2. 부록 ═══════════════════════════════════════════════
1809
+ 본문에서 반복 참조되는 기준·환경을 뒤로 뺀다. 본문이 가벼워진다. */
1810
+ .apx { margin: var(--s16) 0 0; }
1811
+
1812
+ .apx__h {
1813
+ display: flex; align-items: baseline; gap: var(--s3);
1814
+ margin: 0 0 var(--s4); padding-bottom: var(--s3);
1815
+ border-bottom: 2px solid var(--krds-border-strong);
1816
+ font-size: var(--t-lg); font-weight: var(--w-bold);
1817
+ }
1818
+
1819
+ .apx__en {
1820
+ font-size: var(--t-sm); font-weight: var(--w-bold); letter-spacing: 0.16em;
1821
+ color: var(--krds-text-muted);
1822
+ }
1823
+
1824
+ .apx__b { margin: 0 0 var(--s6); }
1825
+ .apx__b:last-child { margin-bottom: 0; }
1826
+
1827
+ .apx__t {
1828
+ display: flex; align-items: baseline; gap: var(--s2);
1829
+ margin: 0 0 var(--s2);
1830
+ font-size: var(--t-md); font-weight: var(--w-bold); color: var(--krds-text);
1831
+ }
1832
+
1833
+ .apx__no {
1834
+ color: var(--krds-text);
1835
+ font-weight: var(--w-bold); white-space: nowrap;
1836
+ }
1837
+
1838
+ .apx__g {
1839
+ width: 100%; border-collapse: collapse; font-size: var(--t-sm);
1840
+ border-top: var(--rule-edge);
1841
+ }
1842
+
1843
+ .apx__g th, .apx__g td {
1844
+ padding: var(--s3) var(--s4); text-align: left; vertical-align: top;
1845
+ line-height: var(--lh-sm);
1846
+ border-bottom: var(--rule-row);
1847
+ }
1848
+
1849
+ .apx__g th:first-child { padding-left: 0; }
1850
+ .apx__g td:last-child { padding-right: 0; }
1851
+ .apx__g tr:last-child th, .apx__g tr:last-child td { border-bottom: var(--rule-edge); }
1852
+
1853
+ /* 면 대신 굵은 글자 + 세로선 — .sheet__grid 와 같은 양식표 문법 */
1854
+ .apx__g th {
1855
+ width: 12em; min-width: 130px; font-weight: var(--w-bold);
1856
+ color: var(--krds-text-subtle);
1857
+ border-right: var(--rule-row);
1858
+ }
1859
+
1860
+ .apx__g td b { display: block; margin-bottom: 0; }
1861
+
1862
+ /* small 은 셀 안의 블록이므로 max-width 가 듣는다 (셀 자체는 표 레이아웃이 무시) */
1863
+ .apx__g td small {
1864
+ display: block; max-width: var(--measure); margin-top: var(--s1);
1865
+ color: var(--krds-text-subtle); font-size: var(--t-sm); line-height: var(--lh-sm);
1866
+ }
1867
+
1868
+ /* 표 셀의 max-width 는 표 레이아웃이 무시한다 — 표 전체를 잡아야 글줄이 잡힌다. */
1869
+ .apx__wrap { max-width: 720px; } /* 라벨 열 12em + 셀 여백 + 본문 43자 */
1870
+
1871
+ @media (max-width: 620px) {
1872
+ .apx__g, .apx__g tbody, .apx__g tr, .apx__g th, .apx__g td { display: block; width: auto; }
1873
+ .apx__g th { border-right: none; border-bottom: none; min-width: 0; padding-bottom: 0; }
1874
+ .apx__g td { padding-top: var(--s2); }
1875
+ }
1876
+
1877
+ /* ══ 15. 판권지 — 관보식으로 문서를 닫는다 ═══════════════════ */
1878
+ .eof { margin-top: var(--s16); }
1879
+
1880
+ .colophon {
1881
+ padding: var(--s6) 0;
1882
+ border-top: var(--rule-thick); border-top-color: var(--krds-primary-deep);
1883
+ border-bottom: var(--rule-thin); border-bottom-color: var(--krds-border);
1884
+ background: var(--krds-canvas);
1885
+ }
1886
+
1887
+ .colophon__t {
1888
+ margin: 0 0 var(--s1); font-size: var(--t-lg); font-weight: var(--w-bold);
1889
+ color: var(--krds-primary-deep);
1890
+ }
1891
+
1892
+ .colophon__sub {
1893
+ margin: 0 0 var(--s4); padding-bottom: var(--s4); max-width: var(--measure);
1894
+ border-bottom: 1px solid var(--krds-divider);
1895
+ font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--krds-text-subtle);
1896
+ }
1897
+
1898
+ .colophon__grid { display: grid; gap: 0; margin: 0; }
1899
+
1900
+ .colophon__grid > div {
1901
+ display: grid; grid-template-columns: 6.5em 1fr;
1902
+ gap: var(--s3); padding: var(--s2) 0;
1903
+ border-bottom: 1px solid var(--krds-divider);
1904
+ }
1905
+
1906
+ .colophon__grid > div:last-of-type { border-bottom: none; }
1907
+
1908
+ .colophon__grid dt {
1909
+ font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--krds-text-muted);
1910
+ }
1911
+
1912
+ .colophon__grid dd { margin: 0; max-width: var(--measure); font-size: var(--t-sm); line-height: var(--lh-sm); }
1913
+
1914
+ .colophon__mark {
1915
+ display: flex; align-items: center; gap: var(--s3);
1916
+ margin: var(--s4) 0 0; padding-top: var(--s4);
1917
+ border-top: 1px solid var(--krds-border);
1918
+ font-size: var(--t-sm); color: var(--krds-text-muted);
1919
+ }
1920
+
1921
+ .colophon__mark b {
1922
+ margin-left: auto; padding: var(--s1) var(--s3);
1923
+ border: 1px solid var(--krds-border-strong); border-radius: var(--r-sm);
1924
+ font-size: var(--t-sm); letter-spacing: 0.04em; color: var(--krds-text-subtle);
1925
+ }
1926
+
1927
+ /* 독자가 실제로 오해할 수 있는 것을 적는다 — 체크 표시는 우리에게 오지 않는다 */
1928
+ .colophon__note {
1929
+ margin: var(--s4) 0 0; max-width: calc(var(--measure) + 32px); padding: var(--s3) var(--s4);
1930
+ background: var(--krds-surface);
1931
+ border-left: 3px solid var(--krds-border-strong);
1932
+
1933
+ font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--krds-text-subtle);
1934
+ }
1935
+
1936
+ .eof__note { margin: var(--s6) 0 0; max-width: var(--measure); font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--krds-text-subtle); }
1937
+
1938
+ /* ══ 16. 진입 모션 ════════════════════════════════════════════ */
1939
+
1940
+ .ask:nth-child(2).is-in, .sheet:nth-child(2).is-in { animation-delay: 0.06s; }
1941
+ .ask:nth-child(3).is-in, .sheet:nth-child(3).is-in { animation-delay: 0.12s; }
1942
+ .ask:nth-child(4).is-in, .sheet:nth-child(4).is-in { animation-delay: 0.18s; }
1943
+ .ask:nth-child(5).is-in { animation-delay: 0.24s; }
1944
+ .ask:nth-child(6).is-in { animation-delay: 0.3s; }
1945
+
1946
+ @keyframes rise { to { opacity: 1; transform: translateY(0); } }
1947
+
1948
+ .ask.is-target, .sheet.is-target {
1949
+ border-color: var(--krds-primary);
1950
+ animation: flash 0.6s ease-out;
1951
+ }
1952
+
1953
+ @keyframes flash {
1954
+ 0% { box-shadow: 0 0 0 0 var(--krds-primary-surface); }
1955
+ 35% { box-shadow: 0 0 0 5px var(--krds-primary-surface); }
1956
+ 100% { box-shadow: 0 0 0 0 var(--krds-primary-surface); }
1957
+ }
1958
+
1959
+ @media (prefers-reduced-motion: reduce) {
1960
+ html { scroll-behavior: auto; }
1961
+
1962
+ *, *::before, *::after {
1963
+ animation-duration: 0.01ms !important;
1964
+ animation-iteration-count: 1 !important;
1965
+ transition-duration: 0.01ms !important;
1966
+ }
1967
+
1968
+
1969
+ .ask__check[aria-pressed="true"] .ask__box::after { opacity: 1; transform: scale(1); }
1970
+ }
1971
+
1972
+ /* ══ 17. 인쇄 = 진짜 페이지 문법 ══════════════════════════════
1973
+ 지원 범위는 실측·스펙 확인분에만 기댄다.
1974
+
1975
+ | 기능 | Chrome 131+ | Firefox | Safari |
1976
+ | @page size/margin | O | O | O 18.2 |
1977
+ | @page 마진 박스 + 쪽번호 | O | X 856371| X |
1978
+ | thead 쪽 넘김 반복 | O | O | X 17205|
1979
+ | break-after: avoid | O | X 1972340| X 294559 (avoid-page 로 보완)
1980
+ | orphans / widows | O | X 137367| O |
1981
+
1982
+ → 배포용 PDF 는 Chrome 131+ 에서 생성한다.
1983
+ 인쇄 대화상자의 「머리글 및 바닥글」은 반드시 체크 해제
1984
+ (안 하면 브라우저 URL·날짜가 아래 푸터와 겹쳐 찍힌다).
1985
+ → Paged.js 는 도입하지 않는다. 추가로 얻는 건 사실상 차례 쪽번호 하나인데
1986
+ 921KB · 3년 미유지보수 · 런타임 DOM 재조립(레일·진행률·체크와 충돌) 이다. */
1987
+
1988
+ @page {
1989
+ size: A4;
1990
+ margin: 20mm 18mm 18mm;
1991
+
1992
+ /* Chrome 131+ 전용. FF·Safari 는 이 블록을 무시할 뿐 깨지지 않는다 */
1993
+ @bottom-left {
1994
+ content: counter(page);
1995
+ font-family: "Pretendard GOV", sans-serif;
1996
+ font-size: 10pt; font-weight: var(--w-bold); color: #1e2124;
1997
+ }
1998
+ @bottom-right {
1999
+ content: "앱 도메인 전환 1차 보고 · FI-soft";
2000
+ font-family: "Pretendard GOV", sans-serif;
2001
+ font-size: 8.5pt; color: #6d7882;
2002
+ }
2003
+ }
2004
+
2005
+ /* 전면부 로마자 쪽번호(i·ii·iii)는 넣지 않는다.
2006
+ 관보 관례이지만 Chrome 이 `counter-reset: page` 를 무시하므로
2007
+ 전면을 로마자로 돌리면 본문이 1 이 아니라 7 부터 시작해 앞뒤가 어긋난다.
2008
+ (#part-1 로 직접 지목해도 동일. 실측 2026-08-23 · Chrome 151)
2009
+ → 표지만 번호 없이 두고 나머지는 연속 아라비아로 간다. */
2010
+
2011
+ /* 표지에는 쪽번호·러닝 푸터를 찍지 않는다 */
2012
+ @page :first {
2013
+ margin: 0;
2014
+ @bottom-left { content: ""; }
2015
+ @bottom-right { content: ""; }
2016
+ }
2017
+
2018
+ @media print {
2019
+ /* 진행 중인 transition 은 !important 보다 우선하므로 먼저 끈다 */
2020
+ *, *::before, *::after {
2021
+ transition: none !important;
2022
+ animation: none !important;
2023
+ }
2024
+
2025
+ /* 없으면 장 색·태그 배경·간지 면이 전부 백지로 인쇄된다 */
2026
+ html {
2027
+ -webkit-print-color-adjust: exact;
2028
+ print-color-adjust: exact;
2029
+ }
2030
+
2031
+ /* ── 화면 전용 크롬 ──
2032
+ .rail 은 ≥1280px 에서 position:fixed 다. fixed 요소는 Chrome·FF 에서
2033
+ 매 인쇄 페이지에 반복되며 본문을 덮으므로 반드시 지운다. */
2034
+ .topbar, .progress, .rail, .skip, .tally__go, .ask__check, .notice { display: none !important; }
2035
+
2036
+ .doc { max-width: none; padding: 0; }
2037
+
2038
+ /* ── 쪽 나누기: 표지 1쪽 · 차례 1쪽 · 절마다 새 쪽 ── */
2039
+ /* 표지는 한 면을 가득 채운다. @page :first 가 여백 0 이므로 100vh = A4 전체.
2040
+ grid 의 1fr 행(도해)이 늘어나면서 메타·발행처가 아래로 붙는다. */
2041
+ .cover {
2042
+ min-height: 100vh; margin: 0; /* 화면용 margin-top 이 남으면 100vh+26px 가 되어 두 쪽으로 갈라진다 */
2043
+ border: none;
2044
+ break-after: page;
2045
+ padding-bottom: 0;
2046
+ }
2047
+
2048
+ .hist { break-after: page; margin-top: 0; }
2049
+ .toc { break-before: page; break-after: page; padding-top: 0; }
2050
+ .toc__link:hover { background: none; }
2051
+ .guide { break-before: page; break-after: page; }
2052
+ .sum { break-before: page; break-after: page; }
2053
+
2054
+ /* 부록은 판권지 앞, 새 쪽에서 */
2055
+ .apx { break-before: page; margin-top: 0; }
2056
+ .apx__b { break-inside: avoid; }
2057
+
2058
+ /* PART 간지는 한 면을 통째로 쓴다 */
2059
+ .pt { break-before: page; break-after: page; margin-top: 0; }
2060
+ /* 간지도 한 면을 채운다. 인쇄에서 vh 는 「용지 전체」이지 본문 영역이 아니다 —
2061
+ A4 297mm 에서 위아래 여백 38mm 를 빼면 본문은 87.2vh 다. 넘기면 쪽이 하나 더 생긴다. */
2062
+ .pt__panel { min-height: 84vh; }
2063
+
2064
+ .part { break-before: page; margin-top: 0; scroll-margin-top: 0; }
2065
+ .eof { break-before: page; margin-top: 0; }
2066
+
2067
+ /* 여백 주석 단은 인쇄에서도 두 단으로 남는다 (쪽에는 여백이 있다) */
2068
+ .part__grid { display: grid; grid-template-columns: 46mm 1fr; gap: 8mm; }
2069
+ .marg { position: static; display: block; background: none; border: none; padding: 0; }
2070
+ .marg__b { break-inside: avoid; margin-bottom: 7mm; }
2071
+
2072
+ /* break-after: avoid 는 FF·Safari 에서 무효(1972340 / 294559).
2073
+ Safari 는 avoid-page 를 받으므로 둘을 겹쳐 쓴다. FF 는 이 층위를 포기한다. */
2074
+ .part__head, .sheet__head, .ask__head, .toc__h {
2075
+ break-after: avoid;
2076
+ break-after: avoid-page;
2077
+ break-inside: avoid;
2078
+ }
2079
+
2080
+ /* ── 쪽 경계에서 잘리지 않게 ──
2081
+ break-inside 에서 avoid-page 는 Safari 미지원이므로 plain avoid 를 쓴다. */
2082
+ .tally, .ask, .urgent, .limit, .gist__item,
2083
+ .cover__meta, .toc__link, .toc__band, .colophon, .board__band,
2084
+ .sum, .note, .flow__row, .figcap, .pt__askl li {
2085
+ break-inside: avoid;
2086
+ box-shadow: none !important;
2087
+ }
2088
+
2089
+ /* 흐름도는 가로 스크롤 컨테이너다 — 풀지 않으면 인쇄에서 잘린다 */
2090
+ .flow__wrap { overflow: visible; }
2091
+ .flow__head, .flow__row { min-width: 0; }
2092
+ .figcap { break-after: avoid; break-after: avoid-page; }
2093
+ .sum__bar { break-inside: avoid; }
2094
+
2095
+ /* 한 쪽보다 큰 카드를 avoid 로 묶으면 통째로 밀린 뒤 잘려 사라진다.
2096
+ overflow:hidden 은 monolithic 후보이므로(css-break-3 §4.1) 반드시 푼다. */
2097
+ .sheet {
2098
+ break-inside: auto;
2099
+ overflow: visible;
2100
+ box-shadow: none !important;
2101
+ }
2102
+
2103
+ .sheet__grid tr, .board tbody tr { break-inside: avoid; }
2104
+
2105
+ /* 표 헤더 반복. 스크롤 컨테이너를 풀어야 표 분할 자체가 가능하다. */
2106
+ .board-wrap { overflow: visible; }
2107
+ .board { min-width: 0; }
2108
+ .board thead { display: table-header-group; }
2109
+ .board thead th { position: static; }
2110
+ /* 범례가 밴드 안에서 두 줄로 접히면 표 머리가 어긋난다 */
2111
+ .legend { font-size: 8.5pt; gap: var(--s1) var(--s2); }
2112
+ .board tbody tr:hover { background: none; }
2113
+
2114
+ p, li, .sheet__grid td p { orphans: 3; widows: 3; }
2115
+
2116
+ /* ── 모션 잔재 제거 ── */
2117
+
2118
+
2119
+ .ref { text-decoration: none; color: inherit; font-weight: var(--w-bold); }
2120
+ }