Skip to main content

max / makenotwork

Hand four more primitives back to makeover: link, field, chip, segment, toggle The same element-vs-class overlap the button carried, measured across every element rule in style.css that could sit under a generated class. - `a { color: var(--content); text-decoration: none }` rendered a described link as body text. A reader could not tell it was a link. - `button.link` took the element rule's fill, border and 6px/12px padding, so a link that posts rendered as an ordinary raised button rather than flat. - `select` and `textarea` set background and box-shadow where the `input` rule sets neither, so a described field on either took --surface-sunken instead of the well, and the app's outer focus ring beat makeover's inset one. The shipped `.field` precedents survived on that accident, not by design. - `button { background; box-shadow }` beat `.chip.latched`, `.toggle.chosen` and `.segment.chosen`, so every one of those rendered raised. The selected state was invisible, which is the defect `.tab.chosen` was fixed for. All handoffs are `revert-layer`, so each rolls back to whichever makeover arm matches the element -- the latched arm for a latched chip, the base arm otherwise -- rather than naming a value. `font` is handed back on the button arm of `.link` alone: an `a.link` has no lower-layer font to roll back to and would land on the UA face. Verified by rendering, before and after, with the four sheets and the layer statement: a described link is --action and underlined, a link button is transparent with no padding or border, select and textarea take the well, and latched chip, chosen toggle and chosen segment take the inset bevel. Left alone and recorded in build.rs: `.facet-prune` and `.facet-take` (nothing in the layer to roll back to, so the app's chrome has to be withdrawn by hand), `.badge` and `.card`, and the disabled treatment, which is a charter decision.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-22 04:00 UTC
Signed with PGP, not checked
Commit: 3290602e3ec2799212f40594ad8d8af736709a1e
Parent: 53a4ee7
2 files changed, +86 insertions, -3 deletions
@@ -651,6 +651,21 @@
651 651 /// buys silence for a real override on the same pair later, and that is the
652 652 /// cost of every line in this list.
653 653 ///
654 + /// The same pass measured the rest of the element-vs-class overlaps and handed
655 + /// four more classes back the same way, which is where the `chip`, `segment`,
656 + /// `toggle`, `link` and `field` entries come from. `button` takes surface and
657 + /// bevel from a chip, a segment and a toggle; `a` renders a described link as
658 + /// body text; `select` and `textarea` set a background and a bevel where the
659 + /// `input` rule sets neither, which is the accident the shipped `.field`
660 + /// precedents survived on. Every one of those entries is a `revert-layer`.
661 + ///
662 + /// Not handed back, and still overlapping: `.facet-prune` and `.facet-take`
663 + /// (makeover gives them no base surface, so there is nothing in the layer to
664 + /// roll back to and the app's chrome has to be withdrawn by hand), `.badge` and
665 + /// `.card` on their own arms, and the disabled treatment, where this file's
666 + /// opacity rule is a charter decision rather than an accident. See the
667 + /// mnw-server task filed 2026-08-21.
668 + ///
654 669 /// **A divergence taken on purpose.** `.table-row { display }` is `grid` here
655 670 /// against makeover's `table-row`, which is the same build-time grid story
656 671 /// goingson is on.
@@ -687,6 +702,21 @@
687 702 ("button", "box-shadow"),
688 703 ("button", "color"),
689 704 ("card", "color"),
705 + ("chip", "background"),
706 + ("chip", "box-shadow"),
707 + ("field", "background"),
708 + ("field", "box-shadow"),
709 + ("field", "outline-offset"),
710 + ("link", "background"),
711 + ("link", "border"),
712 + ("link", "color"),
713 + ("link", "font"),
714 + ("link", "padding"),
715 + ("link", "text-decoration"),
716 + ("segment", "background"),
717 + ("segment", "box-shadow"),
718 + ("toggle", "background"),
719 + ("toggle", "box-shadow"),
690 720 ("chosen", "box-shadow"),
691 721 ("progress-fill", "background"),
692 722 ("tab", "box-shadow"),
@@ -470,18 +470,27 @@
470 470 Tone is handed back on `[data-tone]` rather than on `.button`, because an
471 471 untoned button has no colour in the layer to roll back to and would land on
472 472 the UA default instead of --content. */
473 - .button {
473 + .button,
474 + .chip,
475 + .segment,
476 + .toggle {
474 477 /* respec-ok: a layer handoff, not a value. */
475 478 background: revert-layer;
476 479 box-shadow: revert-layer;
477 480 }
478 481
479 - .button:hover {
482 + .button:hover,
483 + .chip:hover,
484 + .segment:hover,
485 + .toggle:hover {
480 486 /* respec-ok: a layer handoff, not a value. */
481 487 background: revert-layer;
482 488 }
483 489
484 - .button:active {
490 + .button:active,
491 + .chip:active,
492 + .segment:active,
493 + .toggle:active {
485 494 /* respec-ok: a layer handoff, not a value. */
486 495 background: revert-layer;
487 496 box-shadow: revert-layer;
@@ -492,6 +501,50 @@
492 501 color: revert-layer;
493 502 }
494 503
504 + /* A described link, same handoff on the `a` and `button` element rules.
505 + `a { color: var(--content); text-decoration: none }` renders a described
506 + link as body text -- the reader cannot tell it is a link at all, which is
507 + the same defect as the lost tone above and worse for being silent.
508 +
509 + `button.link` is the second arm: a link that posts is a button in the
510 + markup, and makeover already flattens it (`background: none`, no border, no
511 + padding, `font: inherit`). The element rule's chrome beat all four, so it
512 + rendered as an ordinary raised button. Only the properties makeover sets on
513 + this class are handed back; `font` is handed back on the button arm alone,
514 + because an `a.link` has no lower-layer font to roll back to and would land
515 + on the UA default face. */
516 + .link {
517 + /* respec-ok: a layer handoff, not a value. */
518 + color: revert-layer;
519 + text-decoration: revert-layer;
520 + }
521 +
522 + button.link {
523 + /* respec-ok: a layer handoff, not a value. */
524 + background: revert-layer;
525 + border: revert-layer;
526 + padding: revert-layer;
527 + font: revert-layer;
528 + box-shadow: revert-layer;
529 + }
530 +
531 + /* A described field on a `select` or a `textarea`. The input rule further down
532 + sets padding and font only, which is why the shipped `.field` precedents
533 + survived; these two also set `background` and `box-shadow`, so a described
534 + field on either renders in --surface-sunken rather than the well. The focus
535 + ring is handed back with them: makeover insets it (`calc(-1 * 2px)`) so it
536 + does not collide with the bevel, and the app's outer 2px was winning. */
537 + .field {
538 + /* respec-ok: a layer handoff, not a value. */
539 + background: revert-layer;
540 + box-shadow: revert-layer;
541 + }
542 +
543 + .field:focus-visible {
544 + /* respec-ok: a layer handoff, not a value. */
545 + outline-offset: revert-layer;
546 + }
547 +
495 548 .btn-primary {
496 549 background: var(--primary-dark);
497 550 color: var(--primary-light);