docs: turn the accepted panel design into an enforceable contract
panel-redesign.md is rewritten for the accepted direction: three layers (Bulma as shipped, adapters, own sp- components), the page layouts, what an implementer must not do, and how that is enforced — guard tests that land before any template, a design-first CI step, and acceptance by evidence (test output plus a screenshot of every page beside its mockup, reviewed by a model that did not write the step). A components page shows every building block in every state; a screen may be built from nothing else. panel/check.py lints the mockups against the contract (class vocabulary, CSS bans on !important, id and page selectors and stray widths, page structure) and writes panel/outlines.json, the per-screen component skeleton an implementation is compared with, so a different design cannot pass as this one. Own modifier classes now carry the sp- prefix (sp-warn, sp-fail, sp-big, sp-danger-zone, ...) so the vocabulary is machine-checkable; the lint also caught a width set outside the layout in the mockup's own CSS. Agent rule .cursor/rules/panel-design.mdc; roadmap row and section updated (0/15, still candidate). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -74,8 +74,8 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad
|
||||
display: grid; place-content: center; text-align: center; color: var(--sp-ok);
|
||||
font-family: var(--sp-mono); font-weight: 600; letter-spacing: .08em; line-height: 1.15;
|
||||
}
|
||||
.sp-postmark.warn { color: #a66a0e; }
|
||||
.sp-postmark.fail { color: var(--sp-fail); }
|
||||
.sp-postmark.sp-warn { color: #a66a0e; }
|
||||
.sp-postmark.sp-fail { color: var(--sp-fail); }
|
||||
.sp-postmark b { font-size: 1.2rem; display: block; }
|
||||
.sp-postmark span { font-size: .52rem; display: block; }
|
||||
|
||||
@@ -93,10 +93,10 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad
|
||||
.sp-box-foot .sp-end { margin-left: auto; }
|
||||
.sp-box-head form.sp-end { margin-block: -.2rem; }
|
||||
.box > .sp-box-foot {padding: .7rem 1.25rem; border-top: 1px solid var(--sp-rule); color: var(--sp-muted); font-size: .85rem; display: flex; gap: 1rem; align-items: center; }
|
||||
.box.is-danger-zone { border-color: var(--sp-fail-rule); }
|
||||
.box.is-danger-zone .sp-box-head { background: var(--sp-fail-bg); border-color: var(--sp-fail-rule); }
|
||||
.box.is-credential { border-color: #e0c874; }
|
||||
.box.is-credential .sp-box-head { background: #fcf6e4; border-color: #e0c874; }
|
||||
.box.sp-danger-zone { border-color: var(--sp-fail-rule); }
|
||||
.box.sp-danger-zone .sp-box-head { background: var(--sp-fail-bg); border-color: var(--sp-fail-rule); }
|
||||
.box.sp-credential { border-color: #e0c874; }
|
||||
.box.sp-credential .sp-box-head { background: #fcf6e4; border-color: #e0c874; }
|
||||
|
||||
.table { background: transparent; }
|
||||
.table thead th { font-family: var(--sp-mono); font-size: .7rem; font-weight: 400; letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); }
|
||||
@@ -119,10 +119,10 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad
|
||||
.sp-health > a:hover { background: var(--sp-paper); }
|
||||
.sp-h-icon { flex: none; width: 2.6rem; height: 2.6rem; border-radius: 8px; display: grid; place-content: center; background: var(--sp-ok-bg); color: var(--sp-ok); }
|
||||
.sp-h-icon .ti { font-size: 1.5rem; vertical-align: 0; }
|
||||
.sp-health > a.warn { background: var(--sp-warn-bg); }
|
||||
.sp-health > a.warn .sp-h-icon { background: #f6e2b8; color: #8a5510; }
|
||||
.sp-health > a.fail { background: var(--sp-fail-bg); }
|
||||
.sp-health > a.fail .sp-h-icon { background: #f5d3cc; color: var(--sp-fail); }
|
||||
.sp-health > a.sp-warn { background: var(--sp-warn-bg); }
|
||||
.sp-health > a.sp-warn .sp-h-icon { background: #f6e2b8; color: #8a5510; }
|
||||
.sp-health > a.sp-fail { background: var(--sp-fail-bg); }
|
||||
.sp-health > a.sp-fail .sp-h-icon { background: #f5d3cc; color: var(--sp-fail); }
|
||||
.sp-h-name { font-family: var(--sp-mono); font-size: .66rem; letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); }
|
||||
.sp-h-value { font-weight: 600; line-height: 1.25; }
|
||||
.sp-h-sub { font-size: .8rem; color: var(--sp-muted); }
|
||||
@@ -131,7 +131,7 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad
|
||||
.sp-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 1rem 1.5rem; margin: 0; }
|
||||
.sp-facts dt { font-family: var(--sp-mono); font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); }
|
||||
.sp-facts dd { margin: 0; overflow-wrap: anywhere; }
|
||||
.sp-facts dd.is-big { font-size: 1.5rem; font-weight: 600; line-height: 1.2; }
|
||||
.sp-facts dd.sp-big { font-size: 1.5rem; font-weight: 600; line-height: 1.2; }
|
||||
.sp-side { position: sticky; top: 1.5rem; }
|
||||
.menu-label { font-family: var(--sp-mono); letter-spacing: .1em; }
|
||||
.menu-list a { display: flex; align-items: center; gap: .55rem; }
|
||||
@@ -156,14 +156,14 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad
|
||||
margin: 0; padding: 1rem 1.25rem; background: #191c21; color: #d9d5cc; border-radius: 0;
|
||||
font-family: var(--sp-mono); font-size: .78rem; line-height: 1.6; overflow-x: auto; white-space: pre;
|
||||
}
|
||||
.sp-log .w { color: #e0b15c; } .sp-log .e { color: #ef8f82; } .sp-log .d { color: #7f8894; }
|
||||
.sp-log .sp-w { color: #e0b15c; } .sp-log .sp-e { color: #ef8f82; } .sp-log .sp-d { color: #7f8894; }
|
||||
.sp-timeline { list-style: none; margin: 0; padding: 0; }
|
||||
.sp-timeline li { position: relative; padding: 0 0 1.1rem 1.6rem; border-left: 2px solid var(--sp-rule); margin-left: .4rem; }
|
||||
.sp-timeline li:last-child { padding-bottom: 0; border-left-color: transparent; }
|
||||
.sp-timeline li::before { content: ""; position: absolute; left: -7px; top: .25rem; width: 12px; height: 12px; border-radius: 50%; background: var(--sp-ok); box-shadow: 0 0 0 3px #fff; }
|
||||
.sp-timeline li.warn::before { background: #d9962b; }
|
||||
.sp-timeline li.fail::before { background: var(--sp-fail); }
|
||||
.sp-timeline li.pending::before { background: #fff; border: 2px solid var(--sp-rule-strong); }
|
||||
.sp-timeline li.sp-warn::before { background: #d9962b; }
|
||||
.sp-timeline li.sp-fail::before { background: var(--sp-fail); }
|
||||
.sp-timeline li.sp-pending::before { background: #fff; border: 2px solid var(--sp-rule-strong); }
|
||||
.sp-timeline time { font-family: var(--sp-mono); font-size: .75rem; color: var(--sp-muted); display: block; }
|
||||
.sp-route { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; font-family: var(--sp-mono); font-size: .9rem; margin-top: .3rem; }
|
||||
.sp-help-topic + .sp-help-topic { border-top: 1px solid var(--sp-rule); }
|
||||
@@ -183,7 +183,7 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad
|
||||
.sp-signin-brand img { width: 20rem; max-width: 100%; height: auto; }
|
||||
.sp-signin-brand p { font-family: var(--sp-mono); letter-spacing: .18em; font-size: .8rem; color: var(--sp-on-brick); margin-top: 1.6rem; }
|
||||
.sp-signin-form { display: flex; flex-direction: column; justify-content: center; padding: 3rem; }
|
||||
.sp-signin-form form, .sp-signin-form .sp-signin-note { width: 22rem; max-width: 100%; margin-inline: auto; }
|
||||
.sp-signin-form form { width: 22rem; max-width: 100%; margin-inline: auto; }
|
||||
.sp-foot { color: var(--sp-muted); font-size: .8rem; padding-block: 1.5rem 0; }
|
||||
.sp-foot a { color: inherit; text-decoration: underline; }
|
||||
.sp-signin-form .sp-foot { text-align: center; margin-top: 2.5rem; }
|
||||
@@ -191,6 +191,6 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad
|
||||
@media (max-width: 768px) {
|
||||
.sp-row, .sp-pair { grid-template-columns: 1fr; }
|
||||
.sp-record-head { flex-wrap: wrap; }
|
||||
.sp-record-head small { margin-left: 0; text-align: left; width: 100%; }
|
||||
.sp-record-head small { margin-left: 0; text-align: left; flex-basis: 100%; }
|
||||
.sp-postmark { display: none; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user