@bridge-ds/toolbar 0.2.0 → 0.3.0

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.
@@ -1,15 +1,15 @@
1
1
  if (typeof document !== 'undefined' && !document.querySelector('style[data-bridge-toolbar-css="' + "Toolbar" + '"]')) {
2
2
  const style = document.createElement('style');
3
3
  style.setAttribute('data-bridge-toolbar-css', "Toolbar");
4
- style.textContent = "/* The Bridge toolbar floats over the admin's content column: bottom right by default, docked left or centre on demand,\n lifted above the page's primary buttons and the outlined surfaces when every dock would cover one. One row, 44px,\n on desktop; compact density so every control is 36px. The border stays neutral. Text: 14 and 12, plus the wordmark.\n Tokens only. */\n._anchor_nhlur_5 {\n position: fixed;\n inset-inline: var(--space-4);\n bottom: var(--space-4);\n z-index: var(--layer-sticky);\n display: flex;\n justify-content: flex-end;\n pointer-events: none;\n}\n\n._anchor_nhlur_5[data-dock=\"start\"] {\n justify-content: flex-start;\n}\n\n._anchor_nhlur_5[data-dock=\"center\"] {\n justify-content: center;\n}\n\n/* Never over the sidebar: the docks live in the content column (the shell's sidebar is size-60 wide above 1024px). */\n@media (min-width: 1025px) {\n ._anchor_nhlur_5 {\n inset-inline-start: calc(var(--size-60) + var(--space-4));\n }\n}\n\n._panel_nhlur_30,\n._pill_nhlur_31 {\n box-sizing: border-box;\n border: var(--border-width-default) solid var(--color-border-default);\n background-color: var(--color-surface-raised);\n box-shadow: var(--elevation-overlay);\n color: var(--color-text-default);\n font-family: var(--typography-ui-family);\n font-size: var(--typography-ui-size);\n line-height: var(--typography-ui-line-height);\n pointer-events: auto;\n}\n\n._panel_nhlur_30[data-dragging],\n._pill_nhlur_31[data-dragging] {\n box-shadow: var(--elevation-modal);\n}\n\n/* Desktop: one row, 44px tall with its border (36px controls); a note, when there is one, takes a second row. */\n._panel_nhlur_30 {\n display: grid;\n grid-template-areas:\n \"grip title actions collapse\"\n \"note note note note\";\n grid-template-rows: calc(var(--size-11) - 2 * var(--border-width-default)) auto;\n grid-template-columns: auto auto minmax(0, 1fr) auto;\n align-items: center;\n column-gap: var(--space-2);\n max-width: min(100%, var(--size-300));\n padding: 0 var(--space-1);\n border-radius: var(--radius-overlay);\n}\n\n._grip_nhlur_63 {\n grid-area: grip;\n cursor: grab;\n touch-action: none;\n}\n\n._panel_nhlur_30[data-dragging] ._grip_nhlur_63 {\n cursor: grabbing;\n}\n\n._title_nhlur_73 {\n display: flex;\n grid-area: title;\n align-items: baseline;\n gap: var(--space-2);\n min-width: 0;\n margin: 0;\n}\n\n._brand_nhlur_82 {\n flex: none;\n font-family: var(--font-family-display);\n font-size: var(--typography-ui-size);\n font-weight: var(--font-weight-semibold);\n}\n\n/* Desktop: the wordmark only; the change's name is in the pill and in the This change tooltip. */\n._panel_nhlur_30 ._name_nhlur_90 {\n display: none;\n}\n\n._name_nhlur_90,\n._pillTitle_nhlur_95 {\n overflow: hidden;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n._actions_nhlur_102 {\n display: flex;\n grid-area: actions;\n align-items: center;\n justify-content: flex-end;\n gap: var(--space-2);\n min-width: 0;\n}\n\n._sides_nhlur_111 {\n flex: none;\n}\n\n._collapse_nhlur_115 {\n grid-area: collapse;\n}\n\n._phoneOnly_nhlur_119 {\n display: none;\n}\n\n._desktopOnly_nhlur_123 {\n display: contents;\n}\n\n._count_nhlur_127 {\n margin-inline-start: var(--space-1-5);\n color: var(--color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n/* The colour pair of each changed token: a 24px split swatch, before half and after half. Values in the tooltip. */\n._swatches_nhlur_134 {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n border-radius: var(--radius-inset);\n}\n\n._swatches_nhlur_134:focus-visible {\n outline: var(--focus-ring-width) solid var(--focus-ring-color);\n outline-offset: var(--focus-ring-offset);\n}\n\n._split_nhlur_146 {\n box-sizing: border-box;\n display: inline-flex;\n flex: none;\n width: var(--size-6);\n height: var(--size-6);\n overflow: hidden;\n border: var(--border-width-default) solid var(--color-border-strong);\n border-radius: var(--radius-pill);\n}\n\n._split_nhlur_146 > span {\n flex: 1 1 0;\n}\n\n/* Under 1.1:1 the two halves look alike: say so, so a near-white change reads as intended. */\n._subtle_nhlur_162 {\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n white-space: nowrap;\n}\n\n._more_nhlur_169 {\n white-space: nowrap;\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n font-variant-numeric: tabular-nums;\n}\n\n._noteRow_nhlur_176 {\n grid-area: note;\n min-width: 0;\n padding-block-end: var(--space-1);\n}\n\n._note_nhlur_176 {\n margin: 0;\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n._noteRow_nhlur_176 ._note_nhlur_176 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0 var(--space-2);\n padding-inline-start: var(--space-2);\n color: var(--color-text-default);\n}\n\n._noteAction_nhlur_198 {\n flex: none;\n}\n\n._sheet_nhlur_202 {\n width: min(90vw, var(--size-80));\n}\n\n._list_nhlur_206 {\n display: grid;\n max-height: var(--size-60);\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n}\n\n._item_nhlur_215 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--control-height-md);\n}\n\n._screenLink_nhlur_223,\n._here_nhlur_224 {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1-5);\n min-height: var(--control-height-md);\n}\n\n._here_nhlur_224 {\n font-weight: var(--font-weight-semibold);\n}\n\n._meta_nhlur_235 {\n flex: none;\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n/* Changed here: one focusable row per surface. Line 1 its role, line 2 its tokens (muted, 12). Nothing truncates. */\n._rows_nhlur_243 {\n display: grid;\n max-height: var(--size-60);\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n}\n\n._row_nhlur_243 {\n height: auto;\n min-height: var(--control-height-md);\n padding-block: var(--space-1);\n justify-content: flex-start;\n text-align: start;\n}\n\n._rowText_nhlur_260 {\n display: grid;\n min-width: 0;\n font-weight: var(--font-weight-regular);\n white-space: normal;\n}\n\n._rowName_nhlur_267 {\n color: var(--color-text-default);\n font-size: var(--typography-ui-size);\n line-height: var(--typography-ui-line-height);\n}\n\n._rowMeta_nhlur_273 {\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n._tipText_nhlur_279 {\n display: grid;\n}\n\n._tipStep_nhlur_283 {\n opacity: 0.8;\n}\n\n._sheetFoot_nhlur_287 {\n margin-top: var(--space-2);\n}\n\n._sheetSection_nhlur_291 {\n margin-top: var(--space-2);\n padding-top: var(--space-2);\n border-top: var(--border-width-default) solid var(--color-border-default);\n}\n\n._sheetSection_nhlur_291:first-child {\n margin-top: 0;\n padding-top: 0;\n border-top: 0;\n}\n\n._sectionTitle_nhlur_303 {\n margin: 0;\n font-weight: var(--font-weight-semibold);\n}\n\n/* A separate notice, not part of a list. */\n._notice_nhlur_309 {\n display: flex;\n align-items: flex-start;\n gap: var(--space-1-5);\n margin: var(--space-2) 0 0;\n padding-top: var(--space-2);\n border-top: var(--border-width-default) solid var(--color-border-default);\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n/* In the sheet on phones only: the token pairs and the way back. */\n._sheetPhone_nhlur_322 {\n display: none;\n}\n\n._back_nhlur_326 {\n display: inline-flex;\n align-items: center;\n min-height: var(--control-height-md);\n}\n\n._pill_nhlur_31 {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto auto;\n align-items: center;\n gap: var(--space-2);\n max-width: min(100%, var(--size-120));\n padding: var(--space-1) var(--space-1) var(--space-1) var(--space-4);\n border-radius: var(--radius-pill);\n}\n\n/* With a note under it, the pill becomes a small card. */\n._pill_nhlur_31[data-note] {\n border-radius: var(--radius-overlay);\n}\n\n._pill_nhlur_31 ._noteRow_nhlur_176 {\n grid-column: 1 / -1;\n padding-inline-end: var(--space-3);\n}\n\n._pill_nhlur_31 ._noteRow_nhlur_176 ._note_nhlur_176 {\n padding-inline-start: 0;\n}\n\n/* Show what changed: a dashed Deep Harbor frame (Bridge's tool colour, not the product's) on each changed surface,\n with a faint Deep Harbor tint and a role chip. Fixed layer: no pointer events, no focus, no layout. */\n._overlay_nhlur_358 {\n position: fixed;\n inset: 0;\n z-index: var(--layer-sticky);\n pointer-events: none;\n}\n\n._box_nhlur_365 {\n position: absolute;\n box-sizing: border-box;\n outline: var(--border-width-strong) dashed var(--color-action-primary-bg);\n outline-offset: var(--border-width-strong);\n}\n\n/* A page-sized surface: an inset frame, so it reads as a selection, not as the window edge. */\n._box_nhlur_365[data-page] {\n outline-offset: 0;\n border-radius: var(--radius-container);\n}\n\n/* No tint on the page frame: it would tint the very colour being compared. */\n._box_nhlur_365[data-page] ._tint_nhlur_379 {\n display: none;\n}\n\n/* No room above (top of the viewport): under the surface instead. */\n/* No room above (top of the viewport): inside the surface's top-left corner instead. */\n._box_nhlur_365[data-inside] ._chip_nhlur_385 {\n top: 0;\n bottom: auto;\n left: 0;\n}\n\n/* The surface a list row points at: solid frame, stronger tint. */\n._box_nhlur_365[data-emphasis] {\n outline-style: solid;\n}\n\n._box_nhlur_365[data-emphasis] ._tint_nhlur_379 {\n opacity: 0.1;\n}\n\n._box_nhlur_365[data-page] ._chip_nhlur_385 {\n top: var(--space-1);\n bottom: auto;\n left: var(--space-1);\n}\n\n._tint_nhlur_379 {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-color: var(--color-action-primary-bg);\n opacity: 0.04;\n}\n\n/* Above the surface's top-left corner, so it never hides the surface's own content. */\n/* Hidden by default: shown on hover, from its list row, and briefly when outlines turn on. */\n._chip_nhlur_385 {\n position: absolute;\n visibility: hidden;\n bottom: calc(100% + var(--border-width-strong) * 2);\n left: calc(var(--border-width-strong) * -2);\n max-width: var(--size-60);\n overflow: hidden;\n padding: 0 var(--space-1-5);\n border-radius: var(--radius-inset);\n background-color: var(--color-action-primary-bg);\n color: var(--color-action-primary-text);\n font-family: var(--typography-ui-family);\n font-size: var(--typography-caption-size);\n font-weight: var(--font-weight-medium);\n line-height: var(--typography-caption-line-height);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n._chip_nhlur_385[data-shown] {\n visibility: visible;\n}\n\n._tip_nhlur_279 {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n@media (max-width: 760px) {\n ._anchor_nhlur_5 {\n inset-inline: var(--space-2);\n bottom: var(--space-2);\n }\n\n /* Phone, open: docked to the bottom edge as one 44px row (sides, Changes, outline toggle, collapse). */\n ._anchor_nhlur_5[data-open] {\n inset-inline: 0;\n bottom: 0;\n }\n\n ._panel_nhlur_30 {\n grid-template-areas:\n \"actions toggle collapse\"\n \"note note note\";\n grid-template-rows: calc(var(--size-11) - var(--border-width-default)) auto;\n grid-template-columns: minmax(0, 1fr) auto auto;\n column-gap: var(--space-2);\n width: 100%;\n padding: 0 var(--space-1);\n border-width: var(--border-width-default) 0 0;\n border-radius: 0;\n }\n\n ._title_nhlur_73 {\n display: none;\n }\n\n ._phoneOnly_nhlur_119 {\n display: inline-flex;\n grid-area: toggle;\n }\n\n ._grip_nhlur_63,\n ._brand_nhlur_82,\n ._studio_nhlur_481,\n ._desktopOnly_nhlur_123 {\n display: none;\n }\n\n ._actions_nhlur_102 {\n justify-content: space-between;\n }\n\n ._noteRow_nhlur_176 ._note_nhlur_176 {\n padding-inline-start: 0;\n }\n\n ._pill_nhlur_31 {\n grid-template-columns: minmax(0, 1fr) auto auto;\n }\n\n ._sheetPhone_nhlur_322 {\n display: block;\n }\n}\n\n/* Below 480px the note's action takes its own line. */\n@media (max-width: 480px) {\n ._noteAction_nhlur_198 {\n flex-basis: 100%;\n justify-content: flex-start;\n }\n}\n";
4
+ style.textContent = "/* The Bridge toolbar floats over the admin's content column: bottom right by default, docked left or centre on demand,\n lifted above the page's primary buttons and the outlined surfaces when every dock would cover one. One row, 44px,\n on desktop; compact density so every control is 36px. The border stays neutral. Text: 14 and 12, plus the wordmark.\n Tokens only. */\n._anchor_a8mxc_5 {\n position: fixed;\n inset-inline: var(--space-4);\n bottom: var(--space-4);\n z-index: var(--layer-sticky);\n display: flex;\n justify-content: flex-end;\n pointer-events: none;\n}\n\n._anchor_a8mxc_5[data-dock=\"start\"] {\n justify-content: flex-start;\n}\n\n._anchor_a8mxc_5[data-dock=\"center\"] {\n justify-content: center;\n}\n\n/* Never over the sidebar: the docks live in the content column (the shell's sidebar is size-60 wide above 1024px). */\n@media (min-width: 1025px) {\n ._anchor_a8mxc_5 {\n inset-inline-start: calc(var(--size-60) + var(--space-4));\n }\n}\n\n._panel_a8mxc_30,\n._pill_a8mxc_31 {\n box-sizing: border-box;\n border: var(--border-width-default) solid var(--color-border-default);\n background-color: var(--color-surface-raised);\n box-shadow: var(--elevation-overlay);\n color: var(--color-text-default);\n font-family: var(--typography-ui-family);\n font-size: var(--typography-ui-size);\n line-height: var(--typography-ui-line-height);\n pointer-events: auto;\n}\n\n/* The outlines layer comes first in the document: the bar, on the same layer, paints above it and its scrim. */\n._panel_a8mxc_30,\n._pill_a8mxc_31 {\n position: relative;\n z-index: var(--layer-sticky);\n}\n\n._panel_a8mxc_30[data-dragging],\n._pill_a8mxc_31[data-dragging] {\n box-shadow: var(--elevation-modal);\n}\n\n/* Desktop: one row, 44px tall with its border (36px controls): compare, then the changes of this screen, then the\n rest. A note, when there is one, takes a second row. */\n._panel_a8mxc_30 {\n display: grid;\n grid-template-areas:\n \"grip title sides nav actions collapse\"\n \"note note note note note note\";\n grid-template-rows: calc(var(--size-11) - 2 * var(--border-width-default)) auto;\n grid-template-columns: auto auto auto auto minmax(0, 1fr) auto;\n align-items: center;\n column-gap: var(--space-2);\n max-width: min(100%, var(--size-300));\n padding: 0 var(--space-1);\n border-radius: var(--radius-overlay);\n}\n\n._grip_a8mxc_71 {\n grid-area: grip;\n cursor: grab;\n touch-action: none;\n}\n\n._panel_a8mxc_30[data-dragging] ._grip_a8mxc_71 {\n cursor: grabbing;\n}\n\n._title_a8mxc_81 {\n display: flex;\n grid-area: title;\n align-items: baseline;\n gap: var(--space-2);\n min-width: 0;\n margin: 0;\n}\n\n._brand_a8mxc_90 {\n flex: none;\n font-family: var(--font-family-display);\n font-size: var(--typography-ui-size);\n font-weight: var(--font-weight-semibold);\n}\n\n/* Desktop: the wordmark only; the change's name is in the pill and in the This change tooltip. */\n._panel_a8mxc_30 ._name_a8mxc_98 {\n display: none;\n}\n\n._name_a8mxc_98,\n._pillTitle_a8mxc_103 {\n overflow: hidden;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n._actions_a8mxc_110 {\n display: flex;\n grid-area: actions;\n align-items: center;\n justify-content: flex-end;\n gap: var(--space-2);\n min-width: 0;\n}\n\n._sides_a8mxc_119 {\n grid-area: sides;\n}\n\n/* The changes of this screen: the count (also the outlines toggle), Previous and Next, Isolate. */\n._nav_a8mxc_124 {\n display: flex;\n grid-area: nav;\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n}\n\n._countButton_a8mxc_132 {\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n._steps_a8mxc_137 {\n flex: none;\n}\n\n._collapse_a8mxc_141 {\n grid-area: collapse;\n}\n\n._count_a8mxc_132 {\n margin-inline-start: var(--space-1-5);\n color: var(--color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n/* The colour pair of each changed token: a 24px split swatch, before half and after half. Values in the tooltip. */\n._swatches_a8mxc_152 {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n border-radius: var(--radius-inset);\n}\n\n._swatches_a8mxc_152:focus-visible {\n outline: var(--focus-ring-width) solid var(--focus-ring-color);\n outline-offset: var(--focus-ring-offset);\n}\n\n._split_a8mxc_164 {\n box-sizing: border-box;\n display: inline-flex;\n flex: none;\n width: var(--size-6);\n height: var(--size-6);\n overflow: hidden;\n border: var(--border-width-default) solid var(--color-border-strong);\n border-radius: var(--radius-pill);\n}\n\n._split_a8mxc_164 > span {\n flex: 1 1 0;\n}\n\n/* Under 1.1:1 the two halves look alike: say so, so a near-white change reads as intended. */\n._subtle_a8mxc_180 {\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n white-space: nowrap;\n}\n\n._more_a8mxc_187 {\n white-space: nowrap;\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n font-variant-numeric: tabular-nums;\n}\n\n._noteRow_a8mxc_194 {\n grid-area: note;\n min-width: 0;\n padding-block-end: var(--space-1);\n}\n\n._note_a8mxc_194 {\n margin: 0;\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n._noteRow_a8mxc_194 ._note_a8mxc_194 {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0 var(--space-2);\n padding-inline-start: var(--space-2);\n color: var(--color-text-default);\n}\n\n._noteAction_a8mxc_216 {\n flex: none;\n}\n\n._sheet_a8mxc_220 {\n width: min(90vw, var(--size-80));\n}\n\n._list_a8mxc_224 {\n display: grid;\n max-height: var(--size-60);\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n}\n\n._item_a8mxc_233 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--control-height-md);\n}\n\n._screenLink_a8mxc_241,\n._here_a8mxc_242 {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1-5);\n min-height: var(--control-height-md);\n}\n\n._here_a8mxc_242 {\n font-weight: var(--font-weight-semibold);\n}\n\n._meta_a8mxc_253 {\n flex: none;\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n/* Changed here: one focusable row per surface. Line 1 its role, line 2 its tokens (muted, 12). Nothing truncates. */\n._rows_a8mxc_261 {\n display: grid;\n max-height: var(--size-60);\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n}\n\n._row_a8mxc_261 {\n height: auto;\n min-height: var(--control-height-md);\n padding-block: var(--space-1);\n justify-content: flex-start;\n text-align: start;\n}\n\n._rowText_a8mxc_278 {\n display: grid;\n min-width: 0;\n font-weight: var(--font-weight-regular);\n white-space: normal;\n}\n\n._rowName_a8mxc_285 {\n color: var(--color-text-default);\n font-size: var(--typography-ui-size);\n line-height: var(--typography-ui-line-height);\n}\n\n._rowMeta_a8mxc_291 {\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n._tipText_a8mxc_297 {\n display: grid;\n}\n\n._tipStep_a8mxc_301 {\n opacity: 0.8;\n}\n\n._sheetFoot_a8mxc_305 {\n margin-top: var(--space-2);\n}\n\n._sheetSection_a8mxc_309 {\n margin-top: var(--space-2);\n padding-top: var(--space-2);\n border-top: var(--border-width-default) solid var(--color-border-default);\n}\n\n._sheetSection_a8mxc_309:first-child {\n margin-top: 0;\n padding-top: 0;\n border-top: 0;\n}\n\n._sectionTitle_a8mxc_321 {\n margin: 0;\n font-weight: var(--font-weight-semibold);\n}\n\n/* A separate notice, not part of a list. */\n._notice_a8mxc_327 {\n display: flex;\n align-items: flex-start;\n gap: var(--space-1-5);\n margin: var(--space-2) 0 0;\n padding-top: var(--space-2);\n border-top: var(--border-width-default) solid var(--color-border-default);\n color: var(--color-text-muted);\n font-size: var(--typography-caption-size);\n line-height: var(--typography-caption-line-height);\n}\n\n/* In the sheet on phones only: the token pairs and the way back. */\n._sheetPhone_a8mxc_340 {\n display: none;\n}\n\n._back_a8mxc_344 {\n display: inline-flex;\n align-items: center;\n min-height: var(--control-height-md);\n}\n\n._pill_a8mxc_31 {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto auto;\n align-items: center;\n gap: var(--space-2);\n max-width: min(100%, var(--size-120));\n padding: var(--space-1) var(--space-1) var(--space-1) var(--space-4);\n border-radius: var(--radius-pill);\n}\n\n/* With a note under it, the pill becomes a small card. */\n._pill_a8mxc_31[data-note] {\n border-radius: var(--radius-overlay);\n}\n\n._pill_a8mxc_31 ._noteRow_a8mxc_194 {\n grid-column: 1 / -1;\n padding-inline-end: var(--space-3);\n}\n\n._pill_a8mxc_31 ._noteRow_a8mxc_194 ._note_a8mxc_194 {\n padding-inline-start: 0;\n}\n\n/* Show what changed: a dashed Deep Harbor frame (Bridge's tool colour, not the product's) on each changed surface,\n with a faint Deep Harbor tint and a role chip. Fixed layer: no pointer events, no focus, no layout. */\n._overlay_a8mxc_376 {\n position: fixed;\n inset: 0;\n z-index: var(--layer-sticky);\n pointer-events: none;\n}\n\n._box_a8mxc_383 {\n position: absolute;\n box-sizing: border-box;\n outline: var(--border-width-strong) dashed var(--color-action-primary-bg);\n outline-offset: var(--border-width-strong);\n}\n\n/* A page-sized surface: an inset frame, so it reads as a selection, not as the window edge. */\n._box_a8mxc_383[data-page] {\n outline-offset: 0;\n border-radius: var(--radius-container);\n}\n\n/* No tint on the page frame: it would tint the very colour being compared. */\n._box_a8mxc_383[data-page] ._tint_a8mxc_397 {\n display: none;\n}\n\n/* No room above (top of the viewport): under the surface instead. */\n/* No room above (top of the viewport): inside the surface's top-left corner instead. */\n._box_a8mxc_383[data-inside] ._chip_a8mxc_403 {\n top: 0;\n bottom: auto;\n left: 0;\n}\n\n/* The surface a list row points at: solid frame, stronger tint. */\n._box_a8mxc_383[data-emphasis] {\n outline-style: solid;\n}\n\n._box_a8mxc_383[data-emphasis] ._tint_a8mxc_397 {\n opacity: 0.1;\n}\n\n._box_a8mxc_383[data-page] ._chip_a8mxc_403 {\n top: var(--space-1);\n bottom: auto;\n left: var(--space-1);\n}\n\n._tint_a8mxc_397 {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-color: var(--color-action-primary-bg);\n opacity: 0.04;\n}\n\n/* Above the surface's top-left corner, so it never hides the surface's own content. */\n/* Hidden by default: shown on hover, from its list row, and briefly when outlines turn on. */\n._chip_a8mxc_403 {\n position: absolute;\n visibility: hidden;\n bottom: calc(100% + var(--border-width-strong) * 2);\n left: calc(var(--border-width-strong) * -2);\n max-width: var(--size-60);\n overflow: hidden;\n padding: 0 var(--space-1-5);\n border-radius: var(--radius-inset);\n background-color: var(--color-action-primary-bg);\n color: var(--color-action-primary-text);\n font-family: var(--typography-ui-family);\n font-size: var(--typography-caption-size);\n font-weight: var(--font-weight-medium);\n line-height: var(--typography-caption-line-height);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n._chip_a8mxc_403[data-shown] {\n visibility: visible;\n}\n\n/* Isolate: the scrim of a dialog over the rest of the page, with a cut-out around each changed surface. */\n._scrim_a8mxc_458 {\n position: absolute;\n inset: 0;\n display: block;\n animation: _scrim-in_a8mxc_1 var(--motion-duration-moderate) var(--motion-easing-enter);\n}\n\n._scrimFill_a8mxc_465 {\n fill: var(--color-overlay-scrim);\n}\n\n@keyframes _scrim-in_a8mxc_1 {\n from {\n opacity: 0;\n }\n}\n\n._tip_a8mxc_297 {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n@media (max-width: 760px) {\n ._anchor_a8mxc_5 {\n inset-inline: var(--space-2);\n bottom: var(--space-2);\n }\n\n /* Phone, open: docked to the bottom edge. Row 1: sides, Changes, collapse. Row 2, for a token change: the count,\n Previous and Next, Isolate. */\n ._anchor_a8mxc_5[data-open] {\n inset-inline: 0;\n bottom: 0;\n }\n\n ._panel_a8mxc_30 {\n grid-template-areas:\n \"sides actions collapse\"\n \"nav nav nav\"\n \"note note note\";\n grid-template-rows: calc(var(--size-11) - var(--border-width-default)) auto auto;\n grid-template-columns: minmax(0, 1fr) auto auto;\n column-gap: var(--space-2);\n width: 100%;\n padding: 0 var(--space-1);\n border-width: var(--border-width-default) 0 0;\n border-radius: 0;\n }\n\n ._title_a8mxc_81 {\n display: none;\n }\n\n ._grip_a8mxc_71,\n ._brand_a8mxc_90,\n ._studio_a8mxc_514 {\n display: none;\n }\n\n ._sides_a8mxc_119 {\n justify-self: start;\n }\n\n ._nav_a8mxc_124 {\n padding-block-end: var(--space-1);\n }\n\n ._noteRow_a8mxc_194 ._note_a8mxc_194 {\n padding-inline-start: 0;\n }\n\n ._pill_a8mxc_31 {\n grid-template-columns: minmax(0, 1fr) auto auto;\n }\n\n ._sheetPhone_a8mxc_340 {\n display: block;\n }\n}\n\n/* Below 480px the note's action takes its own line. */\n@media (max-width: 480px) {\n ._noteAction_a8mxc_216 {\n flex-basis: 100%;\n justify-content: flex-start;\n }\n}\n";
5
5
  document.head.appendChild(style);
6
6
  }
7
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
8
- import { useState, useEffect, useLayoutEffect, useMemo, useRef, useCallback } from "react";
9
- import { ThemeProvider, Tooltip, Button, ButtonGroup, IconButton, Popover, PopoverTrigger, PopoverContent, Checkbox, Icon, Link, Badge } from "@bridge-ds/react";
10
- import { GripVertical, ListChecks, ChevronUp, Check, Info, Minimize2, ScanSearch } from "lucide-react";
11
- import { g as githubReads, D as DEFAULT_PROXY, l as loadBuild, u as useDocumentScope } from "./index-3f0I3tAL.js";
12
- import { t as tokenChanges, c as changedScreens, b as changeMode, d as readableTitle, e as toggleIncluded, r as readChanges, w as whereAmI, f as readReturn, g as readUse, h as shouldRender, O as OPEN_KEY, i as readDock, l as liveTokensUrl, n as noVisibleDifference, j as readScroll, S as SCROLL_PARAM, k as sameScreenOn, m as studioChangesUrl, o as studioChangeUrl, T as TOGETHER_EMPTY_LINE, p as contrastRatio, q as TOGETHER_HINT, P as PARAM, u as isSubtle, v as toHex, x as fromText, y as isFlipKey, z as placeToolbar, A as togetherLabel, B as changeSummary, C as dockAt, D as stepDock, E as DOCK_KEY } from "./session-CzlIsFDY.js";
7
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
8
+ import { useState, useEffect, useId, useLayoutEffect, useMemo, useRef, useCallback } from "react";
9
+ import { ThemeProvider, Tooltip, Button, ButtonGroup, IconButton, VisuallyHidden, Kbd, Popover, PopoverTrigger, PopoverContent, Checkbox, Icon, Link, Badge } from "@bridge-ds/react";
10
+ import { ScanSearch, ChevronLeft, ChevronRight, GripVertical, ListChecks, ChevronUp, Check, Info, Minimize2 } from "lucide-react";
11
+ import { g as githubReads, D as DEFAULT_PROXY, l as loadBuild, u as useDocumentScope } from "./index-CCTqUFz3.js";
12
+ import { t as tokenChanges, c as changedScreens, b as changeMode, d as readableTitle, e as toggleIncluded, r as readChanges, w as whereAmI, f as readReturn, g as readUse, h as shouldRender, O as OPEN_KEY, i as readDock, l as liveTokensUrl, n as noVisibleDifference, j as readScroll, S as SCROLL_PARAM, k as sameScreenOn, m as studioChangesUrl, o as studioChangeUrl, T as TOGETHER_EMPTY_LINE, p as contrastRatio, q as toHex, u as fromText, v as TOGETHER_HINT, x as isSubtle, y as isFlipKey, z as placeToolbar, A as togetherLabel, P as PARAM, B as changeSummary, C as dockAt, D as stepDock, E as DOCK_KEY } from "./session-D6oH78KG.js";
13
13
  const VISUAL_BRANCH = "bridge-visual";
14
14
  const cacheKey = (n) => `bridge-admin:facts:v3:${n}`;
15
15
  function session$1() {
@@ -232,9 +232,6 @@ function surfaceLine(tokenNames, surfaces) {
232
232
  const tokens = `${names.length} ${names.length === 1 ? "token" : "tokens"} changed: ${names.slice(0, 3).join(", ")}${names.length > 3 ? ` and ${names.length - 3} more` : ""}`;
233
233
  return `${tokens}, on ${surfaces} ${surfaces === 1 ? "surface" : "surfaces"}`;
234
234
  }
235
- function outOfView(n) {
236
- return n === 1 ? "Nothing changed in view. 1 surface changes further down: scroll to see it." : `Nothing changed in view. ${n} surfaces change further down: scroll to see them.`;
237
- }
238
235
  const EMPTY_LINE = "This change doesn't touch this screen. Open Screens to see where it does.";
239
236
  const LANDMARKS = { main: "Content", header: "Header", nav: "Navigation", aside: "Sidebar", footer: "Footer", form: "Form", dialog: "Dialog" };
240
237
  const ROLES = { main: "Content", banner: "Header", navigation: "Navigation", complementary: "Sidebar", contentinfo: "Footer", dialog: "Dialog", toolbar: "Toolbar", tablist: "Tabs", table: "Table", grid: "Table", menu: "Menu", listbox: "List" };
@@ -315,6 +312,13 @@ function shownRect(el) {
315
312
  return w > 0 && h > 0 ? r : null;
316
313
  }
317
314
  const visible = (el) => el.getClientRects().length > 0;
315
+ function rendered(el) {
316
+ const check = el.checkVisibility;
317
+ if (check && !check.call(el, { opacityProperty: true, visibilityProperty: true })) return false;
318
+ const r = el.getBoundingClientRect();
319
+ return r.width > 0 && r.height > 0;
320
+ }
321
+ const isPage = (el) => el === document.documentElement || el === document.body;
318
322
  function changedElements(changedVars, sheet2, ignore, sheetIs = "before") {
319
323
  const live = sheet2;
320
324
  const t0 = performance.now();
@@ -420,6 +424,43 @@ function changedElements(changedVars, sheet2, ignore, sheetIs = "before") {
420
424
  const surfaces = outermost([...plain, ...charts.values()], (a, b) => a.el !== b.el && a.el.contains(b.el));
421
425
  return { elements, surfaces, ms: Math.round((performance.now() - t0) * 10) / 10 };
422
426
  }
427
+ const SAME_LINE = 8;
428
+ function readingOrder(places) {
429
+ return places.map((p, i) => ({ p, i })).sort((a, b) => (Math.abs(a.p.top - b.p.top) <= SAME_LINE ? a.p.left - b.p.left : a.p.top - b.p.top) || a.i - b.i).map((x) => x.i);
430
+ }
431
+ function stepTo(current, delta, count) {
432
+ if (count <= 0) return null;
433
+ if (current === null || current < 0 || current >= count) return delta === 1 ? 0 : count - 1;
434
+ return (current + delta + count) % count;
435
+ }
436
+ const changeCount = (n) => `${n} changed`;
437
+ const positionLabel = (position, n) => `${position + 1} / ${n} changed`;
438
+ const stepAnnouncement = (position, n, label) => `Changed element ${position + 1} of ${n}: ${label}`;
439
+ function elsewhereLine(screens) {
440
+ if (!screens.length) return "This change doesn't touch this screen.";
441
+ const names = screens.length <= 2 ? screens.join(" and ") : `${screens.slice(0, 2).join(", ")} and ${screens.length - 2} more`;
442
+ return `This change doesn't touch this screen. It shows on ${names}.`;
443
+ }
444
+ function isTyping(target) {
445
+ const t = target;
446
+ if (!t) return false;
447
+ if (t.isContentEditable) return true;
448
+ const tag = (t.tagName ?? "").toLowerCase();
449
+ if (tag === "input" || tag === "textarea" || tag === "select") return true;
450
+ return Boolean(t.closest && t.closest('[role="combobox"], [role="textbox"], [role="searchbox"]'));
451
+ }
452
+ function isEscape(e) {
453
+ return e.key === "Escape" && !e.altKey && !e.ctrlKey && !e.metaKey && !isTyping(e.target);
454
+ }
455
+ const TIP_ROOM = { width: 300, height: 64 };
456
+ function tipSide(box2, view, bar, room = TIP_ROOM) {
457
+ const floor = bar ? Math.min(view.height, bar.top) : view.height;
458
+ if (floor - box2.bottom >= room.height) return "bottom";
459
+ const fitsBeside = box2.top >= 0 && box2.top + room.height <= floor;
460
+ if (fitsBeside && view.width - box2.right >= room.width) return "right";
461
+ if (fitsBeside && box2.left >= room.width) return "left";
462
+ return "top";
463
+ }
423
464
  const IGNORE = "[data-bridge-toolbar], [data-bridge-overlay]";
424
465
  function useChangedElements(on, live, vars, screen, sheetIs = "before") {
425
466
  const [result, setResult] = useState(null);
@@ -490,52 +531,52 @@ function usePinnedBridgeTokens(url, theme) {
490
531
  };
491
532
  }, [url, theme]);
492
533
  }
493
- const anchor = "_anchor_nhlur_5";
494
- const panel = "_panel_nhlur_30";
495
- const pill = "_pill_nhlur_31";
496
- const grip = "_grip_nhlur_63";
497
- const title = "_title_nhlur_73";
498
- const brand = "_brand_nhlur_82";
499
- const name = "_name_nhlur_90";
500
- const pillTitle = "_pillTitle_nhlur_95";
501
- const actions = "_actions_nhlur_102";
502
- const sides = "_sides_nhlur_111";
503
- const collapse = "_collapse_nhlur_115";
504
- const phoneOnly = "_phoneOnly_nhlur_119";
505
- const desktopOnly = "_desktopOnly_nhlur_123";
506
- const count = "_count_nhlur_127";
507
- const swatches = "_swatches_nhlur_134";
508
- const split = "_split_nhlur_146";
509
- const subtle = "_subtle_nhlur_162";
510
- const more = "_more_nhlur_169";
511
- const noteRow = "_noteRow_nhlur_176";
512
- const note = "_note_nhlur_176";
513
- const noteAction = "_noteAction_nhlur_198";
514
- const sheet = "_sheet_nhlur_202";
515
- const list = "_list_nhlur_206";
516
- const item = "_item_nhlur_215";
517
- const screenLink = "_screenLink_nhlur_223";
518
- const here = "_here_nhlur_224";
519
- const meta = "_meta_nhlur_235";
520
- const rows = "_rows_nhlur_243";
521
- const row = "_row_nhlur_243";
522
- const rowText = "_rowText_nhlur_260";
523
- const rowName = "_rowName_nhlur_267";
524
- const rowMeta = "_rowMeta_nhlur_273";
525
- const tipText = "_tipText_nhlur_279";
526
- const tipStep = "_tipStep_nhlur_283";
527
- const sheetFoot = "_sheetFoot_nhlur_287";
528
- const sheetSection = "_sheetSection_nhlur_291";
529
- const sectionTitle = "_sectionTitle_nhlur_303";
530
- const notice = "_notice_nhlur_309";
531
- const sheetPhone = "_sheetPhone_nhlur_322";
532
- const back = "_back_nhlur_326";
533
- const overlay = "_overlay_nhlur_358";
534
- const box = "_box_nhlur_365";
535
- const tint = "_tint_nhlur_379";
536
- const chip = "_chip_nhlur_385";
537
- const tip = "_tip_nhlur_279";
538
- const studio = "_studio_nhlur_481";
534
+ const anchor = "_anchor_a8mxc_5";
535
+ const panel = "_panel_a8mxc_30";
536
+ const pill = "_pill_a8mxc_31";
537
+ const grip = "_grip_a8mxc_71";
538
+ const title = "_title_a8mxc_81";
539
+ const brand = "_brand_a8mxc_90";
540
+ const name = "_name_a8mxc_98";
541
+ const pillTitle = "_pillTitle_a8mxc_103";
542
+ const actions = "_actions_a8mxc_110";
543
+ const sides = "_sides_a8mxc_119";
544
+ const nav = "_nav_a8mxc_124";
545
+ const countButton = "_countButton_a8mxc_132";
546
+ const steps = "_steps_a8mxc_137";
547
+ const collapse = "_collapse_a8mxc_141";
548
+ const split = "_split_a8mxc_164";
549
+ const subtle = "_subtle_a8mxc_180";
550
+ const noteRow = "_noteRow_a8mxc_194";
551
+ const note = "_note_a8mxc_194";
552
+ const noteAction = "_noteAction_a8mxc_216";
553
+ const sheet = "_sheet_a8mxc_220";
554
+ const list = "_list_a8mxc_224";
555
+ const item = "_item_a8mxc_233";
556
+ const screenLink = "_screenLink_a8mxc_241";
557
+ const here = "_here_a8mxc_242";
558
+ const meta = "_meta_a8mxc_253";
559
+ const rows = "_rows_a8mxc_261";
560
+ const row = "_row_a8mxc_261";
561
+ const rowText = "_rowText_a8mxc_278";
562
+ const rowName = "_rowName_a8mxc_285";
563
+ const rowMeta = "_rowMeta_a8mxc_291";
564
+ const tipText = "_tipText_a8mxc_297";
565
+ const tipStep = "_tipStep_a8mxc_301";
566
+ const sheetFoot = "_sheetFoot_a8mxc_305";
567
+ const sheetSection = "_sheetSection_a8mxc_309";
568
+ const sectionTitle = "_sectionTitle_a8mxc_321";
569
+ const notice = "_notice_a8mxc_327";
570
+ const sheetPhone = "_sheetPhone_a8mxc_340";
571
+ const back = "_back_a8mxc_344";
572
+ const overlay = "_overlay_a8mxc_376";
573
+ const box = "_box_a8mxc_383";
574
+ const tint = "_tint_a8mxc_397";
575
+ const chip = "_chip_a8mxc_403";
576
+ const scrim = "_scrim_a8mxc_458";
577
+ const scrimFill = "_scrimFill_a8mxc_465";
578
+ const tip = "_tip_a8mxc_297";
579
+ const studio = "_studio_a8mxc_514";
539
580
  const styles = {
540
581
  anchor,
541
582
  panel,
@@ -547,14 +588,12 @@ const styles = {
547
588
  pillTitle,
548
589
  actions,
549
590
  sides,
591
+ nav,
592
+ countButton,
593
+ steps,
550
594
  collapse,
551
- phoneOnly,
552
- desktopOnly,
553
- count,
554
- swatches,
555
595
  split,
556
596
  subtle,
557
- more,
558
597
  noteRow,
559
598
  note,
560
599
  noteAction,
@@ -581,10 +620,13 @@ const styles = {
581
620
  box,
582
621
  tint,
583
622
  chip,
623
+ scrim,
624
+ scrimFill,
584
625
  tip,
585
626
  studio
586
627
  };
587
628
  const INSET = 8;
629
+ const HOLE = 4;
588
630
  function boxOf(el) {
589
631
  const r = shownRect(el);
590
632
  if (!r) return null;
@@ -604,10 +646,13 @@ function ChangeOutlines({
604
646
  tip: tip2,
605
647
  onShown,
606
648
  emphasis,
607
- flash
649
+ flash,
650
+ isolate = false,
651
+ bar
608
652
  }) {
609
653
  const [tick, setTick] = useState(0);
610
654
  const [active, setActive] = useState(null);
655
+ const maskId = `bridge-isolate-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
611
656
  useEffect(() => {
612
657
  let frame = 0;
613
658
  const on = () => {
@@ -658,30 +703,61 @@ function ChangeOutlines({
658
703
  document.removeEventListener("focusin", focus);
659
704
  };
660
705
  }, [surfaces]);
661
- return /* @__PURE__ */ jsx(ThemeProvider, { theme, brand: "bridge", density: "compact", className: styles.overlay, "data-bridge-overlay": "", ...{ [PIN_ATTR]: "" }, "aria-hidden": "true", children: boxes.map((b, i) => {
662
- if (!b) return null;
663
- const s = surfaces[i];
664
- const showChip = flash || active === i || emphasis === i;
665
- const chip2 = /* @__PURE__ */ jsx("span", { className: styles.chip, "data-page": b.page || void 0, "data-shown": showChip || void 0, children: s.label });
666
- return /* @__PURE__ */ jsxs(
667
- "span",
668
- {
669
- className: styles.box,
670
- "data-page": b.page || void 0,
671
- "data-inside": !b.page && b.top < 24 || void 0,
672
- "data-emphasis": emphasis === i || void 0,
673
- style: { left: b.left, top: b.top, width: b.width, height: b.height, borderRadius: b.radius },
674
- children: [
675
- /* @__PURE__ */ jsx("span", { className: styles.tint }),
676
- active === i || emphasis === i ? (
677
- // Above the chip when there is room, else below it: never over the toolbar, which keeps clear of boxes.
678
- /* @__PURE__ */ jsx(Tooltip, { open: true, content: tip2(s), side: b.top < 64 ? "bottom" : "top", align: "start", className: PIN_CLASS, children: chip2 })
679
- ) : chip2
680
- ]
681
- },
682
- i
683
- );
684
- }) });
706
+ return /* @__PURE__ */ jsxs(ThemeProvider, { theme, brand: "bridge", density: "compact", className: styles.overlay, "data-bridge-overlay": "", "data-isolate": isolate || void 0, ...{ [PIN_ATTR]: "" }, "aria-hidden": "true", children: [
707
+ isolate ? /* @__PURE__ */ jsxs("svg", { className: styles.scrim, width: "100%", height: "100%", focusable: "false", children: [
708
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("mask", { id: maskId, children: [
709
+ /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: "white" }),
710
+ boxes.map(
711
+ (b, i) => b && !b.page ? /* @__PURE__ */ jsx("rect", { x: b.left - HOLE, y: b.top - HOLE, width: b.width + 2 * HOLE, height: b.height + 2 * HOLE, rx: (parseFloat(b.radius) || 0) + HOLE, fill: "black" }, i) : null
712
+ )
713
+ ] }) }),
714
+ /* @__PURE__ */ jsx("rect", { className: styles.scrimFill, width: "100%", height: "100%", mask: `url(#${maskId})` })
715
+ ] }) : null,
716
+ boxes.map((b, i) => {
717
+ if (!b) return null;
718
+ const s = surfaces[i];
719
+ const showChip = flash || active === i || emphasis === i;
720
+ const chip2 = /* @__PURE__ */ jsx("span", { className: styles.chip, "data-page": b.page || void 0, "data-shown": showChip || void 0, children: s.label });
721
+ return /* @__PURE__ */ jsxs(
722
+ "span",
723
+ {
724
+ className: styles.box,
725
+ "data-page": b.page || void 0,
726
+ "data-inside": !b.page && b.top < 24 || void 0,
727
+ "data-emphasis": emphasis === i || void 0,
728
+ style: { left: b.left, top: b.top, width: b.width, height: b.height, borderRadius: b.radius },
729
+ children: [
730
+ (active === i || emphasis === i) && !b.page ? /* @__PURE__ */ jsx(
731
+ Tooltip,
732
+ {
733
+ open: true,
734
+ content: tip2(s),
735
+ side: tipSide({ left: b.left, top: b.top, right: b.left + b.width, bottom: b.top + b.height }, { width: window.innerWidth, height: window.innerHeight }, bar?.() ?? null),
736
+ align: "start",
737
+ className: PIN_CLASS,
738
+ children: /* @__PURE__ */ jsx("span", { className: styles.tint })
739
+ }
740
+ ) : /* @__PURE__ */ jsx("span", { className: styles.tint }),
741
+ (active === i || emphasis === i) && b.page ? /* @__PURE__ */ jsx(Tooltip, { open: true, content: tip2(s), side: "bottom", align: "start", className: PIN_CLASS, children: chip2 }) : chip2
742
+ ]
743
+ },
744
+ i
745
+ );
746
+ })
747
+ ] });
748
+ }
749
+ function ChangeNav({ countText, tip: tip2, outlinesOn, disabled, total, isolate, announce, onToggle, onStep, onIsolate }) {
750
+ return /* @__PURE__ */ jsxs("div", { className: styles.nav, role: "group", "aria-label": "What changed on this screen", children: [
751
+ /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: tip2, children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "md", iconStart: ScanSearch, pressed: outlinesOn, "aria-keyshortcuts": "C", disabled, onClick: onToggle, className: styles.countButton, children: countText }) }),
752
+ total ? /* @__PURE__ */ jsxs(Fragment, { children: [
753
+ /* @__PURE__ */ jsxs(ButtonGroup, { appearance: "attached", "aria-label": "Step through the changed elements", className: styles.steps, children: [
754
+ /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: "Previous changed element", children: /* @__PURE__ */ jsx(IconButton, { icon: ChevronLeft, variant: "secondary", size: "md", label: "Previous changed element", onClick: () => onStep(-1) }) }),
755
+ /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: "Next changed element", children: /* @__PURE__ */ jsx(IconButton, { icon: ChevronRight, variant: "secondary", size: "md", label: "Next changed element", onClick: () => onStep(1) }) })
756
+ ] }),
757
+ /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: isolate ? "Show the whole page again. Press Esc." : "Dim everything but the changed elements. Esc turns it off.", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "md", pressed: isolate, "aria-keyshortcuts": isolate ? "Escape" : void 0, onClick: () => onIsolate(!isolate), children: "Isolate" }) })
758
+ ] }) : null,
759
+ /* @__PURE__ */ jsx(VisuallyHidden, { role: "status", children: announce })
760
+ ] });
685
761
  }
686
762
  function useSheet(css, applied) {
687
763
  const [el, setEl] = useState(null);
@@ -753,7 +829,6 @@ function useTogether(build, latest, changes, use, here2, applied) {
753
829
  };
754
830
  }
755
831
  const SIDE_LABEL = { before: "Live product", after: "This change" };
756
- const MAX_PAIRS = 3;
757
832
  function session() {
758
833
  try {
759
834
  return window.sessionStorage;
@@ -966,19 +1041,21 @@ function Toolbar({
966
1041
  };
967
1042
  }, [build, change, tg]);
968
1043
  const liveUrl = !tg && facts?.mode === "tokens" ? liveTokensUrl(build) : null;
969
- const [outlines, setOutlines] = useState(false);
1044
+ const [outlinePick, setOutlinePick] = useState(null);
1045
+ const outlines = outlinePick ?? open;
1046
+ const toggleOutlines = useCallback(() => setOutlinePick((p) => !(p ?? open)), [open]);
970
1047
  const canOutline = facts?.mode === "tokens" && (facts.tokens.length ?? 0) > 0;
971
1048
  const live = useLiveSheet(liveUrl, outlines && canOutline, side === "before" && facts?.mode === "tokens");
972
1049
  const onePairs = usePairs(tg ? null : facts, liveUrl, brand2, side === "before");
973
1050
  const pairs = tg ? T?.pairs ?? [] : onePairs;
974
1051
  const noDiff = tg ? T?.noDiff ?? null : facts?.mode === "tokens" ? noVisibleDifference(facts.files, { theme, brand: brand2 }) : null;
975
1052
  const outlinesOn = outlines && canOutline && !noDiff;
1053
+ const screenKey = `${hash}|${theme}|${tenantId}|${tg ? T?.included.join(",") ?? "" : ""}`;
976
1054
  const diff = useChangedElements(
977
1055
  outlinesOn,
978
1056
  tg ? T?.sheet ?? null : live.link,
979
1057
  (facts?.tokens ?? []).map((t) => t.cssVar),
980
- // Switching a change on or off repaints the combination: the outlines are measured again.
981
- `${hash}|${theme}|${tenantId}|${tg ? T?.included.join(",") ?? "" : ""}`,
1058
+ screenKey,
982
1059
  tg ? "after" : "before"
983
1060
  );
984
1061
  const nameOf = (v) => facts?.tokens.find((t) => t.cssVar === v)?.name ?? v;
@@ -989,6 +1066,9 @@ function Toolbar({
989
1066
  const [emphasis, setEmphasis] = useState(null);
990
1067
  const [flash, setFlash] = useState(false);
991
1068
  const [sheetOpen, setSheetOpen] = useState(false);
1069
+ const [position, setPosition] = useState(null);
1070
+ const [announce, setAnnounce] = useState("");
1071
+ const [isolate, setIsolate] = useState(false);
992
1072
  const phone = useMedia("(max-width: 760px)");
993
1073
  const reduced = useMedia("(prefers-reduced-motion: reduce)");
994
1074
  usePinnedBridgeTokens(liveTokensUrl(build), theme);
@@ -1052,7 +1132,7 @@ function Toolbar({
1052
1132
  const onKey = (e) => {
1053
1133
  if (canOutline && !noDiff && isKey(e, "c")) {
1054
1134
  e.preventDefault();
1055
- setOutlines((o) => !o);
1135
+ toggleOutlines();
1056
1136
  return;
1057
1137
  }
1058
1138
  if (!isFlipKey(e)) return;
@@ -1061,7 +1141,15 @@ function Toolbar({
1061
1141
  };
1062
1142
  window.addEventListener("keydown", onKey);
1063
1143
  return () => window.removeEventListener("keydown", onKey);
1064
- }, [choose, side, canOutline, noDiff]);
1144
+ }, [choose, side, canOutline, noDiff, toggleOutlines]);
1145
+ useEffect(() => {
1146
+ if (!isolate) return;
1147
+ const onEscape = (e) => {
1148
+ if (isEscape(e)) setIsolate(false);
1149
+ };
1150
+ window.addEventListener("keydown", onEscape, true);
1151
+ return () => window.removeEventListener("keydown", onEscape, true);
1152
+ }, [isolate]);
1065
1153
  useLayoutEffect(() => {
1066
1154
  const el = root.current;
1067
1155
  const anchor2 = el?.parentElement;
@@ -1148,8 +1236,39 @@ function Toolbar({
1148
1236
  const behind = facts?.behind ? "Live has new changes since this change started." : null;
1149
1237
  const shared = screens?.length && screens.every((s) => s.tenant === screens[0].tenant && s.theme === screens[0].theme) ? screens[0] : null;
1150
1238
  const shopOf = (t) => shops.find((x) => x.id === t)?.name ?? t;
1151
- const surfaces = outlinesOn ? diff?.surfaces ?? [] : [];
1239
+ const surfaces = useMemo(() => outlinesOn ? diff?.surfaces ?? [] : [], [outlinesOn, diff]);
1152
1240
  const shownCount = outlinesOn && diff ? shown.count : null;
1241
+ const order = useMemo(() => {
1242
+ const on = surfaces.map((s, i) => ({ s, i })).filter(({ s }) => rendered(s.el));
1243
+ const places = on.map(({ s }) => {
1244
+ if (isPage(s.el)) return { top: -1, left: 0 };
1245
+ const r = s.el.getBoundingClientRect();
1246
+ return { top: r.top + window.scrollY, left: r.left + window.scrollX };
1247
+ });
1248
+ return readingOrder(places).map((k) => on[k].i);
1249
+ }, [surfaces]);
1250
+ const total = outlinesOn && diff ? order.length : null;
1251
+ const current = position !== null ? order[position] ?? null : null;
1252
+ useEffect(() => {
1253
+ setPosition(null);
1254
+ setAnnounce("");
1255
+ }, [screenKey, outlinesOn]);
1256
+ useEffect(() => {
1257
+ if (position !== null && position >= order.length) setPosition(null);
1258
+ }, [order.length, position]);
1259
+ const isolateOn = isolate && Boolean(total);
1260
+ const step = (delta) => {
1261
+ const next = stepTo(position, delta, order.length);
1262
+ if (next === null) return;
1263
+ const s = surfaces[order[next]];
1264
+ setPosition(next);
1265
+ setEmphasis(null);
1266
+ if (!isPage(s.el)) s.el.scrollIntoView({ block: "center", inline: "nearest", behavior: reduced ? "auto" : "smooth" });
1267
+ setAnnounce(stepAnnouncement(next, order.length, s.label));
1268
+ };
1269
+ const isHere = (sc) => sc.route === hash && sc.tenant === tenantId && sc.theme === theme;
1270
+ const elsewhere = (screens ?? []).filter((sc) => !isHere(sc));
1271
+ const screenHref = (sc) => `?${PARAM}=${change}&tenant=${encodeURIComponent(sc.tenant)}&theme=${encodeURIComponent(sc.theme)}#${sc.route}`;
1153
1272
  const activeHere = new Set((T?.pairs ?? []).flatMap((p) => p.token.from)).size;
1154
1273
  const note2 = shownIn ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
1155
1274
  "Shown in ",
@@ -1162,7 +1281,17 @@ function Toolbar({
1162
1281
  ] }) : noDiff ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
1163
1282
  /* @__PURE__ */ jsx("span", { children: noDifferenceText(noDiff, shops) }),
1164
1283
  /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "md", onClick: fixNoDiff, className: styles.noteAction, children: noDiff.kind === "theme" ? `Switch to ${noDiff.touched}` : `Switch to ${brandName(shops, noDiff.touched)}` })
1165
- ] }) : (outlinesOn || side === "before") && live.state === "error" ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: "Could not load the live product. Check your connection, then try again." }) : shownCount === 0 ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: diff?.surfaces.length ? outOfView(diff.surfaces.length) : tg ? TOGETHER_EMPTY_LINE : EMPTY_LINE }) : tg && T && side === "after" && activeHere < T.included.length ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
1284
+ ] }) : (outlinesOn || side === "before") && live.state === "error" ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: "Could not load the live product. Check your connection, then try again." }) : total === 0 ? tg ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: TOGETHER_EMPTY_LINE }) : elsewhere.length ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
1285
+ /* @__PURE__ */ jsx("span", { children: elsewhereLine(elsewhere.map((sc) => sc.label)) }),
1286
+ /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "md", render: /* @__PURE__ */ jsx("a", { href: screenHref(elsewhere[0]) }), onClick: goTo(elsewhere[0]), className: styles.noteAction, children: [
1287
+ "Go to ",
1288
+ elsewhere[0].label
1289
+ ] })
1290
+ ] }) : /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: screens ? elsewhereLine([]) : EMPTY_LINE }) : total && shownCount === 0 && position === null ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
1291
+ "Nothing changed in view. Next takes you to ",
1292
+ total === 1 ? "the changed element" : `the ${total} changed elements`,
1293
+ "."
1294
+ ] }) : tg && T && side === "after" && activeHere < T.included.length ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
1166
1295
  activeHere,
1167
1296
  " of these ",
1168
1297
  T.included.length,
@@ -1178,62 +1307,67 @@ function Toolbar({
1178
1307
  const from = p?.token?.from;
1179
1308
  return tg && from?.length ? fromText(from, titleOf) : null;
1180
1309
  };
1181
- const pairTip = (p) => `${p.token.name}${p.token.step ? ` (${p.token.step})` : ""}${fromOf(p) ? `, ${fromOf(p)}` : ""}: ${p.color ? hexPair(p.before, p.after) : `${p.before} → ${p.after}`}`;
1182
1310
  const splitOf = (before, after) => /* @__PURE__ */ jsxs("span", { className: styles.split, "aria-hidden": "true", children: [
1183
1311
  /* @__PURE__ */ jsx("span", { style: { backgroundColor: before } }),
1184
1312
  /* @__PURE__ */ jsx("span", { style: { backgroundColor: after } })
1185
1313
  ] });
1186
1314
  const subtleOf = (before, after) => isSubtle(before, after) ? /* @__PURE__ */ jsx("span", { className: styles.subtle, children: "Subtle change" }) : null;
1187
- const shownPairs = visiblePairs.filter((p) => p.color).slice(0, MAX_PAIRS);
1188
1315
  const roleGroups = [...visiblePairs.reduce((m, p) => m.set(p.token.name, [...m.get(p.token.name) ?? [], p]), /* @__PURE__ */ new Map())].map(([name2, list2]) => ({ name: name2, pairs: list2 }));
1189
- const swatches2 = visiblePairs.length ? /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: visiblePairs.slice(0, 6).map(pairTip).join(". ") + (visiblePairs.length > 6 ? `. And ${visiblePairs.length - 6} more.` : ""), children: /* @__PURE__ */ jsxs("span", { className: styles.swatches, tabIndex: 0, "aria-label": `Tokens this change edits: ${visiblePairs.map(pairTip).join(". ")}`, children: [
1190
- shownPairs.map((p) => /* @__PURE__ */ jsx("span", { children: splitOf(p.before, p.after) }, p.token.path)),
1191
- visiblePairs.length > shownPairs.length && /* @__PURE__ */ jsxs("span", { className: styles.more, children: [
1192
- "+",
1193
- visiblePairs.length - shownPairs.length,
1194
- " more ",
1195
- visiblePairs.length - shownPairs.length === 1 ? "token" : "tokens"
1196
- ] }),
1197
- shownPairs[0] ? subtleOf(shownPairs[0].before, shownPairs[0].after) : null
1198
- ] }) }) : null;
1199
1316
  const tokenNames = (facts?.tokens ?? []).map((t) => t.name);
1200
- const summary = shownCount === null ? null : surfaceLine(diff.surfaces.flatMap((s) => s.roots.map(nameOf)), shownCount);
1201
- const toggleTip = `${summary ?? `Outline what ${tokenNames.length === 1 ? tokenNames[0] : "this change"} changes on this screen.`} Press C.`;
1202
- const toggleLabel = shownCount === null ? "Show what changed" : `Show what changed · ${shownCount}`;
1203
- const outlineToggle = canOutline ? /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: toggleTip, children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "md", pressed: outlinesOn, "aria-keyshortcuts": "C", disabled: Boolean(noDiff), onClick: () => setOutlines((o) => !o), children: toggleLabel }) }) : null;
1204
- const outlineIcon = canOutline ? /* @__PURE__ */ jsx(
1205
- IconButton,
1317
+ const summary = shownCount === null ? null : surfaceLine(diff.surfaces.flatMap((s) => s.roots.map(nameOf)), total ?? shownCount);
1318
+ const countText = !outlinesOn ? "Show what changed" : total === null ? "Finding changes" : total === 0 ? "Nothing changed here" : position !== null ? positionLabel(position, total) : changeCount(total);
1319
+ const toggleTip = outlinesOn ? `${summary ? `${summary}. ` : ""}Press C to hide the outlines.` : `Outline what ${tokenNames.length === 1 ? tokenNames[0] : "this change"} changes on this screen. Press C.`;
1320
+ const nav2 = canOutline ? /* @__PURE__ */ jsx(
1321
+ ChangeNav,
1206
1322
  {
1207
- icon: ScanSearch,
1208
- size: "md",
1209
- variant: "ghost",
1210
- pressed: outlinesOn,
1323
+ countText,
1324
+ tip: toggleTip,
1325
+ outlinesOn,
1211
1326
  disabled: Boolean(noDiff),
1212
- label: shownCount === null ? "Show what changed" : `Show what changed, ${shownCount} ${shownCount === 1 ? "surface" : "surfaces"}`,
1213
- className: styles.phoneOnly,
1214
- onClick: () => setOutlines((o) => !o)
1327
+ total,
1328
+ isolate: isolateOn,
1329
+ announce,
1330
+ onToggle: toggleOutlines,
1331
+ onStep: step,
1332
+ onIsolate: setIsolate
1215
1333
  }
1216
1334
  ) : null;
1217
1335
  const shownSurfaces = surfaces.map((s, i) => ({ s, i })).filter(({ s }) => shownRect(s.el));
1218
1336
  const focusSurface = (i) => {
1219
1337
  const el = surfaces[i]?.el;
1220
1338
  if (!el) return;
1221
- el.scrollIntoView({ block: "center", behavior: reduced ? "auto" : "smooth" });
1339
+ if (!isPage(el)) el.scrollIntoView({ block: "center", behavior: reduced ? "auto" : "smooth" });
1222
1340
  setEmphasis(i);
1341
+ if (order.includes(i)) setPosition(order.indexOf(i));
1223
1342
  };
1224
1343
  const tokensOf = (x) => [...new Set(x.roots.map(nameOf))].join(", ");
1225
- const sides2 = /* @__PURE__ */ jsx(ButtonGroup, { appearance: "attached", "aria-label": "Compare", className: styles.sides, children: ["before", "after"].map((s) => /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: `${sideLabel(s)}: ${s === "before" ? "what customers see today." : modeDetail(facts)} Press B to flip.`, children: /* @__PURE__ */ jsx(
1226
- Button,
1344
+ const sides2 = /* @__PURE__ */ jsx(ButtonGroup, { appearance: "attached", "aria-label": "Compare", className: styles.sides, children: ["before", "after"].map((s) => /* @__PURE__ */ jsx(
1345
+ Tooltip,
1227
1346
  {
1228
- variant: "secondary",
1229
- size: "md",
1230
- pressed: side === s,
1231
- "aria-keyshortcuts": "B",
1232
- disabled: !canFlip && side !== s,
1233
- onClick: () => choose(s),
1234
- children: sideLabel(s)
1235
- }
1236
- ) }, s)) });
1347
+ className: PIN_CLASS,
1348
+ content: /* @__PURE__ */ jsxs(Fragment, { children: [
1349
+ sideLabel(s),
1350
+ ": ",
1351
+ s === "before" ? "what customers see today." : modeDetail(facts),
1352
+ " ",
1353
+ /* @__PURE__ */ jsx(Kbd, { keys: "B", size: "sm" }),
1354
+ " flips sides on the same screen."
1355
+ ] }),
1356
+ children: /* @__PURE__ */ jsx(
1357
+ Button,
1358
+ {
1359
+ variant: "secondary",
1360
+ size: "md",
1361
+ pressed: side === s,
1362
+ "aria-keyshortcuts": "B",
1363
+ disabled: !canFlip && side !== s,
1364
+ onClick: () => choose(s),
1365
+ children: sideLabel(s)
1366
+ }
1367
+ )
1368
+ },
1369
+ s
1370
+ )) });
1237
1371
  return /* @__PURE__ */ jsxs(
1238
1372
  ThemeProvider,
1239
1373
  {
@@ -1247,6 +1381,39 @@ function Toolbar({
1247
1381
  "data-dock": place.dock,
1248
1382
  style: place.lift ? { paddingBottom: `${place.lift}px` } : void 0,
1249
1383
  children: [
1384
+ outlinesOn && surfaces.length ? /* @__PURE__ */ jsx(
1385
+ ChangeOutlines,
1386
+ {
1387
+ surfaces,
1388
+ theme,
1389
+ emphasis: emphasis ?? current,
1390
+ flash,
1391
+ isolate: isolateOn,
1392
+ bar: () => root.current?.getBoundingClientRect() ?? null,
1393
+ onShown: setShownStable,
1394
+ tip: (s) => {
1395
+ const prop = s.props.find((p) => /^rgb/.test(p.before) && /^rgb/.test(p.after));
1396
+ const token = prop ? visiblePairs.find((p) => p.color && toHex(p.after) === toHex(prop.after) && toHex(p.before) === toHex(prop.before)) : null;
1397
+ const name2 = token?.token.name ?? [...new Set(s.roots.map(nameOf))].slice(0, 2).join(", ");
1398
+ const rootsFrom = [...new Set(s.roots.flatMap((r) => facts?.tokens.find((t) => t.cssVar === r)?.from ?? []))];
1399
+ const fromLine = fromOf(token) ?? (tg && rootsFrom.length ? fromText(rootsFrom, titleOf) : null);
1400
+ return /* @__PURE__ */ jsxs("span", { className: styles.tip, children: [
1401
+ prop ? splitOf(prop.before, prop.after) : null,
1402
+ /* @__PURE__ */ jsxs("span", { className: styles.tipText, children: [
1403
+ /* @__PURE__ */ jsxs("span", { children: [
1404
+ s.label,
1405
+ ": ",
1406
+ name2,
1407
+ prop ? `, ${hexPair(prop.before, prop.after)}` : ""
1408
+ ] }),
1409
+ token?.token.step ? /* @__PURE__ */ jsx("span", { className: styles.tipStep, children: token.token.step }) : null,
1410
+ fromLine ? /* @__PURE__ */ jsx("span", { className: styles.tipStep, children: fromLine.charAt(0).toUpperCase() + fromLine.slice(1) }) : null
1411
+ ] }),
1412
+ prop ? subtleOf(prop.before, prop.after) : null
1413
+ ] });
1414
+ }
1415
+ }
1416
+ ) : null,
1250
1417
  /* @__PURE__ */ jsxs(
1251
1418
  "div",
1252
1419
  {
@@ -1257,6 +1424,7 @@ function Toolbar({
1257
1424
  "data-side": side,
1258
1425
  "data-diff-ms": outlinesOn ? diff?.ms : void 0,
1259
1426
  "data-diff-count": shownCount ?? void 0,
1427
+ "data-diff-total": total ?? void 0,
1260
1428
  "data-diff-elements": outlinesOn ? diff?.elements.length : void 0,
1261
1429
  "data-note": note2 ? "" : void 0,
1262
1430
  style: drag ? { transform: `translateX(${drag}px)` } : void 0,
@@ -1281,19 +1449,15 @@ function Toolbar({
1281
1449
  /* @__PURE__ */ jsx("span", { className: styles.brand, children: "Bridge" }),
1282
1450
  /* @__PURE__ */ jsx("span", { className: styles.name, title: title2, children: title2 })
1283
1451
  ] }),
1284
- outlineIcon,
1452
+ sides2,
1453
+ nav2,
1285
1454
  /* @__PURE__ */ jsxs("div", { className: styles.actions, children: [
1286
- sides2,
1287
- /* @__PURE__ */ jsx("span", { className: styles.desktopOnly, children: swatches2 }),
1288
1455
  /* @__PURE__ */ jsxs(Popover, { open: sheetOpen, onOpenChange: setSheetOpen, children: [
1289
1456
  /* @__PURE__ */ jsx(
1290
1457
  PopoverTrigger,
1291
1458
  {
1292
- render: phone ? /* @__PURE__ */ jsx(IconButton, { icon: ListChecks, size: "md", variant: "ghost", label: shownCount ? `Changes, ${shownCount} changed here` : "Changes" }) : /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "md", iconEnd: ChevronUp }),
1293
- children: phone ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
1294
- "Changes",
1295
- shownCount ? /* @__PURE__ */ jsx("span", { className: styles.count, children: shownCount }) : null
1296
- ] })
1459
+ render: phone ? /* @__PURE__ */ jsx(IconButton, { icon: ListChecks, size: "md", variant: "ghost", label: "Changes, screens and tokens" }) : /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "md", iconEnd: ChevronUp }),
1460
+ children: phone ? null : /* @__PURE__ */ jsx(Fragment, { children: "Changes" })
1297
1461
  }
1298
1462
  ),
1299
1463
  /* @__PURE__ */ jsxs(PopoverContent, { side: "top", align: "center", className: `${styles.sheet} ${PIN_CLASS}`, "aria-label": "Changes", children: [
@@ -1359,15 +1523,15 @@ function Toolbar({
1359
1523
  shared.theme
1360
1524
  ] }) : null,
1361
1525
  /* @__PURE__ */ jsx("ul", { className: styles.list, children: screens.map((sc) => {
1362
- const current = sc.route === hash && sc.tenant === tenantId && sc.theme === theme;
1526
+ const current2 = isHere(sc);
1363
1527
  const where = shared ? null : /* @__PURE__ */ jsxs("span", { className: styles.meta, children: [
1364
1528
  " ",
1365
1529
  shopOf(sc.tenant),
1366
1530
  ", ",
1367
1531
  sc.theme
1368
1532
  ] });
1369
- return /* @__PURE__ */ jsxs("li", { className: styles.item, "aria-current": current ? "page" : void 0, children: [
1370
- current ? /* @__PURE__ */ jsxs("span", { className: styles.here, children: [
1533
+ return /* @__PURE__ */ jsxs("li", { className: styles.item, "aria-current": current2 ? "page" : void 0, children: [
1534
+ current2 ? /* @__PURE__ */ jsxs("span", { className: styles.here, children: [
1371
1535
  /* @__PURE__ */ jsx(Icon, { icon: Check, size: "sm" }),
1372
1536
  sc.label,
1373
1537
  where
@@ -1375,7 +1539,7 @@ function Toolbar({
1375
1539
  Link,
1376
1540
  {
1377
1541
  variant: "standalone",
1378
- href: `?${PARAM}=${change}&tenant=${encodeURIComponent(sc.tenant)}&theme=${encodeURIComponent(sc.theme)}#${sc.route}`,
1542
+ href: screenHref(sc),
1379
1543
  onClick: goTo(sc),
1380
1544
  className: styles.screenLink,
1381
1545
  children: [
@@ -1384,17 +1548,17 @@ function Toolbar({
1384
1548
  ]
1385
1549
  }
1386
1550
  ),
1387
- /* @__PURE__ */ jsx("span", { className: styles.meta, children: current ? "You are here" : `${Math.max(1, Math.round(sc.percent))}% changed` })
1551
+ /* @__PURE__ */ jsx("span", { className: styles.meta, children: current2 ? "You are here" : `${Math.max(1, Math.round(sc.percent))}% changed` })
1388
1552
  ] }, `${sc.route}|${sc.tenant}|${sc.theme}`);
1389
1553
  }) })
1390
1554
  ] }) : null,
1391
- visiblePairs.length ? /* @__PURE__ */ jsxs("section", { className: `${styles.sheetSection} ${styles.sheetPhone}`, "aria-label": "Tokens this change edits", children: [
1555
+ visiblePairs.length ? /* @__PURE__ */ jsxs("section", { className: styles.sheetSection, "aria-label": "Tokens this change edits", children: [
1392
1556
  /* @__PURE__ */ jsx("p", { className: styles.sectionTitle, children: "Tokens" }),
1393
1557
  /* @__PURE__ */ jsx("ul", { className: styles.list, children: roleGroups.map((g) => /* @__PURE__ */ jsxs("li", { className: styles.item, children: [
1394
1558
  /* @__PURE__ */ jsxs("span", { className: styles.rowText, children: [
1395
1559
  /* @__PURE__ */ jsx("span", { children: g.name }),
1396
1560
  /* @__PURE__ */ jsxs("span", { className: styles.rowMeta, children: [
1397
- g.pairs.length === 1 ? g.pairs[0].token.step ?? "" : `${g.pairs.length} steps`,
1561
+ g.pairs.length === 1 ? [g.pairs[0].token.step, g.pairs[0].color ? hexPair(g.pairs[0].before, g.pairs[0].after) : `${g.pairs[0].before} → ${g.pairs[0].after}`].filter(Boolean).join(", ") : `${g.pairs.length} steps`,
1398
1562
  isSubtle(g.pairs[0].before, g.pairs[0].after) ? ", subtle change" : ""
1399
1563
  ] })
1400
1564
  ] }),
@@ -1409,7 +1573,6 @@ function Toolbar({
1409
1573
  screens === null ? /* @__PURE__ */ jsx("p", { className: `${styles.note} ${styles.sheetFoot}`, children: tg ? facts ? "Screens are measured per change, not for this mix. Show what changed outlines this screen." : "Reading the changes." : facts ? "The screens this change affects are not measured yet." : "Reading the change." }) : screens.length === 0 ? /* @__PURE__ */ jsx("p", { className: `${styles.note} ${styles.sheetFoot}`, children: "No admin screen changes. Component examples may still change: Studio lists them." }) : null
1410
1574
  ] })
1411
1575
  ] }),
1412
- /* @__PURE__ */ jsx("span", { className: styles.desktopOnly, children: outlineToggle }),
1413
1576
  /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "md", render: /* @__PURE__ */ jsx("a", { href: studio2 }), className: styles.studio, children: "Back to Studio" })
1414
1577
  ] }),
1415
1578
  /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: "Collapse", children: /* @__PURE__ */ jsx(IconButton, { icon: Minimize2, size: "md", label: "Collapse the Bridge toolbar", className: styles.collapse, onClick: () => toggleOpen(false) }) }),
@@ -1423,38 +1586,7 @@ function Toolbar({
1423
1586
  note2 && /* @__PURE__ */ jsx("div", { className: styles.noteRow, children: note2 })
1424
1587
  ]
1425
1588
  }
1426
- ),
1427
- outlinesOn && surfaces.length ? /* @__PURE__ */ jsx(
1428
- ChangeOutlines,
1429
- {
1430
- surfaces,
1431
- theme,
1432
- emphasis,
1433
- flash,
1434
- onShown: setShownStable,
1435
- tip: (s) => {
1436
- const prop = s.props.find((p) => /^rgb/.test(p.before) && /^rgb/.test(p.after));
1437
- const token = prop ? visiblePairs.find((p) => p.color && toHex(p.after) === toHex(prop.after) && toHex(p.before) === toHex(prop.before)) : null;
1438
- const name2 = token?.token.name ?? [...new Set(s.roots.map(nameOf))].slice(0, 2).join(", ");
1439
- const rootsFrom = [...new Set(s.roots.flatMap((r) => facts?.tokens.find((t) => t.cssVar === r)?.from ?? []))];
1440
- const fromLine = fromOf(token) ?? (tg && rootsFrom.length ? fromText(rootsFrom, titleOf) : null);
1441
- return /* @__PURE__ */ jsxs("span", { className: styles.tip, children: [
1442
- prop ? splitOf(prop.before, prop.after) : null,
1443
- /* @__PURE__ */ jsxs("span", { className: styles.tipText, children: [
1444
- /* @__PURE__ */ jsxs("span", { children: [
1445
- s.label,
1446
- ": ",
1447
- name2,
1448
- prop ? `, ${hexPair(prop.before, prop.after)}` : ""
1449
- ] }),
1450
- token?.token.step ? /* @__PURE__ */ jsx("span", { className: styles.tipStep, children: token.token.step }) : null,
1451
- fromLine ? /* @__PURE__ */ jsx("span", { className: styles.tipStep, children: fromLine.charAt(0).toUpperCase() + fromLine.slice(1) }) : null
1452
- ] }),
1453
- prop ? subtleOf(prop.before, prop.after) : null
1454
- ] });
1455
- }
1456
- }
1457
- ) : null
1589
+ )
1458
1590
  ]
1459
1591
  }
1460
1592
  );
@@ -1483,4 +1615,4 @@ function useHash() {
1483
1615
  export {
1484
1616
  ToolbarRoot as default
1485
1617
  };
1486
- //# sourceMappingURL=Toolbar-CzR1TM9x.js.map
1618
+ //# sourceMappingURL=Toolbar-DJUb3p2c.js.map