@bongos/core 1.24.47 → 1.24.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -60,6 +60,9 @@
60
60
  shadows, motion, stacking — every surface loads. Imported FIRST so this
61
61
  sheet's own rules follow it; the hall's scale names below are aliases of it. */
62
62
  @import url("/modules/ui-design/public/tokens.css");
63
+ /* The hall's one button and one field (task 1005084): .btn and its modifiers,
64
+ the text field / select / textarea. Straight after the scales it spends. */
65
+ @import url("controls.css");
63
66
  @import url("page-notes.css");
64
67
  @import url("craft-review.css");
65
68
 
@@ -430,20 +433,7 @@ code, kbd, pre {
430
433
  the composition around it. */
431
434
  .num, .tabular { font-variant-numeric: tabular-nums; }
432
435
 
433
- select, input[type="text"], input[type="search"], textarea {
434
- font-family: var(--font-body);
435
- font-size: 14px;
436
- color: var(--ink);
437
- background: none;
438
- border: 1px solid var(--rule);
439
- border-radius: var(--radius-pill);
440
- min-height: 30px;
441
- padding: 5px 12px;
442
- }
443
- select:hover, input[type="text"]:hover, input[type="search"]:hover { border-color: var(--ink-faint); }
444
- textarea { border-radius: var(--radius-sm); }
445
- select:disabled { opacity: 0.55; cursor: not-allowed; }
446
- select option { background: var(--bg-card); color: var(--ink); }
436
+ /* The field (text input, select, textarea) is controls.css's (task 1005084). */
447
437
 
448
438
  button { font-family: var(--font-body); }
449
439
 
@@ -1422,8 +1412,7 @@ html.setup-gate-open { overflow: hidden; }
1422
1412
  }
1423
1413
  .setup-gate code { font-family: var(--font-mono); font-size: 14px; padding: 1px 6px; border-radius: 6px; background: var(--glass); }
1424
1414
  .setup-gate__crafts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
1425
- .setup-gate__craft,
1426
- .setup-gate__save {
1415
+ .setup-gate__craft {
1427
1416
  min-height: 36px;
1428
1417
  padding: 0 16px;
1429
1418
  border-radius: var(--radius-pill);
@@ -1435,8 +1424,8 @@ html.setup-gate-open { overflow: hidden; }
1435
1424
  cursor: pointer;
1436
1425
  }
1437
1426
  .setup-gate__craft[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-tint); }
1438
- .setup-gate__save { margin-top: 12px; background: var(--accent); border-color: var(--accent); color: var(--accent-on); }
1439
- .setup-gate__save:disabled { opacity: .5; cursor: default; }
1427
+ /* The save is the shared primary door (controls.css, task 1005084). */
1428
+ .setup-gate__save { margin-top: 12px; }
1440
1429
  .setup-gate__err { margin: 8px 0 0; font-size: 14px; color: var(--danger); }
1441
1430
  .setup-gate__foot { margin: 24px 0 0; font-size: 14px; }
1442
1431
  .setup-gate__foot a { color: var(--ink-soft); }
@@ -2634,23 +2623,16 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
2634
2623
  wherever there is room and drops it where there is not. */
2635
2624
  min-width: min(150px, 100%);
2636
2625
  max-width: 100%;
2637
- min-height: 32px;
2638
- font-family: var(--font-body);
2639
- padding: 4px 8px;
2640
- font-size: 13.5px;
2641
2626
  text-transform: none;
2642
2627
  letter-spacing: normal;
2643
2628
  font-weight: 400;
2644
2629
  }
2645
- /* task 1829: the Work Board free-text search box, sized to match the filter
2646
- selects it sits alongside. */
2630
+ /* task 1829: the Work Board free-text search box. Both it and the selects are
2631
+ the shared field (controls.css, task 1005084); the filter only sets widths
2632
+ and undoes the label voice they would inherit. */
2647
2633
  .filter input[type="search"] {
2648
2634
  min-width: min(200px, 100%);
2649
2635
  max-width: 100%;
2650
- min-height: 32px;
2651
- font-family: var(--font-body);
2652
- padding: 4px 8px;
2653
- font-size: 13.5px;
2654
2636
  text-transform: none;
2655
2637
  letter-spacing: normal;
2656
2638
  font-weight: 400;
@@ -2673,94 +2655,8 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
2673
2655
  }
2674
2656
  .pager__range { font-family: var(--font-mono); font-size: 12px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
2675
2657
 
2676
- /* Pill or nothing (DESIGN.md, Shapes). A ghost button is a hairline pill; the
2677
- one filled shape on a page is the accent door, and only where the action is
2678
- the live thing. 28px of box plus the row’s own air clears the 24px floor. */
2679
- .btn-ghost {
2680
- display: inline-flex;
2681
- align-items: center;
2682
- justify-content: center;
2683
- gap: 6px;
2684
- min-height: 30px;
2685
- min-width: 56px;
2686
- padding: 0 14px;
2687
- font-size: 13px;
2688
- text-transform: lowercase;
2689
- color: var(--ink-soft);
2690
- background: none;
2691
- border: 1px solid var(--rule);
2692
- border-radius: var(--radius-pill);
2693
- cursor: pointer;
2694
- }
2695
- .btn-ghost:hover:not(:disabled) { border-color: var(--ink-faint); color: var(--ink); text-decoration: none; }
2696
- .btn-ghost:disabled { color: var(--ink-faint); border-color: var(--rule-soft); cursor: default; }
2697
-
2698
- /* The accent door: the page’s one primary action. --accent-on is the dark ink
2699
- that goes on the salmon; white on it fails AA and is banned. */
2700
- .btn-accent {
2701
- display: inline-flex;
2702
- align-items: center;
2703
- justify-content: center;
2704
- gap: 6px;
2705
- min-height: 34px;
2706
- min-width: 74px;
2707
- padding: 0 16px;
2708
- font-size: 13.5px;
2709
- font-weight: 500;
2710
- text-transform: lowercase;
2711
- color: var(--accent-on);
2712
- background: var(--accent);
2713
- border: 0;
2714
- border-radius: var(--radius-pill);
2715
- cursor: pointer;
2716
- }
2717
- .btn-accent:hover:not(:disabled) { background: var(--accent-lift); color: var(--accent-on); text-decoration: none; }
2718
- .btn-accent:disabled { background: var(--glass); color: var(--ink-faint); cursor: default; }
2719
-
2720
- /* `.btn` / `.btn--ghost` — the SECOND button vocabulary in the hall, used by
2721
- ideas, idea, copy-desk, my-projects and collab. Task 1003305 found it had no
2722
- rule anywhere in the surface: every one of those buttons was rendering as a
2723
- browser default control, on a page whose every other shape is a pill. They
2724
- are not renamed to .btn-accent/.btn-ghost because the class is spelled into
2725
- markup and into tests/idea_spark_hall.mjs; instead the two vocabularies are
2726
- made to say the same thing. `.btn` is the accent door and `.btn--ghost` its
2727
- quiet sibling, which is exactly how the calling pages already use the pair
2728
- (submit vs. discard, mark vs. withdraw). --accent-on is the dark ink for the
2729
- salmon; white on it fails AA and DESIGN.md bans it. */
2730
- .btn {
2731
- display: inline-flex;
2732
- align-items: center;
2733
- justify-content: center;
2734
- gap: 6px;
2735
- min-height: 34px;
2736
- min-width: 74px;
2737
- padding: 0 16px;
2738
- font-family: var(--font-body);
2739
- font-size: 13.5px;
2740
- font-weight: 500;
2741
- text-transform: lowercase;
2742
- color: var(--accent-on);
2743
- background: var(--accent);
2744
- /* transparent rather than absent: collab.css's `.btn--quiet` sets only a
2745
- border-COLOUR, and a modifier cannot paint an edge that was never reserved. */
2746
- border: var(--line) solid transparent;
2747
- border-radius: var(--radius-pill);
2748
- cursor: pointer;
2749
- }
2750
- .btn:hover:not(:disabled) { background: var(--accent-lift); color: var(--accent-on); text-decoration: none; }
2751
- .btn:disabled { background: var(--glass); color: var(--ink-faint); cursor: default; }
2752
- .btn--ghost {
2753
- min-height: 30px;
2754
- min-width: 56px;
2755
- padding: 0 14px;
2756
- font-size: 13px;
2757
- font-weight: 400;
2758
- color: var(--ink-soft);
2759
- background: none;
2760
- border-color: var(--rule);
2761
- }
2762
- .btn--ghost:hover:not(:disabled) { background: none; border-color: var(--ink-faint); color: var(--ink); }
2763
- .btn--ghost:disabled { background: none; color: var(--ink-faint); border-color: var(--rule-soft); }
2658
+ /* The buttons — .btn and its modifiers, and the older names pages still write
2659
+ (.btn-accent, .btn-ghost, .btn--ghost …) — are controls.css's (task 1005084). */
2764
2660
 
2765
2661
  /* ---------- profile / standing ---------- */
2766
2662
 
@@ -3040,11 +2936,8 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
3040
2936
  gap keeps the label and the select together when the lede wraps. */
3041
2937
  .curve__filter { display: inline-flex; align-items: center; gap: 6px; margin-left: 10px; }
3042
2938
  .curve__filter-label { color: var(--ink-soft); }
3043
- .curve__filter-select {
3044
- font: inherit; color: inherit; background: var(--surface-2);
3045
- border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
3046
- padding: 2px 6px; max-width: 16ch;
3047
- }
2939
+ /* the shared field (controls.css); only its width is the filter's */
2940
+ .curve__filter-select { max-width: 16ch; }
3048
2941
 
3049
2942
  .curve__headline {
3050
2943
  display: grid;
@@ -3297,22 +3190,6 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
3297
3190
  }
3298
3191
  .setup__divider::before, .setup__divider::after { content: ""; flex: 1; border-top: 1px solid var(--rule-soft); }
3299
3192
 
3300
- .setup__btn {
3301
- display: inline-flex;
3302
- align-items: center;
3303
- gap: 8px;
3304
- height: 34px;
3305
- padding: 0 16px;
3306
- border-radius: var(--radius-sm);
3307
- border: 1px solid var(--accent);
3308
- background: var(--accent);
3309
- color: #fff;
3310
- font-size: 13.5px;
3311
- font-weight: 600;
3312
- cursor: pointer;
3313
- }
3314
- .setup__btn:hover:not(:disabled) { background: var(--accent-deep); border-color: var(--accent-deep); color: #fff; text-decoration: none; }
3315
- .setup__btn:disabled, .setup__btn--open[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
3316
3193
  .setup__getcode { margin: 10px 0; }
3317
3194
  /* A <summary> is a control, so it owes the 24px floor like any other; it
3318
3195
  measured 20px tall (task 1003304). The height is bought with padding rather
@@ -3387,31 +3264,9 @@ html[data-door="out"] #hall-main { width: 100%; }
3387
3264
  line-height: 18px;
3388
3265
  }
3389
3266
  .landing__cta { margin: 14px 0; }
3390
- .landing__btn {
3391
- display: inline-flex;
3392
- align-items: center;
3393
- justify-content: center;
3394
- gap: 10px;
3395
- min-height: 46px;
3396
- padding: 0 22px;
3397
- border-radius: var(--radius-pill);
3398
- border: 0;
3399
- background: var(--accent);
3400
- color: var(--accent-on);
3401
- font-size: 14px;
3402
- font-weight: 500;
3403
- text-transform: lowercase;
3404
- cursor: pointer;
3405
- }
3406
- .landing__btn:hover { background: var(--accent-lift); text-decoration: none; color: var(--accent-on); }
3267
+ /* .landing__btn is the shared primary door, --quiet its ghost (controls.css). */
3407
3268
  .landing__btn--block { display: flex; width: 100%; }
3408
3269
  .landing__gh { flex-shrink: 0; }
3409
- .landing__btn--quiet {
3410
- background: transparent;
3411
- color: var(--ink);
3412
- box-shadow: inset 0 0 0 1px var(--border-strong);
3413
- }
3414
- .landing__btn--quiet:hover { background: var(--surface-2); color: var(--ink); }
3415
3270
  .landing__note { font-size: 12.5px; color: var(--ink-faint); }
3416
3271
  .landing__error { color: var(--danger); }
3417
3272
  .landing__error-h { color: var(--danger); margin: 0 0 4px; font-size: 14px; }
@@ -3642,29 +3497,8 @@ html[data-door="out"] #hall-main { width: 100%; }
3642
3497
  the touches chip and the whole-card selection target (promoted from work.css,
3643
3498
  task 1003659, so their cascade position is the same on every page). */
3644
3499
 
3645
- /* The page's one primary action, and the only accent FILL on the board.
3646
- --accent-on is the dark ink that goes on the salmon: white on it fails AA and
3647
- DESIGN.md bans it outright, which is what the old `color: #fff` was. */
3648
- .task__claim {
3649
- display: inline-flex;
3650
- align-items: center;
3651
- justify-content: center;
3652
- min-height: 34px;
3653
- min-width: 74px;
3654
- padding: 0 16px;
3655
- background: var(--accent);
3656
- border: 0;
3657
- color: var(--accent-on);
3658
- border-radius: var(--radius-pill);
3659
- font-size: 13.5px;
3660
- font-weight: 500;
3661
- text-transform: lowercase;
3662
- cursor: pointer;
3663
- white-space: nowrap;
3664
- transition: background 150ms, opacity 150ms;
3665
- }
3666
- .task__claim:hover:not(:disabled) { background: var(--accent-lift); color: var(--accent-on); }
3667
- .task__claim:disabled { background: var(--glass); color: var(--ink-faint); cursor: default; }
3500
+ /* The page's one primary action, and the only accent FILL on the board: the
3501
+ shared primary door at the row size (controls.css, task 1005084). */
3668
3502
 
3669
3503
  /* Files a claimable task is responsible for — a compact count chip in the meta
3670
3504
  row; the full path list rides the tooltip (task 2170 density pass). The mono
@@ -3778,27 +3612,13 @@ html[data-door="out"] #hall-main { width: 100%; }
3778
3612
  color: var(--ink-faint);
3779
3613
  }
3780
3614
 
3781
- .wip__release {
3782
- display: inline-flex;
3783
- align-items: center;
3784
- justify-content: center;
3785
- min-height: 30px;
3786
- padding: 0 14px;
3787
- background: none;
3788
- border: var(--line) solid var(--rule);
3789
- color: var(--ink-soft);
3790
- border-radius: var(--radius-pill);
3791
- font-size: 13px;
3792
- text-transform: lowercase;
3793
- cursor: pointer;
3794
- transition: background 150ms, color 150ms, border-color 150ms;
3795
- }
3615
+ /* .wip__release is the shared ghost at the row size (controls.css); a release
3616
+ is the undo of a claim, so its hover warns. */
3796
3617
  .wip__release:hover:not(:disabled) {
3797
3618
  background: var(--danger-weak);
3798
3619
  color: var(--danger);
3799
3620
  border-color: color-mix(in srgb, var(--danger) 40%, transparent);
3800
3621
  }
3801
- .wip__release:disabled { opacity: 0.55; cursor: default; }
3802
3622
 
3803
3623
  .wip__select {
3804
3624
  appearance: none;
@@ -4064,38 +3884,8 @@ html[data-door="out"] #hall-main { width: 100%; }
4064
3884
  .td-dep:hover { text-decoration: underline; }
4065
3885
  .td-dep-status { color: var(--ink-faint); font-size: 12px; margin-left: 6px; }
4066
3886
  .td-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 18px 0 0; }
4067
- /* Pill or nothing (DESIGN.md, Shapes): the ghost pill, with --btn--primary the
4068
- one accent door. It carried a literal `#fff` on the salmon until task 1003305
4069
- — the exact pairing DESIGN.md bans, because it fails AA. */
4070
- .td-btn {
4071
- display: inline-flex;
4072
- align-items: center;
4073
- justify-content: center;
4074
- font: inherit;
4075
- font-size: 13px;
4076
- min-height: 30px;
4077
- min-width: 56px;
4078
- padding: 0 14px;
4079
- border: var(--line) solid var(--rule);
4080
- border-radius: var(--radius-pill);
4081
- background: none;
4082
- color: var(--ink-soft);
4083
- text-transform: lowercase;
4084
- cursor: pointer;
4085
- }
4086
- .td-btn:hover:not(:disabled) { border-color: var(--ink-faint); color: var(--ink); text-decoration: none; }
4087
- .td-btn--primary {
4088
- min-height: 34px;
4089
- min-width: 74px;
4090
- padding: 0 16px;
4091
- font-weight: 500;
4092
- background: var(--accent);
4093
- color: var(--accent-on);
4094
- border-color: var(--accent);
4095
- }
4096
- .td-btn--primary:hover:not(:disabled) { background: var(--accent-lift); border-color: var(--accent-lift); color: var(--accent-on); }
4097
- .td-btn:disabled { color: var(--ink-faint); border-color: var(--rule-soft); cursor: default; }
4098
- .td-btn--primary:disabled { background: var(--glass); }
3887
+ /* .td-btn is the shared ghost at the row size and .td-btn--primary the accent
3888
+ door (controls.css, task 1005084). */
4099
3889
  .td-action-note { flex-basis: 100%; font-size: 12.5px; color: var(--ink-soft); margin: 4px 0 0; }
4100
3890
 
4101
3891
  /* Idea triage inside the record overlay (task 1002447). A two-column grid so
@@ -4103,17 +3893,9 @@ html[data-door="out"] #hall-main { width: 100%; }
4103
3893
  .td-form { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 10px; margin: 14px 0 0; }
4104
3894
  .td-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
4105
3895
  .td-field--wide { grid-column: 1 / -1; }
4106
- /* The base `select, input` rule already carries the world's field; this only
4107
- re-states the sizing the two-column grid needs. */
4108
- .td-field input, .td-field select {
4109
- font-size: 13px;
4110
- min-width: 0;
4111
- max-width: 100%;
4112
- }
4113
- /* The 24px floor (task 1004301 found it failing): at 13px the base field's padding left a
4114
- number input 21px tall beside a select that clears it — the task page's "Wait for task"
4115
- box. Sized to sit level with its select. */
4116
- .td-field input { min-height: 26px; box-sizing: border-box; }
3896
+ /* The field is the shared one (controls.css); the two-column grid only needs
3897
+ it to shrink with its column. */
3898
+ .td-field input, .td-field select { min-width: 0; max-width: 100%; }
4117
3899
  .td-form .td-actions, .td-form-hint, .td-form .td-action-note { grid-column: 1 / -1; }
4118
3900
  .td-form .td-actions { margin: 4px 0 0; }
4119
3901
  .td-form-hint { font-size: 12.5px; color: var(--ink-soft); margin: 0; }
@@ -4316,7 +4098,6 @@ html[data-door="out"] #hall-main { width: 100%; }
4316
4098
  .filter-views__tag { font-size: 11px; color: var(--ink-faint); margin-left: 6px; }
4317
4099
  .filter-views__empty, .filter-views__note { font-size: 12.5px; color: var(--ink-soft); margin: 0 0 10px; }
4318
4100
  .filter-views__note:empty { display: none; }
4319
- .filter-views__row .btn-ghost { min-height: 24px; padding: 0 8px; font-size: 12px; }
4320
4101
  .filter-views__save { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; }
4321
4102
  .filter-views__save .filter { flex: 1 1 180px; }
4322
4103
  /* On a phone the button can sit anywhere in a wrapped row, so the menu spans the
@@ -4378,9 +4159,6 @@ html[data-door="out"] #hall-main { width: 100%; }
4378
4159
  than edit the markup, the name joins the lede it meant. */
4379
4160
  .scroll__note { margin: 0 0 14px; font-size: 13.5px; color: var(--ink-soft); max-width: var(--measure); }
4380
4161
 
4381
- /* collab.js:73-74 — the settle buttons asked for a small variant of .btn that
4382
- does not exist, so "Someone helped" rendered full-size on every row. */
4383
- .btn--sm { min-height: 26px; padding: 0 11px; font-size: 12.5px; }
4384
4162
 
4385
4163
  /* The notice line: roster.js and blockers.js notice() set body.className='note'
4386
4164
  for an empty / error message, and neither page's sheet defines it. */
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.24.47",
3
+ "version": "1.24.48",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.24.47",
9
+ "version": "1.24.48",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.24.47",
3
+ "version": "1.24.48",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
@@ -11253,5 +11253,11 @@
11253
11253
  "id": "1005082",
11254
11254
  "text": "The design rulebook now describes the builders' hall as it really is, and spells out the name: 'cloud bongos' in the logo, 'Cloud Bongos' in sentences. The design-tool token file is now built automatically from the real styles"
11255
11255
  }
11256
+ ],
11257
+ "1.24.48": [
11258
+ {
11259
+ "id": "1005084",
11260
+ "text": "The builders' hall now has one button and one text box style everywhere instead of eight button sizes and five box styles; main buttons are the full 46px pill with dark text on the orange, and the setup screen's save button is"
11261
+ }
11256
11262
  ]
11257
11263
  }
package/src/module-api.js CHANGED
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
81
81
  // MAJOR (see allowBoxScope below): passes the request through untouched.
82
82
  function deprecatedNoopMiddleware(_req, _res, next) { next(); }
83
83
 
84
- const CORE_VERSION = '1.24.47'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
84
+ const CORE_VERSION = '1.24.48'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
85
85
 
86
86
  // A namespaced logger so a module's log lines are attributable + consistent.
87
87
  // Usage: const log = api.logger('discord'); log.info('mounted');
@@ -196,7 +196,10 @@ test('goals.html no longer borrows work.css, and work.css no longer holds what i
196
196
  assert.ok(!new RegExp(`^${sel.replace('.', '\\.')}(\\s|:|,|\\{)`, 'm').test(work), `work.css must not restate ${sel}`);
197
197
  }
198
198
  const style = read('style.css');
199
- for (const sel of ['.claim-count-line', '.wip__release', '.wip__select']) {
199
+ for (const sel of ['.claim-count-line', '.wip__select']) {
200
200
  assert.ok(new RegExp(`^${sel.replace('.', '\\.')} \\{`, 'm').test(style), `style.css carries ${sel}`);
201
201
  }
202
+ // task 1005084: .wip__release is the shared ghost (controls.css); style.css keeps its warning hover
203
+ assert.match(read('controls.css'), /\.wip__release/, 'the shared sheet draws .wip__release');
204
+ assert.match(style, /^\.wip__release:hover:not\(:disabled\) \{/m, 'style.css keeps the release\'s warning hover');
202
205
  });
@@ -42,6 +42,7 @@ const HALL = path.join(ROOT, 'modules', 'hall-ui', 'public');
42
42
  const read = (f) => fs.readFileSync(path.join(HALL, f), 'utf8');
43
43
 
44
44
  const styleCss = read('style.css');
45
+ const controlsCss = read('controls.css');
45
46
  const workCss = read('work.css');
46
47
  const workHtml = read('work.html');
47
48
 
@@ -104,7 +105,8 @@ test('a prose link buys BOTH axes — padding for width, negative margin to give
104
105
  // ---- 3. the world's own bans ------------------------------------------------
105
106
 
106
107
  test('nothing on the board paints text white on the accent', () => {
107
- const claim = rule(styleCss, '.task__claim');
108
+ // task 1005084: the claim is the shared primary door, drawn in controls.css
109
+ const claim = controlsCss.replace(/\/\*[\s\S]*?\*\//g, '').match(/([^{}]*\.task__claim\b[^{}]*)\{([^{}]*background:[^{}]*)\}/)?.[2] ?? null;
108
110
  assert.ok(claim, '.task__claim has a rule');
109
111
  assert.match(claim, /background:\s*var\(--accent\)/, 'the claim button is the page\'s one accent fill');
110
112
  assert.match(claim, /color:\s*var\(--accent-on\)/,
@@ -116,7 +118,9 @@ test('nothing on the board paints text white on the accent', () => {
116
118
  });
117
119
 
118
120
  test('the shared task + bulk-toolbar rules live in style.css (the shared base), not the page-local work.css', () => {
119
- for (const sel of ['.task__age', '.task__age--stale', '.task__tag--newcomer', '.task__tag--mine', '.task__tag--rank', '.task__tag--rank-open', '.task__claim', '.task__touches', '.task', '.bulk-toolbar', '.bulk-toolbar__count', '.bulk-toolbar__actions', '.bulk-toolbar__btn', '.bulk-toolbar__clear']) {
121
+ // .task__claim left for the shared controls.css (task 1005084); work.css still must not restate it
122
+ assert.equal(rule(workCss, '.task__claim'), null, 'work.css must not restate .task__claim');
123
+ for (const sel of ['.task__age', '.task__age--stale', '.task__tag--newcomer', '.task__tag--mine', '.task__tag--rank', '.task__tag--rank-open', '.task__touches', '.task', '.bulk-toolbar', '.bulk-toolbar__count', '.bulk-toolbar__actions', '.bulk-toolbar__btn', '.bulk-toolbar__clear']) {
120
124
  assert.ok(rule(styleCss, sel), `style.css carries ${sel}, beside .task__tag`);
121
125
  assert.equal(rule(workCss, sel), null, `work.css must not restate ${sel}`);
122
126
  }
@@ -147,10 +147,12 @@ test('A: an older branding pack with no joinability falls back to the apply door
147
147
  });
148
148
 
149
149
  test('A: the quiet fill is a defined variant, not an inline colour', () => {
150
- const css = read('style.css');
151
- const i = css.indexOf('\n.landing__btn--quiet {');
152
- assert.ok(i > 0, 'style.css defines .landing__btn--quiet');
153
- const block = css.slice(i, css.indexOf('}', i));
150
+ // task 1005084: .landing__btn--quiet is the shared ghost in controls.css
151
+ const css = read('controls.css').replace(/\/\*[\s\S]*?\*\//g, '');
152
+ const m = css.match(/([^{}]*\.landing__btn--quiet[\s,][^{}]*)\{([^{}]*)\}/);
153
+ assert.ok(m, 'controls.css defines .landing__btn--quiet');
154
+ const block = m[2];
155
+ assert.match(block, /background:\s*transparent/, 'the quiet variant is the ghost');
154
156
  assert.deepEqual(block.match(/#[0-9a-f]{3,8}\b/gi) || [], [], 'the variant carries no literal colour');
155
157
  // Same geometry as the request button means it inherits .landing__btn's
156
158
  // min-height and padding rather than restating them.