/* ══════════════════════════════════════════════════════════════════════════
   links.css — 목록 화면(`/links/`).

   **홈과 같은 언어로 쓴다.** 홈(`home.css`)이 세운 문법은 넷이다.
     ① 뼈대는 선, 잉크는 옅게(`--fg-3`) — 틀은 «화면의 뼈대» 로만 읽힌다
     ② 라벨은 고정폭 · 아주 작게 · 자간을 벌려(0.2em) — `env` `codes` `by client`
     ③ 색은 **상태에만**(점·응답 코드). 이름·메타는 색을 갖지 않는다
     ④ 메타는 줄 끝에 흐린 고정폭으로

   그 넷을 이 화면에 옮기되 **문자 격자는 옮기지 않는다.** 홈의 등록부는 모든 폭이 `ch`
   단위인 전사 화면이지만, 여기에는 한글 이름·설명이 들어온다(한글 1.664ch) — 격자로 두면
   줄마다 열이 밀린다. 그래서 이 화면의 규칙은 **역할로 서체를 가른다**:

       내용(이름 · 설명 · 고객사 · 분야)      → 본문 서체. 읽는 글자다
       뼈대·메타(열 이름 · 주소 · 코드 ·      → 고정폭. 세로로 훑는 값이고, 길이가
                담당자 · 점검 시각 · 개수)       들쭉날쭉하면 열이 흔들려 보인다

   구획의 머리는 홈의 라벨 막(`── by client ────────`)과 같은 모양이다 — 짧은 선, 라벨,
   남은 폭을 채우는 선. 홈은 그것을 박스 문자로 그리고 여기서는 1px 선으로 그린다: 같은
   형태이면서 한글이 섞여도 흔들리지 않는다.

   셸에서 오는 것을 다시 만들지 않는다 — 토큰(`tokens.css`), 단추(`controls.css`),
   입력 필드(`drawer.css` 의 `.field/.input/.select`)는 그대로 쓴다.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 지면 ── 셸의 `#main` 이 폭과 **셸과의 사이 여백**(`--gap-shell`)을 이미 잡으므로,
   여기서는 구획끼리의 사이만 만든다. */

/* ══ 배너 ══ 홈의 표지와 **같은 규격**, 다른 내용.

   같은 것: 높이(min-height 384px)·패딩(40/30)·눈썹(고정폭 11px, 자간 0.2em)·제목 스케일
   (clamp(1.6rem, 2.6vw, 2.35rem))·리드(14px)·액센트 동사 하나. 두 화면을 오갈 때 머리가
   같은 크기여야 한 사이트로 읽힌다.

   다른 것: 홈의 TUI 문법(문자 격자·박스 문자·계기)은 **가져오지 않는다.** 이 화면은 문서형
   표라 그 장치를 얹으면 표 위에 다른 제품이 앉은 것처럼 보인다.

   눈썹의 자간은 0.2em 이다 — 홈과 같다. 이 줄만 라틴 글자라 크게 벌려도 낱말로 읽힌다
   (한글 라벨을 0.04em 으로 줄인 이유는 `.act-title` 주석에 있다). */
/* 배너는 **셸의 것**이다(`shell/banner.css` 의 `.band`). 여기에는 이 화면만의 것만 남는다 —
   지금은 «배너 다음 구획의 여백» 하나뿐이다. 규격을 여기에 다시 적으면 두 화면이 갈린다. */

/* ── 찾기 ── */
/* 라벨 막이 이미 선을 그리므로 **밑줄을 두지 않는다.** 둘 다 두면 구획 머리에 선이 두 줄이
   되고, 그 사이의 빈 띠가 «접힌 무언가» 처럼 읽힌다. */
.find-head {
	display: flex;
	align-items: center;
	gap: 1rem;
	padding-bottom: 0.75rem;
}

.find-head-end {
	display: flex;
	align-items: center;
	gap: 0.75rem;
}

/* 개수는 홈의 `⎿ found 49 links` 와 같은 값이다 — 그 화면처럼 흐린 고정폭으로 둔다.
   자간을 조금 벌려 라벨 막의 리듬과 같은 결로 읽히게 한다. */
.find-count {
	margin: 0;
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	letter-spacing: 0.06em;
	color: var(--fg-3);
	white-space: nowrap;
}

.find-form {
	padding-top: 1rem;
}

.find-row-search {
	margin-bottom: 0.9rem;
}

/* 검색 상자 — 돋보기와 입력이 한 칸처럼 보이게 겹친다. */
.find-search-box {
	position: relative;
	display: block;
}

.find-icon {
	position: absolute;
	left: 0.7rem;
	top: 50%;
	width: 1rem;
	height: 1rem;
	transform: translateY(-50%);
	color: var(--fg-3);
	pointer-events: none;
}

/* ── 지우기 단추 ── 돋보기와 **대칭**이다: 왼쪽에 아이콘, 오른쪽에 단추. 둘 다 칸 안에
   절대 배치한다.

   **이 규칙이 아예 없었다.** 클래스가 마크업에만 있어서 기본 단추로 흐름에 놓였고, 입력칸이
   폭을 다 쓰므로 다음 줄로 떨어졌다 — 글자를 치는 순간 ① 칸 아래에 × 가 하나 생기고
   ② 상자가 40 → 61px 로 자라 가운데 정렬된 돋보기가 10px 내려갔다(실측, 사용자 지적).
   바탕을 갈아엎을 때(`4be789e` → `b2b88c6`) 옛 규칙(flex 전제)이 옮겨지지 않은 자리다.

   표적은 `--tap-min` 을 쓴다 — 실제로 누르는 단추이고, 터치 기기에서는 그 값이 44px 이 된다. */
.find-clear {
	position: absolute;
	top: 50%;
	right: 0.35rem;
	display: grid;
	place-items: center;
	min-width: var(--tap-min);
	min-height: var(--tap-min);
	padding: 0;
	border: 0;
	background: none;
	font-size: 1.15rem;
	line-height: 1;
	color: var(--fg-3);
	cursor: pointer;
	transform: translateY(-50%);
}

@media (hover: hover) {
	.find-clear:hover {
		color: var(--fg);
	}
}

/* 브라우저가 그리는 `type="search"` 의 기본 지우기 표시는 지운다 — 우리 단추와 둘이 된다. */
.find-search-box .input::-webkit-search-cancel-button {
	display: none;
}

/* 질의문은 **고정폭**이다. 홈의 입력 줄(`❯ …`)과 같은 결 — 사람이 치는 값이고, 주소·코드와
   같은 서체로 두면 «이 화면의 입력» 이라는 것이 서체로 읽힌다. 상자는 그대로 둔다:
   걸러내기 넷이 상자이므로 여기만 선으로 바꾸면 한 줄 안에서 문법이 갈린다. */
.find-search-box .input {
	padding-left: 2.2rem;
	/* 오른쪽은 지우기 단추의 자리다 — 비워 두지 않으면 글자가 단추 아래로 흐른다. */
	padding-right: 2.6rem;
	font-family: var(--font-mono);
}

/* 칸 이름은 홈의 오른쪽 사실 라벨(`env` · `codes` · `owners`)과 같은 규격이다 —
   고정폭 · 아주 작게 · 자간 0.2em · 흐린 잉크. 셸의 `.label` 을 이 화면에서만 바꾼다:
   서랍의 폼에는 그대로 두어야 한다(폼은 «쓰는» 화면이라 라벨이 읽혀야 한다). */
.find-form .label {
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	font-weight: 400;
	letter-spacing: 0.04em;   /* 한글 음절이 갈라지지 않는 한도 — `.act-title` 주석 참조 */
	text-transform: uppercase;
	color: var(--fg-3);
}

/* ══ 폭을 재는 기준 ══ 이 화면의 반응형은 **뷰포트가 아니라 «담긴 폭»** 으로 판단한다.
   구획 폭은 지면 여백과 `--page-max` 사다리를 이미 뺀 값이라, 「접을 때」와 「넘칠 때」가
   어긋나지 않는다(뷰포트로 재면 어긋난다 — 상세 화면에서 그 어긋남이 결함 구간을 만들었다).

   컨테이너는 **구획과 줄에만** 걸고 격자에는 걸지 않는다: `container-type: inline-size` 는
   `contain: inline-size` 를 함께 걸어 그 요소가 내용으로 폭을 정할 수 없게 만들므로, 표
   격자에 걸면 열 계산이 바뀐다. */
#find { container: find / inline-size; }
#results { container: results / inline-size; }
.result-bar { container: resultbar / inline-size; }

/* 걸러내기 일곱 — 좁아지면 자동으로 줄어든다(칸을 고정하지 않는다).
   가장 긴 값 「인증 필요 (401·403)」이 124px 이고 셀렉트의 패딩·화살표가 48px 이라 172px 이
   하한이다(실측). 그래서 한 줄에 일곱은 안 된다: 172×7 + 홈통 12×6 = 1276px 로 지면(1280px)
   에 여유가 4px 뿐이다. */
.find-row-filters {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: 0.75rem;
}

/* 넓은 화면에서는 **넷 + 셋**이다. 윗줄은 링크가 «무엇인가»(고객사·분야·계약 상태·진행 상태),
   아랫줄은 «지금 어떤가와 누가»(운영 서버·개발 서버·담당자)다. 아랫줄은 **오른쪽에 붙인다** —
   2열부터 시작해 두 줄의 오른쪽 끝이 맞고, 왼쪽에 생기는 빈 칸이 두 줄의 성질이 다르다는
   것을 말한다(줄마다 라벨을 붙이지 않고도).

   **기준은 뷰포트가 아니라 이 구획의 폭이다.** 4열이 서려면 칸마다 172px 이 필요하고
   (가장 긴 값 「인증 필요 (401·403)」 124px + 셀렉트 패딩·화살표 48px), 홈통 12px×3 을 더하면
   구획 736px 이다 — 실측도 같다: 726px 까지 칸이 172px 를 지키고 722px 에서 171px 로 떨어진다.
   전에는 `@media (min-width: 62rem)`(992px)이었는데, 그 값은 «구획 폭» 이 아니라 뷰포트라
   지면 여백·`--page-max` 사다리가 끼면 어긋난다. */
@container find (min-width: 46rem) {
	.find-row-filters {
		grid-template-columns: repeat(4, 1fr);
	}

	/* 위치를 순서(`nth-child`)가 아니라 **그 칸이 무엇인지**로 지정한다 — 칸을 하나 넣거나
	   빼면 순서 규칙은 조용히 다른 칸을 옮긴다. */
	.find-row-filters .field:has(#filter-prod) {
		grid-column-start: 2;
	}
}

/* ── 마무리 줄 ── 걸린 조건(왼쪽)과 동작(오른쪽)이 **한 줄**에 앉는다.
   칩에 자기 줄을 주면 줄이 하나 더 생겨(26px + 위아래 여백) 동작 단추가 내려가고 걸러내기와
   목록 사이가 그만큼 멀어진다 — 조건을 바꾸고 결과를 보는 일이 한눈에 들어오지 않는다.
   좁아지면 칩이 먼저 여러 줄이 되고, 그래도 모자라면 동작 줄이 아래로 내려간다(`wrap`). */
.find-foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 0.6rem 1rem;
	margin-top: 0.9rem;
}

/* 동작 둘은 **오른쪽**에 붙인다. 왼쪽에 두면 그 위 걸러내기 칸들의 왼쪽 끝과 한 줄로 이어져
   «다섯 번째 칸» 처럼 읽힌다. 줄이 접혀도 오른쪽 정렬을 유지한다. */
.find-actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	flex: 0 0 auto;
	gap: 0.5rem;
	margin-left: auto;            /* 칩이 없을 때도 오른쪽 끝에 남는다 */
}

/* 걸린 조건 — 누르면 그 조건만 빠진다. 칩은 «조건 하나 빼기», 옆의 「조건 초기화」는
   «전부 빼기» — 같은 일의 두 크기라 나란히 둔다. */
.find-chips {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	flex: 1 1 auto;
	gap: 0.4rem;
	min-width: 0;
}

.find-chips:empty {
	display: none;
}

.chip {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	padding: 0.2rem 0.5rem;
	border: 1px solid var(--line-strong);
	font-size: var(--t-sm);
	color: var(--fg-2);
}

.chip-x {
	border: 0;
	background: none;
	font: inherit;
	color: var(--fg-3);
	cursor: pointer;
}

@media (hover: hover) {
	.chip-x:hover {
		color: var(--fg);
	}
}

.find-toggle {
	display: none;                /* 넓은 화면에서는 걸러내기가 늘 펼쳐져 있다 */
}

.find-toggle-count {
	margin-left: 0.3rem;
	color: var(--accent);
}

/* ── 결과 ── */
/* 라벨 막 + 오른쪽 끝의 개수 — 「찾기」 막과 같은 짜임이다(`.act-title` 이 남은 폭을 선으로
   채우고, 그 뒤에 수치가 붙는다). 두 막이 같은 모양이라 화면이 «구획 → 구획» 으로 읽힌다. */
.result-head {
	display: flex;
	align-items: center;
	gap: 1rem;
	padding-bottom: 0.7rem;
}
/* 결과 줄 — 왼쪽은 **데이터에 하는 일**(점검), 오른쪽은 **보는 방식**(보기 셋).
   `space-between` 이라 좁아져도 두 덩어리의 역할이 자리로 구분된다. */
.result-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 0.5rem;
	padding-bottom: 0.6rem;
}

.result-check {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

/* 마지막 점검 시각 — 단추의 결과를 말하는 자리라 단추보다 한 단계 옅다.
   자릿수가 바뀌어도(「방금」 ↔ 「12분 전 점검」) 보기 단추가 밀리지 않도록 왼쪽에 둔다. */
.result-checked {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-family: var(--font-mono);
	font-size: var(--t-sm);
	color: var(--fg-3);
}

/* 범위와 시각 사이의 가운뎃점 — 두 값을 가르는 것뿐이라 더 옅다. */
.result-sep {
	color: var(--line-strong);
}

/* 점검 범위 — 조건이 걸리면 이 값이 바뀐다(전체 49건 → 사내 25건). 값이 바뀌는 자리라
   시각보다 한 단계 진하게 둔다. */
#health-scope {
	color: var(--fg-2);
}

/* 보기 셋은 **같은 폭**이다. 글자 수에 맡기면 리스트 87px · 카드 74px · 피드 74px 로
   서로 달라, 셋이 «한 벌의 선택지» 가 아니라 각자 다른 단추로 읽힌다(실측).
   격자로 두면 가장 넓은 것에 맞춰 셋이 함께 정해진다 — 값을 손으로 적지 않는다. */
.result-views {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	width: max-content;
	gap: 0.3rem;
}

/* 「지금 점검」도 그 셋과 같은 폭이다. 두 덩어리가 서로 다른 컨테이너라 격자로는 못 맞추므로
   줄 전체에 **한 값**을 준다 — 넷 중 가장 넓은 내용(아이콘 + 「지금 점검」)이 그 값이다.
   글자를 늘리면 이 값도 함께 봐야 한다(그래서 한 곳에만 적는다). */
.result-bar .btn.is-small {
	min-width: 6.5rem;
}

/* 아이콘은 보기 셋과 「지금 점검」이 함께 쓴다 — 한쪽만 규칙을 가지면 나중에 넣는 아이콘이
   크기 없이 들어간다(«한 페이지 전용 클래스에 전역 규칙» 과 같은 종류의 실수).

   **아이콘에 이름을 준다**(`.result-bar .btn svg` 가 아니라). 부모 둘에 기대면 선택자가
   세 토막이 되고, 그 단추를 다른 구획으로 옮기는 순간 규칙이 조용히 빠진다.

   **간격은 단추의 `gap` 하나가 소유한다.** 여기에 `margin-right` 를 더 주고 있었는데, 그러면
   6.4px(gap) + 5.6px(margin) = 12px 이 되어 아이콘이 글자에서 떠 보였다(실측). 간격을 두
   군데서 만들면 어느 쪽을 고쳐야 하는지도 알 수 없다. */
.result-btn-icon {
	width: 0.9rem;
	height: 0.9rem;
}

/* ── 표 ── 열 규격을 **한 곳에서** 정한다. 머리와 줄이 각자 값을 가지면 언젠가 갈린다. */
/* 열 여섯: 이름 · 주소 · 상태 · 담당자 · 점검 · 도구.
   **머리와 줄이 같은 값을 쓴다** — 앞서 머리는 다섯 칸인데 줄은 도구를 다섯째에 넣어
   「점검 시각」 머리 아래에 단추가 서 있었다(실측). 열이 어긋나면 머리가 거짓말을 한다. */
/* 머리와 줄은 **같은 열 정의를 읽는다** — 이 규칙에 둘 다 있어야 x 좌표가 맞는다.
   («모양» 만 변수로 갈린다: 접힌 표·카드·피드에서 머리는 정렬 줄이 된다. 아래 `.entry-head`
   규칙이 그 변수를 읽고 이 선언을 덮는다.) */
.entry-head,
.entries[data-view='list'] .entry {
	display: grid;
	/* 열 여덟: 고객사 · 분야 · 이름 · 주소 · 상태 · 담당자 · 점검 · 도구.
	   **폭을 고정한다.** 머리와 줄은 서로 다른 격자 컨테이너라, `auto`·`minmax` 처럼
	   내용으로 정해지는 열을 쓰면 두 격자가 각자 다른 값을 낸다 — 실제로 머리의 「주소」는
	   764px, 줄의 주소 칸은 936px 에서 시작했다(실측). `1fr` 하나만 남기고 나머지를 고정하면
	   남는 폭이 같으므로 두 격자가 같아진다. */
	grid-template-columns:
		6.5rem                     /* 고객사 */
		5.5rem                     /* 분야 — 값이 일곱 종뿐이고 전부 5~6자다. 가장 긴
		                              「영업·마케팅」이 69px 라 88px 이면 19px 이 남는다(실측).
		                              6.5rem 은 35px 이 남아, 그만큼을 이름 열이 못 썼다. */
		minmax(9rem, 1fr)          /* 이름 + 설명 — **하한을 준다.** 그리드는 남는 폭을 fr 보다
		                              먼저 minmax 상한에 채우므로(§12.6 → §12.7), 하한이 없으면
		                              주소 열이 이름 열을 0px 로 밀어낸다(실측 1100px). */
		26rem                      /* 주소 — **잘리지 않는 폭.** 가장 긴 주소가
		                              `https://cp-receipt-tracker-agent-dev.popupstudio.ai` 이고
		                              그 글자가 337px, 칩의 나머지 칸(이름 4ch · 점 7px · 코드
		                              3.5ch)과 간격이 73px 이라 410px 이 필요하다(실측).
		                              25rem(400px)이던 시절에는 그 한 줄이 잘렸다.
		                              **고정 폭이어야 한다** — `minmax` 로 두면 남는 폭에 따라
		                              줄어들어 다시 잘린다. */
		6rem                       /* 담당자 */
		6rem                       /* 점검 시각 — **가능한 값**으로 잡는다. 지금 화면은
		                              「2분 전 점검」(64px)이지만 이 값은 시간이 지나면 자란다:
		                              「23시간 전 점검」이 81px 로 최대다(실측). 5rem(80px)으로
		                              두면 하루만 지나도 이 열이 잘린다 — «지금 보이는 것» 이
		                              아니라 «나올 수 있는 것» 으로 재야 하는 열이다. */
		9rem;                      /* 도구 — 점검·편집·삭제 셋. 7.5rem 이던 시절엔 셋이 넘쳤다 */
	gap: 0 1rem;
	/* ── 수직 정렬 ── 줄에는 **두 종류의 칸**이 있다.
	     · 여러 줄 블록(이름+설명 · 주소 두 줄) → **위쪽**. 블록은 시작이 맞아야 두 블록의
	       첫 줄이 한 줄로 읽힌다(아래 `align-self: start`).
	     · 한 줄 칸(고객사 · 분야 · 담당자 · 점검 시각 · 도구) → **가운데**.
	   전부 `baseline` 으로 두었더니 한 줄 칸이 모두 첫 줄에 붙어 줄의 아래 절반이 비고,
	   오른쪽이 위로 쏠려 두 줄 블록과 «다른 줄» 처럼 보였다(실측). 가운데로 내리면 한 줄
	   칸들이 블록의 중간 높이에 서서 줄 하나가 한 띠로 읽힌다.
	   **아래쪽은 쓰지 않는다.** 점검 시각을 아래에 붙여 봤지만 담당자는 가운데, 시각은 아래,
	   도구는 가운데가 되어 오른쪽 끝이 들쭉날쭉해진다 — 아래쪽에 속하는 것이 이 줄에는 없다. */
	align-items: center;
}

/* 주소 블록만 위에서 시작한다 — 그 블록이 줄의 높이를 정한다(두 줄 × 24px).

   **이름 블록은 가운데다.** 처음에는 «여러 줄 블록은 둘 다 위에서 시작» 이라는 규칙이었는데,
   이름 블록이 주소 블록보다 8px 짧아 그 차이가 전부 아래로 몰렸다 — 위 여백 0 · 아래 8
   (잉크로 재면 2 · 11)이라 «가운데인데 아래가 넓다» 로 보였다(사용자 지적).

   위에서 시작할 때의 명분은 «두 블록의 첫 줄이 한 줄에 선다» 였는데, 실측해 보면 그렇지도
   않았다: 이름의 잉크는 위에서 2px, 주소의 잉크는 6px 에서 시작한다(칩이 24px 안에서 글자를
   가운데 두기 때문). 즉 얻는 것 없이 비대칭만 남았다. 가운데로 두면 잉크가 6~7px 에서
   시작해 오히려 주소 첫 줄과 맞는다. */
.entry-urls {
	align-self: start;
}

.entry-main {
	align-self: center;
}

/* 표 머리 = **등록부의 라벨 줄**. 홈의 칸 라벨과 같은 규격(고정폭·micro·자간 0.2em)이고,
   아래위 선 두 줄이던 것을 **아래 한 줄**로 줄인다 — 위 선은 구획 라벨 막이 이미 그었다. */
.entry-head {
	/* 기본은 표의 머리(격자)다. 정렬 줄이 되는 조건에서는 위 변수가 `flex` 로 바뀐다. */
	display: var(--head-mode, grid);
	flex-wrap: wrap;
	gap: var(--head-gap, 0 1rem);
	/* 아래 숨은 **정렬 줄일 때만** 준다(`--head-below`). 표의 머리와 첫 줄은 붙어 있는 것이
	   표의 문법이지만, 카드·피드에서 머리는 정렬 줄이라 붙으면 그 아래 선과 카드의 테두리가
	   맞닿아 선 두 개로 보인다(실측: 간격 0px). 값은 카드 격자의 홈통과 같은 0.75rem —
	   첫 줄까지의 거리가 줄 사이 거리와 같아야 한 격자로 읽힌다. */
	margin-bottom: var(--head-below, 0);
	padding: 0.4rem 0 0.5rem;
	/* 위 선을 다시 켰다(단추 간격을 보기 위해). 한때 «위 선은 구획 라벨 막이 이미 그었다» 며
	   아래 한 줄로 줄였던 자리다 — 되돌리려면 `border-block` → `border-bottom`. */
	border-block: 1px solid var(--line-strong);
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	letter-spacing: 0.04em;   /* 한글 음절이 갈라지지 않는 한도 — `.act-title` 주석 참조 */
	color: var(--fg-3);
}

/* 누를 수 있는 것은 **24px 이상**이다(WCAG SC 2.5.8). 글자 크기만 따르면 20px 이 되고,
   그건 「눌러도 안 눌리는」 열 이름이다 — 글자는 그대로 두고 높이만 확보한다. */
.col-sort {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* **가로도 24px 이다.** 열 이름을 고정폭 micro 로 줄이자 두 글자 이름(「분야」·「이름」)이
	   22px 이 되어 최소 표적을 밑돌았다(실측) — 글자를 작게 만드는 변경은 표적 크기를 함께
	   깎는다. 높이만 잡아 둔 규칙이 그것을 못 막았다. */
	min-width: var(--tap-min);
	min-height: var(--tap-min);
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	color: var(--fg-3);
	cursor: pointer;
}

@media (hover: hover) {
	.col-sort:hover {
		color: var(--fg);
	}
}

[aria-sort='ascending'] .col-sort,
[aria-sort='descending'] .col-sort {
	color: var(--fg);
}

/* ── 방향 표시 ──
   정렬은 처음부터 있었지만 표시가 **색뿐**이었다(흐린 이름 → 진한 이름). 그래서 이 열들이
   눌린다는 것 자체가 보이지 않았다 — 사용자가 「정렬 화살표 기능을 추가해 달라」 고 했고,
   기능은 이미 있었다. 없던 것은 **손잡이라는 신호**다.

   **자리는 항상 잡아 둔다.** 활성일 때만 글리프를 두면 정렬을 옮길 때마다 머리글 폭이
   바뀌는데, 머리와 줄은 서로 다른 격자라(위 «열 폭» 주석) 폭이 흔들리면 열이 어긋난 것처럼
   보인다. 그래서 비활성에도 같은 크기의 흐린 삼각형을 둔다.

   **글리프(▾)가 아니라 테두리로 그린다.** 고정폭 글꼴에 이 문자가 없으면 대체 글꼴로 떨어져
   크기·기준선이 달라진다 — 표의 머리글에서 그건 열마다 다른 화살표가 된다. 테두리 삼각형은
   글꼴과 무관하게 6.4×4px 다. */
.col-sort {
	gap: 0.3rem;
}

.col-sort::after {
	content: '';
	flex: none;
	width: 0;
	height: 0;
	border-inline: 0.2rem solid transparent;
	/* 라벨(`--fg-3`)보다 약하되 «있다» 는 것은 보여야 한다. `--line-strong` 은 선 색이라
	   1.5:1 로 거의 안 보였고, `--fg-3` 그대로면 머리글에 진한 삼각형 다섯 개가 선다.
	   토큰에서 파생시킨다 — 색을 새로 하드코딩하지 않는다. */
	border-top: 0.25rem solid color-mix(in srgb, var(--fg-3) 45%, transparent);
	border-bottom: 0 solid transparent;
}

@media (hover: hover) {
	.col-sort:hover::after {
		border-top-color: var(--fg-2);
	}
}

/* 활성 — 방향을 뒤집는다. 높이(4px)와 폭(6.4px)은 그대로다: 어느 쪽이든 테두리 하나만
   색을 갖고 나머지는 0 이다. */
.col-sort.is-sorted::after {
	border-top-width: 0;
	border-bottom: 0.25rem solid var(--fg);
}

.col-sort.is-sorted.is-desc::after {
	border-top: 0.25rem solid var(--fg);
	border-bottom-width: 0;
}

/* ── 왼쪽 홈통 ── 홈의 등록부는 줄마다 `│ ` 로 시작한다. 그 홈통을 여기서는 **1px 선**으로
   그린다: 표의 왼쪽 끝을 따라 내려가 «이 줄들은 한 판 안의 내용» 이라고 말한다.
   머리와 줄에 **같은 값**을 주어야 열이 어긋나지 않는다(둘은 서로 다른 격자 컨테이너다). */
.entry-head,
.entries[data-view='list'] .entry {
	padding-left: 0.85rem;
	border-left: 1px solid var(--line);
}

.entries {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* **등록부는 닫힌다.** 홈의 판이 `╰───` 로 닫히는 자리다 — 마지막 줄의 옅은 밑줄만 있으면
   목록이 «잘려서 끝난» 것처럼 보인다(다음 줄이 더 있는지 알 수 없다). */
.entries[data-view='list'] {
	border-bottom: 1px solid var(--line-strong);
}

.entry {
	padding: 0.55rem 0;
	border-bottom: 1px solid var(--line);
}

@media (hover: hover) {
	/* 줄 전체가 손에 반응한다 — 어느 줄을 보고 있는지가 표에서 가장 자주 잃는 정보다. */
.entries[data-view='list'] .entry:hover {
		background: var(--bg-2);
	}
}

/* 이름 링크의 덮개(`.entry-name::after`)가 이 칸을 기준으로 펴진다. */
.entry-main {
	display: block;
	position: relative;
	min-width: 0;
	color: inherit;
	text-decoration: none;
}

/* 고객사·분야 — 각자 열이다. 이름보다 한 단계 낮은 잉크로 둔다: 이 표의 주어는 이름이고
   이 둘은 그 이름이 «어디에 속하는가» 다. */
.entry-project,
.entry-work {
	min-width: 0;
	overflow: hidden;
	font-size: var(--t-sm);
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* 고객사·분야는 **읽는 글자**라 본문 서체를 유지한다(한글이 들어온다). 다만 이름보다 한
   단계 작고 옅게 두어, 줄의 주어가 이름이라는 것이 서체 무게로 먼저 읽히게 한다. */
.entry-project {
	color: var(--fg-2);
}

.entry-work {
	color: var(--fg-3);
}

/* 이름 줄 = 이름 + 배지. 배지는 고정, **이름이 줄어든다** — 이 열은 `minmax(9rem, 1fr)`
   이라 좁아지면 누군가는 줄어야 하는데, 잘린 배지는 뜻을 잃고 잘린 이름은 안 잃는다. */
.entry-title {
	display: flex;
	align-items: center;
	gap: 0.3rem;
	min-width: 0;
	margin: 0 0 0.15rem;
}

/* **이름만 `<a>` 다.** 칸 전체를 앵커로 감싸면 그 안의 미지정 배지 단추가 링크 안의 단추가
   된다(무효 HTML). 대신 아래 `::after` 로 이 링크를 칸 전체까지 늘려서 «칸 아무 데나 눌러도
   상세로 간다» 는 성질을 지킨다. */
.entry-name {
	min-width: 0;
	overflow: hidden;
	font-size: var(--t-base);
	font-weight: 600;
	color: var(--fg);
	white-space: nowrap;
	text-overflow: ellipsis;
	text-decoration: none;
	/* 이름은 이제 **그 자체가 링크**다 — 누르는 것이라 24px 이어야 한다(SC 2.5.8).
	   `min-height` 가 아니라 `line-height` 로 주는 이유는 말줄임(`text-overflow`)이
	   글자 상자 안에서 일어나야 해서다: 상자만 키우면 글자가 위에 붙는다. */
	line-height: var(--tap-min);
}

/* 늘린 링크 — 이름 칸(`.entry-main`) 전체를 덮는다. 이름 글자 폭만 누를 수 있게 두면 짧은
   이름일수록 표적이 작아진다(실측 25px). 배지는 아래에서 이 덮개 위로 올린다. */
.entry-name::after {
	content: '';
	position: absolute;
	inset: 0;
}

/* 계약·진행 **한 쌍의 겹**(`core/value-controls.js` 가 짓는다). 표·피드에서는 인라인
   한 덩어리로 이름 뒤에 붙고, 카드에서는 이 겹 하나가 우측 상단으로 간다 — 쌍을 옮기는
   자리가 한 곳이라 «앞이 계약, 뒤가 진행» 이 어느 보기에서도 갈리지 않는다.

   겹 자신이 덮개(`.entry-name::after`) **위**에 있어야 누른 것이 배지가 된다 — 덮개 아래에
   두면 배지를 눌러도 상세로 넘어간다(전에는 `.tag` 하나하나에 걸던 규칙이다). */
.entry-axes {
	display: inline-flex;
	position: relative;
	z-index: 1;
	/* **겹은 줄어들지 않는다 — 이름이 대신 줄어든다.** 잘린 배지는 무슨 값인지 알 수 없지만
	   이름은 앞부분만으로도 찾는다(전에 배지 하나하나에 걸어 둔 약속이고, 겹이 생겼으니 겹에도
	   있어야 한다 — 지금은 배지들의 min-content 가 겹을 지켜 주지만 그것은 우연이다). */
	flex: none;
	align-items: center;
	gap: 0.3rem;
}

@media (hover: hover) {
	/* 목록에서만 — 줄이 이미 `--bg-2` 라 담당자 단추의 호버 배경이 그 색이면 표시가 사라진다.
   («정해진 값» 단추와 고르개 자체는 상세도 쓰므로 `shell/base.css` 에 있다.) */
.entry:hover .cell-set:hover {
		background: var(--bg);     /* 줄이 이미 --bg-2 다 — 같은 색이면 표시가 사라진다 */
	}
}

/* 담당자는 **고정폭**이다. 값이 전부 라틴 소문자(`hykim`·`gun`·`ubuntu(chris)`)라 세로로
   훑는 열이고, 홈의 등록부에서도 담당은 줄 끝의 고정폭 메타다 — 같은 값을 같은 서체로 둔다.
   미지정(`미지정`)만 한글인데 그 한 낱말은 폭이 흔들려도 열을 밀지 않는다(열이 고정폭). */
.entry-owner {
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	color: var(--fg-2);
}

/* 점검 시각은 고정폭 — 「3분 전」·「방금」처럼 길이가 들쭉날쭉해서 비례 서체로 두면
   열이 흔들려 보인다. */
.entry-checked {
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	color: var(--fg-3);
}

.entry-tools {
	display: flex;
	gap: 0.35rem;
}

/* ── 도구 셋의 색 ── **잉크와 테두리에만** 준다(면을 칠하지 않는다). 채운 단추는 줄에서
   가장 강한 것이 되어, 이 표의 신호인 상태 점·응답 코드보다 먼저 눈에 든다.

   셋의 무게가 다른 것이 요점이다:
     점검  액센트 — 가장 자주 하고 되돌릴 수 있는 일
     편집  중립   — 평범한 일. 색을 주면 셋이 다 소리치게 된다
     삭제  위험색 — 되돌릴 수 없는 일. 다만 **평소에는 조용하고** 손이 닿을 때 진해진다
                    (늘 빨간 단추는 «지우기» 를 권하는 꼴이다 — 셸의 `.is-danger` 규칙) */
.entry-tools .btn[data-action='check'] {
	border-color: var(--accent);
	color: var(--accent);
}
.entry-tools .btn[data-action='check']:focus-visible {
	background: var(--accent-soft);
	border-color: var(--accent);
	color: var(--accent);
}

/* 초점은 **가드 밖**이다 — 키보드는 기기와 무관하다. */

@media (hover: hover) {
	.entry-tools .btn[data-action='check']:hover {
		background: var(--accent-soft);
		border-color: var(--accent);
		color: var(--accent);
	}
}

.entry-tools .btn[data-action='edit'] {
	color: var(--fg-2);
}

.entry-tools .btn[data-action='delete'] {
	border-color: var(--line);
	color: var(--bad);
}

/* ── 비어 있음 ── 조건에 맞는 것이 없을 때. 지면 한가운데가 아니라 **표가 있던 자리**에 둔다. */
/* 가운데 정렬을 쓰지 않는다. 홈이 «없음» 을 말하는 방식은 `⎿ nothing to fix` — 다른 줄과
   같은 자리에서 시작하는 한 줄이다. 가운데로 띄우면 그것만 다른 화면의 조각처럼 보인다. */
.empty {
	padding: 1.6rem 0 1.6rem 0.85rem;
	border-left: 1px solid var(--line);
	border-bottom: 1px solid var(--line-strong);
}

.empty-title {
	margin: 0 0 0.3rem;
	font-family: var(--font-mono);
	font-size: var(--t-sm);
	font-weight: 400;
	color: var(--fg-2);
}

.empty-desc {
	margin: 0;
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	color: var(--fg-3);
}

/* ── 카드·피드 ──
   리스트가 기준이고 나머지 둘은 같은 줄을 다르게 접은 것이다.

   **머리는 열 이름이 아니라 «정렬 줄» 이 된다.** 카드 격자 위에 일곱 칸 짜리 열 이름이 그대로
   서 있으면 아래 카드와 칸이 맞지 않아 길 잃은 줄로 읽힌다(실측). 그렇다고 감출 수는 없다 —
   정렬 손잡이가 여기밖에 없다. 그래서 격자를 풀어 손잡이를 한 줄로 늘어놓고, 손잡이가 없는
   칸(주소·도구)은 그 줄에서 뺀다: 누를 수 없는 낱말이 손잡이 사이에 섞이면 어느 것이 눌리는지
   알 수 없다. */
/* **정렬 줄이 되는 조건은 둘이다**: ① 표가 아닐 때(카드·피드) ② 표를 접었을 때. 선언을 두 곳에
   복사하지 않으려고 «모양» 을 변수로 받는다 — 조건 쪽은 변수만 바꾼다(`--head-*`). */
.entry-head:has(~ .entries:not([data-view='list'])) {
	--head-mode: flex;
	--head-gap: 0.25rem 1.1rem;
	--head-quiet: none;
	--head-below: 0.75rem;
}

.entry-head .col-static,
.entry-head [role='columnheader']:has(.sr-only) {
	display: var(--head-quiet, block);
}

/* 카드·피드의 줄은 **블록이 쌓인다.** 간격이 없으면 값들이 붙어 「사내영업·마케팅」·
   「ubuntu(chris)방금 점검」처럼 한 낱말로 읽힌다(실측). */
.entries:not([data-view='list']) .entry {
	display: grid;
	gap: 0.4rem;
	align-content: start;
}

/* ── 카드·피드에서 주소는 **항상 접는다** ── 표에서는 열 폭이 정해져 있어 접기 규칙을 접힌
   화면에만 두었지만(`@container results`), 카드는 폭이 18rem 이라 **넓은 화면에서도** 칸이
   좁다 — 1440px 에서 주소 36건이 잘렸다(실측). 「자른 주소는 복사해도 쓸 수 없다」는 이 화면의
   규칙이므로, 이 두 보기에서는 폭과 무관하게 접는다. */
.entries:not([data-view='list']) .url-chip {
	white-space: normal;
}

/* 끊는 자리는 **주소의 이음매**를 먼저 쓴다(`/`·`-`·`.` 뒤). `word-break: break-all` 은
   글자 단위로 끊어서 마지막 줄에 한 글자만 남기도 했다(실측: 「…popupstudio.a」 / 「i」).
   `overflow-wrap: anywhere` 는 «넘칠 때만» 끊고 이음매를 먼저 고르므로 읽을 수 있는 조각이
   된다 — 그래도 끊을 자리가 없으면(한 낱말이 칸보다 길면) 어디서든 끊는다. */
.entries:not([data-view='list']) .url-chip-host {
	overflow: visible;
	text-overflow: clip;
	overflow-wrap: anywhere;
}

/* 카드에서 꺾이는 것은 **우연이 아니라 규칙**이다. 카드 폭은 18rem(내부 269px)이고 가장 긴
   주소는 337px 이라, 어떤 현실적인 카드 폭으로도 4열에서는 한 줄에 들어가지 않는다(한 줄에
   넣으려면 카드가 439px 이어야 하고 그러면 1440px 에서 3열이 된다 — 실측). 주소를 자르거나
   `https://` 를 지우는 대신 **두 줄을 정식으로 허용**한다(사용자 결정).

   그래서 두 가지를 고정한다:
     ① 칩의 줄 높이를 한 칸(24px)으로 → 칩 높이는 늘 24 의 배수다(한 줄 24 · 꺾이면 48 ·
        프로젝트명 자체가 칸보다 길면 72). 줄 높이 16.5px 이면 꺾인 칩이 33px 이 되어 그 아래
        블록이 9px 씩 어긋난다.
     ② 꺾이는 자리는 **주소의 뜻**이 정한다(아래 `.url-part`) — 브라우저가 이음매를 아무 데서나
        고르지 않게. */
.entries[data-view='card'] .url-chip {
	line-height: var(--tap-min);
	/* 슬롯·점·코드는 주소의 **첫 줄**에 속한다 — 가운데 정렬로 두면 두 줄짜리 주소의 사이에
	   걸려 「DEV」가 어느 줄의 것인지 알 수 없었다(실측).

	   `baseline` 로도 해 봤지만 안 된다: 인라인블록의 기준선은 **마지막 줄**의 것이라, 주소의
	   앞 조각이 두 줄이 되는 좁은 카드에서 「PROD」가 둘째 줄로 내려갔다(실측 1000px). */
	align-items: start;
}

/* 점은 글자가 아니라 7px 사각형이라 위 정렬에서는 칸의 맨 위에 붙는다 — 첫 줄(한 칸)의
   가운데로 내린다. 값은 «칸 − 점» 의 절반이라 토큰에서 계산된다(점 크기는 셸이 정한다).
   카드 안의 `.dot` 은 주소 칩에만 있다(배지는 `.tag`, 담당자는 `.cell-set`). */
.entries[data-view='card'] .dot {
	margin-top: calc((var(--tap-min) - 7px) / 2);
}

.entries[data-view='card'] .url-chip-host {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

/* 꺾이는 자리는 **주소의 뜻**이 정한다 — 마크업이 두 조각으로 오고(`splitAddress`), 카드에서
   그 조각을 각자 상자로 둔다: 두 조각이 한 줄에 들면 한 줄, 안 들면 조각 경계에서 꺾인다.

     PROD  https://agentv.               DEV  https://cp-marketing-agent-
           popupstudio.ai                     dev.popupstudio.ai

   브라우저에 맡기면(`overflow-wrap: anywhere`) 이음매를 아무 데서나 골라 마지막 줄에 한
   글자만 남기도 했다(실측 4칸). 조각 자체가 칸보다 길면 그때만 조각 안에서 끊는다 —
   그것이 `overflow-wrap` 이 여기서 «마지막 수단» 인 이유다(실측: 카드가 305px 인 폭에서
   `https://cp-receipt-tracker-agent-` 가 두 줄이 되어 칩이 72px 이 된다. 24 의 배수는 지킨다). */
.entries[data-view='card'] .url-part {
	display: inline-block;
	overflow-wrap: anywhere;
}

/* ── 고객사 · 분야는 **한 줄**이다 ── 상세의 제목이 「고객사 · 서비스명」인 것과 같은 짜임이다:
   «어디에 속하나» 는 한 줄, «무엇인가» 는 그 아래.

   전에는 두 줄로 쌓였다(고객사 / 분야) — 그만큼 카드가 높았다. **격자에서 한 줄은 «같은 행에
   놓기» 다**: 두 요소가 서로 다른 열·같은 행을 받아야 한 줄이 된다(마크업은 그대로).
   구분자는 상세 제목과 같은 가운뎃점이고, 값이 아니라 구분자라 잉크를 한 단 내린다. */
.entries:not([data-view='list']) .entry-project {
	grid-area: who-a;
	justify-self: start;
}

/* 이 줄은 카드의 **눈썹**이다 — 표에서는 고객사·분야가 각자 «열» 이라 이름과 같은 급이어도
   열 위치가 층위를 말해 주지만, 카드에는 열이 없어 글자 크기만 남는다. 13px 로 두면 바로
   아래 설명(13px)과 같은 급이 되어 «머리» 로 읽히지 않았다(실측: 눈썹 13 · 이름 14 · 설명 13).
   서체는 그대로 둔다 — 한글이 들어오는 읽는 글자다. */
.entries:not([data-view='list']) .entry-project,
.entries:not([data-view='list']) .entry-work {
	font-size: var(--t-micro);
}

.entries:not([data-view='list']) .entry-work {
	grid-area: who-b;
	display: flex;
	align-items: baseline;
	gap: 0.4rem;
	margin: 0;
}

.entries:not([data-view='list']) .entry-work::before {
	content: '·';
	color: var(--fg-3);
}

/* 나머지 다섯 칸의 **자리 이름**. 카드와 피드가 같은 이름을 쓰고, 두 보기는 그 이름을 서로
   다른 격자에 배치한다(카드는 한 열, 피드는 두 열) — 이름을 한 곳에 두면 배치만 갈린다.
   한때 카드에만 지정해서 피드가 자동 배치로 떨어져 값들이 흩어졌다(실측). */
.entries:not([data-view='list']) .entry-main { grid-area: main; }
.entries:not([data-view='list']) .entry-urls { grid-area: urls; }
.entries:not([data-view='list']) .entry-owner { grid-area: owner; }
.entries:not([data-view='list']) .entry-checked { grid-area: checked; }
.entries:not([data-view='list']) .entry-tools { grid-area: tools; }

/* 피드도 **카드와 같은 리듬**이다 — 줄이 각자 테두리를 가진 블록이므로 줄 사이는 밑줄이
   아니라 홈통(0.75rem)이 만든다. 카드 격자의 `gap` 과 같은 값이라 보기를 바꿔도 덩어리
   사이의 거리가 그대로다. */
.entries[data-view='feed'] {
	display: grid;
	gap: 0.75rem;
}

.entries[data-view='card'] {
	/* 배지 쌍이 앉을 모서리의 **예약 폭**. 감이 아니라 «나올 수 있는 값» 으로 잡는다:
	   낱말이 가장 긴 조합은 「사내 서비스」+「서비스 종료」로 143px 이고(실측, 두 배지 + 겹의
	   0.3rem), 눈썹의 분야와 붙지 않게 9px 을 더해 152px = 9.5rem 이다. 낱말이 늘면 이 값을
	   다시 재야 한다 — 회귀 검사가 실제 배지 폭과 이 값을 비교한다. */
	--axes-w: 9.5rem;
	display: grid;
	/* 카드 최소 폭 **19rem**. 18rem 이면 1920px 이상에서 5열(카드 298px)이 되어 주소가
	   61칸에서 꺾이고 그중 4칸은 마지막 줄에 한 글자만 남았다. 19rem 은 같은 지면에서 4열
	   (375px)이 되어 꺾임이 9칸으로 줄고 짧은 꼬리가 0이 된다(실측). 그 아래 폭에서는 두
	   값이 같은 열 수를 내므로 손해가 없다. 카드가 넓어진 만큼 높이는 299→256px 로 줄었다. */
	grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
	gap: 0.75rem;
}

.entries[data-view='card'] .entry {
	/* 세 칸이다. 첫 행은 눈썹(고객사 · 분야)과 **배지 자리**, 마지막 행은 점검 시각과 단추,
	   나머지는 한 칸을 다 쓴다.

	   `axes` 칸에는 **아무 아이템도 넣지 않는다** — 배지 쌍(`.entry-axes`)은 마크업상
	   이름 줄 안에 있어 이 격자의 아이템이 아니고, 아래에서 절대배치로 이 칸 위에 앉는다.
	   그래도 칸을 «비워 둔 채로 잡아» 두는 이유는, 그러지 않으면 분야가 배지 밑으로
	   들어가기 때문이다(흐름에서 빠진 상자는 글자가 그 존재를 모른다). 칸을 잡아 두면
	   분야는 그 경계에서 말줄임된다 — 값이 길어져도 겹치지 않는다. */
	grid-template-columns: auto minmax(0, 1fr) var(--axes-w);
	grid-template-areas:
		"who-a   who-b axes"
		"main    main  main"
		"urls    urls  urls"
		"owner  owner owner"
		"footer footer footer";
	/* **남는 높이는 주소 행이 먹는다.** 격자는 한 줄의 카드를 가장 높은 것에 맞춰 늘리는데,
	   그 남는 높이를 어디에 두느냐가 «무엇이 자리가 고정되는가» 를 정한다.

	   길이가 변하는 것은 «내용» 이다 — 설명(1~2줄)과 주소(칩 24·48·72px). 그 아래의 담당자·
	   점검·단추는 **메타와 동작**이라 카드마다 같은 자리에 있어야 훑을 수 있다. 그래서 주소
	   행에 `1fr` 을 주어 남는 높이를 거기로 보내면, 담당자가 아래 구분선 바로 위에 붙고 그
	   아래 동작 줄도 바닥에 붙는다(주소 길이 때문에 담당자의 y 가 카드마다 달라지던 것을
	   고친 것이다 — 사용자 지적).

	   마지막 행에 `1fr` 을 주었을 때는 도구 줄만 바닥에 붙고 담당자는 주소를 따라 떠 있었다.
	   행이 모두 `auto` 면 남는 높이가 마지막 행 «아래» 에 고여 단추의 y 마저 카드마다 달라진다
	   (실측 20px 차). `margin-top: auto` 는 여기서 듣지 않는다: 격자 아이템은 **자기 행
	   안에서만** 움직인다(카드는 flex 가 아니다). */
	grid-template-rows: auto auto 1fr auto auto;
	position: relative;
	padding: 0.9rem;
	border: 1px solid var(--line);
}

/* ── 계약·진행 배지는 카드의 **우측 상단**이다 ── 눈썹과 같은 줄, 오른쪽 끝.

   카드에는 열이 없어 배지가 이름 옆에 있으면 이름 길이에 따라 x 가 카드마다 달라지고, 좁을
   때는 다음 줄로 내려갔다(실측: 폭에 따라 0~6건). 모서리는 이름 길이와 무관한 **한 자리**다.

   절대배치인 이유는 이 쌍이 마크업상 이름 줄(`.entry-title`) 안에 있어서다 — 표에서는 배지가
   이름 바로 뒤에 붙어야 하고(그 설계가 옳다), 카드만을 위해 마크업을 형제로 빼면 표에 배지
   열이 새로 생겨 머리와 줄의 격자가 갈린다(이 프로젝트가 이미 어긋났던 자리: 머리 764 vs
   줄 936). 위 격자의 `axes` 칸이 자리를 예약하므로 겹침은 구조적으로 막혀 있다.

   `top`·`right` 는 카드의 안쪽 여백(`padding: 0.9rem`)과 같은 값이라 눈썹과 같은 줄에 선다. */
.entries[data-view='card'] .entry-axes {
	position: absolute;
	top: 0.9rem;
	right: 0.9rem;
	z-index: 1;
}

/* 모서리의 기준점은 **카드**여야 한다. 표에서 이름 칸(`.entry-main`)이 `position: relative`
   인 것은 그 칸 전체를 덮는 링크 덮개(`.entry-name::after`) 때문인데, 그 덮개가 살아 있으면
   위 배지 쌍이 카드가 아니라 이름 칸을 기준으로 앉아 이름 줄 옆으로 돌아간다(실측: 위 53px).

   **카드에서는 그 덮개가 필요 없다.** 덮개는 표에서 이름 «글자만» 누를 수 있어 표적이 25px
   까지 작아지던 것을 고치려고 둔 것이고(실측), 카드에서 이름은 이미 한 줄을 다 쓰는 블록이라
   표적이 줄 전체다. 덮개를 끄고 이름 칸의 좌표계도 카드에 넘긴다. */
.entries[data-view='card'] .entry-main {
	position: static;
}

.entries[data-view='card'] .entry-name::after {
	content: none;
}

/* 카드의 설명은 **두 줄까지**다. 표는 한 줄, 상세는 전문이고 카드는 그 사이다 —
   풀어 두면 설명 길이대로 줄 수가 갈리고(1~4줄) 그만큼 아래 블록(주소·담당자·점검)의 y 가
   카드마다 어긋난다. 격자는 «같은 것이 같은 높이에» 있어야 열을 따라 훑을 수 있다.
   (`shell/value.css` 의 `:not([data-view='list'])` 가 `nowrap` 을 이미 풀어 놨다.) */
.entries[data-view='card'] .entry-desc {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
}

/* 이름도 **두 줄까지** 쓴다. 카드 폭이 18rem 이라 긴 이름이 한 줄에 안 들어가 말줄임됐다
   (`codepresso_marketing_ag…` — 실측). 표에서는 열 폭이 정해져 한 줄로 접는 것이 맞지만,
   카드에는 아래로 한 줄 더 쓸 자리가 있다. **이름은 이 카드의 주어라 잘리면 안 된다.**
   기본 규칙(`.entry-name`)의 `nowrap`·`ellipsis`·`line-height` 를 여기서 되돌린다 —
   두 줄일 때 `line-height: var(--tap-min)`(24px) 은 줄 간격이 아니라 «한 줄의 높이» 라
   48px 이 되어 배지 줄과 어긋난다. 표적 높이는 두 줄이 이미 채운다. */
/* **이름 줄 아래에 선을 하나 둔다** — 카드의 해부를 상세와 같게 만든다:
   제목 → 선 → 값 → 선 → 동작줄(`.detail-actions` 위의 선). 선이 없으면 설명이 이름에
   붙어 한 덩어리로 읽혔다. 피드에는 두지 않는다(거기서는 세로 선이 그 몫을 한다).
   이 줄에는 이름만 남는다 — 배지 쌍은 위에서 모서리로 갔다. */
.entries[data-view='card'] .entry-title {
	padding-bottom: 0.5rem;
	margin-bottom: 0.55rem;
	border-bottom: 1px solid var(--line);
}

.entries[data-view='card'] .entry-name {
	/* 카드의 주어는 한 단 크다 — 표에서는 첫 열이라는 자리가 그것을 말하지만 카드에서는
	   크기가 말한다(눈썹 11 · 이름 16 · 설명 13 의 세 단). */
	font-size: var(--t-lg);
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	white-space: normal;
	text-overflow: clip;
	overflow-wrap: anywhere;
	line-height: 1.5;
}

/* 도구 줄은 카드의 **바닥**이다 — 상세가 정의표와 동작 줄 사이에 선을 하나 두는 것과 같다
   (`.detail-actions` 위의 선). 선이 없으면 단추가 마지막 값과 한 덩어리로 읽힌다.
   피드에는 두지 않는다: 거기서는 세로 선이 이미 그 몫을 하고, 가로선을 더하면 격자가 된다.

   **단추는 오른쪽이다.** 이 제품의 다른 자리가 모두 그렇다 — 표의 도구 열은 줄 끝, 상세의
   동작 줄과 서랍의 저장·취소는 `flex-end`. 카드만 왼쪽이면 그 하나가 예외가 된다.
   카드 폭이 서로 다르면 오른쪽 정렬이 카드마다 어긋나지만, 이 격자는 `auto-fill … 1fr` 이라
   **폭이 모두 같다** — 열마다 단추의 x 가 정확히 맞는다(실측). */
/* ── 카드·피드의 열 이름 ── 값 앞에 그 열의 이름을 붙인다.

   표에서는 머리(`.entry-head`)가 「무엇인지」를 말한다. 두 보기에는 머리가 없어 값만 남고,
   `ubuntu(chris)` · `방금 점검` 이 무엇인지 알 수 없었다(실측 지적). 글자는 마크업의
   `data-label` 한 곳에 있고 여기서 `attr()` 로 읽는다 — 두 번 적지 않는다.

   규격은 표 머리와 같다(고정폭 · micro · 자간) — 같은 일을 하는 글자는 같게 보여야 한다. */
.entries:not([data-view='list']) .entry-owner,
.entries:not([data-view='list']) .entry-checked {
	/* **상세의 정의표와 같은 짜임**(`.detail-row`): 라벨 칸이 고정이고 값이 남은 폭을 쓴다.
	   전에는 `::before` 가 글자 흐름 안에 있어 값의 시작이 라벨 길이에 따라 흔들렸다
	   (「담당자 ubuntu(chris)」 / 「점검 시각 방금 점검」의 값 x 가 달랐다). */
	display: grid;
	/* 라벨 칸의 폭은 **주소 줄의 값이 시작하는 x** 다(`--value-x`, `shell/value.css`).
	   5.5rem 으로 두었을 때는 담당자 값이 주소보다 23px 오른쪽에서 시작해, 한 카드 안에서
	   값의 기준선이 둘이었다(실측). 라벨은 왼쪽 끝에서 시작하므로 간격은 그 폭에 포함돼
	   있고(`gap: 0`), 라벨이 그보다 길어지면 값을 밀지 않고 그 칸 안에서 처리된다. */
	grid-template-columns: var(--value-x) minmax(0, 1fr);
	align-items: baseline;
	/* 값은 **자기 폭만** 쓴다. 격자 아이템의 기본값(`stretch`)으로 두면 담당자의 점선
	   「미지정」 배지가 남은 폭 전체로 늘어나 입력칸처럼 보였다(실측 카드 폭 -5.5rem).
	   표에서는 배지가 인라인이라 이 문제가 없었다 — 격자로 옮기면서 생긴 것이다. */
	justify-items: start;
	gap: 0;
}

.entries:not([data-view='list']) .entry-owner::before,
.entries:not([data-view='list']) .entry-checked::before {
	content: attr(data-label);
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	letter-spacing: 0.04em;
	color: var(--fg-3);
}

/* ── 카드의 바닥 줄 ── **위 공용 규칙 뒤에 온다.** `.entries[data-view='card'] .entry-checked`
   와 `.entries:not([data-view='list']) .entry-checked` 는 특이도가 같아(0-3-0) 순서가 승부를
   가린다 — 앞에 두었을 때 공용 규칙의 라벨 격자(`5.5rem` + `attr()`)가 이겨서 라벨이 그대로
   찍히고 상자가 160px 로 넓어져 단추와 겹쳤다(실측 49칸). 특이도를 올려 이기지 않고 순서로
   푼다: 이기는 규칙이 뒤에 있는 것이 읽는 순서와도 같다. */
/* 점검 시각과 단추는 **바닥 줄 하나를 나눠 쓴다** — 왼쪽이 「언제 본 것인가」, 오른쪽이
   「무엇을 할까」다. 라벨(`점검 시각`)을 떼는 이유는 값이 스스로를 말하기 때문이다:
   「방금 점검」·「1분 전 점검」에 이미 «점검» 이 들어 있어 라벨은 같은 낱말을 두 번 찍는다.
   (담당자는 값이 `ubuntu(chris)` 라 이름표가 없으면 무엇인지 알 수 없어 그대로 둔다.)
   덕분에 한 줄이 줄어 카드가 그만큼 낮아진다.

   **둘은 같은 칸(`footer`)에 있다.** 칸을 둘로 쪼개면 그 열 폭이 눈썹 줄과 공유돼(격자의 열은
   행마다 다를 수 없다) 첫 열이 「고객사」와 「1분 전 점검」 중 긴 쪽으로 잡히고, 좁은 카드에서는
   반대로 min-content 까지 줄어 점검 시각이 세 줄로 쪼개졌다(실측 2560px: 도구보다 50px 위).
   한 칸에 두 아이템을 넣고 하나는 `start`, 하나는 `end` 로 붙이면 열을 나누지 않아도 된다. */
.entries[data-view='card'] .entry-tools {
	grid-area: footer;
	/* 칸을 다 쓰되(선이 한 줄로 이어지도록) 단추는 오른쪽 끝에 모인다. */
	justify-self: stretch;
	justify-content: flex-end;
	/* 카드의 **바닥에 붙는다** — 위 `grid-template-rows` 의 `1fr` 행 안에서. */
	align-self: end;
	margin-top: 0.35rem;
	padding-top: 0.55rem;
	/* 선은 **이 아이템 하나가** 긋는다. 둘이 각자 그으면 폭이 내용만큼이라 카드 중간에서
	   끊긴 두 토막이 된다. */
	border-top: 1px solid var(--line);
}

.entries[data-view='card'] .entry-checked {
	grid-area: footer;
	/* 단추와 **세로 중심을 맞춘다.** 둘 다 바닥 정렬이라 상자 높이가 다르면 글자가 단추
	   밑선에 붙는다(실측: 글자 25px vs 단추 32px → 4px 아래로 처짐). 단추가 쓰는 토큰
	   (`--control-h-sm`)과 같은 높이를 주고 그 안에서 가운데 정렬하면 두 상자가 같아진다 —
	   숫자를 따로 두지 않는 이유는 단추 크기가 바뀌면 여기도 따라와야 해서다(터치 기기에서는
	   이 토큰이 44px 이 된다). */
	display: flex;
	align-items: center;
	min-height: var(--control-h-sm);
	justify-self: start;
	align-self: end;
	/* 단추와 같은 줄에 앉도록 위 여백을 맞춘다(선은 도구 줄이 그었다). */
	margin-top: 0.35rem;
	padding-top: 0.55rem;
	/* **쪼개지지 않는다** — 「1분 전 점검」은 한 값이다. 단추와 한 칸을 쓰므로 서로의 폭을
	   모르는데, `formatRelative` 가 만드는 가장 긴 값(「23시간 전 점검」 81px)과 단추 셋
	   (153px)을 더해도 가장 좁은 카드의 안쪽(259px)에 33px 을 남긴다(실측).
	   회귀 검사가 이 산수를 지킨다 — 낱말이 길어지면 거기서 걸린다. */
	white-space: nowrap;
	/* 선을 그은 도구 줄과 같은 칸이라 그 위에 앉아야 글자가 보인다. */
	position: relative;
}

.entries[data-view='card'] .entry-checked::before {
	content: none;
}


/* ── 피드 ── **사건의 흐름이다.** 줄 하나가 «한 서비스에 무슨 일이 있나» 를 말한다.

   테두리 있는 블록으로 만들었더니 「깔끔하지만 피드 느낌이 없다」(사용자 지적) — 상자는
   «따로 떨어진 것들» 이고 피드는 «이어지는 것» 이라, 상자를 세로로 쌓으면 카드 목록이 된다.

   그래서 이 제품이 이미 가진 문법을 쓴다 — 홈의 등록부와 같은 **Claude Code 의 줄**이다
   (`CLAUDE.md`: `⏺` 사건 점 · `⎿` 결과 연결 · 줄 끝의 흐린 메타). 왼쪽에 홈통을 두고
   머리 줄에 상태 색 점을 찍고, 나머지 줄을 세로 선으로 잇는다:

     ⏺ agentv  사내 · 영업·마케팅                       [사내 서비스] [미지정]
     │ 대량 메일 발송과 답장·리마인더 추적, …
     │ PROD ● 200 https://agentv.popupstudio.ai
     │ DEV  ● ERR https://agentv-dev.popupstudio.ai
     ╰ ubuntu(chris) · 2분 전 점검                        [점검] [편집] [삭제]

   테두리·구분선은 없다. 흐름을 끊는 것은 줄 사이의 여백뿐이다. */
.entries[data-view='feed'] {
	display: grid;
	/* 줄 사이의 절반. 나머지 절반은 각 줄의 `padding-bottom` 이 내고, 그 경계에 선이 있다 —
	   선 위아래가 같은 값이어야 선이 «두 줄 사이» 로 읽힌다(한쪽에 붙으면 아래 줄의 머리가 된다). */
	gap: 0.9rem;
}

.entries[data-view='feed'] .entry {
	/* 첫 열이 **홈통**이다(점과 세로 선의 자리). 이름과 흐린 메타가 머리 줄을 이루고,
	   오른쪽 끝 자리(10.5rem = 168px)는 배지 쌍과 단추가 나눠 쓴다 — 폭은 **단추 셋(153px) +
	   오른쪽 홈통(6px) + 점검 시각과의 틈(9px)** 이 정한다. 배지 최장 조합(143px)도 이 안에 든다.

	   이 틈이 «점검 시각과 단추의 거리» 다. 23px 일 때는 값이 단추에 붙어 보였고, 32px 로
	   넓히자 이번엔 값이 «동떨어져» 보였다(사용자 지적 둘) — 그 값은 점검 단추의 **이름표**라
	   단추에 딱 붙어야 한다. 9px 은 단추끼리의 간격(6px)보다 한 단만 넓은 값이다.

	   `.entry-main` 을 `display: contents` 로 풀어 **이름을 줄 하나로 끌어올린다** — 그래야
	   고객사·분야가 이름과 같은 줄에 앉는다(마크업에서는 이름이 설명과 함께 한 겹 안에 있다).
	   그 겹의 좌표계도 사라지므로 배지 쌍의 절대배치 기준이 줄 자신이 된다. */
	position: relative;
	/* 홈통 · 고객사(내용 폭) · 남은 폭 · 점검 시각(내용 폭) · 오른쪽 끝 자리.

	   **첫 줄이 눈썹**이다(고객사 · 분야). 점이 그 줄에 찍히고, 서비스명은 그 아래 자기 줄을
	   갖는다 — 카드·상세와 같은 순서다(«어디에 속하나» 먼저, «무엇인가» 다음).

	   둘째 열이 `auto` 인 것은 **고객사가 분야를 바로 뒤에 붙이기 위해서**다. 그 열을 다른
	   것과 나눠 쓰면 열 폭이 그 중 긴 쪽으로 잡혀 분야가 밀린다(실측 105~133px) — 그래서
	   이름·설명·주소·담당자는 모두 두 열 이상을 span 하고, span 안의 `1fr` 이 폭을 받는다. */
	grid-template-columns: 1.35rem auto minmax(0, 1fr) auto 10.5rem;
	grid-template-areas:
		"dot  who-a who-b who-b   axes"
		"rail title title title   ."
		"rail desc  desc  desc    ."
		"rail urls  urls  urls    ."
		"rail owner owner checked tools";
	column-gap: 0;
	/* ── 세로 간격은 **묶음**이 정한다 ── 모든 줄을 24px 한 칸에 앉혀 기준선을 고르게 했더니
	   「너무 일정해서 오히려 보기 힘들다」(사용자 지적). 간격이 전부 같으면 여섯 줄이 한 덩어리로
	   보여 어디가 이름이고 어디가 값인지 눈이 짚을 데가 없다 — 조판에서 간격은 «리듬» 이 아니라
	   «묶음» 을 말한다.

	   그래서 줄들을 네 묶음으로 나누고, **묶음 사이에만** 숨을 준다(`--feed-lead`):

	     눈썹 · 이름              «누구의 무엇인가»          ← 붙인다(둘이 한 제목이다)
	     설명                     «무엇을 하나»
	     PROD · DEV · 담당자       «어디 있나 · 누구 것인가»    ← 붙인다(이 서비스의 사실들이다)

	   마지막 줄은 담당자와 **한 행**을 쓰고 오른쪽 끝에 점검 시각·단추가 온다. 셋을 모두
	   **위 정렬**(`align-self: start`)로 두는 것이 요점이다:
	     · 가운데 정렬이었을 때는 행 높이가 단추(32px)로 잡혀 담당자가 주소에서 16px 밀렸다
	       (사용자 지적: 「PROD, DEV, 담당자 간격 너무 먼 거 아니야?」).
	     · 담당자만 자기 행으로 떼어 놓으니 이번엔 동작 줄이 아래에 혼자 남아 왼쪽에 40px
	       빈 띠가 생겼다(사용자 지적: 세로 선이 「혼자 길게」 내려간 것도 이 때문이다).
	   한 행 + 위 정렬이면 담당자는 주소에 붙고(간격 0), 단추는 그 줄의 오른쪽에 선다.

	   묶음 안은 `row-gap: 0`(줄 자신의 높이만), 묶음 사이는 그 묶음의 첫 줄이 위 여백으로 만든다. */
	--feed-lead: 0.55rem;
	row-gap: 0;
	padding: 0;
	border: 0;
}

/* ── 줄 사이의 선 ── 상자가 아니라 **줄 사이 한 줄**이다. 점과 세로 선만으로는 어디서 한
   항목이 끝나는지 알 수 없었다(「구분감이 없어서 못 알아보겠다」 — 사용자 지적, 특히 모바일:
   좁아지면 메타·단추가 자기 줄로 내려가 한 항목이 여섯 줄이 된다).

   상자를 다시 두르지 않는 이유는 그것이 흐름을 끊기 때문이고(카드가 그 꼴이다), 스트림의
   관례가 «항목 사이 한 줄» 이다. 마지막 줄 아래에는 긋지 않는다 — 더 올 것이 없다. */
.entries[data-view='feed'] .entry:not(:last-child) {
	padding-bottom: 0.9rem;
	border-bottom: 1px solid var(--line);
}

/* 사건 점 — **색이 그 서비스의 상태**다(`.entry` 의 `is-*`). 피드에서 가장 먼저 읽히는 것이
   「무슨 일이 있나」라 점이 머리 줄의 첫 글자다. 홈의 등록부와 같은 글자·같은 색 규약이다. */
.entries[data-view='feed'] .entry::before {
	content: '⏺';
	grid-area: dot;
	font-family: var(--font-mono);
	font-size: var(--t-micro);
	/* 눈썹 줄과 같은 줄 높이 — 점이 그 줄의 첫 글자다. */
	line-height: 1.4;
	color: var(--fg-3);
}

.entries[data-view='feed'] .entry.is-ok::before { color: var(--ok); }
.entries[data-view='feed'] .entry.is-dev::before { color: var(--accent); }
.entries[data-view='feed'] .entry.is-auth::before { color: var(--warn); }
.entries[data-view='feed'] .entry.is-down::before { color: var(--bad); }
.entries[data-view='feed'] .entry.is-unchecked::before { color: var(--line-strong); }

/* 세로 선 — 점 아래의 줄들을 그 사건에 **묶는다**(`⎿` 의 자리). 마지막에 안쪽으로 꺾어
   `╰` 를 만든다: 둥근 모서리 한 번이 그 글자를 그린다.

   선은 **왼쪽에 내용이 있는 마지막 줄**(담당자)에서 끝나야 한다 — 묶을 것이 없는 자리에
   선이 있으면 그것은 «무엇을 묶는 선» 이 아니라 그냥 그어진 선이다(사용자 지적: 선이 「혼자
   길게」 내려갔다). 담당자가 마지막 행의 왼쪽에 있으므로 홈통은 그 행까지만 있으면 된다.

   **꺾이는 자리는 담당자의 세로 중심**이다 — 선이 가리키는 것이 그 값이어야 한다.
   마지막 행의 높이는 단추(`--control-h-sm`)가 정하고 담당자의 글자는 그 행의 위쪽
   `--tap-min` 안에서 가운데에 앉으므로, 아래 여백은 «행 높이 − 담당자 중심» 이다:
   `--control-h-sm − --tap-min/2`. 숫자로 박지 않는 이유는 터치 기기에서 두 토큰이 함께
   44px 이 되기 때문이다(그때도 여백이 22px 로 따라와 중심을 가리킨다). */
.entries[data-view='feed'] .entry::after {
	content: '';
	grid-area: rail;
	width: 0.5rem;
	margin: 0.1rem 0 calc(var(--control-h-sm) - var(--tap-min) / 2) 0.28rem;
	border-left: 1px solid var(--line-strong);
	border-bottom: 1px solid var(--line-strong);
	border-bottom-left-radius: 5px;
}

/* 머리 줄 — 이름이 주어, 고객사·분야는 **줄 끝의 흐린 메타**다(등록부와 같은 규약).
   `display: contents` 로 겹을 풀었으므로 이름 줄과 설명이 각자 격자 아이템이 된다. */
.entries[data-view='feed'] .entry-main {
	display: contents;
}

/* 이름은 눈썹 **아래 자기 줄**을 갖는다 — 이 줄의 주어다. 공용 규칙의 아래 여백
   (`margin: 0 0 0.15rem`)을 지운다: 그 2.4px 때문에 이름→설명 간격만 27px 이 되어 한 칸
   리듬이 깨졌다(다른 칸은 24px — 실측). 리듬은 격자가 만들고 블록은 여백을 갖지 않는다. */
.entries[data-view='feed'] .entry-title {
	grid-area: title;
	align-items: baseline;
	margin: 0;
	padding: 0;
	border: 0;
}

.entries[data-view='feed'] .entry-name {
	font-size: var(--t-lg);
	/* 한 칸(24px) — 이름은 누르는 것이기도 하니 그 칸이 표적이다(SC 2.5.8). */
	line-height: var(--tap-min);
}

.entries[data-view='feed'] .entry-name::after {
	content: none;
}

/* 고객사·분야는 **줄의 눈썹**이다 — 이름 위 한 줄. 크기는 카드와 같다(11px, 공용 규칙이
   이미 준다) — 카드·피드가 같은 순서·같은 급으로 읽히게 한다. */
.entries[data-view='feed'] .entry-project,
.entries[data-view='feed'] .entry-work {
	align-self: baseline;
	/* 눈썹은 이름과 **한 묶음**이라 자기 글자 높이만 쓴다(24px 칸에 앉히면 둘 사이가
	   12px 이 되어 남남으로 읽혔다 — 실측). */
	line-height: 1.4;
}

.entries[data-view='feed'] .entry-work {
	padding-left: 0.4rem;
}

/* 배지 쌍은 머리 줄의 **오른쪽 끝** — 카드와 같은 자리다.

   **오른쪽 홈통(0.4rem)** 을 둔다. 0 이면 배지와 단추의 테두리가 구획 끝에 닿아 답답했다
   (사용자 지적) — 왼쪽은 점이 홈통 안에서 6px 들어와 있으니 두 끝이 대칭이 아니었다.
   단추도 같은 값을 쓴다(아래): 두 조각이 같은 x 에서 끝나야 오른쪽이 한 선이 된다. */
.entries[data-view='feed'] .entry-axes {
	position: absolute;
	top: 0;
	right: 0.4rem;
}

/* 본문은 읽는 폭(46rem)을 넘지 않고 두 줄까지다. `ch` 로 잡으면 이 서체의 `ch`(7.2px)
   때문에 한글이 대부분 두 줄로 꺾인다(실측 564px) — 한글이 섞인 글은 `rem` 으로 잡는다. */
.entries[data-view='feed'] .entry-desc {
	grid-area: desc;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	max-width: 46rem;
	/* 문단의 줄 높이(1.55) — 두 줄이 될 때 그 안이 먼저 붙어 보여야 한 문단으로 읽힌다.
	   24px 로 두면 두 줄 사이가 위 묶음 간격보다 넓어져 문단이 갈라진다. */
	line-height: 1.55;
	/* **묶음 사이의 숨** — 제목(눈썹·이름) 다음이다. */
	margin-top: var(--feed-lead);
}

/* 주소는 **한 줄에 통째로** — 피드가 카드보다 잘하는 일이고, 이 보기의 값이다. */
.entries[data-view='feed'] .entry-urls {
	/* 두 주소는 **한 쌍**이라 그 사이는 붙인다(칩 자신의 24px 높이만). */
	row-gap: 0;
	margin-top: var(--feed-lead);
}

/* 칩도 한 칸(24px) 리듬을 지킨다. 좁은 화면에서 주소가 두 줄로 꺾이면 칩이 33px 이 되어
   그 아래 줄이 9px 어긋났다(실측 390px, 4칸) — 줄 높이를 한 칸으로 두면 꺾여도 정확히
   두 칸(48px)이다. */
.entries[data-view='feed'] .url-chip {
	line-height: var(--tap-min);
}

/* ── 마지막 줄 ── 담당자(왼쪽) · 점검 시각(메타와 같은 x) · 단추(줄 끝).
   점검 시각이 머리 줄의 흐린 메타와 **같은 열**을 쓰므로 두 줄의 오른쪽 끝이 한 선에 선다.
   셋 다 `min-height` 로 표적 높이를 갖고, 테두리·선은 없다(흐름을 끊지 않는다). */
.entries[data-view='feed'] .entry-owner,
.entries[data-view='feed'] .entry-checked,
.entries[data-view='feed'] .entry-tools {
	/* **위 정렬** — 행 높이는 단추(32px)가 정하지만 글자는 그 행의 첫 줄에 앉는다.
	   가운데로 두면 담당자가 주소에서 그만큼(16px) 밀린다(위 주석). */
	align-self: start;
	align-items: center;
	min-height: var(--tap-min);
	padding: 0;
	border: 0;
	white-space: nowrap;
}

/* 담당자는 **주소에 붙는다** — 이 서비스의 사실이라 주소와 한 묶음이다(위 그림). */
.entries[data-view='feed'] .entry-owner {
	display: flex;
	gap: 0.4rem;
	justify-self: start;
}

/* 점검 시각은 라벨을 떼고 흐린 글자로 — 값(「2분 전 점검」)이 이미 «점검» 을 말한다.

   **단추의 글자와 베이스라인을 맞춘다.** 이 값은 점검 단추의 이름표라 «상자 대 상자» 가
   아니라 «글자 대 글자» 로 읽히는 자리다. 상자 중심으로 맞추면(`stretch` + 가운데) 크기가
   다른 두 글자(값 11px · 라벨 13px)의 베이스라인이 2px 어긋나 값이 살짝 떠 보이고, 아래쪽
   맞춤은 6px 처진다(실측 셋을 나란히 비교). 베이스라인은 단추의 안쪽 여백이 바뀌어도 따라
   맞는다 — 그래서 숫자가 아니라 정렬 규칙으로 둔다.

   담당자는 이 규칙을 쓰지 않는다(주소에 붙어야 하므로 위 정렬 그대로). */
.entries[data-view='feed'] .entry-checked {
	display: flex;
	align-self: baseline;
	justify-self: end;
	color: var(--fg-3);
}

.entries[data-view='feed'] .entry-checked::before {
	content: none;
}

.entries[data-view='feed'] .entry-tools {
	justify-self: end;
	justify-content: flex-end;
	/* 점검 시각과 베이스라인을 맞추기 위해 이 줄도 같은 정렬을 쓴다 — flex 컨테이너의
	   베이스라인은 첫 아이템(점검 단추)의 것이므로, 격자가 두 글자를 한 선에 앉힌다. */
	align-self: baseline;
	/* 배지 쌍과 같은 오른쪽 홈통. */
	padding-right: 0.4rem;
}

/* 좁아지면 **단추가 자기 줄로** 내려간다 — 마지막 줄에 메타와 단추가 함께 들어가지 못하는
   폭이다(메타 ~230px + 단추 156px). 경계는 실측으로 정한다(아래 검사가 지킨다). */
@container results (max-width: 30rem) {
	.entries[data-view='feed'] .entry {
		/* **세 열로 줄인다.** 넓은 화면의 다섯 열(홈통 · 이름 · 메타 둘 · 오른쪽 끝)을 그대로
		   두면 고객사가 `1fr` 열에, 분야가 오른쪽 메타 열에 남아 둘이 지면 양끝으로 갈라진다
		   (실측: 모바일에서 「사내」와 「· 영업·마케팅」이 300px 떨어졌다). 접힌 뒤에는 메타도
		   왼쪽에서 읽으므로 고객사가 자기 폭(`auto`)만 쓰고 분야가 바로 뒤에 붙는다.

		   **그 열을 쓰는 것은 고객사뿐이다** — 나머지는 모두 두 열을 span 한다. 담당자를 그
		   열에 두었더니 열이 「담당자 ubuntu(chris)」 폭으로 잡혀 분야가 최대 105px 밀렸다
		   (실측). 그래서 담당자·점검 시각·단추는 각자 자기 줄을 쓴다 — 모바일은 세로가 있다. */
		grid-template-columns: 1.35rem auto minmax(0, 1fr);
		grid-template-areas:
			"dot  who-a   who-b"
			"rail title   title"
			"rail desc    desc"
			"rail urls    urls"
			"rail owner   owner"
			"rail checked checked"
			"rail tools   tools";
	}

	/* 좁아지면 점검 시각도 자기 줄이라 **왼쪽 정렬**이다(줄 끝에 맞출 것이 없다). */
	.entries[data-view='feed'] .entry-checked {
		justify-self: start;
	}

	/* 좁은 폭에서는 셋이 각자 줄이다 — 점검 시각이 «할 일» 묶음의 첫 줄이라 숨은 그 앞에만
	   있고 단추는 붙는다(둘이 한 묶음이다). */
	.entries[data-view='feed'] .entry-checked {
		margin-top: var(--feed-lead);
	}

	.entries[data-view='feed'] .entry-tools {
		grid-area: tools;
		justify-self: start;
		justify-content: flex-start;
	}
}

/* ── 좁은 화면 ── 표를 접는다. 열이 다섯이면 어느 것도 못 읽는다. */
/* 좁아지면 결과 줄 단추의 **최소 폭을 놓아 준다.** 넷을 같은 폭(6.5rem)으로 맞춘 것은
   나란히 놓였을 때의 규칙인데, 그 폭이 안 되면 «같은 폭» 보다 «화면 안에 있음» 이 먼저다.

   **기준은 이 줄 자신의 폭이다**(뷰포트가 아니다). 실측: 줄 폭 324px 까지 넘치지 않고
   320px 에서 2px 넘친다. 그래서 20rem(320px)이다. 전에는 30rem(480px, 뷰포트)이었는데
   그건 실제로 넘치는 폭보다 160px 이나 이른 값이었다. */
@container resultbar (max-width: 20rem) {
	.result-bar .btn.is-small {
		min-width: 0;
	}

	.result-views {
		width: 100%;
	}
}

/* ── 좁아지면 표를 접는다 ── **주소를 자르지 않기로 한 대가**다.

   **기준은 뷰포트가 아니라 구획(`#results`)의 폭이다.** 전에는 `@media (max-width: 80rem)`
   이었는데, 표의 폭을 정하는 것은 구획이고 구획 폭은 `--page-max` 사다리 때문에 계단식으로
   떨어진다 — 뷰포트 1280px 에서 1203px 이던 것이 1276px 에서 1024px 로 179px 준다. 그러면
   «접을 때» 와 «넘칠 때» 가 어긋난다(상세 화면에서 실제로 그 어긋남이 결함 구간을 만들었다).

   값은 산수가 아니라 실측이다: 접기를 끄고 사다리도 끈 채 폭을 줄이면 **구획 1199px 까지
   안전하고 1196px 에서 넘친다.** 그래서 75rem(1200px)이다.
   (예전 계산은 열 합 59rem + 열 사이 6rem + 이름 하한 9rem = 1264px 이었는데, 줄의 왼쪽
   홈통 14.6px 과 `clamp` 거터가 빠져 실제로는 더 이른 폭에서 넘쳤다.)

   접힌 화면에서는 한 줄이 여러 행으로 쌓이므로 주소가 자기 폭을 다 쓴다 — 거기서도
   잘리지 않는다. */
@container results (max-width: 75rem) {
	/* **감추지 않는다.** 전에는 `display: none` 이었고 주석도 「정렬은 못 하지만 표가 깨지는
	   것보다 낫다」고 적혀 있었다 — 그 대가로 접힌 화면에서는 정렬 손잡이 다섯 개가 모두
	   사라졌다(실측: 900px 에서 5/5 안 보임). 카드·피드가 쓰는 **정렬 줄**이 이미 있으므로
	   같은 모양을 쓴다. 새 장치를 만들지 않는다. */
	.entry-head {
		--head-mode: flex;
		--head-gap: 0.25rem 1.1rem;
		--head-quiet: none;
		--head-below: 0.75rem;
	}

	.entries[data-view='list'] .entry {
		display: grid;
		grid-template-columns: 1fr;
		gap: 0.4rem;
	}

	/* 접힌 화면에서 주소는 **자르지 않고 접는다.** 표에서는 열 폭이 정해져 있어 넘치는 뒤를
	   잘랐지만(앞이 정보, 뒤가 반복), 여기서는 줄이 세로로 쌓이므로 아래로 한 줄 더 쓰면 된다 —
	   360px 에서 23건이 잘리던 것이 0건이 된다(실측). **자른 주소는 복사해도 쓸 수 없다**는
	   것이 이 규칙의 이유다. */
	.url-chip {
		white-space: normal;
	}

	.url-chip-host {
		overflow: visible;
		text-overflow: clip;
		word-break: break-all;
	}

}

/* ── 좁아지면 걸러내기가 접힌 채로 시작한다 ── 일곱을 펼치면 두 줄(약 160px)을 먹어
   목록이 첫 화면에서 사라진다(실측). 접혀 있어도 걸린 조건 수는 토글에 적혀 있다.

   **이 규칙은 `#find` 컨테이너에 걸린다** — 대상(`.find-toggle`·`.find-row-filters`)이 그
   구획 안에 있기 때문이다. 위의 표 접기는 `#results` 컨테이너다. 컨테이너 질의는 **그 컨테이너
   의 자손에만** 적용되므로, 한 블록에 섞어 두면 한쪽이 조용히 아무 일도 하지 않는다.
   경계는 표 접기와 같은 75rem 이다: 둘 다 «지면이 좁아졌다» 는 한 사실에 반응한다. */
@container find (max-width: 75rem) {
	.find-toggle {
		display: inline-flex;
	}

	.find-row-filters {
		display: none;
	}

	/* 여는 상태의 이름은 `.is-open` 이다 — JS 가 켜는 것과 CSS 가 보는 것이 같아야 한다.
	   전에는 CSS 가 `[hidden]` 을 보고 JS 는 `.is-open` 을 켜서 **토글이 아무 일도 하지
	   않았다**(실측: 480px 에서 늘 펼쳐진 260px). 상태 이름이 갈리면 컨트롤이 조용히 죽는다. */
	.find-row-filters.is-open {
		display: grid;
	}
}
