@invisibleloop/pulse 0.14.2 → 0.15.1

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.
@@ -32,15 +32,21 @@ Use `mcp__chrome-devtools__navigate_page` to load the page route, then `mcp__chr
32
32
 
33
33
  ### 6. Lighthouse — desktop
34
34
 
35
- Run `mcp__chrome-devtools__lighthouse_audit` on the route with `{ "strategy": "desktop" }`.
35
+ **Pre-flight (required before every Lighthouse run):**
36
+ 1. Call `pulse_build` to produce a production build and start the production server on port 3001.
37
+ 2. Call `navigate_page` with `url: "http://localhost:3001/"` so the browser is on the production server.
36
38
 
37
- **Pass bar: Performance, Accessibility, Best Practices, and SEO must all be 100.** Report the actual scores. If any score is below 100, identify the failing audit(s), fix the issue, and restart from step 3.
39
+ Then run `mcp__chrome-devtools__lighthouse_audit` with `{ "device": "desktop" }`.
40
+
41
+ **Pass bar: Accessibility, Best Practices, and SEO must all be 100.** Performance is measured and reported but is not a hard requirement (it varies with machine load). Report the actual scores. If Accessibility, Best Practices, or SEO is below 100, identify the failing audit(s), fix the issue, and restart from step 3.
38
42
 
39
43
  ### 7. Lighthouse — mobile
40
44
 
41
- Run `mcp__chrome-devtools__lighthouse_audit` on the same route with `{ "strategy": "mobile" }`.
45
+ The browser should still be on `http://localhost:3001/` from step 6. Run `mcp__chrome-devtools__lighthouse_audit` with `{ "device": "mobile" }`.
46
+
47
+ **Same pass bar: Accessibility, Best Practices, and SEO must all be 100.** Fix any failures and restart from step 3.
42
48
 
43
- **Same pass bar: all four categories must be 100.** Report the actual scores. If any score is below 100, fix and restart from step 3.
49
+ After both Lighthouse runs pass, call `pulse_restart_server` to return to the dev server.
44
50
 
45
51
  ### 8. Performance
46
52
 
@@ -36,13 +36,15 @@ Before finishing any spec, verify every point below. Fix anything that fails.
36
36
  - Navigation → `nav({ logo, links, actions })`
37
37
  - Footers → `footer({ logo, links, columns, legal, ... })`
38
38
 
39
- - **Creative override — raw HTML throughout is permitted** when the design intent genuinely calls for it: a highly custom visual identity, an asymmetric or typographically-driven layout, a brutalist/editorial/retro/neon/paper vibe where components would constrain the expression. This is a deliberate design decision, not a shortcut. When taking this path:
40
- - State it explicitly in the build brief: *"Building component-free — raw HTML throughout for creative control."*
39
+ - **Creative override — raw HTML throughout is permitted** when the design intent genuinely calls for it: a highly custom visual identity, an asymmetric or typographically-driven layout, a brutalist/editorial/retro/neon/paper vibe where components would constrain the expression, or a layout that requires features a component simply doesn't support (e.g. full-viewport height, custom gradient glows, clamp-scaled display type). This is a deliberate design decision, not a shortcut. When taking this path:
40
+ - **Declare it in a comment at the top of the spec** so the reviewer recognises it: `// component-free — creative override: <reason>`. This is the signal the review tool reads.
41
41
  - Functional atoms (`button`, `input`, `badge`, `modal`) should still come from components unless there is a specific design reason not to.
42
42
  - `/pulse-ui.css` is always required — it provides the token system your custom CSS will use.
43
43
  - The quality gate replaces the component checklist: **100/100/100/100 Lighthouse on both desktop and mobile is the pass bar.** A component-free page that passes every audit is correct. A component-heavy page that fails accessibility is not.
44
44
 
45
- - When reviewing a spec built under creative override, do not flag raw section HTML as a violation — check the Lighthouse results instead.
45
+ - **When reviewing**: before flagging a class name like `.hero` as a violation, first ask whether the `hero()` component could actually reproduce the layout. If the answer is no, it is a creative override — check Lighthouse instead of refactoring. Do not flatten a good custom layout into a generic component just to clear a pattern-match.
46
+
47
+ - **The review tool auto-detects creative override** from the spec comment. When detected, component pattern checks are shown as advisory (`⚡`) not as failures, and the Lighthouse gate is the stated pass bar.
46
48
 
47
49
  - **Never write App Store or Google Play download buttons by hand.** Always use `appBadge({ store: 'apple', href })` and `appBadge({ store: 'google', href })`. Raw `<a>` tags with badge images are incorrect — `appBadge` renders the correct accessible, styled badge for each store.
48
50
 
@@ -1 +1 @@
1
- 0.14.1
1
+ 0.14.2
@@ -1406,6 +1406,242 @@ a:hover {
1406
1406
  flex-shrink: 0;
1407
1407
  }
1408
1408
 
1409
+ /* ─── Sidebar search ─────────────────────────────────────────────────────────── */
1410
+ .sidebar-search-wrap {
1411
+ display: flex;
1412
+ align-items: center;
1413
+ gap: 0.4rem;
1414
+ padding: 0.6rem 0.75rem;
1415
+ border-bottom: 1px solid var(--border-subtle);
1416
+ flex-shrink: 0;
1417
+ position: relative;
1418
+ }
1419
+
1420
+ .sidebar-search-icon {
1421
+ color: var(--muted-2);
1422
+ flex-shrink: 0;
1423
+ pointer-events: none;
1424
+ }
1425
+
1426
+ .sidebar-search {
1427
+ flex: 1;
1428
+ min-width: 0;
1429
+ background: transparent;
1430
+ border: none;
1431
+ outline: none;
1432
+ font-family: var(--font);
1433
+ font-size: 0.82rem;
1434
+ color: var(--text);
1435
+ padding: 0;
1436
+ line-height: 1.4;
1437
+ }
1438
+
1439
+ .sidebar-search::placeholder {
1440
+ color: var(--muted-2);
1441
+ }
1442
+
1443
+ .sidebar-search::-webkit-search-cancel-button {
1444
+ -webkit-appearance: none;
1445
+ }
1446
+
1447
+ .sidebar-search-full {
1448
+ display: flex;
1449
+ align-items: center;
1450
+ justify-content: center;
1451
+ width: 22px;
1452
+ height: 22px;
1453
+ flex-shrink: 0;
1454
+ background: var(--surface-2);
1455
+ border: 1px solid var(--border);
1456
+ border-radius: 4px;
1457
+ color: var(--muted-2);
1458
+ cursor: pointer;
1459
+ transition: color 0.1s, background 0.1s;
1460
+ }
1461
+
1462
+ .sidebar-search-full:hover {
1463
+ color: var(--text);
1464
+ background: var(--border);
1465
+ }
1466
+
1467
+ .sidebar-no-results {
1468
+ padding: 0.75rem 1.25rem;
1469
+ font-size: 0.8rem;
1470
+ color: var(--muted-2);
1471
+ }
1472
+
1473
+ /* ─── Search overlay ─────────────────────────────────────────────────────────── */
1474
+ .search-overlay {
1475
+ position: fixed;
1476
+ inset: 0;
1477
+ z-index: 500;
1478
+ display: flex;
1479
+ align-items: flex-start;
1480
+ justify-content: center;
1481
+ padding-top: 10vh;
1482
+ }
1483
+
1484
+ .search-overlay[hidden] {
1485
+ display: none;
1486
+ }
1487
+
1488
+ .search-overlay-backdrop {
1489
+ position: absolute;
1490
+ inset: 0;
1491
+ background: rgba(0, 0, 0, 0.6);
1492
+ backdrop-filter: blur(3px);
1493
+ }
1494
+
1495
+ .search-overlay-panel {
1496
+ position: relative;
1497
+ width: min(640px, calc(100vw - 2rem));
1498
+ background: var(--surface);
1499
+ border: 1px solid var(--border);
1500
+ border-radius: 12px;
1501
+ box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
1502
+ display: flex;
1503
+ flex-direction: column;
1504
+ overflow: hidden;
1505
+ max-height: 70vh;
1506
+ }
1507
+
1508
+ .search-overlay-header {
1509
+ display: flex;
1510
+ align-items: center;
1511
+ gap: 0.75rem;
1512
+ padding: 0.875rem 1rem;
1513
+ border-bottom: 1px solid var(--border-subtle);
1514
+ flex-shrink: 0;
1515
+ }
1516
+
1517
+ .search-overlay-input-wrap {
1518
+ display: flex;
1519
+ align-items: center;
1520
+ gap: 0.6rem;
1521
+ flex: 1;
1522
+ color: var(--muted-2);
1523
+ }
1524
+
1525
+ .search-overlay-input {
1526
+ flex: 1;
1527
+ background: transparent;
1528
+ border: none;
1529
+ outline: none;
1530
+ font-family: var(--font);
1531
+ font-size: 1rem;
1532
+ color: var(--text);
1533
+ padding: 0;
1534
+ line-height: 1.4;
1535
+ }
1536
+
1537
+ .search-overlay-input::placeholder {
1538
+ color: var(--muted-2);
1539
+ }
1540
+
1541
+ .search-overlay-input::-webkit-search-cancel-button {
1542
+ -webkit-appearance: none;
1543
+ }
1544
+
1545
+ .search-overlay-close {
1546
+ font-family: var(--mono);
1547
+ font-size: 0.7rem;
1548
+ color: var(--muted-2);
1549
+ background: var(--surface-2);
1550
+ border: 1px solid var(--border);
1551
+ border-radius: 4px;
1552
+ padding: 0.2rem 0.5rem;
1553
+ cursor: pointer;
1554
+ flex-shrink: 0;
1555
+ }
1556
+
1557
+ .search-overlay-results {
1558
+ overflow-y: auto;
1559
+ flex: 1;
1560
+ padding: 0.5rem;
1561
+ }
1562
+
1563
+ .search-result {
1564
+ display: block;
1565
+ padding: 0.65rem 0.75rem;
1566
+ border-radius: 6px;
1567
+ text-decoration: none;
1568
+ color: var(--text);
1569
+ transition: background 0.1s;
1570
+ }
1571
+
1572
+ .search-result:hover,
1573
+ .search-result--selected {
1574
+ background: var(--surface-2);
1575
+ }
1576
+
1577
+ .search-result-meta {
1578
+ margin-bottom: 0.15rem;
1579
+ }
1580
+
1581
+ .search-result-section {
1582
+ font-size: 0.68rem;
1583
+ font-weight: 600;
1584
+ text-transform: uppercase;
1585
+ letter-spacing: 0.08em;
1586
+ color: var(--accent);
1587
+ }
1588
+
1589
+ .search-result-title {
1590
+ font-size: 0.9rem;
1591
+ font-weight: 500;
1592
+ color: var(--text);
1593
+ line-height: 1.4;
1594
+ }
1595
+
1596
+ .search-result-title mark,
1597
+ .search-result-snip mark {
1598
+ background: rgba(201, 184, 0, 0.3);
1599
+ color: inherit;
1600
+ border-radius: 2px;
1601
+ }
1602
+
1603
+ .search-result-snip {
1604
+ font-size: 0.78rem;
1605
+ color: var(--muted-2);
1606
+ margin-top: 0.25rem;
1607
+ line-height: 1.5;
1608
+ display: -webkit-box;
1609
+ -webkit-line-clamp: 2;
1610
+ -webkit-box-orient: vertical;
1611
+ overflow: hidden;
1612
+ }
1613
+
1614
+ .search-overlay-empty {
1615
+ padding: 2rem 1rem;
1616
+ text-align: center;
1617
+ color: var(--muted-2);
1618
+ font-size: 0.9rem;
1619
+ }
1620
+
1621
+ .search-overlay-footer {
1622
+ display: flex;
1623
+ gap: 1.25rem;
1624
+ padding: 0.6rem 1rem;
1625
+ border-top: 1px solid var(--border-subtle);
1626
+ flex-shrink: 0;
1627
+ font-size: 0.72rem;
1628
+ color: var(--muted-2);
1629
+ }
1630
+
1631
+ .search-overlay-footer kbd {
1632
+ display: inline-flex;
1633
+ align-items: center;
1634
+ justify-content: center;
1635
+ font-family: var(--mono);
1636
+ font-size: 0.68rem;
1637
+ background: var(--surface-2);
1638
+ border: 1px solid var(--border);
1639
+ border-radius: 3px;
1640
+ padding: 0.1rem 0.35rem;
1641
+ color: var(--muted-2);
1642
+ margin-right: 0.2rem;
1643
+ }
1644
+
1409
1645
  .logo-link {
1410
1646
  display: flex;
1411
1647
  align-items: center;