www.git

www

~ Personal site — projects, posts, about. Built with sqzass.
git clone https://github.com/debuman/www.git
commit 514a56600e17ba903261ddd2b23015c4fd6f486d
parent 5e191b0b5ee3ac0cda2d06c49309a85629077be1
Author: sqzer <110329244+sqzer-x@users.noreply.github.com>
Date: Wed, 5 Aug 2026 19:01:20 +0900

Tiles become cards, the newest post moves above its section head, and a
descender stops being cut

Four things.

The title was clipped. I had reached for -webkit-line-clamp to cap the title at
three lines in a fixed-height card, and in this engine that combination computes
display as flow-root, which kills the clamp and leaves overflow: hidden behind.
The box is then line-height tall, 1.2em, while the text's own line box is
1.44em, so six pixels came off the bottom — the descender of the g in
"Beginning". Line count is counted with max-height now and padding-bottom gives
the descender somewhere to sit. Both in em, so they follow the size. Measured:
the run's bottom now sits 7px inside the box instead of 6px outside it. The
description had the same construction and keeps its two-line cap the same way,
though its 1.65 line-height was already loose enough to have hidden the bug.

The newest post moves above the section head. That one piece is not an entry in
the list, it is what is being put out now; the head belongs to the list that
follows it. Underneath, the ledger caps at three rows and everything past that
is what the All posts door is for. With one post written the list renders empty,
which is the honest state and not a hole to fill.

The section's top space moves with it. It used to be carried by the head's
margin, and the head is no longer the first thing in the section, so the card
carries it and the head keeps a smaller one — the distance between two sections
and the distance inside one should not be the same number.

The project tiles get a border, a ground and a left edge. They were the only
things on the page with no frame at all, so a single card floated at the top
while everything below it was loose type, and they were centred under a head
that starts at the left. The facts line pins to the bottom of each card with
margin-top: auto, so a row of them agrees on where that line sits however long
the blurbs run.

Diffstat:
Mstatic/css/main.css | 53+++++++++++++++++++++++++++++++++++++++--------------
Mstatic/fonts/display-kr.woff2 | 0binary
Mtemplates/home.html | 28+++++++++++++++-------------
3 files changed, 54 insertion(+), 27 deletion(-)

diff --git a/static/css/main.css b/static/css/main.css
@@ -503,6 +503,13 @@ main { display: block; padding-bottom: clamp(5rem, 12vw, 9rem); }
 
 .room { padding-block: 0; }
 
+/* 갈래의 위 여백은 그 갈래의 첫 물건이 진다. 전에는 언제나 머리가 졌는데,
+   글 갈래에서는 머리가 카드 뒤로 갔다. */
+.room > .feature:first-child { margin-top: clamp(4.5rem, 11vw, 7rem); }
+/* 카드 뒤에 오는 머리는 갈래를 여는 것이 아니라 그 아래 목록을 여는 것이라
+   덜 띄운다. 갈래 사이의 거리와 갈래 안의 거리는 달라야 한다. */
+.feature + .room-head { margin-top: clamp(2.5rem, 6vw, 3.5rem); }
+
 /* 문은 머리의 오른쪽 끝에 선다. 밑줄은 이 사이트의 문(.door)과 같은 물건이다. */
 .room-door {
   flex: none;
@@ -607,8 +614,10 @@ main { display: block; padding-bottom: clamp(5rem, 12vw, 9rem); }
 
 /* ---------- project tiles ---------- */
 
-/* 목록이 아니라 타일이다. 가운데 정렬에 테두리도 구분선도 없고, 커서가
-   닿으면 그 아래에서 빛이 올라온다. */
+/* 카드다. 테두리와 바닥을 갖고, 글은 왼쪽에서 시작한다.
+   테두리가 없던 때는 이 여섯 개가 페이지에서 유일하게 액자 없는 물건이라,
+   위의 카드 하나만 상자로 떠 있고 아래는 글자만 떠다녔다. 갈래 머리가 왼쪽에서
+   시작하는데 그 아래 내용이 가운데 정렬인 것도 같은 어긋남이었다. */
 /* 트랙에 상한을 두고 justify-content 로 가운데 모은다. `1fr` 로 두면 항목이
    두 개일 때 3열 격자의 왼쪽 두 칸에 붙어 페이지 축이 어긋난다 — 갈래마다
    개수가 다른 목록에서는 이게 항상 일어난다. */
@@ -621,17 +630,21 @@ main { display: block; padding-bottom: clamp(5rem, 12vw, 9rem); }
 
 .tile {
   position: relative; isolation: isolate;
-  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
-  gap: 0.5rem; text-align: center;
-  padding: clamp(1.25rem, 3vw, 1.75rem) 1rem;
-  border: 0; background: transparent;
+  display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start;
+  gap: 0.5rem; text-align: left;
+  padding: clamp(1.25rem, 3vw, 1.75rem);
+  border: 1px solid var(--rule); border-radius: var(--radius);
+  background: var(--bg-2);
+  transition: border-color var(--tr-ink);
 }
+/* 손이 닿으면 테두리가 한 단 오른다 — 맨 위 카드와 같은 응답이다. */
+.tile:hover { border-color: var(--rule-2); }
 /* 누르면 눌린다. 빛이 번지는 대신 물건이 압축된다 — 이 집의 이름들이 전부
    모음을 눌러 뺀 것이고(sqzer, sqzass, ommp), 랜딩이 이미 같은 값을 쓴다.
    0.988 은 눈이 알아채되 글자가 흐려지지는 않는 지점이다. */
 
 .tile-title {
-  display: flex; align-items: center; justify-content: center; gap: 0.45rem;
+  display: flex; align-items: center; gap: 0.45rem;
   margin: 0; font-size: 1.05rem; font-weight: var(--w-item); letter-spacing: var(--track-set);
   color: var(--ink-2); transition: color var(--tr-ink);
 }
@@ -639,20 +652,22 @@ main { display: block; padding-bottom: clamp(5rem, 12vw, 9rem); }
 .tile-title .chip-mark { width: 1.4em; height: 1.4em; }
 
 .tile-blurb {
-  margin: 0; max-width: 32ch;
+  margin: 0;
   font-size: 0.85rem; line-height: 1.6; color: var(--ink-3); text-wrap: pretty;
 }
 
+/* 사실 줄은 카드 아래쪽에 붙는다. margin-top:auto 가 그 위 여백을 전부 먹어서,
+   설명 길이가 달라도 여섯 장의 사실 줄이 같은 높이에 선다. */
 .tile-meta {
-  display: flex; align-items: center; justify-content: center; gap: 0.7rem;
-  margin-top: 0.15rem;
+  display: flex; align-items: center; gap: 0.7rem;
+  margin-top: auto; padding-top: 0.35rem;
   font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.06em;
   color: var(--ink-4); font-variant-numeric: tabular-nums;
   transition: color var(--tr-ink);
 }
 .tile:hover .tile-meta { color: var(--ink-3); }
 
-.tile-links { display: flex; align-items: center; justify-content: center; gap: 0.6rem; margin-top: 0.1rem; }
+.tile-links { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.1rem; }
 .tile-links a, .frame-meta a {
   position: relative; z-index: 2;
   display: inline-flex; color: var(--ink-4);
@@ -827,8 +842,15 @@ html[lang="ko"] [data-tooltip]::after { letter-spacing: 0; text-transform: none;
   font-weight: var(--w-section); letter-spacing: var(--track-air); line-height: 1.2;
   color: var(--ink-2); transition: color var(--tr-ink);
   /* 세 줄까지. 1440 에서 이름표 안쪽이 372px 이고 날짜·설명·문·간격이 125px 을
-     쓰므로 제목에 247px 이 남는다 — 세 줄이 178px 이라 어떤 제목이 와도 들어온다. */
-  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
+     쓰므로 제목에 247px 이 남는다 — 세 줄이 178px 이라 어떤 제목이 와도 들어온다.
+
+     -webkit-line-clamp 를 쓰지 않는다. 이 조합에서 display 가 flow-root 로
+     계산돼 clamp 자체가 죽고 overflow:hidden 만 남았는데, 그러면 상자 높이가
+     line-height(1.2em)라 글자의 실제 줄상자(1.44em)가 6px 잘린다 — "Beginning"
+     의 g 아래가 그렇게 날아갔다. 줄 수는 max-height 로 세고, padding-bottom 이
+     디센더가 앉을 자리를 만든다. 둘 다 em 이라 크기를 바꿔도 따라온다. */
+  padding-bottom: 0.25em;
+  max-height: calc(3 * 1.2em + 0.25em);
   overflow: hidden;
   /* 이 시트의 모든 제목이 balance 다. 한때 여기만 pretty 로 바꿔 두고 "balance 는
      제목을 한 줄로 붙인다"고 적었는데, 재 보니 39자 제목에서 둘 다 세 줄이고
@@ -838,7 +860,10 @@ html[lang="ko"] [data-tooltip]::after { letter-spacing: 0; text-transform: none;
 .feature:hover .feature-title { color: var(--ink); }
 .feature-desc {
   margin: 0; max-width: 38ch; font-size: 0.96rem; color: var(--ink-3); text-wrap: pretty;
-  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
+  /* 두 줄까지. 줄 간격이 1.65em 이라 글자 줄상자(1.44em)보다 넉넉해서 여기는
+     따로 자리를 만들 필요가 없다. */
+  line-height: 1.65;
+  max-height: calc(2 * 1.65em);
   overflow: hidden;
 }
 
diff --git a/static/fonts/display-kr.woff2 b/static/fonts/display-kr.woff2
Binary files differ.
diff --git a/templates/home.html b/templates/home.html
@@ -28,18 +28,6 @@
 {%- for s in site.sections %}
 {%- if s.url == home ~ "posts/" and s.pages %}
 <section class="room wrap">
-  {#- 갈래 이름과 그 갈래로 가는 문이 한 줄에 선다. 사이의 헤어라인이 둘을
-      같은 줄의 양끝으로 묶는다 — 이름은 왼쪽에서 시작하고 문은 오른쪽 끝에서
-      기다린다. 전에는 이름이 가운데 위에, 문이 가운데 아래에 따로 서서 한
-      갈래의 머리와 꼬리가 166px 떨어져 있었다.
-      아래 내용(카드의 라벨, 원장의 행)이 전부 왼쪽 정렬이므로, 가운데 서 있던
-      것은 오히려 머리 쪽이었다. #}
-  <header class="room-head">
-    <h2>{{ t("writing") }}</h2>
-    <span class="room-rule" aria-hidden="true"></span>
-    <a class="room-door" href="{{ s.url }}">{{ t("all_posts") }}</a>
-  </header>
-
   {%- for p in s.pages %}
   {%- if loop.first %}
   <a class="feature" href="{{ p.url }}">
@@ -70,7 +58,21 @@
   {%- endif %}
   {%- endfor %}
 
-  {{ ledger(s.pages, 4, false, 1, page.language) }}
+  {#- 갈래 이름과 그 갈래로 가는 문이 한 줄에 선다. 사이의 헤어라인이 둘을 같은
+      줄의 양끝으로 묶는다.
+
+      맨 위 글이 이 줄보다 **앞에** 온다. 그 한 편은 갈래의 목록이 아니라 지금
+      내놓는 것이고, 머리는 그 뒤에 이어지는 목록의 머리다. 카드를 머리 아래
+      첫 항목으로 두면 "Writing 의 첫 줄"로 읽히는데, 크기가 다른 첫 줄이다. #}
+  <header class="room-head">
+    <h2>{{ t("writing") }}</h2>
+    <span class="room-rule" aria-hidden="true"></span>
+    <a class="room-door" href="{{ s.url }}">{{ t("all_posts") }}</a>
+  </header>
+
+  {#- 맨 위 한 편은 위에서 카드로 냈으므로 건너뛴다. 최대 세 줄 — 그 이상은
+      Posts 페이지가 받는다. #}
+  {{ ledger(s.pages, 3, false, 1, page.language) }}
 </section>
 {%- endif %}
 {%- endfor %}