From d0ae4fd1c0449b7f150f91f702c729f28bbff675 Mon Sep 17 00:00:00 2001 From: Smokey <150986568+jacisjake@users.noreply.github.com> Date: Tue, 27 Oct 2026 12:31:17 -0600 Subject: [PATCH] Perch layout: crows stand on the branch - Each crow stands on its own branch segment; segments join into one line per row, names sit under it in one style - Fixed headroom row for "?" and sparkles, centered over each crow - Trust star gets its own corner, clear of the beak - Dazed crows fade in place instead of tipping out of line - Five crows per row on a phone; tighter rows Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UQnSw4RRWp8uqpj3nsnnXF --- ui/src/style.css | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/ui/src/style.css b/ui/src/style.css index 09235b7..ea904ea 100644 --- a/ui/src/style.css +++ b/ui/src/style.css @@ -81,16 +81,12 @@ main { max-width: 680px; margin: 0 auto; padding: 0 16px 64px; } } .composer textarea:focus { outline: none; } -/* ---------- the perch: an inked branch with stippled underside ---------- */ -.perch { - position: relative; display: flex; flex-wrap: wrap; gap: 10px 6px; justify-content: center; align-items: flex-end; - min-height: 140px; padding: 16px 8px 12px; margin: 8px 0 22px; border-bottom: 2px solid var(--ink); -} -.perch::after { - content: ""; position: absolute; left: 4%; right: 4%; bottom: -12px; height: 10px; background: var(--stipple); - -webkit-mask-image: linear-gradient(#000, transparent); mask-image: linear-gradient(#000, transparent); -} -.crow { margin: 0; width: 84px; display: grid; justify-items: center; position: relative; } +/* ---------- the perch ---------- + Every crow stands on its own segment of one branch line; segments touch, + so each row reads as one branch. Names sit under the branch, all alike. + Each crow has a fixed 22px headroom row for marks ("?", sparkles). */ +.perch { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 0; margin: 4px 0 26px; } +.crow { margin: 0; width: 76px; padding-top: 22px; display: grid; justify-items: center; position: relative; } .crow.role-sentry { order: -1; } .crow.role-elder { order: 99; } .crow-body { width: 72px; height: 66px; } @@ -100,16 +96,23 @@ main { max-width: 680px; margin: 0 auto; padding: 0 16px 64px; } .crow.role-elder .disc { fill: #d6dde6; } .crow .bird { fill: #000; } .crow .jaw { transform-origin: 211px 182px; transition: transform 150ms; } -.crow figcaption { margin-top: 2px; font: 400 15px/1.2 var(--display); } -.crow.role-sentry figcaption, .crow.role-elder figcaption { font-style: italic; text-decoration: underline; text-underline-offset: 3px; } - -.crow .badge { - position: absolute; top: -4px; right: 4px; width: 22px; height: 22px; - fill: var(--card); stroke: var(--ink); stroke-width: 1.6; stroke-linejoin: round; - opacity: 0; transform: scale(0.4); transition: 150ms; +.crow figcaption { + justify-self: stretch; position: relative; margin-top: 0; padding-top: 6px; + border-top: 2px solid var(--ink); text-align: center; font: 400 15px/1.2 var(--display); } -.crow[data-trust="1"] .badge { opacity: 1; transform: rotate(-12deg); } -.crow[data-trust="2"] .badge { opacity: 1; transform: rotate(-12deg); fill: var(--ink); animation: twinkle 2.4s infinite; } +.crow figcaption::before { + content: ""; position: absolute; left: 0; right: 0; top: 0; height: 7px; background: var(--stipple); + -webkit-mask-image: linear-gradient(rgb(0 0 0 / 0.6), transparent); mask-image: linear-gradient(rgb(0 0 0 / 0.6), transparent); +} + +/* Trust star: its own corner, top right of the headroom, clear of the beak. */ +.crow .badge { + position: absolute; top: 4px; right: 4px; width: 18px; height: 18px; + fill: var(--card); stroke: var(--ink); stroke-width: 1.8; stroke-linejoin: round; + opacity: 0; transition: opacity 150ms; +} +.crow[data-trust="1"] .badge { opacity: 1; } +.crow[data-trust="2"] .badge { opacity: 1; fill: var(--ink); } /* Body layer: poses */ .pose-perched .crow-body { animation: breathe 3.2s ease-in-out infinite; } @@ -117,10 +120,10 @@ main { max-width: 680px; margin: 0 auto; padding: 0 16px 64px; } .pose-flying .jaw { transform: rotate(-10deg); } .pose-waiting .crow-body { animation: tilt 1.4s ease-in-out infinite; } .pose-waiting::after { - content: "?"; position: absolute; top: -12px; left: 4px; font: 400 26px/1 var(--display); + content: "?"; position: absolute; top: 0; left: 0; right: 0; text-align: center; font: 400 22px/1 var(--display); animation: pop 1.4s ease-in-out infinite; } -.pose-grounded .crow-body { transform: rotate(-18deg) translateY(6px); opacity: 0.5; } +.pose-grounded .crow-body { opacity: 0.4; } /* Reaction layer: one-shots on top */ .r-cheer .crow-body { animation: hop 0.8s ease-out; } @@ -129,7 +132,7 @@ main { max-width: 680px; margin: 0 auto; padding: 0 16px 64px; } .r-levelUp .crow-body { animation: levelup 2s ease-out; } .r-levelUp .jaw { transform: rotate(16deg); } .r-levelUp::before { - content: ""; position: absolute; top: -26px; width: 56px; height: 30px; animation: rise 2s ease-out forwards; + content: ""; position: absolute; top: -6px; left: calc(50% - 28px); width: 56px; height: 30px; animation: rise 2s ease-out forwards; background: var(--sparkle) 16px 0 / 26px 26px no-repeat, var(--glint) 0 14px / 12px 12px no-repeat, var(--glint) 44px 10px / 10px 10px no-repeat; } .r-levelDown .crow-body { animation: shrug 1s ease-out; }