{"name":"hamelize","displayName":"하멜라이즈","templates":{"body-about":"{{!\n  서비스 소개 — **이 서비스가 무엇인지 말하는 자리** (2026-09-14 요구).\n\n  **홈페이지와 같은 모양이다.** 자기 주소에 선 채로 설정이 가리키는 문서의 <b>본문만</b>\n  담는다 — 그 문서로 곧장 보내면 제목이 그 문서의 이름이 되어 <i>여기가 어디인가</i>를\n  주소로도 제목으로도 알 수 없다.\n\n  **제목은 자리의 이름이다.** 뷰가 고정해 넘긴다(`nav.*`) — 문서가 무엇으로 불리든 여기\n  서 있는 동안은 서비스 소개이다.\n\n  **제목줄은 피드의 것이다**(갈아타는 상자). 읽고 나서 하는 일은 <i>여기서 어디로 갈까</i>이고\n  이 화면은 어느 피드에도 매여 있지 않다.\n\n  **셋을 한 파일로 합치지 않는다**(사이드바의 잎 여섯과 같은 판단). 지금은 거의 같지만\n  <b>따로 손댈 자리</b>가 서 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n\n<article class=\"content document-body\">\n  {{&body}}\n</article>\n","body-account-add":"{{!\n  계정 추가 — **한 사람 더 들인다** (2026-09-11 요구 · 2026-09-25에 제 화면을 얻었다).\n\n  **로그인 화면과 서는 것이 같다.** 그래도 갈라 두는 까닭은 <b>거는 판단이 다르기\n  때문</b>이다 — 로그인은 들어와 있으면 묻지 않고 이쪽은 들어와 있는 사람의 자리다.\n  ~~한 화면에 깃발을 세웠다~~(`/-/login?add=1`): 그 깃발이 주소를 읽는 자리에서 빠져\n  <b>눌러도 홈으로 갈 뿐</b>이었다(2026-09-25 보고).\n\n  **그림은 로그인과 같은 조각이 진다**(`login-providers`) — 화면이 갈린 것과 마크업이\n  갈리는 것은 다른 말이고, 두 벌을 두면 한쪽만 고쳐진다.\n\n  **머리가 어느 일인지 말한다** — 여기에 `로그인`이 서면 <b>지금 것이 끊긴 줄 안다.</b>\n}}\n{{> body-title}}\n\n{{!\n  **지금 누구인지 고르기 전에 말한다** (2026-09-25 요구).\n\n  **머리가 말한다고 해도 여기서 다시 말한다.** 머리의 그것은 <i>늘 서 있는 것</i>이라\n  읽히지 않고, 여기서 사람이 재는 것은 <b>지금 이 계정과 고를 수단의 관계</b>다 — 바로\n  아래 힌트가 *수단이 다르면 계정도 다르다*고 말하므로, 그 말이 걸릴 자리가 있어야 한다.\n\n  **세션이 없으면 그 줄이 없다**(게스트에게도 이 화면이 선다) — 말할 것이 없을 뿐이고\n  화면은 그대로 선다.\n}}\n{{#session}}\n<p class=\"signed-in\">\n  <span class=\"label\">{{t.account_add.signed_in}}</span>\n  <span class=\"who\">{{#avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"24\" height=\"24\">{{/avatar_url}}{{^avatar_url}}<span class=\"avatar avatar-fallback\" aria-hidden=\"true\">{{> icon-person}}</span>{{/avatar_url}}<span class=\"name\">{{> name-badged}}</span></span>\n</p>\n{{/session}}\n\n{{> login-providers}}\n","body-asset-edit":"{{!\n  에셋의 본문을 고치는 화면 — **문서의 편집기를 그대로 쓴다**\n  (<a href=\"../../../../.claude/milestone-36_asset_layer.md\">36</a> 확정 6).\n\n  **같은 blockdown이므로 같은 편집기다.** 여기서 두 벌을 두면 특수 블록이 한쪽에서만 서는\n  일이 생긴다 — 굽는 자리가 코어에서 하나인 것과 같은 이유다.\n\n  **초안을 남기지 않는다**(`data-editor-id`가 없다). 에셋에는 초안 표가 없고, 그 표를\n  나눠 쓰는 일은 <b>필요를 보고</b> 정한다 — 없는 자리를 흉내 내지 않는다.\n}}\n{{> body-title}}\n\n{{!\n  **제목 밑에 그림이 선다** (2026-09-16 요구).\n\n  적는 글이 <b>그 그림에 대한 것</b>이라 무엇을 보고 쓰는지가 화면에 있어야 한다 — 없으면\n  사람이 창을 하나 더 열어 맞춰 본다. **읽는 화면과 같은 조각**이다.\n}}\n{{> asset-shot}}\n\n<form class=\"compose\" method=\"post\" action=\"{{href}}/-/edit\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"base_seq\" value=\"{{revision_seq}}\">\n\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  <label class=\"document-edit-label\" for=\"asset-source\">{{t.document.source}}</label>\n  <div id=\"asset-source\" class=\"document-editor\" data-editor></div>\n  <input type=\"hidden\" name=\"source\" data-editor-source value=\"{{source}}\">\n\n  <ul class=\"suggestions commands\" data-command-list hidden></ul>\n\n  <div class=\"document-actions\">\n    <button class=\"button is-primary\" type=\"submit\">{{t.document.save_do}}</button>\n    <a class=\"button\" href=\"{{href}}\">{{t.document.cancel_do}}</a>\n  </div>\n</form>\n","body-asset-empty":"{{!\n  이 이름의 파일이 없다 — **빨간 링크가 닿는 자리**\n  (<a href=\"../../../../.claude/milestone-36_asset_layer.md\">36</a> 확정 4).\n\n  **문서와 달리 여기서 만들 수 없다.** 문서는 빈 자리에서 곧바로 세우지만 파일은 <b>올려야\n  생기는 것</b>이라, 만드는 길은 에셋 풀이나 문서를 고치다 여는 탐색기다.\n\n  **올라가는 길은 제목이 진다**(2026-09-16 요구) — 제목 앞의 마디가 풀로 가는 문이므로\n  ~~본문 아래의 단추~~를 따로 두지 않는다: 같은 자리로 가는 길이 둘일 이유가 없다.\n}}\n{{> body-title}}\n\n<p class=\"hint\">{{t.asset.missing}}</p>\n","body-asset-history":"{{!\n  에셋의 판 목록 — **파일을 갈아 끼운 것도 판이다**\n  (<a href=\"../../../../.claude/milestone-36_asset_layer.md\">36</a> 확정 6).\n\n  **문서의 판 목록과 같은 표다.** 견줌은 아직 없다 — 문서 쪽 견줌이 두 층(블록·줄)으로\n  서는 자리라, 그것을 여기로 끌어오는 일은 <b>필요를 보고</b> 한다.\n}}\n{{> body-title}}\n<p><a href=\"{{href}}\">{{t.asset.to_media}}</a></p>\n\n{{#revisions.length}}\n<table class=\"revisions\">\n  <thead>\n    <tr>\n      <th scope=\"col\">{{t.revision.seq}}</th>\n      <th scope=\"col\">{{t.revision.preview}}</th>\n      <th scope=\"col\">{{t.history.when}}</th>\n    </tr>\n  </thead>\n  <tbody>\n    {{#revisions}}\n    <tr>\n      <td>{{seq}}</td>\n      <td>{{#preview}}{{.}}{{/preview}}{{^preview}}<span class=\"hint\">{{t.revision.no_preview}}</span>{{/preview}}</td>\n      <td><time datetime=\"{{created_at}}\">{{when}}</time></td>\n    </tr>\n    {{/revisions}}\n  </tbody>\n</table>\n{{/revisions.length}}\n{{^revisions.length}}\n<p class=\"hint\">{{t.revision.none}}</p>\n{{/revisions.length}}\n","body-asset-move":"{{!\n  에셋의 이름을 바꾸는 화면 — **옛 이름은 넘겨주기로 남는다**\n  (<a href=\"../../../../.claude/milestone-36_asset_layer.md\">36</a> 확정 6).\n\n  **문서의 옮기기와 같은 자리다.** 갈리는 것은 에셋에 <b>하위가 없다</b>는 것뿐이라,\n  따라 움직이는 것도 없다.\n}}\n{{> body-title}}\n\n<form class=\"compose\" method=\"post\" action=\"{{href}}/-/move\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  <label for=\"asset-move-name\">{{t.asset.rename_to}}</label>\n  <input id=\"asset-move-name\" name=\"name\" value=\"{{name}}\" required>\n  <p class=\"hint\">{{t.asset.rename_hint}}</p>\n\n  <div class=\"document-actions\">\n    <button class=\"button is-primary\" type=\"submit\">{{t.asset.rename}}</button>\n    <a class=\"button\" href=\"{{href}}\">{{t.back.cancel}}</a>\n  </div>\n</form>\n","body-asset-one":"{{!\n  에셋 하나를 읽는 화면 — **`/:표지`**\n  (<a href=\"../../../../.claude/milestone-36_asset_layer.md\">36</a> 확정 4·6).\n\n  **문서의 사촌이다.** 그림이 맨 위에 서고 그 아래 <b>제 본문</b>이 선다 — 본문은 문서와\n  같은 blockdown이고 코어가 구운 것을 그대로 세운다.\n\n  **이름에 확장자가 없다**(확정 4). 형식은 사실로서 적히되 주소의 일부가 아니다 — 그래서\n  파일을 갈아 끼워도 이 자리와 이 이름이 그대로 남는다.\n}}\n{{> body-title}}\n\n{{#redirected}}\n{{!\n  **옛 이름으로 왔다** — 이름을 바꿀 때 남긴 자취를 따라왔다. 조용히 따라가면 부른 주소가\n  왜 다른 곳인지 읽는 사람이 알 수 없다(문서의 표지와 같은 규칙).\n}}\n<p class=\"notice document-redirected\">{{t.asset.redirected}} <code>{{from}}</code></p>\n{{/redirected}}\n\n{{!\n  **다루는 판은 창과 한 조각이다** (2026-09-16 요구) — 그림·사실·태그·할 일이 거기 다 있고,\n  <b>같은 일에 같은 그림</b>이다. 권한이 없으면 단추가 서지 않고 태그 칸은 잠긴다.\n}}\n{{> asset-one-panel}}\n\n{{!\n  **태그는 풀로 가는 문이기도 하다** — 위의 칸이 <i>고치는 자리</i>라면 이 줄은 <b>같은\n  갈래의 나머지를 보는 가장 짧은 길</b>이다.\n\n  **해시태그 나열식이다** (2026-09-19 요구). ~~세로로 늘어선 목록이었다~~ — 한 줄에 하나씩\n  서니 태그 셋만 되어도 본문이 그만큼 밀렸고, <b>읽는 자리에서는 태그가 주인공이 아니다.</b>\n  가로로 흐르고 넘치면 접힌다.\n\n  **`.asset-tags`를 쓰지 않는다.** 그 이름은 사이드바의 <b>거르는 도구</b>가 이미 쓰고\n  있고(더하기·이것만·개수) 여기 것은 <b>가는 문</b>이라 하는 일이 다르다 — 한 이름이 두\n  모양으로 살면 하나를 고칠 때 다른 하나가 함께 바뀐다.\n\n  **`#`은 스타일시트가 붙인다** — 글자이지 이름의 일부가 아니다. 마크업에 적으면 태그를\n  복사한 사람이 <b>없는 이름</b>을 손에 쥔다.\n}}\n{{#tags.length}}\n<ul class=\"asset-hashtags\">\n  {{#tags}}\n  <li><a href=\"{{href}}\">{{name}}</a></li>\n  {{/tags}}\n</ul>\n{{/tags.length}}\n\n<article class=\"document-body\">\n  {{&body}}\n</article>\n\n{{^body}}\n<p class=\"hint\">{{t.asset.no_body}}</p>\n{{/body}}\n","body-assets":"{{!\n  **에셋 풀 — 스토리지 전체를 본다** (2026-09-15 요구).\n\n  **설정 탭이 아니라 정규 레이어다.** SNS·문서와 나란한 자리이고, 그래서 사이드바도 제\n  것을 쓴다(`sidebar-assets`) — 태그 목록이 그 레이어의 내용이다.\n\n  **격자는 탐색기와 같은 조각이다**(`asset-gallery`). 갈리는 것은 <b>누른 뒤에 일어나는\n  일</b>뿐이다 — 탐색기에서는 부른 블록에 그림이 앉고, 여기서는 그 그림 하나를 다루는\n  창이 뜬다.\n\n  **찾는 일은 헤더가 진다**(2026-09-15 요구) — 검색은 어느 레이어에서든 같은 자리에 있고,\n  무엇을 뒤질지는 그 안의 탭이 고른다.\n}}\n{{!\n  **제목줄은 다른 화면과 한 벌이다** (2026-09-19 요구).\n\n  ~~풀이 제 제목줄을 지었다~~(`pool-head` · `pool-admin`) — 같은 일을 하는 줄이 두 이름으로\n  살면서 <b>점 셋의 옷이 다른 화면과 갈렸다.</b> 이제 `body-title`이 그 줄을 지고, 풀이\n  더하는 것은 <b>담기는 것</b>뿐이다: 점 셋 안(`actions-pool`)과 그 왼편의 부속\n  (`title-parts-pool`).\n}}\n{{> body-title}}\n\n{{!\n  **찾는 칸은 머리가 진다** (2026-09-16 요구).\n\n  ~~검색 결과의 머리를 그대로 이었다~~(폼 + 탭줄) — 헤더의 드롭다운이 이미 그 일을 하고\n  <b>에셋 레이어에서는 그 탭이 미리 골라져 있으므로</b>, 화면 안에 칸을 또 두면 같은 일에\n  자리가 둘이 된다.\n\n  **탭줄은 찾은 뒤에만 선다.** 그냥 풀을 보는 중에는 갈아탈 <i>결과</i>가 없고, 찾은\n  뒤에는 이 화면이 곧 결과 화면이라 다른 대상으로 건너갈 길이 있어야 한다.\n}}\n{{#query}}{{> body-tabs}}{{/query}}\n\n<div class=\"asset-pool\" data-asset-browser data-asset-admin>\n  {{> asset-gallery}}\n</div>\n\n{{> pager-numbers}}\n","body-blind":"{{> body-title}}\n{{> modal-blind}}\n\n{{!\n  빠져나갈 길은 **페이지에만** 둔다 — 모달에는 자바스크립트가 붙이는 `닫기`가 이미 있다.\n  지우기·넓히기 화면과 같은 판단이다.\n}}\n","body-block":"{{> body-title}}\n{{> modal-block}}\n\n{{!\n  빠져나갈 길은 페이지에만 둔다 — 모달에는 자바스크립트가 붙이는 `닫기`가 이미 있다.\n  `delete`와 같은 규칙이며, 부분은 페이지와 모달이 함께 쓰는 것만 담는다.\n}}\n","body-bot-retire":"{{> body-title}}\n{{> modal-bot-retire}}\n\n","body-bot":"{{> body-title}}\n{{> modal-bot}}\n\n{{!\n  빠져나갈 길은 **페이지에만** 둔다 — 모달에는 자바스크립트가 붙이는 `닫기`가 이미 있다.\n}}\n","body-compose":"{{!\n  **감싸는 자리가 없다** — 카멜라이즈는 `compose` 한 겹을 열고 들어간다(그쪽은 서버가\n  값을 그 이름 아래 넣어 넘긴다). 하멜은 **화면과 모달이 같은 뷰를 쓰므로**(`formView`) 값이\n  통째로 뿌리에 서고, 여기서 한 겹을 열면 <b>모달에서는 그 겹이 없어</b> 같은 파샬이 두\n  모양의 값을 보게 된다 — 폼의 `돌아갈 자리`와 `답글 대상`이 실제로 그렇게 비어 나갔다\n  (2026-09-03에 잡혔다). 나머지 폼 다섯(`body-edit`·`delete`·`widen`·`blind`·`block`)이 이미\n  이 모양이다.\n}}\n{{> body-title}}\n{{> modal-compose}}\n","body-delete":"{{> body-title}}\n{{> modal-delete}}\n\n{{!\n  빠져나갈 길은 **페이지에만** 둔다. 모달에는 자바스크립트가 붙이는 `닫기`가 이미 있고,\n  거기서 이 링크는 \"지금 보고 있는 글로 전체 페이지 이동\"이라 맥락을 버린다 — 취소 수단이\n  둘이면 어느 쪽이 무슨 일을 하는지 알 수 없다.\n}}\n","body-document-access":"{{!\n  문서 속성 — **문서의 성질을 다루는 한 화면**\n  (<a href=\"../../../../.claude/milestone-31_document_tree.md\">31</a> 확정 5·7·10).\n\n  **탭이 넷이다**(2026-09-07 요구). 문서 속성 · 권한 · 내보내기 · 위험.\n\n  가름은 <b>무엇을 다루는가</b>다 — 첫 탭은 *이 문서가 무엇인가*, 둘째는 *누가 무엇을 할 수\n  있는가*, 셋째는 *가져가는 길*, 넷째는 <b>되돌릴 수 없는 일</b>이다. 마지막을 섹션으로\n  두면 앞엣것을 고치다가 스크롤 끝에서 만난다.\n}}\n{{> body-title}}\n{{!\n  **돌아가는 길은 취소다** (2026-09-16 요구) — 이 화면에서 하는 일을 접고 보던 자리로\n  가는 것이라, 전역 규칙의 <b>취소</b>가 그대로 이 자리의 이름이다: 수식어 없는\n  `button`이고, <b>되돌아가는 것이므로 링크</b>다(상태를 바꾸지 않으니 폼도 토큰도 없다).\n\n  **자리는 그대로 둔다**(요구) — 제목 바로 아래가 <i>여기서 나가는 문</i>의 자리다.\n}}\n<p><a class=\"button\" href=\"/{{href_path}}\">{{t.back.to_document}}</a></p>\n\n{{> body-tabs}}\n\n{{#tab_is.properties}}\n{{!\n  **문서의 정보** — 아직 무엇을 세울지 정하지 않았다(2026-09-07 미확정). 지금은 **주소가\n  말해 주지 않는 것들**만 둔다: 언제 생겼고 언제 고쳐졌으며 판이 몇인가.\n}}\n<dl class=\"document-facts\">\n  <dt>{{t.document.fact_path}}</dt><dd><code>{{path}}</code></dd>\n  <dt>{{t.document.fact_depth}}</dt><dd>{{depth}}</dd>\n  <dt>{{t.document.fact_revisions}}</dt><dd>{{revision_seq}}</dd>\n  <dt>{{t.document.fact_created}}</dt><dd><time datetime=\"{{created_at}}\">{{created_when}}</time></dd>\n  <dt>{{t.document.fact_updated}}</dt><dd><time datetime=\"{{updated_at}}\">{{updated_when}}</time></dd>\n</dl>\n\n{{!\n  **잠그기가 문서 속성이다**(2026-09-07 요구). 권한 설정이 아니라 <b>본문 블록 손잡이를\n  켜고 끄는 편의 기능</b>이며 편집자는 누구라도 잠그고 푼다 — 그 성질이 *이 문서가\n  무엇인가*에 가깝지 *누가 무엇을 할 수 있는가*가 아니다.\n}}\n{{#can_edit}}\n<fieldset data-document-id=\"{{document_id}}\">\n  <legend>{{t.document.lock}}</legend>\n  <p class=\"hint\">{{t.document.lock_hint}}</p>\n  <label class=\"checkbox\"><input type=\"checkbox\" data-doc-lock {{#locked}}checked{{/locked}}> {{t.document.locked_label}}</label>\n</fieldset>\n{{/can_edit}}\n{{/tab_is.properties}}\n\n{{#tab_is.access}}\n{{!\n  **권한 — 라벨 둘이다** (2026-09-17 요구 ·\n  <a href=\"../../../../.claude/milestone-38_document_access.md\">38</a> 확정 2).\n\n  ~~필드마다 `상속 중` 칸이 있었다~~(31 확정 5 — 공개설정·열람자·편집자·관리자). **명단을\n  걷었다**: 그룹은 <b>물려받지 않고 매번 묻는</b> 방식이라 상속 칸이 설 자리가 없다.\n\n  **빈 칸은 여는 것이다**(확정 3) — *아무도 막지 않는다*이지 *아무도 못 본다*가 아니다.\n  에셋의 라벨과 반대인 자리이고, 경로가 반드시 시조를 지나므로 그래야 한다.\n\n  **조상이 건 것은 여기서 풀 수 없다.** 사슬은 <b>전부가 걸리므로</b> 움직임이 좁히는\n  방향으로만 일어난다 — 그래서 칸에 담기는 것은 <b>이 문서가 제 몫으로 거는 것</b>뿐이고,\n  위에서 걸린 것까지는 <b>레이블 뒤</b>가 말한다.\n}}\n<form class=\"compose\" method=\"post\" action=\"/{{href_path}}/-/access\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  {{#access.can_label}}\n  <fieldset>\n    <legend>{{t.document.groups}}</legend>\n    {{!\n      **레이블 뒤에 사슬을 통째로 적는다** (2026-09-18 요구).\n\n      **칸에는 제 것만 담긴다** — 거기 적는 일이 <i>이 문서가 무엇을 거는가</i>이기\n      때문이다. 그런데 실제로 이 문서를 가르는 것은 <b>시조까지의 모든 마디</b>이므로\n      (38 확정 2), 칸만 보면 <i>비었는데 왜 안 보이지</i>가 화면에서 답을 얻지 못한다.\n\n      **위에서부터 적고 겹친 것은 한 번만 선다.** 여기서 답하는 물음은 <b>무엇이 걸려\n      있나</b> 하나다 — ~~어느 마디가 걸었는지를 상자로 늘어놓았다~~(2026-09-18 요구).\n\n      **줄을 갈라 세운다**(2026-09-18 요구) — 레이블 뒤에 이어 붙이면 <i>칸의 이름</i>과\n      <i>걸려 있는 사실</i>이 한 줄에서 섞인다. 제 레이블(`모계 그룹:`)을 달되 <b>필드\n      레이블의 옷은 입히지 않는다</b>.\n    }}\n    <label class=\"field\">\n      <span>{{t.document.groups_read}}</span>\n      {{#groups_read_all}}<span class=\"chain\">{{t.document.groups_chain}} {{.}}</span>{{/groups_read_all}}\n      <input class=\"input\" type=\"text\" name=\"groups_read\" value=\"{{groups_read}}\"\n             autocomplete=\"off\" maxlength=\"512\">\n    </label>\n    <label class=\"field\">\n      <span>{{t.document.groups_write}}</span>\n      {{#groups_write_all}}<span class=\"chain\">{{t.document.groups_chain}} {{.}}</span>{{/groups_write_all}}\n      <input class=\"input\" type=\"text\" name=\"groups_write\" value=\"{{groups_write}}\"\n             autocomplete=\"off\" maxlength=\"512\">\n    </label>\n    {{!\n      **~~*쉼표로 가릅니다. 비우면 이 문서는 아무도 막지 않습니다.*가 여기 섰다~~**\n      (2026-09-18 요구).\n\n      **쉼표는 칸이 보여 준다** — 값이 하나라도 들어 있으면 그것이 곧 규칙이고, 비어 있으면\n      적을 것이 없는 자리다. **비었을 때의 뜻**은 레이블 뒤가 이미 말한다: 거기까지 비면\n      <b>아무 마디도 걸지 않았다</b>는 것이 화면에 그대로 있다.\n    }}\n  </fieldset>\n  {{/access.can_label}}\n\n  {{!\n    **~~조상이 건 그룹 상자가 여기 섰다~~** (2026-09-18 요구) — 마디마다의 경로와 그 라벨을\n    줄로 늘어놓고 <i>여기서 풀 수 없습니다</i>라 적었다.\n\n    **레이블 뒤의 한 줄이 그 일을 한다.** 사람이 여기서 묻는 것은 <b>무엇이 걸려 있나</b>\n    하나이고, 상자는 그 답을 두 번째로 적으면서 화면만 길게 만들었다.\n  }}\n\n  {{!\n    **에셋 태그 — 권한이 아니라 분류다** (2026-09-15 요구).\n\n    정하는 것은 <b>무엇을 찾을 수 있나</b>이지 <b>무엇을 볼 수 있나</b>가 아니다. 태그가 맞지\n    않아도 주소를 아는 사람에게 그림은 그대로 열리며, 가리는 일은 위의 그룹이 진다.\n\n    **그룹과 같은 꼴로 선다** (2026-09-18 요구) — 칸에는 <b>이 마디가 더하는 말들</b>이\n    쉼표로 담기고, 사슬이 모은 전부는 <b>모계 줄</b>이 말한다.\n\n    **~~마디마다 하나였다~~**(2026-09-18 보고) — 옆 칸 둘과 모양이 같은데 규칙만 달라서,\n    쉼표를 적은 값이 <i>`여성,이십대`라는 이름의 태그 하나</i>로 저장됐다.\n\n    **셈은 반대다.** 그룹의 사슬은 마디마다 걸리는 문이라 <b>전부를 지나야</b> 하고, 태그의\n    사슬은 분류라 <b>모은다</b> — 그래서 <c>연재/1984년/12월</c>에서 올린 그림이 연재로\n    훑어도 걸린다. 에셋은 태그를 여럿 가지므로 모아도 잃는 것이 없다.\n\n    **~~`상속 중` 칸이 있었다~~**(2026-09-18 요구) — 끄면 제 태그만 쓰는 스위치였다. 사슬이\n    모으는 쪽으로 가면서 <b>자식이 좁힐 길은 사라졌고</b>, 그 대신 칸 셋과 전파 워커의 절반이\n    함께 나갔다.\n\n    **비어 있으면 전부다.** 그것이 기본이고, 커뮤니티에 따라 <i>잠긴 문서가 있을지라도\n    리소스는 공유한다</i>는 자리를 연다.\n  }}\n  <fieldset>\n    <legend>{{t.document.asset_tag}}</legend>\n    <label class=\"field\">\n      <span>{{t.document.asset_tag}}</span>\n      {{#asset_tags_all}}<span class=\"chain\">{{t.document.asset_tags_chain}} {{.}}</span>{{/asset_tags_all}}\n      <input class=\"input\" type=\"text\" name=\"asset_tag\" value=\"{{asset_tag_text}}\"\n             placeholder=\"{{t.document.asset_tag_all}}\" autocomplete=\"off\" maxlength=\"512\">\n    </label>\n  </fieldset>\n\n  <button class=\"button is-primary\" type=\"submit\">{{t.document.save_do}}</button>\n</form>\n\n{{/tab_is.access}}\n\n{{#tab_is.export}}\n{{!\n  **내보내기** — 형식이 늘어날 자리이므로(파싱된 HTML·PDF는 플러그인으로 넓힌다 · 확정 10)\n  목록이 설 곳이 필요하다.\n\n  **편집자에게만 나간다** — 소스가 그들에게만 실리는 것과 같은 규칙이고, 읽는 사람이\n  가져갈 것은 화면의 글이다.\n}}\n<ul class=\"exports\">\n  <li><a href=\"{{export_md}}\" download><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-file-text}}</span><span class=\"nav-label\">{{t.document.export_md}}</span></a></li>\n</ul>\n<p class=\"hint\">{{t.document.export_hint}}</p>\n{{/tab_is.export}}\n\n{{#tab_is.danger}}\n{{!\n  **위험** — 되돌릴 수 없는 일만 여기 산다. 앞의 탭들을 고치다가 스크롤 끝에서 만나지\n  않도록 <b>들어오려면 한 번 눌러야 하는 자리</b>다.\n}}\n{{#can_edit}}\n<p class=\"hint\">{{t.document.delete_hint}}</p>\n<p><a class=\"button is-danger\" href=\"{{delete_href}}\">{{t.document.delete}}</a></p>\n{{/can_edit}}\n{{^can_edit}}\n<p class=\"hint\">{{t.document.danger_locked}}</p>\n{{/can_edit}}\n{{/tab_is.danger}}\n","body-document-backlinks":"{{!\n  역참조가 **페이지로 서는 자리** (2026-09-19 요구로 모달이 먼저가 되었다).\n\n  **지름길이 막히면 이 화면이 선다** — 주소로 곧장 왔거나 스크립트가 죽었을 때다. 폼 여섯이\n  이미 그 규약이고, 여기서도 <b>모달과 같은 조각</b>을 쓴다(`modal-backlinks`): 목록의\n  모양이 두 자리에서 갈리지 않는다.\n\n  **다시 이 화면이 제 몫을 하게 되어도 마크업은 그대로다** — 붙일 것이 생기면 이 파일이\n  그것을 담고, 목록은 조각이 계속 진다.\n}}\n{{> body-title}}\n{{!\n  **돌아가는 길은 취소다** (2026-09-16 요구) — 이 화면을 접고 보던 자리로 가는 것이라,\n  전역 규칙의 <b>취소</b>가 그대로 이 자리의 이름이다: 수식어 없는 `button`이고,\n  <b>되돌아가는 것이므로 링크</b>다. **자리는 그대로 둔다.**\n}}\n<p><a class=\"button\" href=\"/{{href_path}}\">{{t.back.to_document}}</a></p>\n\n{{> modal-backlinks}}\n","body-document-delete":"{{!\n  문서를 지우는 화면 (31 확정 8).\n\n  **소프트 삭제이고 경로는 비켜 준다** — 지운 문서의 이름을 영영 못 쓰게 하는 것은 *삭제*의\n  뜻이 아니다.\n\n  **하위는 함께 지우지 않는다.** 지운 마디의 자식들은 그 위 조상의 값을 따르게 되므로\n  <b>실효 권한이 조용히 바뀐다</b> — 없던 마디가 끼어드는 것의 반대이고, 같은 부류로\n  <b>알고 둔다</b>(확정 5).\n}}\n{{> body-title}}\n\n<p class=\"hint\">{{t.document.delete_hint}}</p>\n\n<form class=\"compose\" method=\"post\" action=\"/{{href_path}}/-/delete\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <p class=\"error\" data-notice role=\"status\"></p>\n  <div class=\"document-actions\">\n    <button class=\"button is-danger\" type=\"submit\">{{t.document.delete}}</button>\n    <a class=\"button\" href=\"/{{href_path}}\">{{t.back.cancel}}</a>\n  </div>\n</form>\n","body-document-denied":"{{!\n  **할 수 없는 자리** (2026-09-18 보고 — *권한 없는 문서에 새 문서 만들기 단추가 떴다*).\n\n  **아무 일도 하지 못하는 단추를 세우지 않는다.** 없는 자리는 만들 수 있는 자리이지만\n  (<a href=\"../../../../.claude/milestone-31_document_tree.md\">31</a> 확정 6) <b>만들 수 없는\n  사람에게는 아니다</b> — 눌러 보고 알게 하는 것은 *만들 수 있는가*가 링크마다의 물음일 때의\n  이야기이고, 이미 그 자리에 선 화면에서는 한 번 물어 답할 수 있다.\n\n  **까닭을 가르지 않는다.** <i>쓸 수 없다</i>와 <i>자리가 찼다</i>를 나눠 적으면 읽을 수 없는\n  문서가 거기 있다는 사실이 새어 나간다 — 코어가 한 값으로 답하고 화면도 한 문장으로 적는다.\n}}\n{{> body-title}}\n\n<p class=\"notice\">{{message}}</p>\n\n{{#back}}\n<p class=\"document-actions\">\n  <a class=\"button\" href=\"{{href}}\">{{label}}</a>\n</p>\n{{/back}}\n","body-document-diff":"{{!\n  문서 판 둘의 견줌 — **이 마일스톤이 출발한 자리다**(31).\n\n  ~~소스가 텍스트가 되면서 그냥 줄 단위 diff가 된다~~(31) — **두 층이 되었다**(33 확정 3):\n  **블록 출납** 위에 **같은 id 블록 안의 줄 diff**다. 그래서 `moved`가 선다 — 줄 diff가\n  말하지 못하던 것이다.\n\n  **표는 그림이 아니라 글자다**(03d — 색이 유일한 신호가 아니다). 색을 쓰지 않는 스킨에서도\n  `+`와 `-`가 선다.\n}}\n{{> body-title}}\n{{!\n  **둘 다 돌아가는 길이다** (2026-09-16 요구) — 하나는 판 목록으로, 하나는 문서로. 둘 다\n  수식어 없는 `button`이고 가운뎃점은 걷었다(사이는 줄이 벌린다). **자리는 그대로 둔다.**\n}}\n<p class=\"back-row\">\n  <a class=\"button\" href=\"/{{href_path}}/-/revisions\">{{t.back.to_revisions}}</a>\n  <a class=\"button\" href=\"/{{href_path}}\">{{t.back.to_document}}</a>\n</p>\n\n{{!\n  **줄이 블록으로 묶여 온다** (33 확정 3). 견줌이 두 층이므로 화면도 두 층이다 — 납작하게\n  펴면 *어느 문단 안의 일인가*가 사라진다.\n\n  `mark`가 묶음 전체의 갈래이고(`same`·`added`·`removed`·`moved`·`changed`), 안쪽 줄의\n  `mark`는 그 줄의 것이다.\n}}\n{{#blocks.length}}\n<div class=\"diff-blocks\">\n  {{#blocks}}\n  <section class=\"diff-block {{mark}}\">\n    <pre class=\"diff-lines\">{{#lines}}<span class=\"line {{mark}}\">{{sign}} {{text}}\n</span>{{/lines}}</pre>\n  </section>\n  {{/blocks}}\n</div>\n{{/blocks.length}}\n{{^blocks.length}}\n<p class=\"hint\">{{t.diff.same}}</p>\n{{/blocks.length}}\n","body-document-edit":"{{!\n  문서를 고치는 화면 — **편집 모드** (31 확정 10).\n\n  **제목 옆의 순환링크도 문서 액션도 없다.** 읽기 모드에만 서는 것들이고, 여기서는 소스를\n  직접 고친다.\n\n  **저장하지 않으면 없던 일이다**(27 확정 1). 그래서 이 화면에는 저장 단추가 있고, 나가는\n  길은 그것을 누르거나 그만두는 것뿐이다.\n}}\n{{> body-title}}\n\n<form class=\"compose\" method=\"post\" action=\"/{{href_path}}/-/edit\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  {{!\n    **딛고 선 판** — 저장할 때 그것이 밀렸는지 본다(27 확정 9).\n\n    **막지는 않는다**(31). 락이 걷혔으므로 마지막 저장이 이기고, 밀린 쪽은 판 목록에서\n    자기 것을 되돌린다 — 그 사실을 알리는 것까지가 이 칸의 일이다.\n  }}\n  <input type=\"hidden\" name=\"base_seq\" value=\"{{revision_seq}}\">\n\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  {{!\n    **넘겨주기 칸이 여기 있었다** — 걷었다(2026-09-13 요구).\n\n    본문 밖의 칸으로 묻게 했는데 **블록 편집의 결이 아니었다**: 문서에 무엇을 더하는 일은\n    전부 블록으로 하는 것이 한 가지 길이다. 이제 `/넘겨주기`가 특수 블록을 심는다.\n  }}\n\n  {{! **이름은 스타일시트가 감춘다** — 읽어 주는 길은 남긴다(`글감` 제목과 같은 방식). }}\n  <label class=\"document-edit-label\" for=\"document-source\">{{t.document.source}}</label>\n  {{!\n    **블록 편집기가 여기 선다** (35 확정 9).\n\n    ~~소스를 그대로 고치는 `textarea`였다~~(31 확정 10) → ~~블록 트리였다~~(33) →\n    **블록마다의 `textarea`**다: 누르면 그 블록의 마크다운이 드러나고 떠나면 코어가 구운\n    HTML이 선다. <b>소스 직접 편집이 블록 단위로 돌아왔다.</b>\n\n    **스크립트가 없으면 이 자리는 빈 채로 선다.** 하멜에는 점진적 향상의 하한이 없고\n    (`README`의 트러블슈팅), 그래서 여기서도 지어내지 않는다.\n  }}\n  <div id=\"document-source\" class=\"document-editor\" data-editor data-editor-id=\"{{id}}\"></div>\n\n  {{! **폼이 실어 보내는 것은 blockdown이다** — 편집기가 보낼 때 채운다. }}\n  <input type=\"hidden\" name=\"source\" data-editor-source value=\"{{source}}\">\n\n  {{!\n    **`/` 커맨드의 목록** (31 확정 14) — 줄머리이거나 공백 뒤의 `/`에서 열린다. 주소나\n    경로의 슬래시에서는 열리지 않는다.\n\n    **감춰 두고 스크립트가 보인다** — 목록을 세우고 고르는 일이 전부 스크립트의 것이다.\n  }}\n  <ul class=\"suggestions commands\" data-command-list hidden></ul>\n\n\n  {{!\n    **단추 둘이 한 줄이다** (2026-09-07 보고). 저장은 폼이 보내는 것이고 그만두기는 떠나는\n    링크라 <b>다른 것</b>이지만, 손이 닿는 자리는 나란해야 한다.\n  }}\n  <div class=\"document-actions\">\n    <button class=\"button is-primary\" type=\"submit\">{{t.document.save_do}}</button>\n    <a class=\"button\" href=\"/{{href_path}}\">{{t.document.cancel_do}}</a>\n  </div>\n</form>\n\n{{!\n  **고른 카드를 무엇으로 놓을지 묻는 자리는 여기 없다** (2026-09-16 요구).\n\n  ~~제 다이얼로그가 이 화면에 박혀 있었다~~ — 그래서 <b>다른 모달과 생김새가 갈렸다</b>:\n  틀도 닫기 단추도 이 자리에만 없었고, 카드는 본문 앞부분만 섰다. 지금은 조각 하나로 서서\n  (`modal-corpus-pick`) <b>다른 모달과 같은 틀</b>에 담긴다.\n}}\n","body-document-empty":"{{!\n  아직 없는 문서 — **만들 수 있는 빈 자리**\n  (<a href=\"../../../../.claude/milestone-05c_archive.md\">05c</a>의 *먼저 부르고 나중에\n  채운다* · <a href=\"../../../../.claude/milestone-31_document_tree.md\">31</a> 확정 6).\n\n  **여기가 위키링크의 빨간 자리다.** 없는 이름을 부른 링크가 이 화면으로 오고, 그것이\n  <b>문서가 생기는 가장 흔한 길</b>이다.\n\n  **만들 수 있는지 미리 재지 않는다**(확정 6). 누르기 전에 재면 링크마다 상속 사슬을 타야\n  하고, 더 큰 것은 <b>색이나 잠금이 닫힌 가지의 존재를 흘린다</b>는 것이다 — 정직하게\n  세워 두고 <b>누른 뒤에 사정을 말한다.</b>\n}}\n{{> body-title}}\n\n<p class=\"hint\">{{t.document.empty}}</p>\n\n<form class=\"compose\" method=\"post\" action=\"/-/documents\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"path\" value=\"{{path}}\">\n\n  {{! **거절당한 사정이 적히는 자리** — 부모의 편집자가 아니면 여기 선다. }}\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  <button class=\"button is-primary\" type=\"submit\">{{t.document.create}}</button>\n</form>\n","body-document-history":"{{!\n  문서의 이력과 판 — **두 각도에서 같은 것을 본다**\n  (<a href=\"../../../../.claude/milestone-10_document_revisions.md\">10</a> ·\n  <a href=\"../../../../.claude/milestone-27_document_drafts.md\">27</a> 확정 2 ·\n  <a href=\"../../../../.claude/milestone-31_document_tree.md\">31</a> 확정 6).\n\n  **탭이 둘이다**(2026-09-07 요구). 이력은 <i>문서에 벌어진 일</i>을 세고 판 목록은\n  <i>본문이 바뀐 자리</i>를 센다 — 그 가름이 있어서 <b>자식의 생성이 부모의 이력에는 남되\n  부모의 판은 늘지 않는다.</b> **감시목록이 거기서 저절로 생긴다.**\n}}\n{{> body-title}}\n{{!\n  **돌아가는 길은 취소다** (2026-09-16 요구) — 이 화면을 접고 보던 자리로 가는 것이라,\n  전역 규칙의 <b>취소</b>가 그대로 이 자리의 이름이다: 수식어 없는 `button`이고,\n  <b>되돌아가는 것이므로 링크</b>다. **자리는 그대로 둔다.**\n}}\n<p><a class=\"button\" href=\"/{{href_path}}\">{{t.back.to_document}}</a></p>\n\n{{> body-tabs}}\n\n{{#tab_is.history}}\n{{#events.length}}\n<ul class=\"document-history\">\n  {{#events}}\n  <li><span class=\"event\">{{label}}</span> <time datetime=\"{{created_at}}\">{{when}}</time></li>\n  {{/events}}\n</ul>\n{{/events.length}}\n{{^events.length}}\n<p class=\"hint\">{{t.document.no_history}}</p>\n{{/events.length}}\n{{/tab_is.history}}\n\n{{#tab_is.revisions}}\n{{!\n  **라디오 둘이 견줄 두 판을 고른다.** 고른 결과가 곧 주소이므로 <b>자바스크립트가 없어도\n  돈다</b> — 라디오와 `GET` 폼 하나다.\n}}\n{{#revisions.length}}\n<form class=\"revision-compare\" method=\"get\" action=\"/{{href_path}}/-/revisions/compare\">\n  <table class=\"revisions\">\n    <thead>\n      <tr>\n        <th scope=\"col\"><abbr title=\"{{t.diff.pick_from}}\">{{t.diff.from}}</abbr></th>\n        <th scope=\"col\"><abbr title=\"{{t.diff.pick_to}}\">{{t.diff.to}}</abbr></th>\n        <th scope=\"col\">{{t.revision.seq}}</th>\n        <th scope=\"col\">{{t.revision.preview}}</th>\n      </tr>\n    </thead>\n    <tbody>\n      {{#revisions}}\n      <tr>\n        <td><input type=\"radio\" name=\"from\" value=\"{{seq}}\"{{#from_picked}} checked{{/from_picked}}></td>\n        <td><input type=\"radio\" name=\"to\" value=\"{{seq}}\"{{#to_picked}} checked{{/to_picked}}></td>\n        <td>{{seq}}</td>\n        <td>{{preview}}</td>\n      </tr>\n      {{/revisions}}\n    </tbody>\n  </table>\n  <button class=\"button is-primary\" type=\"submit\">{{t.diff.compare}}</button>\n</form>\n{{/revisions.length}}\n{{^revisions.length}}\n<p class=\"hint\">{{t.document.no_revisions}}</p>\n{{/revisions.length}}\n{{/tab_is.revisions}}\n","body-document-move":"{{!\n  문서를 옮기는 화면 (31 확정 8).\n\n  **정상적인 편집 행위다.** 편집자라면 시도할 수 있고, 목적지의 부모가 자기에게 잠겨 있으면\n  거절이 온다 — 자식의 생성·이동·삭제가 부모의 편집행위이기 때문이다(확정 6).\n\n  **하위가 함께 간다.** 경로가 트리이므로 접두를 갈아 끼우면 아래가 전부 따라오고, 옛 자리에\n  <b>표지</b>가 선다(확정 20) — 그러지 않으면 들어오던 링크가 전부 깨진다.\n}}\n{{> body-title}}\n\n<form class=\"compose\" method=\"post\" action=\"/{{href_path}}/-/move\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  <label for=\"document-move-path\">{{t.document.move_to}}</label>\n  <input id=\"document-move-path\" name=\"path\" value=\"{{path}}\" required>\n  <p class=\"hint\">{{t.document.move_hint}}</p>\n\n  {{!\n    **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구).\n\n    ~~그만두는 길이 폼 밖의 제 줄에 있었다~~ — 같은 물음의 두 답인데 줄이 갈리면 <b>고르는\n    일이 두 번</b>으로 읽히고, 아래 것은 <i>이 폼과 상관없는 링크</i>처럼 보인다.\n\n    **편집 화면과 같은 줄이다**(`.document-actions`) — 저장·취소가 거기서 이미 그렇게 서고,\n    같은 일에 두 생김새를 두면 사람이 두 번 배운다.\n\n    **그만두는 것은 링크다**(전역 규칙) — 되돌아가는 일이라 상태를 바꾸지 않으므로 폼도\n    토큰도 필요 없다. 폼 안에 서지만 보내지 않는다.\n  }}\n  <div class=\"document-actions\">\n    <button class=\"button is-primary\" type=\"submit\">{{t.document.move}}</button>\n    <a class=\"button\" href=\"/{{href_path}}\">{{t.back.cancel}}</a>\n  </div>\n</form>\n","body-document":"{{!\n  문서를 읽는 화면 (<a href=\"../../../../.claude/milestone-31_document_tree.md\">31</a> 확정 10).\n\n  **읽기 모드다.** 제목 옆에 순환링크(역참조)가 서고 줄의 우상단에 문서 액션이 선다 —\n  편집 모드에는 둘 다 없다.\n\n  **본문은 서버가 구운 것을 그대로 세운다.** 마크다운은 코어가 산수화까지 마쳐 돌려주고\n  특수 블록은 문서 레이어가 그린다(`DocumentRenderer`) — 뷰어가 다시 훑을 자리가 없다.\n}}\n{{> body-title}}\n\n{{#redirected}}\n{{!\n  **표지를 거쳐 왔다** (31 확정 20 · 2026-09-11에 넘겨주기가 같은 깃발을 쓴다). 조용히\n  따라가면 읽는 사람은 자기가 부른 주소가 왜 다른 곳인지 모른다.\n\n  **어느 이름으로 왔는지 적는다.** 그것이 없으면 *무엇이* 넘어온 것인지를 말하지 못한다 —\n  옮기기가 남긴 옛 이름이거나 사람이 세운 넘겨주기다.\n}}\n<p class=\"notice document-redirected\">{{t.document.redirected}} <code>{{from}}</code></p>\n{{/redirected}}\n\n{{!\n  **~~*닫힌 문서입니다. 지정된 사람만 볼 수 있습니다.*가 여기 섰다~~** (2026-09-18 요구 ·\n  31 확정 7이 세운 줄이다).\n\n  그때는 <b>명단</b>이 문서를 닫았고 <i>지정된 사람</i>이 그 명단을 가리켰다. 38이 명단을\n  걷으면서 문장이 가리킬 것이 없어졌다 — 그룹은 <b>사슬의 마디마다</b> 서고, 무엇이 어디서\n  거는지는 <b>문서 속성</b>이 말한다.\n}}\n{{!\n  **본문의 블록에 손잡이가 오버레이된다** (31 확정 11).\n\n  세우는 일은 스크립트의 몫이다 — 소스와 화면의 블록 수가 같을 때만 서고, 어긋나면\n  아무것도 세우지 않는다: <b>잘못 짚은 손잡이는 남의 문단을 옮긴다.</b>\n\n  **`잠그기`가 이것을 켜고 끈다**(문서 액션). 권한 설정이 아니라 <b>손잡이 토글</b>이며\n  편집자는 누구라도 잠그고 푼다.\n}}\n{{!\n  **손잡이의 본은 스킨이 지고 스크립트가 복제한다** (2026-09-07 요구로 띠가 되었다).\n\n  블록마다 손잡이를 세우는 것은 스크립트의 일이지만 <b>그림과 낱말은 스킨의 것</b>이다 —\n  스크립트가 SVG를 지으면 <b>스킨을 갈아도 같은 그림이 따라온다.</b>\n\n  **좌측은 끄는 띠, 우측은 점셋 드롭다운**이다. 아이콘은 띠의 한가운데 선다.\n}}\n<template data-block-band=\"left\">\n  <span class=\"block-band is-left\" draggable=\"true\">\n    <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-grip}}</span>\n  </span>\n</template>\n\n<template data-block-band=\"right\">\n  <span class=\"block-band is-right\">\n    <details class=\"dropdown dot-menu block-menu\" data-dropdown>\n      <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.screen.actions}}</span></summary>\n      <ul class=\"dropdown-menu\">\n        <li><button type=\"button\" data-block-action=\"up\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-arrow-up}}</span><span class=\"nav-label\">{{t.document.move_up}}</span></button></li>\n        <li><button type=\"button\" data-block-action=\"down\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-arrow-down}}</span><span class=\"nav-label\">{{t.document.move_down}}</span></button></li>\n        <li><button type=\"button\" data-block-action=\"remove\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-trash}}</span><span class=\"nav-label\">{{t.document.remove}}</span></button></li>\n      </ul>\n    </details>\n  </span>\n</template>\n\n<article class=\"document-body\" data-blocks=\"{{#can_edit}}1{{/can_edit}}\">\n  {{&body}}\n</article>\n\n{{!\n  **저장 단추는 본문 아래다** (2026-09-07 요구 — 편집 화면과 같은 자리).\n\n  조작이 초안을 만들고 그때 드러난다(31 확정 11) — 읽는 화면에 저장 경계가 없어서 판을\n  만들 수 없던 문제가(10) 그래서 다시 열리지 않는다.\n\n  **감춰 두고 스크립트가 보인다**(`hidden`). 손잡이는 스크립트가 세우므로, 없는 곳에서는\n  <b>누를 수 없는 단추</b>가 서지 않는다.\n}}\n<form class=\"compose\" method=\"post\" action=\"/{{href_path}}/-/edit\" data-block-save hidden>\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"base_seq\" value=\"{{revision_seq}}\">\n  <input type=\"hidden\" name=\"source\" value=\"\">\n  <p class=\"error\" data-notice role=\"status\"></p>\n  <div class=\"document-actions\">\n    <button class=\"button is-primary\" type=\"submit\">{{t.document.save_do}}</button>\n    <button class=\"button\" type=\"button\" data-block-reset>{{t.document.cancel_do}}</button>\n  </div>\n</form>\n\n{{!\n  **역참조 상자를 걷었다** (2026-09-07 요구).\n\n  ~~본문 아래에 앞머리가 섰다~~ — 그것을 세우려면 문서와 함께 역참조를 당겨와야 했고,\n  <b>왕복 하나가 통째로 그 상자의 값</b>이었다(공개 주소에서 342ms). **역참조는 제목 옆의\n  문으로 가서 본다**: 거기서 전부를 보고 *가리키는 것이 없다*도 그 화면이 답한다.\n}}\n","body-edit":"{{> body-title}}\n{{> modal-edit}}\n\n{{!\n  빠져나갈 길은 **페이지에만** 둔다 — 모달에는 자바스크립트가 붙이는 `닫기`가 이미 있다.\n  `delete`와 같은 규칙이며, 부분은 페이지와 모달이 함께 쓰는 것만 담는다.\n}}\n","body-emojis":"{{!\n  **이모지 관리 — 격자로 본다** (2026-09-21 요구 ·\n  <a href=\"../../../../.claude/milestone-45_emojis.md\">45</a> 확정 3).\n\n  **에셋 풀과 같은 뼈대다**: 제목줄에 선택 액션, 격자 위에 갈래 탭, 아래에 쪽 번호.\n  ~~폼 둘과 줄 목록이었다~~ — 이모지는 <b>눈으로 고르는 그림</b>이라 이름의 목록보다 격자가\n  맞고, 올리는 일도 여럿을 한 번에 하는 일이다.\n\n  **끌어다 놓아도 올라간다** — 상자 전체가 받는다(`data-emoji-drop`).\n}}\n{{> body-title}}\n\n{{#notice}}<p class=\"notice notification is-success is-light\">{{notice}}</p>{{/notice}}\n{{#problem}}<p class=\"error notification is-danger is-light\">{{problem}}</p>{{/problem}}\n\n{{!\n  **갈래 탭은 격자 위에 선다** — 유니코드·SVG·이미지는 <b>다루는 법이 다른 셋</b>이다\n  (앞엣것은 글자이고 뒤의 둘은 파일이다).\n\n  **링크다.** 여는 일을 스크립트에 맡기지 않는다 — 주소에 실려 있어야 *거기 가서 이것을\n  보라*를 남에게 일러 줄 수 있다(설정의 서브탭과 같은 규칙).\n}}\n{{!\n  **찾는 칸은 화면이 진다** (2026-09-21 요구) — 머리의 검색은 글과 문서의 것이고, 여기서\n  찾는 것은 <b>이 표 안의 그림</b>이다. 코드로도 이름으로도 찾고, 글자를 붙여 넣어도 찾는다.\n\n  **폼이다** — `Enter`가 곧 찾기이고, 스크립트는 주소를 갈아 그 화면을 다시 세울 뿐이다.\n}}\n<form class=\"emoji-find\" data-emoji-find>\n  <label class=\"is-sr-only\" for=\"emoji-find\">{{t.emoji.find}}</label>\n  <input class=\"input\" id=\"emoji-find\" type=\"search\" name=\"q\" value=\"{{query}}\"\n         placeholder=\"{{t.emoji.find_hint}}\" autocomplete=\"off\">\n  <button class=\"button\" type=\"submit\">{{t.emoji.find}}</button>\n</form>\n\n<nav class=\"tabs emoji-kinds\" aria-label=\"{{t.emoji.kinds}}\">\n  <ul>\n    {{#kinds}}\n    <li class=\"{{#active}}is-active{{/active}}\">\n      <a href=\"{{href}}\"{{#active}} aria-current=\"page\"{{/active}}>{{label}} <span class=\"count\">{{count}}</span></a>\n    </li>\n    {{/kinds}}\n  </ul>\n</nav>\n\n{{!\n  **정렬은 탭마다 고른다** (2026-09-21 요구). 링크라 주소에 실리고, 고른 것은 눌린 채로 선다.\n}}\n<p class=\"emoji-sorts\">\n  <span class=\"label\">{{t.emoji.sort}}</span>\n  {{#sorts}}\n  <a class=\"button is-small{{#active}} is-active{{/active}}\" href=\"{{href}}\"{{#active}} aria-current=\"true\"{{/active}}>{{label}}</a>\n  {{/sorts}}\n</p>\n\n{{!\n  **~~누르면 코드가 복사된다는 안내~~가 걷혔다** (2026-09-22 요구).\n\n  누름이 <b>드롭다운을 여는 일</b>이 되면서 그 문장이 거짓이 되었다 — 복사는 이제 그 상자의\n  항목이고, 갈래마다 복사할 것이 다르다(코드 · 유니코드 · 미디어 경로). **상자가 스스로\n  말하므로 위에 적어 둘 것이 없다.**\n}}\n\n<div class=\"emoji-pool\" data-emoji-drop>\n  {{^items.length}}<p class=\"empty help\">{{t.emoji.empty}}</p>{{/items.length}}\n\n  {{> emoji-grid}}\n</div>\n\n{{> pager-numbers}}\n","body-erase":"{{> body-title}}\n{{> modal-erase}}\n\n{{!\n  빠져나갈 길은 페이지에만 둔다 — 모달에는 자바스크립트가 붙이는 `닫기`가 이미 있다.\n  `block`과 같은 규칙이다.\n}}\n","body-error":"{{> body-title}}\n<p class=\"error\">{{message}}</p>\n{{#code}}<p class=\"meta\"><code>{{.}}</code></p>{{/code}}\n\n{{!\n  **~~돌아갈 자리 목록~~은 없다**(2026-08-21 요구). `로그인`·`서버 피드`·`홈 피드`·`알림`이\n  여기 늘어서 있었는데 **넷 다 헤더가 이미 진다** — 같은 길을 본문에 한 번 더 적으면\n  이 화면이 무엇을 말하는 자리인지 흐려진다.\n}}\n","body-feed-bookmarks":"{{!\n  북마크 — **이름은 하나이고 목록은 둘이다**(05e 요구).\n\n  화면의 제목은 `북마크`이고, 포스트냐 문서냐는 그 아래 탭이 말한다. 헤더의 링크는 보고\n  있는 섹션의 목록으로 가되 이름은 양쪽 다 `북마크`다.\n\n  **탭줄은 이제 담긴 것을 가른다**(2026-09-05) — 활동·로컬 미디어·원격 미디어. 대상(글·문서)을\n  가르던 자리와 같은 마크업이라 공통 파샬로 뽑았고(`body-tabs`), 문서 북마크는 여전히 하멜에\n  화면이 없다.\n}}\n{{> body-title}}\n\n{{> body-tabs}}\n\n{{> body-feedbody}}\n","body-feed-federated":"{{!\n  **이 피드만 다르게 그리고 싶을 때 고치는 자리다**(05e 요구). 지금은 공통 본문을 그대로\n  부르므로 `feed`와 같은 화면이 선다 — 이름이 갈려 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n{{> body-tabs}}\n{{> body-feedbody}}\n","body-feed-home":"{{!\n  **이 피드만 다르게 그리고 싶을 때 고치는 자리다**(05e 요구). 지금은 공통 본문을 그대로\n  부르므로 `feed`와 같은 화면이 선다 — 이름이 갈려 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n{{> body-tabs}}\n{{> body-feedbody}}\n","body-feed-list":"{{!\n  **이 피드만 다르게 그리고 싶을 때 고치는 자리다**(05e 요구). 지금은 공통 본문을 그대로\n  부르므로 `feed`와 같은 화면이 선다 — 이름이 갈려 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n{{> body-tabs}}\n{{> body-feedbody}}\n","body-feed-mentions":"{{!\n  멘션 피드 — **나를 부른 글** (2026-08-20 요구).\n\n  **이 피드만 다르게 그리고 싶을 때 고치는 자리다**(05e 요구). 지금은 공통 본문을 그대로\n  부르므로 `feed`와 같은 화면이 선다 — 이름이 갈려 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n{{> body-tabs}}\n{{> body-feedbody}}\n","body-feed-server":"{{!\n  **이 피드만 다르게 그리고 싶을 때 고치는 자리다**(05e 요구). 지금은 공통 본문을 그대로\n  부르므로 `feed`와 같은 화면이 선다 — 이름이 갈려 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n{{> body-tabs}}\n{{> body-feedbody}}\n","body-feed":"{{!\n  **피드의 바닥이다.** 자기 이름의 템플릿이 없는 피드가 여기로 떨어진다(05e 요구).\n  필수 템플릿이므로 어느 스킨에나 있고, 그래서 떨어질 곳이 늘 있다.\n}}\n{{> body-title}}\n{{> body-tabs}}\n{{> body-feedbody}}\n","body-feededit":"{{> body-title}}\n\n{{!\n  커스텀 피드의 조건 — **블록 넷** (2026-08-25 요구).\n\n  1. **이름과 종류** — 이 피드가 무엇으로 짓는 것인가\n  2. **계정 담기** · 3. **해시태그 담기** · 4. **검색어**\n\n  **뒤의 셋 중 고른 것만 선다.** 감추는 일은 스타일시트가 한다(`option:checked`를 `:has()`로\n  잡는다) — <b>고른 종류에 딸린 칸만 보인다</b>는 것은 화면의 사정이므로 자바스크립트를\n  요구할 일이 아니고, `:has()`를 모르는 브라우저에서는 <b>셋이 다 선다</b>: 감춰서 잃는 것이\n  없어야 그 규칙을 스타일시트에 둘 수 있다.\n\n  **감춘 칸의 값은 효력이 없다.** 코어가 종류를 사실로 들고, 조건을 읽을 때 그것이 가리키는\n  것만 싣는다 — <b>그래서 감춰 두어도 화면이 거짓말하지 않는다.</b> 지우지도 않는 이유는\n  종류를 되돌렸을 때 적어 둔 것이 살아 있어야 하기 때문이다.\n\n  **폼은 여전히 값의 성질로 갈린다**(M13의 근거 그대로): 이름·종류·검색어는 *고쳐 쓰는 값*,\n  계정과 해시태그는 *더하고 빼는 목록*이다.\n}}\n<div class=\"feed-edit\">\n\n{{#failed}}\n<p class=\"error notification is-danger is-light\">{{.}}</p>\n{{/failed}}\n\n{{!\n  **빈 조건을 말하는 문장도 종류마다 다르다.** *사람을 더하거나 검색 조건을 적으세요*는\n  둘이 겹쳤던 시절의 말이라(~~M13~~), 지금은 고른 종류가 무엇을 기다리는지 그대로 적는다.\n}}\n{{#empty_condition}}\n{{#kind_is.accounts}}<p class=\"hint\">{{t.feeds.empty_condition_accounts}}</p>{{/kind_is.accounts}}\n{{#kind_is.tag}}<p class=\"hint\">{{t.feeds.empty_condition_tag}}</p>{{/kind_is.tag}}\n{{#kind_is.search}}<p class=\"hint\">{{t.feeds.empty_condition_search}}</p>{{/kind_is.search}}\n{{/empty_condition}}\n\n{{!\n  ── 1. 이름과 종류 ───────────────────────────────────────────────────────\n\n  **이 폼이 화면의 `고쳐 쓰는 값`을 통째로 진다** (2026-08-25 요구). 아래 검색어 칸도\n  `form` 속성으로 여기 붙어 있어(4번 블록), <b>저장 하나가 이름·종류·검색어를 함께\n  보낸다</b> — 단추를 바닥에 모으려면 그것들이 한 폼이어야 한다.\n\n  **`form` 속성은 HTML의 것이다.** 폼 안에 없어도 어느 폼의 칸인지 적을 수 있고, 그래서\n  <b>화면의 차례와 폼의 경계를 따로 정할 수 있다</b> — 자바스크립트가 끼지 않는다.\n}}\n<form id=\"feed-basics\" class=\"box\" method=\"post\" action=\"/-/feeds/{{list.id}}/edit\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n\n  <div class=\"field\">\n    <label class=\"label\" for=\"feed-title\">{{t.feeds.title}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"feed-title\" type=\"text\" name=\"title\" value=\"{{list.title}}\" required>\n    </div>\n  </div>\n\n  {{!\n    **아래 블록들을 여닫는 것이 이 칸이다.** `id`가 규약인 이유는 스타일시트가 그것으로\n    잡기 때문이다 — 감추는 규칙이 이 칸 하나를 보고 셋을 정한다.\n  }}\n  <div class=\"field\">\n    <label class=\"label\" for=\"feed-kind\">{{t.feeds.kind}}</label>\n    <div class=\"control\">\n      <div class=\"select\">\n        <select id=\"feed-kind\" name=\"kind\">\n          <option value=\"accounts\"{{#kind_is.accounts}} selected{{/kind_is.accounts}}>{{t.feeds.kind_accounts}}</option>\n          <option value=\"tag\"{{#kind_is.tag}} selected{{/kind_is.tag}}>{{t.feeds.kind_tag}}</option>\n          <option value=\"search\"{{#kind_is.search}} selected{{/kind_is.search}}>{{t.feeds.kind_search}}</option>\n        </select>\n      </div>\n    </div>\n    <p class=\"hint help\">{{t.feeds.kind_help}}</p>\n  </div>\n</form>\n\n{{!\n  ── 2. 계정 담기 ─────────────────────────────────────────────────────────\n\n  **멤버는 이 서비스의 유일한 `또는`이다** — 검색 문법의 토큰 여럿은 `그리고`라\n  `from:a from:b`가 *둘 다 쓴 글*이 된다. 그래서 이 자리가 질의로 대체되지 않는다.\n}}\n<fieldset class=\"box by-accounts\">\n  <legend class=\"subtitle is-6\">{{t.feeds.members}}</legend>\n\n  {{#list.members.length}}\n  <ul class=\"people\">\n    {{#list.members}}\n    <li class=\"person\">\n      <a href=\"/@{{handle}}\">{{> name-badged}}</a>\n      <code>@{{handle}}</code>\n      <form method=\"post\" action=\"/-/feeds/{{list.id}}/members\">\n        <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n        <input type=\"hidden\" name=\"remove\" value=\"{{id}}\">\n        <button class=\"button is-small\" type=\"submit\">{{t.feeds.remove_member}}</button>\n      </form>\n    </li>\n    {{/list.members}}\n  </ul>\n  {{/list.members.length}}\n  {{^list.members.length}}\n  <p class=\"empty\">{{t.empty.people}}</p>\n  {{/list.members.length}}\n\n  <form class=\"field has-addons\" method=\"post\" action=\"/-/feeds/{{list.id}}/members\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <p class=\"control is-expanded\">\n      <label class=\"is-sr-only\" for=\"feed-member\">{{t.feeds.add_member}}</label>\n      <input class=\"input\" id=\"feed-member\" type=\"text\" name=\"handle\"\n             placeholder=\"@{{t.feeds.handle}}\" autocomplete=\"off\">\n    </p>\n    <p class=\"control\">\n      <button class=\"button\" type=\"submit\">{{t.feeds.add_member}}</button>\n    </p>\n  </form>\n</fieldset>\n\n{{!\n  ── 3. 해시태그 담기 ─────────────────────────────────────────────────────\n\n  **계정 담기와 같은 모양이다** — 더하고 빼는 목록이라 폼이 줄마다 선다. 코어가 드는 것은\n  태그 목록이 아니라 <b>질의 한 줄</b>(`tag:위키 tag:일기`)이고, 그것을 읽고 고쳐 다시 적는\n  일은 뷰어가 한다 — <b>코어에 목록을 하나 더 만들지 않는 이유</b>는 그 값이 이미 질의로\n  표현되기 때문이다: 저장 방식이 둘이면 어느 것이 참인지 물어야 한다.\n\n  **`#`을 붙여 보여 준다.** 코어의 토큰은 이름만 들지만 사람이 아는 표기는 `#`이 붙은 쪽이다.\n}}\n<fieldset class=\"box by-tag\">\n  <legend class=\"subtitle is-6\">{{t.feeds.tags}}</legend>\n\n  {{#tags.length}}\n  <ul class=\"tags\">\n    {{#tags}}\n    <li class=\"tag-row\">\n      {{!\n        **그 태그의 피드로 간다** (2026-08-25). ~~해시태그를 훑는 화면이 아직 없다~~고\n        적어 두었던 자리이며, 같은 날 그 화면이 섰다 — 담긴 사람이 프로필로 가는 것과\n        같은 자리다.\n      }}\n      <a class=\"hashtag\" href=\"/-/tags/{{.}}\">#{{.}}</a>\n      <form method=\"post\" action=\"/-/feeds/{{list.id}}/tags\">\n        <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n        <input type=\"hidden\" name=\"remove\" value=\"{{.}}\">\n        <button class=\"button is-small\" type=\"submit\">{{t.feeds.remove_tag}}</button>\n      </form>\n    </li>\n    {{/tags}}\n  </ul>\n  {{/tags.length}}\n  {{^tags.length}}\n  <p class=\"empty\">{{t.feeds.empty_tags}}</p>\n  {{/tags.length}}\n\n  <form class=\"field has-addons\" method=\"post\" action=\"/-/feeds/{{list.id}}/tags\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <p class=\"control is-expanded\">\n      <label class=\"is-sr-only\" for=\"feed-tag\">{{t.feeds.add_tag}}</label>\n      <input class=\"input\" id=\"feed-tag\" type=\"text\" name=\"tag\"\n             placeholder=\"#{{t.feeds.tag_hint}}\" autocomplete=\"off\">\n    </p>\n    <p class=\"control\">\n      <button class=\"button\" type=\"submit\">{{t.feeds.add_tag}}</button>\n    </p>\n  </form>\n</fieldset>\n\n{{!\n  ── 4. 검색어 ────────────────────────────────────────────────────────────\n\n  **질의는 검색과 같은 문법이다.** 두 벌이면 *어디서 무엇이 되는가*를 매번 되묻는다 —\n  그래서 도움말도 검색 화면이 쓰는 그 목록이다(`views/search-guide.ts`).\n}}\n<div class=\"box by-search\">\n  <div class=\"field\">\n    <label class=\"label\" for=\"feed-query\">{{t.feeds.query}}</label>\n    <div class=\"control\">\n      {{!\n        **1번 블록의 폼에 붙는다**(`form`). 상자는 여기 서지만 값은 그 폼이 보낸다 —\n        저장이 하나뿐이므로 <b>고쳐 쓰는 값도 한 폼</b>이어야 한다.\n      }}\n      <input class=\"input\" id=\"feed-query\" form=\"feed-basics\" type=\"search\" name=\"query\"\n             value=\"{{list.query}}\" placeholder=\"{{t.feeds.query_hint}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"hint help\">{{t.feeds.query_help}}</p>\n  </div>\n\n  <section class=\"syntax content is-small\">\n    <h2>{{t.search.syntax}}</h2>\n    <dl>\n      {{#syntax}}\n      <dt><code>{{token}}</code></dt>\n      <dd>{{hint}} — <code>{{example}}</code></dd>\n      {{/syntax}}\n    </dl>\n    <p class=\"hint has-text-grey\">{{negation}}</p>\n  </section>\n</div>\n\n{{!\n  ── 단추 줄 — **화면 바닥에 셋이 나란히** (2026-08-25 요구) ────────────────\n\n  `저장` · `삭제` · `취소`.\n\n  **저장이 상자 안에 있지 않다.** 고쳐 쓰는 값이 상자 둘에 흩어져 있어(1번과 4번) 상자마다\n  단추를 두면 <b>같은 이름의 단추가 둘</b>이고, 사람은 어느 것이 무엇까지 저장하는지 물어야\n  한다 — `form` 속성이 그 둘을 한 폼으로 묶었으므로 단추도 하나면 된다.\n\n  **`취소`는 이동이라 링크다**(03d 마크업 규약) — 상태를 바꾸지 않으므로 폼도 토큰도 필요\n  없다. 단추처럼 보이는 것은 <b>줄에 나란히 서기 때문</b>이고, 하는 일은 여전히 이동이다.\n\n  **`삭제`만 색이 다르다.** 되돌릴 수 없는 하나이고, 차례로는 가운데에 서므로 색이 그것을\n  말한다 — 문서·포스트 액션 상자의 `지우기`와 같은 모양이다.\n}}\n<div class=\"feed-actions\">\n  <button class=\"button is-primary\" type=\"submit\" form=\"feed-basics\">{{t.settings.save}}</button>\n\n  <form method=\"post\" action=\"/-/feeds/{{list.id}}/delete\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <button class=\"button is-danger is-light\" type=\"submit\">{{t.feeds.delete}}</button>\n  </form>\n\n  <a class=\"button\" href=\"/-/feeds\">{{t.action.cancel}}</a>\n</div>\n\n</div>\n","body-feedfilters":"{{!\n  필터 격자의 <b>페이지</b> — 자바스크립트가 없을 때 서는 자리다.\n\n  모달이 이 페이지의 조각을 그 자리에 띄우므로 <b>같은 것을 두 벌 짓지 않는다</b>.\n  페이지에만 필요한 것은 빠져나갈 링크 하나다.\n}}\n{{> body-title}}\n{{> modal-feedfilters}}\n\n<p class=\"back\"><a class=\"button\" href=\"{{back}}\">{{t.back.cancel}}</a></p>\n","body-feedmenu":"{{> body-title}}\n\n{{!\n  피드 메뉴 구성 — **두 섹션이다** (M19 · 2026-08-24 요구).\n\n  **A. 활성**은 메뉴에 서는 것들이고 차례가 곧 메뉴의 차례다. **B. 비활성**은 서지 않는\n  것들이며, 켜면 활성의 맨 뒤에 붙는다.\n\n  **손잡이의 좌·우가 문서 조각과 같다**(05e 요구) — 왼쪽은 *어디에 놓는가*, 오른쪽은\n  *무엇을 하는가*. 이미 사람이 익힌 자리라 새로 배울 것이 없다.\n\n  **자바스크립트가 없어도 된다.** 끌어 놓기는 위·아래 단추 위에 얹히는 것이지 그것을 갈아\n  끼우는 것이 아니다 — 폼 하나가 지금 차례를 hidden으로 지고 있고, 누른 단추가 그것을\n  어떻게 바꿀지 말한다.\n}}\n{{#failed}}\n<p class=\"error\" data-key=\"feed_menu.failed\">{{.}}</p>\n{{/failed}}\n\n{{!\n  **~~기본값 탭의 안내 문구~~가 걷혔다** (2026-09-05 요구).\n\n  **탭줄을 밀어냈다** — 그 탭에서만 서는 줄이라 탭 사이를 오갈 때 <b>띠가 위아래로 흔들리고</b>,\n  누르려던 자리가 눌리지 않는다. 설명이 자리를 흔들면 그 설명이 손해를 낸다.\n\n  **말은 이미 탭 이름이 하고 있다**(`피드 바로가기 기본값`). *정한 적 없는 사람이 물려받는다*는\n  것은 `기본값`이라는 낱말이 뜻하는 바 그대로다.\n}}\n\n{{!\n  **범위를 고르는 줄은 관리자에게만 선다**(M19). 서비스 기본값은 *정한 적 없는 사람이\n  물려받는 것*이고, 그것을 정하는 사람은 관리자뿐이다.\n}}\n{{!\n  **탭줄은 세 화면이 나눠 쓴다** (2026-09-05 요구 — `내 피드 구성`).\n\n  ~~여기서 손수 그렸다~~ — `커스텀 피드`가 첫 탭으로 들어오면서 **같은 띠를 두 템플릿이\n  그리게 되었고**, 그때부터는 한 벌만 두는 편이 맞다(`body-tabs`). 무엇이 서는지는 뷰가\n  정한다: `기본값` 탭은 관리자에게만 넘어온다.\n}}\n{{> body-tabs}}\n\n<section class=\"feed-menu-section\">\n  <h2 class=\"subtitle is-6\">{{t.feeds.active}}</h2>\n  <ul class=\"feed-menu\" data-reorder=\"{{action}}\">\n    {{#active}}\n    <li class=\"feed-entry\" data-key=\"feed_menu.entry\" data-value=\"{{key}}\">\n      {{!\n        **왼쪽은 끌어 놓는 자리다.** 차례를 다시 세우는 것과 <b>다른 목록으로 옮기는 것</b>\n        을 겸한다(2026-08-25 요구) — 켜고 끄는 것도 결국 *메뉴에 있는가*라 같은 일이다.\n\n        자바스크립트가 없으면 이 손잡이는 아무 일도 하지 않는다 — 그때 차례를 바꾸고 켜고\n        끄는 것은 오른쪽 드롭다운이다.\n      }}\n      <span class=\"grip\" data-move aria-hidden=\"true\">{{> icon-grip}}</span>\n\n      <span class=\"feed-title\">{{title}}</span>\n      {{#system}}<span class=\"kind\">{{t.feeds.system}}</span>{{/system}}\n\n      {{!\n        **오른쪽은 점 셋의 드롭다운이다**(2026-08-25 요구 — *문서 편집 화면과 UX 맞추기*).\n        ~~단추 셋을 줄에 늘어놓던 것~~을 걷었다: 문서 조각의 우변이 이미 같은 일을 같은\n        모양으로 하고 있고(`iteration-item`), <b>같은 일이 화면마다 다른 모양이면 배우는\n        것이 두 번</b>이다.\n\n        `<details>`라 <b>자바스크립트 없이 열린다</b> — 안의 것은 그대로 평범한 폼이므로\n        위·아래·끄기는 끌어 놓기가 없어도 그 자리에 남는다.\n      }}\n      <div class=\"item-handle edit\">\n        <details class=\"dropdown dot-menu advanced\" data-dropdown>\n          <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.feeds.entry_actions}}</span></summary>\n          <ul class=\"dropdown-menu\">\n            {{^first}}\n            <li>\n              <form method=\"post\" action=\"{{action}}\">\n                <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n                <input type=\"hidden\" name=\"order\" value=\"{{order}}\">\n                <input type=\"hidden\" name=\"target\" value=\"{{key}}\">\n                <input type=\"hidden\" name=\"action\" value=\"up\">\n                <button type=\"submit\">{{t.feeds.up}}</button>\n              </form>\n            </li>\n            {{/first}}\n            {{^last}}\n            <li>\n              <form method=\"post\" action=\"{{action}}\">\n                <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n                <input type=\"hidden\" name=\"order\" value=\"{{order}}\">\n                <input type=\"hidden\" name=\"target\" value=\"{{key}}\">\n                <input type=\"hidden\" name=\"action\" value=\"down\">\n                <button type=\"submit\">{{t.feeds.down}}</button>\n              </form>\n            </li>\n            {{/last}}\n            <li>\n              <form method=\"post\" action=\"{{action}}\">\n                <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n                <input type=\"hidden\" name=\"order\" value=\"{{order}}\">\n                <input type=\"hidden\" name=\"target\" value=\"{{key}}\">\n                <input type=\"hidden\" name=\"action\" value=\"off\">\n                <button type=\"submit\">{{t.feeds.turn_off}}</button>\n              </form>\n            </li>\n          </ul>\n        </details>\n      </div>\n    </li>\n    {{/active}}\n  </ul>\n</section>\n\n{{!\n  **비활성 목록도 늘 선다** (2026-08-25 요구 — 목록 둘 사이를 끌어 놓는다). 비어 있을 때\n  감추면 <b>거기에 놓을 자리가 없어진다</b> — 마지막 하나를 끄는 길이 끌어 놓기로는 막힌다.\n\n  **`data-reorder`가 비어 있다.** 값이 있는 목록이 메뉴이고 그 값이 보낼 주소다;\n  여기 놓는다는 것은 <b>메뉴에서 빠진다</b>는 뜻이라 차례를 짓지 않는다.\n}}\n<section class=\"feed-menu-section\">\n  <h2 class=\"subtitle is-6\">{{t.feeds.inactive}}</h2>\n  <ul class=\"feed-menu\" data-reorder=\"\">\n    {{#inactive}}\n    <li class=\"feed-entry off\" data-key=\"feed_menu.entry\" data-value=\"{{key}}\">\n      <span class=\"grip\" data-move aria-hidden=\"true\">{{> icon-grip}}</span>\n\n      <span class=\"feed-title\">{{title}}</span>\n      {{#system}}<span class=\"kind\">{{t.feeds.system}}</span>{{/system}}\n      <div class=\"item-handle edit\">\n        <details class=\"dropdown dot-menu advanced\" data-dropdown>\n          <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.feeds.entry_actions}}</span></summary>\n          <ul class=\"dropdown-menu\">\n            <li>\n              <form method=\"post\" action=\"{{action}}\">\n                <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n                <input type=\"hidden\" name=\"order\" value=\"{{order}}\">\n                <input type=\"hidden\" name=\"target\" value=\"{{key}}\">\n                <input type=\"hidden\" name=\"action\" value=\"on\">\n                <button type=\"submit\">{{t.feeds.turn_on}}</button>\n              </form>\n            </li>\n          </ul>\n        </details>\n      </div>\n    </li>\n    {{/inactive}}\n  </ul>\n  {{!\n    ~~`모두 서 있습니다`~~를 걷었다(2026-08-25 요구). **빈 목록은 스스로 비어 있음을 말한다** —\n    제목 아래에 아무것도 없는 자리를 두고 그것을 또 문장으로 적는 것은 같은 말을 두 번 하는\n    일이다. 놓을 자리가 있다는 것은 <b>높이가</b> 말한다(`min-height`).\n  }}\n</section>\n\n{{!\n  **화면 아래에 아무것도 두지 않는다** (2026-08-25 요구).\n\n  ~~`내 피드로` 링크~~는 사이드바에 `내 피드`가 이미 서 있어 걷었고(M19의 넷째 조각),\n  ~~`시스템 피드는 끌 수만 있습니다`~~도 함께 걷었다 — <b>물음이 생기지 않는 규칙에는\n  안내가 필요 없다.</b> 시스템 피드는 애초에 커스텀 피드가 아니라 `내 피드`에 서지 않고,\n  드롭다운에 `지우기`가 없다는 것이 곧 그 말이다.\n}}\n","body-feeds":"{{> body-title}}\n{{> body-tabs}}\n\n{{!\n  **내 피드** — 내가 만든 커스텀 피드의 목록이다 (M19).\n\n  **메뉴 구성과 갈라졌다**(2026-08-24 요구). 한 화면에 두면 <b>메뉴에서 빼는 것</b>과\n  <b>피드를 지우는 것</b>이 나란히 서서 매번 어느 쪽인지 읽어야 한다 — 여기서 하는 일은\n  *만들고 없애는 것*이고, *어디에 세우는가*는 `메뉴 구성`이 진다.\n\n  **차례가 없다.** 세우는 차례는 메뉴의 것이므로 이 목록은 만든 순서 그대로다.\n}}\n{{#failed}}\n<p class=\"error\" data-key=\"feed_menu.failed\">{{.}}</p>\n{{/failed}}\n\n{{!\n  **만들 때는 이름만 받는다**(M13). 조건은 만들고 나서 고치는 화면이 받는다 — 사람을\n  고르는 일은 <b>이미 있는 피드</b>가 있어야 자연스럽다.\n\n  **검색 칸과 같은 모양이고 목록 앞에 선다** (2026-08-25 요구). ~~상자에 담아 화면 아래~~\n  두었던 것을 걷었다 — 이름 한 칸을 받는 일에 상자와 강조 버튼이 붙어 있으면 <b>화면에서\n  가장 큰 것이 가장 작은 일</b>이 된다. 검색 칸이 이미 그 크기의 본보기이고(`is-small` +\n  `has-addons`), <b>여기서 하는 일도 그것과 같다</b>: 한 줄 받아 한 번 누른다.\n}}\n<form class=\"search field has-addons\" method=\"post\" action=\"/-/feeds\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <p class=\"control is-expanded\">\n    <label class=\"is-sr-only\" for=\"feed-new\">{{t.feeds.new}}</label>\n    <input class=\"input is-small\" id=\"feed-new\" type=\"text\" name=\"title\"\n           placeholder=\"{{t.feeds.title}}\" required>\n  </p>\n  <p class=\"control\">\n    <button class=\"button is-small\" type=\"submit\">{{t.feeds.new}}</button>\n  </p>\n</form>\n\n{{#feeds.length}}\n<ul class=\"feed-menu\">\n  {{#feeds}}\n  <li class=\"feed-entry\" data-key=\"feed\" data-value=\"{{id}}\">\n    <a class=\"feed-title\" href=\"/-/feeds/{{id}}\">{{title}}</a>\n    {{!\n      **조건을 한 줄로 말한다** — 목록에서 알고 싶은 것은 *이 피드가 무엇을 담는가*다.\n\n      **그 종류가 쓰는 것만 적는다**(2026-08-25 고침). ~~담긴 사람 수와 검색 조건을 나란히~~\n      적던 것은 둘이 겹치던 시절의 말이라, 해시태그 피드에 `0명`이 붙어 <b>사람을 담아야\n      하는 것처럼</b> 읽혔다. 무엇이 그 종류의 조건인지는 서버가 정해서 준다(`condition`).\n    }}\n    <span class=\"kind\">{{kind_label}}</span>\n    {{#condition}}<span class=\"count\">{{.}}</span>{{/condition}}\n    {{#empty_condition}}<span class=\"off\">{{t.feeds.empty_condition_short}}</span>{{/empty_condition}}\n\n    {{!\n      **줄의 일들은 점 셋에 담긴다** (2026-09-05 요구 — ~~`고치기` 링크 하나~~).\n\n      **포스트 액션과 같은 모양이다**: 딸린 대상이 한 줄이고, 담기는 것이 둘 이상이면\n      상자가 진다. `삭제하기`가 그 줄에 서면서 <b>되돌릴 수 없는 것이 목록에 그대로\n      노출</b>되는데, 상자는 그것을 한 겹 안에 둔다.\n\n      **`삭제하기`가 뒤다** — 되돌릴 수 없는 것이 여는 손에서 가장 먼 자리다(포스트 액션의\n      그 규칙 그대로).\n    }}\n    <span class=\"tools\">\n      <details class=\"dropdown dot-menu\" data-dropdown>\n        <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.screen.actions}}</span></summary>\n        <ul class=\"dropdown-menu\">\n          <li><a class=\"action to-edit\" href=\"/-/feeds/{{id}}/edit\">{{t.feeds.edit}}</a></li>\n          {{!\n            **삭제는 폼이다** — 링크로 두면 눌러서 지워지는 주소가 생기고, 그것은 남이\n            누르게 만들 수 있다(`csrf`가 그 자리를 막는다). 고치기 화면이 이미 같은 폼을\n            지고 있으므로 가는 곳도 그것과 같다.\n          }}\n          <li>\n            <form method=\"post\" action=\"/-/feeds/{{id}}/delete\">\n              <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n              <button class=\"action delete\" type=\"submit\">{{t.feeds.delete}}</button>\n            </form>\n          </li>\n        </ul>\n      </details>\n    </span>\n  </li>\n  {{/feeds}}\n</ul>\n{{/feeds.length}}\n{{^feeds.length}}\n<p class=\"empty\">{{t.feeds.none}}</p>\n{{/feeds.length}}\n\n\n\n{{!\n  **화면 아래에 아무것도 두지 않는다** (2026-08-25 요구).\n\n  ~~`메뉴에 세우기` 링크~~는 사이드바의 `주요 피드` 드롭다운이 이미 그 화면으로 가는\n  문이라 걷었고, ~~`커스텀 피드는 사람과 검색 조건으로 짓습니다`~~도 함께 걷었다 —\n  <b>고치는 화면이 그 둘을 칸으로 내놓고 있어</b>(`/feeds/{id}/edit`) 여기서 미리 말할\n  것이 없다: 만드는 폼이 이름만 받는 것이 이미 *조건은 그 다음이다*를 말한다.\n\n  메뉴 구성 화면에서도 같은 날 같은 이유로 아래 문구 둘을 걷었다.\n}}\n","body-group":"{{!\n  **그룹 하나의 등록정보 — 화면이다** (2026-09-23 요구).\n\n  ~~모달이었다~~. 이 뷰어의 모달은 `<dialog>` 하나뿐이라 **그 위에 둘째를 띄울 수 없고**, 뱃지에\n  설 이모지를 고르려면 <b>고치던 값을 들고 나갔다가 되돌려 놓는</b> 춤이 필요했다 — 그 춤에서\n  고른 직후의 미리보기가 <i>없음</i>으로 서는 자국이 났다.\n\n  **폼이 화면에 살면 그 일이 아예 없다** — 고르는 창이 떠도 이 화면은 뒤에 그대로 있고, 닫히면\n  그 자리로 돌아온다. 쓰기 폼이 같은 까닭으로 화면이 되었다(46 확정 4).\n\n  **속은 한 벌이다**(`modal-group`) — 이름이 그때의 것이라 남겨 두었다. 담기는 것과 손은\n  그대로이고 갈리는 것은 <b>어디에 서는가</b>뿐이라, 조각을 둘로 두면 한쪽만 고쳐진다.\n}}\n{{> body-title}}\n\n{{#notice}}<p class=\"notice notification is-success is-light\">{{notice}}</p>{{/notice}}\n{{#problem}}<p class=\"error notification is-danger is-light\">{{problem}}</p>{{/problem}}\n\n{{> modal-group}}\n","body-homepage-document":"{{!\n  홈페이지가 문서를 가리킬 때 서는 화면 (2026-09-14 요구).\n\n  **루트에 선 채로 대상 문서의 제목과 본문을 담는다.** 주소를 갈아 끼우고 문서 화면으로\n  보내면 <b>홈페이지라는 사실이 렌더 한 번에만 살아</b> 새로고침에서 문서 화면이 되었다 —\n  그래서 자리를 옮기지 않고 여기서 그린다.\n\n  **제목줄은 피드의 것이다**(`feed_switch`) — 입구에서 사람이 하는 일은 <i>여기서 어디로\n  갈까</i>이고, 그것이 첫 화면이 지는 일이다. 역참조 곁문은 서지 않는다: <i>누가 여기를\n  가리키는가</i>는 <b>그 문서를 문서로 열었을 때</b>의 물음이다.\n\n  **문서 화면을 빌려 쓰지 않는 이유**는 그 템플릿이 <i>문서인가 홈페이지인가</i>를 매번\n  갈라야 하기 때문이다 — 스킨을 짜는 사람에게 <b>한 파일 안의 두 화면</b>이 된다.\n\n  **본문은 서버가 구운 것을 그대로 세운다**(문서 화면과 같다). 손잡이는 서지 않는다 —\n  고치는 일은 문서의 자리에서 한다.\n}}\n{{> body-title}}\n\n{{!\n  **~~닫혔다는 알림이 여기 섰다~~** (2026-09-18 요구) — 문서 화면과 함께 걷었다.\n}}\n{{!\n  **문서 화면과 같은 옷을 입는다**(`document-body`) — 같은 본문이 두 자리에서 다르게 보이면\n  그것이 곧 두 벌의 규칙이 된다.\n\n  **`data-blocks`는 붙이지 않는다.** 그 표가 손잡이를 세우는 자리이고(읽는 화면의 블록\n  조작), 입구는 고치는 자리가 아니다.\n}}\n{{!\n  **~~문서로 가는 문~~을 두지 않는다** (2026-09-14 요구).\n\n  근거는 *제 주소를 잃는다*였는데 <b>잃지 않는다</b>: 대상 주소는 설정 화면에 그대로 적혀\n  있고(`home.target_label`) 문서는 위키링크·검색·사이드바·주소창으로 열린다.\n\n  **쓸모 있는 사람이 편집자뿐인데 편집자는 그 주소를 아는 사람이다** — 입구에 선 모두가\n  보는 줄로 둘 값이 아니다.\n}}\n<article class=\"document-body\">\n  {{&body}}\n</article>\n","body-homepage":"{{!\n  홈페이지 — **이 서비스가 무엇인지 말하는 자리** (2026-09-05 요구).\n\n  **폴백이 곧 이 화면이다.** 카멜에는 세울 대상을 정하는 설정이 있지만(뷰어의 `site.json`)\n  하멜에는 그 자리가 아직 없다 — 그래서 여기 적힌 것이 <b>대상이 정해지기 전까지 서는\n  본문</b>이고, 그 자리는 **스킨의 것**이다(요구): 뷰가 문장을 지으면 스킨을 갈아도 같은\n  글이 따라온다.\n\n  **담은 것은 두 저장소의 README에서 왔다**(`sierra`·`hamel`). **전문을 옮기지는 않았다** —\n  그쪽 문서의 몸은 <i>세우고 돌리는 법</i>(도커 명령·환경 변수)이고 그것은 이 서비스를 처음\n  여는 사람이 읽을 것이 아니다. **머리와 뜻을 옮기고 나머지는 그 문서로 보낸다.**\n\n  **제목줄은 피드의 것과 같다** — 갈아타는 상자가 여기에도 선다: 첫 화면에서 어느 피드로든\n  갈 수 있어야 한다.\n}}\n{{> body-title}}\n\n<div class=\"content\">\n  <p>\n    <b>빠르게 쓴 글이 나중에 찾아 읽히는 문서가 되는 곳.</b>\n    SNS의 입력 속도로 포스트를 쌓고, 그중에서 골라 하이퍼텍스트로 엮어 아카이브로 남깁니다.\n    연합은 그 글이 이 서버 밖에서도 읽히게 하는 통로이지 목적이 아닙니다.\n  </p>\n\n  <h2>Sierra 시에라 — 연합우주 호환 REST 서버</h2>\n  <p>\n    이 서비스의 코어입니다. 계정과 글, 문서와 아카이브, 그리고 연합을 집니다.\n    확장 넷이 런타임으로 붙습니다 — 문서(<code>sierradoc</code>) · 로그인 어댑터 둘\n    (<code>sierra-oauth-github</code> · <code>sierra-oauth-google</code>) ·\n    개발 도구(<code>sierra-tool-dev</code>).\n  </p>\n\n  <h2>Hamel 하멜 — 손에 쥔 화면</h2>\n  <p>\n    지금 보고 있는 이 화면입니다. <b>설치되어 온전한 앱으로 도는 것</b>이 목적이며\n    (<i>홈 화면에 추가</i> · <i>앱 설치</i>), 서버가 시에라를 프록시하고 브라우저가 그립니다.\n    오프라인은 지원하지 않습니다.\n  </p>\n  <p>\n    <code>브라우저(라우팅 · 뷰 모델 · 렌더) → 서버(세션 · 프록시 · 스킨 배달) → 시에라(API)</code>\n  </p>\n\n  {{!\n    **~~여기에 서버 피드로 가는 문을 두었다~~** — 걷었다(2026-09-05 요구).\n\n    그 근거는 *소개만 있고 들어갈 문이 없으면 막다른 자리가 된다*였는데, **제목줄이 이미\n    그 문이다**: 갈아타는 상자가 이 화면에도 서고 거기서 어느 피드로든 간다. 같은 문을 두\n    번 두면 <b>첫 화면이 안내가 아니라 갈림길이 된다.</b>\n  }}\n</div>\n","body-login":"{{!\n  로그인 — **수단을 고른다** (05p).\n\n  **그림은 조각이 진다**(`login-providers`) — 계정 추가 화면이 같은 것을 세우며, 마크업을\n  두 벌 두면 한쪽만 고쳐진다(2026-09-25).\n\n  **이 화면과 계정 추가 화면은 다른 화면이다.** 서는 것이 같아도 <b>거는 판단이 다르다</b>:\n  이쪽은 *이미 들어와 있으면 물을 것이 없다*이고, 저쪽은 들어와 있어야 하는 자리다.\n}}\n{{> body-title}}\n\n{{> login-providers}}\n","body-messages":"{{> body-title}}\n{{!\n  **방향으로 가르는 탭**(2026-09-08 요구). 코어는 받은 것과 보낸 것을 <b>한 목록으로</b>\n  주므로(참여한 최상위 메시지) 여기서 거르는 것은 화면이고, 입구는 전체다 — 대화는 오고\n  가는 것이라 그 자리가 기본이다.\n}}\n{{> body-tabs}}\n{{#messages.length}}\n{{> body-newer}}\n{{!\n  **피드와 같은 마크업이다**(2026-09-08 요구).\n\n  ~~`div.messages > div.message`로 감싸고 곁줄을 달았다~~ — 그러면 이 목록만 자기 마크업을\n  지고, 피드를 고칠 때 여기가 따라오지 않는다. <b>줄마다 서는 것은 글 한 편</b>이고 그것은\n  이미 `<article>`이다.\n\n  **메시지함만의 사실은 글에 얹힌다** — 읽었는가는 `data-unread`로 그 `<article>`이 지고,\n  누구와의 대화인가는 머리의 봉투 곁이 진다(받는 사람). **~~`보냄` 문구~~는 걷었다**: 보낸\n  것에는 그 자리에 상대가 서 있으므로 낱말이 같은 말을 두 번 한다.\n}}\n{{#messages}}{{> iteration-post}}{{/messages}}\n{{> body-older}}\n{{/messages.length}}\n{{^messages.length}}\n<p class=\"empty\">{{t.empty.messages}}</p>\n{{/messages.length}}\n","body-notifications":"{{> body-title}}\n\n{{!\n  **단추는 제목줄의 우상단에 있다** (2026-08-26 요구 — `body-title`의 `화면 액션`).\n  ~~여기 줄로 서 있던~~ 것을 그 상자로 옮겼고, 이 화면이 내는 것은 담기는 항목뿐이다\n  (`actions-notifications`).\n\n  **자리는 비워 두고 글자는 스크립트가 넣는다.** 푸시를 지원하지 않는 브라우저나 사람이\n  거절한 경우에 <b>그 사실이 설 곳</b>이며, 아무 일도 없으면 비어 있어 아무것도 보이지 않는다.\n}}\n{{#push}}<p class=\"meta help\" data-push-state></p>{{/push}}\n\n{{#notifications.length}}\n{{> body-newer}}\n<ul class=\"notifications\">\n  {{#notifications}}\n  {{!\n    **한 목록에 두 갈래가 선다**(2026-08-23 요구). 코어의 알림(사람이 나에게 한 일)과\n    뷰어의 작업(내가 걸어 둔 일)이 <b>시간순으로 섞여</b> 온다 — 위아래로 갈라 두었더니\n    어제 뜬 백업이 방금 온 팔로우보다 위에 섰다.\n\n    겹치는 자리는 이름이 같다(`kind`·`label`·`created_at`·`unread`). 다른 것만 `is_job`으로\n    갈린다: 작업에는 사람이 없고, 갈 곳이 글이 아니라 작업과 백업이다.\n  }}\n  <li class=\"notification {{type}}\" data-unread=\"{{unread}}\">\n    <span class=\"kind\">{{kind}}</span>\n    {{#unread_label}}<span class=\"unread\">{{.}}</span>{{/unread_label}}\n    {{^is_job}}\n    <a href=\"/@{{actor.handle}}\" data-profile=\"{{actor.handle}}\">{{#actor}}{{> name-badged}}{{/actor}}</a>\n    {{/is_job}}\n    <span class=\"what\">{{label}}</span>\n    {{#post_href}}<a href=\"{{.}}\">{{t.notify.view_post}}</a>{{/post_href}}\n    {{!\n      **청은 이 줄에서 정한다** (2026-08-31 · 잠긴 계정). 프로필로 가야 정할 수 있으면\n      그 청은 쌓이기만 한다.\n    }}\n    {{#is_follow_request}}\n    <form method=\"post\" action=\"/-/requests/{{actor.id}}\">\n      <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n      <button class=\"button is-primary\" type=\"submit\" name=\"decision\" value=\"authorize\">{{t.notify.authorize}}</button>\n      <button class=\"button\" type=\"submit\" name=\"decision\" value=\"reject\">{{t.notify.reject}}</button>\n    </form>\n    {{/is_follow_request}}\n    {{#is_job}}\n    <a href=\"/-/jobs/{{id}}\">{{t.notify.view_job}}</a>\n    {{#backup}}<a href=\"/-/backups/{{.}}\">{{t.notify.view_backup}}</a>{{/backup}}\n    {{/is_job}}\n    <time datetime=\"{{created_at}}\"{{#created_title}} title=\"{{.}}\"{{/created_title}}>{{created_display}}</time>\n\n    {{!\n      항목별 읽음. 메시지 목록과 같은 모양이다 — `글 보기`를 따라간 것으로는 읽음이 되지\n      않는다(그러면 GET이 상태를 바꾼다). 눌러도 **목록에서 사라지지 않는다.**\n\n      **보낼 곳은 항목이 안다**(`read_action`) — 코어의 알림과 뷰어의 작업이 서로 다른 문을\n      쓰므로, 스킨이 갈래를 보고 주소를 짓게 두면 그 지식이 두 곳에 생긴다.\n    }}\n    {{#unread}}\n    <form class=\"actions\" method=\"post\" action=\"{{read_action}}\">\n      <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n      <input type=\"hidden\" name=\"return\" value=\"{{path}}\">\n      <button type=\"submit\">{{t.action.mark_read}}</button>\n    </form>\n    {{/unread}}\n  </li>\n  {{/notifications}}\n</ul>\n{{> body-older}}\n{{/notifications.length}}\n{{^notifications.length}}\n<p class=\"empty\">{{t.empty.notifications}}</p>\n{{/notifications.length}}\n","body-onboarding":"{{> body-title}}\n\n{{!\n  아이디를 정하는 화면 (05p). Sierra가 여기로 보낸다.\n\n  **되돌릴 수 없는 것 하나를 묻는다.** 아이디는 주소이자 멘션이자 연합 actor URI가 부르는\n  이름이라 한번 정하면 바꾸지 못한다 — 그 사실을 화면이 그대로 적는다.\n\n  **문법과 한도는 코어가 준다.** 여기에 다시 적으면 두 곳이 갈린다.\n\n  **동의를 여기서 받는다** (2026-09-14 요구). ~~로그인 화면이 *계속하면 동의한 것으로\n  봅니다*라 적었다~~ — 그것은 <b>읽었는지 물은 적이 없는 문장</b>이다. 계정이 서는 자리가\n  이곳이므로, 서비스 문서 셋을 하나씩 걸고 <b>모두 체크해야 보낼 수 있게</b> 한다.\n}}\n{{#failed}}\n<p class=\"error\" data-key=\"onboarding.failed\">{{.}}</p>\n{{/failed}}\n\n<form class=\"compose onboarding\" method=\"post\" action=\"/-/onboarding\" data-gate>\n  {{! 티켓은 우리에게도 불투명하다 — Sierra가 봉인해 보낸 것을 그대로 되돌려 보낸다. }}\n  <input type=\"hidden\" name=\"ticket\" value=\"{{ticket}}\">\n  <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n\n  <label for=\"onboarding-handle\">{{t.onboarding.handle}}</label>\n\n  {{!\n    **묻는 단추가 칸 옆에 선다** (2026-09-14 요구).\n\n    <b>정하기 전에 묻는다.</b> 아이디는 한번 정하면 바꾸지 못하므로(아래 경고) 보내고 나서\n    거절당하는 것보다 <b>누르기 전에 아는</b> 편이 낫다.\n\n    **답은 칸 아래에 남는다** — 물은 자리와 답이 붙어 있어야 무엇에 대한 답인지가 읽힌다.\n\n    **`type=\"button\"`이다.** 폼 안의 단추는 기본이 전송이라, 이것을 빠뜨리면 <b>누르는 순간\n    계정이 선다.</b>\n  }}\n  <div class=\"handle-row\">\n    <input id=\"onboarding-handle\" type=\"text\" name=\"handle\" value=\"{{handle}}\" maxlength=\"{{max}}\"\n           pattern=\"{{pattern}}\" required autofocus data-handle>\n    <button class=\"button is-light\" type=\"button\" data-handle-check>{{t.onboarding.check}}</button>\n  </div>\n  <p class=\"handle-answer\" data-handle-answer hidden></p>\n\n  <p class=\"hint\">\n    <b>{{t.onboarding.warn}}</b> {{t.onboarding.note}}\n  </p>\n\n  {{!\n    **줄마다 문서 하나다** (2026-09-14 요구). 체크 옆에 그 문서로 가는 링크가 서고, 누르면\n    읽으러 간다 — <b>읽지 않고 체크하는 것을 막을 수는 없지만</b> 적어도 <i>무엇에 동의하는가</i>가\n    한 줄에 하나씩 적힌다.\n\n    **정해 둔 것만 선다** — 비어 있는 설정은 그런 문서가 없는 서버이고(05p와 같은 규칙)\n    없는 곳으로 가는 체크를 세우지 않는다. 셋 다 없으면 이 묶음이 통째로 서지 않는다.\n\n    **여기서는 상자로 뜬다** (2026-09-14 요구). 읽으러 <b>떠나면 정하던 아이디를 잃는다</b> —\n    칸에 친 것도 체크한 것도 화면과 함께 사라지므로, 문서는 <i>보던 자리를 잃지 않고</i>\n    열려야 한다. 상자에는 <b>제목과 본문만</b> 담는다.\n  }}\n  {{#acknowledge.length}}\n  <ul class=\"acknowledge\">\n    {{#acknowledge}}\n    <li>\n      <label>\n        <input type=\"checkbox\" name=\"read_{{kind}}\" required data-gate-box>\n        <a href=\"{{href}}\" data-doc-modal=\"{{kind}}\">{{label}}</a> {{t.onboarding.acknowledge}}\n      </label>\n    </li>\n    {{/acknowledge}}\n  </ul>\n  {{/acknowledge.length}}\n\n  {{!\n    **다 체크해야 눌린다**(요구). 브라우저의 `required`가 이미 막지만 그것은 <b>누른 뒤에</b>\n    말하는 방식이라, 단추 자체를 잠가 <i>아직 남았다</i>를 먼저 보인다.\n\n    **처음에는 잠겨 있다** — 체크가 하나라도 있으면 그렇다. 스크립트가 그 자리를 연다\n    (`data-gate`).\n  }}\n  <button class=\"button is-primary\" type=\"submit\" {{#acknowledge.length}}disabled{{/acknowledge.length}}>\n    {{t.action.confirm}}\n  </button>\n</form>\n","body-people":"{{> body-title}}\n{{!\n  **두 명단이 서로를 잇는다**(05e). 프로필 카드에서 팔로워 자리를 팔로우 토글이 가져갔으므로\n  (요구 — *팔로워(팔로우 토글)*) 팔로워 명단으로 가는 길이 여기 말고 없다.\n}}\n<p class=\"crosslinks\">\n  <a class=\"button\" href=\"/@{{account.handle}}\">{{t.back.profile}}</a>\n  <a href=\"/@{{account.handle}}/-/followers\">{{t.card.followers}}</a>\n  <a href=\"/@{{account.handle}}/-/following\">{{t.card.following}}</a>\n</p>\n\n{{#people.length}}\n{{> body-newer}}\n<ul class=\"people\">\n  {{#people}}<li>{{> iteration-person}}</li>{{/people}}\n</ul>\n{{> body-older}}\n{{/people.length}}\n{{^people.length}}\n<p class=\"empty\">{{t.empty.people}}</p>\n{{/people.length}}\n","body-post":"{{> body-title}}\n<div class=\"thread\">\n  {{#thread}}{{> iteration-post}}{{/thread}}\n</div>\n","body-postdiff":"{{!\n  판 둘의 <b>견줌</b> — 줄이 `+`·`-`로 선다 (2026-09-06 요구).\n\n  **문서의 견줌과 같은 모양이다**(`camelize`의 `body-docdiff`). 갈리는 것은 <b>덩이가\n  없다</b>는 것뿐이다: 문서는 조각의 배열이라 *무엇이 들고 났는가*가 따로 서지만, 글은\n  <b>한 덩이의 글자</b>다.\n\n  **표는 그림이 아니라 글자다**(03d — 색이 유일한 신호가 아니다). 색을 쓰지 않는 스킨에서도\n  무엇이 들고 났는지 읽힌다.\n}}\n{{> body-title}}\n{{!\n  **돌아가는 길은 취소이고, 가는 길은 고르는 것이다** (2026-09-16 요구).\n\n  앞엣것은 이 화면을 접는 일이라 수식어 없는 `button`이고, 뒤엣것은 <b>다른 자리로 가는\n  길</b>이라 으뜸이 아닌 `is-light`다 — 나란히 선 둘이 같은 무게면 어느 쪽이 나가는 문인지가\n  읽히지 않는다.\n\n  **가운뎃점을 걷었다** — 단추 둘 사이의 점은 <i>글 속의 나열</i>에 쓰는 것이고, 사이는\n  줄이 벌린다(`.back-row`). **자리는 그대로 둔다.**\n}}\n<p class=\"back-row\">\n  <a class=\"button\" href=\"{{post.permalink}}/-/revisions\">{{t.back.to_revisions}}</a>\n  <a class=\"button is-light\" href=\"{{post.permalink}}\">{{t.revision.current_post}}</a>\n</p>\n\n<h2 class=\"title is-6\">{{diff.heading}}</h2>\n\n{{#diff.lines.length}}\n<pre class=\"diff-lines\">{{#diff.lines}}<span class=\"line {{mark}}\">{{sign}} {{text}}\n</span>{{/diff.lines}}</pre>\n{{/diff.lines.length}}\n\n{{!\n  **같음과 재지 않음은 다른 사실이다.** 한쪽이 너무 길면 코어가 줄을 견주지 않고 빈 목록을\n  내는데, 그때 *같다*고 적으면 거짓이 된다.\n}}\n{{#diff.same}}\n<p class=\"empty\">{{t.diff.same}}</p>\n{{/diff.same}}\n{{#diff.too_long}}\n<p class=\"empty\">{{t.diff.too_long}}</p>\n{{/diff.too_long}}\n","body-postrevisions":"{{!\n  글의 <b>판 목록</b> — 표다 (2026-09-06 요구).\n\n  **라디오 둘이 견줄 두 판을 고른다.** 문서의 판 목록이 같은 모양을 쓴다(`camelize`의\n  `body-docrevisions`) — 목록이 곧 고르는 자리이고, 그것이 이 화면이 표로 서는 이유다.\n\n  **기본은 이웃한 둘이다.** 열고 아무것도 고르지 않은 채 누르는 것이 가장 흔한 길이며,\n  그때 보고 싶은 것은 *방금 무엇이 바뀌었나*다.\n\n  **자바스크립트가 없어도 돈다** — 라디오와 `GET` 폼 하나다. 고른 결과가 곧 주소이므로\n  견줌 하나를 그대로 건넬 수 있다.\n}}\n{{> body-title}}\n{{!\n  **돌아가는 길은 취소다** (2026-09-16 요구) — 이 화면을 접고 보던 자리로 가는 것이라,\n  전역 규칙의 <b>취소</b>가 그대로 이 자리의 이름이다: 수식어 없는 `button`이고,\n  <b>되돌아가는 것이므로 링크</b>다. **자리는 그대로 둔다.**\n}}\n<p><a class=\"button\" href=\"{{post.permalink}}\">{{t.back.to_post}}</a></p>\n\n{{#revisions.length}}\n<form class=\"revision-compare\" method=\"get\" action=\"{{compare}}\">\n  <table class=\"revisions\">\n    <thead>\n      <tr>\n        <th scope=\"col\"><abbr title=\"{{t.diff.pick_from}}\">{{t.diff.from}}</abbr></th>\n        <th scope=\"col\"><abbr title=\"{{t.diff.pick_to}}\">{{t.diff.to}}</abbr></th>\n        <th scope=\"col\">{{t.revision.seq}}</th>\n        <th scope=\"col\">{{t.revision.author}}</th>\n        <th scope=\"col\">{{t.revision.preview}}</th>\n      </tr>\n    </thead>\n    <tbody>\n      {{#revisions}}\n      <tr data-key=\"revision\" data-value=\"{{seq}}\">\n        <td><input type=\"radio\" name=\"from\" value=\"{{seq}}\"{{#from_checked}} checked{{/from_checked}}\n                   aria-label=\"{{t.diff.pick_from}}\"></td>\n        <td><input type=\"radio\" name=\"to\" value=\"{{seq}}\"{{#to_checked}} checked{{/to_checked}}\n                   aria-label=\"{{t.diff.pick_to}}\"></td>\n        {{!\n          **번호가 그 판의 문이다** — 눌러서 그때의 모양을 통째로 본다.\n        }}\n        <th scope=\"row\"><a href=\"{{post.permalink}}/{{seq}}\">{{seq_label}}</a>\n            {{#current}}<span class=\"mark\" data-key=\"revision.current\" data-value=\"true\">{{t.revision.in_use}}</span>{{/current}}</th>\n        <td>{{#author}}<a class=\"handle\" href=\"/@{{handle}}\">{{> name-badged}}</a>{{/author}}\n            <time datetime=\"{{created_at}}\"{{#created_title}} title=\"{{.}}\"{{/created_title}}>{{created_display}}</time></td>\n        {{!\n          **미리보기가 비면 그 사실을 적는다** — 빈 칸은 무엇이 없는지 말하지 않는다.\n        }}\n        <td class=\"preview\">{{#empty}}<span class=\"meta\">{{.}}</span>{{/empty}}{{^empty}}{{preview}}{{/empty}}</td>\n      </tr>\n      {{/revisions}}\n    </tbody>\n  </table>\n  <button class=\"button is-small\" type=\"submit\">{{t.diff.compare}}</button>\n</form>\n{{/revisions.length}}\n\n{{^revisions.length}}\n<p class=\"empty\">{{t.revision.none}}</p>\n{{/revisions.length}}\n","body-privacy":"{{!\n  개인정보정책 — **사람의 것을 어떻게 다루는지 말하는 자리** (2026-09-14 요구).\n\n  **홈페이지와 같은 모양이다.** 자기 주소에 선 채로 설정이 가리키는 문서의 <b>본문만</b>\n  담는다 — 그 문서로 곧장 보내면 제목이 그 문서의 이름이 되어 <i>여기가 어디인가</i>를\n  주소로도 제목으로도 알 수 없다.\n\n  **제목은 자리의 이름이다.** 뷰가 고정해 넘긴다(`nav.*`) — 문서가 무엇으로 불리든 여기\n  서 있는 동안은 개인정보정책이다.\n\n  **제목줄은 피드의 것이다**(갈아타는 상자). 읽고 나서 하는 일은 <i>여기서 어디로 갈까</i>이고\n  이 화면은 어느 피드에도 매여 있지 않다.\n\n  **셋을 한 파일로 합치지 않는다**(사이드바의 잎 여섯과 같은 판단). 지금은 거의 같지만\n  <b>따로 손댈 자리</b>가 서 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n\n<article class=\"content document-body\">\n  {{&body}}\n</article>\n","body-profile":"{{!\n  **프로필 화면 상단은 카드 그대로다**(05e 요구 — *개별 포스트에서 띄우는 모달과 같은 구성*).\n\n  전에는 같은 것을 두 벌 적어 두었고, 그래서 카드에만 없는 것이 생겼다(실제로 아바타와\n  팔로우 버튼이 빠져 있었다). 이제 한 벌이다 — 카드가 고쳐지면 여기도 함께 고쳐진다.\n\n  **제목 조각은 남는다.** 그것은 규약이고(`prefix`·`heading`) 감추는 것은 스타일시트의\n  몫이다 — 구조가 가릴 수 있는 것을 표현에 미루지 않는다는 규칙의 반대쪽이다: 여기서는\n  **표현이 정할 것을 구조가 지우지 않는다**.\n\n  **주석 안에 두 겹 중괄호를 적지 않는다.** Mustache의 주석은 <b>처음 만나는 닫는\n  중괄호 두 개에서 끝나므로</b>, 안에 태그를 적으면 거기서 주석이 끊기고 나머지가 화면에\n  그대로 나온다 — 실제로 이 자리에서 그렇게 됐고 제목까지 함께 삼켰다.\n}}\n{{> body-title}}\n\n<section class=\"profile\">\n  {{> modal-card}}\n\n  {{!\n    **이사한 계정은 그렇게 선다** (M29 바 · 2026-09-06).\n\n    표시가 없으면 그 사람은 <b>말이 없어진 것</b>처럼 보이고, 팔로우하려는 사람이 빈 계정을\n    팔로우한다. 새 주소는 <b>글자로 세운다</b> — 남의 서버 주소를 우리 화면의 링크로 걸면\n    그 자리가 곧 아무나 쓸 수 있는 링크가 된다.\n  }}\n  {{#moved_to}}\n  <p class=\"moved-note\" data-key=\"account.moved_to\" data-value=\"{{.}}\">\n    {{t.migration.moved}} <code>{{.}}</code>\n  </p>\n  {{/moved_to}}\n</section>\n\n{{!\n  **담아 둔 것뿐이라고 적는다** (2026-09-06).\n\n  남의 서버의 타임라인이 아니라 <b>우리가 받은 것</b>이고 그 앞은 비어 있다 — 적지 않으면\n  <i>글이 이것뿐인 사람</i>으로 읽힌다.\n}}\n{{#remote_note}}\n<p class=\"remote-note help\">{{.}}</p>\n{{/remote_note}}\n\n{{> body-tabs}}\n\n{{#posts.length}}\n{{> body-newer}}\n<div class=\"feed\">\n  {{#posts}}{{> iteration-post}}{{/posts}}\n</div>\n{{> body-older}}\n{{/posts.length}}\n{{^posts.length}}\n<p class=\"empty\">{{t.empty.posts}}</p>\n{{/posts.length}}\n","body-revision":"{{> body-title}}\n{{!\n  **돌아가는 길은 취소이고, 가는 길은 고르는 것이다** (2026-09-16 요구).\n\n  앞엣것은 이 화면을 접는 일이라 수식어 없는 `button`이고, 뒤엣것은 <b>다른 자리로 가는\n  길</b>이라 으뜸이 아닌 `is-light`다 — 나란히 선 둘이 같은 무게면 어느 쪽이 나가는 문인지가\n  읽히지 않는다.\n\n  **가운뎃점을 걷었다** — 단추 둘 사이의 점은 <i>글 속의 나열</i>에 쓰는 것이고, 사이는\n  줄이 벌린다(`.back-row`). **자리는 그대로 둔다.**\n}}\n<p class=\"back-row\">\n  <a class=\"button\" href=\"{{post.permalink}}/-/revisions\">{{t.back.to_revisions}}</a>\n  <a class=\"button is-light\" href=\"{{post.permalink}}\">{{t.revision.current_post}}</a>\n</p>\n\n{{!\n  판 하나를 그리는 규칙은 `revision` 부분이 갖는다 — 이력 목록과 같은 것을 쓴다.\n  여기서 다시 짜면 한 판의 모양이 두 곳에서 갈라진다.\n}}\n<ol class=\"revisions\">\n  {{#revision}}{{> iteration-revision}}{{/revision}}\n</ol>\n","body-search":"{{> body-title}}\n\n{{> search-head}}\n{{!\n  **담긴 것의 탭은 둘째 줄이다** (2026-09-05 요구).\n\n  **대상이 먼저다**(포스트·계정) — 그것이 *무엇을 찾는가*이고, 이 줄은 찾은 것 가운데\n  **무엇을 담은 글인가**다. 축이 다르므로 한 줄에 섞지 않는다.\n\n  **계정 탭에서는 서지 않는다** — 사람에게는 첨부도 인용도 없다. 뷰가 그때 넘기지 않는다.\n}}\n{{#content_tabs.length}}\n<nav class=\"tabs is-small\" aria-label=\"{{t.nav.search}}\">\n  <ul>\n    {{#content_tabs}}\n    <li{{#active}} class=\"is-active\"{{/active}}><a href=\"{{path}}\"{{#active}} aria-current=\"page\"{{/active}}>{{title}}</a></li>\n    {{/content_tabs}}\n  </ul>\n</nav>\n{{/content_tabs.length}}\n{{#posts.length}}\n<div class=\"feed\">\n  {{#posts}}{{> iteration-post}}{{/posts}}\n</div>\n{{> body-older}}\n{{/posts.length}}\n\n{{!\n  **문서 결과는 목록이다** (M09). 포스트는 글 자체가 결과라 카드로 서지만, 문서는\n  <b>가리키는 이름</b>이 결과다.\n\n  **줄에 서는 것이 셋으로 정리됐다** (2026-08-25 요구).\n\n  - **제목은 `아카이브/문서`다.** 찾은 목록은 아카이브를 가로지르므로 이름만으로는 같은\n    제목의 문서 둘을 가릴 수 없고, 아카이브를 따로 떼어 두면 <b>제목이 두 조각</b>이 된다 —\n    위키링크가 이미 그 둘을 `/`로 잇는 표기를 쓴다(05m).\n  - **날짜.**\n  - **걸린 조각의 본문.** 담긴 글로 찾은 사람에게 <i>이 이름이 왜 나왔는가</i>를 말한다.\n\n  **~~종류~~와 ~~조각 수~~는 걷었다.** 아카이브 안의 목록이 *무엇이 있는가*를 말하는 자리라\n  거기서는 값을 하지만, 찾은 목록에서 알고 싶은 것은 <b>이게 내가 찾던 것인가</b>다.\n}}\n{{#documents.length}}\n<ul class=\"documents found\">\n  {{#documents}}\n  <li class=\"document-ref\">\n    <a class=\"title\" href=\"{{href}}\">{{full_title}}</a>\n    <time datetime=\"{{updated_at}}\"{{#updated_title}} title=\"{{.}}\"{{/updated_title}}>{{updated_display}}</time>\n    {{#excerpt}}<p class=\"excerpt\">{{.}}</p>{{/excerpt}}\n  </li>\n  {{/documents}}\n</ul>\n{{> body-older}}\n{{/documents.length}}\n\n{{!\n  **계정 결과는 프로필 카드다** (2026-08-25 요구). ~~한 줄짜리 사람 목록~~이었고\n  (`iteration-person` — 팔로워·팔로잉 명단이 쓰는 것) 그 자리에서 걷었다.\n\n  **명단과 검색은 하는 일이 다르다.** 명단은 <i>이미 아는 사람들</i>을 훑는 자리라 이름 한\n  줄이면 되지만, 검색은 <b>모르는 사람을 알아보는 자리</b>다 — 소개와 커스텀 필드로 찾아\n  놓고 그것을 보여 주지 않으면 <i>왜 이 사람이 걸렸는지</i>가 화면에 없다.\n\n  **카드는 모달·프로필 화면이 쓰는 것과 같은 조각이다**(`modal-card`). 서버가 그 값을\n  하나씩 지어 주므로(`profileView`) 여기서는 반복만 한다.\n}}\n{{#accounts.length}}\n<div class=\"account-cards\">\n  {{#accounts}}{{> modal-card}}{{/accounts}}\n</div>\n{{> body-older}}\n{{/accounts.length}}\n\n{{^posts.length}}\n{{^documents.length}}\n{{^accounts.length}}\n<p class=\"empty\">{{t.empty.results}}</p>\n{{/accounts.length}}\n{{/documents.length}}\n{{/posts.length}}\n\n{{!\n  ~~**문법 표는 포스트 쪽에만 선다**(M09)~~를 걷었다(2026-08-25 요구).\n\n  **표가 서야 할 자리는 칸과 함께 뜨는 곳이다** — 헤더의 드롭다운이 이미 칸과 표를 함께\n  낸다(`header-search`). 이 화면에도 칸이 생겼지만 표는 오지 않는다: 같은 표를 한 화면에\n  둘 그릴 이유가 없고, 문법을 펼쳐 보려는 사람은 그 드롭다운을 연다.\n\n  **~~어디에서 찾는지 말하는 한 줄~~도 걷었다**(2026-08-25 요구). 안내해야 할 만큼 특수한\n  구성이 아니다 — 대상은 탭이 말하고, 무엇이 걸렸는지는 결과가 말한다.\n}}\n","body-special-documents":"{{!\n  **전체 문서 · 고아 문서** (39 확정 4 — `/-/documents` · `/-/orphans`). 같은 표, 다른 체. 일반 문서와\n  에셋 문서가 함께 선다(에셋은 `:이름`). 선택 액션은 문서 권한자의 것 — 재계산(문서에만) · 삭제.\n\n  줄의 값: `id` · `kind`(`document`/`asset`) · `kind_label` · `path`(표시) · `href` · `created`·`created_at` ·\n  `updated`·`updated_at` · `by`(아이디, 없을 수 있다) · `by_href`.\n}}\n{{> body-title}}\n{{> table-toolbar}}\n<div class=\"table-wrap\">\n<table class=\"table is-fullwidth special-table\">\n  <thead>\n    <tr>\n      {{#table.select}}<th class=\"cell-check\">{{> table-check-all}}</th>{{/table.select}}\n      <th scope=\"col\">{{#table.sort.path}}{{> table-sort}}{{/table.sort.path}}</th>\n      <th scope=\"col\">{{t.specials.col_kind}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.updated_at}}{{> table-sort}}{{/table.sort.updated_at}}</th>\n      <th scope=\"col\">{{#table.sort.updated_by}}{{> table-sort}}{{/table.sort.updated_by}}</th>\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\" data-kind=\"{{kind}}\">\n      {{#table.select}}<td rowspan=\"2\" class=\"cell-check\">{{> table-check}}</td>{{/table.select}}\n      <td colspan=\"4\"><a href=\"{{href}}\">{{path}}</a></td>\n    </tr>\n    <tr data-kind=\"{{kind}}\">\n      <td>{{kind_label}}</td>\n      <td colspan=\"2\" class=\"has-text-right\"><time datetime=\"{{updated_at}}\">{{updated}}</time></td>\n      <td>{{#by}}<a href=\"{{by_href}}\">@{{by}}</a>{{/by}}</td>\n    </tr>\n  </tbody>\n  {{/rows}}\n</table>\n</div>\n{{> table-empty}}\n{{> table-toolbar}}\n","body-special-groups":"{{!\n  **전체 그룹 목록** (<a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a> ·\n  <a href=\"../../../../.claude/milestone-39_special_pages_permissions.md\">39</a> 확정 4 — `/-/groups`).\n\n  **한 표다.** 그룹 권한자(`can_manage`)에게는 소속 유저·문서·에셋의 수와 설정 단추, 선택 액션(병합·삭제)이\n  서고, 그 밖의 사람에게는 뱃지 그룹의 이름만 선다. **격리 스위치는 `그룹 설정` 모달로 갔다** — 제목줄의\n  점셋이 연다(`actions-groups`). 이름 컬럼 하나다 — 표시 이름을 따로 두지 않는다(2026-09-20 교정).\n\n  줄의 값: `id`(= 이름) · `name` · `accounts` · `documents` · `assets`. 이름이 곧 그룹 창을 여는 단추다\n  (`data-row-act=\"group\"`).\n}}\n{{> body-title}}\n{{> table-toolbar}}\n<div class=\"table-wrap\">\n<table class=\"table is-fullwidth special-table\">\n  <thead>\n    <tr>\n      {{#table.select}}<th class=\"cell-check\">{{> table-check-all}}</th>{{/table.select}}\n      <th scope=\"col\">{{#table.sort.name}}{{> table-sort}}{{/table.sort.name}}</th>\n      {{#can_manage}}\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.accounts}}{{> table-sort}}{{/table.sort.accounts}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.documents}}{{> table-sort}}{{/table.sort.documents}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.assets}}{{> table-sort}}{{/table.sort.assets}}</th>\n      {{/can_manage}}\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\">\n      {{#table.select}}<td class=\"cell-check\">{{> table-check}}</td>{{/table.select}}\n      {{!\n        이름은 평범한 링크다 (2026-09-20 요구) — 셀 안의 것에 옷을 입히지 않는다. 그룹\n        권한자에게는 그 링크가 등록정보 화면을 연다.\n\n        **~~`설정` 칸~~이 걷혔다** (2026-09-23 요구) — **이름에 어차피 링크가 걸려 있다.**\n        같은 곳으로 가는 문이 한 줄에 둘이면 둘이 다른 데로 가는 줄 알고 읽게 된다(카드의\n        `프로필 보기`를 걷어낸 그 판단과 같다).\n      }}\n      <td>{{#can_manage}}<a href=\"/-/groups\" data-row-act=\"group\" data-row-id=\"{{id}}\">{{name}}</a>{{/can_manage}}{{^can_manage}}{{name}}{{/can_manage}}</td>\n      {{#can_manage}}\n      <td class=\"has-text-right\">{{accounts}}</td>\n      <td class=\"has-text-right\">{{documents}}</td>\n      <td class=\"has-text-right\">{{assets}}</td>\n      {{/can_manage}}\n    </tr>\n  </tbody>\n  {{/rows}}\n</table>\n</div>\n{{> table-empty}}\n{{> table-toolbar}}\n","body-special-redirects":"{{!\n  **넘겨주기 목록** (39 확정 4 — `/-/redirects`). 옮기기의 표지(`moved`)와 사람이 적은 것(`written`)이\n  한 표에 선다. 갈 곳 없는 넘겨주기는 링크가 아니다(`to_href`가 없다). 삭제는 문서 권한의 것이고\n  갈래마다 뜻이 다르다(표지 / 문서) — 그것은 코어가 가른다.\n\n  줄의 값: `id`(옛 경로) · `kind` · `kind_label` · `from`·`from_href` · `to`·`to_href`(없을 수 있다) ·\n  `at`·`at_display` · `by`·`by_href`.\n}}\n{{> body-title}}\n{{> table-toolbar}}\n<div class=\"table-wrap\">\n<table class=\"table is-fullwidth special-table\">\n  <thead>\n    <tr>\n      {{#table.select}}<th class=\"cell-check\">{{> table-check-all}}</th>{{/table.select}}\n      <th scope=\"col\">{{#table.sort.from}}{{> table-sort}}{{/table.sort.from}}</th>\n      <th scope=\"col\">{{#table.sort.to}}{{> table-sort}}{{/table.sort.to}}</th>\n      <th scope=\"col\">{{t.specials.redirect_kind}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.created_at}}{{> table-sort}}{{/table.sort.created_at}}</th>\n      <th scope=\"col\">{{t.specials.col_updated_by}}</th>\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\" data-kind=\"{{kind}}\">\n      {{#table.select}}<td rowspan=\"2\" class=\"cell-check\">{{> table-check}}</td>{{/table.select}}\n      <td colspan=\"3\"><a href=\"{{from_href}}\">{{from}}</a></td>\n      <td colspan=\"2\">{{#to_href}}<a href=\"{{.}}\">{{to}}</a>{{/to_href}}{{^to_href}}{{to}}{{/to_href}}</td>\n    </tr>\n    <tr data-kind=\"{{kind}}\">\n      <td>{{kind_label}}</td>\n      <td colspan=\"2\" class=\"has-text-right\"><time datetime=\"{{at}}\">{{at_display}}</time></td>\n      <td colspan=\"2\">{{#by}}<a href=\"{{by_href}}\">@{{by}}</a>{{/by}}</td>\n    </tr>\n  </tbody>\n  {{/rows}}\n</table>\n</div>\n{{> table-empty}}\n{{> table-toolbar}}\n","body-special-specials":"{{!\n  **모든 특수 페이지 목록** (39 확정 4 — `/-/specials`). 자기 자신은 빠진다. 분류는 소속 레이어.\n\n  **표는 이 파일이 짠다** (2026-09-20 요구 — 스킨이 표를 짤 수 있어야 한다). 뷰는 `rows`에 이름 붙은\n  값을 넘기고 `table`에 기계(정렬 링크·쪽·크기·액션)를 넘긴다. 선택 액션이 없으니 체크박스 열도 없다.\n\n  줄의 값: `href` · `label` · `layer`.\n}}\n{{> body-title}}\n{{> table-toolbar}}\n<div class=\"table-wrap\">\n<table class=\"table is-fullwidth special-table\">\n  <thead>\n    <tr>\n      <th scope=\"col\">{{t.specials.col_name}}</th>\n      <th scope=\"col\">{{t.specials.col_layer}}</th>\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\">\n      <td><a href=\"{{href}}\">{{label}}</a></td>\n      <td>{{layer}}</td>\n    </tr>\n  </tbody>\n  {{/rows}}\n</table>\n</div>\n{{> table-empty}}\n{{> table-toolbar}}\n","body-special-tags":"{{!\n  **전체 태그 목록 — 탭 둘** (39 확정 4 — `/-/tags`).\n\n  해시태그는 읽기만이다 — 본문에서 파생되고 판마다 불변이라 손댈 수 없다. 문서태그는 문서 마디의 에셋\n  태그와 에셋의 태그가 한 이름 공간이라 병합·삭제가 성립한다(태그 권한).\n\n  줄의 값 — 해시태그: `id`(키) · `name` · `href` · `posts`. 문서태그: `id`(이름) · `name` · `href` ·\n  `documents` · `assets`. 어느 탭인가는 `tab_is.hashtags` / `tab_is.documents`.\n}}\n{{> body-title}}\n{{> body-tabs}}\n{{> table-toolbar}}\n<div class=\"table-wrap\">\n<table class=\"table is-fullwidth special-table\">\n  {{#tab_is.hashtags}}\n  <thead>\n    <tr>\n      <th scope=\"col\">{{#table.sort.name}}{{> table-sort}}{{/table.sort.name}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.posts}}{{> table-sort}}{{/table.sort.posts}}</th>\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\">\n      <td><a href=\"{{href}}\">#{{name}}</a></td>\n      <td class=\"has-text-right\">{{posts}}</td>\n    </tr>\n  </tbody>\n  {{/rows}}\n  {{/tab_is.hashtags}}\n  {{#tab_is.documents}}\n  <thead>\n    <tr>\n      {{#table.select}}<th class=\"cell-check\">{{> table-check-all}}</th>{{/table.select}}\n      <th scope=\"col\">{{#table.sort.name}}{{> table-sort}}{{/table.sort.name}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.documents}}{{> table-sort}}{{/table.sort.documents}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.assets}}{{> table-sort}}{{/table.sort.assets}}</th>\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\">\n      {{#table.select}}<td class=\"cell-check\">{{> table-check}}</td>{{/table.select}}\n      <td><a href=\"{{href}}\">{{name}}</a></td>\n      <td class=\"has-text-right\">{{documents}}</td>\n      <td class=\"has-text-right\">{{assets}}</td>\n    </tr>\n  </tbody>\n  {{/rows}}\n  {{/tab_is.documents}}\n</table>\n</div>\n{{> table-empty}}\n{{> table-toolbar}}\n","body-special-updates":"{{!\n  **최근 업데이트** (39 확정 4 — `/-/updates`). 위키위키의 `RecentChanges`다.\n\n  **문서를 단위로 센다** — 한 문서에 한 줄, 마지막 사건과 사건의 수. 줄의 `펼치기`가 그 문서의 이력을\n  제자리에 세운다(`data-detail` 줄에 문서 이력 문). 시간축이라 정렬 토글이 없고 페이지네이션 자리에\n  커서 로더가 선다. 선택 액션이 없으니 체크박스 열도 없다.\n\n  줄의 값: `id`(문서) · `path`·`href` · `event`(낱말) · `count` · `at`·`at_display` · `by`·`by_href` ·\n  `by_gone`(계정이 사라졌다).\n}}\n{{> body-title}}\n{{> table-toolbar}}\n<div class=\"table-wrap\">\n<table class=\"table is-fullwidth special-table\">\n  <thead>\n    <tr>\n      <th scope=\"col\">{{t.specials.col_name}}</th>\n      <th scope=\"col\">{{t.specials.col_log}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{t.specials.col_updated}}</th>\n      <th scope=\"col\">{{t.specials.col_updated_by}}</th>\n      <th scope=\"col\"><span class=\"is-sr-only\">{{t.specials.act_expand}}</span></th>\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\">\n      <td colspan=\"3\"><a href=\"{{href}}\">{{path}}</a></td>\n      <td colspan=\"2\">{{event}}{{#many}} ({{count}}){{/many}}</td>\n    </tr>\n    <tr>\n      <td colspan=\"2\" class=\"has-text-right\"><time datetime=\"{{at}}\">{{at_display}}</time></td>\n      <td colspan=\"2\">{{#by}}<a href=\"{{by_href}}\">@{{by}}</a>{{/by}}{{#by_gone}}{{t.specials.unknown_actor}}{{/by_gone}}</td>\n      <td><button class=\"button is-small is-light\" type=\"button\" data-row-act=\"expand\" data-row-id=\"{{id}}\">{{t.specials.act_expand}}</button></td>\n    </tr>\n    <tr class=\"row-detail\" data-detail=\"{{id}}\" hidden><td colspan=\"5\"><div class=\"row-detail-body\"></div></td></tr>\n  </tbody>\n  {{/rows}}\n</table>\n</div>\n{{> table-empty}}\n{{> table-toolbar}}\n","body-special-users":"{{!\n  **전체 계정 목록** (39 확정 4 — `/-/users`). 아이디 · 표시 이름 · 소속 그룹 · 가입일. 선택 액션은\n  계정 권한자에게만 선다 — 메시지 발송 · 그룹 지정 · 서버 뮤트 · 서버 차단 · 완전 삭제.\n\n  줄의 값: `id` · `handle` · `href` · `display_name` · `groups`(쉼표로 이은 글자) · `joined`(표시) ·\n  `joined_at`(ISO) · `avatar_url`(없을 수 있다). 정렬 링크: `table.sort.handle` · `table.sort.created_at`.\n}}\n{{> body-title}}\n{{> table-toolbar}}\n<div class=\"table-wrap\">\n<table class=\"table is-fullwidth special-table\">\n  <thead>\n    <tr>\n      {{#table.select}}<th class=\"cell-check\">{{> table-check-all}}</th>{{/table.select}}\n      <th scope=\"col\">{{t.specials.col_avatar}}</th>\n      <th scope=\"col\">{{#table.sort.handle}}{{> table-sort}}{{/table.sort.handle}}</th>\n      <th scope=\"col\">{{t.specials.col_display_name}}</th>\n      <th scope=\"col\">{{t.groups.name}}</th>\n      <th scope=\"col\" class=\"has-text-right\">{{#table.sort.created_at}}{{> table-sort}}{{/table.sort.created_at}}</th>\n    </tr>\n  </thead>\n  {{#rows}}\n  <tbody>\n    <tr data-row=\"{{id}}\">\n      {{#table.select}}<td rowspan=\"2\" class=\"cell-check\">{{> table-check}}</td>{{/table.select}}\n      {{! 초상화 — 사람 줄(iteration-person)과 같은 그림, 없으면 같은 대체 그림 (2026-09-20 사람의 손질). }}\n      <td rowspan=\"2\">{{#avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"32\" height=\"32\" loading=\"lazy\">{{/avatar_url}}{{^avatar_url}}<span class=\"avatar avatar-fallback\" aria-hidden=\"true\">{{> icon-person}}</span>{{/avatar_url}}</td>\n      <td colspan=\"2\"><a href=\"{{href}}\">@{{handle}}</a></td>\n      <td colspan=\"2\">{{display_name}}</td>\n    </tr>\n    <tr>\n      <td colspan=\"2\">{{groups}}</td>\n      <td colspan=\"2\" class=\"has-text-right\"><time datetime=\"{{joined_at}}\">{{joined}}</time></td>\n    </tr>\n  </tbody>\n  {{/rows}}\n</table>\n</div>\n{{> table-empty}}\n{{> table-toolbar}}\n","body-tos":"{{!\n  운영방침 — **이곳에서 무엇이 되고 무엇이 안 되는지 말하는 자리** (2026-09-14 요구).\n\n  **홈페이지와 같은 모양이다.** 자기 주소에 선 채로 설정이 가리키는 문서의 <b>본문만</b>\n  담는다 — 그 문서로 곧장 보내면 제목이 그 문서의 이름이 되어 <i>여기가 어디인가</i>를\n  주소로도 제목으로도 알 수 없다.\n\n  **제목은 자리의 이름이다.** 뷰가 고정해 넘긴다(`nav.*`) — 문서가 무엇으로 불리든 여기\n  서 있는 동안은 운영방침이다.\n\n  **제목줄은 피드의 것이다**(갈아타는 상자). 읽고 나서 하는 일은 <i>여기서 어디로 갈까</i>이고\n  이 화면은 어느 피드에도 매여 있지 않다.\n\n  **셋을 한 파일로 합치지 않는다**(사이드바의 잎 여섯과 같은 판단). 지금은 거의 같지만\n  <b>따로 손댈 자리</b>가 서 있다는 것이 이 파일의 값이다.\n}}\n{{> body-title}}\n\n<article class=\"content document-body\">\n  {{&body}}\n</article>\n","body-widen":"{{> body-title}}\n{{> modal-widen}}\n\n{{!\n  빠져나갈 길은 **페이지에만** 둔다 — 모달에는 자바스크립트가 붙이는 `닫기`가 이미 있다.\n  지우기 화면과 같은 판단이다.\n}}\n","layout":"{{!\n  레이아웃 — **`<html>`과 `<head>`는 앱 셸이 진다**(`server/shell.ts`).\n\n  카멜의 `layout`은 완성된 문서를 내지만 하멜에서는 셸이 그 자리를 지고 이 조각이 `#app`에\n  들어간다. **그 안쪽은 카멜에서 그대로 베꼈다** — `header.site > .bar` · `.shell` ·\n  `main.content`가 같아야 `hamelize.css`(=`camelize.css`)가 그대로 붙는다.\n\n  **컬러 스키마도 셸이 진다** — `<html class=\"theme-*\">`가 그것이고, 비어 있으면 Bulma가\n  기기 설정을 따른다.\n}}\n<header class=\"site\">\n  <div class=\"bar\">\n    {{!\n      **서비스 이름은 나가는 문이다**(카멜의 2026-08-20 요구). 얼굴이 없으면 이름만 선다 —\n      빈 그림 자리를 두지 않는다.\n    }}\n    <a class=\"site-name has-text-weight-bold\" href=\"{{home_href}}\">{{!\n      **올린 얼굴이 없으면 스킨의 것이 선다** (2026-09-11 요구 — 서비스 파비콘 폴백).\n\n      브라우저의 탭은 이미 그렇게 떨어지는데(`shell.ts`의 `iconLinks`) <b>머리의 자리만\n      비어 있었다</b> — 같은 얼굴이 두 자리에 서는데 한쪽에만 폴백이 있으면, 얼굴을 올리기\n      전까지 <i>이 서비스에 표시가 없는 것</i>처럼 보인다.\n    }}{{#favicon}}<span class=\"nav-icon\"><img class=\"site-favicon\" src=\"{{image}}\" alt=\"\" width=\"20\" height=\"20\"></span>{{/favicon}}{{^favicon}}<span class=\"nav-icon\"><img class=\"site-favicon\" src=\"/skin-assets/icon.svg\" alt=\"\" width=\"20\" height=\"20\"></span>{{/favicon}}<span class=\"nav-label\">{{instance.name}}</span></a>\n\n    {{!\n      **~~레이어 바로가기가 이름 뒤에 섰다~~** (2026-09-18 요구로 곁칸에 옮겼다).\n\n      <b>눌러야 열리는 자리</b>라 무엇이 있는지 알려면 먼저 열어 봐야 했고, 곁칸은 이미\n      <i>갈 곳의 목록</i>이 사는 자리다 — 같은 성질의 것을 두 곳에 두지 않는다\n      (`sidebar-layers`).\n    }}\n\n    {{!\n      **찾는 상자가 머리에 선다**(05e 요구). 카멜의 레이아웃과 같은 자리이며, ~~하멜에는\n      이 줄이 없었다~~ — 베끼면서 빠뜨렸다(2026-09-02에 잡았다): 검색은 헤더의 이 상자와\n      결과 화면의 칸 둘로 들어가는데 앞엣것이 통째로 없었다.\n    }}\n    {{> header-search}}\n    {{> header-account}}\n  </div>\n</header>\n\n{{!\n  **자취 — 머리와 몸 사이, 본문 폭으로** (<a href=\"../../../../.claude/milestone-40_breadcrumbs.md\">40</a>).\n\n  ~~본문 칸 안 제목 위~~ → **`header.site`와 `.shell` 사이**(2026-09-20 요구). 폭은 본문과 맞춘다 —\n  `.shell`의 옷을 함께 입어 같은 최대 폭·안전 영역을 받고, 넓은 화면에서는 기둥의 자리\n  (`--nav-width` + 칸 사이)만큼 오른쪽을 비운다(기둥은 본문 오른쪽이다).\n\n  제목줄의 `trail`(문서 트리의 조상)과 <b>다른 물건이다</b> — 그쪽은 자리이고 이쪽은\n  지나온 화면이다. 입력폼에서는 `crumbs`가 비어 통째로 서지 않는다(확정 1).\n\n  **두 그림, 한 스택**(확정 4). `rewind`는 `돌아가기` 하나 — <b>되돌아가는 것이라 링크</b>다\n  (전역 규칙의 취소 옷: `a.button`), 걷어 낼 것이 없으면 서지 않는다. `trails`는 최근 다섯을\n  갈래 이름의 링크로 늘어놓고 `title`에 그때의 제목을 든다. 마지막은 늘 지금 화면의 갈래다.\n}}\n{{! **금은 화면 폭이다**(2026-09-20 요구) — 머리·발의 외곽선과 같은 자리라 바깥 띠(`crumbs-band`)가 긋고, 안의 줄은 본문 폭이다. }}\n{{#crumbs}}\n<div class=\"crumbs-band\">\n<div class=\"shell crumbs-shell\">\n<nav class=\"crumbs\" aria-label=\"{{t.crumbs.label}}\">\n  {{#back}}<a class=\"button crumb-back\" href=\"{{href}}\" title=\"{{label}}\" data-rewind><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-rewind}}</span><span class=\"nav-label\">{{t.action.rewind}}</span></a>{{/back}}\n  {{! **지금 화면의 갈래는 trails에서만 선다**(2026-09-20 요구) — rewind는 단추 하나다. }}\n  {{#trails}}<span class=\"nav-icon crumb-icon\" aria-hidden=\"true\">{{> icon-map-pin}}</span><span class=\"crumb-line\">{{#items}}<a class=\"crumb\" href=\"{{href}}\" title=\"{{label}}\" data-crumb=\"{{index}}\">{{kind}}</a><span class=\"crumb-mark\" aria-hidden=\"true\">›</span>{{/items}}<span class=\"crumb is-current\">{{current}}</span></span>{{/trails}}\n</nav>\n</div>\n</div>\n{{/crumbs}}\n\n{{!\n  **둘러보기가 본문 옆에 선다**(카멜의 05e 요구). `.shell`이 기준 폭을 지고, 좁아지면\n  둘러보기가 화면 아래로 내려가 붙박이다 — 어느 쪽이 될지는 CSS가 정한다.\n}}\n<div class=\"shell\">\n  {{!\n    **편집 모드에서는 사이드바가 글감 탐색기가 된다**\n    (<a href=\"../../../../.claude/milestone-31_document_tree.md\">31</a> 확정 10).\n\n    둘러보기가 그 자리를 내주는 이유는 <b>고치는 동안 갈 곳이 아니라 담을 것</b>이 옆에\n    있어야 하기 때문이다 — *빠르게 쓴 글이 문서가 된다*의 <b>되는</b> 자리가 여기다.\n\n    **머리의 검색과 계정은 그대로 선다.** 갈아 끼우는 것은 옆의 한 칸이지 화면 전체가 아니다.\n  }}\n  {{!\n    **사이드바는 자기 파일이 진다** (2026-09-14 요구 — 사이드바 개편). ~~여기서 갈랐다~~ —\n    편집 모드의 갈아 끼우기까지 `sidebar`가 안으로 들였다: 레이아웃이 아는 것은 <b>그 자리에\n    사이드바가 선다</b>까지이고, 무엇이 서는지는 그 파일과 부속 아홉이 진다.\n  }}\n  {{> sidebar}}\n\n  {{!\n    `content`는 Bulma가 **클래스 없는 HTML**에 타이포그래피를 되돌려 주는 자리다. 포스트\n    본문은 코어가 산수화한 것이라 태그마다 클래스를 달 수 없으므로 여기서 한 번에 받는다.\n  }}\n  <main class=\"content px-4\">\n    {{{body}}}\n  </main>\n</div>\n\n{{!\n  **좁은 화면의 막대** (2026-09-07 요구).\n\n  ~~기둥이 화면 아래에 눌러앉아 풋터인 척했다~~ → **기둥은 기둥으로 두고 밖으로 밀어낸다.**\n  그 자리를 이 막대가 받으며, 우상단의 햄버거가 기둥을 미끄러뜨려 부른다.\n\n  **지금은 담긴 것이 그것 하나다.** 다른 것을 둘 자리가 생기면 왼쪽이 그 자리다.\n\n  **넓은 화면에서는 서지 않는다** — 거기서는 기둥이 늘 보이므로 부를 일이 없다.\n}}\n<div class=\"mobile-bar\">\n  <button class=\"mobile-menu\" type=\"button\" data-nav-toggle aria-expanded=\"false\" aria-controls=\"site-nav\">\n    <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-menu}}</span>\n    <span class=\"nav-label\">{{t.nav.explore}}</span>\n  </button>\n</div>\n\n{{> footer-site}}\n","modal":"{{!\n  모달의 베이스 — **`modal-*` 조각이 여기 담긴다** (05e 요구, 파일 이름 정리).\n\n  `layout`이 페이지의 베이스인 것과 같은 자리다. 조각마다 바깥을 다시 짜지 않게 하고,\n  스킨이 모달의 안쪽 틀을 한 곳에서 정하게 한다.\n\n  **닫기 단추는 여기 없다.** 그것은 스크립트가 만들어 붙이고(`modal.ts`), 자리는 스타일시트가\n  정한다(`.hamel-modal-close`) — 마크업에 두면 그 단추가 무엇을 여는지 스킨이 알아야 한다.\n\n  **하멜에서는 자바스크립트가 하한이 아니다**(하한은 카멜이 진다). 그래도 이 파일이 카멜의\n  것과 같은 이유는 **모달의 안쪽 틀을 스킨이 한 곳에서 정한다**는 규칙이 그대로여서다.\n}}\n<div class=\"modal-body\">\n  {{{body}}}\n</div>\n"},"partials":{"accounts-group":"{{!\n  **다른 사람에 관한 묶음** — 함께 들어와 있는 계정들과 `계정 추가`\n  (2026-09-11 요구 — 다중 계정 · 2026-09-25 요구에 한 조각이 되었다).\n\n  **묶음째 갈아 끼운다.** ~~줄들만 뒤늦게 끼워 넣었다~~ — 조용히 있다가 항목이 늘면\n  사람은 <b>기다리면 되는 자리인지</b>를 알 수 없다: 갈아타려고 연 메뉴에 아무 말이 없으면\n  *다른 계정이 없다*로 읽고 닫는다. 그래서 펼치는 순간 이 묶음이 통째로 <b>묻는 중</b>이\n  되고, 답이 오면 통째로 다시 선다.\n\n  **`계정 추가`도 그 묶음 안이다.** 둘 다 <i>다른 사람</i>에 관한 일이고, 갈아탈 줄이 설\n  자리가 어디인지를 <b>그 항목이 이미 가리키고 있다</b> — 밖에 두면 묻는 동안 묶음이\n  비어 그 자리가 사라진다.\n\n  **묻는 동안에도 `계정 추가`는 눌린다.** 옅어지는 것은 <i>지금 다시 세는 중</i>이라는\n  말이고, 멀쩡히 서 있는 문을 왕복 하나 동안 잠글 이유는 없다.\n}}\n<ul class=\"{{#loading}}is-loading{{/loading}}\">\n  {{#loading}}\n  <li class=\"is-waiting\">{{t.status.loading}}</li>\n  {{/loading}}\n  {{^loading}}\n  {{#accounts}}\n  <li>{{> iteration-account}}</li>\n  {{/accounts}}\n  {{/loading}}\n  {{!\n    **제 주소로 간다**(`/-/accounts/add` — 2026-09-25 요구) — 로그인 주소의 깃발이었을 때는\n    서버만 그 깃발을 알아 <b>눌러도 홈으로 갈 뿐이었다</b>.\n\n    **돌아올 자리를 싣는다.** 한 사람 더 들이는 일은 보던 것을 그만두는 일이 아니다.\n    **그 값은 완주의 몫이다** — 무르는 자리가 아니므로 화면에 취소를 세우지 않는다.\n\n    **떠나는 링크가 아니다.** 수단이 둘 이상이면 그 주소가 내주는 것은 우리 화면이라\n    라우터가 그린다(게스트의 `로그인` 링크와 같다).\n  }}\n  <li><a href=\"/-/accounts/add?return={{path_encoded}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-person-plus}}</span><span class=\"nav-label\">{{t.nav.add_account}}</span></a></li>\n</ul>\n","actions-asset":"{{!\n  에셋 화면의 `화면 액션`\n  (<a href=\"../../../../.claude/milestone-36_asset_layer.md\">36</a> 확정 6).\n\n  **문서의 것과 같은 차례다** — 고치기 · 옮기기 · 이력 보기. 지우기는 여기 없다:\n  <b>에셋 풀의 관리 창</b>이 그 일을 지고, 그것은 관리자의 자리다.\n}}\n{{#can_edit}}\n<li><a href=\"{{edit_href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pencil}}</span><span class=\"nav-label\">{{t.document.edit}}</span></a></li>\n<li><a href=\"{{move_href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-expand}}</span><span class=\"nav-label\">{{t.asset.rename}}</span></a></li>\n{{/can_edit}}\n<li><a href=\"{{history_href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-rewind}}</span><span class=\"nav-label\">{{t.document.history}}</span></a></li>\n","actions-document":"{{!\n  문서 화면의 `화면 액션` (31 확정 10).\n\n  **넷만 선다** — 고치기 · 옮기기 · 이력 보기 · 문서 속성. 잠그기·내보내기·지우기는\n  <b>문서 속성 화면으로 갔다</b>(2026-09-07 요구): 이 상자는 *지금 이 문서로 무엇을 하는가*의\n  자리이고, 그 셋은 <b>문서의 성질을 다루는 일</b>이라 한 화면에 모인다.\n\n  **차례는 자주 쓰는 것에서 드문 것으로다** — 고치는 일이 맨 위이고, 성질을 보는 일이 맨\n  아래다.\n}}\n{{#can_edit}}\n<li><a href=\"{{edit_href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pencil}}</span><span class=\"nav-label\">{{t.document.edit}}</span></a></li>\n<li><a href=\"{{move_href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-expand}}</span><span class=\"nav-label\">{{t.document.move}}</span></a></li>\n{{/can_edit}}\n<li><a href=\"{{history_href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-rewind}}</span><span class=\"nav-label\">{{t.document.history}}</span></a></li>\n{{!\n  **문서 속성은 관리자만 본다**(31 확정 7) — 필드는 수정 권한이 있는 것만 보이고, 편집자가\n  알아야 할 *닫혀 있다*는 제목 아래가 말한다.\n}}\n{{#can_manage}}\n<li><a href=\"{{access_href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-shield-check}}</span><span class=\"nav-label\">{{t.document.properties}}</span></a></li>\n{{/can_manage}}\n","actions-emojis":"{{!\n  이모지 관리의 `화면 액션` (2026-09-21 요구).\n\n  **더하는 일과 이름 짓는 일이 앞이고, 고른 것에 하는 일이 그다음이다.** 되돌릴 수 없는 것은\n  가로줄 아래에 선다(전역 규칙).\n}}\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"add\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-file-plus}}</span><span class=\"nav-label\">{{t.emoji.add_files}}</span>\n      </button>\n    </li>\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"unicode\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-hash}}</span><span class=\"nav-label\">{{t.emoji.add_unicode}}</span>\n      </button>\n    </li>\n    {{!\n      **이름 배정은 올린 뒤의 일이다**(2026-09-21 요구) — 여럿을 올리고 한 창에서 적는다.\n      기다리는 것이 없으면 세우지 않는다: 눌러도 빈 창이 뜨는 항목을 두지 않는다.\n    }}\n    {{#nameless}}\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"name\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pencil}}</span><span class=\"nav-label\">{{t.emoji.assign_names}} ({{.}})</span>\n      </button>\n    </li>\n    {{/nameless}}\n    {{!\n      **표준 유니코드는 한꺼번에 선다** (2026-09-21 요구 · 45 확정 7).\n\n      **세우는 일과 걷는 일이 나란히 선다** — 걷는 것은 <i>그 목록으로 세운 것</i>뿐이라\n      되돌릴 수 있는 쌍이고, 그래서 가로줄 위에 함께 둔다. 지우기와 같은 무게가 아니다.\n    }}\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"standard\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-list-plus}}</span><span class=\"nav-label\">{{t.emoji.add_standard}}</span>\n      </button>\n    </li>\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"unstandard\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-rotate}}</span><span class=\"nav-label\">{{t.emoji.remove_standard}}</span>\n      </button>\n    </li>\n    <li class=\"rule\" role=\"separator\"></li>\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"all\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-list-check}}</span><span class=\"nav-label\">{{t.pool.pick_all}}</span>\n      </button>\n    </li>\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"none\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-rotate}}</span><span class=\"nav-label\">{{t.pool.pick_none}}</span>\n      </button>\n    </li>\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"off\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-eye-off}}</span><span class=\"nav-label\">{{t.emoji.turn_off}}</span>\n      </button>\n    </li>\n    <li>\n      <button class=\"action\" type=\"button\" data-emoji-act=\"on\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-eye}}</span><span class=\"nav-label\">{{t.emoji.turn_on}}</span>\n      </button>\n    </li>\n    <li class=\"rule\" role=\"separator\"></li>\n    <li>\n      <button class=\"action delete\" type=\"button\" data-emoji-act=\"remove\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-trash}}</span><span class=\"nav-label\">{{t.emoji.remove}}</span>\n      </button>\n    </li>\n","actions-groups":"{{!\n  그룹 목록의 `화면 액션` (39 확정 4) — **그룹 설정** 하나. 격리 스위치 다섯과 문서의 축 둘이\n  모달로 갔고 이 줄이 그것을 연다. 서비스 권한자에게만 뷰가 넘긴다 — 사이트 설정을 만지는 일이다.\n}}\n    <li>\n      <button class=\"action\" type=\"button\" data-group-gates>\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-gear}}</span><span class=\"nav-label\">{{t.groups.gates}}</span>\n      </button>\n    </li>\n","actions-notifications":"{{!\n  알림 화면의 `화면 액션` — <b>담기는 것만 여기 있다</b>.\n\n  상자와 여는 방식은 `body-title`이 지고, 이 파샬은 <c>&lt;li&gt;</c>들만 낸다.\n\n  **둘 다 폼이다.** `모두 읽음`은 POST이고 알림 토글은 스크립트가 JSON으로 보내지만\n  <b>그 요청도 CSRF 표를 지난다</b> — 표를 들고 있는 자리가 폼 하나다(`csrfOf`).\n  토글 쪽 폼에 `action`이 없는 것이 정직하다: 보내지지 않는다(단추가 `type=\"button\"`이다).\n\n  **단추는 감춰 두고 스크립트가 보인다**(`hidden`). 구독은 브라우저가 만들어 주는 값이라\n  스크립트가 없으면 만들 방법이 아예 없다 — 아무 일도 하지 못하는 단추를 세우지 않는다.\n  열쇠가 없는 서버에서는 이 줄 자체가 서지 않는다.\n\n  **`.action`을 달지 않는다**(2026-08-26 요구). 그 이름은 <b>바깥에서 알약으로 들어오는\n  것들</b>에 붙은 표이고(프로필 카드), 상자 안의 항목은 `.dropdown-menu li button`이 이미\n  같은 줄 모양으로 눌러 준다 — 달아 두면 알약 스타일을 한 번 입고 그것을 다시 벗기게 된다.\n}}\n<li>\n  <form method=\"post\" action=\"/-/notifications/read\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <button type=\"submit\">{{t.action.read_all}}</button>\n  </form>\n</li>\n{{#push}}\n<li>\n  <form class=\"push\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <button type=\"button\" hidden\n            data-push data-push-key=\"{{push.key}}\"\n            data-on=\"{{t.push.turn_off}}\" data-off=\"{{t.push.turn_on}}\">{{t.push.turn_on}}</button>\n  </form>\n</li>\n{{/push}}\n","actions-pool":"{{!\n  에셋 풀의 `화면 액션` (2026-09-19에 제목줄을 한 벌로 모으며 나왔다).\n\n  **고르는 일과 되돌릴 수 없는 일이 한 상자에 있다** — 가로줄이 그 둘을 가른다(전역 규칙).\n\n  ~~이 항목들이 화면 템플릿 안에 있었다~~ — 그래서 풀만 제 제목줄을 지고 있었고, 점 셋의\n  옷도 다른 화면과 갈렸다. <b>상자와 여는 방식은 모든 화면이 한 벌을 나눠 쓴다.</b>\n}}\n    <li>\n      <button class=\"action\" type=\"button\" data-pool-act=\"all\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-list-check}}</span><span class=\"nav-label\">{{t.pool.pick_all}}</span>\n      </button>\n    </li>\n    <li>\n      <button class=\"action\" type=\"button\" data-pool-act=\"none\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-rotate}}</span><span class=\"nav-label\">{{t.pool.pick_none}}</span>\n      </button>\n    </li>\n    {{!\n      **지우기는 고칠 수 있는 사람의 일이다** (2026-09-17 보고 ·\n      <a href=\"../../../../.claude/milestone-38_document_access.md\">38</a> 확정 5).\n      ~~아무에게나 섰다~~ — 코어는 지우기를 <b>에셋 편집 그룹</b>으로 재는데 여기에는\n      문이 없었고, 그래서 <i>눌러도 거절이 오는 항목</i>이 상자에 있었다.\n\n      **가로줄도 함께 사라진다** — 되돌릴 수 없는 것이 없으면 가를 것도 없다.\n    }}\n    {{#can_purge}}\n    <li class=\"rule\" role=\"separator\"></li>\n    {{!\n      **상자 안의 빨강은 `delete`가 진다**(2026-09-17 요구). ~~`is-danger`를 달았다~~ —\n      그것은 <b>단추의 클래스</b>이고 상자 안의 항목은 단추 꼴이 아니라 한 줄이라,\n      색이 붙는 자리가 따로 있다(`.dropdown-menu li .action.delete`). 문서 액션·포스트\n      액션의 삭제가 이미 그 규칙을 탄다.\n    }}\n    <li>\n      <button class=\"action delete\" type=\"button\" data-pool-act=\"purge\">\n        <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-trash}}</span><span class=\"nav-label\">{{t.pool.purge_chosen}}</span>\n      </button>\n    </li>\n    {{/can_purge}}\n","asset-gallery":"{{!\n  **갤러리 — 두 자리가 같은 격자를 쓴다** (2026-09-15 요구).\n\n  문서를 고치다 여는 모달과 관리자가 보는 화면이 <b>같은 마크업</b>을 쓴다. 갈리는 것은\n  <b>누른 뒤에 일어나는 일</b>뿐이다 — 모달에서는 부른 블록에 그림이 앉고, 관리 화면에서는\n  메뉴가 뜬다. 생김새를 둘로 두면 한쪽만 고쳐진다.\n\n  **격자 칸은 그림이 전부다.** 이름도 크기도 아직 세우지 않는다 — 고를 때 눈이 보는 것은\n  그림이고, 나머지는 <b>필요를 파악해 가며</b> 더한다(2026-09-15에 그렇게 정했다).\n\n  **누르는 것은 단추다.** 그림에 처리기를 걸면 키보드로 닿지 못하고, 링크로 두면 <i>그리로\n  간다</i>는 거짓말이 된다 — 여기서 누르는 일은 이동이 아니다.\n}}\n{{!\n  **고르는 모드는 격자가 안다**(37 확정 9). 그 표가 붙어 있는 동안 <b>누르면 곧 심기는</b>\n  동작이 꺼지고, 누름은 <i>고르는 일</i>이 된다 — 탐색기의 규칙이다.\n}}\n<ul class=\"asset-grid\" data-asset-grid{{#picking}} data-asset-picking{{/picking}}>\n  {{!\n    **앞줄의 첫 칸이 올리는 자리다** (2026-09-16 요구).\n\n    **격자 안에 두는 이유**는 그것이 <i>여기에 한 장을 더한다</i>는 뜻이기 때문이다 —\n    화면 어딘가의 단추로 두면 무엇에 더하는지가 자리로 말해지지 않는다.\n\n    **끌어다 놓는 자리와 같은 말을 한다.** 상자 전체가 받으므로(`data-asset-admin`) 이\n    칸은 <b>그 사실을 알리는 그림</b>이자 누를 수 있는 길이다.\n  }}\n  {{#can_upload}}\n  <li class=\"asset-cell asset-cell-add\">\n    <button class=\"asset-add\" type=\"button\" data-asset-upload>\n      <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-file-plus}}</span>\n      <span class=\"asset-add-label\">{{upload_label}}</span>\n      <span class=\"asset-add-hint\">{{drop_label}}</span>\n      {{! **붙을 태그를 미리 말한다** — 올린 뒤에 알면 지우고 다시 붙여야 한다. }}\n      {{#upload_tag}}<span class=\"asset-add-tag\">{{.}}</span>{{/upload_tag}}\n    </button>\n  </li>\n  {{/can_upload}}\n  {{#items}}\n  {{!\n    **고른 것은 칸이 말한다**(`is-chosen` · `aria-pressed`). 그림 위에 표를 얹지 않고 칸의\n    테두리로 말하는 것은, <b>표가 그림을 가리면 무엇을 고르고 있는지가 안 보이기</b>\n    때문이다.\n  }}\n  <li class=\"asset-cell{{#chosen}} is-chosen{{/chosen}}\">\n    <button class=\"asset-pick\" type=\"button\" data-asset-pick=\"{{id}}\" data-asset-url=\"{{url}}\"\n            title=\"{{name}}\" aria-pressed=\"{{#chosen}}true{{/chosen}}{{^chosen}}false{{/chosen}}\">\n      {{!\n        **이름이 곧 대체 텍스트다** (36 확정 4). 문서 레이어의 파일에는 <b>대체 텍스트 칸이\n        없다</b> — 설명은 그 파일의 <b>제 본문</b>이 지고, 격자에서 읽어 줄 한 마디는 이름이다.\n      }}\n      <img src=\"{{thumbnail_url}}\" alt=\"{{name}}\" loading=\"lazy\">\n    </button>\n  </li>\n  {{/items}}\n</ul>\n\n{{^items.length}}\n{{!\n  **빈 것은 빈 채로 말한다** — 격자만 비워 두면 <i>아직 받는 중인가</i>와 가릴 수 없다.\n}}\n<p class=\"is-waiting\">{{empty}}</p>\n{{/items.length}}\n","asset-one-panel":"{{!\n  **그림 하나를 다루는 판** — 창과 화면이 나눠 쓴다\n  (2026-09-15 요구 · 2026-09-16 요구로 자리가 둘이 되었다).\n\n  **같은 일에 같은 그림.** 에셋 풀에서 칸을 눌러 뜨는 창과 `/:이름` 화면이 <b>이 한\n  조각</b>을 쓴다 — 생김새를 둘로 두면 한쪽만 고쳐지고, 그러면 <i>같은 파일을 다루는 두\n  화면이 다른 일을 할 수 있는 것처럼</i> 읽힌다.\n\n  **할 수 없는 일은 서지 않는다.** 권한이 없으면 단추를 감추고 태그 칸은 잠근다 — 눌러도\n  거절이 오는 단추를 세우지 않는다는 규칙과, <b>미구현은 감추지 않는다</b>는 규칙은 다른\n  자리다: 이것은 구현되어 있으되 <b>이 사람의 일이 아닌</b> 것이다.\n}}\n<div class=\"asset-one\" data-asset-one=\"{{id}}\">\n  <img class=\"asset-one-shot\" src=\"{{url}}\" alt=\"{{name}}\">\n\n  {{!\n    **이름이 곧 주소다** (36 확정 4). 창에서는 그 파일의 화면으로 가는 문이 되고, 그 화면\n    자신에서는 <b>링크가 아니다</b> — 눌러도 같은 자리인 링크는 조용히 아무 일도 하지 않는다.\n  }}\n  <dl class=\"asset-facts\">\n    <dt>{{t.asset.name}}</dt>\n    <dd>{{#page_href}}<a href=\"{{.}}\">{{name}}</a>{{/page_href}}{{^page_href}}{{name}}{{/page_href}}</dd>\n    <dt>{{t.asset.kind}}</dt>\n    <dd>{{#mime_type}}{{.}}{{/mime_type}}{{^mime_type}}<span class=\"hint\">{{t.status.none}}</span>{{/mime_type}}</dd>\n    <dt>{{t.document.asset_size}}</dt>\n    <dd>{{size}}</dd>\n    {{#width}}\n    <dt>{{t.asset.pixels}}</dt>\n    <dd>{{width}} × {{height}}</dd>\n    {{/width}}\n  </dl>\n\n  {{!\n    **그룹은 태그 앞에 선다** (2026-09-17 요구 ·\n    <a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a>).\n\n    **태그보다 앞인 까닭**은 <b>판정하는 것이 먼저 읽혀야</b> 하기 때문이다 — 태그는 찾는\n    일을 좁히고 그룹은 <b>누가 볼 수 있는가</b>를 가른다.\n\n    **검열 권한이 없는 사람에게는 칸이 서지 않는다.** 태그와 갈리는 자리다: 태그는 잠긴 채로\n    보이지만(무엇이 붙어 있는지는 누구나 알아야 한다) 그룹은 <b>만질 수 있는 사람의 살림</b>\n    이고, 못 만지는 사람에게 두 칸을 더 세우면 창이 그만큼 길어진다.\n\n    **읽기와 쓰기를 여기서 가른다.** 여럿을 한 번에 다루는 자리(풀의 그룹 관리)는 축을\n    가르지 않는다 — 네 칸을 한 번에 맞히는 사람은 없다.\n  }}\n  {{#can_label}}\n  <form class=\"asset-one-groups\" id=\"asset-one-groups\" data-asset-groups>\n    {{!\n      **레이블 뒤에 사슬을 통째로 적는다** (2026-09-18 요구).\n\n      **칸에는 제 것만 담긴다** — 거기 적는 일이 <i>이 자산이 무엇을 거는가</i>이기\n      때문이다. 실제로 이 자산을 가르는 것은 <b>레이어의 축과 `/`의 라벨까지</b>이므로\n      (38 확정 5), 칸만 보면 <i>비었는데 왜 안 보이지</i>가 답을 얻지 못한다.\n    }}\n    <label class=\"field\">\n      <span>{{t.document.asset_groups_read}}</span>\n      {{#groups_read_all}}<span class=\"chain\">{{t.document.groups_chain}} {{.}}</span>{{/groups_read_all}}\n      <input class=\"input\" type=\"text\" name=\"groups_read\" value=\"{{groups_read_text}}\"\n             list=\"asset-group-names\" placeholder=\"{{t.document.asset_groups_hint}}\"\n             autocomplete=\"off\">\n    </label>\n    <label class=\"field\">\n      <span>{{t.document.asset_groups_write}}</span>\n      {{#groups_write_all}}<span class=\"chain\">{{t.document.groups_chain}} {{.}}</span>{{/groups_write_all}}\n      <input class=\"input\" type=\"text\" name=\"groups_write\" value=\"{{groups_write_text}}\"\n             list=\"asset-group-names\" placeholder=\"{{t.document.asset_groups_hint}}\"\n             autocomplete=\"off\">\n    </label>\n    <datalist id=\"asset-group-names\">\n      {{#group_names}}<option value=\"{{.}}\"></option>{{/group_names}}\n    </datalist>\n  </form>\n  {{/can_label}}\n\n  {{!\n    **태그는 글자 칸 하나로 고친다.** 쉼표로 가른다 — 태그 하나마다 칸을 세우면 지우는\n    자리가 태그 수만큼 늘고, 여기서 하는 일은 <b>목록을 통째로 적어 넣는 것</b>이다.\n\n    **고칠 수 없는 사람에게는 잠긴 채로 보인다**(`readonly`) — 감추지 않는 이유는 <b>무엇이\n    붙어 있는지는 누구나 알아야</b> 하기 때문이다.\n  }}\n  <form class=\"asset-one-tags\" id=\"asset-one-tags\" data-asset-tags>\n    <label class=\"field\">\n      <span>{{t.document.asset_tags}}</span>\n      <input class=\"input\" type=\"text\" name=\"tags\" value=\"{{tags_text}}\"\n             placeholder=\"{{t.document.asset_tags_hint}}\" autocomplete=\"off\"\n             {{^can_edit}}readonly{{/can_edit}}>\n    </label>\n  </form>\n\n  {{!\n    **할 일이 한 줄에 선다** (2026-09-15 요구).\n\n    **적용 단추는 폼 밖에 있다**(`form=`) — 줄을 함께 서려면 상자를 벗어나야 하고, 그래도\n    <b>엔터가 그 폼을 보낸다</b>: 칸 안에서 치던 손이 단추를 찾아가지 않아도 된다.\n\n    **갈래는 전역 규칙의 것이다.** 적용은 <b>결정</b>(`is-primary`), 나머지 셋은 <b>선택</b>\n    (`is-light`), 지우기는 <b>파괴</b>(`is-danger`)다 — 되돌릴 수 없는 것이 색으로 갈리고\n    <b>줄 끝으로 밀려</b>, 가로줄 없이도 손이 헛짚지 않는다.\n\n    **다섯이 한 문을 지난다**(2026-09-17 보고 ·\n    <a href=\"../../../../.claude/milestone-38_document_access.md\">38</a> 확정 5). ~~교체는\n    편집자, 태그·썸네일·지우기는 관리자로 갈랐다~~ — 코어는 그 다섯을 <b>같은 문</b>으로\n    재므로(레이어의 쓰기 명단 × 이 자산의 쓰기 라벨) 화면에서 갈라 두면 <b>한쪽은 눌러도\n    거절이 오고 한쪽은 할 수 있는데 안 보인다.</b>\n\n    **그 답은 코어가 싣는다**(`can_write`) — ~~*로그인했는가*로 셌다~~(36, 그때는 그것이\n    전부였다): 축이 넷이 되면서 <b>에셋 편집 그룹 밖의 사람에게 교체 단추가 섰다.</b>\n\n    **라벨만 갈린다**(`can_label`) — 그쪽은 문이 정말 다르다.\n  }}\n  {{#can_edit}}\n  <div class=\"asset-one-deeds\">\n    {{!\n      **한 단추가 둘을 보낸다** — 그룹과 태그는 폼이 갈리지만(하나는 관리자만 본다) 사람이\n      하는 일은 <i>이 창에서 고친 것을 적용한다</i> 하나다.\n    }}\n    <button class=\"button is-primary\" type=\"submit\" form=\"asset-one-tags\">{{t.document.asset_apply}}</button>\n    <button class=\"button is-light\" type=\"button\" data-asset-swap>{{t.document.asset_swap}}</button>\n    <button class=\"button is-light\" type=\"button\" data-asset-rethumb>{{t.document.asset_rethumb}}</button>\n    <button class=\"button is-light\" type=\"button\" data-asset-newthumb>{{t.document.asset_newthumb}}</button>\n    <button class=\"button is-danger asset-one-drop\" type=\"button\" data-asset-delete>{{t.document.asset_delete}}</button>\n  </div>\n  {{/can_edit}}\n</div>\n","asset-shot":"{{!\n  그림 하나 — **읽는 화면과 고치는 화면이 나눠 쓴다**\n  (<a href=\"../../../../.claude/milestone-36_asset_layer.md\">36</a> · 2026-09-16 요구).\n\n  **대체 텍스트는 이름이다.** 문서 레이어의 파일에는 대체 텍스트 칸이 없고(설명은 그 파일의\n  제 본문이 진다) 한 마디로 부를 이름이 곧 그 자리다.\n\n  **바이트가 없으면 서지 않는다** — 링크만 있는 것이 장차 이 표에 설 수 있고, 그때\n  <b>깨진 그림</b>을 세우지 않는다.\n}}\n{{#url}}\n<figure class=\"asset-shot\">\n  <img src=\"{{url}}\" alt=\"{{name}}\">\n</figure>\n{{/url}}\n","body-feedbody":"{{!\n  피드 본문 — **피드 다섯이 함께 쓴다** (05e 요구).\n\n  서버·홈·연합 피드와 포스트 북마크·리스트 피드가 각자 자기 이름의 템플릿을 갖되\n  (`feed-server` … `feed-list`) 그리는 것은 같으므로, 같은 것을 다섯 번 적지 않고\n  여기 한 벌만 둔다. **다르게 그리고 싶은 피드는 자기 템플릿에서 이것을 안 부르면 된다.**\n}}\n{{#posted_href}}\n<p class=\"notice\">{{t.feed.posted}} <a href=\"{{.}}\">{{t.feed.go_see}}</a></p>\n{{/posted_href}}\n\n{{#posts.length}}\n{{> body-newer}}\n<div class=\"feed\">\n  {{#posts}}{{> iteration-post}}{{/posts}}\n</div>\n{{> body-older}}\n{{/posts.length}}\n{{^posts.length}}\n{{!\n  **빈 자리는 한 번만 말한다** (2026-09-05 요구).\n\n  **~~필터가 전부 걷어 냈다는 것을 빈 자리가 말한다~~**(2026-08-26 요구 → 걷었다). 그 줄이\n  지키려던 것은 <b>원인이 이 화면에 없을 때</b>였다 — 값이 종류별 전역이라 다른 화면에서\n  끈 것 때문에 여기가 빌 수 있다. 그러나 실제로 서 보니 <b>없다는 말이 두 번</b>이었고,\n  <b>왜 없는지는 읽는 사람이 가릴 필요가 없는 구분</b>이었다(요구): 글이 없는 것과 걷어 낸\n  것이 화면에서 하는 일은 같다 — 읽을 것이 없다.\n\n  **시스템은 여전히 안다.** 필터 격자가 그 사실을 그 자리에서 말하고(`modal-feedfilters`의\n  `emptied`) 도구는 제목줄 우상단에 있다 — 원인을 찾는 사람은 거기서 만난다.\n}}\n<p class=\"empty\">{{t.empty.posts}}</p>\n{{/posts.length}}\n","body-newer":"{{!\n  **위쪽 로더 — `새 글 보기`** (2026-09-02 요구).\n\n  **하멜만의 것이다.** 카멜은 같은 자리에 <b>페이지 넘김</b>(`body-pager`)을 두는데, 그것은\n  <b>자바스크립트가 없어도 도는 하한</b>에 맞춘 모양이다 — 링크를 누르면 화면이 갈아 끼워지고\n  보던 자리를 잃는다. 하멜에는 그 하한이 없으므로(하한은 카멜이 진다) <b>이어 붙일 수 있다.</b>\n\n  **읽는 중에 화면이 저절로 바뀌지 않는다**는 선언은 그대로다 — 목록은 <b>사람이 누른 뒤</b>에만\n  움직인다.\n\n  **~~새 글이 있는지 시계가 물어보지 않는다~~ → 물어본다**(2026-09-08 요구). 뒤집힌 것은\n  <i>묻는 일</i>이지 <i>바꾸는 일</i>이 아니다 — 시계는 <b>이 줄을 세울지</b>만 정하고 목록은\n  그대로 있다. 그 전에는 새 글이 없어도 줄이 늘 서 있었고, 눌러 보고서야 없다는 것을 알았다.\n\n  **없으면 자리도 없다.** 처음에는 감춰 두고(`hidden`) 코어가 *있다*고 답할 때 선다 —\n  스크립트가 없으면 서지 않는데, 그 하한은 카멜이 지던 것이고 하멜에는 없다(위 문단).\n\n  **주소는 코어의 것이고 마크업이 들고 있다**(`Link` 헤더의 `rel=\"prev\"` — 프록시가 우리\n  주소로 다시 써서 준다). 화면이 커서를 짓지 않는다.\n\n  **커서가 없으면 서지 않는다.** 첫 페이지에도 `min_id`가 오므로(코어의 `PrevMinId`는\n  *페이지가 비어 있을 때만* 비어 있다) 이 줄은 글이 하나라도 있으면 선다.\n\n  **새 이름을 짓지 않았다** — `pager`를 그대로 입고 갈리는 것은 `data-load` 하나다.\n  스킨 검사가 그것을 잰다(클래스 이름이 곧 생김새다).\n}}\n{{#newer}}\n<nav class=\"pager\" aria-label=\"{{t.loader.label}}\" data-watch=\"{{.}}\" hidden>\n  <a rel=\"prev\" href=\"{{.}}\" data-load=\"newer\">{{t.loader.newer}}</a>\n</nav>\n{{/newer}}\n","body-older":"{{!\n  **아래쪽 로더 — `이전 글 보기`** (2026-09-02 요구).\n\n  위쪽과 한 짝이며(`body-newer`) 갈리는 것은 **방향**뿐이다: 받은 것을 목록 <b>뒤에</b> 이어\n  붙인다. 카멜의 `body-pager`가 서던 자리가 여기다.\n\n  **더 볼 것이 없으면 사라진다.** 코어가 `rel=\"next\"`를 내지 않는 것이 곧 그 뜻이며, 눌러도\n  아무 일이 없는 단추를 남겨 두지 않는다 — 카멜의 페이저도 같은 규칙을 쓴다.\n}}\n{{#older}}\n<nav class=\"pager\" aria-label=\"{{t.loader.label}}\">\n  <a rel=\"next\" href=\"{{.}}\" data-load=\"older\">{{t.loader.older}}</a>\n</nav>\n{{/older}}\n","body-quoted":"{{!\n  **폼 머리에 서는 그 글** — 답글의 원글 · 인용 대상 · 지우기·넓히기·가리기의 그 글.\n\n  **피드와 같은 마크업이다**(2026-09-03 요구). ~~자기 배치(`p.who`)~~를 갖고 있었는데\n  <b>그 이름에는 CSS가 한 줄도 없어</b> 꾸밈 없는 글자 뭉치로 섰다 — 인용 카드가 2026-09-01에\n  상자에 `post`를 함께 달아 <b>포스트의 규칙을 그대로 타게</b> 된 것과 같은 자리이며, 근거도\n  같다: *레이아웃을 포스트와 동일하게*. 머리 배치·두 줄 나눔·우상귀의 공개 범위·홈통이\n  포스트를 고칠 때 함께 따라온다.\n\n  **액션은 없다.** 여기는 그 글에 무언가 하는 자리가 아니라(그 일은 아래 폼이 한다) *무엇을\n  걸고 쓰는가*를 말하는 자리다 — 반응 단추가 두 벌 서면 같은 글의 수가 화면 두 곳에서\n  달라진다는, 인용 카드가 반응을 갖지 않는 근거와 같다.\n\n  **폼 머리에서는 사람에게로 가는 링크가 없다.** 쓰다 만 폼을 두고 떠나게 하지 않는다 —\n  시각 하나만 링크이고(그 글로 가는 길) 나머지는 글자로 선다. 얼굴이 감싼 링크를 잃었으므로\n  홈통의 자리는 그림 자신이 진다(`.post > header > .avatar`).\n\n  **제 자리에 서는 인용은 다르다**(`standalone` — 2026-09-13 요구). 문서 본문의 인용\n  블록이 그것인데, <b>거기에는 두고 떠날 폼이 없다</b> — 포스트를 인용한 것이니 포스트\n  렌더링으로서 온전히 굴러야 한다. 그때는 얼굴과 이름이 <b>피드에서와 똑같이</b> 카드를\n  연다(`data-profile`).\n\n  **모달 하나를 나눠 쓰는 것이 그 금지의 뿌리였다.** 폼도 카드도 같은 `<dialog>`에 담기므로\n  (`modal.ts`) 폼 위에서 이름을 누르면 <b>카드가 폼을 밀어낸다</b> — 쓰던 글이 사라진다.\n\n  이름표 규약은 `post` 조각과 같다(03d `값에 붙는 이름표`) — 같은 것을 가리키므로 키도 같다.\n}}\n<article class=\"post quoted\" data-key=\"post\" data-value=\"{{id}}\">\n  <header>\n    {{#standalone}}\n    {{! 얼굴과 이름이 같은 훅을 문다 — 피드에서와 같다(`iteration-post`). }}\n    <a class=\"avatar-link\" href=\"/@{{author.handle}}\" data-profile=\"{{author.handle}}\"\n       aria-hidden=\"true\" tabindex=\"-1\">{{#author.avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"48\" height=\"48\" loading=\"lazy\">{{/author.avatar_url}}{{^author.avatar_url}}<span class=\"avatar avatar-fallback\">{{> icon-person}}</span>{{/author.avatar_url}}</a>\n    <a class=\"author\" href=\"/@{{author.handle}}\" data-profile=\"{{author.handle}}\"\n       data-key=\"post.author\" data-value=\"{{author.handle}}\">{{#author}}{{> name-badged}}{{/author}}</a>\n    {{/standalone}}\n    {{^standalone}}\n    {{#author.avatar_url}}\n    <img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"48\" height=\"48\" loading=\"lazy\">\n    {{/author.avatar_url}}\n    <span class=\"author\" data-key=\"post.author\" data-value=\"{{author.handle}}\">{{#author}}{{> name-badged}}{{/author}}</span>\n    {{/standalone}}\n    {{! 아이디는 코드 블럭이고 누르면 복사된다(05e D4) — 피드에서와 같은 훅이다. }}\n    <code class=\"handle\" data-copy=\"@{{author.handle}}\"\n          data-key=\"post.handle\" data-value=\"{{author.handle}}\">@{{author.handle}}</code>\n    <a class=\"permalink\" href=\"{{permalink}}\"\n       data-key=\"post.created_at\" data-value=\"{{created_at}}\"><time datetime=\"{{created_at}}\"{{#created_title}} title=\"{{.}}\"{{/created_title}}>{{created_display}}</time></a>\n    {{> post-visibility}}\n  </header>\n\n  {{#hidden}}<p class=\"restricted\" data-key=\"post.visibility\" data-value=\"{{visibility}}\">{{hidden_label}}</p>{{/hidden}}\n\n  {{^hidden}}\n  <div class=\"content\">{{{content_html}}}</div>\n\n  {{! **첨부 목록은 한 조각이다**(43) — 글과 같은 것을 쓴다. }}\n  {{> post-media}}\n  {{/hidden}}\n</article>\n","body-redirect":"{{!\n  넘겨주기 알림 — **코어가 자리만 굽고 여기서 말한다**\n  (2026-09-11 요구 · 03d의 *코어는 키만 내고 뷰어가 문장을 만든다*).\n\n  **본문 앞단에 선다**(2026-09-13 요구). ~~조회가 표지를 따라 보내므로 여기까지 오는 것은\n  갈 곳이 없을 때였다~~ — 그런데 사람은 <b>왜 넘기는지를 적어 두고</b>, 곧장 보내면 그\n  문장이 읽히지 않는다. 이제 이 줄이 갈 곳을 가리키고 <b>가는 것은 사람이 고른다.</b>\n}}\n<span class=\"redirect-note\">{{t.document.redirect_to}}</span>\n<a href=\"{{href}}\"><code>{{path}}</code></a>\n","body-tabs":"{{!\n  피드의 탭줄 — **활동 · 로컬 미디어 · 원격 미디어** (2026-09-05 요구).\n\n  **북마크의 탭줄에서 뽑았다.** 그쪽은 대상(글·문서)을 갈랐고 이쪽은 <b>담긴 것</b>을 가르는데,\n  서는 자리와 마크업이 같으므로 같은 것을 두 벌 적지 않는다 — 값의 모양도 그대로다\n  (`path`·`title`·`active`).\n\n  **넘어온 것이 없으면 서지 않는다.** 연합 피드에는 원격 글의 첨부 칸이 없고 멘션은 코어에\n  자기 피드가 없어 검색으로 낸다 — 그 둘에는 뷰가 탭을 넘기지 않는다.\n\n  **Bulma의 `tabs`다**(2026-08-25 요구). `aria-current`는 그대로 둔다: 벤더가 아는 것은\n  `is-active`(눈에 보이는 표시)뿐이고 <b>지금 어느 자리인가를 말하는 것은 그것이 아니다.</b>\n}}\n{{#tabs.length}}\n<nav class=\"tabs\" aria-label=\"{{heading}}\">\n  <ul>\n    {{!\n      **탭도 그림과 낱말로 선다**(2026-09-06 요구 — 체크된 리스트 · 그림 · 필름 · 따옴표 ·\n      선물). 좁은 화면에서는 낱말이 잘려 그림만 남는다(설정 탭줄과 같은 처리이며,\n      `display: none`이 아니라 1px로 잘라 두므로 읽어 주는 길은 그대로다).\n\n      **그림은 이름으로 고른다**(`icon_is`). 무스타시는 이름을 값으로 조립할 수 없으므로\n      뷰가 켜 둔 칸을 보고 고르며, 설정 탭줄이 같은 규칙을 쓴다.\n\n      **그림 없는 탭도 있다** — 북마크의 글·문서 갈이가 그것이고, 그때는 낱말만 선다.\n\n      **문서 속성의 넷이 2026-09-07에 왔다** — 인포·사람·파일·경고. 좁은 화면에서 낱말이\n      잘리므로(`.tabs .nav-label`) <b>그림이 없으면 무엇인지 물어야 한다.</b>\n\n      **메시지함의 셋이 2026-09-08에 왔다** — 목록·아래 화살표·위 화살표. **이름은 하는 일이\n      아니라 모양이다**(README): 화살표 둘은 블록을 옮기는 자리에서도 쓰는 그림이고, 여기서는\n      <b>들어온 것과 나간 것</b>을 말한다.\n    }}\n    {{#tabs}}\n    <li{{#active}} class=\"is-active\"{{/active}}><a href=\"{{path}}\"{{#active}} aria-current=\"page\"{{/active}}\n       >{{#icon}}<span class=\"nav-icon\" aria-hidden=\"true\"\n        >{{#icon_is.list_check}}{{> icon-list-check}}{{/icon_is.list_check}}{{#icon_is.image}}{{> icon-image}}{{/icon_is.image}}{{#icon_is.film}}{{> icon-film}}{{/icon_is.film}}{{#icon_is.quote}}{{> icon-quote}}{{/icon_is.quote}}{{#icon_is.gift}}{{> icon-gift}}{{/icon_is.gift}}{{#icon_is.info}}{{> icon-info}}{{/icon_is.info}}{{#icon_is.person}}{{> icon-person}}{{/icon_is.person}}{{#icon_is.file}}{{> icon-file-text}}{{/icon_is.file}}{{#icon_is.warning}}{{> icon-warning}}{{/icon_is.warning}}{{#icon_is.arrow_down}}{{> icon-arrow-down}}{{/icon_is.arrow_down}}{{#icon_is.arrow_up}}{{> icon-arrow-up}}{{/icon_is.arrow_up}}{{#icon_is.robot}}{{> icon-robot}}{{/icon_is.robot}}</span>{{/icon}}<span\n        class=\"nav-label\">{{title}}</span></a></li>\n    {{/tabs}}\n  </ul>\n</nav>\n{{/tabs.length}}\n","body-title":"{{!\n  화면의 제목줄.\n\n  **줄의 우상단이 `화면 액션`의 자리다** (2026-08-26 요구). 그 화면에 딸린 일들을 점 셋\n  상자 하나에 담는다 — <b>포스트 액션·프로필 액션과 같은 모양</b>이며, 갈리는 것은\n  **딸린 대상**이다: 그쪽은 한 글·한 사람이고 이쪽은 <b>지금 보고 있는 화면</b>이다.\n\n  **무엇이 담기는지는 화면이 정한다.** 서버가 파샬의 이름을 넘기고(`actions.partial`)\n  여기서는 그것을 그 자리에 끼운다 — 상자와 여는 방식은 <b>모든 화면이 한 벌을 나눠 쓰고</b>\n  안에 서는 것만 갈린다. 이름을 서버가 넘기는 것은 템플릿 이름을 서버가 고르는 것과\n  같은 자리다(`sendPage`).\n\n  **여기서 부르는 이름은 고정이다**(`screen-actions`). 어느 파샬이 그 자리에 서는지는\n  렌더할 때 이어 준다(`withScreenActions`) — 동적 파샬로 하지 않은 이유는 <b>mustache 4.2가\n  그것을 모른다</b>는 것이다: 문법이 통과하지만 빈 문자열이 나온다.\n\n  **없으면 상자가 서지 않는다.** 액션이 하나도 없는 화면에 <b>비어 있는 점 셋</b>을\n  세우지 않는다.\n}}\n<div class=\"title-line\">\n  {{!\n    **부모를 가진 문서는 제목이 경로를 드러낸다** (2026-09-14 요구).\n\n    `2026년/12월/24일`이면 앞의 두 마디가 <b>자기 조상으로 가는 문</b>이고 마지막 마디는\n    링크가 아니다 — 지금 서 있는 자리라 누를 값이 없다.\n\n    **`/` 앞뒤에 공백을 두지 않는다**(요구). 경로는 한 덩어리의 이름이고, 띄우면 <b>세 이름이\n    나란히 선 것</b>처럼 읽힌다.\n\n    **조상이 없으면 서지 않는다** — 뷰가 빈 배열을 넘기므로 조건이 따로 없다.\n\n    **~~접두(`prefix`)와 부제(`subject`)~~가 걷혔다** (2026-09-14 요구 — *제목에서 접두어를\n    다 걷어낸다*). 남아 있던 둘이 이것이다: 해시태그 화면의 `해시태그: #고양이`와 없는\n    문서의 `테스트: 테스트`(1단 이름에서는 이름과 경로가 같아 **같은 말이 두 번** 섰다).\n    <b>제목은 그 자리의 이름 하나다</b> — 경로는 이제 마디로 서고, 그것은 설명이 아니라 길이다.\n  }}\n  <h1>{{#trail}}<a class=\"trail\" href=\"{{href}}\">{{label}}</a><span class=\"trail-mark\" aria-hidden=\"true\">/</span>{{/trail}}{{heading}}</h1>\n  {{!\n    **열리는 것이 둘이다** (2026-08-26 요구). 담기는 것이 서넛이면 <b>상자</b>가 그 자리에서\n    열리고(알림 화면), 격자만큼 크면 <b>모달</b>이 뜬다(피드의 필터 — 서른 줄짜리 드롭다운은\n    훑을 수 없다). **점 셋과 그 낱말은 어느 쪽이든 같다.**\n\n    갈림은 서버가 무엇을 넘겼는가다 — 파샬 이름이면 상자, 주소면 문이다.\n  }}\n  {{!\n    **게스트에게는 세우지 않는다** (2026-09-07 요구).\n\n    화면 액션에 담기는 것은 대개 <b>로그인해야 할 수 있는 일</b>이라, 게스트에게는 상자가\n    한두 줄짜리로 남거나 통째로 비어 어중간해진다.\n\n    **판단이 여기 있는 것이 맞다.** 무엇을 보일지는 <b>스킨의 재량</b>이고 뷰는 값을\n    넘기는 데까지다 — 뷰가 미리 지우면 <i>세우고 싶은 스킨</i>이 그럴 방법을 잃는다.\n\n    **감추는 것은 문이지 주소가 아니다.** 눌러서 간 화면이 권한을 재고 오류를 낸다 —\n    가림이 *목록에서 빼되 주소로는 열린다*고 한 그 구분과 같다.\n\n    **화면마다 가르지 않는다**(2026-09-07 요구). 그렇게까지 심화할 자리가 아니므로\n    <b>한 규칙이 모든 화면에 선다.</b>\n\n    **`signed_in`이지 `session`이 아니다** — 후자는 계정을 불러온 뒤에야 참이 되므로\n    그것으로 재면 <b>상자가 늦게 나타난다</b>. 포스트 액션이 같은 이유로 이 값을 쓴다.\n  }}\n  {{!\n    **역참조로 가는 곁문** (2026-09-07 요구 · 2026-09-19에 자리를 옮겼다).\n\n    문서를 읽는 화면에서 <b>순환링크로 가는 문</b>이다 — 31 확정 10이 *제목 옆*이라 한\n    자리이고, 본문 아래의 역참조 상자가 여는 곳과 같은 데로 간다.\n\n    **~~제목 안에 글자처럼 세웠다~~**(2026-09-19 아침) — 끝 글자를 따라가게 하려던 것인데\n    <b>글자와 그림의 수직 정렬이 떨어지지 않는다</b>: 기준선에 두면 처지고 가운데에 맞추면\n    글자마다 달리 보인다(문장에 이모지를 섞을 때의 그 문제다). **같은 줄에 이미 그림으로\n    선 것이 있으므로** 그 옆에 같은 크기로 세운다 — <b>맞출 대상을 글자에서 그림으로\n    바꾼다.</b>\n\n    **우상귀의 점 셋과 한 무리로 서되 다른 것이다.** 그쪽은 <i>이 화면에 무엇을 하는가</i>\n    이고 이것은 <b>하나뿐인 곁길</b>이라, 상자에 담지 않고 그림 하나로 선다 — 왼편이 그\n    사실을 말한다.\n\n    **그림은 사슬이다**(2026-09-07 요구). ~~되감기 화살표를 썼다~~ — <b>되돌리기와\n    역참조는 다른 일</b>인데 같은 그림을 주면 어느 쪽인지 물어야 한다.\n\n    **낱말은 눈에서만 빠진다**(`.title-aside`). 지우지 않고 잘라 두므로 스크린 리더는\n    여전히 읽는다 — 점 셋이 이미 같은 규칙이다.\n\n    **그 자리에서 연다**(`form`). 목록은 <i>어디로 갈까</i>를 고르는 길목이라 화면을 갈아\n    끼울 값이 없고, <b>스크립트가 죽으면 평범한 링크</b>라 그 주소의 페이지가 선다.\n  }}\n  {{#title_aside}}\n  <a class=\"title-aside\" href=\"{{href}}\" title=\"{{label}}\"{{#form}} data-form{{/form}}><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-link}}</span><span class=\"nav-label\">{{label}}</span></a>\n  {{/title_aside}}\n\n  {{!\n    **갈아타는 자리** (2026-09-05 요구 · 2026-09-19에 자리를 옮겼다).\n\n    피드를 보는 중에 다른 피드로 넘어가는 문이다. 담기는 것은 어느 피드에서나 같다 —\n    사람이 짠 주요 피드와 그것을 짜는 자리. <b>피드가 아닌 화면에는 뷰가 넘기지 않는다</b>.\n\n    **~~제목이 곧 그 문이었다~~**(2026-09-19 요구). 제목 영역 전체가 눌리는 것이 요점이었는데,\n    <b>제목의 성질이 화면마다 갈렸다</b>: 어떤 화면에서는 이름이고 어떤 화면에서는 단추라\n    <i>눌러도 되는가</i>를 매번 보아야 했다. 이제 <b>제목은 늘 이름</b>이고, 누르는 것은\n    점 셋 곁에 그림으로 선다 — 역참조 곁문이 이미 그 자리를 쓴다.\n\n    **서는 조건은 `feed_screen`이고 담기는 것은 `feed_switch`다** (2026-09-18) —\n    ~~목록의 길이로 갈랐다~~: 시스템 셋이 기본에서 빠진 뒤로 <b>목록이 비는 것이 예사</b>가\n    됐고, 길이로 가르면 그때 상자가 통째로 사라진다. 아래의 `내 피드 목록`은 <b>목록과\n    무관하게 늘 서는 줄</b>이라, 함께 사라지면 피드를 만드는 화면으로 가는 문이 없어진다.\n\n    **아래 화살표다** — 우상귀의 점 셋은 *이 화면에 무엇을 하는가*이고 이것은 <b>어디로\n    가는가</b>라, 그림이 갈려야 한다.\n\n    **`<details>`다** — 자바스크립트가 없어도 열리고 닫힌다(사이드바의 그 상자와 같은 규칙).\n\n    **폭은 기본형이다**(2026-09-21 요구). ~~`wide`를 입어 제목줄의 두 변에 붙었다~~(2026-09-05\n    보고 — *제목 길이에 따라 다른 자리에 뜬다*) — 그 보고의 상자는 <b>제목 자리에 있었고</b>\n    폭이 제목 길이를 따라 흔들렸다. 2026-09-19에 상자가 <b>오른쪽 무리의 그림</b>으로 옮겨\n    앉으면서 기대던 변이 <i>줄 끝</i> 하나로 고정됐고, 그때부터 화면 폭을 다 쓰는 것은\n    <b>까닭 없이 넓은 목록</b>이다 — 여느 드롭다운과 같은 상자로 되돌린다.\n  }}\n  {{#feed_screen}}\n  <details class=\"dropdown feed-switch\" data-dropdown>\n    <summary title=\"{{t.nav.main_feeds}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-chevron-down}}</span><span class=\"nav-label\">{{t.nav.main_feeds}}</span></summary>\n    <ul class=\"dropdown-menu\">\n      {{!\n        **항목마다 그림이 갈린다** (2026-09-05 요구) — 홈은 집, 서버는 눈, 연합은 지구,\n        커스텀 피드는 갈래를 따른다(계정=사람 · 해시태그=우물정 · 검색=물음표).\n\n        **뷰는 이름만 넘긴다**(`icon.home` 따위) — 그림은 스킨의 것이다. 뷰가 SVG를 지으면\n        <b>스킨을 갈아도 같은 그림이 따라온다.</b>\n      }}\n      {{#feed_switch}}\n      <li><a href=\"{{href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">\n        {{#icon.home}}{{> icon-lock}}{{/icon.home}}\n        {{#icon.server}}{{> icon-eye}}{{/icon.server}}\n        {{#icon.federated}}{{> icon-globe}}{{/icon.federated}}\n        {{#icon.account}}{{> icon-person}}{{/icon.account}}\n        {{#icon.tag}}{{> icon-hash}}{{/icon.tag}}\n        {{#icon.search}}{{> icon-question}}{{/icon.search}}\n      </span><span class=\"nav-label\">{{title}}</span></a></li>\n      {{/feed_switch}}\n      {{!\n        **`내 피드 목록`이 그 앞이다** (2026-09-05 요구 — 사이드바에서 옮겨 왔다).\n\n        위의 것들이 *짜 놓은 차례*라면 이 줄은 <b>내가 만든 것들의 목록</b>이고, 끝줄은\n        <b>이 상자 자체를 고치는 자리</b>다 — 가까운 것에서 먼 것으로 간다.\n\n        **만드는 일과 세우는 일은 다르다**(2026-08-24 요구): 그 화면에서 피드를 만들고\n        지우며, 메뉴에 세우는 것은 끝줄이 지는 일이다.\n      }}\n      <li><a class=\"to-my-feeds\" href=\"/-/feeds\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-list-plus}}</span><span class=\"nav-label\">{{t.nav.my_feeds}}</span></a></li>\n      {{!\n        **~~끝줄(`이 드롭다운 관리`)~~이 걷혔다** (2026-09-05 요구).\n\n        그 자리가 하던 일은 **`내 피드 구성` 화면이 진다** — 바로 위의 줄이 그리로 가고,\n        그 화면의 둘째 탭이 곧 이 상자의 차례를 짜는 자리다. **한 상자에 문이 둘일 이유가\n        없다.**\n      }}\n    </ul>\n  </details>\n  {{/feed_screen}}\n\n  {{!\n    **부속 — 점 셋 상자의 것이지만 밖으로 빼낸 것들** (2026-09-19 요구).\n\n    <b>자주 눌러서</b> 상자를 거치지 않게 한 자리다: 에셋 풀의 `그룹 관리`가 그 첫 줄이고,\n    고른 것이 있을 때만 뜻이 서므로 스크립트가 그 표를 켜고 끈다.\n\n    **여기 서는 것은 단추와 링크다** — 갈아타기·역참조처럼 그림 하나로 서는 것은 그 옆의\n    제 자리가 있다. 이쪽은 <b>낱말이 보이는 편이 나은 것</b>이고, 그래서 옷도 전역 규칙의\n    단추 그대로다.\n\n    **어느 파샬이 서는지는 뷰가 정한다**(`parts.partial`) — 점 셋 안이 그러는 것과 같은\n    기제이고, 자리와 차례는 여기 한 벌뿐이다.\n  }}\n  {{#parts.partial}}{{> title-parts}}{{/parts.partial}}\n\n  {{#signed_in}}\n  {{#actions.href}}\n  <a class=\"screen-actions door\" href=\"{{.}}\" data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.screen.actions}}</span></a>\n  {{/actions.href}}\n\n  {{#actions.partial}}\n  <details class=\"dropdown advanced screen-actions\" data-dropdown>\n    <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.screen.actions}}</span></summary>\n    <ul class=\"dropdown-menu\">\n      {{>screen-actions}}\n    </ul>\n  </details>\n  {{/actions.partial}}\n  {{/signed_in}}\n</div>\n","corpus-browser":"{{!\n  **글감을 훑는 한 벌** — 사이드바와 모달이 <b>같은 것</b>을 쓴다(2026-09-13 요구).\n\n  ~~사이드바에만 있었다~~. `/인용`이 그리로 초점을 옮겼는데 **초점이 옮겨진 것만으로는 입력의\n  다음 단계로 넘어갔다는 것을 알아채기 어렵다**는 것이 실물에서 드러났다 — 모달은 그 사실을\n  <b>덮어서</b> 말한다.\n\n  **한 벌을 두 자리에 세운다.** 베껴 두면 한쪽만 고쳐지는 날이 오고, 그날 사람은 <i>어느\n  쪽이 맞는가</i>를 묻게 된다.\n\n  **`id`를 두지 않는다.** 둘이 함께 서 있으므로 `id`는 반드시 겹치고, 겹친 `for`는 <b>엉뚱한\n  칸을 가리킨다</b> — 이름은 `aria-label`이 진다.\n}}\n<div class=\"corpus-head\">\n  {{!\n    **처음에는 아무 피드도 서지 않는다** (2026-09-07 요구). 편집 화면을 여는 것이 곧 글감을\n    부르는 일은 아니고, <b>고를 때 부르는 것</b>이 왕복도 적다 — `/인용`이 곧 그 *고를 때*라\n    모달은 열리면서 첫 피드를 세운다.\n  }}\n  <select data-corpus-feed aria-label=\"{{t.document.corpus}}\">\n    <option value=\"\">{{t.document.corpus_none}}</option>\n    <option value=\"home\">{{t.feed.home}}</option>\n    <option value=\"server\">{{t.feed.server}}</option>\n    <option value=\"federated\">{{t.feed.federated}}</option>\n    {{!\n      **내가 지은 피드도 글감의 출처다**(2026-09-08 요구). 시스템 피드 셋만 고를 수\n      있었는데, <b>글감으로 쓰려고 짜 둔 피드</b>가 대개 그 셋보다 좁다.\n\n      **값에 `list:`가 붙는다**: 시스템 피드는 이름이 곧 주소의 한 칸이고 커스텀 피드는\n      id로 부르므로, 한 칸에 담으려면 접두가 있어야 한다.\n\n      **없으면 줄도 없다** — 지은 피드가 하나도 없는 사람에게는 이 자리가 비어 있다.\n    }}\n    {{#corpus_feeds}}\n    <option value=\"list:{{id}}\">{{title}}</option>\n    {{/corpus_feeds}}\n  </select>\n  <input type=\"search\" placeholder=\"{{t.document.corpus_search}}\"\n         aria-label=\"{{t.document.corpus_search}}\" data-corpus-search>\n</div>\n<ul class=\"corpus-cards\" data-corpus-cards></ul>\n{{!\n  **자기 스크롤을 갖지 않는다** (2026-09-07 요구). 기둥 안에 스크롤바가 하나 더 서면\n  화면에 굴릴 것이 둘이 되고, 어느 것이 움직이는지가 매번 물음이 된다 —\n  <b>넘기는 것으로 대신한다.</b>\n}}\n<nav class=\"corpus-pages\" data-corpus-pages hidden>\n  <button type=\"button\" data-corpus-page=\"prev\">{{t.document.newer}}</button>\n  <button type=\"button\" data-corpus-page=\"next\">{{t.document.older}}</button>\n</nav>\n","emoji-grid":"{{!\n  **이모지 격자** (2026-09-21 요구 · <a href=\"../../../../.claude/milestone-45_emojis.md\">45</a> 확정 3·4).\n\n  **한 조각이 두 자리에 선다** — `/-/emojis`에서는 <b>다루는 격자</b>이고(누르면 그 이모지의\n  상자가 열린다) 고르는 창에서는 <b>고르는 격자</b>다(`picking` — 누르면 그 코드가 부른\n  자리에 담긴다). 생김새를 둘로 두면 같은 것을 고르는 일이 화면마다 다르게 보인다.\n\n  **칸은 그림이 전부다.** 이름은 손을 올렸을 때 뜬다 — 2rem 칸에 글자가 설 자리가 없다.\n}}\n<ul class=\"emoji-grid{{#picking}} is-picking{{/picking}}\">\n  {{#items}}\n  <li class=\"emoji-cell{{#chosen}} is-chosen{{/chosen}}{{^shortcode}} is-nameless{{/shortcode}}{{^enabled}} is-off{{/enabled}}\">\n    {{#picking}}\n    {{!\n      **고른 것이 무엇인지까지 함께 든다** (45 확정 19). 부르는 쪽에 따라 쓰는 것이 갈린다 —\n      본문에 넣는 자리는 <b>코드</b>를, 그룹 뱃지는 <b>갈래와 값</b>을 쓴다(그쪽은 코드를\n      풀 표를 들고 있지 않아야 한다).\n    }}\n    <button class=\"emoji-pick\" type=\"button\" data-emoji-pick=\":{{shortcode}}:\"\n            data-emoji-kind=\"{{kind}}\" data-emoji-value=\"{{value}}\" title=\"{{title}}\">\n      {{#url}}<img src=\"{{url}}\" alt=\"{{title}}\">{{/url}}{{#text}}<span class=\"emoji-glyph\">{{text}}</span>{{/text}}\n    </button>\n    {{/picking}}\n    {{^picking}}\n    {{!\n      **누르면 그 이모지의 상자가 열린다** (2026-09-22 요구).\n\n      ~~누르면 코드가 복사됐다~~(2026-09-21 요구) — 한 칸에 할 일이 <b>하나뿐일 때</b>의\n      모양이었다. 복사할 것만 셋이고(코드 · 유니코드 · 미디어 경로) 갈래마다 있는 것이\n      다르며, 등록정보와 지우기까지 붙으면 <b>누름 하나에 다섯을 담을 수 없다.</b>\n\n      **여는 일은 `<details>`가 진다**(전역 규칙) — 스크립트는 바깥 누름과 `Esc`로 닫기를\n      거들 뿐이고(`data-dropdown`), 죽어도 상자는 열리고 닫힌다.\n\n      **고르는 일은 그대로 수식 키가 진다**(에셋 풀의 규약). 수식 키를 누른 클릭에서는\n      상자가 열리지 않는다 — 스크립트가 그 누름을 막는다(`data-emoji-cell`).\n\n      **`aria-pressed`는 여기 없다.** `<summary>`는 <i>펼쳐졌는가</i>를 말하는 자리라\n      (`aria-expanded`는 브라우저가 적는다) 눌린 상태를 겹쳐 말하면 둘 다 흐려진다 —\n      고른 것은 <b>칸이</b> 말한다(`.emoji-cell.is-chosen`).\n    }}\n    <details class=\"dropdown emoji-menu\" data-dropdown>\n      <summary class=\"emoji-pick\" data-emoji-cell=\"{{id}}\" title=\"{{title}}\">\n        {{#url}}<img src=\"{{url}}\" alt=\"{{title}}\">{{/url}}{{#text}}<span class=\"emoji-glyph\">{{text}}</span>{{/text}}\n      </summary>\n      <ul class=\"dropdown-menu\">\n        {{!\n          **복사할 것은 갈래가 정한다.** 이름이 없으면 부를 코드가 없고, 유니코드에는 그림이\n          없으며(확정 5) 파일에는 글자가 없다 — <b>없는 것을 담은 줄을 세우지 않는다.</b>\n\n          **끈 것에도 코드는 있다.** ~~켜진 것만 복사됐다~~ — 끄는 일은 *고르는 판에 세우지\n          않는다*이지 <i>그 이름이 사라진다</i>가 아니고, 옛 글에는 그 코드가 그대로 적혀 있다.\n        }}\n        {{#shortcode}}\n        <li><button class=\"action\" type=\"button\" data-copy=\":{{shortcode}}:\"\n              ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-copy}}{{> icon-check}}</span><span class=\"nav-label\">{{t.emoji.copy_code}}</span></button></li>\n        {{/shortcode}}\n        {{#text}}\n        <li><button class=\"action\" type=\"button\" data-copy=\"{{text}}\"\n              ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-copy}}{{> icon-check}}</span><span class=\"nav-label\">{{t.emoji.copy_glyph}}</span></button></li>\n        {{/text}}\n        {{!\n          **주소는 `/`로 시작하므로 복사될 때 도메인이 붙는다**(`behaviors`의 규약) —\n          붙여 넣은 자리에서 <i>어느 서버의 그림인지</i>를 잃지 않는다.\n        }}\n        {{#url}}\n        <li><button class=\"action\" type=\"button\" data-copy=\"{{url}}\"\n              ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-link}}{{> icon-check}}</span><span class=\"nav-label\">{{t.emoji.copy_url}}</span></button></li>\n        {{/url}}\n        {{!\n          **고치고 지우는 것은 권한자의 자리다**(45 확정 3-1 · 39의 권한 축). 목록은 누구나\n          보지만(글에 선 그림이 무엇인지는 감출 것이 아니다) <b>눌러도 403인 항목을 두지\n          않는다</b> — 점 셋 상자가 서지 않는 것과 같은 판단이다.\n        }}\n        {{#emoji_admin}}\n        <li><button class=\"action\" type=\"button\" data-emoji-info=\"{{id}}\"\n              ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-info}}</span><span class=\"nav-label\">{{t.emoji.info}}</span></button></li>\n        {{!\n          **가로줄이 되돌릴 수 있는 것과 없는 것을 가른다**(전역 규칙). 위의 넷은 읽고\n          고치는 일이고 아래 하나는 <b>돌아오지 않는다</b> — 옛 글이 깨지지는 않지만\n          (확정 2) 그 이모지 자체는 사라진다.\n        }}\n        <li class=\"rule\" role=\"separator\"></li>\n        <li><button class=\"action delete\" type=\"button\" data-emoji-erase=\"{{id}}\"\n              ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-trash}}</span><span class=\"nav-label\">{{t.action.delete}}</span></button></li>\n        {{/emoji_admin}}\n      </ul>\n    </details>\n    {{/picking}}\n  </li>\n  {{/items}}\n</ul>\n","footer-site":"{{!\n  사이트 풋터. 지금은 서버 소개 한 줄이다.\n\n  **머리와 같은 뼈대로 선다**(2026-09-19 요구 — *헤더와 같은 스타일의 아웃라인*).\n  바깥이 선을 긋고 안쪽 `.bar`가 내용 폭을 진다 — 머리의 선이 화면을 가로지르므로\n  <b>발의 선도 그래야 짝이 된다</b>: 안쪽 요소에 선을 그으면 본문 폭에서 끊긴다.\n\n  **이름을 새로 짓지 않는다.** 안쪽 상자가 하는 일이 머리의 것과 같으므로 이름도 `bar`다.\n\n  **`px-4`를 빼고 제 이름으로 선다**(2026-09-19 요구 — `service-description`의 좌우 패딩은\n  0이다). 유틸리티는 `!important`로 붙어 스타일시트가 되돌릴 수 없으므로, 답은 <b>그\n  클래스를 마크업에서 빼는 것</b>이다 — `.container`에서 이미 한 번 배운 자리다.\n}}\n  <footer class=\"site\">\n    <div class=\"bar service-description py-5 has-text-grey\">\n      <p>{{instance.description}}</p>\n\n      {{!\n        **서비스가 무엇인지 말하는 문서 셋** (2026-09-19 요구 — 사이드바에서 옮겨 왔다).\n\n        소개·약관·정책은 한 무리다 — 셋 다 이 서비스를 설명하는 문서이고 읽는 사람이 찾는\n        자리도 같다. **발이 그 자리다**: 한 번 읽고 마는 문서라 <b>둘러보는 자리에 설\n        이유가 없고</b>, 페이지를 끝까지 읽어 내려온 눈이 마지막에 닿는 곳이다.\n\n        **정해 둔 것만 선다.** 비어 있으면 그런 문서가 없는 것이고, 없는 곳을 가리키는\n        링크를 세우지 않는다 — 로그인 화면이 약관·방침에 이미 그 규칙을 쓴다(05p).\n        하나도 없으면 목록 자체가 서지 않는다.\n\n        **그림은 두지 않는다.** 사이드바에서 아이콘이 하던 일은 <b>세로로 늘어선 줄들을\n        갈라 보이는 것</b>이었는데, 여기서는 셋이 한 줄에 나란히 서므로 <b>낱말이 곧\n        구분</b>이다 — 작은 글씨 옆의 그림 셋은 거들지 않고 시끄럽기만 하다.\n      }}\n      {{#site_links.length}}\n      <ul class=\"service-links\">\n        {{#site_links}}\n        <li><a href=\"{{href}}\">{{label}}</a></li>\n        {{/site_links}}\n      </ul>\n      {{/site_links.length}}\n    </div>\n  </footer>\n","header-account":"{{!\n  헤더 오른쪽의 사용자 액션 (05e 요구).\n\n  **쓰는 자리는 하나다**(2026-08-21 요구) — 어디서나 새 포스트다. 아카이브를 만드는 폼이\n  사라지면서 섹션마다 다르던 이유가 없어졌다.\n}}\n      <nav class=\"user-nav\" aria-label=\"{{t.nav.account}}\">\n        {{!\n          **메뉴는 목록이다.** 항목이 둘뿐이어도 그렇다 — 스크린 리더가 몇 개인지 먼저\n          알리는 것이 목록의 값이고, 그 값은 개수와 무관하다.\n\n          `class=\"write\"`이지 `compose`가 아니다. 후자는 <b>작성 폼</b>의 이름이고\n          (검사가 그것으로 *피드에 폼이 없음*을 본다) 이것은 폼으로 가는 링크다.\n        }}\n        <ul>\n          {{#session}}\n          {{!\n            **쓰는 자리는 하나다**(2026-08-21 요구). ~~아카이브 쪽에서는 `아카이브 생성`~~\n            이었다 — 그 폼이 사라졌고(아카이브는 없는 문서를 만들 때 함께 생긴다) 어디서나\n            <b>새 포스트</b>가 선다: 아카이브를 보다가 쓰고 싶어진 글도 결국 포스트다.\n          }}\n          <li class=\"nav-item\">\n            <a class=\"write button is-small is-primary\" href=\"/-/compose?return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-file-plus}}</span><span class=\"nav-label\">{{t.nav.compose}}</span></a>\n          </li>\n          <li class=\"nav-item\">\n            {{!\n              **`data-accounts`는 펼치는 순간 다른 계정을 묻는다는 뜻이다**\n              (2026-09-11 요구 — 다중 계정). 이름과 얼굴은 코어에 물어야 아는 값이라 첫\n              그림에 실으면 계정 수만큼 왕복이 얹힌다 — 관계를 상자를 펼칠 때 묻는 규칙과\n              같은 자리다(`data-relations`).\n            }}\n            <details class=\"dropdown account\" data-dropdown data-accounts>\n              {{!\n                **로그인해 있으면 얼굴과 이름이 선다**(05e 요구). `사용자 메뉴`라는 낱말이\n                아니라 <b>내가 누구로 들어와 있는지</b>를 말한다 — 그것이 이 메뉴에서 가장\n                자주 확인하는 값이고, 여는 것이 무엇인지는 열어 보면 안다.\n\n                **초상화가 없을 수 있다.** 그때는 사람 그림이 대신 선다 — 자리가 비면\n                이름만 남아 무엇을 여는 것인지 읽히지 않는다.\n              }}\n              <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{#avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"24\" height=\"24\">{{/avatar_url}}{{^avatar_url}}{{> icon-person}}{{/avatar_url}}</span><span class=\"nav-label\">{{> name-badged}}</span></summary>\n              <ul class=\"dropdown-menu\">\n                {{!\n                  **~~섹션을 고르는 자리~~를 걷었다**(2026-08-21 요구). `SNS 모드`·`아카이브\n                  모드` 둘이 여기 있었다.\n\n                  그것들은 헤더가 섹션마다 갈린 것을 <b>사람이 넘는 길</b>이었는데, 헤더가\n                  하나가 되면서 넘을 것이 없어졌다 — 아카이브는 기둥에 있는 갈 곳 하나이고\n                  (`sidebar`), 돌아오는 길도 같은 기둥이 진다. **모드라는 말 자체가\n                  없어진 것**이 요점이다: 두 세계를 오가는 것이 아니라 한 서비스 안에서\n                  다른 것을 볼 뿐이다.\n                }}\n                {{!\n                  **항목마다 그림이 앞에 선다** (2026-09-13 요구 · 피드 갈아타기 상자와 같은\n                  길). 목록에서 훑는 것은 <b>이름</b>이고 그림은 그것을 빨리 찾게 도울 뿐이라,\n                  그림이 자리를 고정하고 이름이 남는 자리를 다 쓴다.\n                }}\n                <li><a href=\"/@{{handle}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-person}}</span><span class=\"nav-label\">{{t.nav.profile}}</span></a></li>\n                {{!\n                  **설정이 둘로 갈렸다** (2026-08-23 요구). 앞엣것은 <b>나의 것</b>(프로필·개인화)\n                  이고 뒤엣것은 <b>서버의 것</b>(등록정보·겉보기·시스템·되돌리기)이다 — 탭이\n                  여섯이 되면서 한 줄이 화면을 다 먹었고, 섞여 있을 이유도 없었다.\n\n                  **서비스 설정은 관리자에게만 선다.** 값이 없으면 이 줄이 없다: 눌러도 404인\n                  자리를 메뉴에 두지 않는다.\n                }}\n                <li><a href=\"/-/settings\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-gear}}</span><span class=\"nav-label\">{{t.nav.settings}}</span></a></li>\n                {{#service_settings}}\n                {{!\n                  **서버를 다루는 줄은 갈라 세운다** (2026-09-15 요구).\n\n                  위는 <b>나의 것</b>이고 여기부터는 <b>서버의 것</b>이다 — 관리자에게만\n                  서므로, 구분선도 <b>이 조건 안</b>에 둔다: 밖에 두면 아닌 사람에게\n                  <i>아무것도 가르지 않는 줄</i> 하나가 남는다.\n                }}\n                <li class=\"rule\" role=\"separator\"></li>\n                <li><a href=\"{{.}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-server}}</span><span class=\"nav-label\">{{t.nav.service_settings}}</span></a></li>\n                {{!\n                  **그룹 관리가 서비스 설정과 한 묶음이다** (2026-09-17 요구 ·\n                  <a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a>).\n\n                  ~~사이에 줄을 그었다~~ — 둘 다 <b>서버를 다루는 일</b>이고 여는 사람도\n                  같다. 줄은 <i>성격이 갈리는 자리</i>에 긋는 것이지 항목마다 긋는 것이\n                  아니다: 셋을 다 그으면 묶음이라는 말이 뜻을 잃는다.\n\n                  **관리자에게만 선다** — 그룹을 배정하는 일은 지금 관리자의 것뿐이다(확정 4).\n\n                  **~~에셋 풀이 곁에 있었다~~**(2026-09-17 요구) — 풀에 직접 닿는 일이\n                  <b>로그인한 사람 모두에게 열리면서</b> 관리자 액션이 아니게 되었다.\n                  <b>문서 레이어의 사이드바</b>로 갔다: 자산을 찾는 사람은 문서를 읽는\n                  사람이고, 갈 곳은 머리가 아니라 그 옆이다.\n                }}\n                <li><a href=\"/-/groups\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-people}}</span><span class=\"nav-label\">{{t.nav.groups}}</span></a></li>\n                {{/service_settings}}\n                {{!\n                  **이모지 관리가 그룹 관리 다음이다** (2026-09-21 요구 ·\n                  <a href=\"../../../../.claude/milestone-45_emojis.md\">45</a>).\n\n                  **제 문지기를 든다**(`emoji_admin`) — 이모지 권한은 서비스 권한과 갈라\n                  두었으므로(2026-09-21) 그 권한만 가진 사람에게도 이 줄이 서야 하고,\n                  서비스 묶음 안에 두면 <b>그 사람에게는 보이지 않는다</b>.\n                }}\n                {{#emoji_admin}}\n                <li><a href=\"/-/emojis\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-smile}}</span><span class=\"nav-label\">{{t.nav.emojis}}</span></a></li>\n                {{/emoji_admin}}\n                {{#admin_menu}}\n                <li class=\"rule\" role=\"separator\"></li>\n                {{/admin_menu}}\n                <li><a href=\"/-/logout\" data-signing=\"out\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-logout}}</span><span class=\"nav-label\">{{t.nav.logout}}</span></a></li>\n                {{!\n                  ── 다중 계정 (2026-09-11 요구) ──\n\n                  **구분선 다음이 다른 사람이다.** 위의 넷은 <b>지금 이 사람</b>에 딸린\n                  것들이고(프로필·설정·로그아웃) 아래는 <b>다른 사람으로 가는 길</b>이다 —\n                  같은 줄에 섞으면 *로그아웃* 옆의 이름을 누르는 일이 생긴다.\n\n                  **묶음이 하나다**(`data-accounts-group` — 2026-09-25 요구). 갈아탈 줄과\n                  `계정 추가`가 <b>함께 서고 함께 갈린다</b> — 펼치는 순간 이 자리가 통째로\n                  *묻는 중*이 되고 답이 오면 통째로 다시 선다. ~~줄들만 뒤늦게 끼워\n                  넣었다~~: 조용히 있다가 항목이 늘면 <b>기다리면 되는 자리인지</b>를 알\n                  수 없다.\n\n                  **줄은 하나다.** 빈 칸이 줄을 만들지 않게 하는 길은 줄을 하나로 두는\n                  것이다 — 조건마다 *앞에 무엇이 있었는가*를 세는 방식은 칸이 늘 때마다\n                  그 셈이 자란다.\n\n                  **갈아타기는 폼이다.** 상태를 바꾸므로 링크가 아니다 — 미리 읽어 보는\n                  브라우저가 계정을 갈아 버린다.\n                }}\n                <li class=\"rule\" role=\"separator\"></li>\n                <li class=\"accounts\" data-accounts-group>{{> accounts-group}}</li>\n              </ul>\n            </details>\n          </li>\n          {{/session}}\n          {{!\n            **로그인은 돌아올 자리를 싣는다**(2026-08-21 요구). 막힌 자리에서 오류 화면이\n            주던 길이며(그 목록을 걷었다), 로그인한 뒤 <b>가려던 곳으로 돌아오는 것</b>은\n            목록이 아니라 이 링크의 성질이다.\n          }}\n          {{^session}}\n          <li class=\"nav-item\"><a href=\"/-/login?return={{path_encoded}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-person}}</span><span class=\"nav-label\">{{t.nav.login}}</span></a></li>\n          {{/session}}\n        </ul>\n      </nav>\n","header-search":"{{!\n  헤더의 검색 (05e 요구).\n\n  **자리는 서비스 이름 옆이다.** 둘러보기가 폭에 따라 기둥이 되었다 옆으로 누웠다 하는 동안\n  검색만은 언제나 같은 자리에 있다 — 찾는 일은 어느 섹션에 있든 같은 일이고, 무리에 섞여\n  자리를 함께 옮기면 *지금 어디를 뒤지는 것인지*가 배치마다 달리 읽힌다.\n\n  **이름은 그냥 `검색`이다.** 포스트냐 문서냐는 그 화면 안의 탭이 말한다 — 북마크와 같다.\n\n  **무엇을 뒤질지는 여기서 고른다**(M20 요구). ~~가는 곳은 지금 어디에 있는가가 정한다~~(M09)\n  에서 한 걸음 옮겼다 — 결과 화면의 탭줄과 <b>같은 모양</b>이 칸 옆에 서고, 문맥은\n  <b>처음 켜져 있는 탭</b>을 고르는 일로 남는다(`in_archive`). 폼이 가는 곳은 입구 하나다.\n\n  **`<li>`가 아니다.** 목록 안이 아니라 헤더 막대에 직접 선다.\n}}\n      <details class=\"dropdown wide search-nav\" data-dropdown>\n        {{!\n          **넓은 드롭다운이다**(05e 요구 — *본문 폭에 맞춘*). 가이드는 검색 결과 화면이\n          쓰는 것과 같은 목록이다(`views/search-guide.ts`).\n        }}\n        <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-search}}</span><span class=\"nav-label\">{{t.nav.search}}</span></summary>\n        <div class=\"dropdown-panel box\">\n          {{!\n            **주소는 이스케이프하지 않는다** — 세 겹 중괄호다. Mustache가 `/`를 `&#x2F;`로\n            바꾸는데 브라우저는 그것도 읽지만 <b>주소가 주소로 보이지 않는다</b>. 값은 서버가\n            고른 두 상수 중 하나이므로 사람이 넣은 글자가 여기 올 수 없다.\n          }}\n          <form class=\"search\" action=\"{{{search_action}}}\" method=\"get\" role=\"search\">\n            {{!\n              **스코프 탭은 결과 화면의 탭줄과 같은 것이다** (M20 요구) — Bulma의 `tabs`이며\n              설정 탭·검색 결과 탭과 한 규칙으로 선다.\n\n              **자바스크립트 없이 선다.** 링크가 아니라 라디오다 — 링크로 두면 <b>아직 치지\n              않은 낱말</b>을 데려갈 수 없고, 고르는 순간 화면이 한 번 갈린다. 값은 폼과 함께\n              입구로 실려 가고 거기서 이름 있는 주소로 내려앉는다.\n\n              **라디오는 보이지 않게 두되 지우지 않는다**(`is-sr-only`) — 키보드로 고르는 길과\n              읽어 주는 길이 그것에 걸려 있다. 눈에 보이는 표시는 `:has(:checked)`가 준다.\n            }}\n            <div class=\"tabs is-small search-scopes\">\n              <ul>\n                {{#search_scopes}}\n                <li>\n                  <label>\n                    <input class=\"is-sr-only\" type=\"radio\" name=\"scope\" value=\"{{value}}\"{{#active}} checked{{/active}}>\n                    <span>{{label}}</span>\n                  </label>\n                </li>\n                {{/search_scopes}}\n              </ul>\n            </div>\n\n            <div class=\"field has-addons\">\n            <p class=\"control is-expanded\">\n              <input class=\"input is-small\" type=\"search\" name=\"q\" value=\"{{query}}\"\n                     placeholder=\"{{t.nav.search}}\" autocomplete=\"off\" data-autocomplete>\n            </p>\n            <p class=\"control\">\n              <button class=\"button is-small\" type=\"submit\">{{t.action.search}}</button>\n            </p>\n            </div>\n          </form>\n\n          {{!\n            ~~**문법 표는 포스트를 찾을 때만 선다**(M09)~~ → **어느 탭에서나 선다**(M20).\n            여섯 연산자가 <b>세 대상 모두에서</b> 뜻을 가지므로 표 하나가 어디서나 참이다 —\n            거는 자리만 갈린다(`from:`은 글쓴이·문서 주인·그 계정 자신).\n          }}\n          {{#search_syntax.length}}\n          <section class=\"syntax content is-small\">\n            <h2>{{t.search.syntax}}</h2>\n            <dl>\n              {{#search_syntax}}\n              <dt><code>{{token}}</code></dt>\n              <dd>{{hint}} — <code>{{example}}</code></dd>\n              {{/search_syntax}}\n            </dl>\n            <p class=\"hint has-text-grey\">{{search_negation}}</p>\n          </section>\n          {{/search_syntax.length}}\n        </div>\n      </details>\n","icon-arrow-down":"{{! 아래 화살표 — 블록을 뒤로 옮긴다. }}\n<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M19 12l-7 7-7-7\"/></svg>\n","icon-arrow-up":"{{! 위 화살표 — 블록을 앞으로 옮긴다. }}\n<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 19V5M5 12l7-7 7 7\"/></svg>\n","icon-bell":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 9a6 6 0 1 0-12 0c0 5-2 6-2 6h16s-2-1-2-6\"/><path d=\"M10.4 20a2 2 0 0 0 3.2 0\"/></svg>\n","icon-bolt":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M13 2 4.5 13H11l-.5 9L20 11h-7z\"/></svg>\n","icon-card":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2.5\" y=\"5\" width=\"19\" height=\"14\" rx=\"2\"/><circle cx=\"8.5\" cy=\"10.5\" r=\"2\"/><path d=\"M5.5 16.2c.5-1.4 1.7-2.1 3-2.1s2.5.7 3 2.1\"/><path d=\"M15 10h4M15 14h4\"/></svg>\n","icon-check":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m4.5 12.5 5 5 10-11\"/></svg>\n","icon-chevron-down":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m6 9 6 6 6-6\"/></svg>\n","icon-clothes":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M8.5 3.5 4 6l1.6 4.2 2-.8V21h8.8V9.4l2 .8L20 6l-4.5-2.5z\"/><path d=\"M8.5 3.5 12 6.5l3.5-3\"/></svg>\n","icon-copy":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\"/><path d=\"M5 15H4.5A1.5 1.5 0 0 1 3 13.5v-9A1.5 1.5 0 0 1 4.5 3h9A1.5 1.5 0 0 1 15 4.5V5\"/></svg>\n","icon-dots":"<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\"><circle cx=\"5\" cy=\"12\" r=\"1.7\"/><circle cx=\"12\" cy=\"12\" r=\"1.7\"/><circle cx=\"19\" cy=\"12\" r=\"1.7\"/></svg>\n","icon-envelope":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\"/><path d=\"m3.6 6.6 8.4 5.9 8.4-5.9\"/></svg>\n","icon-expand":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 4.5H4.5V9M15 4.5H19.5V9M9 19.5H4.5V15M15 19.5H19.5V15\"/></svg>\n","icon-eye-off":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M3 3 21 21\"/></svg>\n","icon-eye":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2 12s3.6-6.5 10-6.5S22 12 22 12s-3.6 6.5-10 6.5S2 12 2 12z\"/><circle cx=\"12\" cy=\"12\" r=\"2.8\"/></svg>\n","icon-file-plus":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-9z\"/><path d=\"M14 3v6h6\"/><path d=\"M12 12.5v5M9.5 15h5\"/></svg>\n","icon-file-text":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 2.5h7l5 5v14H6z\"/><path d=\"M13 2.5v5h5\"/><path d=\"M9 13h6M9 17h4\"/></svg>\n","icon-film":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2.5\" y=\"4.5\" width=\"19\" height=\"15\" rx=\"2\"/><path d=\"M7.5 4.5v15M16.5 4.5v15M2.5 12h19\"/><path d=\"M2.5 8.2h5M2.5 15.8h5M16.5 8.2h5M16.5 15.8h5\"/></svg>\n","icon-gear":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M12 2.5v2.2M12 19.3v2.2M4.2 7l1.9 1.1M17.9 15l1.9 1.1M4.2 17l1.9-1.1M17.9 9l1.9-1.1\"/></svg>\n","icon-gift":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3.5\" y=\"10\" width=\"17\" height=\"10\" rx=\"1.5\"/><path d=\"M3.5 13.5h17M12 10v10\"/><path d=\"M12 10S10.8 5.5 8.8 5.5a2 2 0 1 0 0 4.5zM12 10s1.2-4.5 3.2-4.5a2 2 0 1 1 0 4.5z\"/></svg>\n","icon-github":"{{!\n  깃허브의 표 — **채우는 그림이다**(윤곽선 아이콘 무리와 갈린다).\n\n  로그인 수단은 <b>남의 서비스</b>를 가리키므로 그 서비스가 아는 모양이어야 한다 —\n  우리 아이콘 규약(`stroke`)에 맞춰 다시 그리면 알아보지 못한다.\n\n  **한 색이다.** 공식 표는 검정이지만 여기서는 `currentColor`로 둔다: 단추의 글자와 같은\n  색으로 서야 어두운 판에서도 읽힌다.\n}}\n<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M12 .5C5.73.5.5 5.73.5 12c0 5.08 3.29 9.39 7.86 10.91.58.11.79-.25.79-.56 0-.28-.01-1.02-.02-2-3.2.7-3.88-1.54-3.88-1.54-.52-1.34-1.28-1.69-1.28-1.69-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.56-.29-5.25-1.28-5.25-5.7 0-1.26.45-2.29 1.19-3.1-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11 11 0 0 1 5.8 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.12 3.05.74.81 1.18 1.84 1.18 3.1 0 4.43-2.69 5.4-5.26 5.69.41.36.78 1.07.78 2.16 0 1.56-.01 2.82-.01 3.2 0 .31.2.68.8.56A11.51 11.51 0 0 0 23.5 12C23.5 5.73 18.27.5 12 .5z\"/></svg>\n","icon-globe":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M3 12h18\"/><path d=\"M12 3a14 14 0 0 1 0 18 14 14 0 0 1 0-18z\"/></svg>\n","icon-google":"{{!\n  구글의 표 — **네 색을 그대로 둔다**(2026-09-14).\n\n  깃허브와 갈리는 자리다: 그쪽은 한 색이라 `currentColor`로 두어도 알아보지만, 구글의 표는\n  <b>색이 곧 그 표</b>라 단추의 글자색을 따르면 다른 그림이 된다.\n}}\n<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path fill=\"#4285F4\" d=\"M23.5 12.27c0-.82-.07-1.6-.2-2.36H12v4.47h6.45a5.5 5.5 0 0 1-2.39 3.62v3h3.86c2.26-2.08 3.58-5.15 3.58-8.73z\"/><path fill=\"#34A853\" d=\"M12 24c3.24 0 5.96-1.08 7.95-2.91l-3.87-3a7.2 7.2 0 0 1-10.72-3.78H1.4v3.09A12 12 0 0 0 12 24z\"/><path fill=\"#FBBC05\" d=\"M5.36 14.31a7.1 7.1 0 0 1 0-4.6V6.62H1.4a12 12 0 0 0 0 10.76l3.96-3.07z\"/><path fill=\"#EA4335\" d=\"M12 4.75c1.77 0 3.35.61 4.6 1.8l3.43-3.43C17.95 1.2 15.23 0 12 0A12 12 0 0 0 1.4 6.62l3.96 3.09A7.15 7.15 0 0 1 12 4.75z\"/></svg>\n","icon-grip":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 6h.01M9 12h.01M9 18h.01M15 6h.01M15 12h.01M15 18h.01\"/></svg>\n","icon-hash":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 9h16M4 15h16M10 3 8 21M17 3l-2 18\"/></svg>\n","icon-heart":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20.8 5.6a5 5 0 0 0-7.1 0L12 7.3l-1.7-1.7a5 5 0 0 0-7.1 7.1l8.8 8.8 8.8-8.8a5 5 0 0 0 0-7.1z\"/></svg>\n","icon-home":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m3 10.2 9-7.2 9 7.2V20a1.8 1.8 0 0 1-1.8 1.8H4.8A1.8 1.8 0 0 1 3 20z\"/><path d=\"M9.4 21.8v-8h5.2v8\"/></svg>\n","icon-image":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2\"/><circle cx=\"8.5\" cy=\"9.5\" r=\"1.6\"/><path d=\"m4 17 4.8-4.8 3.2 3.2 3-3L20 16.5\"/></svg>\n","icon-info":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 11.5v5\"/><path d=\"M12 7.75h.01\"/></svg>\n","icon-link":"{{!\n  사슬 두 고리.\n\n  **`rewind`와 갈라 둔다**(2026-09-07 요구). 되돌리기와 역참조는 다른 일인데 같은 그림을\n  주면 <b>어느 쪽인지 물어야 한다</b> — 이름을 모양으로 짓는 규칙은 *같은 그림에 이름을\n  여럿 주지 말라*는 뜻이지 다른 일에 같은 그림을 주라는 뜻이 아니다.\n}}\n<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>\n","icon-list-check":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 6.5h10M10 12h10M10 17.5h10\"/><path d=\"m3.5 6.3 1.4 1.4 2.3-2.4\"/><path d=\"m3.5 11.8 1.4 1.4 2.3-2.4\"/><path d=\"m3.5 17.3 1.4 1.4 2.3-2.4\"/></svg>\n","icon-list-plus":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 5.5h11M4 12h11M4 18.5h7\"/><path d=\"M18 15v6M15 18h6\"/></svg>\n","icon-lock":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"4\" y=\"10\" width=\"16\" height=\"11\" rx=\"2\"/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"/></svg>\n","icon-logout":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14.5 4.5h3a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-3\"/><path d=\"M10 8.5 6.5 12 10 15.5\"/><path d=\"M6.5 12H15\"/></svg>\n","icon-map-pin":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>\n","icon-mention":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M16 12v1.5a2.5 2.5 0 0 0 5 0V12a9 9 0 1 0-3.6 7.2\"/></svg>\n","icon-menu":"{{!\n  햄버거 — **좁은 화면에서 기둥을 부르는 손잡이** (2026-09-07 요구).\n\n  줄 셋이다. 그것이 *메뉴*를 뜻한다는 약속은 이미 굳었고, 여기서 다른 그림을 쓰면 <b>무엇을\n  여는 단추인지</b>를 사람이 눌러 보아야 안다.\n}}\n<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M4 7h16M4 12h16M4 17h16\"/></svg>\n","icon-pencil":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 20h4l10-10a2.8 2.8 0 1 0-4-4L4 16z\"/><path d=\"M13.5 6.5l4 4\"/></svg>\n","icon-people":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"9\" cy=\"8\" r=\"3.5\"/><path d=\"M2.5 20c0-3.4 2.9-5.5 6.5-5.5s6.5 2.1 6.5 5.5\"/><path d=\"M16.5 5.2a3.5 3.5 0 0 1 0 6.6\"/><path d=\"M18.5 15c1.9.8 3 2.2 3 4\"/></svg>\n","icon-person-plus":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"9.5\" cy=\"8\" r=\"3.5\"/><path d=\"M3.5 19.5c0-3.3 2.7-5.5 6-5.5s6 2.2 6 5.5\"/><path d=\"M18.5 8.5v6M15.5 11.5h6\"/></svg>\n","icon-person":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"8\" r=\"4\"/><path d=\"M4 21c0-4 3.6-6.5 8-6.5s8 2.5 8 6.5\"/></svg>\n","icon-pin":"<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M9 3h6l-1 6 3 3.2V15H7v-2.8L10 9z\"/><path d=\"M11.1 15h1.8v6.2h-1.8z\"/></svg>\n","icon-play":"<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\"><path d=\"M8 5.5v13l11-6.5z\"/></svg>\n","icon-question-circle":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M9.9 9.75a2.25 2.25 0 1 1 2.7 2.25c-.38.15-.6.53-.6.98v.52\"/><path d=\"M12 16.5h.01\"/></svg>\n","icon-question":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9.2 9a3 3 0 1 1 3.6 3c-.5.2-.8.7-.8 1.3v.7\"/><path d=\"M12 18h.01\"/></svg>\n","icon-quote":"<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M9.5 6.5c-2.5 1-4 3.2-4 6V17h5.5v-5.5H8c0-1.8.6-3.1 2.2-4z\"/><path d=\"M18.5 6.5c-2.5 1-4 3.2-4 6V17H20v-5.5h-3c0-1.8.6-3.1 2.2-4z\"/></svg>\n","icon-reply":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 11.5a7.5 7.5 0 0 1-7.5 7.5H8l-4.5 3v-5A7.5 7.5 0 1 1 20 11.5z\"/></svg>\n","icon-repost":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 9.5V8a3 3 0 0 1 3-3h9\"/><path d=\"m13 2 3 3-3 3\"/><path d=\"M20 14.5V16a3 3 0 0 1-3 3H8\"/><path d=\"m11 22-3-3 3-3\"/></svg>\n","icon-rewind":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3.5 12a8.5 8.5 0 1 0 2.6-6.1\"/><path d=\"M3 4v5h5\"/></svg>\n","icon-robot":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"12\" rx=\"2\"/><path d=\"M12 4.5V8\"/><circle cx=\"12\" cy=\"3.2\" r=\"1.2\"/><path d=\"M2.5 13v3M21.5 13v3\"/><path d=\"M9 13v1.5M15 13v1.5\"/></svg>\n","icon-rotate":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 12a9 9 0 1 0 3-6.7L3 8\"/><path d=\"M3 3v5h5\"/></svg>\n","icon-search":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m20 20-3.7-3.7\"/></svg>\n","icon-server":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"7\" rx=\"2\"/><rect x=\"3\" y=\"13\" width=\"18\" height=\"7\" rx=\"2\"/><path d=\"M7 7.5h.01M7 16.5h.01\"/></svg>\n","icon-shield-check":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 3l7 3v5.5c0 4.4-2.9 8.2-7 9.5-4.1-1.3-7-5.1-7-9.5V6z\"/><path d=\"M9 12.3l2 2 4-4.2\"/></svg>\n","icon-smile":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M8.5 14.5a4.5 4.5 0 0 0 7 0\"/><path d=\"M9 9.5h.01\"/><path d=\"M15 9.5h.01\"/></svg>\n","icon-speaker-off":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 5 6.5 9H3v6h3.5L11 19z\"/><path d=\"m15.5 9.5 5 5M20.5 9.5l-5 5\"/></svg>\n","icon-star":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m12 3 2.9 5.9 6.5.9-4.7 4.6 1.1 6.5-5.8-3-5.8 3 1.1-6.5L3.4 9.8l6.5-.9z\"/></svg>\n","icon-trash":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4.5 7h15\"/><path d=\"M9.5 7V5.5A1.5 1.5 0 0 1 11 4h2a1.5 1.5 0 0 1 1.5 1.5V7\"/><path d=\"M6.5 7l.8 12.1a1.5 1.5 0 0 0 1.5 1.4h6.4a1.5 1.5 0 0 0 1.5-1.4L18.5 7\"/><path d=\"M10.5 11v6M13.5 11v6\"/></svg>\n","icon-warning":"{{! 세모 안의 느낌표 — 되돌릴 수 없는 일이 있는 자리. }}\n<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0zM12 9v4M12 17h.01\"/></svg>\n","iteration-account":"{{!\n  다른 계정 한 줄 — **누르면 갈아탄다** (2026-09-11 요구 — 다중 계정).\n\n  **지금 계정의 줄과 같은 모양이다**(얼굴·이름) — 읽는 사람에게 그 둘은 같은 것이고,\n  갈리는 것은 <i>누르면 갈아탄다</i>는 것뿐이다.\n\n  **폼인 것은 상태를 바꾸기 때문이다.** 미리 읽어 보는 브라우저가 계정을 갈아 버리지\n  않도록 링크로 두지 않으며, 드롭다운 안의 폼 줄은 이미 있는 모양이다(`.action-form`).\n}}\n<span class=\"action-form\"><form method=\"post\" action=\"/-/accounts/{{session}}/switch\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <button type=\"submit\"><span class=\"nav-icon\" aria-hidden=\"true\"\n    >{{#avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"24\" height=\"24\">{{/avatar_url}}{{^avatar_url}}{{> icon-person}}{{/avatar_url}}</span><span\n    class=\"nav-label\">{{> name-badged}}</span></button>\n</form></span>\n","iteration-person":"{{!\n  **남의 서버 사람도 우리 화면에서 연다** (2026-09-06 — ~~그 서버로 보냈다~~).\n\n  <b>그 자리가 생겼다</b>: 원격 프로필 화면이 서면서 팔로우·세워 둔 글·*이사했습니다*가\n  우리 안에서 보인다 — 밖으로 보내면 <b>따라가려던 사람이 남의 로그인 화면을 만난다.</b>\n  주소는 `acct`가 진다: 도메인이 붙어 있어야 남의 `@bob`과 우리 `@bob`이 갈린다.\n}}\n{{#remote}}<a class=\"author remote\" href=\"/@{{acct}}\" data-profile=\"{{acct}}\" title=\"@{{acct}}\">\n  {{#avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"32\" height=\"32\" loading=\"lazy\">{{/avatar_url}}{{^avatar_url}}<span class=\"avatar avatar-fallback\" aria-hidden=\"true\">{{> icon-person}}</span>{{/avatar_url}}\n  {{> name-badged}}\n</a>\n<span class=\"handle\">@{{handle}}<span class=\"mention-domain\">@{{domain}}</span></span>{{/remote}}\n{{^remote}}<a class=\"author\" href=\"/@{{handle}}\" data-profile=\"{{handle}}\">\n  {{#avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"32\" height=\"32\" loading=\"lazy\">{{/avatar_url}}{{^avatar_url}}<span class=\"avatar avatar-fallback\" aria-hidden=\"true\">{{> icon-person}}</span>{{/avatar_url}}\n  {{> name-badged}}\n</a>\n<span class=\"handle\">@{{handle}}</span>{{/remote}}\n","iteration-post":"{{!\n  **메타 항목마다 `data-key`·`data-value`가 붙는다**(03d `값에 붙는 이름표`). 텍스트는\n  사람이 읽을 것이고 `data-value`는 기계가 읽을 원시값이라, 스킨은 문구를 파싱하지 않고\n  `[data-key=\"post.visibility\"][data-value=\"followers\"]`처럼 골라 꾸밀 수 있다.\n}}\n{{!\n  **읽지 않음은 글에 얹힌다**(2026-09-08 요구 — 메시지함이 피드와 같은 마크업을 쓴다).\n\n  ~~목록이 자기 상자로 감싸고 그 상자에 달았다~~ — 그러면 이 목록만 자기 마크업을 지고\n  피드를 고칠 때 따라오지 않는다. **메시지가 아닌 글에는 그 칸이 없으므로 속성도 서지\n  않는다.**\n}}\n<article class=\"post{{#in_reply_to}} reply{{/in_reply_to}}\" id=\"post-{{key}}\" style=\"--depth: {{depth}}\"\n         data-key=\"post\" data-value=\"{{key}}\"{{#unread}} data-unread=\"true\"{{/unread}}>\n  {{#hidden}}\n  {{!\n    **여기 남는 메타는 공개 범위 하나뿐이다.** 익명 자리는 작성자도 본문도 싣지 않는다\n    (PROJECT.md `접근 권한`) — 이름표도 있는 것에만 붙는다.\n  }}\n  <p class=\"restricted\" data-key=\"post.visibility\" data-value=\"{{visibility}}\">{{hidden_label}}</p>\n  {{/hidden}}\n\n  {{^hidden}}\n  {{#repost}}\n  {{!\n    시각을 함께 낸다. 이 항목의 자리는 **리포스트한 때**가 정하는데 아래 헤더의 날짜는\n    **원글이 쓰인 때**라, 옛 글이 맨 위에 옛 날짜를 달고 서면 정렬이 깨진 것으로 읽힌다.\n  }}\n  {{!\n    **원격이 퍼뜨렸으면 링크가 아니다**(2026-08-26). `by.id`가 가리키는 것이 원격 액터라\n    `/@아이디`가 그 사람을 찾지 못한다 — 눌러도 404가 되는 링크를 세우지 않는다. 이름은\n    도메인까지 적는다: `@bob`이 두 서버에 있을 수 있다.\n  }}\n  <p class=\"repost-note\">\n    {{^remote}}<a href=\"/@{{by.handle}}\" data-profile=\"{{by.handle}}\"\n       data-key=\"post.repost_by\" data-value=\"{{display}}\">@{{display}}</a>{{/remote}}{{#remote}}<span\n       class=\"remote-actor\" data-key=\"post.repost_by\" data-value=\"{{display}}\">@{{display}}</span>{{/remote}} {{t.post.reposted_by}}\n    <time datetime=\"{{at}}\"{{#at_title}} title=\"{{.}}\"{{/at_title}} data-key=\"post.repost_at\" data-value=\"{{at}}\">{{at_display}}</time> {{t.post.repost_suffix}}\n  </p>\n  {{/repost}}\n\n  <header>\n    {{!\n      **얼굴을 눌러도 그 사람의 자리로 간다**(2026-08-20 요구). 이름 옆에 서 있던 것과 같은\n      훅(`data-profile`)이라 <b>같은 카드가 뜬다</b> — 그림과 이름이 한 사람을 가리키는데\n      누를 수 있는 것이 이름뿐인 것은, 그림을 누른 사람에게 아무 일도 일어나지 않는다는 뜻이다.\n\n      **링크로 감싼다.** 훅만 달면 자바스크립트가 없을 때 눌리지 않는다 — 카드는 향상이고\n      하한은 그 사람의 화면으로 가는 평범한 링크다(*자바스크립트가 없어도 전부 동작한다*).\n\n      **읽는 쪽에서는 뺀다**(`aria-hidden`·`tabindex=\"-1\"`). 바로 옆의 이름이 같은 곳을\n      가리키므로 그대로 두면 같은 링크가 연달아 둘 읽힌다.\n    }}\n    {{!\n      **얼굴이 없으면 사람 그림이 선다** (2026-09-11 요구 — 계정 초상화 폴백).\n\n      ~~링크째 서지 않았다~~ — 본문은 홈통만큼 밀려 있는데(`--gutter`) 그 자리가 비어\n      <b>글이 한 칸 밀린 것처럼</b> 보였다. 머리의 사용자 메뉴가 이미 같은 폴백을 쓴다\n      (`header-account`) — 같은 값이 자리마다 다르게 떨어지면 그것이 곧 어긋남이다.\n    }}\n    <a class=\"avatar-link\" href=\"/@{{author.handle}}\" data-profile=\"{{author.handle}}\"\n       aria-hidden=\"true\" tabindex=\"-1\">{{#author.avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"48\" height=\"48\" loading=\"lazy\">{{/author.avatar_url}}{{^author.avatar_url}}<span class=\"avatar avatar-fallback\">{{> icon-person}}</span>{{/author.avatar_url}}</a>\n    <a class=\"author\" href=\"/@{{author.handle}}\" data-profile=\"{{author.handle}}\"\n       data-key=\"post.author\" data-value=\"{{author.handle}}\">{{#author}}{{> name-badged}}{{/author}}</a>\n    {{!\n      **이름과 아이디가 다른 키다.** 값은 같지만 하나는 사람이 고른 이름이고 하나는 주소라,\n      한쪽만 감추는 스킨이 있을 수 있다.\n    }}\n    {{!\n      **아이디는 코드 블럭이다**(05e 요구). 사람이 고른 이름과 달리 이것은 *그대로 옮겨 적어야\n      하는 문자열*이라 — 멘션에 치고, 검색의 `from:`에 넣고, 남에게 알려 준다.\n\n      **누르면 복사된다**(05e 요구 D4). 훅은 무엇을 복사할지만 말하고, 누를 수 있는 것으로\n      만드는 일은 스크립트가 한다 — 마크업에 단추를 두면 스크립트가 없을 때 아무 일도\n      일어나지 않는 단추가 선다. 없을 때의 하한은 코드 블럭 그 자체다(골라서 복사한다).\n    }}\n    <code class=\"handle\" data-copy=\"@{{author.handle}}\"\n          data-key=\"post.handle\" data-value=\"{{author.handle}}\">@{{author.handle}}</code>\n    <a class=\"permalink\" href=\"{{permalink}}\"\n       data-key=\"post.created_at\" data-value=\"{{created_at}}\"><time datetime=\"{{created_at}}\"{{#created_title}} title=\"{{.}}\"{{/created_title}}>{{created_display}}</time></a>\n    {{!\n      **`·n판`이 시각 옆에 선다**(2026-09-06 요구) — 판이 둘 이상일 때만이다.\n\n      <b>가는 곳은 그 판의 화면이다</b>(목록이 아니다). 거기서 목록으로 가는 문이 다시 서고,\n      목록에서 둘을 골라 견준다 — <b>지금 읽은 것이 무엇인지</b>부터 보이는 차례다.\n\n      **점은 마크업이 낸다.** 문구는 번호만 말하므로(`3판`) 앞의 구분점은 <i>시각 옆에\n      붙는다</i>는 자리의 사실이고, 그것은 표현이다.\n\n      **값은 그 문구가 말하는 번호다** — 문구와 주소와 값이 한 번호를 말한다(뷰가 셋을 함께\n      짓는다). 없으면 속성도 내지 않는다(03d `없는 것에는 달지 않는다`).\n    }}\n    {{#revision_label}}<a class=\"revision-note\" href=\"{{revision_href}}\"\n       data-key=\"post.revision\"{{#revision_value}} data-value=\"{{.}}\"{{/revision_value}}>·{{revision_label}}</a>{{/revision_label}}\n    {{!\n      **공개 범위는 상자의 우상귀다**(05e 요구) — 아래 오른쪽의 `포스트 액션`과 마주 본다.\n      *이 글이 어디까지 가는가*와 *이 글에 무엇을 하는가*는 같은 축의 두 물음이라 같은 변에 선다.\n\n      **그림으로 서고 낱말은 가려진다**(05e 요구). 갈리는 자리는 값이 아니라 이름이다 —\n      Mustache에 견줌이 없으므로 뷰가 `visibility_is.federated`처럼 열리는 자리를 준다.\n\n      **`비공개`는 아직 코어에 없다**(05e가 드러냈다). 자리를 먼저 세워 둔다 — 그 범위가\n      생기는 날 스킨은 이미 그림을 알고 있다.\n\n      **가리키면 낱말이 뜬다**(2026-08-20 요구 — `title`). 낱말을 눈에서 가린 자리라 그림\n      여섯을 외우지 않은 사람에게는 *어디까지 가는 글인지*를 알 방법이 없었다. 스크린 리더는\n      그대로 `.nav-label`을 읽으므로 이것은 **눈으로 보는 쪽의 하한**이다.\n    }}\n    {{!\n      **고정한 글은 그렇게 보인다**(2026-09-04 요구 — *지금은 아무 변화가 없어 보인다*).\n\n      **공개 범위 옆이 그 자리다.** 둘 다 <b>이 글이 놓인 사정</b>을 말하고(어디까지 가는가 ·\n      프로필에 세워져 있는가) 본문이 아니므로, 같은 변에 같은 규칙으로 선다 — 그림으로 서고\n      낱말은 눈에서만 가려지며 가리키면 뜬다.\n\n      **인용 카드에는 두지 않는다.** 카드에 담기는 것은 남의 글이고, 그 글이 그 사람의\n      프로필에 세워져 있는지는 이 자리에서 답할 물음이 아니다.\n    }}\n    {{#pinned}}\n    <span class=\"pinned-note\" title=\"{{t.post.pinned}}\" data-key=\"post.pinned\">\n      <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pin}}</span>\n      <span class=\"nav-label\">{{t.post.pinned}}</span>\n    </span>\n    {{/pinned}}\n    {{> post-visibility}}\n  </header>\n\n  {{#deleted}}\n  <p class=\"deleted\" data-key=\"post.deleted\" data-value=\"true\">{{t.post.deleted}}</p>\n  {{/deleted}}\n\n  {{^deleted}}\n  {{!\n    **가려진 글은 본문 자리가 갈린다** (M17).\n\n    **지워진 것과 다르다.** 저쪽은 글이 없고 이쪽은 <b>있는데 가려졌다</b> — 그래서 글쓴이와\n    시각은 그대로 서고, 되돌릴 수도 있다.\n\n    **본문은 코어가 이미 걷어 냈다.** 남에게 오는 `content_html`은 빈 문자열이므로 화면이\n    무언가를 감추는 것이 아니다 — 쓴 사람과 관리자에게는 본문이 함께 오고, 그때는 아래\n    안내와 본문이 나란히 선다: 무엇이 가려졌는지 알아야 이의를 제기할 수 있다.\n  }}\n  {{#is_blinded}}\n  <p class=\"blinded\" data-key=\"post.blinded\" data-value=\"true\">{{blind_label}}</p>\n  {{/is_blinded}}\n\n  {{!\n    **열람주의는 본문 앞에 서서 본문을 가린다** (M29 `가` · 2026-09-06).\n\n    <b>여는 것은 `details`다</b> — 자바스크립트 없이 서고, 열고 닫은 상태를 브라우저가 진다.\n    가리개의 글자가 곧 `summary`이므로 <b>화면이 문구를 지어내지 않는다</b>: 글쓴이가 쓴\n    그 말이 상자의 이름이다.\n\n    **본문을 두 번 적지 않는다.** 섹션이 여는 태그만 두르고 본문은 한 벌뿐이라, 가리개가\n    없는 글은 예전 그대로 `div.content` 하나로 선다 — 무스타시는 텍스트를 이어 붙일 뿐이므로\n    이렇게 감쌀 수 있다. 두 벌로 적으면 <b>본문을 고칠 때 한쪽만 고쳐진다.</b>\n  }}\n  {{#summary}}\n  <details class=\"cw\" data-key=\"post.summary\" data-value=\"{{.}}\">\n    <summary class=\"cw-label\">{{.}}</summary>\n  {{/summary}}\n  <div class=\"content\">{{{content_html}}}</div>\n  {{#summary}}\n  </details>\n  {{/summary}}\n\n  {{!\n    **여론조사는 읽기만 한다** (M29 `다`). 고르는 자리가 없는 것은 표를 던지는 일이 원본\n    서버로 나가는 기구를 요구하기 때문이고, <b>없는 단추를 세우면 눌린다.</b>\n\n    **비율은 뷰가 셌다**(`share`) — 스킨이 나누면 같은 셈이 스킨마다 살고, 여럿 고르는\n    조사에서 무엇으로 나눌지를 스킨이 판단하게 된다.\n  }}\n  {{#poll}}\n  <ul class=\"poll\" data-key=\"post.poll\" data-value=\"{{options.length}}\">\n    {{#options}}\n    <li style=\"--share: {{share}}%\" data-key=\"poll.option\" data-value=\"{{name}}\">\n      <span class=\"poll-name\">{{name}}</span>\n      {{#votes_display}}<span class=\"poll-votes\" data-key=\"poll.votes\" data-value=\"{{.}}\">{{.}}</span>{{/votes_display}}\n    </li>\n    {{/options}}\n  </ul>\n  <p class=\"poll-foot\">\n    {{#voters_display}}<span data-key=\"poll.voters\" data-value=\"{{.}}\">{{.}}{{t.poll.voters}}</span>{{/voters_display}}\n    {{#multiple}}<span data-key=\"poll.multiple\" data-value=\"true\">{{t.poll.multiple}}</span>{{/multiple}}\n    {{#ended}}<span data-key=\"poll.ended\" data-value=\"true\">{{t.poll.ended}}</span>{{/ended}}\n    {{^ended}}{{#ends_display}}<time class=\"poll-ends\"{{#ends_title}} title=\"{{.}}\"{{/ends_title}}\n          data-key=\"poll.ends_at\" data-value=\"{{.}}\">{{.}}{{t.poll.ends_suffix}}</time>{{/ends_display}}{{/ended}}\n  </p>\n  {{/poll}}\n\n  {{!\n    **민감 표시는 첨부를 가린다** (M29 `나`) — 열람주의와 다른 축이라 상자가 따로 선다.\n    열람주의를 연 사람이 그림까지 보기로 한 것은 아니다.\n  }}\n  {{#media.length}}\n  {{#sensitive}}\n  <details class=\"sensitive\" data-key=\"post.sensitive\" data-value=\"true\">\n    <summary class=\"sensitive-label\">{{t.post.sensitive}}</summary>\n  {{/sensitive}}\n  {{! **첨부 목록은 한 조각이다**(43) — 글·인용·판이 같은 것을 쓴다. 종류마다의 그림은 그 조각이 안다. }}\n  {{> post-media}}\n  {{#sensitive}}\n  </details>\n  {{/sensitive}}\n  {{/media.length}}\n\n  {{!\n    **인용 카드는 본문 아래 · 액션 위다** (M29 · 2026-08-31).\n\n    본문이 먼저인 것은 **내가 한 말이 먼저**이기 때문이다 — 카드가 위에 서면 남의 글이 내\n    글의 제목처럼 읽힌다. 첨부보다 아래인 것도 같은 결이다: 내가 붙인 것이 먼저다.\n\n    **카드에는 단추가 없다.** 무엇을 인용했는지만 말하고, 그 글에 무언가 하려면 눌러서 연다 —\n    카드마다 단추를 두면 같은 글의 수가 화면 두 곳에서 다르게 보이기 시작한다.\n\n    **승인이 없거나 거둬졌으면 자리 자체가 없다.** 코어가 걸러 보내므로 여기서 판정하지\n    않고, 그래서 화면은 *인용하지 않았다*와 구별하지 못한다 — 그것이 규격이 요구하는 바다.\n  }}\n  {{#quote}}\n  <blockquote class=\"post quote-card\" data-key=\"post.quote\" data-value=\"{{id}}\">\n    {{!\n      **머리가 포스트와 같은 마크업이다**(2026-09-01 요구 — *레이아웃을 포스트와 동일하게*).\n      상자에 `post`를 함께 달아 <b>같은 규칙을 그대로 탄다</b> — 카드용 배치를 따로 쓰면\n      포스트 머리를 고칠 때 이쪽이 따라오지 않는다. ~~갈리는 것은 초상화 크기 하나~~였는데\n      **그것도 걷혔다**(2026-09-08 요구): 얼굴은 포스트와 같은 지름으로 선다. 카드가 작게\n      읽히는 일은 본문 글자 크기와 배경이 진다.\n    }}\n    <header>\n      <a class=\"avatar-link\" href=\"/@{{author.handle}}\" data-profile=\"{{author.handle}}\"\n         aria-hidden=\"true\" tabindex=\"-1\">{{#author.avatar_url}}<img class=\"avatar\" src=\"{{.}}\" alt=\"\" width=\"48\" height=\"48\" loading=\"lazy\">{{/author.avatar_url}}{{^author.avatar_url}}<span class=\"avatar avatar-fallback\">{{> icon-person}}</span>{{/author.avatar_url}}</a>\n      <a class=\"author\" href=\"/@{{author.handle}}\" data-profile=\"{{author.handle}}\"\n         data-key=\"post.author\" data-value=\"{{author.handle}}\">{{#author}}{{> name-badged}}{{/author}}</a>\n      <code class=\"handle\" data-copy=\"@{{author.handle}}\"\n            data-key=\"post.handle\" data-value=\"{{author.handle}}\">@{{author.handle}}</code>\n      <a class=\"permalink\" href=\"{{permalink}}\"\n         data-key=\"post.created_at\" data-value=\"{{created_at}}\"><time datetime=\"{{created_at}}\"{{#created_title}} title=\"{{.}}\"{{/created_title}}>{{created_display}}</time></a>\n      {{> post-visibility}}\n    </header>\n\n    <div class=\"content\">{{{content_html}}}</div>\n  </blockquote>\n  {{/quote}}\n\n  {{!\n    **차례는 대화 → 반응 → 관리다**(03d `동작과 이동`). 앞의 셋은 글에 무언가를 보태는\n    일이고 뒤의 셋은 글 자체를 다루는 일이라, 자주 누르는 것이 앞에 서고 되돌리기 어려운\n    것이 뒤에 선다. `지우기`가 `답글` 옆에 서 있으면 오눌림의 값이 그만큼 비싸진다.\n\n    **05e가 그 차례를 자리로 굳혔다** — 기본 셋은 왼쪽에 늘어서고 나머지는 오른쪽 점 셋\n    안으로 들어간다. 요구가 `편집·삭제` 둘만 적었지만 ~~`문서에 담기`~~·`이력`도 같은 자리다:\n    셋 다 자기 글에만 서고 자주 누르는 것이 아니라는 점이 같다.\n\n    **상자 안의 차례는 상자가 정한다**(2026-08-22 요구) — `고치기 · ~~문서에 담기~~ ·\n    ~~새 문서 만들기~~ · 편집 이력 보기 · 지우기`. 줄에서 접힐 때 따라 들어온 차례를 그대로\n    쓰던 것을 <b>상자 안에서 자주 여는 것</b>과 <b>되돌릴 수 없는 것</b>으로 다시 세웠다(아래).\n\n    **지금은 `고치기 · 프로필에 세우기 · 포스트에 인용 · 문서 주소 복사 · 판 주소 복사 ·\n    편집 이력 보기 · 가리기 · 공개로 넓히기 · 지우기`다**(2026-09-03 요구가 담기를 걷고\n    복사 둘을 세웠다). 복사 둘은 나란히 선다 — <b>같은 글의 두 주소</b>이고, 판 쪽은 판이\n    둘 이상일 때만 온다.\n  }}\n  <footer class=\"actions\">\n    <span class=\"basic\">\n    {{#signed_in}}\n    {{!\n      **기본 액션은 그림으로 선다**(05e 요구). 낱말은 마크업에 남고 스타일시트가 눈에서만\n      가린다 — 지우면 그림 하나뿐인 자리를 무엇이라 부를지 알 수 없게 된다. 헤더의\n      둘러보기가 좁아질 때 하는 것과 같은 처리다.\n    }}\n    <a class=\"action reply\" href=\"/-/compose?in_reply_to={{id}}{{#reply_mention}}&amp;mention={{reply_mention}}{{/reply_mention}}&amp;return={{path_encoded}}\"\n       data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-reply}}</span><span class=\"nav-label\">{{t.post.reply}}</span><span class=\"count\">{{reply_count_display}}</span></a>\n    {{!\n      **`data-api`·`data-verb`는 하멜이 더한 훅이다.** 카멜에서는 이 링크가 <b>카멜 자신의\n      라우트</b>를 가리키고 그 서버가 코어를 부르는데, 하멜은 프록시이므로 **브라우저가 코어의\n      주소를 그대로** 부른다 — 그 값을 뷰가 실어 준다(스킨이 조립하지 않는다).\n\n      **어느 동사로 갈지는 서버가 정한다**(`reposted`). 화면이 다시 계산하면 어긋난다 —\n      카멜이 그 자리에서 `.../repost/unrepost`를 만들어 404를 냈다.\n\n      **카멜에서도 무해하다**: 그쪽은 이 두 속성을 읽지 않는다.\n    }}\n    <a class=\"action reaction\" data-toggle=\"repost\" rel=\"nofollow\"\n       data-api=\"{{api}}\" data-verb=\"{{#reposted}}unrepost{{/reposted}}{{^reposted}}repost{{/reposted}}\"\n       data-state=\"{{#reposted}}on{{/reposted}}{{^reposted}}off{{/reposted}}\"\n       data-on=\"{{t.post.repost_undo}}\" data-off=\"{{t.post.repost}}\"\n       href=\"{{permalink}}/-/{{#reposted}}unrepost{{/reposted}}{{^reposted}}repost{{/reposted}}?csrf={{csrf}}&return={{path_encoded}}\"\n       ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-repost}}</span><span class=\"nav-label\" data-label>{{#reposted}}{{t.post.repost_undo}}{{/reposted}}{{^reposted}}{{t.post.repost}}{{/reposted}}</span><span class=\"count\" data-count>{{repost_count_display}}</span></a>\n    {{!\n      **좋아요는 상대에게 향한다** (2026-08-31). 북마크와 나란히 서지만 성질이 반대다 —\n      저쪽은 나에게로 향하는 표시라 비공개이고, 이쪽은 알림이 가고 연합에 나가며 누가\n      눌렀는지도 공개다. 그래서 아이콘도 갈라 둔다(하트 · 별).\n    }}\n    {{!\n      **`data-api`·`data-verb`는 하멜이 더한 훅이다.** 카멜에서는 이 링크가 <b>카멜 자신의\n      라우트</b>를 가리키고 그 서버가 코어를 부르는데, 하멜은 프록시이므로 **브라우저가 코어의\n      주소를 그대로** 부른다 — 그 값을 뷰가 실어 준다(스킨이 조립하지 않는다).\n\n      **어느 동사로 갈지는 서버가 정한다**(`liked`). 화면이 다시 계산하면 어긋난다 —\n      카멜이 그 자리에서 `.../like/unlike`를 만들어 404를 냈다.\n\n      **카멜에서도 무해하다**: 그쪽은 이 두 속성을 읽지 않는다.\n    }}\n    <a class=\"action reaction\" data-toggle=\"like\" rel=\"nofollow\"\n       data-api=\"{{api}}\" data-verb=\"{{#liked}}unlike{{/liked}}{{^liked}}like{{/liked}}\"\n       data-state=\"{{#liked}}on{{/liked}}{{^liked}}off{{/liked}}\"\n       data-on=\"{{t.post.like_undo}}\" data-off=\"{{t.post.like}}\"\n       href=\"{{permalink}}/-/{{#liked}}unlike{{/liked}}{{^liked}}like{{/liked}}?csrf={{csrf}}&return={{path_encoded}}\"\n       ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-heart}}</span><span class=\"nav-label\" data-label>{{#liked}}{{t.post.like_undo}}{{/liked}}{{^liked}}{{t.post.like}}{{/liked}}</span><span class=\"count\" data-count>{{like_count_display}}</span></a>\n    {{!\n      **`data-api`·`data-verb`는 하멜이 더한 훅이다.** 카멜에서는 이 링크가 <b>카멜 자신의\n      라우트</b>를 가리키고 그 서버가 코어를 부르는데, 하멜은 프록시이므로 **브라우저가 코어의\n      주소를 그대로** 부른다 — 그 값을 뷰가 실어 준다(스킨이 조립하지 않는다).\n\n      **어느 동사로 갈지는 서버가 정한다**(`bookmarked`). 화면이 다시 계산하면 어긋난다 —\n      카멜이 그 자리에서 `.../bookmark/unbookmark`를 만들어 404를 냈다.\n\n      **카멜에서도 무해하다**: 그쪽은 이 두 속성을 읽지 않는다.\n    }}\n    <a class=\"action reaction\" data-toggle=\"bookmark\" rel=\"nofollow\"\n       data-api=\"{{api}}\" data-verb=\"{{#bookmarked}}unbookmark{{/bookmarked}}{{^bookmarked}}bookmark{{/bookmarked}}\"\n       data-state=\"{{#bookmarked}}on{{/bookmarked}}{{^bookmarked}}off{{/bookmarked}}\"\n       data-on=\"{{t.post.bookmark_undo}}\" data-off=\"{{t.post.bookmark}}\"\n       href=\"{{permalink}}/-/{{#bookmarked}}unbookmark{{/bookmarked}}{{^bookmarked}}bookmark{{/bookmarked}}?csrf={{csrf}}&return={{path_encoded}}\"\n       ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-star}}</span><span class=\"nav-label\" data-label>{{#bookmarked}}{{t.post.bookmark_undo}}{{/bookmarked}}{{^bookmarked}}{{t.post.bookmark}}{{/bookmarked}}</span><span class=\"count\" data-count>{{bookmark_count_display}}</span></a>\n    {{/signed_in}}\n    </span>\n\n    {{!\n      **고급 액션은 드롭다운 안에 있다**(05e 요구). 여는 것은 `포스트 액션`이라는 낱말이다 —\n      헤더의 `피드`·`사용자 메뉴`와 같은 판단이고, 점 셋이 남는 자리는 **문서 조각의 편집\n      핸들 하나**다: 그 자리는 좁아서 낱말이 들어가지 않는다.\n\n      드롭다운은 `<details>`라 자바스크립트가 없어도 열린다 — 안의 것들은 열려 있든 접혀\n      있든 평범한 링크 그대로다.\n\n      **~~자기 글일 때만 선다~~ → 로그인한 사람에게 선다**(08b). 남의 글도 문서에 담을 수\n      있게 되면서 <b>남의 글에도 열 것이 생겼다</b>. 커뮤니티 관리자에게 여는 일은 여전히\n      별도 마일스톤(M17)의 것이다 — 코어에 그런 권한이 없다.\n\n      **상자는 하나다.** 자기 글용과 남의 글용을 따로 세웠다가 곧 갈렸다 — 한쪽 스킨에서\n      점 셋 아이콘이 다른 쪽 상자에만 있었다. <b>같은 자리에 같은 모양으로 서는 것</b>이\n      규칙이면 마크업도 하나여야 하고, 갈리는 것은 <b>안에 무엇이 담기는가</b>뿐이다.\n    }}\n    {{#signed_in}}\n    {{!\n      **펼치는 순간 이 사람과의 관계를 묻는다**(2026-09-08 요구 — `data-relations`).\n\n      ~~상태를 모른 채 세웠다~~: 포스트에 관계를 실어 오면 <b>한 쪽에 선 저자만큼 왕복이\n      는다</b>. 목록에 글이 열이어도 <b>상자를 펴는 것은 하나</b>이고, 그때 묻는 것은 저자\n      하나다 — 보지 않을 것을 미리 묻지 않는다.\n\n      **자기 글에는 훅이 서지 않는다** — 물을 관계가 없다.\n    }}\n    <details class=\"dropdown advanced\" data-dropdown{{^own}} data-relations=\"{{author.id}}\"{{/own}}>\n      <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.post.actions}}</span></summary>\n      <ul class=\"dropdown-menu\">\n        {{!\n          **항목마다 그림이 선다**(2026-09-06 요구 — 연필·복사·따옴표·핀·선물·휴지통).\n\n          <b>낱말은 남는다.</b> 기본 액션과 같은 처리이며(`nav-icon`+`nav-label`), 지우면\n          그림 하나뿐인 자리를 무엇이라 부를지 알 수 없게 된다.\n\n          **가리기와 넓히기에도 준다**(방패·네 귀). 요구가 센 여섯은 늘 서는 것들이고 이 둘은\n          조건이 붙는 자리인데, 그림 없는 줄이 사이에 끼면 <b>목록이 어긋난 것으로 읽힌다</b> —\n          방패는 이 스킨이 이미 관리에 쓰는 그림이다(설정의 탭줄).\n\n          **차례는 2026-09-05 요구가 정했다**: 고치기 · 퍼머링크 복사하기 · 인용하기 ·\n          고정하기 · 추천하기 · 지우기.\n\n          **묶음이 셋으로 읽힌다.** 앞의 하나는 <b>이 글 자체를 고치는 일</b>이고, 가운데\n          넷은 <b>이 글을 어딘가에 놓는 일</b>이며(주소로 · 타임라인에 · 내 프로필 맨 위에 ·\n          내 추천 목록에), 끝은 <b>되돌릴 수 없는 일</b>이다.\n\n          **`own`으로 여닫는 자리가 셋으로 갈렸다** — 차례가 조건보다 앞서기 때문이다. 한\n          덩어리로 묶어 두면 *내 글일 때만 보이는 것들*이 서로 붙어 서고, 그러면 남의 글에서\n          상자의 차례가 통째로 달라진다.\n\n          **언급되지 않은 넷은 뒤에 남는다**(판 주소 복사 · 편집 이력 · 가리기 · 넓히기).\n          그중 판 주소만 앞으로 따라오는데, <b>퍼머링크 옆이 그 자리</b>이기 때문이다\n          (2026-09-03 요구).\n        }}\n        {{#own}}\n        <li><a class=\"action edit\" href=\"{{permalink}}/-/edit?return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pencil}}</span><span class=\"nav-label\">{{t.action.edit}}</span></a></li>\n        {{/own}}\n        {{!\n          **`퍼머링크 복사하기`가 둘째다**(2026-09-05 요구). ~~상자의 뒤쪽~~에 있었는데,\n          <b>글을 남에게 건네는 가장 짧은 길</b>이라 자주 눌리는 쪽으로 올라왔다.\n\n          **누르면 복사된다** — 링크인 것은 스크립트가 없을 때의 하한이다(그때는 그 자리로\n          간다). 훅은 무엇을 복사할지만 말한다.\n        }}\n        {{!\n          **복사한 표시는 그림이 진다**(2026-09-08 요구 — *`복사됨`이 붙는 동안 상자 폭이\n          흔들린다*).\n\n          낱말을 덧붙이면 <b>줄이 길어지고 상자가 그만큼 넓어진다</b> — 1.2초 동안 흔들리는\n          것이 복사보다 눈에 띈다. **그림 둘을 같은 자리에 세우고 하나만 보인다**: 폭이\n          변하지 않는다.\n\n          **읽어 주는 길에는 아무 일도 없다** — 이 자리는 `aria-hidden`이고, 무엇을 했는지는\n          클립보드에 든 것이 말한다.\n        }}\n        <li><a class=\"action copy-link\" href=\"{{permalink}}\"\n               data-copy=\"{{permalink}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-copy}}{{> icon-check}}</span><span class=\"nav-label\">{{t.post.copy_link}}</span></a></li>\n        {{!\n          **~~`판 주소 복사하기`~~와 ~~`편집 이력 보기`~~를 걷었다**(2026-09-06 요구).\n\n          <b>둘 다 판으로 가는 문이었고, 그 문이 헤더로 옮겨 갔다</b> — 시각 옆의 `·n판`이\n          그 자리다. 상자에 두면 <i>판이 있다</i>는 사실을 알려면 상자를 먼저 열어야 하는데,\n          헤더에 두면 <b>글을 읽는 동안 보인다.</b>\n        }}\n        {{!\n          **`인용하기`가 셋째다.** 이 글을 <b>타임라인에 놓는</b> 일이라 주소로 건네는 것\n          다음에 선다 — 안에서 하는 일일수록 앞이다.\n\n          **~~`포스트에 인용`~~이었다**(2026-08-31 요구 → 2026-09-05에 갈았다). 그 이름이\n          지키려던 것은 <b>문서에 끼워 넣는 일과 헷갈리지 않는다</b>였는데(08b `타인의 포스트\n          임베딩`), 그 자리가 상자에서 걷히면서(2026-09-03) **헷갈릴 상대가 사라졌다** —\n          이제 상자 안의 나머지가 모두 *하는 일*의 이름이라 낱말도 그 모양을 따른다.\n\n          **인용할 수 없는 글에도 선다.** 판정은 코어가 지고(정책·공개 범위) 안 되는 글은\n          오류 문구가 말한다.\n        }}\n        {{!\n          **줄 하나가 갈래를 가른다** — 위는 <b>이 글을 다루는 일</b>이고 아래는 <b>이 사람에게\n          말을 거는 일</b>이다(2026-09-08 요구).\n        }}\n        <li class=\"rule\" role=\"separator\"></li>\n        <li><a class=\"action quote\" href=\"/-/compose?quote={{id}}&amp;return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-quote}}</span><span class=\"nav-label\">{{t.post.quote}}</span></a></li>\n        {{!\n          **`멘션 보내기`와 `메시지 보내기`가 인용 다음이다**(2026-09-08 요구).\n\n          셋 다 <b>이 사람에게 말을 거는 일</b>인데 향하는 곳이 다르다 — 인용은 이 글을 걸고\n          타임라인에, 멘션은 이름을 불러 타임라인에, 메시지는 그 사람에게만 간다. **열린\n          쪽부터** 선다.\n\n          **메시지는 이 서버 안의 일이다**(2026-09-06) — 연합으로 나가는 통로가 없으므로\n          남의 서버 사람에게는 그 줄이 서지 않는다. 프로필 카드가 이미 같은 규칙을 쓴다.\n        }}\n        {{^own}}\n        <li><a class=\"action mention\" href=\"/-/compose?mention={{author.handle}}&amp;return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-mention}}</span><span class=\"nav-label\">{{t.post.mention}}</span></a></li>\n        {{^author.acct}}\n        <li><a class=\"action message\" href=\"/-/compose?to={{author.handle}}&amp;return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-envelope}}</span><span class=\"nav-label\">{{t.post.message}}</span></a></li>\n        {{/author.acct}}\n        {{/own}}\n        {{!\n          **`고정하기`는 자기 글만이다** (M29). 남의 글을 내 프로필 맨 위에 놓는 일은\n          리포스트가 하고, 고정은 <i>내 프로필이 무엇을 먼저 말하는가</i>다.\n\n          **공개된 글만 선다** — 대상이 보는 사람마다 갈리면 *이것부터 읽으라*가 뜻을 잃는다.\n          그 판정은 코어가 지므로 여기서는 단추만 두고, 안 되는 글은 오류 문구가 말한다.\n\n          **토글이다**(하멜이 더한 훅) — 카멜에서는 `data-form` 링크인데 그쪽에는 그 자리의\n          토글이 없어서였고, **하멜에는 그 하한이 없다.**\n        }}\n        {{#own}}\n        <li><a class=\"action pin\" data-toggle=\"pin\" rel=\"nofollow\"\n               data-api=\"{{api}}\" data-verb=\"{{#pinned}}unpin{{/pinned}}{{^pinned}}pin{{/pinned}}\"\n               data-state=\"{{#pinned}}on{{/pinned}}{{^pinned}}off{{/pinned}}\"\n               data-on=\"{{t.post.unpin}}\" data-off=\"{{t.post.pin}}\"\n               href=\"{{permalink}}/-/{{#pinned}}unpin{{/pinned}}{{^pinned}}pin{{/pinned}}?csrf={{csrf}}&return={{path_encoded}}\"\n               ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pin}}</span><span class=\"nav-label\" data-label>{{#pinned}}{{t.post.unpin}}{{/pinned}}{{^pinned}}{{t.post.pin}}{{/pinned}}</span></a></li>\n        {{/own}}\n        {{!\n          **`추천하기`는 남의 글에도 선다**(2026-09-05 · 사용자 컬렉션) — `own` 밖인 것이 그\n          뜻이다. 고정은 *내 글 가운데 무엇을 먼저 말하는가*이고, 추천은 <b>무엇을 남에게\n          보여 주는가</b>라 대상이 넓다.\n\n          **북마크와 갈리는 자리는 하나다**: 그쪽 목록은 나만 보고 이쪽은 **내 프로필에 선다.**\n\n          **고정 다음인 것은 자리의 무게다** — 프로필 맨 위는 하나이고 추천 목록은 여럿이다.\n        }}\n        <li><a class=\"action recommend\" data-toggle=\"recommend\" rel=\"nofollow\"\n               data-api=\"{{api}}\" data-verb=\"{{#recommended}}unrecommend{{/recommended}}{{^recommended}}recommend{{/recommended}}\"\n               data-state=\"{{#recommended}}on{{/recommended}}{{^recommended}}off{{/recommended}}\"\n               data-on=\"{{t.post.recommend_undo}}\" data-off=\"{{t.post.recommend}}\"\n               href=\"{{permalink}}/-/{{#recommended}}unrecommend{{/recommended}}{{^recommended}}recommend{{/recommended}}?csrf={{csrf}}&return={{path_encoded}}\"\n               ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-gift}}</span><span class=\"nav-label\" data-label>{{#recommended}}{{t.post.recommend_undo}}{{/recommended}}{{^recommended}}{{t.post.recommend}}{{/recommended}}</span></a></li>\n        {{!\n          **가리기는 남의 글에 손대는 일이다** (M17). 그래서 `own` 밖에 서고 <b>관리자에게만</b>\n          보인다 — 여는 조건이 다른 항목들과 갈리는 유일한 자리다.\n\n          **확인 화면을 지난다.** 되돌릴 수 있게 되었어도 남의 글이라는 사실은 그대로다(03d).\n        }}\n        {{#site_admin}}\n        {{^own}}\n        {{#is_blinded}}\n        <li><a class=\"action unblind\" href=\"{{permalink}}/-/blind?return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-shield-check}}</span><span class=\"nav-label\">{{t.blind.unblind}}</span></a></li>\n        {{/is_blinded}}\n        {{^is_blinded}}\n        <li><a class=\"action blind\" href=\"{{permalink}}/-/blind?return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-shield-check}}</span><span class=\"nav-label\">{{t.blind.blind}}</span></a></li>\n        {{/is_blinded}}\n        {{/own}}\n        {{/site_admin}}\n        {{!\n          **`공개로 넓히기`는 나만 보는 글에만 선다** (M12). 넓히는 방향으로만 열리므로\n          (좁히는 길이 없다) 지우기 바로 앞이 그 자리다 — <b>되돌릴 수 없는 것끼리</b> 뒤에\n          모이고, 그중에서도 글을 잃는 쪽이 맨 끝이다.\n        }}\n        {{#own}}\n        {{#visibility_is.private}}\n        <li><a class=\"action widen\" href=\"{{permalink}}/-/widen?return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-expand}}</span><span class=\"nav-label\">{{t.action.widen}}</span></a></li>\n        {{/visibility_is.private}}\n        {{/own}}\n        {{!\n          **줄 하나가 다시 갈래를 가른다** — 아래는 <b>이 사람과의 관계를 바꾸는 일</b>이다\n          (2026-09-08 요구).\n        }}\n        <li class=\"rule\" role=\"separator\"></li>\n        {{!\n          **`팔로우하기`가 그 갈래의 첫 줄이다**(2026-09-08 요구 — ~~인용 앞~~에서 옮겼다).\n\n          **말을 거는 일과 관계를 바꾸는 일이 다르다.** 멘션·메시지는 <i>지금 한 번</i>이고\n          팔로우·뮤트·차단은 <b>앞으로 무엇이 보이는가</b>를 바꾼다 — 셋이 한 갈래로 모이면서\n          줄의 뜻이 *무거운 것*에서 *관계*로 옮겨 갔다.\n\n          **상태는 상자를 펼칠 때 알아낸다**(`data-relations`). 처음 서는 순간에는 `off`이고,\n          코어가 멱등이라 관계를 못 물어도 눌러서 옳게 동작한다.\n\n          **자기 글에는 서지 않는다** — 자기를 팔로우하는 자리가 없다.\n        }}\n        {{^own}}\n        <li><a class=\"action follow\" data-toggle=\"follow\" rel=\"nofollow\"\n               data-api=\"/api/v1/accounts/{{author.id}}\" data-verb=\"follow\" data-state=\"off\"\n               data-on=\"{{t.post.unfollow}}\" data-off=\"{{t.post.follow}}\"\n               href=\"/@{{author.handle}}/-/follow?csrf={{csrf}}&amp;return={{path_encoded}}\"\n               ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-person}}</span><span class=\"nav-label\" data-label>{{t.post.follow}}</span></a></li>\n        {{/own}}\n        {{!\n          **`뮤트하기`와 `차단하기`가 사람 쪽의 끝이다.** 둘 다 *이 사람을 그만 보는 일*이고,\n          뮤트는 조용히 가리는 것이라 앞, 차단은 <b>양쪽 팔로우를 끊고 해제해도 돌아오지\n          않으므로</b> 뒤다 — 프로필 카드가 같은 차례를 쓴다.\n\n          **상태를 모른 채 세운다**(팔로우와 같은 판단). 뮤트한 사람의 글은 피드에서 이미\n          빠져 있으므로, 이 줄을 보는 자리에서는 대개 뮤트 전이다.\n\n          **차단은 확인 화면을 지난다** — 되돌릴 수 있어도 잃는 것이 있다.\n        }}\n        {{^own}}\n        <li><a class=\"action mute\" data-toggle=\"mute\" rel=\"nofollow\"\n               data-api=\"/api/v1/accounts/{{author.id}}\" data-verb=\"mute\" data-state=\"off\"\n               data-on=\"{{t.post.unmute}}\" data-off=\"{{t.post.mute}}\"\n               href=\"/@{{author.handle}}/-/mute?csrf={{csrf}}&amp;return={{path_encoded}}\"\n               ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-eye-off}}</span><span class=\"nav-label\" data-label>{{t.post.mute}}</span></a></li>\n        <li><a class=\"action block\" href=\"/@{{author.handle}}/-/block?return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-shield-check}}</span><span class=\"nav-label\" data-label>{{t.post.block}}</span></a></li>\n        {{/own}}\n        {{!\n          **`읽음으로 표시`는 메시지에만 선다**(2026-09-08 — 목록의 곁줄에서 옮겨 왔다).\n\n          이 글에 하는 일이므로 상자가 그 자리이고, <b>읽지 않은 것에만</b> 선다 — 이미 읽은\n          것에 서면 누를 이유가 없는 줄이 늘 하나 붙어 있다.\n\n          **폼이다.** 되돌릴 수 없는 쓰기라 링크로 두지 않는다(코어도 `POST`로만 받는다).\n        }}\n        {{#unread}}\n        <li class=\"action-form\"><form method=\"post\" action=\"/-/messages/{{id}}/read\">\n          <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n          <input type=\"hidden\" name=\"return\" value=\"{{path}}\">\n          <button type=\"submit\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-check}}</span><span class=\"nav-label\">{{t.action.mark_read}}</span></button>\n        </form></li>\n        {{/unread}}\n        {{!\n          **`지우기`가 맨 뒤다.** 되돌릴 수 없는 하나이므로 여는 손에서 가장 먼 자리에 둔다 —\n          상자 안에서 그것만 빨간 것과 같은 판단이다.\n        }}\n        {{#own}}\n        <li><a class=\"action delete\" href=\"{{permalink}}/-/delete?return={{path_encoded}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-trash}}</span><span class=\"nav-label\">{{t.action.delete}}</span></a></li>\n        {{/own}}\n      </ul>\n    </details>\n    {{/signed_in}}\n  </footer>\n  {{/deleted}}\n  {{/hidden}}\n</article>\n","iteration-revision":"{{!\n  이름표는 `revision.*`이다(03d `값에 붙는 이름표`) — `post.revision`은 <b>글이 몇 판인가</b>를\n  말하고 이쪽은 <b>그 판 자신</b>이라, 같은 키를 쓰면 목록과 헤더가 구별되지 않는다.\n}}\n<li class=\"revision\" data-current=\"{{current}}\" data-key=\"revision\" data-value=\"{{seq}}\">\n  {{!\n    **판 하나의 주소는 `-/`를 지나지 않는다**(2026-09-03 요구) —\n    ~~`…/-/revisions/{번호}`~~에서 줄었다. 포스트가 순수 리소스인 근거(24)가\n    그 아래의 판에도 걸린다.\n  }}\n  <a class=\"permalink\" href=\"{{post.permalink}}/{{seq}}\"\n     data-key=\"revision.seq\" data-value=\"{{seq}}\">{{seq_label}}</a>\n  {{#current}}<span class=\"mark\" data-key=\"revision.current\" data-value=\"true\">{{t.revision.in_use}}</span>{{/current}}\n  <time datetime=\"{{created_at}}\"{{#created_title}} title=\"{{.}}\"{{/created_title}} data-key=\"revision.created_at\" data-value=\"{{created_at}}\">{{created_display}}</time>\n  <div class=\"content\">{{{content_html}}}</div>\n\n  {{! **첨부 목록은 한 조각이다**(43) — 글과 같은 것을 쓴다. }}\n  {{> post-media}}\n</li>\n","login-providers":"{{!\n  수단을 고르는 자리 (05p · 2026-09-25에 조각으로 갈라섰다).\n\n  **화면 둘이 나눠 쓴다** — `body-login`(누구인가)과 `body-account-add`(한 사람 더).\n  <b>그리는 것이 같고 거는 판단이 다른 자리</b>라 화면은 둘이고 그림은 하나다: 마크업을\n  두 벌 두면 <b>한쪽만 고쳐진다</b>.\n\n  **자격 증명은 이 화면을 지나가지 않는다.** 여기서 묻는 것은 *어느 수단으로 들어올\n  것인가* 하나이고, 고르면 그 수단의 화면으로 나간다.\n\n  **수단이 다르면 계정도 다르다.** 한 계정에 신원 하나이므로 다른 수단을 고르면 다른\n  계정이다 — 적지 않으면 부계정이 생긴 것을 사고로 여긴다.\n\n  **주소는 서버가 지어 준 것을 그대로 쓴다.** 이스케이프된 채로 나가지만 브라우저가 속성\n  값의 문자 참조를 해석하므로 그대로 눌린다 — 삼중 중괄호를 쓸 이유가 없다.\n\n  **누르면 이 앱을 떠난다.** 인가는 코어의 화면에서 일어나므로 라우터가 가로채지 않는다\n  (`data-away`가 그 표시다) — 하멜의 어느 링크와도 다른 성질이라 마크업이 그것을 말한다.\n\n  **떠나는 동안 덮는다**(`data-signing` — 2026-09-16 요구). 누르고 나서 코어의 인가 화면이\n  설 때까지 <b>이 화면이 그대로 서 있고</b>, 그 몇 초가 <i>눌리지 않았다</i>로 읽혀 한 번 더\n  누르게 된다 — 그 두 번째 누름은 <b>진행 중이던 로그인을 버리고 새로 시작한다</b>\n  (`/-/site/login`은 부를 때마다 새로 짓는다).\n}}\n<p class=\"hint\">\n  {{{t.login.hint}}}\n</p>\n\n{{!\n  **수단마다 그 서비스의 표가 선다** (2026-09-14 요구).\n\n  **남의 표는 남의 모양으로 둔다.** 우리 아이콘은 윤곽선 한 벌이지만 로그인 수단은 <b>남의\n  서비스를 가리키는 것</b>이라, 우리 규약에 맞춰 다시 그리면 알아보지 못한다 — 알아보는\n  것이 이 그림의 전부다.\n\n  **줄이 아니라 단추다**(요구). 고르는 행위가 이 화면의 일이고, 목록의 한 줄은 <i>읽을\n  것</i>처럼 보인다.\n\n  **모르는 수단에는 그림이 없다.** 코어가 어댑터를 늘리면 이름만으로 서고, 그때 표를\n  더하는 자리가 여기다 — 빈 자리에 아무 그림이나 세우지 않는다.\n}}\n<ul class=\"login-providers\">\n  {{#providers}}\n  <li>\n    <a class=\"button provider is-medium\" href=\"{{href}}\" data-away data-signing=\"in\">\n      <span class=\"logo\" aria-hidden=\"true\">\n        {{#is.github}}{{> icon-github}}{{/is.github}}\n        {{#is.google}}{{> icon-google}}{{/is.google}}\n      </span>\n      <span class=\"label\">{{label}}</span>\n    </a>\n  </li>\n  {{/providers}}\n</ul>\n","modal-asset-groups":"{{!\n  **고른 것들의 그룹을 더하고 뺀다**\n  (<a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a> · 2026-09-17 요구).\n\n  **갈아 끼우기가 아니다.** 여럿을 골라 놓고 <i>여기에 이 그룹을 더한다</i>는 손과 <i>이\n  그룹으로 통일한다</i>는 손은 갈리는데, 앞엣것을 갈아 끼우기로 하려면 <b>고른 것들이 지금\n  무엇을 들고 있는지</b>를 사람이 모두 알아야 한다.\n\n  **축을 가른다**(2026-09-17 요구). ~~두 라벨에 함께 넣고 함께 뺐다~~ — *네 칸을 한 번에\n  맞히는 사람은 없다*가 그때의 근거였는데, <b>에셋이 라벨 둘을 갖는다는 것을 사람은 이미\n  알고 온다</b>: 축을 합치면 <i>읽기만 여는 일</i>을 여럿에 한 번에 할 길이 없어지고,\n  그 일이야말로 하나씩 하기 가장 번거롭다.\n\n  **빈 칸은 아무 일도 하지 않는다** — 갈아 끼우는 창이 아니므로 비워 둔 축은 그대로 남는다.\n\n  **같은 이름이 한 축의 양쪽에 오면 빼는 쪽이 이긴다** — 좁은 쪽이고, 사람이 마지막에 적은\n  뜻일 가능성이 높다.\n}}\n<section class=\"asset-groups\">\n  <p class=\"asset-groups-count\">{{count_label}}</p>\n\n  {{!\n    **묶음이 둘이고 칸이 넷이다.** 축마다 제목을 세우는 것은 <b>어느 축을 만지고 있는지</b>가\n    칸 이름만으로는 읽히지 않기 때문이다 — `더할 그룹`이 넷 중 어느 것인지 물어야 한다면\n    그 창은 이미 틀렸다.\n  }}\n  <fieldset class=\"asset-groups-axis\">\n    <legend>{{t.document.asset_groups_read}}</legend>\n\n    <div class=\"field\">\n      <label class=\"label\" for=\"asset-read-add\">{{t.pool.groups_add}}</label>\n      <div class=\"control\">\n        <input class=\"input\" id=\"asset-read-add\" type=\"text\" list=\"asset-group-names\"\n               data-pool-groups-field=\"read_add\" autocomplete=\"off\">\n      </div>\n    </div>\n\n    <div class=\"field\">\n      <label class=\"label\" for=\"asset-read-remove\">{{t.pool.groups_remove}}</label>\n      <div class=\"control\">\n        <input class=\"input\" id=\"asset-read-remove\" type=\"text\" list=\"asset-group-names\"\n               data-pool-groups-field=\"read_remove\" autocomplete=\"off\">\n      </div>\n    </div>\n  </fieldset>\n\n  <fieldset class=\"asset-groups-axis\">\n    <legend>{{t.document.asset_groups_write}}</legend>\n\n    <div class=\"field\">\n      <label class=\"label\" for=\"asset-write-add\">{{t.pool.groups_add}}</label>\n      <div class=\"control\">\n        <input class=\"input\" id=\"asset-write-add\" type=\"text\" list=\"asset-group-names\"\n               data-pool-groups-field=\"write_add\" autocomplete=\"off\">\n      </div>\n    </div>\n\n    <div class=\"field\">\n      <label class=\"label\" for=\"asset-write-remove\">{{t.pool.groups_remove}}</label>\n      <div class=\"control\">\n        <input class=\"input\" id=\"asset-write-remove\" type=\"text\" list=\"asset-group-names\"\n               data-pool-groups-field=\"write_remove\" autocomplete=\"off\">\n      </div>\n    </div>\n  </fieldset>\n\n  <p class=\"help\">{{t.pool.groups_adjust_hint}}</p>\n\n  <datalist id=\"asset-group-names\">\n    {{#names}}<option value=\"{{.}}\"></option>{{/names}}\n  </datalist>\n\n  <p class=\"asset-groups-deeds\">\n    <button class=\"button is-primary\" type=\"button\" data-pool-groups-act=\"save\">{{t.pool.apply}}</button>\n    <button class=\"button\" type=\"button\" data-pool-groups-act=\"cancel\">{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-asset-one":"{{!\n  **그림 하나를 다루는 창 — 에셋 풀에서 뜬다** (2026-09-15 요구).\n\n  탐색기에서 누르는 일은 <i>고르는 것</i>이고 여기서는 <i>다루는 것</i>이다. 같은 격자를\n  쓰면서도 이 창이 풀에서만 서는 까닭이 그것이다.\n\n  **속은 `/:이름` 화면과 한 조각이다**(2026-09-16 요구) — 같은 일에 같은 그림.\n}}\n{{> asset-one-panel}}\n","modal-assets":"{{!\n  **에셋 풀 모달 — 문서가 고를 그림** (2026-09-15 요구).\n\n  **풀 화면과 같은 모양이다.** 머리에 찾는 칸이 서고 곁에 태그가 선다 — 같은 것을 두 자리에서\n  다르게 다루면 <b>같은 일을 두 번 배워야 한다.</b>\n\n  **태그가 무엇을 보일지 정한다.** 이 문서의 실효 태그에서 시작하고, 곁칸에서 더 좁히거나\n  갈아 끼운다 — 비어 있으면 전부다.\n\n  **고르면 곧 심긴다.** 부른 블록이 이미 정해져 있으므로 한 번 더 누를 일이 없다.\n}}\n<form class=\"asset-find\" data-asset-find role=\"search\">\n  <input class=\"input\" type=\"search\" name=\"q\" value=\"{{query}}\"\n         placeholder=\"{{t.document.asset_find}}\" autocomplete=\"off\">\n</form>\n\n<div class=\"asset-browser\" data-asset-browser>\n  <aside class=\"asset-side\" data-asset-side>\n    {{#picked.length}}\n    <ul class=\"asset-picked\">\n      {{#picked}}\n      <li><button class=\"tag is-primary\" type=\"button\" data-asset-drop=\"{{.}}\">{{.}} ×</button></li>\n      {{/picked}}\n    </ul>\n    {{/picked.length}}\n\n    <ul class=\"asset-tags\">\n      {{#tags}}\n      <li class=\"asset-tag\">\n        <button class=\"asset-tag-add\" type=\"button\" data-asset-add=\"{{name}}\"\n                title=\"{{t.document.asset_tag_add}}\">+</button>\n        <button class=\"asset-tag-only\" type=\"button\" data-asset-only=\"{{name}}\"\n                title=\"{{t.document.asset_tag_only}}\">{{name}}</button>\n        <span class=\"asset-tag-count\">{{count}}</span>\n      </li>\n      {{/tags}}\n    </ul>\n\n    {{! **없으면 그냥 없다**(2026-09-17 요구) — 빈 칸이 이미 *좁힐 것이 없다*를 말한다. }}\n  </aside>\n\n  <div class=\"asset-main\">\n    {{> asset-gallery}}\n\n    {{!\n      **풀 화면과 같은 번호로 넘긴다** (2026-09-16 요구).\n\n      ~~`더 보기`로 이어 붙였다~~ — *고를 때까지 넘겨 보는 자리라 끝이 값이 아니다*가 그\n      근거였는데, <b>같은 것을 두 자리에서 다르게 다루면 같은 일을 두 번 배워야 한다</b>는\n      이 모달의 첫 줄과 어긋났다. 어디쯤인지와 얼마나 남았는지는 <b>고르는 자리에서도</b>\n      읽을 값이다.\n\n      **주소를 갈지 않고 속만 간다**(`inplace`) — 모달이 선 채로 넘어간다.\n    }}\n    {{> pager-numbers}}\n  </div>\n</div>\n","modal-backlinks":"{{!\n  참조 목록 — **들어오는 것과 나가는 것** (2026-09-19 요구로 탭이 되었다).\n\n  **모달과 페이지가 이 한 조각을 나눠 쓴다.** 제목 옆 곁문은 이것을 모달로 열고\n  (`data-form`), 주소로 곧장 온 사람에게는 같은 조각이 페이지로 선다 — 폼 여섯이 이미\n  그 규약이다.\n\n  **두 방향은 다른 물음이다.** 들어오는 것은 <i>이것을 지우면 무엇이 깨지나</i>이고\n  나가는 것은 <i>이것이 무엇에 기대고 있나</i>다 — 세로로 이어 두면 <b>둘째 목록이 첫째의\n  꼬리로 읽힌다.</b>\n\n  **라디오 탭이다**(`group-tabs`의 그 기제). 모달 안이라 주소로 가를 수 없고, 스크립트로\n  여닫으면 <b>그것이 죽었을 때 한쪽밖에 못 본다</b> — 라디오와 CSS면 둘 다 풀린다.\n\n  **권한과 상관없이 정직하게 산출된다**(31 확정 18). 비공개 문서가 이것을 가리키면 그\n  경로가 여기 뜬다 — 가리키는 관계는 위키의 뼈대이고, 권한으로 가리면 <i>왜 여기 아무것도\n  없는가</i>를 아무도 답할 수 없다. **누르면 403이다.**\n}}\n<div class=\"group-tabs link-tabs\">\n  <input type=\"radio\" name=\"backlink-tab\" id=\"backlink-tab-in\" checked>\n  <label for=\"backlink-tab-in\">{{t.backlinks.incoming}}</label>\n\n  <input type=\"radio\" name=\"backlink-tab\" id=\"backlink-tab-out\">\n  <label for=\"backlink-tab-out\">{{t.backlinks.outgoing}}</label>\n\n  {{! ── 들어오는 참조 ── }}\n  <div class=\"group-tab-body\">\n    {{#backlinks.length}}\n    <ul class=\"backlinks\">\n      {{#backlinks}}\n      {{!\n        **거쳐 온 이름을 그 줄에 적는다** (2026-09-11 요구). 표지를 지나 들어온 링크는 그\n        소스에 <b>지금 경로가 아닌 이름</b>이 적혀 있으므로, 적지 않으면 열어 보고도 못\n        찾는다 — 옮기기가 남긴 옛 이름이거나 사람이 세운 넘겨주기다.\n\n        **에셋 문서도 이 목록에 선다** (2026-09-19 요구) — 에셋은 제 본문을 가지고 그\n        본문이 문서를 가리킬 수 있다. <b>경로가 그 사실을 이미 말하므로</b>(`:표지`) 낱말을\n        더 적지 않고, 갈래만 클래스로 남긴다.\n      }}\n      <li{{#asset}} class=\"is-asset\"{{/asset}}><a href=\"{{href}}\">{{title}}</a><span class=\"backlink-path\">{{path}}</span\n         >{{#via}}<span class=\"backlink-via\">{{t.backlinks.via}} <a href=\"{{via_href}}\">{{.}}</a></span>{{/via}}</li>\n      {{/backlinks}}\n    </ul>\n    {{/backlinks.length}}\n    {{!\n      **빈 자리의 말은 화면이 넘긴다** — 같은 조각이 문서와 에셋 둘에 서므로\n      <b>*이 문서를*이라 박아 두면 한쪽에서 거짓말이 된다.</b>\n    }}\n    {{^backlinks.length}}\n    <p class=\"hint\">{{empty}}</p>\n    {{/backlinks.length}}\n  </div>\n\n  {{! ── 나가는 참조 ── }}\n  <div class=\"group-tab-body\">\n    {{#outgoing.length}}\n    {{!\n      **아직 없는 곳도 이 목록에 선다** — 05c의 *먼저 부르고 나중에 채운다*가 그 줄의 뜻이다.\n      빼면 <i>나가는 참조</i>라는 이름이 반쪽만 말한다. 누르면 <b>만들 수 있는 빈 자리</b>로\n      간다.\n    }}\n    <ul class=\"backlinks\">\n      {{#outgoing}}\n      <li class=\"{{#asset}}is-asset {{/asset}}{{#missing}}is-missing{{/missing}}\"><a href=\"{{href}}\">{{title}}</a><span class=\"backlink-path\">{{path}}</span\n         >{{#missing}}<span class=\"backlink-missing\">{{t.backlinks.not_yet}}</span>{{/missing}}</li>\n      {{/outgoing}}\n    </ul>\n    {{/outgoing.length}}\n    {{^outgoing.length}}\n    <p class=\"hint\">{{outgoing_empty}}</p>\n    {{/outgoing.length}}\n  </div>\n</div>\n","modal-blind":"{{!\n  가리기·풀기 확인 (M17).\n\n  **되돌릴 수 있게 되었어도 확인 화면을 지난다**(03d). 남의 글에 손대는 일이라는 사실은\n  그대로이고, 그 판단이 관리자라고 달라지지 않는다.\n\n  **가릴 때는 사유를 받고, 풀 때는 받지 않는다.** 사유는 *왜 가렸는가*이고 푸는 일에는\n  그 물음이 없다 — 자취도 함께 지워진다(M17의 물음 `다`).\n}}\n<div class=\"danger\">\n  {{#post.is_blinded}}\n  <p class=\"hint\">{{t.blind.unblind_warn}}</p>\n  {{/post.is_blinded}}\n  {{^post.is_blinded}}\n  <p class=\"hint\">{{t.blind.blind_warn}}</p>\n  {{/post.is_blinded}}\n\n  {{#post}}{{> body-quoted}}{{/post}}\n\n  <form method=\"post\" action=\"{{post.permalink}}/-/blind\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n\n    {{#post.is_blinded}}\n    <input type=\"hidden\" name=\"undo\" value=\"1\">\n    {{!\n      **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n      줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n      **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n      이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n    <div class=\"document-actions\">\n      <button class=\"button\" type=\"submit\">{{t.blind.unblind}}</button>\n      {{#on_page}}<a class=\"button\" href=\"{{post.permalink}}\">{{t.back.cancel}}</a>{{/on_page}}\n    </div>\n    {{/post.is_blinded}}\n\n    {{^post.is_blinded}}\n    <div class=\"field\">\n      <label class=\"label\" for=\"blind-reason\">{{t.blind.reason}}</label>\n      <div class=\"control\">\n        <input class=\"input\" id=\"blind-reason\" type=\"text\" name=\"reason\"\n               value=\"{{post.blind_reason}}\" maxlength=\"500\"\n               placeholder=\"{{t.blind.reason_hint}}\" autocomplete=\"off\">\n      </div>\n    </div>\n\n    {{!\n      **남기는 것과 보이는 것을 갈라야 둘 다 성립한다.** 사유를 언제나 공개로 두면\n      *적어 두면 새어 나간다*가 되어 아무것도 적지 않게 되고, 그러면 되물을 근거가 사라진다.\n\n      **쓴 사람에게는 어느 쪽이든 보인다** — 이의를 제기하려면 무엇 때문인지 알아야 한다.\n      감추는 대상은 남이다.\n    }}\n    <label class=\"choice checkbox\">\n      <input type=\"checkbox\" name=\"reason_public\" value=\"1\"> {{t.blind.reason_public}}\n    </label>\n\n    <div class=\"document-actions\">\n      <button class=\"button is-danger\" type=\"submit\">{{t.blind.blind}}</button>\n      {{#on_page}}<a class=\"button\" href=\"{{post.permalink}}\">{{t.back.cancel}}</a>{{/on_page}}\n    </div>\n    {{/post.is_blinded}}\n  </form>\n</div>\n","modal-block":"{{!\n  차단 확인. **팔로우·뮤트와 달리 토글 링크가 아니다** — 차단은 양방향 가시성을 뒤집고\n  팔로우를 끊으며, 해제해도 팔로우는 복구되지 않는다. 되돌릴 수 없는 조작은 지우기와 같은\n  모양을 따른다(03d `동작과 이동`).\n}}\n<div class=\"danger\">\n  <p class=\"who\">{{> iteration-person}}</p>\n\n  {{#blocking}}\n  <p class=\"hint\">\n    {{{t.block.unblock_warn}}}\n  </p>\n  {{/blocking}}\n\n  {{^blocking}}\n  <p class=\"hint\">\n    {{{t.block.warn}}}\n  </p>\n  {{/blocking}}\n\n  {{!\n    **`data-api`는 하멜이 더한 훅이다** — 카멜의 `action`은 아이디를 손잡이로 부르는데\n    코어는 계정 id를 쓰고, 하멜은 프록시이므로 브라우저가 코어의 주소를 그대로 부른다.\n    화면을 그릴 때 이미 알고 있던 id를 여기 함께 둔다(왕복을 하나 아낀다).\n  }}\n  <form method=\"post\" action=\"/@{{handle}}/-/{{blockAction}}\"\n        data-api=\"/api/v1/accounts/{{id}}/{{blockAction}}\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n    {{!\n      **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n      줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n      **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n      이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n    <div class=\"document-actions\">\n      <button class=\"button is-danger\" type=\"submit\">{{blockLabel}}</button>\n      {{#on_page}}<a class=\"button\" href=\"/@{{handle}}\">{{t.back.cancel}}</a>{{/on_page}}\n    </div>\n  </form>\n</div>\n","modal-bot-retire":"{{!\n  **봇 걷기 — 확인 화면을 지난다** (2026-09-08 요구).\n\n  **무엇이 지워지는지 적는다.** 토큰이 끊기고 봇 표시가 걷혀 그 봇은 말을 멈춘다 —\n  <b>계정과 글은 남는다</b>: 연합으로 나간 글에는 남의 서버에 사본이 있고, 지우는 일은\n  계정을 지우는 일과 같은 무게다.\n}}\n<p class=\"bot-who\">{{> iteration-person}}</p>\n<p class=\"warning notification is-warning is-light\">{{t.bot.retire_note}}</p>\n\n<form method=\"post\" action=\"/-/settings/apps/{{id}}/retire\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n  {{!\n    **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n    줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n    **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n    이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n  <div class=\"document-actions\">\n    <button class=\"button is-danger\" type=\"submit\">{{t.bot.retire}}</button>\n    {{#on_page}}<a class=\"button\" href=\"/-/settings/apps\">{{t.back.cancel}}</a>{{/on_page}}\n  </div>\n</form>\n","modal-bot":"{{!\n  **봇 설정 — 설치와 같은 화면이다** (2026-09-09 요구).\n\n  ~~설치 모달과 설정 모달이 따로 있었다~~. 담기는 것이 거의 같은데 자리가 둘이면 <b>어느\n  쪽에서 무엇을 하는지</b>를 매번 확인해야 한다 — **아이디 칸 하나가 갈린다**: 설치할 때는\n  적고, 그 뒤로는 읽기만 한다(연합 actor URI에 박히는 영구 계약이라 고칠 수 없다).\n\n  **여기 있는 것은 동작에 관한 것뿐이다.** 이름·소개·얼굴은 프로필이고 그것을 고치는 자리는\n  <i>내 프로필과 같은 화면</i>이다(카드의 `프로필 수정`).\n}}\n{{#account}}<p class=\"bot-who\">{{> iteration-person}}</p>{{/account}}\n\n{{#installed}}\n{{!\n  **아이디는 고칠 수 없다** — 주소이자 연합의 이름이므로 한 번 정하면 영구 계약이다.\n}}\n<p class=\"field\">\n  <label for=\"bot-handle\">{{t.bot.handle}}</label>\n  <input id=\"bot-handle\" value=\"{{handle}}\" readonly>\n</p>\n{{/installed}}\n\n{{^installed}}\n{{!\n  **설치는 동작을 묻는다**(2026-09-09 요구). 아이디와 <b>이 봇에게 열어 줄 권한</b>이 그것이다 —\n  이름·소개·얼굴은 기본값이 서고 필요할 때 `프로필 수정`에서 고친다: 들이기 전에 소개문을\n  쓰라고 하면 <b>한 번도 쓰지 않을 봇의 소개문</b>을 먼저 쓰게 된다.\n\n  **한 번에 끝난다.** 누르면 봇이 서고 <b>클라이언트까지 함께 나온다</b> — 그 자리에서 비밀을\n  받아 봇 프로그램에 넣으면 되고, 모달을 두 번 열 일이 없다.\n\n  **적는 동안 아이디를 확인한다**(`data-handle-check`) — 보내고 나서 *이미 쓰인다*를 만나면\n  사람은 이미 다 적은 뒤다.\n\n  **아이디만 뒤에 고칠 수 없다** — 주소이자 연합의 이름이라 한 번 정하면 영구 계약이다.\n}}\n<form class=\"compose\" method=\"post\" action=\"/-/settings/apps\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  <label for=\"bot-handle\">{{t.bot.handle}}</label>\n  <input id=\"bot-handle\" name=\"handle\" required autocomplete=\"off\"\n         data-handle-check placeholder=\"echo\">\n  <p class=\"hint help\" data-handle-note>{{t.bot.handle_hint}}</p>\n\n  {{!\n    **봇이 자기를 말하는 파일**(2026-09-09 요구 · `manifest.json`). 이름·소개·얼굴·권한을 봇\n    서버가 선언해 두면 <b>설치는 주소 하나</b>로 끝난다 — 봇을 짓는 사람이 아는 것을 설치하는\n    사람이 베껴 적지 않는다.\n\n    **적으면 곧 읽는다**(`data-manifest`) — 누르는 단추를 두면 누르지 않은 채 설치를 눌러\n    <b>미리 보지 못한 것</b>을 들이게 된다.\n\n    **선언은 요청이지 허가가 아니다.** 여기 서는 이름과 얼굴과 권한은 <i>봇이 청하는 것</i>이고,\n    사람이 보고 `들이기`를 누르는 것까지가 설치다.\n  }}\n  <label for=\"bot-manifest\">{{t.bot.manifest}}</label>\n  <input id=\"bot-manifest\" name=\"manifest_url\" type=\"url\" autocomplete=\"off\"\n         data-manifest placeholder=\"https://example.com/manifest.json\">\n  <p class=\"manifest-seen\">\n    <img class=\"avatar\" data-manifest-avatar alt=\"\" hidden>\n    <span class=\"hint help\" data-manifest-note>{{t.bot.manifest_hint}}</span>\n  </p>\n\n  {{!\n    **권한은 선언이 채운다** — 읽고 나면 잠근다. ~~손으로 적었다~~: 무엇이 필요한지는 봇을\n    짓는 사람이 알고, 청한 것 가운데 <b>몇 개를 꺼서 들이면</b> 도는 것처럼 보이다가 어느\n    자리에서 멈추는 봇이 된다 — 사람이 정하는 것은 <i>들일지 말지</i>다.\n\n    **선언이 없으면 열려 있다** — 그 길이 막히지는 않는다. 비워 두면 코어의 기본 스코프다.\n  }}\n  <label for=\"bot-scopes\">{{t.bot.scopes}}</label>\n  <input id=\"bot-scopes\" name=\"scopes\" placeholder=\"read:messages write:posts\" autocomplete=\"off\"\n         data-manifest-scopes>\n  <p class=\"hint help\">{{t.bot.scopes_hint}}</p>\n\n  {{!\n    **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n    줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n    **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n    이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n  <div class=\"document-actions\">\n    <button class=\"button is-primary\" type=\"submit\">{{t.bot.create}}</button>\n    {{#on_page}}<a class=\"button\" href=\"/-/settings/apps\">{{t.back.cancel}}</a>{{/on_page}}\n  </div>\n</form>\n{{/installed}}\n\n{{#installed}}\n{{!\n  **새 판이 있으면 승인을 묻는다**(2026-09-09 요구). 봇이 자라면 청하는 권한이 달라질 수\n  있는데, 그것이 <b>조용히 넓어지면</b> 사람이 허락한 적 없는 것을 봇이 갖는다 — 코어는\n  알려 주기만 하고 넓히는 것은 사람이 누른 뒤다.\n\n  **켜고 끄는 자리가 아니다.** 봇은 자기가 청한 것을 다 가진 채로만 돌므로 그 가운데 몇\n  개를 꺼서 승인하면 <b>도는 것처럼 보이다가 어느 자리에서 멈추는 봇</b>이 된다 — 여기서\n  묻는 것은 <i>이 판을 들일지 말지</i> 하나다.\n}}\n{{#manifest.update_available}}\n<div class=\"manifest-update notification is-info is-light\">\n  <p><b>{{t.bot.new_version}}</b> {{manifest.installed_version}} → {{manifest.manifest.version}}</p>\n  {{#manifest.manifest.summary}}<p>{{.}}</p>{{/manifest.manifest.summary}}\n  <p class=\"hint\">{{t.bot.new_scopes}} <code>{{manifest.scopes}}</code></p>\n\n  <form method=\"post\" action=\"/-/settings/apps/{{id}}/manifest\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <input type=\"hidden\" name=\"return\" value=\"/-/settings/apps/{{id}}\">\n    <div class=\"document-actions\">\n      <button class=\"button is-primary\" type=\"submit\">{{t.bot.bless}}</button>\n      {{#on_page}}<a class=\"button\" href=\"/-/settings/apps\">{{t.back.cancel}}</a>{{/on_page}}\n    </div>\n  </form>\n</div>\n{{/manifest.update_available}}\n\n{{#issued}}\n{{!\n  **방금 낸 것** — 비밀이 든 유일한 순간이다. 코어는 한 번 주고 해시만 남기므로 다시 물을 수\n  없고, 이 모달을 닫으면 사라진다.\n}}\n<div class=\"issued\">\n  <p class=\"warning notification is-warning is-light\">{{t.bot.secret_once}}</p>\n  {{#client_id}}\n  <p><span class=\"label\">{{t.bot.client_id}}</span> <code data-copy=\"{{.}}\">{{.}}</code></p>\n  {{/client_id}}\n  {{#client_secret}}\n  <p><span class=\"label\">{{t.bot.client_secret}}</span> <code data-copy=\"{{.}}\">{{.}}</code></p>\n  {{/client_secret}}\n  {{!\n    **토큰도 그 자리에서 복사한다**(2026-09-09 요구) — 클라이언트만 주면 사람은 그것으로\n    토큰을 받는 왕복을 손으로 한 번 더 해야 한다.\n  }}\n  {{#token}}\n  <p><span class=\"label\">{{t.bot.token}}</span> <code data-copy=\"{{.}}\">{{.}}</code></p>\n  {{/token}}\n</div>\n{{/issued}}\n\n{{!\n  **스코프는 손으로 적는다** — 무엇이 필요한지는 그 봇을 짓는 사람이 알고, 목록으로 세우면\n  <b>코어가 아는 것과 갈리는 표</b>가 하나 더 생긴다.\n}}\n<form method=\"post\" action=\"/-/settings/apps/{{id}}/clients\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"return\" value=\"/-/settings/apps/{{id}}\">\n\n  <label for=\"bot-scopes\">{{t.bot.scopes}}</label>\n  <input id=\"bot-scopes\" name=\"scopes\" placeholder=\"read:messages write:posts\" autocomplete=\"off\">\n\n  <button class=\"button\" type=\"submit\">{{t.bot.issue}}</button>\n</form>\n\n{{!\n  **토큰은 다시 낼 수 있다**(2026-09-09 요구). `client_credentials`가 회전을 주지 않으므로\n  손에 쥔 것이 만료되면 <b>새로 내는 것이 유일한 길</b>이다 — 클라이언트 비밀은 다시 물을 수\n  없지만, 임자는 이미 그 봇을 만질 수 있는 사람이라 코어가 그 이름으로 내준다.\n\n  **어느 클라이언트의 이름으로 낼지는 표에서 고른다** — 아래 줄의 `다시 내기`가 그 값을\n  들고 있다.\n}}\n{{!\n  **나가 있는 토큰이 표로 선다**(권한 · 타이머 · 관리). 줄마다 <b>무엇을 할 수 있고 ·\n  언제까지이며 · 어떻게 끊는가</b>가 한 눈에 들어와야 한다.\n}}\n<h3>{{t.bot.tokens}}</h3>\n{{^tokens.length}}<p class=\"empty\">{{t.bot.no_tokens}}</p>{{/tokens.length}}\n{{#tokens.length}}\n<table class=\"tokens\">\n  <thead>\n    <tr>\n      <th>{{t.bot.column_scopes}}</th>\n      <th>{{t.bot.column_expires}}</th>\n      <th>{{t.bot.column_manage}}</th>\n    </tr>\n  </thead>\n  <tbody>\n    {{#tokens}}\n    <tr>\n      <td><code>{{scopes}}</code></td>\n      <td><time>{{expires}}</time></td>\n      <td>\n        <form method=\"post\" action=\"/-/settings/apps/{{botId}}/tokens\">\n          <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n          <input type=\"hidden\" name=\"return\" value=\"/-/settings/apps/{{botId}}\">\n          <input type=\"hidden\" name=\"client_id\" value=\"{{clientId}}\">\n          <input type=\"hidden\" name=\"scopes\" value=\"{{scopes}}\">\n          <button class=\"button is-small\" type=\"submit\">{{t.bot.mint}}</button>\n        </form>\n        <form method=\"post\" action=\"/-/settings/apps/{{botId}}/tokens/{{id}}/revoke\">\n          <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n          <input type=\"hidden\" name=\"return\" value=\"/-/settings/apps/{{botId}}\">\n          <button class=\"button is-small\" type=\"submit\">{{t.bot.cut}}</button>\n        </form>\n      </td>\n    </tr>\n    {{/tokens}}\n  </tbody>\n</table>\n{{/tokens.length}}\n{{/installed}}\n","modal-bulk-groups":"{{!\n  **고른 계정들에 그룹을 지정한다** (39 확정 4). 배정은 더하기가 아니라 갈아 끼우기다(37) —\n  적은 것이 곧 그 사람들의 그룹 전부가 된다. 그 사실을 칸 아래에 적는다.\n}}\n<section class=\"group-move\">\n  <p>{{t.table.selected_count}}: <b>{{count}}</b></p>\n  <div class=\"field\">\n    <label class=\"label\" for=\"bulk-groups\">{{t.groups.name}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"bulk-groups\" type=\"text\" list=\"bulk-group-names\" data-bulk-groups-value autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.specials.assign_hint}}</p>\n  </div>\n  <datalist id=\"bulk-group-names\">{{#names}}<option value=\"{{.}}\"></option>{{/names}}</datalist>\n  <p class=\"group-deeds\">\n    <button class=\"button is-primary\" type=\"button\" data-bulk-groups-act=\"save\">{{t.groups.save}}</button>\n    <button class=\"button\" type=\"button\" data-bulk-groups-act=\"cancel\">{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-card":"{{!\n  프로필 카드 — **모달과 프로필 화면 상단이 같은 것을 쓴다**(05e 요구).\n\n  세 켜다: 헤더(사용자 배경 위에 초상화, 그 아래 반투명 바에 이름과 아이디) ·\n  본문(소개와 커스텀 필드) · **잇는 것들**(셈과 프로필 액션 — 2026-08-24 요구로 ~~풋터~~에서\n  이름이 바뀌었다). 높이·투명도는 전부 스타일시트의 몫이라 여기에는 자리만 있다.\n\n  **~~사용자 소개와 커스텀 필드는 아직 없다~~ 섰다**(M11 프로필 확장).\n}}\n<div class=\"card\">\n  <div class=\"card-header\">\n    {{#account.header_url}}\n    <img class=\"header\" src=\"{{.}}\" alt=\"\">\n    {{/account.header_url}}\n\n    {{!\n      **얼굴이 없으면 사람 그림이 선다** (2026-09-11 요구 — 계정 초상화 폴백).\n\n      ~~자리째 비었다~~ — 배경은 없어도 상자가 지는데(`.card-header`) 초상화는 사라져서\n      <b>이름만 아래에 붙은 띠</b>가 되었다. 배경의 폴백이 이미 있으므로 그 짝을 맞춘다.\n    }}\n    {{#account.avatar_url}}\n    <img class=\"avatar large\" src=\"{{.}}\" alt=\"\" width=\"96\" height=\"96\">\n    {{/account.avatar_url}}\n    {{^account.avatar_url}}\n    <span class=\"avatar large avatar-fallback\" aria-hidden=\"true\">{{> icon-person}}</span>\n    {{/account.avatar_url}}\n\n    {{!\n      **기본 정보는 헤더 하단에 붙는다** — 여백 없는 반투명 바탕 위다(05e 요구).\n      배경 이미지가 없는 계정에서도 같은 자리에 서야 하므로 바탕은 이 요소가 진다.\n    }}\n    <div class=\"identity\">\n      {{!\n        **이름이 곧 프로필로 가는 길이다**(05e 요구). 카드 아래에 `프로필 보기`를 따로\n        두었다가 걷어냈다 — 같은 곳으로 가는 링크가 한 조각에 둘이면, 둘이 다른 곳으로\n        가는 줄 알고 읽게 된다.\n      }}\n      {{!\n        **그룹 뱃지는 이름 앞에 선다**\n        (<a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a> 확정 7 · 요구).\n\n        <b>이름 앞이라야</b> *누구인가*를 읽기 전에 <b>어느 그룹의 사람인가</b>가 먼저\n        읽힌다. 값은 코어가 내고 자리는 여기가 정한다.\n\n        **관리자 여부와 다르다** — 그쪽은 등급이라 드러나면 표적이 되지만 그룹은 <b>그룹</b>\n        이고, 같은 서버를 쓰는 사람들 사이에서 숨길 값이 아니다. 그래서 <b>그룹 이름에\n        비밀을 담지 않는다</b>가 규칙으로 선다.\n\n        **연합으로는 나가지 않는다** — 액터 문서에 싣지 않으므로 남의 서버에는 이 줄이 없다.\n\n        **꾸밈은 뷰어가 입힌다** — 코어가 내는 것은 <b>이름</b>이고, 그 이름에 어떤 말과 빛이\n        붙는지는 그룹의 꾸밈이 정한다(`/api/v1/groups`). 뱃지를 끈 그룹은 여기 오지 않는다.\n      }}\n      {{!\n        **뱃지를 여기서 엮지 않는다** (<a href=\"../../../../.claude/milestone-47_names_carry_badges.md\">47</a> 확정 1).\n\n        ~~이름 앞에 `group_badges`를 늘어놓았다~~ — 그 방식은 **이 자리에만** 뱃지를 세웠고,\n        새 화면이 설 때마다 빠졌다. 이제 이름이 뱃지를 데리고 오므로(`display_name`) 여느\n        이름과 똑같이 적는다.\n      }}\n      <p class=\"display-name\"><a href=\"/@{{account.handle}}\">{{#account}}{{> name-badged}}{{/account}}</a></p>\n      {{!\n        **아이디는 코드 블럭이고 누르면 복사된다**(05e 요구 D4). 포스트 쪽과 같은 훅이다 —\n        같은 값이고 같은 쓰임이라 다르게 다룰 이유가 없다.\n      }}\n      <p class=\"handle\"><code data-copy=\"@{{account.handle}}\"\n            data-key=\"account.handle\" data-value=\"{{account.handle}}\">@{{account.handle}}</code></p>\n    </div>\n  </div>\n\n  {{!\n    **본문이 채워졌다**(M11). 요구가 여기 세우라고 한 둘이 이제 코어에 있다.\n\n    **여백은 상자가 아니라 그 안에 서는 것들이 진다**(2026-08-21 요구). `card-body` 자체는\n    마진도 패딩도 갖지 않는다 — 안이 비어 있어도 자리를 먹고, 둘이 들어오면 여백이 두 겹이\n    되기 때문이다.\n\n    **소개는 코어가 만든 HTML이다**(`bio_html`) — 포스트 본문과 같은 통로를 지났으므로\n    같은 산수화를 거쳤고, 그래서 세 겹 중괄호로 낸다. 사람이 적은 원본(`bio`)이 서는 자리는\n    고치는 폼 하나다.\n  }}\n  <div class=\"card-body\">\n    {{#account.bio_html}}<div class=\"bio content\">{{{.}}}</div>{{/account.bio_html}}\n\n    {{!\n      **표다** (2026-08-24 요구). ~~`<dl>`~~이었고 그것도 이름-값의 짝이지만, 값이 여러 줄이\n      될 수 있게 되면서 <b>이름이 값 위에 서는 것</b>이 읽기 어려워졌다 — 표는 이름과 값을\n      한 줄에 나란히 두고, 줄이 길어져도 이름은 제 자리에 남는다.\n\n      **윤곽선은 없고 위쪽 정렬이다**(같은 요구). 칸이 몇 줄짜리든 이름은 첫 줄 옆에 선다.\n\n      **이름은 `<th scope=\"row\">`다.** 표의 모양을 빌리면서 <i>무엇이 무엇의 이름인가</i>를\n      잃지 않는 자리이며, `<dl>`의 `<dt>`가 하던 일을 그대로 진다.\n    }}\n    {{#fields.length}}\n    <table class=\"profile-fields\">\n      <tbody>\n        {{#fields}}\n        <tr>\n          <th scope=\"row\">{{name}}</th>\n          {{!\n            **주소만 링크가 된다**(M11 `다`). 스킴 없는 글자를 추측해 링크로 만들면 주소처럼\n            생긴 것이 전부 링크가 되고, 틀렸을 때 사람이 고칠 길이 없다.\n\n            **파비콘을 부르지 않는다** — 05e 요구를 뒤집은 자리다. 바깥을 부르는 일이라\n            CSP·추적·실패 처리가 따라오고 얻는 것은 아이콘 하나다.\n\n            **여러 줄이 그대로 선다** — 줄바꿈은 스타일시트가 지키고(`white-space`) 마크업은\n            `<br>`을 짓지 않는다: 값은 사람이 적은 글자이고 우리가 태그로 바꾸는 순간\n            이스케이프의 책임이 여기로 온다.\n          }}\n          <td>{{#is_link}}<a href=\"{{value}}\" rel=\"nofollow noopener ugc\">{{value}}</a>{{/is_link}}{{^is_link}}{{value}}{{/is_link}}</td>\n        </tr>\n        {{/fields}}\n      </tbody>\n    </table>\n    {{/fields.length}}\n\n    {{#relationship.followed_by}}<p class=\"note\">{{t.card.follows_you}}</p>{{/relationship.followed_by}}\n  </div>\n\n  {{!\n    **~~풋터~~가 아니라 본문 밑의 한 켜다** (2026-08-24 요구 — `profile-connections`).\n\n    담긴 것은 그대로다 — 셈과 프로필 액션(2026-08-25 요구로 ~~사용자 액션~~에서 이름이\n    갈렸다 — 헤더 오른쪽의 것이 그 이름을 쓴다). 옮긴 이유는 <b>그것들이 카드의 마무리가 아니라\n    이 사람에게 딸린 것들</b>이어서다: 소개·필드와 같은 결이고 같은 안쪽 선에 서야 한다.\n    카드가 여백을 지지 않으므로(`.card-body`) 여기도 자기 몫을 든다.\n\n    **아카이브가 빠졌다**(같은 요구). *문서로 들어가는 길은 위키링크뿐*(2026-08-21 요구)과\n    같은 방향이며, 그 규정이 둘러보기에서 `아카이브`를 걷어낸 근거 그대로다 — 남의 문서에\n    닿는 길은 그 사람이 쓴 링크이지 목록이 아니다.\n  }}\n  <div class=\"profile-connections\">\n    {{!\n      **셈이 왼쪽이다**(05e 요구). 둘 다 \"이 사람에게 딸린 것이 얼마나 되는가\"를 말하는\n      자리라 숫자와 링크가 한 몸이다.\n\n      **~~팔로워 수가 곧 팔로우 토글이었다~~** (2026-09-22 요구). 그 자리는 <b>같은 줄에 선\n      팔로잉과 다른 일</b>을 했다 — 나란한 둘 가운데 하나는 명단으로 가고 하나는 관계를\n      바꾸니, 어느 쪽인지 눌러 보아야 알았다. **이제 둘 다 제 명단으로 간다**(전역 규칙의\n      반복성). 토글은 점 셋 상자로 갔다 — 관계를 바꾸는 일이 모여 있는 자리다.\n\n      **그래서 `people` 화면이 둘을 서로 잇던 까닭도 사라졌다** — 여기서 바로 간다.\n    }}\n    <span class=\"counts\">\n      {{!\n        **남의 서버 사람에게는 명단으로 가는 링크가 없다** (2026-09-06).\n\n        <b>우리에게 그 목록이 없다.</b> 팔로워·팔로잉은 그 서버가 쥐고 있고 우리가 아는 것은\n        <i>우리 서버 사람 몇이 그를 따르는가</i>인데, 그것은 그 사람의 수가 아니다 — 눌러도\n        빈 명단이 서는 링크를 세우지 않는다.\n\n        **그래도 수는 적는다**(2026-09-22) — 팔로우 토글이 떠나면서 이 자리가 비었는데,\n        <b>아는 값을 감추는 것</b>과 없는 명단으로 보내는 것은 다른 일이다.\n      }}\n      {{^remote}}\n      <a href=\"/@{{account.handle}}/-/followers\">{{t.card.followers}} {{relationship.followers_count}}</a>\n      <a href=\"/@{{account.handle}}/-/following\">{{t.card.following}} {{relationship.following_count}}</a>\n      {{/remote}}\n      {{#remote}}\n      <span class=\"count\">{{t.card.followers}} {{relationship.followers_count}}</span>\n      {{/remote}}\n    </span>\n\n    {{#signed_in}}\n    {{!\n      **프로필 액션은 드롭다운 안에 있다**(05e 요구 · 2026-08-25 요구로 이름과 여는 모양이\n      갈렸다). 자주 누르는 것이 아니고, 뮤트·차단은 되돌릴 수 있어도 한 번 더 생각할 자리가\n      있는 편이 낫다.\n\n      **~~사용자 액션~~이라 부르지 않는다**(2026-08-25 요구). 헤더 오른쪽의 것이 이미 그\n      이름을 쓰고 있어(`header-account`) 문서에서 어느 쪽을 말하는지 매번 되물어야 했다 —\n      **이것은 프로필에 딸린 것들**이라 카드가 서는 자리마다 함께 따라다닌다.\n\n      **여는 것은 점 셋이다**(같은 요구). ~~낱말~~이었고 그 근거는 *헤더의 `피드`·`사용자\n      메뉴`와 같다*였는데, 이름이 갈리면서 짝도 갈렸다 — 여기가 닮은 것은 <b>포스트 액션</b>\n      이다: 한 대상(글·사람)에 딸린 일들을 한 상자에 담고 상자가 그 대상 옆에 선다.\n      낱말은 마크업에 남고 스타일시트가 눈에서만 가린다.\n\n      **자기 카드에서도 같은 상자다**(같은 요구). `프로필 수정`이 상자 밖에 홀로 서 있었고,\n      그 자리는 남의 카드에서 점 셋이 서는 자리다 — <b>같은 자리에 같은 모양</b>이면\n      마크업도 하나여야 하고 갈리는 것은 안에 담기는 것뿐이다(포스트 액션과 같은 판단).\n\n      카드는 조각이라 `path_encoded`가 없다. 돌아갈 자리는 `returnTo`가 준다 —\n      페이지 쪽과 다른 값을 쓰는 유일한 자리다.\n    }}\n    <details class=\"dropdown advanced\" data-dropdown>\n      <summary><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-dots}}</span><span class=\"nav-label\">{{t.card.actions}}</span></summary>\n      <ul class=\"dropdown-menu\">\n        {{#self}}\n        <li><a class=\"action edit\" href=\"/-/settings/profile\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pencil}}</span><span class=\"nav-label\">{{t.profile.edit}}</span></a></li>\n        {{/self}}\n        {{^self}}\n        {{!\n          **낱말과 그림이 포스트 액션의 것과 같다**(2026-09-08 요구). 두 상자가 같은 일을\n          하므로 <b>같은 이름과 같은 그림</b>으로 서야 한다 — 자리마다 다르면 사람은 그 둘이\n          다른 일인지 매번 확인한다.\n        }}\n        <li><a class=\"action mention\" href=\"/-/compose?mention={{account.handle}}&return={{returnTo}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-mention}}</span><span class=\"nav-label\">{{t.post.mention}}</span></a></li>\n        {{! **메시지는 이 서버 안의 일이다** — 연합으로 나가는 통로가 없다(2026-09-06). }}\n        {{^remote}}\n        <li><a class=\"action message\" href=\"/-/compose?to={{account.handle}}&return={{returnTo}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-envelope}}</span><span class=\"nav-label\">{{t.post.message}}</span></a></li>\n        {{/remote}}\n        {{!\n          **`팔로우`가 관계를 바꾸는 갈래의 첫 줄이다** (2026-09-22 요구 — 셈에서 옮겨 왔다).\n\n          **포스트 액션이 이미 그 차례다**(2026-09-08 요구 — *팔로우·뮤트·차단*): 말을 거는\n          일(멘션·메시지)은 <i>지금 한 번</i>이고 이 셋은 <b>앞으로 무엇이 보이는가</b>를\n          바꾼다. 두 상자가 같은 일을 하므로 <b>낱말도 그림도 차례도 같다</b>.\n\n          **여기서는 상태를 알고 선다** — 카드는 관계를 함께 물어 왔으므로(`followAction`)\n          포스트 액션처럼 `off`로 세웠다가 펼칠 때 고쳐 잡을 까닭이 없다.\n\n          **남의 서버 사람에게도 선다** — 팔로우는 연합으로 나가는 일이라 명단과 사정이\n          다르다(그쪽은 우리에게 목록이 없어 링크가 서지 않는다).\n        }}\n        <li><a class=\"action follow\" data-toggle=\"follow\" rel=\"nofollow\"\n               data-api=\"/api/v1/accounts/{{account.id}}\" data-verb=\"{{followAction}}\"\n               data-state=\"{{followState}}\"\n               data-on=\"{{t.post.unfollow}}\" data-off=\"{{t.post.follow}}\"\n               href=\"/@{{account.handle}}/-/{{followAction}}?csrf={{csrf}}&return={{returnTo}}\"\n               ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-person}}</span><span class=\"nav-label\" data-label>{{followLabel}}</span></a></li>\n        <li><a class=\"action mute\" data-toggle=\"mute\" rel=\"nofollow\"\n               data-api=\"/api/v1/accounts/{{account.id}}\" data-verb=\"{{muteAction}}\"\n               data-state=\"{{muteState}}\"\n               data-on=\"{{t.post.unmute}}\" data-off=\"{{t.post.mute}}\"\n               href=\"/@{{account.handle}}/-/{{muteAction}}?csrf={{csrf}}&return={{returnTo}}\"\n               ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-eye-off}}</span><span class=\"nav-label\" data-label>{{muteLabel}}</span></a></li>\n        {{!\n          **`차단`이 상자의 끝이다.** 되돌릴 수 있어도 양쪽 팔로우를 끊고 해제해도 돌아오지\n          않으므로, 포스트 액션의 `지우기`와 같은 자리에 선다.\n        }}\n        <li><a class=\"action block\" href=\"/@{{account.handle}}/-/block?return={{returnTo}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-shield-check}}</span><span class=\"nav-label\" data-label>{{blockLabel}}</span></a></li>\n        {{/self}}\n        {{!\n          **봇의 줄은 봇에게만 선다**(2026-09-08 요구). 코어가 그 사실을 프로필에 실어 주고\n          (`is_bot` — actor의 `type`이 이미 공개하는 값이다) 화면은 그것을 다시 묻지 않는다.\n\n          **자기 카드에도 선다** — 봇 계정으로 로그인해 자기 설정을 여는 일이 있다.\n\n          **`봇 걷기`는 되돌릴 수 없는 쪽이라 끝이다.** 토큰이 끊기고 봇 표시가 지워지며,\n          <b>계정과 글은 남는다</b> — 연합으로 나간 글에는 남의 서버에 사본이 있다.\n        }}\n        {{#is_bot}}\n        <li class=\"rule\" role=\"separator\"></li>\n        {{!\n          **프로필 수정은 내 것과 같은 화면이다**(2026-09-09 요구) — 칸도 차례도 규칙도 같고\n          갈리는 것은 보내는 자리 하나다. 봇에게는 브라우저가 없어 자기 설정을 열 수 없다.\n        }}\n        <li><a class=\"action bot-profile\" href=\"/-/settings/apps/{{account.id}}/profile\"\n               ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pencil}}</span><span class=\"nav-label\">{{t.profile.edit}}</span></a></li>\n        <li><a class=\"action bot-settings\" href=\"/-/settings/apps/{{account.id}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-robot}}</span><span class=\"nav-label\">{{t.bot.settings}}</span></a></li>\n        <li><a class=\"action bot-retire\" href=\"/-/settings/apps/{{account.id}}/retire\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-trash}}</span><span class=\"nav-label\">{{t.bot.retire}}</span></a></li>\n        {{/is_bot}}\n        {{!\n          **계정 완전 삭제는 상자의 끝이다**(2026-09-09 요구). 되돌릴 수 없고, 남의 화면에\n          자국을 남기며(답글이 부모를 잃고 복제가 사라진다), <b>관리자에게만</b> 선다 —\n          가리기와 같은 자리이고 무게만 다르다.\n\n          **자기 자신에게는 서지 않는다** — 마지막 관리자가 자기를 지우면 아무도 문을 열 수\n          없는 서비스가 된다(코어도 그것을 막는다).\n        }}\n        {{!\n          **프로필 검열이 지우기 위에 선다** (2026-09-17 요구).\n\n          **되돌릴 수 있는 것과 없는 것을 가로줄이 가른다**(전역 규칙) — 표시 이름 한 줄을\n          고치려고 <b>계정을 통째로 지우는 문</b>을 쓰게 두지 않는다. 지금까지 그 문 하나뿐이었다.\n\n          **그룹도 그 화면에서 만진다** — 사람에게 매기는 것이 한 자리에 모인다.\n        }}\n        {{#site_admin}}\n        {{^self}}\n        <li class=\"rule\" role=\"separator\"></li>\n        {{! **모달이 아니라 화면이다** — 고칠 것이 상자 셋이라 그 자리에서 열 크기가 아니다. }}\n        <li><a class=\"action\" href=\"/-/moderation/profiles/{{account.handle}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-pencil}}</span><span class=\"nav-label\">{{t.profile.moderate}}</span></a></li>\n        <li class=\"rule\" role=\"separator\"></li>\n        <li><a class=\"action erase\" href=\"/@{{account.handle}}/-/erase?return={{returnTo}}\"\n               data-form><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-trash}}</span><span class=\"nav-label\">{{t.erase.action}}</span></a></li>\n        {{/self}}\n        {{/site_admin}}\n      </ul>\n    </details>\n    {{/signed_in}}\n  </div>\n\n</div>\n","modal-compose":"{{#parent}}{{> body-quoted}}{{/parent}}\n{{!\n  **인용 대상도 폼 머리에 선다** (M29 · 2026-08-31). 답글의 원글과 같은 자리인데, 그쪽은\n  *무엇에 답하는가*이고 이쪽은 *무엇을 걸고 쓰는가*다 — 둘이 함께 실릴 수도 있다(막지 않는다).\n}}\n{{#quoted}}<div class=\"quoting\">{{> body-quoted}}</div>{{/quoted}}\n\n{{!\n  **받는 사람은 여럿일 수 있다** (39 — 계정 목록의 `메시지 발송`). 하나든 여럿이든 같은 줄이다.\n}}\n{{#recipients.length}}\n<p class=\"to\">{{t.compose.recipients}} {{#recipients}}{{> iteration-person}} {{/recipients}}</p>\n{{/recipients.length}}\n\n{{!\n  **훅은 전부 선택이다**(05e). 아래 `data-*`를 지워도 폼은 그대로 동작한다 — 파일을 고르고\n  제출하면 서버가 한꺼번에 올린다. 붙여 두면 고르는 순간 올라가고 미리보기·진행률이 선다.\n\n  `data-draft`의 값이 초안의 이름이다. 답글·메시지가 새 글과 섞이지 않게 대상을 함께 적는다.\n}}\n<form class=\"compose post-compose\" method=\"post\" action=\"/-/posts\" enctype=\"multipart/form-data\"\n      data-dropzone data-draft=\"compose:{{in_reply_to}}{{#recipients}}{{handle}},{{/recipients}}\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n  {{#in_reply_to}}<input type=\"hidden\" name=\"in_reply_to\" value=\"{{.}}\">{{/in_reply_to}}\n  {{#quoted_post_id}}<input type=\"hidden\" name=\"quoted_post_id\" value=\"{{.}}\">{{/quoted_post_id}}\n  {{!\n    **거절당한 사정이 적히는 자리** (2026-09-03에 물렸다). 브라우저가 여기에 문장을 넣는다 —\n    <b>이 자리가 없으면 폼 전체가 그 문장으로 갈아 끼워지고</b>, 그때 방금 쓴 글이 사라진다:\n    이 화면에서 가장 나쁜 일이다.\n\n    **카멜에서는 늘 비어 있다** — 그쪽은 폼 왕복이라 서버가 화면을 다시 그리며 사정을 적는다.\n    비어 있는 동안은 스타일시트가 감춘다(`:empty`).\n  }}\n  <p class=\"error\" data-notice role=\"status\"></p>\n  {{!\n    **담을 자리를 들고 다닌다**(2026-08-21 요구 — 블록 경계의 `글 쓰기`).\n\n    이 둘이 실려 오면 제출한 글이 <b>그 문서의 그 자리</b>에 담긴다. 쓰고 나서 다시 담으러\n    오는 두 걸음이 한 걸음이 되고, 그 사이에서 <b>어디에 담으려 했는지를 잃지 않는다.</b>\n    없으면 아무 일도 없다 — 평범한 새 글이다.\n  }}\n  {{#document_id}}<input type=\"hidden\" name=\"document_id\" value=\"{{.}}\">{{/document_id}}\n  {{#before}}<input type=\"hidden\" name=\"before\" value=\"{{.}}\">{{/before}}\n  {{#recipients.length}}\n  {{!\n    메시지는 공개 범위가 잠긴다 — `direct` 하나뿐이다(M2). 아래 공개 범위 칸이 함께\n    사라지므로, 고를 수 없는 것을 고르는 화면이 되지 않는다.\n  }}\n  {{#recipients}}<input type=\"hidden\" name=\"recipients\" value=\"{{handle}}\">{{/recipients}}\n  <input type=\"hidden\" name=\"visibility\" value=\"direct\">\n  {{/recipients.length}}\n\n  <label for=\"compose-body\">{{composeLabel}}</label>\n  {{!\n    **첫 값이 실려 올 수 있다** — 프로필 카드의 `멘션`이 `@아이디 `를 채워 보낸다(05e).\n    비어 있으면 아무 일도 없다. 초안 되살리기는 *비어 있을 때만* 하므로 둘이 다투지 않는다.\n  }}\n  {{!\n    **`data-grow`는 칸이 내용만큼 자란다는 뜻이다** (2026-09-11 요구). 어디까지 자라는지는\n    스킨의 CSS가 말하고(`max-height`) 그 위로는 칸이 스크롤한다.\n  }}\n  <textarea id=\"compose-body\" name=\"body\" required\n            maxlength=\"{{limits.post_max_length}}\" data-suggest data-grow>{{body_prefill}}</textarea>\n  <p class=\"counter\">{{t.compose.remaining}} <span data-counter>{{limits.post_max_length}}</span></p>\n\n  {{!\n    **첨부는 두 길이 나란히 선다** (2026-09-22 요구). 칸의 이름이라 `<label>`이 아니라 문단이다 —\n    아래 두 단추가 저마다 제 이름을 이미 들고 있고, 이 줄까지 그 칸의 이름이면 <b>읽어 주는\n    기계가 이름 둘을 이어 부른다.</b>\n  }}\n  <p class=\"form-label\">{{t.compose.attach}}</p>\n  {{!\n    **한도는 서버가 말한다.** 인스턴스 응답에 실려 오는 값을 그대로 심는다 — 스크립트에\n    숫자를 두면 사이트 설정을 바꿔도 화면이 옛 한도로 막는다.\n\n    **파일 칸은 눈에서만 물러난다**(2026-09-22 요구 — *버튼 형식으로 디자인해서 나란히*).\n    브라우저가 내는 <i>파일 선택 · 선택된 파일 없음</i>이 옆의 단추와 다른 물건처럼 서 있었다.\n    <b>지우지 않고 가린다</b>: 초점은 그대로 받아야 하고(탭으로 닿는다) 여는 일은\n    <b>마크업이 한다</b> — `<label for>`가 곧 그 단추다(스크립트가 없어도 열린다).\n  }}\n  <div class=\"compose-picks\">\n    {{!\n      **직접 첨부는 서버가 끌 수 있다** (46 확정 6 · 2026-09-25 요구) — `media.attachment_enabled`.\n      **끄면 이 칸과 그 레이블이 함께 빠진다**: 파일 칸만 남기면 <b>눈에 보이지 않는데 탭으로는\n      닿는</b> 칸이 서고, 레이블만 남기면 여는 곳이 없는 단추가 선다.\n\n      **끈 것이 분명할 때만 걷는다** — 모르는 값은 켜진 것으로 본다(뷰가 그렇게 잰다).\n      *이 서버에 없는 기능*이라 미구현 단추의 규칙(눌러서 알린다)이 여기 해당하지 않는다.\n    }}\n    {{#attach.device}}\n    <input id=\"compose-media\" class=\"compose-file\" type=\"file\" name=\"media\" multiple data-uploader\n           data-max-bytes=\"{{limits.media_max_size_bytes}}\">\n    <label class=\"button is-light\" for=\"compose-media\">{{t.compose.from_device}}</label>\n    {{/attach.device}}\n    {{!\n      **갤러리에서도 고른다** (<a href=\"../../../../.claude/milestone-46_attachment_assets.md\">46</a>\n      확정 2). 문서의 미디어 블록이 쓰는 그 탐색기이며 — 같은 것을 고르는 일이 화면마다 다르게\n      보이지 않게 — 고른 뒤에는 **그 파일을 가리키는 첨부**가 선다(확정 1).\n\n      **고르러 가는 단추는 으뜸이 아니다**(전역 규칙 · 2026-09-15 요구) — 눌러도 아직 아무것도\n      정해지지 않고, 이 판을 끝내는 단추는 `쓰기` 하나다. **기기에서 고르는 것도 같은 갈래**라\n      같은 옷을 입는다(전역 규칙의 *선택*: 고르러 간다 · 갤러리 · 업로드).\n\n      **감추지 않는다** — 하멜에는 점진적 향상의 하한이 없다(그 하한은 카멜이 진다): 스크립트가\n      죽으면 이 폼 자체가 서지 않으므로, *스크립트가 있을 때만 서는 단추*라는 구분이 없다.\n    }}\n    {{!\n      **갤러리도 서버가 끌 수 있다** — 문서 레이어의 `asset.post_attach_enabled`다(46 확정 6).\n      코어의 스위치와 <b>따로 선다</b>: 직접 첨부만 닫은 서버에서는 이 단추 하나가 남는다.\n    }}\n    {{#attach.gallery}}\n    <button class=\"button is-light\" type=\"button\" data-asset-browse>{{t.compose.from_gallery}}</button>\n    {{/attach.gallery}}\n    {{!\n      **이모지는 오른끝이다** (2026-09-22 요구). 앞의 둘은 <i>첨부를 얻는 두 길</i>이고 이것은\n      <b>본문에 넣는 일</b>이라 같은 무리가 아니다 — 줄을 나누지 않고 <b>사이를 벌려</b>\n      가른다(스타일시트가 민다).\n\n      **고르는 격자는 그룹 뱃지의 창과 같은 조각이다** — 고른 뒤의 일만 갈린다(커서 자리).\n    }}\n    <button class=\"button is-light compose-emoji\" type=\"button\" data-emoji-insert>{{t.compose.emoji}}</button>\n  </div>\n  {{!\n    **개수 상한은 담기는 자리가 든다** — 두 길이 같은 목록에 쌓이므로(올린 것 · 가리킨 것)\n    <b>세는 자리도 하나</b>여야 한다. 파일 칸에 두었더니 그 칸이 빠지는 순간 갤러리 쪽의\n    셈이 함께 사라졌다. 용량은 올리는 길만 재므로 그대로 파일 칸에 있다.\n  }}\n  <ul class=\"attachments\" data-attachments data-max=\"{{limits.media_max_per_post}}\"></ul>\n\n  {{!\n    **대체 텍스트 칸은 스크립트가 없을 때의 하한이다**(2026-08-20 요구).\n\n    자바스크립트가 있으면 첨부는 고르는 순간 올라가고 **장마다 자기 칸**이 생긴다\n    (`camel.js`의 첨부 편집기) — 그때 이 칸은 <b>아무 데도 닿지 않는다</b>: 폼이 실어 보내는\n    것은 `media_ids`뿐이고 서버 쪽 `media_description`은 폼에서 곧장 온 파일에만 붙는다\n    (`routes/posts.ts`). 남겨 두면 적어도 사라지는 칸이 화면에 선다.\n\n    **그래서 감추는 일을 스크립트가 한다.** `hidden`을 마크업에 박으면 스크립트가 없는\n    브라우저에서 영영 감춰지고, CSS로 가리면 스킨마다 다시 적어야 한다 — 훅 하나를 달아\n    두고 편집기가 붙는 자리에서 함께 감춘다.\n  }}\n  <p data-single-description>\n    <label for=\"compose-media-description\">{{t.compose.alt_text}}</label>\n    <input id=\"compose-media-description\" type=\"text\" name=\"media_description\">\n  </p>\n\n  {{!\n    **~~링크 첨부 칸~~을 걷었다**(2026-08-20 요구). 카드는 이제 <b>본문이 만든다</b> — 코어가\n    산수화한 글에서 첫 바깥 링크를 찾아 oembed·OpenGraph를 물어본다. 본문에 이미 그 주소가\n    있는 글에서 주소를 한 번 더 적게 하는 것은 같은 말을 두 번 하는 일이었다.\n  }}\n\n  {{#inherited_visibility}}\n  {{!\n    **답글은 공개 범위를 고르지 않는다**(25) — 원글의 것을 그대로 받는다. 고를 칸을 두면\n    고른 값이 읽히지 않고, 화면과 판정이 다른 것을 말한다.\n\n    값을 보내지 않는다. 코어가 상속하므로 실어 보낼 것이 없고, 보내면 거절된다.\n  }}\n  <p class=\"visibility inherited\" data-key=\"visibility.inherited\">\n    {{t.visibility.label}}: {{.}}\n  </p>\n  {{/inherited_visibility}}\n\n  {{^recipients.length}}{{^inherited_visibility}}\n  <label for=\"compose-visibility\">{{t.visibility.label}}</label>\n  <select id=\"compose-visibility\" name=\"visibility\">\n    {{!\n      **맨 위가 무엇인지 말한다** (2026-09-22 요구 — `**(기본값)`). <i>기본값</i> 한 낱말로는\n      <b>어디까지 나가는지</b>를 고르는 자리에서 알 수 없었다 — 값이 실려 오면 그 이름을\n      함께 세운다(없으면 옛 낱말 그대로).\n    }}\n    <option value=\"\">{{#inherit_label}}{{.}}{{/inherit_label}}{{^inherit_label}}{{t.choice.inherit}}{{/inherit_label}}</option>\n    <option value=\"federated\">{{t.visibility.federated}}</option>\n    <option value=\"server\">{{t.visibility.server}}</option>\n    <option value=\"quiet\">{{t.visibility.quiet}}</option>\n    <option value=\"followers\">{{t.visibility.followers}}</option>\n    {{!\n      **맨 아래가 가장 좁다** (M12). 위에서 아래로 좁아지는 차례이고, `나만 보기`가 그 끝이다 —\n      고르는 사람이 *얼마나 넓히는가*를 한 방향으로 읽는다.\n    }}\n    <option value=\"private\">{{t.visibility.private}}</option>\n  </select>\n  {{/inherited_visibility}}{{/recipients.length}}\n\n  <button class=\"button is-primary\" type=\"submit\">{{t.compose.submit}}</button>\n</form>\n","modal-corpus-pick":"{{!\n  **고른 글감을 무엇으로 놓을지** (31 확정 12·13 · 2026-09-16 요구로 모양을 맞췄다).\n\n  <b>본문 붙여넣기</b>는 거기서부터 본문 교정을 시작한다는 뜻이고 — 복제된 글자는 그 자체로\n  문서의 본문이며 원 포스트와 이어진 자취를 남기지 않는다 — <b>인용</b>은 살아 있는\n  레퍼런스로 남는다(08b).\n\n  **사이드바의 카드와 같은 구성이다**(요구). ~~본문 앞부분만 섰다~~ — 누른 것이 무엇인지\n  확인하러 온 자리인데 <b>누가 언제 쓴 글인지</b>가 빠져 있으면, 같은 말로 시작하는 글이\n  둘일 때 확인할 방법이 없다. 카드의 세 조각(<i>글쓴이 · 때 · 글</i>)을 그대로 쓴다.\n\n  **누를 것이 아니므로 그 표시를 걷는다**(`corpus-chosen`) — 여기서 카드는 <i>고른 것</i>이지\n  고르는 자리가 아니다.\n}}\n<section class=\"corpus-chosen-box\">\n  <div class=\"corpus-card corpus-chosen\">\n    <span class=\"corpus-author\">{{author}}</span>\n    <time class=\"corpus-when\">{{when}}</time>\n    <span class=\"corpus-text\">{{text}}</span>\n  </div>\n\n  {{!\n    **끝을 내는 단추가 둘이다.** 어느 쪽도 다른 화면으로 가지 않으므로 <b>으뜸은 하나</b>로\n    두고(`is-primary`) 다른 갈래를 그 옆에 세운다 — 나란한 두 결정이 같은 무게로 서면\n    <i>무엇이 기본인지</i>가 읽히지 않는다.\n\n    **취소는 수식어가 없다**(전역 규칙) — 제자리에서 무르는 것이므로 링크가 아니라 단추다.\n  }}\n  <p class=\"corpus-deeds\">\n    <button class=\"button is-primary\" type=\"button\" data-corpus-pick=\"body\">{{t.document.paste_body}}</button>\n    <button class=\"button is-light\" type=\"button\" data-corpus-pick=\"quote\">{{t.document.paste_quote}}</button>\n    <button class=\"button\" type=\"button\" data-corpus-pick=\"cancel\">{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-corpus":"{{!\n  **글감 모달** — `/인용`이 부르는 자리 (2026-09-13 요구).\n\n  ~~옆의 사이드바로 초점만 옮겼다~~ — **초점이 옮겨진 것만으로는 입력의 다음 단계로\n  넘어갔다는 것을 알아채기 어렵다.** 모달은 화면을 덮으므로 그 사실을 말할 필요가 없다.\n\n  **사이드바보다 넓다.** 그래서 카드가 기둥 하나가 아니라 <b>격자</b>로 선다\n  (`.corpus-gallery`) — 훑는 일에는 그 편이 눈이 덜 움직인다.\n\n  **고르면 곧 끝난다.** 사이드바에서는 카드를 누른 뒤 <i>본문이냐 인용이냐</i>를 다시 묻지만\n  (거기서는 무엇을 하려는지 말한 적이 없다), 여기 온 사람은 <b>커맨드로 이미 말했다</b> —\n  다시 묻는 것은 한 걸음을 공으로 늘리는 일이다.\n\n  **이 자리는 다시 쓰인다.** 앞으로 설 특수 블록들도 *포스트 하나를 고르는 일*을 하므로,\n  무엇에 쓸지는 <b>부르는 쪽</b>이 알고 여기는 <i>고르는 일</i>만 안다.\n}}\n<section class=\"corpus corpus-gallery\" data-corpus>\n  <h2 class=\"corpus-title\">{{t.document.corpus_pick}}</h2>\n  {{> corpus-browser}}\n</section>\n","modal-delete":"<div class=\"danger\">\n  <p class=\"hint\">\n    {{{t.delete.post_warn}}}\n  </p>\n\n  {{#post}}{{> body-quoted}}{{/post}}\n\n  <form method=\"post\" action=\"{{post.permalink}}/-/delete\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n    {{!\n      **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n      줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n      **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n      이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n    <div class=\"document-actions\">\n      <button class=\"button is-danger\" type=\"submit\">{{t.delete.post}}</button>\n      {{#on_page}}<a class=\"button\" href=\"{{post.permalink}}\">{{t.back.cancel}}</a>{{/on_page}}\n    </div>\n  </form>\n</div>\n","modal-edit":"<form class=\"compose post-compose\" method=\"post\" action=\"{{post.permalink}}/-/edit\" enctype=\"multipart/form-data\"\n      data-dropzone data-draft=\"edit:{{post.id}}\">\n  <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n  <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n  {{!\n    **거절당한 사정이 적히는 자리** (2026-09-03에 물렸다). 브라우저가 여기에 문장을 넣는다 —\n    <b>이 자리가 없으면 폼 전체가 그 문장으로 갈아 끼워지고</b>, 그때 방금 쓴 글이 사라진다:\n    이 화면에서 가장 나쁜 일이다.\n\n    **카멜에서는 늘 비어 있다** — 그쪽은 폼 왕복이라 서버가 화면을 다시 그리며 사정을 적는다.\n    비어 있는 동안은 스타일시트가 감춘다(`:empty`).\n  }}\n  <p class=\"error\" data-notice role=\"status\"></p>\n\n  <label for=\"compose-body\">{{t.compose.body}}</label>\n  {{!\n    **고치는 칸도 자란다** (2026-09-21 요구 — 쓰기 폼 교정). 글쓰기와 같은 물건이므로\n    같은 훅이 선다 — 한쪽만 자라면 같은 일이 화면마다 다르게 동작한다.\n  }}\n  <textarea id=\"compose-body\" name=\"body\" required\n            maxlength=\"{{limits.post_max_length}}\" data-suggest data-grow>{{post.content}}</textarea>\n  <p class=\"counter\">{{t.compose.remaining}} <span data-counter>{{limits.post_max_length}}</span></p>\n\n  {{!\n    **쓰기 폼과 같은 줄이다**(2026-09-22 요구) — 파일 칸은 눈에서만 물러나고 `<label for>`가\n    그 단추이며, 그 옆에 갤러리가 선다(46 확정 2가 ~~쓰기 폼에만~~ 세웠던 것을 여기까지\n    끌어왔다). **고쳐 붙이는 것과 새로 붙이는 것이 다른 길일 이유가 없다** — 붙는 것도 같다:\n    갤러리에서 고른 것은 <b>그 에셋을 가리키는 첨부</b>다(확정 1).\n  }}\n  <p class=\"form-label\">{{t.compose.attach_more}}</p>\n  {{!\n    **두 길을 서버가 따로 끈다** (46 확정 6 · 2026-09-25 요구) — 코어의\n    `media.attachment_enabled`와 문서 레이어의 `asset.post_attach_enabled`다. **쓰기 폼과 같은\n    가지를 든다**: 한쪽만 닫은 서버에서 고치기 화면만 단추 둘을 세우면 <b>같은 일이 화면마다\n    다르게 보인다</b>(전역 규칙의 반복성).\n  }}\n  <div class=\"compose-picks\">\n    {{#attach.device}}\n    <input id=\"compose-media\" class=\"compose-file\" type=\"file\" name=\"media\" multiple data-uploader\n           data-max-bytes=\"{{limits.media_max_size_bytes}}\">\n    <label class=\"button is-light\" for=\"compose-media\">{{t.compose.from_device}}</label>\n    {{/attach.device}}\n    {{#attach.gallery}}\n    <button class=\"button is-light\" type=\"button\" data-asset-browse>{{t.compose.from_gallery}}</button>\n    {{/attach.gallery}}\n    {{! **이모지도 같은 줄의 오른끝이다** — 쓰기 폼과 같은 물건이다(2026-09-22 요구). }}\n    <button class=\"button is-light compose-emoji\" type=\"button\" data-emoji-insert>{{t.compose.emoji}}</button>\n  </div>\n  {{! **개수 상한은 담기는 자리가 든다** — 쓰기 폼과 같은 손이다(두 길이 한 목록에 쌓인다). }}\n  <ul class=\"attachments\" data-attachments data-max=\"{{limits.media_max_per_post}}\"></ul>\n\n  {{!\n    **이미 붙어 있는 것은 단추 뒤에 선다** (2026-09-22 요구 — ~~본문과 단추 사이~~).\n    <b>붙이는 일이 먼저이고 지금 붙어 있는 것이 그 다음</b>이라야, 단추를 누른 결과(바로\n    위의 줄)와 그 글이 이미 들고 있는 것이 한 자리에서 읽힌다.\n\n    **떼는 법은 스타일시트가 감춘다**(같은 요구) — 체크 하나에 딸린 안내 한 줄이 이 폼에서\n    가장 긴 문장이었다. 지우지 않고 가리므로 **읽어 주는 기계에는 그대로 남는다**.\n  }}\n  {{#post.media.length}}\n  <fieldset class=\"keep\">\n    <legend>{{t.edit.attached}}</legend>\n    <p class=\"hint\">{{t.edit.detach_hint}}</p>\n    <ul class=\"media\">\n      {{#post.media}}\n      <li>\n        {{!\n          **링크 카드에는 떼기가 없다**(2026-08-20 요구). 그것은 사람이 붙인 것이 아니라\n          <b>본문이 부른 것</b>이라, 본문에서 링크를 지우면 함께 사라지고 바꾸면 따라 바뀐다 —\n          체크를 풀 수 있게 두면 아무 일도 일어나지 않는 자리가 된다.\n        }}\n        {{#is_link}}\n        <span class=\"from-body\">\n          <a href=\"{{url}}\" data-attachment=\"{{id}}\">{{#title}}{{title}}{{/title}}{{^title}}{{url}}{{/title}}</a>\n          <span class=\"hint\">{{t.edit.from_link}}</span>\n        </span>\n        {{/is_link}}\n        {{^is_link}}\n        <label class=\"choice\">\n          <input type=\"checkbox\" name=\"keep\" value=\"{{id}}\" checked>\n          <a href=\"{{url}}\" data-attachment=\"{{id}}\">\n            {{#preview_url}}<img src=\"{{.}}\" alt=\"{{description}}\" loading=\"lazy\">{{/preview_url}}\n            {{^preview_url}}{{#title}}{{title}}{{/title}}{{^title}}{{url}}{{/title}}{{/preview_url}}\n          </a>\n        </label>\n        {{/is_link}}\n      </li>\n      {{/post.media}}\n    </ul>\n  </fieldset>\n  {{/post.media.length}}\n\n  {{!\n    **이 칸도 편집기가 서면 물러난다**(2026-08-20 요구). 새 글 폼에는 훅이 붙어 있었는데\n    <b>고치기 폼에만 빠져 있었다</b> — 그래서 자바스크립트가 있을 때에도 칸이 그대로 서\n    있었고, 채워도 어디에도 닿지 않았다: 편집기가 붙은 폼이 싣는 것은 `media_ids`뿐이다.\n\n    `hidden`을 마크업에 박지 않는 이유는 새 글 폼과 같다 — 스크립트가 없는 브라우저에서는\n    이 칸이 파일 하나에 설명을 붙이는 유일한 길이다(`camel.js`의 `hydrate`).\n  }}\n  <p data-single-description>\n    <label for=\"compose-media-description\">{{t.compose.alt_text}}</label>\n    <input id=\"compose-media-description\" type=\"text\" name=\"media_description\">\n  </p>\n\n  {{!\n    **~~링크 첨부 칸~~을 걷었다**(2026-08-20 요구). 카드는 이제 <b>본문이 만든다</b> — 코어가\n    산수화한 글에서 첫 바깥 링크를 찾아 oembed·OpenGraph를 물어본다. 본문에 이미 그 주소가\n    있는 글에서 주소를 한 번 더 적게 하는 것은 같은 말을 두 번 하는 일이었다.\n  }}\n\n  {{!\n    **상태는 한 문장이다** (2026-09-22 요구 — ~~*공개 범위와 답글은 고칠 수 없습니다…*~~).\n    <b>자리가 그 말을 이미 한다</b>: 고를 칸이 없으므로 고칠 수 없다는 말이 따로 설 값이\n    없었다. 남는 것은 <i>지금 이 글이 누구에게 보이는가</i> 하나이고 — 그것을 모르면 본문을\n    어디까지 쓸지 판단할 수 없다(휴먼 테스트 10절) — **작성 폼의 공개 범위 칸이 서는 그\n    자리**에 선다: 두 폼을 오가는 눈이 같은 자리에서 같은 것을 읽는다.\n  }}\n  <p class=\"hint state\">{{{state_note}}}</p>\n\n  {{!\n    **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n    줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n    **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n    이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n  <div class=\"document-actions\">\n    <button class=\"button is-primary\" type=\"submit\">{{t.action.edit}}</button>\n    {{#on_page}}<a class=\"button\" href=\"{{post.permalink}}\">{{t.back.cancel}}</a>{{/on_page}}\n  </div>\n</form>\n","modal-emoji-info":"{{!\n  **이모지 등록정보** (2026-09-22 요구 · <a href=\"../../../../.claude/milestone-45_emojis.md\">45</a>).\n\n  격자의 칸이 여는 상자에서 오는 자리다. **한 이모지를 크게 보고, 그것이 무엇으로 불리는지를\n  읽고, 권한이 있으면 그 자리에서 고친다.**\n\n  **그림이 5rem이다.** 격자의 칸은 2rem이라 *글줄에 서는 그림*의 크기이고(45 확정 3), 여기는\n  <b>그 하나만 보는 자리</b>라 무엇이 그려져 있는지가 읽혀야 한다.\n\n  **칸은 읽기 전용으로 선다.** 권한이 없으면 잠긴 채이고 있어도 **복사는 된다** — 이 창이\n  답하는 물음의 절반이 *이것을 어떻게 부르는가*이며, 그 답은 <b>골라서 복사할 수 있어야</b> 한다.\n\n  **글자는 권한이 있어도 잠긴다**(`text`). 유니코드 이모지의 글자는 <b>그 행의 바이트에 해당하는\n  것</b>이고, 바이트를 갈아 끼우는 문은 두지 않기로 했다(45 확정 3-1) — 바꾸려면 새로 세운다.\n}}\n<section class=\"emoji-info\">\n  <h2 class=\"subtitle is-6\">{{t.emoji.info}}</h2>\n\n  {{!\n    **크게 선 그림 옆에 화면이 부르는 이름이 선다**(`label`). 칸의 `이름`과 다른 값일 수 있다 —\n    사전이 옮긴 말이 있으면 그것이 이기기 때문이다(45 확정 8). <b>칸은 저장된 것</b>을 들고\n    여기는 <b>보이는 것</b>을 말한다.\n  }}\n  <p class=\"emoji-face large\">\n    {{#url}}<img src=\"{{url}}\" alt=\"{{label}}\">{{/url}}{{#text}}<span class=\"emoji-glyph\">{{glyph}}</span>{{/text}}\n  </p>\n  <p class=\"emoji-face-label help\">{{label}}</p>\n\n  <form data-emoji-info-form=\"{{id}}\">\n    {{!\n      **복사 단추가 칸에 붙어 선다**(`has-addons`) — 칸과 단추 사이가 벌어지면 <b>어느 칸의\n      단추인지</b>를 눈으로 이어야 한다.\n\n      **복사되는 것은 저장된 값이다.** 고쳐 적는 중이라면 아직 그 값이 아니고, 이 단추가\n      말하는 것은 <i>지금 등록되어 있는 것</i>이다 — 적용한 뒤에 복사하면 새 값이 온다.\n    }}\n    <div class=\"field\">\n      <label class=\"label\" for=\"emoji-info-code\">{{t.emoji.shortcode}}</label>\n      <div class=\"field has-addons\">\n        <p class=\"control is-expanded\">\n          <input class=\"input\" id=\"emoji-info-code\" name=\"shortcode\" value=\"{{shortcode}}\"\n                 pattern=\"[a-zA-Z0-9_]{1,64}\" placeholder=\"{{t.emoji.shortcode_hint}}\"\n                 autocomplete=\"off\"{{^emoji_admin}} readonly{{/emoji_admin}}>\n        </p>\n        <p class=\"control\">\n          <button class=\"button\" type=\"button\" data-copy=\":{{shortcode}}:\"\n            ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-copy}}{{> icon-check}}</span><span class=\"nav-label\">{{t.action.copy}}</span></button>\n        </p>\n      </div>\n    </div>\n\n    <div class=\"field\">\n      <label class=\"label\" for=\"emoji-info-name\">{{t.emoji.name}}</label>\n      <div class=\"field has-addons\">\n        <p class=\"control is-expanded\">\n          <input class=\"input\" id=\"emoji-info-name\" name=\"name\" value=\"{{name}}\"\n                 maxlength=\"128\" autocomplete=\"off\"{{^emoji_admin}} readonly{{/emoji_admin}}>\n        </p>\n        <p class=\"control\">\n          <button class=\"button\" type=\"button\" data-copy=\"{{name}}\"\n            ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-copy}}{{> icon-check}}</span><span class=\"nav-label\">{{t.action.copy}}</span></button>\n        </p>\n      </div>\n    </div>\n\n    {{! **글자 칸은 유니코드 갈래에만 선다** — 파일에는 그런 것이 없다(확정 5). }}\n    {{#text}}\n    <div class=\"field\">\n      <label class=\"label\" for=\"emoji-info-text\">{{t.emoji.glyph}}</label>\n      <div class=\"field has-addons\">\n        <p class=\"control is-expanded\">\n          <input class=\"input\" id=\"emoji-info-text\" value=\"{{text}}\" readonly>\n        </p>\n        <p class=\"control\">\n          <button class=\"button\" type=\"button\" data-copy=\"{{text}}\"\n            ><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-copy}}{{> icon-check}}</span><span class=\"nav-label\">{{t.action.copy}}</span></button>\n        </p>\n      </div>\n    </div>\n    {{/text}}\n\n    {{!\n      **고치는 단추는 권한자에게만 선다**(45 확정 3-1) — 없는 사람에게 이 창은 <b>읽고\n      복사하는 자리</b>이고, 눌러도 403인 단추를 세우지 않는다.\n\n      **`삭제하기`는 되돌릴 수 없다**(전역 규칙의 파괴) — 옛 글은 깨지지 않지만(확정 2)\n      그 이모지 자체는 돌아오지 않으므로, 누르면 한 번 묻는다.\n    }}\n    {{#emoji_admin}}\n    <p class=\"control emoji-name-deeds\">\n      <button class=\"button is-primary\" type=\"submit\">{{t.emoji.apply}}</button>\n      <button class=\"button is-danger\" type=\"button\" data-emoji-erase=\"{{id}}\">{{t.action.delete}}</button>\n    </p>\n    {{/emoji_admin}}\n  </form>\n</section>\n","modal-emoji-names":"{{!\n  **이름 배정 창** (2026-09-21 요구 · 45).\n\n  올린 직후의 그림에는 이름이 없다 — 그것들을 한 줄씩 늘어놓고 <b>한 창에서 적는다</b>.\n  한 장씩 고쳐 넣게 하면 여럿을 올린 뜻이 사라진다.\n\n  **폼이다.** 스크립트가 보내지만 마크업이 폼이어야 `Enter`가 저장이 되고, 칸마다 이름표가 선다.\n}}\n<section class=\"emoji-names\">\n  <h2 class=\"subtitle is-6\">{{t.emoji.assign_names}}</h2>\n  <p class=\"help\">{{t.emoji.assign_help}}</p>\n\n  <form data-emoji-names>\n    <ul class=\"emoji-name-list\">\n      {{#items}}\n      <li class=\"emoji-name-row\">\n        <span class=\"emoji-face\">{{#url}}<img class=\"emoji\" src=\"{{url}}\" alt=\"\">{{/url}}{{#text}}{{text}}{{/text}}</span>\n        <label class=\"is-sr-only\" for=\"emoji-name-{{id}}\">{{t.emoji.shortcode}}</label>\n        <input class=\"input\" id=\"emoji-name-{{id}}\" data-emoji-name=\"{{id}}\" type=\"text\"\n               pattern=\"[a-zA-Z0-9_]{1,64}\" placeholder=\"{{t.emoji.shortcode_hint}}\" autocomplete=\"off\">\n      </li>\n      {{/items}}\n    </ul>\n\n    <p class=\"control emoji-name-deeds\">\n      <button class=\"button is-primary\" type=\"submit\">{{t.emoji.assign_do}}</button>\n      <button class=\"button\" type=\"button\" data-emoji-names-cancel>{{t.action.cancel}}</button>\n    </p>\n  </form>\n</section>\n","modal-emoji-pick":"{{!\n  **이모지를 고르는 창** (2026-09-21 요구 · <a href=\"../../../../.claude/milestone-45_emojis.md\">45</a> 확정 4·9).\n\n  **관리 화면과 같은 뼈대다** — 찾는 칸 · 갈래 탭 · 정렬 단추 · 격자 · 쪽 번호. 고르는 일이\n  거기서와 같은 손짓이어야 <b>두 번 배우지 않는다.</b>\n\n  **여기서는 주소를 갈지 않는다**(창이 닫힌다) — 탭도 정렬도 쪽도 <b>단추</b>이고, 누르면\n  창의 속만 다시 선다(에셋 탐색기가 이미 그 규약이다: `inplace`).\n}}\n<section class=\"emoji-picker\">\n  <h2 class=\"subtitle is-6\">{{t.emoji.pick}}</h2>\n\n  <form class=\"emoji-find\" data-emoji-pick-find>\n    <label class=\"is-sr-only\" for=\"emoji-pick-find\">{{t.emoji.find}}</label>\n    <input class=\"input\" id=\"emoji-pick-find\" type=\"search\" name=\"q\" value=\"{{query}}\"\n           placeholder=\"{{t.emoji.find_hint}}\" autocomplete=\"off\">\n    <button class=\"button\" type=\"submit\">{{t.emoji.find}}</button>\n  </form>\n\n  {{!\n    **관리 화면과 같은 마크업이다** (2026-09-21 요구 — <i>탭 모양을 맞춰 달라</i>).\n\n    ~~단추로 세웠다~~ — Bulma의 탭 옷은 `li > a`에 걸리므로 <b>단추로 세우면 그 옷을 입지\n    못한다.</b> 여기서도 링크로 세우고 <b>누름만 스크립트가 가로챈다</b>(쪽 번호와 같은 길):\n    주소가 실려 있어 새 탭으로 열면 관리 화면의 그 자리가 선다.\n  }}\n  <nav class=\"tabs emoji-kinds\" aria-label=\"{{t.emoji.kinds}}\">\n    <ul>\n      {{#kinds}}\n      <li class=\"{{#active}}is-active{{/active}}\">\n        <a href=\"{{href}}\" data-emoji-kind=\"{{key}}\"{{#active}} aria-current=\"page\"{{/active}}>{{label}} <span class=\"count\">{{count}}</span></a>\n      </li>\n      {{/kinds}}\n    </ul>\n  </nav>\n\n  <p class=\"emoji-sorts\">\n    <span class=\"label\">{{t.emoji.sort}}</span>\n    {{#sorts}}\n    <a class=\"button is-small{{#active}} is-active{{/active}}\" href=\"{{href}}\"\n       data-emoji-sort=\"{{key}}\"{{#active}} aria-current=\"true\"{{/active}}>{{label}}</a>\n    {{/sorts}}\n  </p>\n\n  {{^items.length}}<p class=\"empty help\">{{t.emoji.empty}}</p>{{/items.length}}\n  {{> emoji-grid}}\n  {{> pager-numbers}}\n\n  <p class=\"control emoji-name-deeds\">\n    <button class=\"button\" type=\"button\" data-emoji-pick=\"\">{{t.emoji.clear}}</button>\n    <button class=\"button\" type=\"button\" data-emoji-names-cancel>{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-emoji-unicode":"{{!\n  **유니코드에 이름 붙이기** (45 확정 5 · 2026-09-21).\n\n  격자가 파일의 자리가 되면서 글자 하나를 등록하는 길이 이 창으로 왔다 — 파일 고르기와\n  한 항목에 둘 수 없다: 고르는 것이 파일이 아니라 <b>글자</b>이기 때문이다.\n}}\n<section class=\"emoji-unicode\">\n  <h2 class=\"subtitle is-6\">{{t.emoji.add_unicode}}</h2>\n  <p class=\"help\">{{t.emoji.add_unicode_help}}</p>\n\n  <form data-emoji-unicode>\n    <div class=\"field\">\n      <label class=\"label\" for=\"emoji-unicode-code\">{{t.emoji.shortcode}}</label>\n      <div class=\"control\">\n        <input class=\"input\" id=\"emoji-unicode-code\" name=\"shortcode\" required\n               pattern=\"[a-zA-Z0-9_]{1,64}\" placeholder=\"{{t.emoji.shortcode_hint}}\" autocomplete=\"off\">\n      </div>\n    </div>\n    <div class=\"field\">\n      <label class=\"label\" for=\"emoji-unicode-text\">{{t.emoji.glyph}}</label>\n      <div class=\"control\">\n        <input class=\"input\" id=\"emoji-unicode-text\" name=\"text\" required maxlength=\"64\" autocomplete=\"off\">\n      </div>\n    </div>\n    <p class=\"control emoji-name-deeds\">\n      <button class=\"button is-primary\" type=\"submit\">{{t.emoji.add}}</button>\n      <button class=\"button\" type=\"button\" data-emoji-names-cancel>{{t.action.cancel}}</button>\n    </p>\n  </form>\n</section>\n","modal-erase":"{{!\n  **계정 완전 삭제** (2026-09-09 요구 — *연결과 참조가 깨지는 것을 감수하고서라도*).\n\n  ~~하드 삭제는 막혀 있다~~였다: 남의 것이 붙들고 있어 행을 뽑을 수 없고, 이 서비스가 뜻하는\n  *지운다*가 이미 소프트 삭제라는 것이 그때의 근거였다. 그러나 소프트 삭제는 <b>보이지 않게\n  하는 것</b>이지 없애는 것이 아니다 — 본문도 얼굴도 파일도 그대로 있다.\n\n  **셈을 먼저 보인다.** 되돌릴 수 없는 문에서 *정말 지울까요*만 묻는 화면은 사람이 무엇을\n  잃는지 모른 채 누르게 한다.\n\n  **깨뜨리는 것도 적는다.** 남의 화면에 자국이 남는 일이므로, 무엇이 어떻게 남는지를 누르는\n  사람이 먼저 알아야 한다.\n}}\n<div class=\"danger\">\n  <p class=\"who\">{{> iteration-person}}</p>\n\n  <p class=\"hint\">{{{t.erase.warn}}}</p>\n\n  <ul class=\"erasure\">\n    <li>{{t.erase.posts}} <b>{{erasure.posts}}</b></li>\n    <li>{{t.erase.media}} <b>{{erasure.media}}</b></li>\n    {{#erasure.revisions}}<li>{{t.erase.revisions}} <b>{{.}}</b></li>{{/erasure.revisions}}\n    {{#erasure.replies}}<li>{{t.erase.replies}} <b>{{.}}</b></li>{{/erasure.replies}}\n    {{#erasure.shares}}<li>{{t.erase.shares}} <b>{{.}}</b></li>{{/erasure.shares}}\n  </ul>\n\n  <p class=\"hint\">{{{t.erase.leftovers}}}</p>\n\n  {{!\n    **아이디를 적어야 열린다.** 셈을 보이는 것만으로는 손이 먼저 나가고, 되돌릴 수 없는 문에\n    한 걸음을 더 두는 값이 그 한 번의 실수보다 싸다.\n  }}\n  <form method=\"post\" action=\"/@{{handle}}/-/erase\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n    <input type=\"hidden\" name=\"id\" value=\"{{account.id}}\">\n\n    <label for=\"erase-confirm\">{{t.erase.confirm_label}}</label>\n    <input id=\"erase-confirm\" name=\"confirm\" required autocomplete=\"off\" placeholder=\"{{handle}}\">\n\n    <p class=\"error\" data-notice role=\"status\"></p>\n\n    {{!\n      **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n      줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n      **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n      이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n    <div class=\"document-actions\">\n      <button class=\"button is-danger\" type=\"submit\">{{t.erase.do}}</button>\n      {{#on_page}}<a class=\"button\" href=\"/@{{handle}}\">{{t.back.cancel}}</a>{{/on_page}}\n    </div>\n  </form>\n</div>\n","modal-feedfilters":"{{!\n  피드의 <b>필터 격자</b> — 2행 3열 (2026-08-26 요구).\n\n  **~~점 셋 상자~~가 감당하지 못했다.** 필터가 열다섯이고 계층이 둘이라 서른 줄이 되었고,\n  드롭다운의 값은 *서너 개를 즉시 누르는 것*에 있다. 모달은 격자를 <b>격자로</b> 편다 —\n  윗줄이 개인 설정, 아랫줄이 시스템 설정이며 각 줄 안에서 묶음 셋이 세로로 선다.\n  좁은 화면에서는 한 줄로 접힌다(CSS의 일이다).\n\n  **항목의 동작은 그대로다** — 눈으로 켜고 끄고, 이 계층이 값을 쥐고 있으면 `복원`이 붙는다.\n\n  **폼이다.** 자바스크립트가 없으면 같은 주소의 페이지가 같은 것을 낸다.\n}}\n<h2 class=\"title is-5\">{{title}}</h2>\n\n{{#shared}}\n<p class=\"meta help\">{{.}}</p>\n{{/shared}}\n\n{{#emptied}}\n<p class=\"notice warn\">{{t.axis.emptied}}</p>\n{{/emptied}}\n\n{{!\n  **프리셋이 먼저다.** 열다섯을 하나씩 누르는 길만 두면 이 모달이 작은 설정 화면이 된다 —\n  자주 가는 길은 한 줄로 끝나야 하고, 그 길이 곧 사람이 실제로 쓰는 시나리오다.\n\n  **끝의 하나는 갈래가 다르다**(2026-08-26 요구 — `기본값으로 복원`). 앞의 둘은 *어떤 모양으로\n  볼까*를 고르지만 그것은 <b>내가 정한 것을 통째로 걷어</b> 시스템 설정을 다시 물려받게 한다 —\n  줄마다 있는 `복원`의 한 벌짜리다. 그림도 갈린다: 번개가 아니라 되돌리는 화살이다.\n\n  **되돌릴 것이 있을 때만 선다** — 물려받기만 하는 사람에게는 눌러도 아무 일이 없다.\n\n}}\n<div class=\"filter-presets\">\n  {{#presets}}\n  <form method=\"post\" action=\"/-/settings/feed-preset\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <input type=\"hidden\" name=\"screen\" value=\"{{screen}}\">\n    <input type=\"hidden\" name=\"preset\" value=\"{{id}}\">\n    <input type=\"hidden\" name=\"return\" value=\"{{back}}\">\n    <button class=\"button is-small{{#reset}} reset{{/reset}}\" type=\"submit\"><span class=\"mark\" aria-hidden=\"true\">{{^reset}}{{> icon-bolt}}{{/reset}}{{#reset}}{{> icon-rotate}}{{/reset}}</span>{{label}}</button>\n  </form>\n  {{/presets}}\n</div>\n\n{{#sections}}\n<section class=\"filter-section\">\n  {{!\n    **제목과 개수가 한 줄에 선다** (2026-08-28 요구).\n\n    개수는 격자의 칸이 아니라 <b>이 줄 전체에 걸리는 값</b>이라 칸들과 나란히 두지 않는다.\n    ~~프리셋과 같은 높이에 두었다~~ — 그 자리는 계층이 갈리기 *전*이라 칸 둘이 어느 계층의\n    것인지를 곁말로 다시 적어야 했다. 여기서는 <b>제목이 그 말을 이미 하고 있다.</b>\n\n    **빈 칸이 `기본값`이다**(설정 화면과 같은 규칙). 물려받는 중이면 칸이 비고 물려받는 값이\n    흐리게 서므로, 되돌리는 단추가 따로 필요 없다.\n  }}\n  <div class=\"filter-tier-row\">\n    <h3 class=\"filter-tier\">{{label}}</h3>\n    {{#limit}}\n    <form class=\"filter-limit\" method=\"post\" action=\"/-/settings/feed-limit\">\n      <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n      <input type=\"hidden\" name=\"screen\" value=\"{{screen}}\">\n      <input type=\"hidden\" name=\"tier\" value=\"{{tier}}\">\n      <input type=\"hidden\" name=\"return\" value=\"{{back}}\">\n      <label for=\"feed-limit-{{tier}}\">{{t.axis.limit}}</label>\n      <input id=\"feed-limit-{{tier}}\" type=\"number\" inputmode=\"numeric\" min=\"1\" max=\"9999\"\n             name=\"value\" value=\"{{value}}\" placeholder=\"{{placeholder}}\">\n      <button class=\"button is-small\" type=\"submit\">{{t.axis.limit_apply}}</button>\n    </form>\n    {{/limit}}\n  </div>\n  <div class=\"filter-grid\">\n    {{#columns}}\n    <div class=\"filter-column\">\n      <h4 class=\"filter-group\">{{label}}</h4>\n      <ul>\n        {{#filters}}\n        <li>\n          <form class=\"axis\" method=\"post\" action=\"/-/settings/feed-axis\">\n            <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n            <input type=\"hidden\" name=\"key\" value=\"{{key}}\">\n            <input type=\"hidden\" name=\"tier\" value=\"{{tier}}\">\n            <input type=\"hidden\" name=\"return\" value=\"{{back}}\">\n            {{!\n              **눈이 상태를 진다.** 체크는 *골랐다*는 뜻인데 이 줄이 말하는 것은\n              보인다·안 보인다다. 걸 것이 없는 칸은 눌리지 않으므로 `disabled`를 함께 단다.\n            }}\n            <button class=\"toggle\" type=\"submit\" name=\"value\" value=\"{{next}}\" aria-pressed=\"{{pressed}}\"\n                    {{#muted}}disabled{{/muted}}><span class=\"mark\" aria-hidden=\"true\">{{#on}}{{> icon-eye}}{{/on}}{{^on}}{{> icon-eye-off}}{{/on}}</span>{{label}}</button>\n            {{^muted}}\n            {{#overridden}}\n            <button class=\"revert\" type=\"submit\" name=\"value\" value=\"\">{{t.axis.revert}}</button>\n            {{/overridden}}\n            {{/muted}}\n          </form>\n        </li>\n        {{/filters}}\n      </ul>\n    </div>\n    {{/columns}}\n  </div>\n</section>\n{{/sections}}\n","modal-group-gates":"{{!\n  **그룹 설정 모달** — 격리 스위치 (37 확정 8 · 38 확정 1·5 · 39 확정 4).\n\n  ~~그룹 화면의 첫 섹션이었다~~ — 표를 훑으러 온 사람 앞에 칸 일곱이 먼저 섰다. 값은 그대로\n  사이트 설정과 시조 문서에 산다; 만지는 자리만 여기다. 단추 하나가 상자를 저장한다.\n}}\n<section class=\"group-block group-gates\" data-group-root=\"{{root_id}}\">\n  <h2 class=\"subtitle\">{{t.groups.gates}}</h2>\n  <div class=\"field\">\n    <label class=\"label\" for=\"group-auto\">{{t.groups.auto}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"group-auto\" type=\"text\" list=\"group-known\" data-group-auto value=\"{{auto}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.groups.auto_hint}}</p>\n  </div>\n  <div class=\"field\">\n    <label class=\"label\" for=\"docs-groups-read\">{{t.groups.docs_read}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"docs-groups-read\" type=\"text\" list=\"group-known\" data-group-layer=\"docs-read\" value=\"{{docs_read}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.groups.docs_read_hint}}</p>\n  </div>\n  <div class=\"field\">\n    <label class=\"label\" for=\"docs-groups-write\">{{t.groups.docs_write}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"docs-groups-write\" type=\"text\" list=\"group-known\" data-group-layer=\"docs-write\" value=\"{{docs_write}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.groups.docs_write_hint}}</p>\n  </div>\n  <div class=\"field\">\n    <label class=\"label\" for=\"asset-pool-read\">{{t.groups.layer_read}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"asset-pool-read\" type=\"text\" list=\"group-known\" data-group-layer=\"read\" value=\"{{layer_read}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.groups.layer_read_hint}}</p>\n  </div>\n  <div class=\"field\">\n    <label class=\"label\" for=\"asset-pool-write\">{{t.groups.layer_write}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"asset-pool-write\" type=\"text\" list=\"group-known\" data-group-layer=\"write\" value=\"{{layer_write}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.groups.layer_write_hint}}</p>\n  </div>\n  <div class=\"field\">\n    <label class=\"label\" for=\"asset-item-read\">{{t.groups.item_read}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"asset-item-read\" type=\"text\" list=\"group-known\" data-group-layer=\"item-read\" value=\"{{item_read}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.groups.item_read_hint}}</p>\n  </div>\n  <div class=\"field\">\n    <label class=\"label\" for=\"asset-item-write\">{{t.groups.item_write}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"asset-item-write\" type=\"text\" list=\"group-known\" data-group-layer=\"item-write\" value=\"{{item_write}}\" autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{t.groups.item_write_hint}}</p>\n  </div>\n  <datalist id=\"group-known\">{{#names}}<option value=\"{{.}}\"></option>{{/names}}</datalist>\n  <p class=\"group-deeds\">\n    <button class=\"button is-primary\" type=\"button\" data-group-auto-save>{{t.groups.save}}</button>\n    <button class=\"button\" type=\"button\" data-group-gates-cancel>{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-group-merge":"{{!\n  **고른 그룹들을 하나의 이름으로** (39 확정 4 — 병합 모달). 권한이 다른 그룹을 합치면\n  **결과 권한을 미리 보인 뒤 진행한다**(확정 1) — 결과는 받는 쪽의 것이다.\n}}\n<section class=\"group-move\">\n  <ul class=\"group-merge-from\">\n    {{#names}}<li><span class=\"group-badge\">{{name}}</span>{{#permissions}} <span class=\"has-text-grey\">{{.}}</span>{{/permissions}}</li>{{/names}}\n  </ul>\n  <div class=\"field\">\n    <label class=\"label\" for=\"group-merge-to\">{{t.groups.merge_into}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"group-merge-to\" type=\"text\" list=\"group-merge-names\" data-merge-to autocomplete=\"off\">\n    </div>\n    <p class=\"help\" data-merge-preview></p>\n  </div>\n  <datalist id=\"group-merge-names\">{{#candidates}}<option value=\"{{.}}\"></option>{{/candidates}}</datalist>\n  <p class=\"group-deeds\">\n    <button class=\"button is-primary\" type=\"button\" data-merge-act=\"save\">{{t.groups.merge}}</button>\n    <button class=\"button\" type=\"button\" data-merge-act=\"cancel\">{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-group-move":"{{!\n  **그룹을 옮기거나 합친다**\n  (<a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a> 확정 5 · 2026-09-17 요구).\n\n  **한 조각이 둘을 진다.** 하는 일은 같고(*이 이름을 저 이름으로*) 갈리는 것은 <b>받는\n  이름이 이미 있는가</b>뿐이다 — 없으면 옮기는 것이고 있으면 합쳐진다. 그 사실을 미리\n  말하는 것이 이 창이 하는 일이다.\n\n  **쓰이는 모든 자리에서 바뀐다** — 계정의 그룹도 자산의 라벨도 함께 간다.\n}}\n<section class=\"group-move\">\n  <p class=\"group-move-from\">\n    <span class=\"group-badge\">{{name}}</span>\n  </p>\n\n  <div class=\"field\">\n    <label class=\"label\" for=\"group-move-to\">{{to_label}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"group-move-to\" type=\"text\" list=\"group-move-names\"\n             data-group-move-to autocomplete=\"off\">\n    </div>\n    <p class=\"help\">{{hint}}</p>\n  </div>\n\n  <datalist id=\"group-move-names\">\n    {{#names}}<option value=\"{{.}}\"></option>{{/names}}\n  </datalist>\n\n  <p class=\"group-deeds\">\n    <button class=\"button is-primary\" type=\"button\" data-group-move-act=\"save\">{{deed}}</button>\n    <button class=\"button\" type=\"button\" data-group-move-act=\"cancel\">{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-group":"{{!\n  **그룹 하나를 여는 창** (<a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a> ·\n  2026-09-17 요구).\n\n  **탭이 셋이다** — 등록 정보(뱃지) · 소속 사용자 · 소속 문서. 그룹에 대해 물을 것이 그\n  셋이고, 한 화면에 늘어놓으면 <b>명부가 길어질수록 꾸미는 칸이 멀어진다</b>.\n\n  **여는 일은 마크업이 맡는다**(전역 규칙) — `<details>`가 아니라 라디오다: 탭은 <b>하나만\n  열린다</b>는 점이 아코디언과 다르고, 그 배타성을 스크립트 없이 내는 것이 라디오다.\n}}\n<section class=\"group-modal\" data-group-panel=\"{{name}}\">\n  <h2 class=\"group-modal-title\">\n    {{! **색을 걷었다**(47 확정 4) — 뱃지가 이모지 하나가 된 순간 색이 설 자리가 없다. }}\n    <span class=\"group-badge{{^badge}} is-off{{/badge}}\">{{{badge_html}}}{{^badge_html}}{{name}}{{/badge_html}}</span>\n    <span>{{name}}</span>\n  </h2>\n\n  <div class=\"group-tabs\">\n    <input type=\"radio\" name=\"group-tab\" id=\"group-tab-info\" checked>\n    <label for=\"group-tab-info\">{{t.groups.tab_info}}</label>\n\n    <input type=\"radio\" name=\"group-tab\" id=\"group-tab-people\">\n    <label for=\"group-tab-people\">{{t.groups.tab_people}}</label>\n\n    <input type=\"radio\" name=\"group-tab\" id=\"group-tab-docs\">\n    <label for=\"group-tab-docs\">{{t.groups.tab_docs}}</label>\n\n    {{! ── 등록 정보 ── }}\n    <div class=\"group-tab-body\" data-group-tab=\"info\">\n      {{! **표시 이름 칸을 걷었다** (2026-09-20 교정) — 이름이 곧 뱃지다. 이름을 바꾸는 일은 `이동`이 진다. }}\n      {{!\n        **뱃지에 서는 것은 이모지다** (<a href=\"../../../../.claude/milestone-45_emojis.md\">45</a>\n        확정 4 · 2026-09-21 요구). ~~자유 텍스트 칸~~ → 고르는 판이다. 담기는 자리는 그대로\n        라벨 칸이고(표를 고치지 않는다) 그 값은 `:코드:`라 <b>본문과 같은 치환</b>을 지난다.\n\n        **고르기는 창이 진다**(2026-09-21 요구 — ~~펼침~~). 이 뷰어의 모달은 `<dialog>` 하나라\n        둘째를 띄우면 첫째가 닫히는데, <b>고치던 값을 들고 갔다가 되돌려 놓으면</b> 그 제약이\n        풀린다 — 고른 코드는 창을 닫으며 이 칸에 담긴다.\n\n        **격자는 `/-/emojis`와 같은 조각이다**(`emoji-grid`).\n      }}\n      <div class=\"field\">\n        <span class=\"label\">{{t.emoji.badge}}</span>\n        {{!\n          **칸 둘이 숨어 있다** (45 확정 19) — 갈래와 값. ~~`:이름:` 하나를 담았다~~:\n          그 코드는 <b>서버의 표에만 있는 이름</b>이라 읽는 쪽이 표를 들어야 풀렸다.\n        }}\n        <input type=\"hidden\" data-group-field=\"badge_kind\" value=\"{{badge_kind}}\">\n        <input type=\"hidden\" data-group-field=\"badge_value\" value=\"{{badge_value}}\">\n        <div class=\"control group-badge-pick\">\n          {{!\n            **미리보기는 갈래와 값으로 선다** (2026-09-23 보고 — *고르면 '없음' 처리된다*).\n\n            ~~굽힌 것(`badge_html`)을 세웠다~~ — 그것은 <b>저장된 뒤에야</b> 있는 값이라, 막\n            고른 참에는 비어 있어 *없음*이 섰다. 여기서는 <b>고르는 중인 값</b>을 그려야 한다.\n\n            **마크업을 스크립트가 짓지 않는다** — 굽는 규칙이 뷰어에 한 벌 더 생기면 코어의\n            것과 갈린다(45 확정 19). 템플릿이 갈래를 보고 세운다.\n          }}\n          <span class=\"group-badge-preview\" data-group-badge>{{#badge_value}}{{#badge_is_image}}<img class=\"emoji\" src=\"{{badge_value}}\" alt=\"{{name}}\">{{/badge_is_image}}{{^badge_is_image}}{{badge_value}}{{/badge_is_image}}{{/badge_value}}{{^badge_value}}{{t.emoji.none}}{{/badge_value}}</span>\n          <button class=\"button is-light\" type=\"button\" data-emoji-open>{{t.emoji.pick}}</button>\n        </div>\n      </div>\n\n      {{!\n        **모두가 드는 그룹의 뱃지는 값이 없다** — 모든 이름 앞에 같은 표가 서는 일이므로\n        그때 끈다(확정 7이 *선다*고 정한 것의 예외를 여기서 사람이 고른다).\n      }}\n      <label class=\"checkbox group-badge-on\">\n        <input type=\"checkbox\" data-group-field=\"badge\" {{#badge}}checked{{/badge}}>\n        <span>{{t.groups.badge_on}}</span>\n      </label>\n      {{!\n        **관리권한 일곱** (39 확정 1) — 이 그룹에 든 사람이 무엇을 관리하는가.\n\n        **서비스 권한자만 고친다.** 그 밖의 사람에게는 잠긴 채로 선다 — 감추면 <i>이 그룹이\n        무엇을 할 수 있는가</i>를 볼 길이 없고, 켜 두면 눌러도 403인 상자가 된다.\n        **서비스는 나머지를 내포한다** — 그 한 줄이 켜지면 아래 여섯은 뜻이 없다.\n      }}\n      <fieldset class=\"field group-permissions\"{{^can_grant}} disabled{{/can_grant}}>\n        <legend class=\"label\">{{t.groups.permissions}}</legend>\n        {{#permissions}}\n        <label class=\"checkbox\">\n          <input type=\"checkbox\" data-group-perm=\"{{key}}\"{{#checked}} checked{{/checked}}{{^can_grant}} disabled{{/can_grant}}>\n          <span>{{label}}</span>\n        </label>\n        {{/permissions}}\n        <p class=\"help\">{{#can_grant}}{{t.groups.permissions_hint}}{{/can_grant}}{{^can_grant}}{{t.groups.permissions_locked}}{{/can_grant}}</p>\n      </fieldset>\n\n      <div class=\"field\">\n        <label class=\"label\" for=\"group-note\">{{t.groups.note_label}}</label>\n        <div class=\"control\">\n          <textarea class=\"textarea\" id=\"group-note\" rows=\"2\" data-group-field=\"note\">{{note}}</textarea>\n        </div>\n        <p class=\"help\">{{t.groups.note_hint}}</p>\n      </div>\n\n      {{!\n        **끝내는 단추와 이 그룹에 하는 일이 한 줄에 선다** (2026-09-17 요구).\n\n        **왼쪽은 이 창을 끝내는 일**(저장·취소)이고 **오른쪽은 이 그룹 자체에 하는 일**\n        (옮기기·합치기·걷기)이다 — 줄 하나에 두되 <b>자리가 갈라 말한다</b>: 같은 무게로\n        나란히 두면 *취소*와 *제거*가 이웃해 선다.\n\n        **걷기는 되돌릴 수 없다**(`is-danger`). 옮기고 합치는 일은 반대로 한 번 더 부르면\n        제자리로 오지만, 걷은 것은 <i>누가 그 그룹이었는지</i>가 남지 않는다 — 누르기 전에\n        화면이 그 무게로 묻는다.\n      }}\n      <p class=\"group-deeds group-deeds-split\">\n        <span class=\"group-deeds-end\">\n          <button class=\"button is-primary\" type=\"button\" data-group-act=\"save\">{{t.groups.save}}</button>\n          <button class=\"button\" type=\"button\" data-group-act=\"cancel\">{{t.action.cancel}}</button>\n        </span>\n\n        <span class=\"group-deeds-own\">\n          <button class=\"button is-light\" type=\"button\" data-group-act=\"move\">{{t.groups.move}}</button>\n          <button class=\"button is-light\" type=\"button\" data-group-act=\"merge\">{{t.groups.merge}}</button>\n          <button class=\"button is-danger\" type=\"button\" data-group-act=\"remove\">{{t.groups.remove}}</button>\n        </span>\n      </p>\n    </div>\n\n    {{! ── 소속 사용자 ── }}\n    <div class=\"group-tab-body\" data-group-tab=\"people\">\n      {{#people.length}}\n      <ul class=\"group-members\">\n        {{#people}}\n        <li><a href=\"/@{{handle}}\">@{{handle}}</a></li>\n        {{/people}}\n      </ul>\n      {{/people.length}}\n      {{^people.length}}\n      <p class=\"is-waiting\">{{t.groups.no_people}}</p>\n      {{/people.length}}\n    </div>\n\n    {{! ── 소속 문서 ── }}\n    <div class=\"group-tab-body\" data-group-tab=\"docs\">\n      {{#docs.length}}\n      {{!\n        **두 라벨 어느 쪽이든 걸린다** — 읽기에만 든 것과 쓰기에만 든 것이 빠지면\n        <i>어긋난 라벨</i>이 바로 이 화면에서 보이지 않게 된다.\n      }}\n      <ul class=\"group-docs\">\n        {{#docs}}\n        <li><a href=\"/:{{name}}\">{{name}}</a></li>\n        {{/docs}}\n      </ul>\n      {{/docs.length}}\n      {{^docs.length}}\n      <p class=\"is-waiting\">{{t.groups.no_docs}}</p>\n      {{/docs.length}}\n    </div>\n  </div>\n</section>\n","modal-revisions":"{{!\n  붙들 판을 고르는 조각 — 모달과 전체 페이지가 같은 것을 쓴다 (2026-08-20 요구).\n\n  **이력 화면과 같은 목록을 다르게 쓴다.** 그쪽은 읽으라고 만든 자리라 고르는 단추가 없다 —\n  여기서는 줄마다 폼이 붙고, 고른 판이 이 조각이 붙들 판이 된다.\n\n  **지금 붙들고 있는 판에는 단추가 서지 않는다.** 눌러도 아무 일이 없는 자리를 만들지 않는다.\n}}\n<div class=\"revision-picker\">\n  {{#following}}\n  <p class=\"hint\">{{{t.revisions.follows}}}</p>\n  {{/following}}\n  {{^following}}\n  <p class=\"hint\">{{{pinned_note}}}</p>\n  {{/following}}\n\n  <ol class=\"revisions\">\n    {{#revisions}}\n    <li class=\"revision\" data-key=\"revision\" data-value=\"{{seq}}\">\n      <p class=\"when\">\n        <span class=\"seq\">{{seq_label}}</span>\n        <time datetime=\"{{created_at}}\"{{#created_title}} title=\"{{.}}\"{{/created_title}}>{{created_display}}</time>\n        {{#current}}<span class=\"mark\">{{t.revision.in_use}}</span>{{/current}}\n      </p>\n      <div class=\"excerpt content\">{{{content_html}}}</div>\n      <form method=\"post\" action=\"{{document.permalink}}/-/items/{{item_id}}/pin\">\n        <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n        <input type=\"hidden\" name=\"revision\" value=\"{{seq}}\">\n        <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n        <button class=\"button is-small\" type=\"submit\">{{t.revision.use_this}}</button>\n      </form>\n    </li>\n    {{/revisions}}\n  </ol>\n</div>\n","modal-tag-merge":"{{!\n  **고른 문서태그들을 하나의 이름으로** (39 확정 4). 쓰이는 모든 자리에서 바뀐다 — 문서 마디의\n  에셋 태그와 에셋의 태그.\n}}\n<section class=\"group-move\">\n  <ul class=\"group-merge-from\">\n    {{#names}}<li><span class=\"tag\">{{.}}</span></li>{{/names}}\n  </ul>\n  <div class=\"field\">\n    <label class=\"label\" for=\"tag-merge-to\">{{t.specials.merge_into}}</label>\n    <div class=\"control\">\n      <input class=\"input\" id=\"tag-merge-to\" type=\"text\" data-tag-merge-to autocomplete=\"off\">\n    </div>\n  </div>\n  <p class=\"group-deeds\">\n    <button class=\"button is-primary\" type=\"button\" data-tag-merge-act=\"save\">{{t.groups.merge}}</button>\n    <button class=\"button\" type=\"button\" data-tag-merge-act=\"cancel\">{{t.action.cancel}}</button>\n  </p>\n</section>\n","modal-widen":"{{!\n  **비공개 글을 넓히는 자리** (M12).\n\n  **확인 화면이 있는 이유는 되돌릴 수 없어서다.** 좁히는 길이 없으므로(코어가 넓히는\n  방향으로만 연다) 이것은 지우기와 같은 결의 한 번뿐인 일이다 — 그래서 액션 링크가\n  곧바로 보내지 않고 이 화면을 먼저 세운다.\n\n  **고를 것이 있다.** 지우기는 예/아니오지만 여기는 *어디까지 넓힐 것인가*가 남는다 —\n  목록은 서버가 준다(`choices`), 화면이 값을 적어 두면 코어가 아는 것과 갈린다.\n}}\n<div class=\"danger\">\n  <p class=\"hint\">{{t.post.widen_hint}}</p>\n\n  {{#post}}{{> body-quoted}}{{/post}}\n\n  <form method=\"post\" action=\"{{post.permalink}}/-/widen\">\n    <input type=\"hidden\" name=\"csrf\" value=\"{{csrf}}\">\n    <input type=\"hidden\" name=\"return\" value=\"{{return_to}}\">\n\n    <label for=\"widen-visibility\">{{t.visibility.label}}</label>\n    <select id=\"widen-visibility\" name=\"visibility\">\n      {{#choices}}\n      <option value=\"{{value}}\">{{label}}</option>\n      {{/choices}}\n    </select>\n\n    {{!\n      **끝내는 것과 그만두는 것이 한 줄에 선다** (2026-09-16 요구) — 같은 물음의 두 답인데\n      줄이 갈리면 고르는 일이 두 번으로 읽힌다.\n\n      **그만두는 길은 화면에만 선다**(`on_page`). 모달에는 스크립트가 붙이는 `닫기`가\n      이미 있어, 여기 하나를 더 두면 <b>나가는 문이 둘</b>이 된다.\n      }}\n    <div class=\"document-actions\">\n      <button class=\"button is-danger\" type=\"submit\">{{t.action.widen}}</button>\n      {{#on_page}}<a class=\"button\" href=\"{{post.permalink}}\">{{t.back.cancel}}</a>{{/on_page}}\n    </div>\n  </form>\n</div>\n","name-badged":"{{!\n  **뱃지를 단 이름** (<a href=\"../../../../.claude/milestone-45_emojis.md\">45</a> 확정 19).\n\n  **코어는 재료 둘을 낸다** — `badge_html`(굽힌 뱃지)과 `display_name`(평문 이름). 엮는 일은\n  뷰어의 것이고, <b>그 엮음이 이 조각 하나</b>다: 자리마다 손으로 이으면 새 화면이 설 때마다\n  빠진다(47이 막으려던 그것이다).\n\n  **이스케이프가 조각마다 옳다.** 뱃지는 코어가 지은 마크업이라 세 겹 중괄호로 그대로 내고,\n  이름은 <b>사람이 적은 글자</b>라 두 겹으로 escape된다 — 하나로 합쳐 두면 그 갈림이 사라진다.\n\n  **사이에 빈칸이 없다**(2026-09-21 요구) — 뱃지로 서는 글자와 그림은 제 여백을 지고 있다.\n}}\n{{{badge_html}}}{{display_name}}\n","nav-corpus":"{{!\n  **글감 탐색기** — 편집 모드의 사이드바 (31 확정 12).\n\n  **서버가 고르지 않는다.** 카드에 담기는 것은 작성자·날짜·본문뿐이고 그것은 피드가 이미\n  내주는 것이라, 코어의 피드 API를 그대로 쓴다 — 문서 레이어에 글감을 재는 코드를 두지\n  않는다.\n\n  **끌어다 놓는 대신 누른다.** `textarea` 안의 드롭 지점에서 커서 자리를 얻는 길이 브라우저마다\n  갈리고, <b>누르면 지금 커서 자리에 들어가는 것</b>이 더 정확하고 손에도 붙는다.\n\n  **감춰 두고 스크립트가 보인다** — 목록도 삽입도 스크립트의 일이다.\n\n  **훑는 한 벌은 조각이 진다**(`corpus-browser`, 2026-09-13). 모달이 같은 것을 쓴다 —\n  여기 베껴 두면 한쪽만 고쳐지는 날이 온다.\n}}\n{{!\n  **자리와 폭은 `site-nav`가 진다.** 둘러보기가 서던 기둥에 그대로 서므로 그 옷을\n  입는다 — 새 이름을 짓는 대신 <b>이미 그 일을 하는 이름</b>을 쓴다.\n}}\n<aside class=\"site-nav corpus\" id=\"site-nav\" data-corpus hidden>\n  {{!\n    **제목은 스타일시트가 감춘다** (2026-09-07 요구). 읽어 주는 길은 남겨 두어야 하므로\n    마크업에서 빼지 않고 잘라 둔다 — 탭의 낱말을 다루는 방식과 같다.\n  }}\n  <h2 class=\"corpus-title\">{{t.document.corpus}}</h2>\n  {{> corpus-browser}}\n</aside>\n","pager-numbers":"{{!\n  **번호 페이저** (2026-09-15 요구).\n\n  `{첫}…{지금 둘레 다섯}…{끝}` 꼴이다. 증분 로딩과 달리 <b>어디쯤인지</b>와 <b>얼마나\n  남았는지</b>가 함께 보이고, 그래서 쪽 하나를 다시 찾아올 수 있다.\n\n  **생략은 자리를 말한다.** 건너뛴 구간에 `…`이 서면 <i>사이가 있다</i>는 것이 읽히고,\n  그것 없이 번호만 이으면 1 다음이 곧 12인 것처럼 보인다.\n\n  **지금 쪽은 링크가 아니다.** 눌러도 같은 자리인 링크는 *조용히 아무 일도 하지 않는 단추*다.\n\n  **제자리에서 넘기는 자리도 있다**(`inplace` — 2026-09-16 요구). 모달은 주소를 갈지 않고\n  속만 가는데, <b>번호는 같은 모양으로 서야 한다</b> — 같은 일에 두 생김새를 두면 사람이\n  두 번 배운다. 그 자리에는 `data-page`가 붙고 <b>주소는 그대로 남는다</b>: 새 탭으로 열면\n  풀 화면의 그 쪽이 선다.\n}}\n{{#pages.length}}\n<nav class=\"pager pager-numbers\" aria-label=\"{{t.loader.label}}\">\n  <ul>\n    {{#pages}}\n    <li>\n      {{#gap}}<span class=\"pager-gap\">…</span>{{/gap}}\n      {{^gap}}\n        {{#current}}<span class=\"pager-now\" aria-current=\"page\">{{number}}</span>{{/current}}\n        {{^current}}<a href=\"{{href}}\"{{#inplace}} data-page=\"{{number}}\"{{/inplace}}>{{number}}</a>{{/current}}\n      {{/gap}}\n    </li>\n    {{/pages}}\n  </ul>\n</nav>\n{{/pages.length}}\n","post-media":"{{!\n  첨부 목록 — **글·인용·판이 나눠 쓴다**\n  (<a href=\"../../../../.claude/milestone-43_media_families.md\">43</a> 확정 5·6).\n\n  **종류가 그림을 가른다.** 그림은 미리보기이고 **누르면 오버레이**(`data-attachment` — 모달이\n  아니다). **영상과 소리는 그 자리에서 튼다**(2026-09-20 요구 — ~~영상도 오버레이~~) — 영상은\n  `controls`를 단 `<video>`, 소리 하나는 `<audio>`, 소리 둘 이상은 **재생목록**이다. 셋이 아닌\n  것은 글자 링크로 남는다. **소리 하나에는 파일 이름을 적지 않는다**(같은 요구).\n\n  **재생목록은 재생기 + 목록(제목·길이)이다**(같은 요구 — ~~단추 나열~~). 길이는 코어가 모르므로\n  스크립트가 트랙의 메타데이터를 읽어 채운다(`data-track-length`). 마크업은 문서의\n  `special-playlist`와 같다 — 갈아타는 스크립트(`data-playlist` · `data-track`)가 하나다.\n}}\n{{#media.length}}\n<ul class=\"media\">\n  {{#media}}\n  {{#is_link}}\n  <li class=\"card\">\n    <a class=\"link-card\" href=\"{{url}}\">\n      {{#preview_url}}\n      <span class=\"cover-wrap\">\n        <img class=\"cover\" src=\"{{.}}\" alt=\"\" loading=\"lazy\">\n        {{#is_playable}}\n        <span class=\"play\" aria-hidden=\"true\">{{> icon-play}}</span>\n        {{/is_playable}}\n      </span>\n      {{/preview_url}}\n      <span class=\"card-body\">\n        <strong class=\"card-title\">{{#title}}{{title}}{{/title}}{{^title}}{{url}}{{/title}}</strong>\n        {{#description}}<span class=\"card-description\">{{.}}</span>{{/description}}\n        {{#source}}<span class=\"card-source\">{{.}}</span>{{/source}}\n      </span>\n    </a>\n  </li>\n  {{/is_link}}\n  {{^is_link}}\n  {{^in_playlist}}\n  {{#is_video}}\n  <li class=\"video\">\n    <video controls preload=\"metadata\" playsinline src=\"{{url}}\" title=\"{{description}}\"></video>\n  </li>\n  {{/is_video}}\n  {{#is_audio}}\n  <li class=\"audio\">\n    <audio controls preload=\"metadata\" src=\"{{url}}\" title=\"{{description}}\"></audio>\n  </li>\n  {{/is_audio}}\n  {{^is_video}}{{^is_audio}}\n  <li>\n    <a href=\"{{url}}\" data-attachment=\"{{id}}\">\n      {{#preview_url}}<img src=\"{{.}}\" alt=\"{{description}}\" loading=\"lazy\">{{/preview_url}}\n      {{^preview_url}}{{#title}}{{title}}{{/title}}{{^title}}{{url}}{{/title}}{{/preview_url}}\n    </a>\n  </li>\n  {{/is_audio}}{{/is_video}}\n  {{/in_playlist}}\n  {{/is_link}}\n  {{/media}}\n</ul>\n{{/media.length}}\n{{#playlist}}\n<figure class=\"playlist\" data-playlist>\n  <audio controls preload=\"metadata\" src=\"{{first}}\" data-playlist-player></audio>\n  {{!\n    **줄이 곧 단추다** — 전역 규칙의 선택 옷(`button is-light`)을 입지 않는다. 목록의 한 줄로 서야\n    제목과 길이가 칸을 맞추고(요구), 단추 나열은 그 둘을 나란히 세울 자리가 없다. 덮어쓰는 이유가 이것이다.\n  }}\n  <ol class=\"tracks\">\n    {{#tracks}}\n    <li><button type=\"button\" class=\"track{{#is_active}} is-active{{/is_active}}\" data-track=\"{{url}}\"><span class=\"track-title\">{{title}}</span><span class=\"track-length\" data-track-length></span></button></li>\n    {{/tracks}}\n  </ol>\n</figure>\n{{/playlist}}\n","post-visibility":"{{!\n  **공개 범위 표시** — 포스트와 인용 카드가 함께 쓴다 (2026-09-01에 뽑았다).\n\n  **인용 카드가 포스트와 같은 머리를 갖게 되면서 뽑았다**(요구: *레이아웃을 포스트와 동일하게*).\n  그림 여섯이 마크업에 두 벌 서 있으면 하나를 고칠 때 다른 하나가 남고, **그 둘이 갈리는\n  것을 눈으로 알아채기 어렵다** — 같은 뜻을 두 곳에 적지 않는다는 규칙이 마크업에도 걸린다.\n\n  **`visibility`·`visibility_label`·`visibility_is`를 쓴다.** 부르는 쪽이 그 셋을 갖고\n  있어야 하고, 인용 카드의 뷰가 그래서 같은 셋을 낸다.\n\n  이름표 규약(03d `값에 붙는 이름표`)·낱말을 눈에서만 가리는 처리·가리키면 뜨는 `title`은\n  전부 원래 자리에서 옮겨 온 그대로다.\n}}\n<span class=\"corner\">\n{{!\n  **메시지에는 받는 사람이 곁에 선다**(2026-09-08 요구).\n\n  글의 머리는 언제나 <b>쓴 사람</b>이라, 내가 보낸 메시지에는 내 이름만 늘어선다 — 누구와의\n  대화인지를 지는 것은 이쪽이고 그래서 <b>봉투 그림 곁</b>이 자리다.\n\n  **코어가 이름과 얼굴을 함께 준다**(`recipients`) — 아이디만 있던 때는 이 줄을 세워도\n  <i>@아이디</i>밖에 그리지 못했다.\n\n  **둘을 한 칸에 담는다**(`.corner` · 2026-09-08 요구 — *봉투 아이콘 옆으로*). 공개 범위는\n  <b>우상귀에 못박혀 있고</b>(절대 위치) 그 곁에 서려면 같은 칸에 들어와야 한다 — 밖에 두면\n  흐름에 남아 머리의 딴 자리에 섰다.\n\n  **공개 범위 그림이 맨 뒤다**(같은 날 요구). 그 자리는 <b>모든 글이 쓰는 자리</b>이므로\n  글마다 같은 곳에 있어야 하고, 메시지에만 있는 것이 그 앞에 붙는다 — 그림이 줄마다 다른\n  자리에 서면 훑을 때 눈이 그것을 찾아다닌다.\n}}\n{{#recipients.length}}\n<span class=\"to-people\">\n  {{#recipients}}{{> iteration-person}}{{/recipients}}\n</span>\n{{/recipients.length}}\n<span class=\"visibility\" title=\"{{visibility_label}}\"\n      data-key=\"post.visibility\" data-value=\"{{visibility}}\">\n  <span class=\"nav-icon\" aria-hidden=\"true\">\n  {{#visibility_is.federated}}{{> icon-globe}}{{/visibility_is.federated}}\n  {{#visibility_is.server}}{{> icon-eye}}{{/visibility_is.server}}\n  {{#visibility_is.followers}}{{> icon-people}}{{/visibility_is.followers}}\n  {{#visibility_is.quiet}}{{> icon-speaker-off}}{{/visibility_is.quiet}}\n  {{#visibility_is.direct}}{{> icon-envelope}}{{/visibility_is.direct}}\n  {{#visibility_is.private}}{{> icon-lock}}{{/visibility_is.private}}\n  </span>\n  <span class=\"nav-label\">{{visibility_label}}</span>\n</span>\n</span>\n","search-head":"{{!\n  **찾는 머리 — 탭줄과 칸** (2026-09-15 요구).\n\n  **검색 결과 화면과 에셋 풀이 나눠 쓴다.** 에셋을 찾는 일이 <b>풀 화면에서 일어나므로</b>\n  (`/-/search/media`는 그리로 보낸다) 그 화면도 같은 머리를 인다 — 찾는 자리가 화면마다\n  다르게 생기면 <i>같은 일을 두 번 배워야 한다.</i>\n\n  **제목은 이 조각이 지지 않는다.** 화면마다 부르는 이름이 다르고(`찾기`·`에셋 풀`),\n  그것은 그 화면의 말이다.\n}}\n{{!\n  **탭이 하나뿐이면 띠가 서지 않는다** — 갈 곳이 하나인 탭줄은 고를 것이 없는 선택지다.\n  서버가 그 판단을 하고 여기서는 받은 것만 그린다. M09가 문서 탭을 열어 지금은 둘이다.\n}}\n{{#tabs.length}}\n{{!\n  **탭줄은 Bulma의 `tabs`다** (2026-08-25 요구). ~~`.feed-tabs`~~라는 우리 이름을 달고\n  같은 모양을 손으로 그리고 있었다 — 설정 탭이 이미 `tabs`를 입고 있어(`settings-tabs tabs`)\n  <b>같은 것이 화면마다 다른 규칙으로 서 있었다.</b>\n\n  **`aria-current`는 그대로 둔다.** Bulma가 아는 것은 `is-active`(눈에 보이는 표시)뿐이고\n  <b>지금 어느 자리인가를 말하는 것은 그것이 아니다</b> — 설정 탭도 둘을 함께 단다.\n}}\n<nav class=\"tabs\" aria-label=\"{{t.nav.search}}\">\n  <ul>\n    {{#tabs}}\n    <li{{#active}} class=\"is-active\"{{/active}}><a href=\"{{path}}\"{{#active}} aria-current=\"page\"{{/active}}>{{title}}</a></li>\n    {{/tabs}}\n  </ul>\n</nav>\n{{/tabs.length}}\n\n{{!\n  **칸이 탭 바로 뒤에 선다** (2026-08-25 요구).\n\n  <b>고쳐 쓸 것이 눈앞에 있어야 한다.</b> 여기까지 온 사람은 결과를 보고 나서 낱말을 고치는데,\n  그러자고 헤더의 드롭다운을 다시 여는 것은 <i>같은 일을 두 번</i>이다. 탭이 대상을 말하고\n  칸이 낱말을 받으니 <b>이 화면 안에서 다시 찾는 일이 닫힌다.</b>\n\n  **가는 곳은 지금 보고 있는 대상이다**(`base`). 탭이 이미 그것을 골라 놓았으므로 여기에\n  스코프를 다시 세우지 않는다 — 같은 것을 한 화면에서 두 번 묻는 꼴이 된다.\n\n  **주소는 이스케이프하지 않는다** — 세 겹 중괄호다. Mustache가 `/`를 `&#x2F;`로 바꾸는데\n  브라우저는 그것도 읽지만 <b>주소가 주소로 보이지 않는다</b>. 값은 서버가 고른 세 상수 중\n  하나이므로 사람이 넣은 글자가 여기 올 수 없다(`header-search`와 같은 근거).\n\n  **문법 표는 여전히 서지 않는다.** 표가 서는 자리는 헤더의 드롭다운 하나이고, 그것을 여기에\n  또 그리면 같은 표가 한 화면에 둘이 된다.\n}}\n<form class=\"search field has-addons\" action=\"{{{base}}}\" method=\"get\" role=\"search\">\n  <p class=\"control is-expanded\">\n    <input class=\"input is-small\" type=\"search\" name=\"q\" value=\"{{query}}\"\n           placeholder=\"{{t.nav.search}}\" autocomplete=\"off\" data-autocomplete>\n  </p>\n  <p class=\"control\">\n    <button class=\"button is-small\" type=\"submit\">{{t.action.search}}</button>\n  </p>\n</form>\n","sidebar-all-guests":"{{!\n  어느 화면에서든 서는 칸 — **게스트** (`viewer.sidebar_all_guests`).\n\n  **처음 온 사람에게 하는 말이다.** 로그인한 사람의 것과 문서가 갈릴 수 있으므로 자리를\n  따로 둔다 — 같은 것을 세우고 싶으면 두 설정에 같은 경로를 적는다.\n}}\n{{#sidebar.all}}<div class=\"sidebar-division doc-sidebar content\">{{&.}}</div>{{/sidebar.all}}\n","sidebar-all-users":"{{!\n  어느 화면에서든 서는 칸 — **로그인한 사람** (`viewer.sidebar_all_users`).\n\n  **각자 재정의한다**(사용자 → 사이트 → 기본값). 옆에 무엇을 둘지는 그 사람의 작업 방식이다.\n}}\n{{#sidebar.all}}<div class=\"sidebar-division doc-sidebar content\">{{&.}}</div>{{/sidebar.all}}\n","sidebar-all":"{{!\n  **어느 화면에서든 서는 칸** (2026-09-14 요구 — 사이드바 개편).\n\n  청중으로 갈린다. **내용은 코어가 이미 골라 보냈으므로**(토큰이 누구인지 말한다) 여기서\n  가르는 것은 <b>무엇을 더 세울지</b>이지 어느 문서인지가 아니다 — 지금은 둘이 같은 값을\n  내고, 갈리는 날 고치는 자리가 이 둘이다.\n\n  **`signed_in`이지 `session`이 아니다** — 후자는 계정을 불러온 뒤에야 참이 되므로 그것으로\n  재면 <b>사이드바가 늦게 모양을 바꾼다</b>.\n}}\n{{#signed_in}}{{> sidebar-all-users}}{{/signed_in}}\n{{^signed_in}}{{> sidebar-all-guests}}{{/signed_in}}\n","sidebar-assets":"{{!\n  **에셋 풀 레이어의 칸** (2026-09-15 요구).\n\n  **태그 목록이 이 레이어의 내용이다** — SNS 레이어에 탐색 링크 여섯이 서는 자리이고,\n  문서 레이어에 문서 목록이 서는 자리다. 서버가 정한 칸은 <b>그 아래</b>에 선다.\n\n  **여기서 누르면 격자가 좁혀진다.** 창을 옮기는 것이 아니라 <b>보고 있는 목록</b>이 갈리므로\n  주소가 아니라 단추다.\n}}\n<div class=\"sidebar-division asset-pool-side\" data-asset-side>\n  {{!\n    **그룹 목록이 태그 앞에 선다** (2026-09-17 요구 ·\n    <a href=\"../../../../.claude/milestone-37_asset_access.md\">37</a>).\n\n    **태그와 같은 구성·기능이다** — 건 것을 위에 보이고 걷을 수 있으며, `{+}`로 더하고\n    이름을 눌러 하나로 갈아 끼운다. <b>훅만 갈린다</b>: 같은 이름으로 받으면 태그 하나를\n    걷는 일이 그룹을 걷는다.\n\n    **앞인 까닭**은 <b>판정하는 것이 먼저 읽혀야</b> 하기 때문이다 — 에셋 하나의 창에서\n    구역 칸이 태그 앞에 서는 것과 같은 차례다.\n\n    **검열 권한이 있는 사람에게만 선다.** 라벨을 만질 수 있는 사람의 살림이고, 아닌 사람에게는\n    <i>좁힐 수 없는 갈래</i>가 하나 늘 뿐이다.\n\n    **읽기 라벨에서 뽑는다** — 곁칸이 하는 일은 *무엇을 볼까*를 좁히는 것이고, 그 물음에\n    답하는 것은 <b>누구에게 보이나</b>다.\n  }}\n  {{#can_label}}\n  {{#grouped.length}}\n  <ul class=\"asset-picked\">\n    {{#grouped}}\n    <li><button class=\"tag is-success\" type=\"button\" data-asset-group-drop=\"{{.}}\">{{.}} ×</button></li>\n    {{/grouped}}\n  </ul>\n  {{/grouped.length}}\n\n  <ul class=\"asset-tags asset-groups-side\">\n    {{#groups}}\n    <li class=\"asset-tag\">\n      <button class=\"asset-tag-add\" type=\"button\" data-asset-group-add=\"{{name}}\"\n              title=\"{{t.document.asset_group_add}}\">+</button>\n      <button class=\"asset-tag-only\" type=\"button\" data-asset-group-only=\"{{name}}\"\n              title=\"{{t.document.asset_group_only}}\">{{name}}</button>\n      <span class=\"asset-tag-count\">{{count}}</span>\n    </li>\n    {{/groups}}\n  </ul>\n\n  {{/can_label}}\n\n  {{#picked.length}}\n  <ul class=\"asset-picked\">\n    {{#picked}}\n    <li><button class=\"tag is-primary\" type=\"button\" data-asset-drop=\"{{.}}\">{{.}} ×</button></li>\n    {{/picked}}\n  </ul>\n  {{/picked.length}}\n\n  <ul class=\"asset-tags\">\n    {{#tags}}\n    <li class=\"asset-tag\">\n      <button class=\"asset-tag-add\" type=\"button\" data-asset-add=\"{{name}}\"\n              title=\"{{t.document.asset_tag_add}}\">+</button>\n      <button class=\"asset-tag-only\" type=\"button\" data-asset-only=\"{{name}}\"\n              title=\"{{t.document.asset_tag_only}}\">{{name}}</button>\n      <span class=\"asset-tag-count\">{{count}}</span>\n    </li>\n    {{/tags}}\n  </ul>\n\n  {{!\n    **없으면 그냥 없다** (2026-09-17 요구) — ~~*더 좁힐 그룹이 없습니다* · *태그가\n    없습니다*라 적었다~~.\n\n    **빈 목록은 스스로 말한다.** 좁힐 것이 없다는 사실은 <b>칸이 비어 있는 것</b>으로 이미\n    읽히고, 문구를 두면 곁칸이 <i>없는 것을 설명하는 글</i>로 시작한다 — 격자의 빈자리와\n    다른 자리다: 그쪽은 <b>아직 받는 중인가</b>와 가릴 수 없어 말이 필요하다.\n  }}\n</div>\n\n{{!\n  **지정 문서의 칸은 한 벌이다** (2026-09-16 보고 — <i>글꼴 크기가 서로 다르다</i>).\n\n  ~~여기만 `sidebar-body`였다~~ — CSS에 그런 이름이 없어 <b>이 칸만 본문 크기로 섰다.</b>\n  다른 칸들은 `doc-sidebar`를 입고 0.875rem이다: 기둥은 <i>훑는 자리</i>이지 읽는 자리가\n  아니라는 그 판단이 여기만 빠져 있었다.\n}}\n{{#sidebar_assets}}<div class=\"sidebar-division doc-sidebar content\">{{&.}}</div>{{/sidebar_assets}}\n","sidebar-docs-guests":"{{!\n  문서 레이어 — **게스트** (`viewer.sidebar_docs_guests`).\n\n  **이 지식기반이 어떻게 짜여 있는가**를 말하는 자리다(31 확정 10 — 미디어위키의 그 자리).\n}}\n{{#sidebar.docs}}<div class=\"sidebar-division doc-sidebar content\">{{&.}}</div>{{/sidebar.docs}}\n","sidebar-docs-users":"{{!\n  문서 레이어 — **로그인한 사람** (`viewer.sidebar_docs_users`).\n\n  **각자 재정의한다.** 읽는 사람과 쓰는 사람이 옆에 두고 싶은 것은 대개 다르다.\n}}\n{{#sidebar.docs}}<div class=\"sidebar-division doc-sidebar content\">{{&.}}</div>{{/sidebar.docs}}\n","sidebar-docs":"{{!\n  **문서 레이어의 칸** — 문서를 읽는 동안 (2026-09-14 요구 — 사이드바 개편).\n\n  **SNS의 줄들은 여기 서지 않는다**(2026-09-07 요구). 좋아요·북마크·멘션·메시지·알림은\n  마이크로블로그의 자리이고, 문서를 읽는 동안 갈 곳이 아니다.\n\n  **갈 곳이 먼저이고 정해 둔 문서가 그 뒤다**(SNS 레이어와 같은 차례) — `all` 다음에\n  <i>여기서 어디로 갈까</i>가 오고, 손으로 짠 목록은 그것을 밀어내지 않는다.\n}}\n{{!\n  **~~에셋 풀이 여기 고정으로 섰다~~** (2026-09-17 요구 · 2026-09-18에 걷었다).\n\n  **레이어를 건너뛰는 일은 이 칸의 것이 아니다.** 여기는 <i>이 레이어 안에서</i> 어디로\n  갈지를 말하는 자리이고, 에셋 풀은 <b>다른 레이어의 첫 자리</b>다 — 레이어 바로가기\n  (`sidebar-layers`)가 그 일을 맡으면서 이 줄은 자리를 잘못 잡은 것이 되었다.\n}}\n{{#signed_in}}\n{{> sidebar-docs-users}}\n{{/signed_in}}\n{{^signed_in}}{{> sidebar-docs-guests}}{{/signed_in}}\n","sidebar-layers":"{{!\n  **레이어 바로가기** — `all` 바로 다음, 레이어를 가리지 않고 (2026-09-18 요구).\n\n  **레이어를 건너뛰는 자리다.** 아래의 칸들은 <i>이 레이어 안에서</i> 어디로 갈지를 말하는데,\n  그 위에 <b>레이어 자체를 갈아타는</b> 문이 있어야 한다 — 이름을 누르면 첫 화면이고, 거기서\n  다시 찾아 들어가야 했다.\n\n  **~~머리의 드롭다운이었다~~** (2026-09-18에 옮겼다). 서비스 이름 뒤의 상자는 <b>눌러야\n  열리는 자리</b>라 거기 무엇이 있는지 알려면 먼저 열어 봐야 했고, 곁칸은 이미 <i>갈 곳의\n  목록</i>이 사는 자리다 — 같은 성질의 것이 두 곳에 갈려 있을 이유가 없다.\n\n  **레이어를 가리지 않고 선다**(요구). 아래의 칸이 택일하는 것과 다른 규칙이다: 이 목록이\n  택일하면 <b>지금 서 있는 레이어에서 벗어나는 길</b>이 그 레이어에 갇힌다.\n\n  **목록은 코어가 짓는다.** 뷰어가 레이어 목록을 묻고 각 레이어가 제 대표 자리들을 답한다 —\n  레이어가 하나 더 서도 <b>이 조각은 그대로다</b>. 하나도 없으면(게스트가 그렇다) 칸이 서지\n  않는다.\n\n  **줄마다 그 자리의 그림이 선다** — 낱말을 읽기 전에 <i>어디로 가는가</i>가 먼저 잡힌다.\n  **레이어가 아니라 갈래로 고른다** — SNS가 셋을 내므로 레이어로 고르면 <b>같은 그림 셋</b>이\n  선다.\n\n  **문서 줄의 낱말은 그 문서의 이름이다**(2026-09-18 요구) — 다른 줄은 갈래가 곧 이름이지만\n  이 자리의 대상은 그때그때 다른 문서다.\n}}\n{{#layers.length}}\n<ul class=\"sidebar-division nav-list\">\n  {{#layers}}\n  <li class=\"nav-item\"><a href=\"{{href}}\"><span class=\"nav-icon\" aria-hidden=\"true\">{{#icon_is.feed}}{{> icon-home}}{{/icon_is.feed}}{{#icon_is.feed_server}}{{> icon-eye}}{{/icon_is.feed_server}}{{#icon_is.feed_federated}}{{> icon-globe}}{{/icon_is.feed_federated}}{{#icon_is.document}}{{> icon-file-text}}{{/icon_is.document}}{{#icon_is.pool}}{{> icon-image}}{{/icon_is.pool}}{{#icon_is.specials}}{{> icon-list-check}}{{/icon_is.specials}}</span><span class=\"nav-label\">{{label}}</span></a></li>\n  {{/layers}}\n</ul>\n{{/layers.length}}\n","sidebar-sns-guests":"{{!\n  SNS 레이어 — **게스트** (`viewer.sidebar_sns_guests`).\n\n  **탐색 링크 여섯은 서지 않는다.** 홈 피드·좋아요·북마크·멘션·메시지·알림은 전부 <i>나</i>에\n  딸린 자리라 게스트에게는 갈 곳이 아니다 — 여기 서는 것은 정해 둔 문서뿐이다.\n}}\n{{#sidebar.sns}}<div class=\"sidebar-division doc-sidebar content\">{{&.}}</div>{{/sidebar.sns}}\n","sidebar-sns-users":"{{!\n  SNS 레이어 — **로그인한 사람** (`viewer.sidebar_sns_users`).\n\n  **두 칸이다.** 탐색 링크 다섯이 먼저 서고 정해 둔 문서가 그 뒤에 온다.\n\n  **문서가 다섯을 밀어내지 않는다** (2026-09-14 요구). 좋아요·북마크·멘션·메시지·알림으로\n  가는 문은 <b>뷰어 전체에서 이 목록 말고는 없다</b>(머리에 있는 것은 작성·로그인·로그아웃·\n  설정·프로필뿐이다) — 이 칸을 채웠다는 이유로 그것이 사라지면 <b>설정 하나가 화면을\n  막는다.</b> 손으로 짠 탐색 문서로 다섯을 *대체*하는 것은 다른 결정이고, 그때는 그것을\n  말하는 스위치가 따로 서야 한다.\n\n  **차례는 `all` 다음이다**(요구). 어느 화면에서든 서는 말이 먼저이고, 그 다음이 <i>여기서\n  어디로 갈까</i>다.\n}}\n<ul class=\"sidebar-division nav-list\">\n  {{!\n    **~~홈 피드가 첫 줄이었다~~** (2026-09-08 요구 · 2026-09-18에 걷었다).\n\n    그 줄이 선 까닭은 <i>피드를 보고 있을 때만</i> 서는 제목줄의 갈아타기 말고는\n    <b>내 피드로 돌아가는 길</b>이 없다는 것이었다. 이제 <b>레이어 바로가기가 이 칸 바로\n    위에 늘 선다</b>(`sidebar-layers` — 홈·서버·연합 셋을 다 든다) — 같은 곳으로 가는 문이\n    나란히 둘 설 이유가 없다.\n\n    **주석에 태그를 적지 않는다.** 무스타시 주석은 <b>첫 닫는 괄호에서 끝나므로</b> 안에\n    태그를 그대로 적으면 그 자리에서 주석이 닫히고 <b>나머지 문장이 화면에 새어 나온다</b> —\n    2026-09-08에 이 줄이 실제로 사이드바에 소스로 섰다.\n  }}\n  {{!\n    **좋아요는 북마크 앞이다**(2026-09-04 요구).\n\n    둘은 <b>내가 골라 둔 글</b>이라는 점에서 한 무리이고, 그래서 나란히 선다 — 향하는 곳은\n    반대다(좋아요는 상대에게 가는 말이고 북마크는 나에게 남기는 표시다).\n\n    **아이콘은 포스트의 그 하트다.** 목록으로 가는 문과 글마다 누르는 단추가 같은 그림이어야\n    <b>무엇이 모인 자리인지</b>가 읽힌다.\n\n    **이름은 그냥 `북마크`이고**(05e 요구) 포스트냐 문서냐는 그 화면 안의 탭이 말한다.\n  }}\n  <li class=\"nav-item\"><a href=\"/-/likes\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-heart}}</span><span class=\"nav-label\">{{t.nav.likes}}</span></a></li>\n  <li class=\"nav-item\"><a href=\"/-/bookmarks/posts\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-star}}</span><span class=\"nav-label\">{{t.nav.bookmarks}}</span></a></li>\n  {{!\n    **멘션은 메시지 앞이다**(2026-08-20 요구). 둘 다 <b>나에게 온 글</b>이고, 부른 것과 보낸\n    것 중 열려 있는 쪽이 먼저다 — 멘션은 아무나 걸 수 있고 메시지는 받겠다고 정한 사람에게만\n    온다.\n\n    **알림과 다른 자리다.** 알림은 *무슨 일이 있었는가*의 목록이라 팔로우·리포스트가 섞여\n    들고 읽으면 지나가지만, 여기 서는 것은 글 자체이고 다른 피드처럼 읽힌다.\n  }}\n  <li class=\"nav-item\"><a href=\"/-/mentions\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-mention}}</span><span class=\"nav-label\">{{t.nav.mentions}}</span></a></li>\n  <li class=\"nav-item\"><a href=\"/-/messages\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-envelope}}</span><span class=\"nav-label\">{{t.nav.messages}}</span></a></li>\n  {{!\n    **개수는 낱말 옆에 남는다**(2026-08-23 요구 · 05e의 *개수는 남는다*와 같은 규칙).\n\n    좁은 화면에서 레이블이 잘려도 <b>이것은 잘리지 않는다</b> — 그림이 대신할 수 있는 것은\n    낱말이고 숫자는 그럴 수 없다. **세는 것은 알림 화면에 서는 것 전부**다: 코어의 알림과\n    뷰어의 작업(백업·되돌리기). 눌러서 세어 본 수와 다르면 카운터가 거짓말이 된다.\n\n    **0이면 자리가 빈다.** Mustache에서 `0`은 거짓이라 조건이 따로 없다.\n  }}\n  <li class=\"nav-item\"><a href=\"/-/notifications\"><span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-bell}}</span><span class=\"nav-label\">{{t.nav.notifications}}</span>{{#unread.total}}<span class=\"nav-count\" aria-label=\"{{unread.label}}\">{{unread.total}}</span>{{/unread.total}}</a></li>\n</ul>\n{{#sidebar.sns}}<div class=\"sidebar-division doc-sidebar content\">{{&.}}</div>{{/sidebar.sns}}\n","sidebar-sns":"{{!\n  **SNS 레이어의 칸** — 피드·프로필을 보는 동안 (2026-09-14 요구 — 사이드바 개편).\n}}\n{{#signed_in}}{{> sidebar-sns-users}}{{/signed_in}}\n{{^signed_in}}{{> sidebar-sns-guests}}{{/signed_in}}\n","sidebar":"{{!\n  사이드바 — **어느 화면에서든 선다** (2026-09-14 요구 — 사이드바 개편).\n\n  **이 파일은 레이아웃이다.** 무엇이 설지는 부속이 정하고 여기서는 <b>차례와 테두리</b>만\n  진다 — 칸을 더하거나 빼는 일이 이 파일 한 곳에서 읽힌다.\n\n    ① sidebar-all    어느 화면에서든\n    ② sidebar-layers 레이어 바로가기 — 레이어를 가리지 않는다 (2026-09-18)\n    ③ sidebar-sns    피드·프로필을 보는 동안   ┐\n    ③ sidebar-docs   문서를 읽는 동안          ├ 레이어가 택일한다\n    ③ sidebar-assets  미디어 풀을 보는 동안     ┘ (2026-09-15에 셋이 되었다)\n    ④ 서비스 문서 셋(소개·약관·정책) — 늘 바닥\n\n  **구분선을 요소로 넣지 않는다.** 칸마다 `sidebar-division`을 입히고 줄은 <b>인접 형제</b>에\n  CSS가 긋는다(`.sidebar-division + .sidebar-division`) — 빈 칸은 아예 렌더되지 않으므로\n  <b>줄이 맨 위에 뜨거나 두 줄이 겹치는 일이 구조적으로 생기지 않는다.</b> 조건마다\n  *앞에 무엇이 있었는가*를 세는 방식은 칸이 늘 때마다 그 셈이 자란다.\n\n  **편집 모드에서는 통째로 글감 탐색기가 된다**(31 확정 10). 고치는 동안 옆에 있어야 하는\n  것은 <b>갈 곳이 아니라 담을 것</b>이라, 칸을 하나 더하는 것이 아니라 자리를 내준다.\n\n  **빌 수 있으면 서지 않는다**(`show_nav` — 2026-09-05). 개편의 목적이 *어느 화면에서든\n  사이드바가 존재한다*이지만 그것은 <b>세울 것이 있을 때</b>의 말이다.\n}}\n{{#corpus_sidebar}}{{> nav-corpus}}{{/corpus_sidebar}}\n{{^corpus_sidebar}}\n{{#show_nav}}\n<nav class=\"site-nav\" id=\"site-nav\" aria-label=\"{{t.nav.explore}}\">\n  {{> sidebar-all}}\n  {{!\n    **레이어를 건너뛰는 자리가 레이어별 칸보다 먼저다** (2026-09-18 요구) — `all` 다음이\n    <i>어느 레이어로 갈까</i>이고, 그 다음이 <i>이 레이어 안에서 어디로 갈까</i>다.\n  }}\n  {{> sidebar-layers}}\n  {{^asset_layer}}\n  {{^document_layer}}{{> sidebar-sns}}{{/document_layer}}\n  {{#document_layer}}{{> sidebar-docs}}{{/document_layer}}\n  {{/asset_layer}}\n  {{#asset_layer}}{{> sidebar-assets}}{{/asset_layer}}\n  {{!\n    **~~서비스가 무엇인지 말하는 문서 셋이 여기 섰다~~** (2026-08-26 → 2026-09-19에 옮겼다).\n\n    소개·약관·정책은 한 무리이고 레이어를 타지 않는다 — 그래서 사이드바 바닥에 두었는데,\n    <b>바닥에 두려던 것이 실은 화면의 바닥</b>이었다. 발이 서면서 그 자리가 생겼고, 셋은\n    거기로 갔다(`footer-site`).\n\n    **사이드바는 둘러보는 자리다.** 한 번 읽고 마는 문서가 <i>자주 누르는 것</i>들 사이에\n    설 이유가 없고, 좁은 화면에서 감추던 규칙도 함께 사라진다 — 발은 어느 폭에서나 선다.\n  }}\n  {{!\n    **판 안에 선 손잡이** (2026-09-19 요구 — 발의 복제품).\n\n    좁은 화면에서 판은 <b>바닥까지 내려와 아래 막대를 덮는다</b>. 가려서 못 누르게 두는\n    대신 <b>같은 것을 판 안에 세운다</b> — 여는 길과 닫는 길이 같은 모양으로 남는다.\n\n    **막대의 그 단추 그대로다**(`mobile-menu` · `data-nav-toggle`) — 한 쌍이므로 생김새가\n    갈리면 <i>같은 일의 앞뒤</i>로 읽히지 않고, 표가 같으므로 스크립트도 손잡이를 세지\n    않는다.\n\n    **넓은 화면에서는 서지 않는다**(CSS) — 거기서는 기둥이 늘 서 있어 여닫을 것이 없다.\n  }}\n  <div class=\"nav-foot\">\n    <button class=\"mobile-menu\" type=\"button\" data-nav-toggle aria-expanded=\"false\" aria-controls=\"site-nav\">\n      <span class=\"nav-icon\" aria-hidden=\"true\">{{> icon-menu}}</span>\n      <span class=\"nav-label\">{{t.nav.explore}}</span>\n    </button>\n  </div>\n</nav>\n{{/show_nav}}\n{{/corpus_sidebar}}\n","table-check-all":"{{! 헤더의 체크박스 — 전체선택 토글. 입력 하나만이다; 칸(th)은 템플릿이 짠다. }}\n<input type=\"checkbox\" data-check-all aria-label=\"{{t.table.select_all}}\">\n","table-check":"{{!\n  줄의 체크박스 (39 확정 3) — **입력 하나만이다.** 칸(td)은 템플릿이 짠다 — 그래야 rowspan 같은\n  칸의 속성을 스킨이 정한다(2026-09-20 요구). 선택 액션이 있을 때만 서는 것은 감싸는 쪽이 판다:\n  table.select 구간 안에 칸을 세우고 그 안에 이 조각을 놓는다. rows 구간 안이면 id가 그 줄의 것이다.\n}}\n<input type=\"checkbox\" data-check value=\"{{id}}\">\n","table-empty":"{{! 줄이 없으면 그렇다고 말한다 — 표만 비워 두면 받는 중인가와 가릴 수 없다. }}\n{{^table.count}}<p class=\"empty\">{{table.empty}}</p>{{/table.count}}\n","table-sort":"{{!\n  정렬 헤더 하나 (39 확정 3). 그 컬럼의 문맥 안에서 부른다 — 예: 열쇠가 handle이면\n  `#table.sort.handle` 구간 안에 이 조각을 세운다. 링크·지금 정렬 여부·방향이 그 문맥에 들어 있다.\n  누르면 정렬이 갈아탄다: 링크라 자바스크립트가 없어도 돈다.\n}}\n<a class=\"sort{{#sorted}} is-sorted is-{{dir}}{{/sorted}}\" href=\"{{href}}\">{{label}}{{#sorted}}<span class=\"sort-mark\" aria-hidden=\"true\"></span>{{/sorted}}</a>\n","table-toolbar":"{{!\n  표의 탐색 줄 — **위아래에 같은 것이 선다** (39 확정 3). 왼쪽 선택 액션 · 중앙 페이지네이션\n  (또는 커서 로더) · 오른쪽 페이지 크기.\n\n  **선택 액션은 상자다** — 되돌릴 수 없는 것은 가로줄 아래 빨강(전역 규칙). 액션이 없으면\n  그 자리는 비어 선다: 세 자리의 배치가 페이지마다 흔들리지 않는다.\n}}\n{{#table}}\n<div class=\"table-toolbar\">\n  <div class=\"toolbar-left\">\n    {{#has_actions}}\n    <details class=\"dropdown\" data-dropdown>\n      <summary class=\"button is-small\">{{t.table.selected_do}}</summary>\n      <ul class=\"dropdown-menu\">\n        {{#actions}}\n        {{#danger}}<li class=\"rule\" role=\"separator\"></li>{{/danger}}\n        <li><button class=\"action{{#danger}} delete{{/danger}}\" type=\"button\" data-bulk=\"{{key}}\">{{label}}</button></li>\n        {{/actions}}\n      </ul>\n    </details>\n    {{/has_actions}}\n  </div>\n  <div class=\"toolbar-center\">\n    {{#pages.length}}\n    <nav class=\"pager pager-numbers\" aria-label=\"{{t.pager.label}}\">\n      <ul>\n        {{#pages}}\n        <li>\n          {{#gap}}<span class=\"pager-gap\">…</span>{{/gap}}\n          {{^gap}}\n            {{#current}}<span class=\"pager-now\" aria-current=\"page\">{{number}}</span>{{/current}}\n            {{^current}}<a href=\"{{href}}\">{{number}}</a>{{/current}}\n          {{/gap}}\n        </li>\n        {{/pages}}\n      </ul>\n    </nav>\n    {{/pages.length}}\n    {{#newer}}<a class=\"button is-small\" rel=\"prev\" href=\"{{.}}\" data-load=\"newer\">{{t.loader.newer}}</a>{{/newer}}\n    {{#older}}<a class=\"button is-small\" rel=\"next\" href=\"{{.}}\" data-load=\"older\">{{t.loader.older}}</a>{{/older}}\n  </div>\n  <div class=\"toolbar-right\">\n    <form class=\"per-page\" method=\"get\" action=\"{{base}}\">\n      {{#hidden}}<input type=\"hidden\" name=\"{{name}}\" value=\"{{value}}\">{{/hidden}}\n      <label>{{t.table.per_page}} <input class=\"input is-small\" type=\"number\" name=\"per_page\" min=\"1\" max=\"200\" value=\"{{per_page}}\" data-per-page></label>\n    </form>\n  </div>\n</div>\n{{/table}}\n","title-parts-pool":"{{!\n  에셋 풀의 제목줄 부속 — **고른 것에 하는 일** (2026-09-17 요구 · 2026-09-19에 자리를\n  규정했다).\n\n  **점 셋 상자의 항목이어야 하지만 밖에 선다.** 다중 선택 중에 자주 누르는 것이라 상자를\n  거치면 손이 두 번 간다 — 그 자리가 <b>점 셋 왼편</b>이다.\n\n  **고른 것이 없으면 뜻이 없는 단추다** — 스크립트가 그 표를 켜고 끈다(`hidden`).\n\n  **옷은 전역 규칙의 선택 단추다**(`button is-light`가 아닌 것은 목록 안의 작은 자리라\n  `is-small`을 쓰기 때문이다) — 낱말이 보여야 하는 것이라 그림만 남기지 않는다.\n}}\n{{#can_label}}\n<button class=\"button is-small\" type=\"button\" data-pool-groups hidden>{{t.pool.groups}}</button>\n{{/can_label}}\n"},"locales":{}}