Skip to main content

max / goingson

Collapse the two compact passes into one Sections 25 and 59 were the same pass split in two purely to manage cascade order, one "early, so feature CSS can override it" and one "late, so it wins conflicts", with the legend telling you which to add to. `@layer responsive` decides that now, so the split has no job left. Section 25's block moves down to join 59 and keeps its position ahead of it, because within a layer source order still settles ties between the two halves. The legend, the TWO SHELLS note and the band map are updated with it. VERIFIED BEHAVIOUR-NEUTRAL TWO WAYS, and the second caught a real bug the first and the linter both missed: - Every layer's rule sequence is compared before and after, as (selector, media, declarations). base 5, components 1497, responsive 160, all three identical. A relocation that preserves per-layer order cannot change the cascade, which is the argument this makes mechanical. - Every resolved declaration is compared, keyed on (element, media context, property). No winner changed. The bug: section 25's header was a multi-line comment and only its first line was dropped in the move, leaving a stray `*/` that closed the new comment early and turned the following prose into garbage CSS. The `@media` block after it stopped being a media block. `lint-frontend.sh` passed, the minifier was happy, and the byte count barely moved. The sequence check is what found it, by showing those rules had lost their media context.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-02 19:06 UTC
Signed with PGP, not checked
Commit: cbf570255d29584b9cdefb403967ed52645916f1
Parent: 6ae3621
1 file changed, +84 insertions, -73 deletions
@@ -76,7 +76,7 @@
76 76
77 77 BAND: RESPONSIVE LAYER 1 (see RESPONSIVE STRATEGY)
78 78 24. Responsive - Large Screens & Tablet
79 - 25. Responsive - Mobile (768px, base pass)
79 + (25 merged into 59: one compact pass, see the COMPACT SHELL band)
80 80
81 81 BAND: A11Y, PAGINATION, FOCUS
82 82 26. Screen Reader & Accessibility
@@ -120,7 +120,7 @@
120 120
121 121 BAND: COMPACT SHELL + CAPABILITY (see TWO AXES)
122 122 58. Mobile Navigation (Nav Dot, Dial, Bottom Sheets)
123 - 59. Compact Responsive (late pass)
123 + 25+59. Responsive - Compact (one pass, was two)
124 124 60. Touch Device Hover Disable
125 125
126 126 BAND: FEATURE SCREENS (C)
@@ -210,20 +210,21 @@
210 210 about room.
211 211
212 212 TWO SHELLS, and that is the decision rather than unfinished work. The
213 - wide shell is §§6, 7 and 8; the compact shell is §25 and §59
214 - together, which are one pass split only to manage cascade order. They
215 - are two designs, not one design badly factored, so they do not collapse
216 - into one: the compact shell hides the header, tab strip and pill nav and
213 + wide shell is §§6, 7 and 8; the compact shell is §25+59, one pass. It
214 + used to be two, split only to manage cascade order, and `@layer
215 + responsive` removed the reason. The two shells are two designs, not one
216 + design badly factored, so they do not collapse into one: the compact
217 + shell hides the header, tab strip and pill nav and
217 218 puts up a bottom tab bar instead. The boundary between them is 600px and
218 219 stays there. Medium (600-839px) gets the wide shell.
219 220
220 - §25 Compact (base pass) | early `(max-width: 599px)` rules; applies
221 - before feature CSS so feature rules can
222 - override.
223 - §59 Compact (late pass) | late `(max-width: 599px)` rules; runs AFTER
224 - feature CSS so it wins conflicts. Add new
225 - compact overrides here unless you need them
226 - early.
221 + §25+59 Compact | every `(max-width: 599px)` rule. One place;
222 + add new compact overrides here. It sits in
223 + `@layer responsive`, so it beats any component
224 + rule regardless of where either sits in this
225 + file. The old "add it early or late depending
226 + on whether you need to win" instruction is
227 + gone with the split that forced it.
227 228 §60 Touch capability | the capability axis. Not a shell.
228 229
229 230 `.ui-mode-mobile` appears nowhere in this file, and should not. It still
@@ -3482,65 +3483,6 @@
3482 3483 }
3483 3484 }
3484 3485
3485 - /* 25. Responsive - Compact (base pass) WIDTH
3486 - Early, so feature CSS can override it. The late pass is §59. */
3487 - @media (max-width: 599px) {
3488 - .tab-navigation {
3489 - flex-wrap: wrap;
3490 - }
3491 -
3492 - .tab {
3493 - flex: 1 1 auto;
3494 - min-width: calc(33% - var(--gap-peer));
3495 - justify-content: center;
3496 - }
3497 -
3498 - .tab-label {
3499 - display: none;
3500 - }
3501 -
3502 - .kbd-hint {
3503 - display: none;
3504 - }
3505 -
3506 - .cards-grid {
3507 - grid-template-columns: 1fr;
3508 - }
3509 -
3510 - .task-table {
3511 - font-size: var(--font-size-base);
3512 - }
3513 -
3514 - .filter-bar {
3515 - flex-direction: column;
3516 - }
3517 -
3518 - .page-title {
3519 - font-size: var(--font-size-3xl);
3520 - }
3521 -
3522 - .day-plan-content {
3523 - flex-direction: column;
3524 - }
3525 -
3526 - /* No .day-plan-sidebar here. It used to set width: 100% and
3527 - max-height: 200px, and §59 sets both again (max-height: none) after the
3528 - component rule in §38, so this pass never decided either. */
3529 -
3530 - .modal-container {
3531 - width: 95%;
3532 - max-height: 95vh;
3533 - }
3534 -
3535 - .bulk-actions-bar {
3536 - flex-wrap: wrap;
3537 - }
3538 -
3539 - .bulk-select-all {
3540 - width: 100%;
3541 - margin-top: var(--gap-peer);
3542 - }
3543 - }
3544 3486
3545 3487
3546 3488 }
@@ -7519,7 +7461,76 @@
7519 7461
7520 7462 /* Section 59-60: the compact pass and the capability pass. */
7521 7463 @layer responsive {
7522 - /* 59. Compact Responsive (late pass) WIDTH */
7464 + /* 25+59. Responsive - Compact WIDTH
7465 + One pass. These were two, §25 "early, so feature CSS can override it" and
7466 + §59 "late, so it wins conflicts", split for no reason except that the
7467 + cascade was decided by file position. `@layer responsive` decides it now,
7468 + so both halves win over every component rule wherever they sit and the
7469 + legend no longer has to tell you which one to add to.
7470 +
7471 + The two halves are kept in their original relative order, §25's rules
7472 + first, because within a layer source order still settles ties between
7473 + them. Nothing moved relative to anything else in this layer, which is
7474 + asserted rather than assumed: the per-layer rule sequence is compared
7475 + before and after. */
7476 + @media (max-width: 599px) {
7477 + .tab-navigation {
7478 + flex-wrap: wrap;
7479 + }
7480 +
7481 + .tab {
7482 + flex: 1 1 auto;
7483 + min-width: calc(33% - var(--gap-peer));
7484 + justify-content: center;
7485 + }
7486 +
7487 + .tab-label {
7488 + display: none;
7489 + }
7490 +
7491 + .kbd-hint {
7492 + display: none;
7493 + }
7494 +
7495 + .cards-grid {
7496 + grid-template-columns: 1fr;
7497 + }
7498 +
7499 + .task-table {
7500 + font-size: var(--font-size-base);
7501 + }
7502 +
7503 + .filter-bar {
7504 + flex-direction: column;
7505 + }
7506 +
7507 + .page-title {
7508 + font-size: var(--font-size-3xl);
7509 + }
7510 +
7511 + .day-plan-content {
7512 + flex-direction: column;
7513 + }
7514 +
7515 + /* No .day-plan-sidebar here. It used to set width: 100% and
7516 + max-height: 200px, and §59 sets both again (max-height: none) after the
7517 + component rule in §38, so this pass never decided either. */
7518 +
7519 + .modal-container {
7520 + width: 95%;
7521 + max-height: 95vh;
7522 + }
7523 +
7524 + .bulk-actions-bar {
7525 + flex-wrap: wrap;
7526 + }
7527 +
7528 + .bulk-select-all {
7529 + width: 100%;
7530 + margin-top: var(--gap-peer);
7531 + }
7532 + }
7533 +
7523 7534
7524 7535 /* --- Safe area padding + room for mobile tab bar --- */
7525 7536 @media (max-width: 599px) {