foundry-design-web-adapter 0.2.0-beta.2 → 0.2.0-beta.3

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.
package/dist/adapter.js CHANGED
@@ -797,7 +797,15 @@ var data38 = {
797
797
  var x_default = data38;
798
798
 
799
799
  // src/keyline-icons.ts
800
- var KEYLINE_ICONS = {
800
+ function normalizeKeylineIcon(icon) {
801
+ const onePixelStroke = icon.body.replace(/stroke-width="[^"]+"/g, 'stroke-width="1"');
802
+ const nonScalingStroke = onePixelStroke.replace(
803
+ /<(path|circle|rect|line|polyline|polygon|ellipse)\b(?![^>]*vector-effect)/g,
804
+ '<$1 vector-effect="non-scaling-stroke"'
805
+ );
806
+ return { ...icon, body: nonScalingStroke };
807
+ }
808
+ var RAW_KEYLINE_ICONS = {
801
809
  accessibility: user_check_default,
802
810
  activity: activity_default,
803
811
  "align-horizontal-space-around": align_offset_left_default,
@@ -837,6 +845,12 @@ var KEYLINE_ICONS = {
837
845
  "wand-sparkles": pencil_ruler_default,
838
846
  x: x_default
839
847
  };
848
+ var KEYLINE_ICONS = Object.fromEntries(
849
+ Object.entries(RAW_KEYLINE_ICONS).map(([semantic, icon]) => [
850
+ semantic,
851
+ normalizeKeylineIcon(icon)
852
+ ])
853
+ );
840
854
  function renderKeylineIcons(root) {
841
855
  root.querySelectorAll("[data-foundry-icon]").forEach((placeholder) => {
842
856
  const semanticName = placeholder.dataset.foundryIcon;
@@ -847,18 +861,51 @@ function renderKeylineIcons(root) {
847
861
  svg.setAttribute("viewBox", `0 0 ${icon.width ?? 24} ${icon.height ?? 24}`);
848
862
  svg.setAttribute("aria-hidden", "true");
849
863
  svg.setAttribute("focusable", "false");
864
+ svg.setAttribute("fill", "none");
865
+ svg.setAttribute("stroke-width", "1");
850
866
  svg.setAttribute("data-keyline-icon", semanticName);
851
867
  svg.innerHTML = icon.body;
852
868
  placeholder.replaceWith(svg);
853
869
  });
854
870
  }
855
871
 
872
+ // src/ui-foundations.ts
873
+ var FOUNDRY_UI_FOUNDATION_CSS = `
874
+ :host {
875
+ --fdc-space-1:4px;
876
+ --fdc-space-2:8px;
877
+ --fdc-space-3:12px;
878
+ --fdc-space-4:16px;
879
+ --fdc-space-5:20px;
880
+ --fdc-space-6:24px;
881
+ --fdc-space-7:28px;
882
+ --fdc-space-8:32px;
883
+ --fdc-radius-xs:4px;
884
+ --fdc-radius-sm:8px;
885
+ --fdc-radius-md:12px;
886
+ --fdc-radius-lg:16px;
887
+ --fdc-control-sm:32px;
888
+ --fdc-control-md:36px;
889
+ --fdc-control-lg:40px;
890
+ --fdc-icon-sm:12px;
891
+ --fdc-icon-md:16px;
892
+ --fdc-icon-lg:20px;
893
+ --fdc-type-caption:12px;
894
+ --fdc-type-body:16px;
895
+ --fdc-type-heading:20px;
896
+ }
897
+ `;
898
+
856
899
  // src/workspace.ts
900
+ function resolveInterfaceTheme(preference, systemPrefersDark) {
901
+ return preference === "system" ? systemPrefersDark ? "dark" : "light" : preference;
902
+ }
857
903
  var DEFAULT_WORKSPACE_STATE = {
858
904
  layersOpen: true,
859
905
  inspectorOpen: true,
860
906
  utility: null,
861
- tray: "hidden",
907
+ changeSummaryVisible: false,
908
+ reviewOpen: false,
862
909
  workbenchOpen: false,
863
910
  comparisonOpen: false
864
911
  };
@@ -873,7 +920,14 @@ function updateWorkspace(state, action) {
873
920
  return { ...state, utility: state.utility === action.utility ? null : action.utility };
874
921
  }
875
922
  if (action.type === "close-utility") return { ...state, utility: null };
876
- if (action.type === "set-tray") return { ...state, tray: action.tray };
923
+ if (action.type === "set-change-summary") {
924
+ return {
925
+ ...state,
926
+ changeSummaryVisible: action.visible,
927
+ reviewOpen: action.visible ? state.reviewOpen : false
928
+ };
929
+ }
930
+ if (action.type === "set-review") return { ...state, reviewOpen: action.open };
877
931
  if (action.type === "set-workbench") return { ...state, workbenchOpen: action.open };
878
932
  return { ...state, comparisonOpen: action.open };
879
933
  }
@@ -914,14 +968,19 @@ var CONTROL_SECTIONS = {
914
968
  {
915
969
  label: "Position and size",
916
970
  properties: [
917
- "widthMode",
918
- "heightMode",
971
+ "left",
972
+ "top",
919
973
  "width",
920
974
  "height",
975
+ "widthMode",
976
+ "heightMode",
921
977
  "minWidth",
922
978
  "maxWidth",
923
979
  "aspectRatio",
924
- "overflow"
980
+ "overflow",
981
+ "rotate",
982
+ "scaleX",
983
+ "scaleY"
925
984
  ],
926
985
  columns: 2,
927
986
  prefixes: {
@@ -932,7 +991,12 @@ var CONTROL_SECTIONS = {
932
991
  minWidth: "Min",
933
992
  maxWidth: "Max",
934
993
  aspectRatio: "Ratio",
935
- overflow: "Clip"
994
+ overflow: "Clip",
995
+ left: "X",
996
+ top: "Y",
997
+ rotate: "\xB0",
998
+ scaleX: "FX",
999
+ scaleY: "FY"
936
1000
  }
937
1001
  },
938
1002
  {
@@ -988,17 +1052,29 @@ var CONTROL_SECTIONS = {
988
1052
  }
989
1053
  ],
990
1054
  color: [
991
- { label: "Appearance", properties: ["color", "backgroundColor", "opacity"] },
992
- { label: "Gradient", properties: ["backgroundImage"], stacked: true }
1055
+ { label: "Appearance", properties: ["opacity"] },
1056
+ { label: "Fill", properties: ["color", "backgroundColor", "backgroundImage"], stacked: true }
993
1057
  ],
994
1058
  effects: [
995
1059
  {
996
- label: "Corners and border",
997
- properties: ["borderRadius", "borderWidth"],
1060
+ label: "Corners",
1061
+ properties: [
1062
+ "borderRadius",
1063
+ "borderTopLeftRadius",
1064
+ "borderTopRightRadius",
1065
+ "borderBottomLeftRadius",
1066
+ "borderBottomRightRadius"
1067
+ ],
998
1068
  columns: 2,
999
- prefixes: { borderRadius: "R", borderWidth: "B" }
1069
+ prefixes: {
1070
+ borderRadius: "All",
1071
+ borderTopLeftRadius: "TL",
1072
+ borderTopRightRadius: "TR",
1073
+ borderBottomLeftRadius: "BL",
1074
+ borderBottomRightRadius: "BR"
1075
+ }
1000
1076
  },
1001
- { label: "Stroke", properties: ["borderColor"] },
1077
+ { label: "Stroke", properties: ["borderWidth", "borderColor"] },
1002
1078
  {
1003
1079
  label: "Effects",
1004
1080
  properties: ["boxShadow", "filter"],
@@ -1021,70 +1097,71 @@ var CONTROL_SECTIONS = {
1021
1097
  ]
1022
1098
  };
1023
1099
  var PANEL_CSS = `
1100
+ ${FOUNDRY_UI_FOUNDATION_CSS}
1024
1101
  :host { all:initial; color-scheme:dark; --fdc-ink:#f0f1f3; --fdc-paper:#141416; --fdc-surface:#1c1c1f; --fdc-subtle:#242428; --fdc-elevated:#29292e; --fdc-line:#303035; --fdc-signal:#3b82f6; --fdc-signal-soft:#172d50; --fdc-component:#9b87f5; --fdc-component-soft:#28233d; --fdc-muted:#9a9aa2; --fdc-font:"Geist Sans",Geist,Arial,sans-serif; font-family:var(--fdc-font); color:var(--fdc-ink); }
1025
1102
  *,*::before,*::after { box-sizing:border-box;font-family:inherit; }
1026
1103
  button,select,input { font:inherit; }
1027
- button:focus-visible,select:focus-visible,input:focus-visible { outline:2px solid var(--fdc-signal);outline-offset:2px; }
1028
- .outline { position:fixed;z-index:2147483645;pointer-events:none;border:1.5px solid var(--fdc-signal);box-shadow:0 0 0 1px rgb(255 255 255 / 90%),0 0 0 4px rgb(54 89 244 / 12%);transition:top 80ms linear,left 80ms linear,width 80ms linear,height 80ms linear; }
1029
- .measure { position:absolute;left:-2px;top:-28px;height:25px;display:flex;align-items:center;padding:0 9px;color:white;background:var(--fdc-signal);border-radius:5px 5px 5px 0;font:650 10px/1 var(--fdc-font);letter-spacing:.02em;white-space:nowrap;box-shadow:0 4px 14px rgb(25 43 124 / 20%); }
1030
- .cross::before,.cross::after { content:"";position:absolute;background:var(--fdc-signal); }.cross::before { width:11px;height:1px;left:-6px;top:-1px; }.cross::after { width:1px;height:11px;left:-1px;top:-6px; }
1031
- .panel { position:fixed;z-index:2147483646;top:12px;right:12px;width:352px;min-width:312px;max-width:min(520px,calc(100vw - 24px));max-height:calc(100vh - 24px);overflow:hidden;display:flex;flex-direction:column;color:var(--fdc-ink);background:var(--fdc-surface);border:1px solid var(--fdc-line);box-shadow:0 1px 2px rgb(0 0 0 / 5%),0 10px 28px rgb(0 0 0 / 10%);pointer-events:auto;border-radius:12px; }
1104
+ button:focus-visible,select:focus-visible,input:focus-visible { outline:4px solid var(--fdc-signal);outline-offset:4px; }
1105
+ .outline { position:fixed;z-index:2147483645;pointer-events:none;border:1px solid var(--fdc-signal);box-shadow:0 0 0 1px rgb(255 255 255 / 90%),0 0 0 4px rgb(54 89 244 / 12%);transition:top 80ms linear,left 80ms linear,width 80ms linear,height 80ms linear; }
1106
+ .measure { position:absolute;left:-4px;top:-28px;height:24px;display:flex;align-items:center;padding:0 8px;color:white;background:var(--fdc-signal);border-radius:4px 4px 4px 0;font:650 12px/1 var(--fdc-font);letter-spacing:.02em;white-space:nowrap;box-shadow:0 4px 16px rgb(25 43 124 / 20%); }
1107
+ .cross::before,.cross::after { content:"";position:absolute;background:var(--fdc-signal); }.cross::before { width:12px;height:1px;left:-8px;top:-1px; }.cross::after { width:1px;height:12px;left:-1px;top:-8px; }
1108
+ .panel { position:fixed;z-index:2147483646;top:12px;right:12px;width:384px;min-width:340px;max-width:min(520px,calc(100vw - 24px));max-height:calc(100vh - 24px);overflow:hidden;display:flex;flex-direction:column;color:var(--fdc-ink);background:var(--fdc-surface);border:1px solid var(--fdc-line);box-shadow:0 1px 4px rgb(0 0 0 / 5%),0 12px 28px rgb(0 0 0 / 10%);pointer-events:auto;border-radius:12px; }
1032
1109
  .top { flex:none;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }
1033
1110
  .top-identity { position:relative;min-height:44px;display:flex;align-items:center;padding:0 12px; }
1034
1111
  .brand { flex:1;display:flex;align-items:center;min-width:0; }
1035
- .brand-copy { display:flex;align-items:baseline;gap:5px; }.brand-copy b { font-size:13px;line-height:1;font-weight:550;letter-spacing:-.02em; }.brand-copy span { color:var(--fdc-muted);font:400 10px/1 var(--fdc-font); }
1036
- .session-status { flex:none;margin-left:8px;display:flex;align-items:center;gap:5px;padding:4px 7px;border:0;color:#236c59;background:#eef8f4;border-radius:999px;font:500 10px/1 var(--fdc-font);cursor:pointer; }.session-status i { width:5px;height:5px;background:#2ca67f;border-radius:50%; }.session-status.saving { color:#6b570f;background:#fff8d8; }.session-status.saving i { background:#d5a91d;animation:fdc-pulse 1s ease-in-out infinite; }.session-status.error,.session-status.offline { color:#8b4d3d;background:#faece7; }.session-status.error i,.session-status.offline i { background:#d16d51; }.session-status.saved { color:#236c59;background:#eef8f4; }.status-popover { position:absolute;z-index:2;top:39px;right:40px;width:238px;padding:10px;border:1px solid var(--fdc-line);border-radius:8px;background:white;box-shadow:0 10px 28px rgb(0 0 0 / 14%); }.status-popover[hidden] { display:none; }.status-popover strong { display:block;font-size:11px;font-weight:550; }.status-popover span,.status-popover code { display:block;margin-top:5px;overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font:400 9px/1.45 var(--fdc-font);white-space:nowrap; }.status-popover button { width:100%;height:28px;margin-top:8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:var(--fdc-ink);font-size:9px;cursor:pointer; }
1037
- .top-identity>.close { flex:none;margin-left:4px; }.top-actions { min-height:40px;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));align-items:center;padding:4px 8px;border-top:1px solid var(--fdc-line);background:var(--fdc-surface); }.top-actions .icon-button { justify-self:center; }.icon-button { width:32px;height:32px;display:grid;place-items:center;border:0;border-radius:6px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.icon-button:hover { background:var(--fdc-subtle);color:var(--fdc-ink); }.icon-button.active { color:#0761d1;background:#edf6ff; }.icon-button:disabled { opacity:.35;cursor:not-allowed; }.icon-button:disabled:hover { color:var(--fdc-muted);background:transparent; }
1038
- .selection { position:relative;padding:14px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.selection::before { content:"";position:absolute;top:13px;left:0;width:2px;height:0;background:var(--fdc-signal);border-radius:0 2px 2px 0;transition:height .18s ease; }.panel.has-selection .selection::before { height:24px; }.selection-heading { display:flex;align-items:center;justify-content:space-between;margin-bottom:9px; }.selection-kind { max-width:220px;overflow:hidden;text-overflow:ellipsis;padding:4px 6px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:4px;font:500 10px/1 var(--fdc-font);text-transform:uppercase;letter-spacing:.025em;white-space:nowrap; }.selection-state { color:var(--fdc-muted);font:450 10px/1 var(--fdc-font); }.panel.has-selection .selection-state { color:#0761d1; }.selection strong { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:16px;line-height:1.3;font-weight:550;letter-spacing:-.025em; }.selection code { display:block;margin-top:5px;overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font:400 11px/1.45 var(--fdc-font);white-space:nowrap; }.selection-hint { display:block;margin-top:9px;color:#858585;font:400 10px/1.45 var(--fdc-font); }.selection-stats { display:flex;gap:5px;margin-top:10px; }.selection-stats[hidden] { display:none; }.selection-stats span { padding:5px 7px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:5px;font:400 10px/1 var(--fdc-font); }.selection-stats span:first-child { color:#0761d1;background:#edf6ff; }.selection.selected-flash strong { animation:fdc-selection-title .2s ease-out; }
1039
- .scope { display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:12px 14px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.scope label { display:flex;flex-direction:column;gap:6px;color:var(--fdc-muted);font:500 11px/1.2 var(--fdc-font); }.scope select { width:100%;height:34px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:6px;background:var(--fdc-surface);color:var(--fdc-ink);font:400 12px/1 var(--fdc-font);text-transform:none;letter-spacing:0;outline:none;cursor:pointer; }
1040
- .tool-shelf { position:fixed;z-index:2147483646;left:50%;bottom:18px;transform:translateX(-50%);display:flex;align-items:center;gap:6px;max-width:calc(100vw - 32px);padding:6px;background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 2px 2px rgb(0 0 0 / 4%),0 8px 16px -4px rgb(0 0 0 / 14%);pointer-events:auto; }.mode-copy { min-width:96px;display:flex;flex-direction:column;gap:2px;padding:0 6px 0 1px; }.mode-copy strong { font-size:10px;font-weight:550;line-height:1.1; }.mode-copy span { color:var(--fdc-muted);font-size:9px;line-height:1.2;white-space:nowrap; }
1041
- .tool-select,.tab { position:relative;flex:none;width:36px;height:36px;display:grid;place-items:center;padding:0;border:0;border-radius:6px;background:transparent;color:#4d4d4d;cursor:pointer; }.tool-select:hover,.tab:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.tool-select.active,.tab.active { color:white;background:var(--fdc-ink); }.tool-select svg,.tab svg,.icon-button svg { width:16px;height:16px;pointer-events:none; }.tool-select::after,.tab::after { content:attr(data-tooltip);position:absolute;left:50%;bottom:calc(100% + 8px);transform:translate(-50%,3px);padding:6px 8px;border-radius:5px;background:var(--fdc-ink);color:white;font:400 11px/1 var(--fdc-font);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s ease,transform .12s ease; }.tool-select:hover::after,.tool-select:focus-visible::after,.tab:not(:disabled):hover::after,.tab:not(:disabled):focus-visible::after { opacity:1;transform:translate(-50%,0); }.tool-divider { width:1px;height:24px;flex:none;background:var(--fdc-line); }.tabs { display:flex;gap:2px;overflow:visible;scrollbar-width:none; }.tab:disabled { color:#a1a1a1;cursor:default; }.tab:disabled:hover { background:transparent; }
1042
- .controls { min-height:210px;overflow:auto;background:var(--fdc-surface); }.inspector-heading { position:sticky;top:0;z-index:1;height:42px;display:flex;align-items:center;gap:8px;padding:0 12px;background:rgb(255 255 255 / 96%);border-bottom:1px solid var(--fdc-line);backdrop-filter:blur(8px); }.inspector-heading svg { width:15px;height:15px;color:#4d4d4d; }.inspector-heading strong { font-size:12px;font-weight:550; }.property-count { margin-left:auto;color:var(--fdc-muted);font:400 10px/1 var(--fdc-font);letter-spacing:.01em; }.property-section { padding:0;border-bottom:1px solid var(--fdc-line); }.section-head { width:100%;min-height:39px;display:flex;align-items:center;padding:0 8px 0 4px;background:white;color:#3f3f3f; }.section-head:hover { background:#fcfcfc; }.section-toggle { min-width:0;min-height:39px;flex:1;display:flex;align-items:center;gap:7px;padding:0 8px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer; }.section-toggle>svg { width:12px;height:12px;color:#858585;transition:transform .12s ease; }.property-section.collapsed .section-toggle>svg { transform:rotate(-90deg); }.section-head strong { font-size:11px;font-weight:500; }.section-grid { display:grid;gap:8px;padding:0 12px 12px; }.property-section.collapsed .section-grid { display:none; }.section-grid.two { grid-template-columns:1fr 1fr; }.section-grid.stacked .property-control { grid-template-columns:1fr;gap:6px; }.property-control { display:grid;grid-template-columns:minmax(0,1fr) 132px 24px;align-items:center;gap:7px;min-height:34px; }.property-label { overflow:hidden;text-overflow:ellipsis;color:#4d4d4d;font-size:11px;font-weight:400;white-space:nowrap; }.control-field { position:relative;display:flex;align-items:center;min-width:0;height:32px;border:1px solid var(--fdc-line);border-radius:5px;background:var(--fdc-paper);overflow:hidden;transition:border-color .12s ease,box-shadow .12s ease,background .12s ease; }.control-field:hover { background:var(--fdc-surface); }.control-field:focus-within { border-color:var(--fdc-signal);background:var(--fdc-surface);box-shadow:0 0 0 2px rgb(0 112 243 / 10%); }.control-reset { width:24px;height:24px;display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:transparent;color:#8a8a8a;cursor:pointer;opacity:0; }.property-control:hover .control-reset,.compact-control:hover .control-reset,.control-reset:focus-visible { opacity:1; }.control-reset:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.control-reset svg { width:12px;height:12px; }.compact-control { min-width:0;display:grid;grid-template-columns:minmax(0,1fr) 24px;gap:5px;align-items:center; }.compact-control .control-field { width:100%; }.field-prefix { min-width:28px;padding-left:8px;color:#7a7a7a;font:400 10px/1 var(--fdc-font); }.compact-control .field-prefix.wide { min-width:40px; }.property-control input,.property-control select,.compact-control input,.compact-control select { width:100%;min-width:0;height:30px;padding:0 7px;border:0;background:transparent;color:var(--fdc-ink);font:400 11px/1 var(--fdc-font);outline:none; }.property-control input[type="number"],.compact-control input[type="number"] { appearance:textfield; }.property-control input[type="number"]::-webkit-inner-spin-button,.property-control input[type="number"]::-webkit-outer-spin-button,.compact-control input[type="number"]::-webkit-inner-spin-button,.compact-control input[type="number"]::-webkit-outer-spin-button { margin:0;appearance:none; }.property-control select { font-family:var(--fdc-font); }.control-field .unit-select { width:40px;flex:none;padding:0 3px;color:#707070;font-size:9px;cursor:pointer; }[data-scrub-for] { cursor:ew-resize;user-select:none;touch-action:none; }.property-label[data-scrub-for]:hover,.field-prefix[data-scrub-for]:hover,[data-scrub-for].scrubbing { color:var(--fdc-signal); }.color-swatch { width:17px;height:17px;flex:none;margin-left:7px;border:1px solid rgb(0 0 0 / 10%);border-radius:3px;background:var(--swatch-color); }.color-swatch.transparent { background-color:white;background-image:linear-gradient(45deg,#d9d9d9 25%,transparent 25%),linear-gradient(-45deg,#d9d9d9 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#d9d9d9 75%),linear-gradient(-45deg,transparent 75%,#d9d9d9 75%);background-size:8px 8px;background-position:0 0,0 4px,4px -4px,-4px 0; }.color-value { overflow:hidden;text-overflow:ellipsis;margin-left:7px;color:#4d4d4d;font:400 10px/1 var(--fdc-font);white-space:nowrap; }.color-picker { position:absolute;inset:0;width:100%!important;height:100%!important;opacity:0;cursor:pointer; }.unit { padding-right:7px;color:#7a7a7a;font:400 10px/1 var(--fdc-font); }.sr-only { position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0; }
1043
- .motion-list { padding:0 12px 12px; }.motion-row { padding:12px 0;border-bottom:1px solid var(--fdc-line); }.motion-title { display:flex;justify-content:space-between;gap:12px;margin-bottom:9px;font-size:12px;font-weight:550; }.motion-title code { color:var(--fdc-muted);font:400 10px/1.3 var(--fdc-font); }.motion-actions { display:grid;grid-template-columns:repeat(4,1fr);gap:4px; }.motion-actions button { min-height:30px;padding:0 5px;border:1px solid var(--fdc-line);background:var(--fdc-paper);border-radius:5px;color:var(--fdc-ink);font-size:10px;font-weight:400;cursor:pointer; }.motion-actions button:hover { border-color:#c7c7c7;background:var(--fdc-surface); }
1044
- .motion-timeline { width:100%;margin:2px 0 10px;accent-color:var(--fdc-signal); }.motion-fields { display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:8px; }.motion-fields label { display:grid;grid-template-columns:auto 1fr;align-items:center;gap:5px;color:var(--fdc-muted);font-size:9px; }.motion-fields input { width:100%;height:28px;padding:0 6px;border:1px solid var(--fdc-line);border-radius:5px;background:var(--fdc-paper);color:var(--fdc-ink);font-size:10px; }
1045
- .empty { padding:48px 28px;text-align:center;color:var(--fdc-muted);font-size:13px;line-height:1.6; }.empty::before { content:"\u2316";display:grid;place-items:center;width:38px;height:38px;margin:0 auto 13px;color:var(--fdc-signal);background:var(--fdc-signal-soft);border-radius:10px;font:18px/1 var(--fdc-font); }
1046
- .change-dock { min-height:48px;display:grid;grid-template-columns:minmax(0,1fr) 30px 68px;align-items:center;gap:6px;padding:7px 8px;border-top:1px solid var(--fdc-line);background:white; }.change-dock[hidden] { display:none; }.change-dock-copy { min-width:0;padding-left:3px; }.change-dock-copy strong,.change-dock-copy span { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.change-dock-copy strong { font-size:10px;font-weight:550; }.change-dock-copy span { margin-top:3px;color:var(--fdc-muted);font-size:9px; }.change-dock button { height:30px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:var(--fdc-ink);font-size:9px;cursor:pointer; }.change-dock .dock-review { color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.change-dock svg { width:12px;height:12px; }.footer { display:grid;grid-template-columns:82px 1fr;gap:6px;padding:8px;background:var(--fdc-surface);border-top:1px solid var(--fdc-line); }.footer:has(.review[hidden]) { grid-template-columns:1fr; }.footer button[hidden] { display:none; }.footer button { min-height:36px;border:1px solid var(--fdc-line);border-radius:6px;background:var(--fdc-surface);color:var(--fdc-ink);font-size:11px;font-weight:450;cursor:pointer; }.footer button:hover { border-color:#d0d0d0;background:var(--fdc-paper); }.footer .review { align-items:center;justify-content:center;gap:7px;color:white;background:var(--fdc-ink);border-color:var(--fdc-ink); }.footer .review:not([hidden]) { display:flex; }.footer .review:hover { background:#2f2f2f; }.change-count { min-width:18px;height:18px;display:inline-grid;place-items:center;padding:0 5px;color:var(--fdc-ink);background:white;border-radius:999px;font:500 9px/1 var(--fdc-font); }.change-count[hidden] { display:none; }
1047
- .review-view { min-height:0;flex:1;display:none;flex-direction:column;background:var(--fdc-surface); }.panel.reviewing .selection,.panel.reviewing .scope,.panel.reviewing .controls,.panel.reviewing>.footer,.panel.reviewing>.change-dock { display:none; }.panel.reviewing .review-view { display:flex; }.review-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 10px;border-bottom:1px solid var(--fdc-line); }.review-head button { width:30px;height:30px;display:grid;place-items:center;padding:0;border:0;border-radius:5px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.review-head button:hover { background:var(--fdc-subtle);color:var(--fdc-ink); }.review-head svg { width:15px;height:15px; }.review-head strong { font-size:12px;font-weight:550; }.review-head span { margin-left:auto;color:var(--fdc-muted);font-size:10px; }.review-body { min-height:160px;overflow-x:hidden;overflow-y:auto; }.review-toolbar { position:sticky;top:0;z-index:1;display:flex;gap:5px;padding:7px 8px;border-bottom:1px solid var(--fdc-line);background:rgb(255 255 255 / 96%);backdrop-filter:blur(8px); }.review-toolbar button { height:27px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#555;font-size:9px;cursor:pointer; }.review-toolbar button:last-child { margin-left:auto; }.review-empty { padding:42px 24px;color:var(--fdc-muted);font-size:12px;line-height:1.55;text-align:center; }.review-group { border-bottom:1px solid var(--fdc-line); }.review-group-title { width:100%;min-height:36px;display:flex;align-items:center;gap:7px;padding:0 12px;border:0;background:white;color:var(--fdc-muted);font-size:10px;font-weight:500;text-align:left;cursor:pointer; }.review-group-title span { margin-left:auto;font-size:9px; }.review-group-title svg { width:11px;height:11px;transition:transform .12s ease; }.review-group.collapsed .review-group-title svg { transform:rotate(-90deg); }.review-group.collapsed .review-card { display:none; }.review-card { display:grid;grid-template-columns:18px minmax(0,1fr);gap:8px;padding:9px 12px 10px; }.review-card.rejected { opacity:.62; }.review-card+.review-card { border-top:1px solid var(--fdc-line); }.review-card input[type="checkbox"] { width:14px;height:14px;margin:2px 0 0;accent-color:var(--fdc-ink); }.review-card-main { min-width:0; }.review-card-line { display:flex;align-items:center;gap:7px; }.review-card-line strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:11px;font-weight:500;white-space:nowrap; }.review-card-tools { display:flex;gap:3px;margin-left:auto; }.review-card-tools button { height:23px;padding:0 6px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#666;font-size:8px;cursor:pointer; }.confidence-pill { flex:none;padding:3px 5px;border-radius:4px;background:#edf6ff;color:#0761d1;font-size:9px;text-transform:capitalize; }.confidence-pill.unresolved { color:#984a2b;background:#fff0e8; }.review-values { display:grid;grid-template-columns:minmax(0,1fr) 12px minmax(0,1fr);align-items:center;gap:4px;margin-top:7px; }.review-before { overflow:hidden;text-overflow:ellipsis;padding:7px;color:var(--fdc-muted);background:var(--fdc-subtle);border-radius:4px;font-size:10px;white-space:nowrap; }.review-values>span { color:var(--fdc-muted);font-size:10px;text-align:center; }.review-after { width:100%;height:28px;min-width:0;padding:0 7px;border:1px solid var(--fdc-line);border-radius:4px;background:white;font-size:10px;outline:none; }.review-after:focus { border-color:var(--fdc-signal);box-shadow:0 0 0 2px rgb(0 112 243 / 10%); }.review-source { margin-top:6px;overflow-wrap:anywhere;color:var(--fdc-muted);font-size:9px;line-height:1.45; }.review-actions { display:grid;grid-template-columns:82px 1fr;gap:6px;padding:8px;border-top:1px solid var(--fdc-line); }.review-actions button { min-height:36px;border:1px solid var(--fdc-line);border-radius:6px;background:white;font-size:11px;cursor:pointer; }.review-actions .apply { color:white;background:var(--fdc-ink);border-color:var(--fdc-ink); }.review-actions button:disabled { opacity:.45;cursor:not-allowed; }.run-summary { padding:14px 12px;border-bottom:1px solid var(--fdc-line); }.run-state { display:flex;align-items:center;gap:8px; }.run-state i { width:8px;height:8px;border-radius:50%;background:#a3a3a3; }.run-state i.active { background:var(--fdc-signal);box-shadow:0 0 0 4px rgb(0 112 243 / 10%); }.run-state i.passed { background:#2ca67f; }.run-state i.attention { background:#d16d51; }.run-state strong { font-size:12px;font-weight:550;text-transform:capitalize; }.run-summary p { margin:8px 0 0;color:var(--fdc-muted);font-size:10px;line-height:1.5; }.run-steps { padding:4px 12px 10px; }.run-step { display:grid;grid-template-columns:18px minmax(0,1fr);gap:7px;padding:8px 0;border-bottom:1px solid var(--fdc-line); }.run-step:last-child { border-bottom:0; }.run-step span:first-child { color:var(--fdc-muted);font-size:10px; }.run-step strong { display:block;font-size:10px;font-weight:500;text-transform:capitalize; }.run-step p { margin:3px 0 0;color:var(--fdc-muted);font-size:9px;line-height:1.45; }.result-list { padding:0 12px 12px; }.result-row { display:flex;align-items:flex-start;justify-content:space-between;gap:8px;padding:8px 0;border-top:1px solid var(--fdc-line);font-size:10px; }.result-row span:last-child { color:var(--fdc-muted);text-align:right; }.result-row.pass span:first-child { color:#23715c; }.result-row.fail span:first-child { color:#a24d30; }.run-files { padding:0 12px 12px;color:var(--fdc-muted);font-size:9px;line-height:1.5; }.run-files code { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
1048
- .toast { position:fixed;left:50%;bottom:76px;transform:translate(-50%,8px);padding:9px 12px;background:var(--fdc-ink);color:white;border-radius:6px;font-size:11px;font-weight:450;opacity:0;transition:.15s ease;pointer-events:none;white-space:nowrap;box-shadow:0 8px 20px rgb(0 0 0 / 16%); }.toast.show { opacity:1;transform:translate(-50%,0); }
1049
- .resize-handle { position:absolute;width:9px;height:9px;min-width:9px;min-height:9px;aspect-ratio:1;padding:0;border:1px solid #f0f1f3;border-radius:1px;background:var(--fdc-signal);box-shadow:0 1px 4px rgb(0 0 0 / 28%);appearance:none;pointer-events:auto;touch-action:none; }
1050
- .resize-handle[data-handle="n"]{top:-5px;left:calc(50% - 4px);cursor:ns-resize}.resize-handle[data-handle="s"]{bottom:-5px;left:calc(50% - 4px);cursor:ns-resize}.resize-handle[data-handle="e"]{right:-5px;top:calc(50% - 4px);cursor:ew-resize}.resize-handle[data-handle="w"]{left:-5px;top:calc(50% - 4px);cursor:ew-resize}.resize-handle[data-handle="ne"]{right:-5px;top:-5px;cursor:nesw-resize}.resize-handle[data-handle="nw"]{left:-5px;top:-5px;cursor:nwse-resize}.resize-handle[data-handle="se"]{right:-5px;bottom:-5px;cursor:nwse-resize}.resize-handle[data-handle="sw"]{left:-5px;bottom:-5px;cursor:nesw-resize}
1051
- .panel-resizer { position:absolute;z-index:3;top:84px;bottom:0;left:-4px;width:8px;border:0;background:transparent;cursor:ew-resize;touch-action:none; }.panel-resizer::after { content:"";position:absolute;top:50%;left:3px;width:2px;height:28px;transform:translateY(-50%);border-radius:2px;background:#4a4a50;opacity:0;transition:opacity .12s ease; }.panel:hover .panel-resizer::after,.panel-resizer:focus-visible::after { opacity:1; }.radius-handle { position:absolute;top:7px;left:7px;width:10px;height:10px;min-width:10px;min-height:10px;aspect-ratio:1;padding:0;border:2px solid #f0f1f3;border-radius:50%;background:#ff4d8d;box-shadow:0 1px 4px rgb(0 0 0 / 28%);appearance:none;pointer-events:auto;cursor:nwse-resize;touch-action:none; }
1052
- .canvas-variant { position:fixed;z-index:2147483645;height:27px;max-width:180px;padding:0 25px 0 8px;border:1px solid #b8d5ff;border-radius:6px;background:white;color:#075fc5;font-size:9px;box-shadow:0 5px 14px rgb(0 0 0 / 10%);pointer-events:auto; }.canvas-variant[hidden] { display:none; }
1053
- .onboarding-card { position:fixed;z-index:2147483647;left:50%;bottom:78px;width:286px;transform:translateX(-50%);padding:13px;border:1px solid var(--fdc-line);border-radius:10px;background:white;box-shadow:0 12px 32px rgb(0 0 0 / 14%);pointer-events:auto; }.onboarding-card[hidden] { display:none; }.onboarding-card-head { display:flex;align-items:center;gap:8px; }.onboarding-card-head svg { width:15px;height:15px;color:var(--fdc-signal); }.onboarding-card-head strong { font-size:11px;font-weight:550; }.onboarding-card p { margin:8px 0 11px;color:var(--fdc-muted);font-size:10px;line-height:1.5; }.onboarding-steps { display:grid;grid-template-columns:repeat(3,1fr);gap:5px; }.onboarding-steps span { padding:7px 5px;border:1px solid var(--fdc-line);border-radius:6px;color:#555;font-size:9px;line-height:1.35;text-align:center; }.onboarding-actions { display:flex;justify-content:flex-end;gap:5px;margin-top:10px; }.onboarding-actions button { height:28px;padding:0 9px;border:1px solid var(--fdc-line);border-radius:5px;background:white;font-size:9px;cursor:pointer; }.onboarding-actions .onboarding-start { color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }
1054
- .review-details { margin-top:7px;color:var(--fdc-muted);font-size:9px; }.review-details summary { cursor:pointer;user-select:none; }.review-details[open] summary { margin-bottom:5px; }.review-details .review-source { display:block; }.review-details .impact-list { display:grid;gap:3px;margin-top:5px; }
1112
+ .brand-copy { display:flex;align-items:baseline;gap:4px; }.brand-copy b { font-size:12px;line-height:1;font-weight:550;letter-spacing:-.02em; }.brand-copy span { color:var(--fdc-muted);font:400 12px/1 var(--fdc-font); }
1113
+ .session-status { flex:none;margin-left:8px;display:flex;align-items:center;gap:4px;padding:4px 8px;border:0;color:#236c59;background:#eef8f4;border-radius:1000px;font:500 12px/1 var(--fdc-font);cursor:pointer; }.session-status i { width:4px;height:4px;background:#2ca67f;border-radius:50%; }.session-status.saving { color:#6b570f;background:#fff8d8; }.session-status.saving i { background:#d5a91d;animation:fdc-pulse 1s ease-in-out infinite; }.session-status.error,.session-status.offline { color:#8b4d3d;background:#faece7; }.session-status.error i,.session-status.offline i { background:#d16d51; }.session-status.saved { color:#236c59;background:#eef8f4; }.status-popover { position:absolute;z-index:2;top:40px;right:40px;width:240px;padding:12px;border:1px solid var(--fdc-line);border-radius:8px;background:white;box-shadow:0 12px 28px rgb(0 0 0 / 14%); }.status-popover[hidden] { display:none; }.status-popover strong { display:block;font-size:12px;font-weight:550; }.status-popover span,.status-popover code { display:block;margin-top:4px;overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font:400 8px/1.45 var(--fdc-font);white-space:nowrap; }.status-popover button { width:100%;height:28px;margin-top:8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:var(--fdc-ink);font-size:8px;cursor:pointer; }
1114
+ .top-identity>.close { flex:none;margin-left:4px; }.top-actions { min-height:40px;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));align-items:center;padding:4px 8px;border-top:1px solid var(--fdc-line);background:var(--fdc-surface); }.top-actions .icon-button { justify-self:center; }.icon-button { width:32px;height:32px;display:grid;place-items:center;border:0;border-radius:8px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.icon-button:hover { background:var(--fdc-subtle);color:var(--fdc-ink); }.icon-button.active { color:#0761d1;background:#edf6ff; }.icon-button:disabled { opacity:.35;cursor:not-allowed; }.icon-button:disabled:hover { color:var(--fdc-muted);background:transparent; }
1115
+ .selection { position:relative;padding:16px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.selection::before { content:"";position:absolute;top:12px;left:0;width:4px;height:0;background:var(--fdc-signal);border-radius:0 4px 4px 0;transition:height .18s ease; }.panel.has-selection .selection::before { height:24px; }.selection-heading { display:flex;align-items:center;justify-content:space-between;margin-bottom:8px; }.selection-kind { max-width:220px;overflow:hidden;text-overflow:ellipsis;padding:4px 8px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:4px;font:500 12px/1 var(--fdc-font);text-transform:uppercase;letter-spacing:.025em;white-space:nowrap; }.selection-state { color:var(--fdc-muted);font:450 12px/1 var(--fdc-font); }.panel.has-selection .selection-state { color:#0761d1; }.selection strong { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:16px;line-height:1.3;font-weight:550;letter-spacing:-.025em; }.selection code { display:block;margin-top:4px;overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font:400 12px/1.45 var(--fdc-font);white-space:nowrap; }.selection-hint { display:block;margin-top:8px;color:#858585;font:400 12px/1.45 var(--fdc-font); }.selection-stats { display:flex;gap:4px;margin-top:12px; }.selection-stats[hidden] { display:none; }.selection-stats span { padding:4px 8px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:4px;font:400 12px/1 var(--fdc-font); }.selection-stats span:first-child { color:#0761d1;background:#edf6ff; }.selection.selected-flash strong { animation:fdc-selection-title .2s ease-out; }
1116
+ .scope { display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:12px 16px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.scope label { display:flex;flex-direction:column;gap:8px;color:var(--fdc-muted);font:500 12px/1.2 var(--fdc-font); }.scope select { width:100%;height:36px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-surface);color:var(--fdc-ink);font:400 12px/1 var(--fdc-font);text-transform:none;letter-spacing:0;outline:none;cursor:pointer; }
1117
+ .tool-shelf { position:fixed;z-index:2147483646;left:50%;bottom:20px;transform:translateX(-50%);display:flex;align-items:center;gap:8px;max-width:calc(100vw - 32px);padding:8px;background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 4px 4px rgb(0 0 0 / 4%),0 8px 16px -4px rgb(0 0 0 / 14%);pointer-events:auto; }.mode-copy { min-width:96px;display:flex;flex-direction:column;gap:4px;padding:0 8px 0 1px; }.mode-copy strong { font-size:12px;font-weight:550;line-height:1.1; }.mode-copy span { color:var(--fdc-muted);font-size:8px;line-height:1.2;white-space:nowrap; }
1118
+ .tool-select,.tab { position:relative;flex:none;width:36px;height:36px;display:grid;place-items:center;padding:0;border:0;border-radius:8px;background:transparent;color:#4d4d4d;cursor:pointer; }.tool-select:hover,.tab:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.tool-select.active,.tab.active { color:white;background:var(--fdc-ink); }.tool-select svg,.icon-button svg { width:20px;height:20px;pointer-events:none; }.tab svg { width:16px;height:16px;pointer-events:none; }.tool-select::after,.tab::after { content:attr(data-tooltip);position:absolute;left:50%;bottom:calc(100% + 8px);transform:translate(-50%,4px);padding:8px 8px;border-radius:4px;background:var(--fdc-ink);color:white;font:400 12px/1 var(--fdc-font);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s ease,transform .12s ease; }.tool-select:hover::after,.tool-select:focus-visible::after,.tab:not(:disabled):hover::after,.tab:not(:disabled):focus-visible::after { opacity:1;transform:translate(-50%,0); }.tool-divider { width:1px;height:24px;flex:none;background:var(--fdc-line); }.tabs { display:flex;gap:4px;overflow:visible;scrollbar-width:none; }.tab:disabled { color:#a1a1a1;cursor:default; }.tab:disabled:hover { background:transparent; }
1119
+ .controls { min-height:212px;overflow:auto;background:var(--fdc-surface); }.inspector-heading { position:sticky;top:0;z-index:1;height:44px;display:flex;align-items:center;gap:8px;padding:0 12px;background:rgb(255 255 255 / 96%);border-bottom:1px solid var(--fdc-line);backdrop-filter:blur(8px); }.inspector-heading svg { width:16px;height:16px;color:#4d4d4d; }.inspector-heading strong { font-size:12px;font-weight:550; }.property-count { margin-left:auto;color:var(--fdc-muted);font:400 12px/1 var(--fdc-font);letter-spacing:.01em; }.property-section { padding:0;border-bottom:1px solid var(--fdc-line); }.section-head { width:100%;min-height:40px;display:flex;align-items:center;padding:0 8px 0 4px;background:white;color:#3f3f3f; }.section-head:hover { background:#fcfcfc; }.section-toggle { min-width:0;min-height:40px;flex:1;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer; }.section-toggle>svg { width:12px;height:12px;color:#858585;transition:transform .12s ease; }.property-section.collapsed .section-toggle>svg { transform:rotate(-90deg); }.section-head strong { font-size:12px;font-weight:500; }.section-grid { display:grid;gap:8px;padding:0 12px 12px; }.property-section.collapsed .section-grid { display:none; }.section-grid.two { grid-template-columns:1fr 1fr; }.section-grid.stacked .property-control { grid-template-columns:1fr;gap:8px; }.property-control { display:grid;grid-template-columns:minmax(0,1fr) 132px 24px;align-items:center;gap:8px;min-height:36px; }.property-label { overflow:hidden;text-overflow:ellipsis;color:#4d4d4d;font-size:12px;font-weight:400;white-space:nowrap; }.control-field { position:relative;display:flex;align-items:center;min-width:0;height:32px;border:1px solid var(--fdc-line);border-radius:4px;background:var(--fdc-paper);overflow:hidden;transition:border-color .12s ease,box-shadow .12s ease,background .12s ease; }.control-field:hover { background:var(--fdc-surface); }.control-field:focus-within { border-color:var(--fdc-signal);background:var(--fdc-surface);box-shadow:0 0 0 4px rgb(0 112 243 / 10%); }.control-reset { width:24px;height:24px;display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:transparent;color:#8a8a8a;cursor:pointer;opacity:0; }.property-control:hover .control-reset,.compact-control:hover .control-reset,.control-reset:focus-visible { opacity:1; }.control-reset:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.control-reset svg { width:12px;height:12px; }.compact-control { min-width:0;display:grid;grid-template-columns:minmax(0,1fr) 24px;gap:4px;align-items:center; }.compact-control .control-field { width:100%; }.field-prefix { min-width:28px;padding-left:8px;color:#7a7a7a;font:400 12px/1 var(--fdc-font); }.compact-control .field-prefix.wide { min-width:40px; }.property-control input,.property-control select,.compact-control input,.compact-control select { width:100%;min-width:0;height:32px;padding:0 8px;border:0;background:transparent;color:var(--fdc-ink);font:400 12px/1 var(--fdc-font);outline:none; }.property-control input[type="number"],.compact-control input[type="number"] { appearance:textfield; }.property-control input[type="number"]::-webkit-inner-spin-button,.property-control input[type="number"]::-webkit-outer-spin-button,.compact-control input[type="number"]::-webkit-inner-spin-button,.compact-control input[type="number"]::-webkit-outer-spin-button { margin:0;appearance:none; }.property-control select { font-family:var(--fdc-font); }.control-field .unit-select { width:40px;flex:none;padding:0 4px;color:#707070;font-size:8px;cursor:pointer; }[data-scrub-for] { cursor:ew-resize;user-select:none;touch-action:none; }.property-label[data-scrub-for]:hover,.field-prefix[data-scrub-for]:hover,[data-scrub-for].scrubbing { color:var(--fdc-signal); }.color-swatch { width:16px;height:16px;flex:none;margin-left:8px;border:1px solid rgb(0 0 0 / 10%);border-radius:4px;background:var(--swatch-color); }.color-swatch.transparent { background-color:white;background-image:linear-gradient(45deg,#d9d9d9 25%,transparent 25%),linear-gradient(-45deg,#d9d9d9 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#d9d9d9 75%),linear-gradient(-45deg,transparent 75%,#d9d9d9 75%);background-size:8px 8px;background-position:0 0,0 4px,4px -4px,-4px 0; }.color-value { overflow:hidden;text-overflow:ellipsis;margin-left:8px;color:#4d4d4d;font:400 12px/1 var(--fdc-font);white-space:nowrap; }.color-picker { position:absolute;inset:0;width:100%!important;height:100%!important;opacity:0;cursor:pointer; }.unit { padding-right:8px;color:#7a7a7a;font:400 12px/1 var(--fdc-font); }.sr-only { position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0; }
1120
+ .motion-list { padding:0 12px 12px; }.motion-row { padding:12px 0;border-bottom:1px solid var(--fdc-line); }.motion-title { display:flex;justify-content:space-between;gap:12px;margin-bottom:8px;font-size:12px;font-weight:550; }.motion-title code { color:var(--fdc-muted);font:400 12px/1.3 var(--fdc-font); }.motion-actions { display:grid;grid-template-columns:repeat(4,1fr);gap:4px; }.motion-actions button { min-height:32px;padding:0 4px;border:1px solid var(--fdc-line);background:var(--fdc-paper);border-radius:4px;color:var(--fdc-ink);font-size:12px;font-weight:400;cursor:pointer; }.motion-actions button:hover { border-color:#c7c7c7;background:var(--fdc-surface); }
1121
+ .motion-timeline { width:100%;margin:4px 0 12px;accent-color:var(--fdc-signal); }.motion-fields { display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:8px; }.motion-fields label { display:grid;grid-template-columns:auto 1fr;align-items:center;gap:4px;color:var(--fdc-muted);font-size:8px; }.motion-fields input { width:100%;height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:var(--fdc-paper);color:var(--fdc-ink);font-size:12px; }
1122
+ .empty { padding:48px 28px;text-align:center;color:var(--fdc-muted);font-size:12px;line-height:1.6; }.empty::before { content:"\u2316";display:grid;place-items:center;width:40px;height:40px;margin:0 auto 12px;color:var(--fdc-signal);background:var(--fdc-signal-soft);border-radius:12px;font:20px/1 var(--fdc-font); }
1123
+ .change-dock { min-height:48px;display:grid;grid-template-columns:minmax(0,1fr) 32px 68px;align-items:center;gap:8px;padding:8px 8px;border-top:1px solid var(--fdc-line);background:white; }.change-dock[hidden] { display:none; }.change-dock-copy { min-width:0;padding-left:4px; }.change-dock-copy strong,.change-dock-copy span { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.change-dock-copy strong { font-size:12px;font-weight:550; }.change-dock-copy span { margin-top:4px;color:var(--fdc-muted);font-size:8px; }.change-dock button { height:32px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:var(--fdc-ink);font-size:8px;cursor:pointer; }.change-dock .dock-review { color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.change-dock svg { width:12px;height:12px; }.footer { display:grid;grid-template-columns:84px 1fr;gap:8px;padding:8px;background:var(--fdc-surface);border-top:1px solid var(--fdc-line); }.footer:has(.review[hidden]) { grid-template-columns:1fr; }.footer button[hidden] { display:none; }.footer button { min-height:36px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-surface);color:var(--fdc-ink);font-size:12px;font-weight:450;cursor:pointer; }.footer button:hover { border-color:#d0d0d0;background:var(--fdc-paper); }.footer .review { align-items:center;justify-content:center;gap:8px;color:white;background:var(--fdc-ink);border-color:var(--fdc-ink); }.footer .review:not([hidden]) { display:flex; }.footer .review:hover { background:#2f2f2f; }.change-count { min-width:20px;height:20px;display:inline-grid;place-items:center;padding:0 4px;color:var(--fdc-ink);background:white;border-radius:1000px;font:500 8px/1 var(--fdc-font); }.change-count[hidden] { display:none; }
1124
+ .review-view { min-height:0;flex:1;display:none;flex-direction:column;background:var(--fdc-surface); }.panel.reviewing .selection,.panel.reviewing .scope,.panel.reviewing .controls,.panel.reviewing>.footer,.panel.reviewing>.change-dock { display:none; }.panel.reviewing .review-view { display:flex; }.review-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 12px;border-bottom:1px solid var(--fdc-line); }.review-head button { width:32px;height:32px;display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.review-head button:hover { background:var(--fdc-subtle);color:var(--fdc-ink); }.review-head svg { width:16px;height:16px; }.review-head strong { font-size:12px;font-weight:550; }.review-head span { margin-left:auto;color:var(--fdc-muted);font-size:12px; }.review-body { min-height:160px;overflow-x:hidden;overflow-y:auto; }.review-toolbar { position:sticky;top:0;z-index:1;display:flex;gap:4px;padding:8px 8px;border-bottom:1px solid var(--fdc-line);background:rgb(255 255 255 / 96%);backdrop-filter:blur(8px); }.review-toolbar button { height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#555;font-size:8px;cursor:pointer; }.review-toolbar button:last-child { margin-left:auto; }.review-empty { padding:44px 24px;color:var(--fdc-muted);font-size:12px;line-height:1.55;text-align:center; }.review-group { border-bottom:1px solid var(--fdc-line); }.review-group-title { width:100%;min-height:36px;display:flex;align-items:center;gap:8px;padding:0 12px;border:0;background:white;color:var(--fdc-muted);font-size:12px;font-weight:500;text-align:left;cursor:pointer; }.review-group-title span { margin-left:auto;font-size:8px; }.review-group-title svg { width:12px;height:12px;transition:transform .12s ease; }.review-group.collapsed .review-group-title svg { transform:rotate(-90deg); }.review-group.collapsed .review-card { display:none; }.review-card { display:grid;grid-template-columns:20px minmax(0,1fr);gap:8px;padding:8px 12px 12px; }.review-card.rejected { opacity:.62; }.review-card+.review-card { border-top:1px solid var(--fdc-line); }.review-card input[type="checkbox"] { width:16px;height:16px;margin:4px 0 0;accent-color:var(--fdc-ink); }.review-card-main { min-width:0; }.review-card-line { display:flex;align-items:center;gap:8px; }.review-card-line strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:12px;font-weight:500;white-space:nowrap; }.review-card-tools { display:flex;gap:4px;margin-left:auto; }.review-card-tools button { height:24px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#666;font-size:8px;cursor:pointer; }.confidence-pill { flex:none;padding:4px 4px;border-radius:4px;background:#edf6ff;color:#0761d1;font-size:8px;text-transform:capitalize; }.confidence-pill.unresolved { color:#984a2b;background:#fff0e8; }.review-values { display:grid;grid-template-columns:minmax(0,1fr) 12px minmax(0,1fr);align-items:center;gap:4px;margin-top:8px; }.review-before { overflow:hidden;text-overflow:ellipsis;padding:8px;color:var(--fdc-muted);background:var(--fdc-subtle);border-radius:4px;font-size:12px;white-space:nowrap; }.review-values>span { color:var(--fdc-muted);font-size:12px;text-align:center; }.review-after { width:100%;height:28px;min-width:0;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;font-size:12px;outline:none; }.review-after:focus { border-color:var(--fdc-signal);box-shadow:0 0 0 4px rgb(0 112 243 / 10%); }.review-source { margin-top:8px;overflow-wrap:anywhere;color:var(--fdc-muted);font-size:8px;line-height:1.45; }.review-actions { display:grid;grid-template-columns:84px 1fr;gap:8px;padding:8px;border-top:1px solid var(--fdc-line); }.review-actions button { min-height:36px;border:1px solid var(--fdc-line);border-radius:8px;background:white;font-size:12px;cursor:pointer; }.review-actions .apply { color:white;background:var(--fdc-ink);border-color:var(--fdc-ink); }.review-actions button:disabled { opacity:.45;cursor:not-allowed; }.run-summary { padding:16px 12px;border-bottom:1px solid var(--fdc-line); }.run-state { display:flex;align-items:center;gap:8px; }.run-state i { width:8px;height:8px;border-radius:50%;background:#a3a3a3; }.run-state i.active { background:var(--fdc-signal);box-shadow:0 0 0 4px rgb(0 112 243 / 10%); }.run-state i.passed { background:#2ca67f; }.run-state i.attention { background:#d16d51; }.run-state strong { font-size:12px;font-weight:550;text-transform:capitalize; }.run-summary p { margin:8px 0 0;color:var(--fdc-muted);font-size:12px;line-height:1.5; }.run-steps { padding:4px 12px 12px; }.run-step { display:grid;grid-template-columns:20px minmax(0,1fr);gap:8px;padding:8px 0;border-bottom:1px solid var(--fdc-line); }.run-step:last-child { border-bottom:0; }.run-step span:first-child { color:var(--fdc-muted);font-size:12px; }.run-step strong { display:block;font-size:12px;font-weight:500;text-transform:capitalize; }.run-step p { margin:4px 0 0;color:var(--fdc-muted);font-size:8px;line-height:1.45; }.result-list { padding:0 12px 12px; }.result-row { display:flex;align-items:flex-start;justify-content:space-between;gap:8px;padding:8px 0;border-top:1px solid var(--fdc-line);font-size:12px; }.result-row span:last-child { color:var(--fdc-muted);text-align:right; }.result-row.pass span:first-child { color:#23715c; }.result-row.fail span:first-child { color:#a24d30; }.run-files { padding:0 12px 12px;color:var(--fdc-muted);font-size:8px;line-height:1.5; }.run-files code { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
1125
+ .toast { position:fixed;left:50%;bottom:76px;transform:translate(-50%,8px);padding:8px 12px;background:var(--fdc-ink);color:white;border-radius:8px;font-size:12px;font-weight:450;opacity:0;transition:.15s ease;pointer-events:none;white-space:nowrap;box-shadow:0 8px 20px rgb(0 0 0 / 16%); }.toast.show { opacity:1;transform:translate(-50%,0); }
1126
+ .resize-handle { position:absolute;width:8px;height:8px;min-width:8px;min-height:8px;aspect-ratio:1;padding:0;border:1px solid #f0f1f3;border-radius:1px;background:var(--fdc-signal);box-shadow:0 1px 4px rgb(0 0 0 / 28%);appearance:none;pointer-events:auto;touch-action:none; }
1127
+ .resize-handle[data-handle="n"]{top:-4px;left:calc(50% - 4px);cursor:ns-resize}.resize-handle[data-handle="s"]{bottom:-4px;left:calc(50% - 4px);cursor:ns-resize}.resize-handle[data-handle="e"]{right:-4px;top:calc(50% - 4px);cursor:ew-resize}.resize-handle[data-handle="w"]{left:-4px;top:calc(50% - 4px);cursor:ew-resize}.resize-handle[data-handle="ne"]{right:-4px;top:-4px;cursor:nesw-resize}.resize-handle[data-handle="nw"]{left:-4px;top:-4px;cursor:nwse-resize}.resize-handle[data-handle="se"]{right:-4px;bottom:-4px;cursor:nwse-resize}.resize-handle[data-handle="sw"]{left:-4px;bottom:-4px;cursor:nesw-resize}
1128
+ .panel-resizer { position:absolute;z-index:3;top:84px;bottom:0;left:-4px;width:8px;border:0;background:transparent;cursor:ew-resize;touch-action:none; }.panel-resizer::after { content:"";position:absolute;top:50%;left:4px;width:4px;height:28px;transform:translateY(-50%);border-radius:4px;background:#4a4a50;opacity:0;transition:opacity .12s ease; }.panel:hover .panel-resizer::after,.panel-resizer:focus-visible::after { opacity:1; }.radius-handle { position:absolute;top:8px;left:8px;width:12px;height:12px;min-width:12px;min-height:12px;aspect-ratio:1;padding:0;border:4px solid #f0f1f3;border-radius:50%;background:#ff4d8d;box-shadow:0 1px 4px rgb(0 0 0 / 28%);appearance:none;pointer-events:auto;cursor:nwse-resize;touch-action:none; }
1129
+ .canvas-variant { position:fixed;z-index:2147483645;height:28px;max-width:180px;padding:0 24px 0 8px;border:1px solid #b8d5ff;border-radius:8px;background:white;color:#075fc5;font-size:8px;box-shadow:0 4px 16px rgb(0 0 0 / 10%);pointer-events:auto; }.canvas-variant[hidden] { display:none; }
1130
+ .onboarding-card { position:fixed;z-index:2147483647;left:50%;bottom:80px;width:288px;transform:translateX(-50%);padding:12px;border:1px solid var(--fdc-line);border-radius:12px;background:white;box-shadow:0 12px 32px rgb(0 0 0 / 14%);pointer-events:auto; }.onboarding-card[hidden] { display:none; }.onboarding-card-head { display:flex;align-items:center;gap:8px; }.onboarding-card-head svg { width:16px;height:16px;color:var(--fdc-signal); }.onboarding-card-head strong { font-size:12px;font-weight:550; }.onboarding-card p { margin:8px 0 12px;color:var(--fdc-muted);font-size:12px;line-height:1.5; }.onboarding-steps { display:grid;grid-template-columns:repeat(3,1fr);gap:4px; }.onboarding-steps span { padding:8px 4px;border:1px solid var(--fdc-line);border-radius:8px;color:#555;font-size:8px;line-height:1.35;text-align:center; }.onboarding-actions { display:flex;justify-content:flex-end;gap:4px;margin-top:12px; }.onboarding-actions button { height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;font-size:8px;cursor:pointer; }.onboarding-actions .onboarding-start { color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }
1131
+ .review-details { margin-top:8px;color:var(--fdc-muted);font-size:8px; }.review-details summary { cursor:pointer;user-select:none; }.review-details[open] summary { margin-bottom:4px; }.review-details .review-source { display:block; }.review-details .impact-list { display:grid;gap:4px;margin-top:4px; }
1055
1132
  @keyframes fdc-pulse { 50% { opacity:.35; } }
1056
1133
  @media (prefers-reduced-motion:reduce){.session-status i,.section-head>svg,.toast,.tool-select::after,.tab::after{animation:none!important;transition:none!important}}
1057
1134
  .multi-outline { position:fixed;z-index:2147483644;border:1px dashed var(--fdc-signal);background:rgb(0 112 243 / 4%);pointer-events:none; }
1058
1135
  .hover-outline { position:fixed;z-index:2147483643;border:1px solid rgb(0 112 243 / 62%);background:rgb(0 112 243 / 4%);pointer-events:none; }
1059
- .hover-outline::after { content:attr(data-label);position:absolute;left:-1px;top:-1px;transform:translateY(-100%);max-width:180px;padding:4px 6px;border-radius:4px 4px 4px 0;background:#0070f3;color:white;font:500 10px/1.2 var(--fdc-font);overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
1136
+ .hover-outline::after { content:attr(data-label);position:absolute;left:-1px;top:-1px;transform:translateY(-100%);max-width:180px;padding:4px 8px;border-radius:4px 4px 4px 0;background:#0070f3;color:white;font:500 12px/1.2 var(--fdc-font);overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
1060
1137
  .snap-guide { position:fixed;z-index:2147483644;pointer-events:none;background:#ff4d8d;box-shadow:0 0 0 1px rgb(255 255 255 / 80%); }.snap-guide.vertical { width:1px;top:0;bottom:0; }.snap-guide.horizontal { height:1px;left:0;right:0; }
1061
- .spacing-guide { position:fixed;z-index:2147483644;pointer-events:auto;background:#ff4d8d; }.spacing-guide.horizontal { height:1px;cursor:ew-resize; }.spacing-guide.vertical { width:1px;cursor:ns-resize; }.spacing-guide span { position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);padding:2px 4px;border-radius:3px;background:#ff4d8d;color:white;font:600 8px/1 var(--fdc-font);white-space:nowrap; }
1062
- .selection-path { display:flex;align-items:center;gap:4px;margin-top:9px;min-width:0; }.selection-path button { min-width:0;height:25px;display:flex;align-items:center;gap:4px;padding:0 7px;border:1px solid var(--fdc-line);border-radius:5px;background:var(--fdc-paper);color:#555;font-size:9px;cursor:pointer; }.selection-path button:hover { color:var(--fdc-ink);border-color:#d2d2d2;background:white; }.selection-path button:disabled { opacity:.4;cursor:default; }.selection-path svg { width:11px;height:11px; }.selection-path .path-name { flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
1138
+ .spacing-guide { position:fixed;z-index:2147483644;pointer-events:auto;background:#ff4d8d; }.spacing-guide.horizontal { height:1px;cursor:ew-resize; }.spacing-guide.vertical { width:1px;cursor:ns-resize; }.spacing-guide span { position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);padding:4px 4px;border-radius:4px;background:#ff4d8d;color:white;font:600 8px/1 var(--fdc-font);white-space:nowrap; }
1139
+ .selection-path { display:flex;align-items:center;gap:4px;margin-top:8px;min-width:0; }.selection-path button { min-width:0;height:24px;display:flex;align-items:center;gap:4px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:var(--fdc-paper);color:#555;font-size:8px;cursor:pointer; }.selection-path button:hover { color:var(--fdc-ink);border-color:#d2d2d2;background:white; }.selection-path button:disabled { opacity:.4;cursor:default; }.selection-path svg { width:12px;height:12px; }.selection-path .path-name { flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
1063
1140
  .selection-path[hidden] { display:none; }
1064
- .layers-panel { position:fixed;z-index:2147483646;top:12px;left:12px;width:252px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:10px;background:var(--fdc-surface);box-shadow:0 1px 2px rgb(0 0 0 / 5%),0 10px 28px rgb(0 0 0 / 10%);pointer-events:auto; }.layers-panel[hidden] { display:none; }.layers-head { min-height:44px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.layers-head svg { width:15px;height:15px; }.layers-head strong { font-size:12px;font-weight:550; }.layers-head span { color:var(--fdc-muted);font-size:9px; }.layers-head .icon-button { margin-left:auto; }.layers-search { padding:8px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.layers-search input { width:100%;height:30px;padding:0 9px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:var(--fdc-ink);font-size:10px;outline:none; }.layers-search input:focus { border-color:var(--fdc-signal);box-shadow:0 0 0 2px rgb(0 112 243 / 10%); }.layer-tree { min-height:120px;overflow:auto;padding:5px; }.layer-row { width:100%;height:30px;display:grid;grid-template-columns:14px 14px minmax(0,1fr) auto;align-items:center;gap:4px;padding:0 7px 0 calc(7px + var(--layer-depth) * 12px);border:0;border-radius:5px;background:transparent;color:#474747;text-align:left;cursor:pointer; }.layer-row:hover { background:var(--fdc-subtle); }.layer-row.selected { color:#075fc5;background:#eaf3ff; }.layer-row .chevron,.layer-row .layer-icon { width:12px;height:12px;color:#8a8a8a; }.layer-row .layer-label { overflow:hidden;text-overflow:ellipsis;font-size:10px;white-space:nowrap; }.layer-row .layer-meta { padding:2px 4px;border-radius:3px;background:#f0f0f0;color:#747474;font-size:8px;text-transform:uppercase; }.layer-row.selected .layer-meta { color:#075fc5;background:#d8e9ff; }.layers-empty { padding:34px 18px;color:var(--fdc-muted);font-size:10px;line-height:1.5;text-align:center; }
1065
- .layers-switch { display:grid;grid-template-columns:1fr 1fr;gap:3px;padding:5px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.layers-switch button { min-width:0;height:28px;display:flex;align-items:center;justify-content:center;gap:6px;padding:0 7px;border:0;border-radius:5px;background:transparent;color:var(--fdc-muted);font-size:10px;cursor:pointer; }.layers-switch button:hover { color:var(--fdc-ink);background:white; }.layers-switch button.active { color:var(--fdc-ink);background:white;box-shadow:0 0 0 1px var(--fdc-line),0 1px 2px rgb(0 0 0 / 5%); }.layers-switch button span { min-width:17px;height:17px;display:grid;place-items:center;padding:0 4px;border-radius:999px;background:var(--fdc-subtle);color:#747474;font-size:8px; }.layers-switch button[data-layer-view="components"].active { color:#5f46bf; }.layers-switch button[data-layer-view="components"].active span { color:#5f46bf;background:var(--fdc-component-soft); }.component-list { display:grid;gap:5px;padding:2px; }.component-card { overflow:hidden;border:1px solid var(--fdc-line);border-radius:7px;background:white; }.component-card:hover { border-color:#d7d0f3;box-shadow:0 2px 8px rgb(52 38 110 / 6%); }.component-card.selected { border-color:#c8bdf1;background:#fbfaff;box-shadow:0 0 0 2px rgb(114 87 217 / 8%); }.component-main { width:100%;min-height:52px;display:grid;grid-template-columns:30px minmax(0,1fr) auto;align-items:center;gap:7px;padding:7px 8px;border:0;background:transparent;color:var(--fdc-ink);text-align:left;cursor:pointer; }.component-main:disabled { cursor:default; }.component-mark { width:28px;height:28px;display:grid;place-items:center;border-radius:7px;color:var(--fdc-component);background:var(--fdc-component-soft); }.component-mark svg { width:14px;height:14px; }.component-copy { min-width:0; }.component-copy strong,.component-copy span { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.component-copy strong { font-size:10px;font-weight:550; }.component-copy span { margin-top:4px;color:var(--fdc-muted);font-size:8px; }.component-status { display:flex;flex-direction:column;align-items:flex-end;gap:4px; }.component-status span { padding:2px 5px;border-radius:999px;color:#5f46bf;background:var(--fdc-component-soft);font-size:8px;white-space:nowrap; }.component-status small { color:#8b8b8b;font-size:8px;white-space:nowrap; }.component-variants { display:flex;gap:4px;overflow:hidden;padding:0 8px 8px 45px; }.component-variants span { max-width:88px;overflow:hidden;text-overflow:ellipsis;padding:3px 5px;border:1px solid #e6e1f7;border-radius:4px;color:#66598c;background:#faf9ff;font-size:8px;white-space:nowrap; }
1066
- .layer-row { grid-template-columns:16px minmax(0,1fr);gap:1px;padding-right:4px;cursor:default; }.layer-row.dragging { opacity:.45; }.layer-row.drop-target { box-shadow:inset 0 2px 0 var(--fdc-signal); }.layer-spacer { width:1px;pointer-events:none; }.layer-toggle { width:16px;height:28px;display:grid;place-items:center;padding:0;border:0;background:transparent;color:#858585;cursor:pointer; }.layer-toggle:disabled { visibility:hidden; }.layer-toggle svg { width:11px;height:11px; }.layer-select { min-width:0;height:28px;display:grid;grid-template-columns:14px minmax(0,1fr) auto;align-items:center;gap:5px;padding:0 4px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer; }
1067
- .health-panel { position:fixed;z-index:2147483646;top:12px;left:12px;width:304px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:10px;background:var(--fdc-surface);box-shadow:0 1px 2px rgb(0 0 0 / 5%),0 10px 28px rgb(0 0 0 / 10%);pointer-events:auto; }.health-panel[hidden] { display:none; }.health-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.health-head>svg { width:15px;height:15px; }.health-head strong { font-size:12px;font-weight:550; }.health-head .icon-button { margin-left:auto; }.health-summary { display:grid;grid-template-columns:54px minmax(0,1fr);gap:10px;padding:12px;border-bottom:1px solid var(--fdc-line); }.health-score { width:54px;height:54px;display:grid;place-items:center;border-radius:50%;background:conic-gradient(var(--score-color) calc(var(--score) * 1%),#ececec 0); }.health-score::before { content:"";grid-area:1/1;width:42px;height:42px;border-radius:50%;background:white; }.health-score strong { z-index:1;grid-area:1/1;font-size:15px;font-weight:600; }.health-summary-copy { min-width:0;align-self:center; }.health-summary-copy strong { display:block;font-size:11px;font-weight:550; }.health-summary-copy span { display:block;margin-top:4px;color:var(--fdc-muted);font-size:9px;line-height:1.4; }.health-filters { display:flex;gap:4px;padding:7px 8px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.health-filters button { min-height:27px;padding:0 8px;border:1px solid transparent;border-radius:5px;background:transparent;color:#666;font-size:9px;cursor:pointer; }.health-filters button:hover,.health-filters button.active { border-color:var(--fdc-line);background:white;color:var(--fdc-ink); }.health-list { min-height:120px;overflow:auto;padding:6px; }.health-card { padding:10px;border:1px solid var(--fdc-line);border-radius:7px;background:white; }.health-card+.health-card { margin-top:6px; }.health-card-top { display:flex;align-items:center;gap:6px; }.health-severity { width:7px;height:7px;flex:none;border-radius:50%;background:#a3a3a3; }.health-severity.high { background:#d15d43; }.health-severity.medium { background:#d69b3c; }.health-severity.low { background:#4b84cb; }.health-card-top strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:10px;font-weight:550;white-space:nowrap; }.health-card-top span:last-child { margin-left:auto;color:var(--fdc-muted);font-size:8px;text-transform:capitalize; }.health-card p { margin:7px 0 0;color:#5d5d5d;font-size:9px;line-height:1.45; }.health-evidence { margin-top:6px;padding:6px;border-radius:4px;background:var(--fdc-paper);color:#777;font-size:8px;line-height:1.4; }.health-actions { display:flex;gap:5px;margin-top:8px; }.health-actions button { min-height:27px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#555;font-size:9px;cursor:pointer; }.health-actions button:hover { border-color:#c8c8c8;color:var(--fdc-ink); }.health-actions .health-fix { margin-left:auto;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.health-actions .health-fix.previewed { color:#23715c;border-color:#bcded2;background:#edf8f4;cursor:default; }.health-actions .health-fix:disabled { opacity:1; }.health-actions .health-ignore { padding:0 6px;color:#888;border-color:transparent; }.health-footer { display:flex;align-items:center;gap:5px;padding:8px;border-top:1px solid var(--fdc-line); }.health-footer button { min-height:30px;padding:0 9px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#555;font-size:9px;cursor:pointer; }.health-footer .health-rescan { flex:1;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.health-empty { padding:36px 18px;text-align:center;color:var(--fdc-muted);font-size:10px;line-height:1.5; }.health-empty svg { display:block;width:22px;height:22px;margin:0 auto 10px;color:#2b9a76; }
1141
+ .layers-panel { position:fixed;z-index:2147483646;top:12px;left:12px;width:252px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:12px;background:var(--fdc-surface);box-shadow:0 1px 4px rgb(0 0 0 / 5%),0 12px 28px rgb(0 0 0 / 10%);pointer-events:auto; }.layers-panel[hidden] { display:none; }.layers-head { min-height:44px;display:flex;flex:none;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.layers-head svg { width:16px;height:16px; }.layers-head strong { font-size:12px;font-weight:550; }.layers-head span { color:var(--fdc-muted);font-size:8px; }.layers-head .icon-button { margin-left:auto; }.layers-search { flex:none;padding:8px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.layers-search input { width:100%;height:32px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:var(--fdc-ink);font-size:12px;outline:none; }.layers-search input:focus { border-color:var(--fdc-signal);box-shadow:0 0 0 4px rgb(0 112 243 / 10%); }.layer-tree { min-height:120px;overflow:auto;padding:4px; }.layer-row { width:100%;height:32px;display:grid;grid-template-columns:16px 16px minmax(0,1fr) auto;align-items:center;gap:4px;padding:0 8px 0 calc(8px + var(--layer-depth) * 12px);border:0;border-radius:4px;background:transparent;color:#474747;text-align:left;cursor:pointer; }.layer-row:hover { background:var(--fdc-subtle); }.layer-row.selected { color:#075fc5;background:#eaf3ff; }.layer-row .chevron,.layer-row .layer-icon { width:12px;height:12px;color:#8a8a8a; }.layer-row .layer-label { overflow:hidden;text-overflow:ellipsis;font-size:12px;white-space:nowrap; }.layer-row .layer-meta { padding:4px 4px;border-radius:4px;background:#f0f0f0;color:#747474;font-size:8px;text-transform:uppercase; }.layer-row.selected .layer-meta { color:#075fc5;background:#d8e9ff; }.layers-empty { padding:36px 20px;color:var(--fdc-muted);font-size:12px;line-height:1.5;text-align:center; }
1142
+ .layers-switch { display:grid;grid-template-columns:1fr 1fr;gap:4px;padding:4px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.layers-switch button { min-width:0;height:28px;display:flex;align-items:center;justify-content:center;gap:8px;padding:0 8px;border:0;border-radius:4px;background:transparent;color:var(--fdc-muted);font-size:12px;cursor:pointer; }.layers-switch button:hover { color:var(--fdc-ink);background:white; }.layers-switch button.active { color:var(--fdc-ink);background:white;box-shadow:0 0 0 1px var(--fdc-line),0 1px 4px rgb(0 0 0 / 5%); }.layers-switch button span { min-width:16px;height:16px;display:grid;place-items:center;padding:0 4px;border-radius:1000px;background:var(--fdc-subtle);color:#747474;font-size:8px; }.layers-switch button[data-layer-view="components"].active { color:#5f46bf; }.layers-switch button[data-layer-view="components"].active span { color:#5f46bf;background:var(--fdc-component-soft); }.component-list { display:grid;gap:4px;padding:4px; }.component-card { overflow:hidden;border:1px solid var(--fdc-line);border-radius:8px;background:white; }.component-card:hover { border-color:#d7d0f3;box-shadow:0 4px 8px rgb(52 38 110 / 6%); }.component-card.selected { border-color:#c8bdf1;background:#fbfaff;box-shadow:0 0 0 4px rgb(114 87 217 / 8%); }.component-main { width:100%;min-height:52px;display:grid;grid-template-columns:32px minmax(0,1fr) auto;align-items:center;gap:8px;padding:8px 8px;border:0;background:transparent;color:var(--fdc-ink);text-align:left;cursor:pointer; }.component-main:disabled { cursor:default; }.component-mark { width:28px;height:28px;display:grid;place-items:center;border-radius:8px;color:var(--fdc-component);background:var(--fdc-component-soft); }.component-mark svg { width:16px;height:16px; }.component-copy { min-width:0; }.component-copy strong,.component-copy span { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.component-copy strong { font-size:12px;font-weight:550; }.component-copy span { margin-top:4px;color:var(--fdc-muted);font-size:8px; }.component-status { display:flex;flex-direction:column;align-items:flex-end;gap:4px; }.component-status span { padding:4px 4px;border-radius:1000px;color:#5f46bf;background:var(--fdc-component-soft);font-size:8px;white-space:nowrap; }.component-status small { color:#8b8b8b;font-size:8px;white-space:nowrap; }.component-variants { display:flex;gap:4px;overflow:hidden;padding:0 8px 8px 44px; }.component-variants span { max-width:88px;overflow:hidden;text-overflow:ellipsis;padding:4px 4px;border:1px solid #e6e1f7;border-radius:4px;color:#66598c;background:#faf9ff;font-size:8px;white-space:nowrap; }
1143
+ .layer-tree { position:relative;scrollbar-gutter:stable; }.layer-selection-glide { position:absolute;z-index:0;top:0;right:4px;left:4px;height:32px;border:1px solid rgb(72 132 220 / 22%);border-radius:8px;background:var(--fdc-signal-soft);transform:translateY(var(--layer-glide-y));transition:transform .24s cubic-bezier(.16,1,.3,1),height .18s cubic-bezier(.16,1,.3,1);pointer-events:none; }.layer-row { position:relative;z-index:1;grid-template-columns:16px minmax(0,1fr);gap:1px;padding-right:4px;cursor:default; }.layer-row.entering { animation:layer-row-enter .22s cubic-bezier(.16,1,.3,1) both;animation-delay:min(calc(var(--layer-position) * 18ms),90ms); }.layer-row.selected { background:transparent; }.layer-row.dragging { opacity:.45; }.layer-row.drop-target { box-shadow:inset 0 4px 0 var(--fdc-signal); }.layer-branch { position:absolute;z-index:-1;top:-1px;bottom:-1px;left:var(--layer-branch-left);width:1px;background:var(--fdc-line);transform-origin:top;animation:layer-branch-draw .28s cubic-bezier(.16,1,.3,1) both;pointer-events:none; }.layer-spacer { width:1px;pointer-events:none; }.layer-toggle { width:16px;height:28px;display:grid;place-items:center;padding:0;border:0;background:transparent;color:#858585;cursor:pointer;transition:color .16s ease; }.layer-toggle:hover { color:var(--fdc-ink); }.layer-toggle:disabled { visibility:hidden; }.layer-toggle svg { width:12px;height:12px;transition:transform .24s cubic-bezier(.16,1,.3,1); }.layer-select { min-width:0;height:28px;display:grid;grid-template-columns:16px minmax(0,1fr) auto;align-items:center;gap:4px;padding:0 4px;border:0;border-radius:4px;background:transparent;color:inherit;text-align:left;cursor:pointer;outline:none; }.layer-select:focus-visible { box-shadow:inset 0 0 0 1px var(--fdc-signal); }.layer-select:active .layer-icon { transform:scale(.88); }.layer-icon { transition:color .16s ease,transform .16s cubic-bezier(.16,1,.3,1); }@keyframes layer-row-enter { from { opacity:0;transform:translateY(-4px); } to { opacity:1;transform:translateY(0); } }@keyframes layer-branch-draw { from { opacity:0;transform:scaleY(0); } to { opacity:1;transform:scaleY(1); } }
1144
+ .health-panel { position:fixed;z-index:2147483646;top:12px;left:12px;width:304px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:12px;background:var(--fdc-surface);box-shadow:0 1px 4px rgb(0 0 0 / 5%),0 12px 28px rgb(0 0 0 / 10%);pointer-events:auto; }.health-panel[hidden] { display:none; }.health-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.health-head>svg { width:16px;height:16px; }.health-head strong { font-size:12px;font-weight:550; }.health-head .icon-button { margin-left:auto; }.health-summary { display:grid;grid-template-columns:56px minmax(0,1fr);gap:12px;padding:12px;border-bottom:1px solid var(--fdc-line); }.health-score { width:56px;height:56px;display:grid;place-items:center;border-radius:50%;background:conic-gradient(var(--score-color) calc(var(--score) * 1%),#ececec 0); }.health-score::before { content:"";grid-area:1/1;width:44px;height:44px;border-radius:50%;background:white; }.health-score strong { z-index:1;grid-area:1/1;font-size:16px;font-weight:600; }.health-summary-copy { min-width:0;align-self:center; }.health-summary-copy strong { display:block;font-size:12px;font-weight:550; }.health-summary-copy span { display:block;margin-top:4px;color:var(--fdc-muted);font-size:8px;line-height:1.4; }.health-filters { display:flex;gap:4px;padding:8px 8px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.health-filters button { min-height:28px;padding:0 8px;border:1px solid transparent;border-radius:4px;background:transparent;color:#666;font-size:8px;cursor:pointer; }.health-filters button:hover,.health-filters button.active { border-color:var(--fdc-line);background:white;color:var(--fdc-ink); }.health-list { min-height:120px;overflow:auto;padding:8px; }.health-card { padding:12px;border:1px solid var(--fdc-line);border-radius:8px;background:white; }.health-card+.health-card { margin-top:8px; }.health-card-top { display:flex;align-items:center;gap:8px; }.health-severity { width:8px;height:8px;flex:none;border-radius:50%;background:#a3a3a3; }.health-severity.high { background:#d15d43; }.health-severity.medium { background:#d69b3c; }.health-severity.low { background:#4b84cb; }.health-card-top strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:12px;font-weight:550;white-space:nowrap; }.health-card-top span:last-child { margin-left:auto;color:var(--fdc-muted);font-size:8px;text-transform:capitalize; }.health-card p { margin:8px 0 0;color:#5d5d5d;font-size:8px;line-height:1.45; }.health-evidence { margin-top:8px;padding:8px;border-radius:4px;background:var(--fdc-paper);color:#777;font-size:8px;line-height:1.4; }.health-actions { display:flex;gap:4px;margin-top:8px; }.health-actions button { min-height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#555;font-size:8px;cursor:pointer; }.health-actions button:hover { border-color:#c8c8c8;color:var(--fdc-ink); }.health-actions .health-fix { margin-left:auto;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.health-actions .health-fix.previewed { color:#23715c;border-color:#bcded2;background:#edf8f4;cursor:default; }.health-actions .health-fix:disabled { opacity:1; }.health-actions .health-ignore { padding:0 8px;color:#888;border-color:transparent; }.health-footer { display:flex;align-items:center;gap:4px;padding:8px;border-top:1px solid var(--fdc-line); }.health-footer button { min-height:32px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#555;font-size:8px;cursor:pointer; }.health-footer .health-rescan { flex:1;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.health-empty { padding:36px 20px;text-align:center;color:var(--fdc-muted);font-size:12px;line-height:1.5; }.health-empty svg { display:block;width:24px;height:24px;margin:0 auto 12px;color:#2b9a76; }
1068
1145
  .tool-select:disabled { color:#b6b6b6;cursor:default; }.tool-select:disabled:hover { background:transparent; }
1069
- .token-row { grid-column:2;display:flex;flex-wrap:wrap;gap:5px;margin-top:7px; }.token-chip { height:24px;padding:0 7px;border:1px solid var(--fdc-line);border-radius:999px;background:var(--fdc-paper);color:#4d4d4d;font-size:9px;cursor:pointer; }.token-chip:hover { border-color:#b7d5ff;color:#0761d1;background:#edf6ff; }
1070
- .section-head .section-action { width:24px;height:24px;display:grid;place-items:center;margin-left:auto;padding:0;border:0;border-radius:4px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.section-head .section-action:hover,.section-head .section-action.active { color:var(--fdc-signal);background:#edf6ff; }.section-head .section-action svg { width:13px;height:13px; }
1071
- .context-tools { display:flex;flex-wrap:wrap;gap:5px;padding:8px 12px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-surface); }.context-tools button { min-height:28px;display:flex;align-items:center;gap:5px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#4d4d4d;font-size:9px;cursor:pointer; }.context-tools button:hover { border-color:#c8c8c8;color:var(--fdc-ink); }.context-tools button.active { color:#075fc5;border-color:#bad7ff;background:#edf6ff; }.context-tools svg { width:12px;height:12px; }
1072
- .native-panel { padding:10px 12px;border-bottom:1px solid var(--fdc-line); }.native-panel-head { display:flex;align-items:center;margin-bottom:7px; }.native-panel-head strong { font-size:10px;font-weight:550; }.native-panel-head span { margin-left:auto;color:var(--fdc-muted);font-size:9px; }.native-search { width:100%;height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:5px;background:var(--fdc-paper);font-size:9px;outline:none; }.native-search:focus { border-color:var(--fdc-signal); }.native-grid { display:flex;flex-wrap:wrap;gap:5px;margin-top:7px; }.native-chip { min-height:26px;display:flex;align-items:center;gap:5px;padding:0 7px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#4d4d4d;font-size:9px;cursor:pointer; }.native-chip:hover { border-color:#bdd7fb;background:#f5f9ff; }.native-chip .swatch { width:12px;height:12px;border:1px solid rgb(0 0 0 / 10%);border-radius:3px;background:var(--token-color); }.design-health { display:flex;align-items:center;gap:6px;margin-top:8px;padding:7px 8px;border-radius:5px;background:#f3f3f3;color:#575757;font-size:9px; }.design-health.pass { color:#23715c;background:#edf8f4; }.design-health.fail { color:#9a4930;background:#fff0e9; }.design-health svg { width:12px;height:12px; }
1073
- .variant-list { display:grid;gap:5px;margin-top:7px; }.variant-button { min-height:30px;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;font-size:9px;cursor:pointer; }.variant-button code { overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font-size:8px;white-space:nowrap; }
1074
- .compare-bar { position:fixed;z-index:2147483646;left:50%;bottom:78px;transform:translateX(-50%);display:flex;align-items:center;gap:5px;padding:6px;border:1px solid var(--fdc-line);border-radius:9px;background:white;box-shadow:0 8px 24px rgb(0 0 0 / 14%);pointer-events:auto; }.compare-bar[hidden] { display:none; }.compare-bar strong { padding:0 7px;font-size:10px;font-weight:550; }.compare-bar button { height:30px;display:flex;align-items:center;gap:5px;padding:0 8px;border:0;border-radius:5px;background:transparent;color:#555;font-size:9px;cursor:pointer; }.compare-bar button:hover,.compare-bar button.active { color:white;background:var(--fdc-ink); }.compare-bar svg { width:12px;height:12px; }.compare-bar input[type="range"] { width:96px;accent-color:var(--fdc-ink);cursor:ew-resize; }
1075
- .command-palette { position:fixed;z-index:2147483647;left:50%;top:18%;transform:translateX(-50%);width:min(480px,calc(100vw - 32px));overflow:hidden;border:1px solid #d8d8d8;border-radius:11px;background:white;box-shadow:0 24px 80px rgb(0 0 0 / 24%);pointer-events:auto; }.command-palette[hidden] { display:none; }.command-palette input { width:100%;height:46px;padding:0 14px;border:0;border-bottom:1px solid var(--fdc-line);font-size:12px;outline:none; }.command-list { max-height:320px;overflow:auto;padding:5px; }.command-item { width:100%;min-height:38px;display:flex;align-items:center;gap:9px;padding:0 10px;border:0;border-radius:6px;background:transparent;color:#333;text-align:left;font-size:11px;cursor:pointer; }.command-item:hover,.command-item.active { background:var(--fdc-subtle); }.command-item svg { width:14px;height:14px;color:#777; }.command-item small { margin-left:auto;color:#8a8a8a;font-size:9px; }
1076
- .comparison-stage { position:fixed;z-index:2147483647;inset:10px;display:flex;flex-direction:column;overflow:hidden;border:1px solid #303030;border-radius:12px;background:#111;box-shadow:0 24px 80px rgb(0 0 0 / 35%);pointer-events:auto; }.comparison-stage[hidden] { display:none; }.comparison-stage header { min-height:46px;display:flex;align-items:center;padding:0 8px 0 14px;color:white;border-bottom:1px solid #292929;background:#171717; }.comparison-stage header strong { font-size:12px;font-weight:550; }.comparison-stage header span { margin-left:8px;color:#8d8d8d;font-size:10px; }.comparison-stage header button { width:30px;height:30px;display:grid;place-items:center;margin-left:auto;padding:0;border:0;border-radius:5px;background:transparent;color:#aaa;cursor:pointer; }.comparison-stage header button:hover { color:white;background:#292929; }.comparison-stage header svg { width:14px;height:14px; }.comparison-frames { min-height:0;flex:1;display:grid;grid-template-columns:1fr 1fr;gap:1px;background:#343434; }.comparison-frame { position:relative;min-width:0;min-height:0;background:white; }.comparison-frame span { position:absolute;z-index:1;top:10px;left:10px;padding:5px 7px;border-radius:5px;background:rgb(17 17 17 / 88%);color:white;font-size:9px; }.comparison-frame iframe { width:100%;height:100%;display:block;border:0;background:white; }
1077
- .impact-list { display:grid;gap:4px;margin-top:7px; }.impact-item { display:flex;align-items:flex-start;gap:5px;color:#666;font-size:8px;line-height:1.35; }.impact-item::before { content:"";width:4px;height:4px;flex:none;margin-top:3px;border-radius:50%;background:#9a9a9a; }.impact-item.warning { color:#985033; }.impact-item.warning::before { background:#d16d51; }
1078
- .mapping-chooser { grid-column:2;margin-top:7px;padding:7px;background:#fff9ed;border:1px solid #f4ddb2;border-radius:6px; }.mapping-chooser>strong { display:block;margin-bottom:5px;color:#80561c;font-size:9px;font-weight:550; }.mapping-option { display:flex;align-items:flex-start;gap:6px;padding:5px 0;color:#5f4b2d;font-size:9px;line-height:1.35;cursor:pointer; }.mapping-option input { margin:1px 0 0;accent-color:var(--fdc-signal); }.mapping-option small { display:block;color:#8b7758;font-size:8px; }
1079
- .workbench { position:fixed;z-index:2147483647;inset:10px;display:flex;flex-direction:column;overflow:hidden;border:1px solid #303030;border-radius:12px;background:#111;box-shadow:0 24px 80px rgb(0 0 0 / 35%);pointer-events:auto; }.workbench[hidden] { display:none; }.workbench-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 8px 0 14px;color:white;border-bottom:1px solid #292929;background:#171717; }.workbench-head strong { font-size:12px;font-weight:550; }.workbench-context { color:#8d8d8d;font-size:10px; }.workbench-controls { display:flex;align-items:center;gap:5px;margin-left:auto; }.workbench-controls button,.workbench-controls select { height:30px;padding:0 9px;border:1px solid #343434;border-radius:6px;background:#202020;color:#d7d7d7;font-size:10px;cursor:pointer; }.workbench-controls button.active { color:#111;background:white;border-color:white; }.workbench-controls .icon-button { width:30px;padding:0; }.workbench-stage { min-height:0;flex:1;display:flex;align-items:flex-start;justify-content:center;overflow:auto;padding:28px;background-color:#151515;background-image:linear-gradient(#202020 1px,transparent 1px),linear-gradient(90deg,#202020 1px,transparent 1px);background-size:24px 24px; }.frame-shell { position:relative;flex:none;border-radius:9px;background:white;box-shadow:0 0 0 1px #333,0 20px 60px rgb(0 0 0 / 35%);overflow:hidden; }.frame-label { position:absolute;left:0;top:-21px;color:#8f8f8f;font-size:9px; }.frame-shell iframe { display:block;width:100%;height:100%;border:0;background:white; }.workbench-warning { position:absolute;left:50%;bottom:18px;transform:translateX(-50%);max-width:520px;padding:8px 11px;border:1px solid #3b3b3b;border-radius:6px;background:#1d1d1d;color:#aaa;font-size:10px;line-height:1.4; }
1080
- .library-panel { position:fixed;z-index:2147483647;top:12px;right:352px;width:300px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:10px;background:white;box-shadow:0 12px 32px rgb(0 0 0 / 14%);pointer-events:auto; }.library-panel[hidden] { display:none; }.library-head { min-height:46px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.library-head svg { width:14px;height:14px; }.library-head strong { font-size:12px;font-weight:550; }.library-head span { color:var(--fdc-muted);font-size:9px; }.library-head .icon-button { margin-left:auto; }.library-actions { display:flex;gap:5px;padding:8px;border-bottom:1px solid var(--fdc-line); }.library-actions button { min-height:30px;display:flex;align-items:center;justify-content:center;gap:6px;flex:1;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#4d4d4d;font-size:9px;cursor:pointer; }.library-actions button:disabled { opacity:.45;cursor:not-allowed; }.library-actions svg { width:12px;height:12px; }.library-body { min-height:120px;overflow:auto;padding:8px; }.library-section+.library-section { margin-top:12px; }.library-section-head { display:flex;align-items:center;margin:0 2px 6px;color:#666;font-size:9px;text-transform:uppercase;letter-spacing:.04em; }.library-section-head span { margin-left:auto;text-transform:none;letter-spacing:0; }.memory-card { padding:9px;border:1px solid var(--fdc-line);border-radius:7px;background:white; }.memory-card+.memory-card { margin-top:5px; }.memory-card-top { display:flex;align-items:center;gap:6px; }.memory-card-top strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:10px;font-weight:550;white-space:nowrap; }.memory-status { width:6px;height:6px;flex:none;border-radius:50%;background:#2ca67f; }.memory-card p { margin:5px 0 0;color:var(--fdc-muted);font-size:8px;line-height:1.45; }.memory-card-actions { display:flex;gap:4px;margin-top:8px; }.memory-card-actions button { height:26px;padding:0 7px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#555;font-size:8px;cursor:pointer; }.memory-card-actions button:first-child { flex:1;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.library-empty { padding:20px 12px;color:var(--fdc-muted);font-size:9px;line-height:1.5;text-align:center; }
1081
- .review-visual { display:grid;grid-template-columns:1fr 1fr;gap:5px;margin-top:7px; }.review-sample { position:relative;min-height:34px;display:grid;place-items:center;overflow:hidden;border:1px solid var(--fdc-line);border-radius:5px;background:#fafafa;color:#777;font-size:8px; }.review-sample::after { content:attr(data-label);position:absolute;left:4px;bottom:3px;padding:2px 3px;border-radius:3px;background:rgb(255 255 255 / 84%);color:#777;font-size:7px; }.review-sample>i { width:32px;height:16px;display:block;border:1px solid #bbb;background:var(--sample-color,#e8e8e8);border-radius:var(--sample-radius,3px);transform:scale(var(--sample-scale,1)); }.review-card.locating { background:#f5f9ff; }.review-group-title .included-count { margin-left:auto;color:#23715c; }.review-group-title .group-total { margin-left:3px; }.baseline-badge { display:inline-flex;align-items:center;gap:4px;margin-top:7px;padding:4px 6px;border-radius:4px;color:#23715c;background:#edf8f4;font-size:8px; }.baseline-badge::before { content:"";width:5px;height:5px;border-radius:50%;background:#2ca67f; }
1082
- .workbench-matrix { display:grid;grid-template-columns:92px repeat(var(--matrix-columns),minmax(110px,1fr));gap:1px;width:min(900px,100%);margin:0 auto 22px;padding:1px;background:#303030;border-radius:7px;overflow:hidden; }.matrix-cell { min-height:52px;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:4px;padding:8px;border:0;background:#1d1d1d;color:#ddd;font-size:9px;text-align:left;cursor:pointer; }.matrix-cell:hover { background:#252525; }.matrix-cell.header { min-height:32px;color:#888;background:#181818;cursor:default; }.matrix-cell strong { font-size:9px;font-weight:500; }.matrix-cell span { color:#777;font-size:8px; }.matrix-cell.verified span { color:#68caa8; }.workbench-stage.matrix-mode { display:block; }.workbench-stage.matrix-mode .frame-shell { margin:0 auto; }
1083
- .component-actions { display:flex;gap:4px;padding:0 8px 8px 45px; }.component-actions button,.component-variants button { height:24px;padding:0 6px;border:1px solid #e6e1f7;border-radius:4px;color:#66598c;background:#faf9ff;font-size:8px;cursor:pointer; }.component-actions button:hover,.component-variants button:hover { border-color:#c8bdf1;background:#f4f0ff; }
1084
- .token-provenance { grid-column:2;display:flex;align-items:center;gap:5px;margin-top:5px;color:#23715c;font-size:8px; }.token-provenance.literal { color:#985033; }.token-provenance::before { content:"";width:5px;height:5px;border-radius:50%;background:currentColor; }
1146
+ .token-row { grid-column:2;display:flex;flex-wrap:wrap;gap:4px;margin-top:8px; }.token-chip { height:24px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:1000px;background:var(--fdc-paper);color:#4d4d4d;font-size:8px;cursor:pointer; }.token-chip:hover { border-color:#b7d5ff;color:#0761d1;background:#edf6ff; }
1147
+ .section-head .section-action { width:24px;height:24px;display:grid;place-items:center;margin-left:auto;padding:0;border:0;border-radius:4px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.section-head .section-action:hover,.section-head .section-action.active { color:var(--fdc-signal);background:#edf6ff; }.section-head .section-action svg { width:12px;height:12px; }
1148
+ .context-tools { display:flex;flex-wrap:wrap;gap:4px;padding:8px 12px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-surface); }.context-tools button { min-height:28px;display:flex;align-items:center;gap:4px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#4d4d4d;font-size:8px;cursor:pointer; }.context-tools button:hover { border-color:#c8c8c8;color:var(--fdc-ink); }.context-tools button.active { color:#075fc5;border-color:#bad7ff;background:#edf6ff; }.context-tools svg { width:12px;height:12px; }
1149
+ .native-panel { padding:12px 12px;border-bottom:1px solid var(--fdc-line); }.native-panel-head { display:flex;align-items:center;margin-bottom:8px; }.native-panel-head strong { font-size:12px;font-weight:550; }.native-panel-head span { margin-left:auto;color:var(--fdc-muted);font-size:8px; }.native-search { width:100%;height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:var(--fdc-paper);font-size:8px;outline:none; }.native-search:focus { border-color:var(--fdc-signal); }.native-grid { display:flex;flex-wrap:wrap;gap:4px;margin-top:8px; }.native-chip { min-height:28px;display:flex;align-items:center;gap:4px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#4d4d4d;font-size:8px;cursor:pointer; }.native-chip:hover { border-color:#bdd7fb;background:#f5f9ff; }.native-chip .swatch { width:12px;height:12px;border:1px solid rgb(0 0 0 / 10%);border-radius:4px;background:var(--token-color); }.design-health { display:flex;align-items:center;gap:8px;margin-top:8px;padding:8px 8px;border-radius:4px;background:#f3f3f3;color:#575757;font-size:8px; }.design-health.pass { color:#23715c;background:#edf8f4; }.design-health.fail { color:#9a4930;background:#fff0e9; }.design-health svg { width:12px;height:12px; }
1150
+ .variant-list { display:grid;gap:4px;margin-top:8px; }.variant-button { min-height:32px;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;font-size:8px;cursor:pointer; }.variant-button code { overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font-size:8px;white-space:nowrap; }
1151
+ .compare-bar { position:fixed;z-index:2147483646;left:50%;bottom:80px;transform:translateX(-50%);display:flex;align-items:center;gap:4px;padding:8px;border:1px solid var(--fdc-line);border-radius:8px;background:white;box-shadow:0 8px 24px rgb(0 0 0 / 14%);pointer-events:auto; }.compare-bar[hidden] { display:none; }.compare-bar strong { padding:0 8px;font-size:12px;font-weight:550; }.compare-bar button { height:32px;display:flex;align-items:center;gap:4px;padding:0 8px;border:0;border-radius:4px;background:transparent;color:#555;font-size:8px;cursor:pointer; }.compare-bar button:hover,.compare-bar button.active { color:white;background:var(--fdc-ink); }.compare-bar svg { width:12px;height:12px; }.compare-bar input[type="range"] { width:96px;accent-color:var(--fdc-ink);cursor:ew-resize; }
1152
+ .command-palette { position:fixed;z-index:2147483647;left:50%;top:18%;transform:translateX(-50%);width:min(480px,calc(100vw - 32px));overflow:hidden;border:1px solid #d8d8d8;border-radius:12px;background:white;box-shadow:0 24px 80px rgb(0 0 0 / 24%);pointer-events:auto; }.command-palette[hidden] { display:none; }.command-search { display:flex;align-items:center;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.command-palette input { min-width:0;flex:1;width:auto;height:48px;padding:0 16px;border:0;font-size:12px;outline:none; }.command-search .icon-button { flex:none;margin-right:8px; }.command-list { max-height:320px;overflow:auto;padding:4px; }.command-item { width:100%;min-height:40px;display:flex;align-items:center;gap:8px;padding:0 12px;border:0;border-radius:8px;background:transparent;color:#333;text-align:left;font-size:12px;cursor:pointer; }.command-item:hover,.command-item.active { background:var(--fdc-subtle); }.command-item svg { width:16px;height:16px;color:#777; }.command-item small { margin-left:auto;color:#8a8a8a;font-size:8px; }
1153
+ .comparison-stage { position:fixed;z-index:2147483647;inset:12px;display:flex;flex-direction:column;overflow:hidden;border:1px solid #303030;border-radius:12px;background:#111;box-shadow:0 24px 80px rgb(0 0 0 / 35%);pointer-events:auto; }.comparison-stage[hidden] { display:none; }.comparison-stage header { min-height:48px;display:flex;align-items:center;padding:0 8px 0 16px;color:white;border-bottom:1px solid #292929;background:#171717; }.comparison-stage header strong { font-size:12px;font-weight:550; }.comparison-stage header span { margin-left:8px;color:#8d8d8d;font-size:12px; }.comparison-stage header button { width:32px;height:32px;display:grid;place-items:center;margin-left:auto;padding:0;border:0;border-radius:4px;background:transparent;color:#aaa;cursor:pointer; }.comparison-stage header button:hover { color:white;background:#292929; }.comparison-stage header svg { width:16px;height:16px; }.comparison-frames { min-height:0;flex:1;display:grid;grid-template-columns:1fr 1fr;gap:1px;background:#343434; }.comparison-frame { position:relative;min-width:0;min-height:0;background:white; }.comparison-frame span { position:absolute;z-index:1;top:12px;left:12px;padding:4px 8px;border-radius:4px;background:rgb(17 17 17 / 88%);color:white;font-size:8px; }.comparison-frame iframe { width:100%;height:100%;display:block;border:0;background:white; }
1154
+ .impact-list { display:grid;gap:4px;margin-top:8px; }.impact-item { display:flex;align-items:flex-start;gap:4px;color:#666;font-size:8px;line-height:1.35; }.impact-item::before { content:"";width:4px;height:4px;flex:none;margin-top:4px;border-radius:50%;background:#9a9a9a; }.impact-item.warning { color:#985033; }.impact-item.warning::before { background:#d16d51; }
1155
+ .mapping-chooser { grid-column:2;margin-top:8px;padding:8px;background:#fff9ed;border:1px solid #f4ddb2;border-radius:8px; }.mapping-chooser>strong { display:block;margin-bottom:4px;color:#80561c;font-size:8px;font-weight:550; }.mapping-option { display:flex;align-items:flex-start;gap:8px;padding:4px 0;color:#5f4b2d;font-size:8px;line-height:1.35;cursor:pointer; }.mapping-option input { margin:1px 0 0;accent-color:var(--fdc-signal); }.mapping-option small { display:block;color:#8b7758;font-size:8px; }
1156
+ .workbench { position:fixed;z-index:2147483647;inset:12px;display:flex;flex-direction:column;overflow:hidden;border:1px solid #303030;border-radius:12px;background:#111;box-shadow:0 24px 80px rgb(0 0 0 / 35%);pointer-events:auto; }.workbench[hidden] { display:none; }.workbench-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 8px 0 16px;color:white;border-bottom:1px solid #292929;background:#171717; }.workbench-head strong { font-size:12px;font-weight:550; }.workbench-context { color:#8d8d8d;font-size:12px; }.workbench-controls { display:flex;align-items:center;gap:4px;margin-left:auto; }.workbench-controls button,.workbench-controls select { height:32px;padding:0 8px;border:1px solid #343434;border-radius:8px;background:#202020;color:#d7d7d7;font-size:12px;cursor:pointer; }.workbench-controls button.active { color:#111;background:white;border-color:white; }.workbench-controls .icon-button { width:32px;padding:0; }.workbench-stage { min-height:0;flex:1;display:flex;align-items:flex-start;justify-content:center;overflow:auto;padding:28px;background-color:#151515;background-image:linear-gradient(#202020 1px,transparent 1px),linear-gradient(90deg,#202020 1px,transparent 1px);background-size:24px 24px; }.frame-shell { position:relative;flex:none;border-radius:8px;background:white;box-shadow:0 0 0 1px #333,0 20px 60px rgb(0 0 0 / 35%);overflow:hidden; }.frame-label { position:absolute;left:0;top:-20px;color:#8f8f8f;font-size:8px; }.frame-shell iframe { display:block;width:100%;height:100%;border:0;background:white; }.workbench-warning { position:absolute;left:50%;bottom:20px;transform:translateX(-50%);max-width:520px;padding:8px 12px;border:1px solid #3b3b3b;border-radius:8px;background:#1d1d1d;color:#aaa;font-size:12px;line-height:1.4; }
1157
+ .library-panel { position:fixed;z-index:2147483647;top:12px;right:352px;width:300px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:12px;background:white;box-shadow:0 12px 32px rgb(0 0 0 / 14%);pointer-events:auto; }.library-panel[hidden] { display:none; }.library-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.library-head svg { width:16px;height:16px; }.library-head strong { font-size:12px;font-weight:550; }.library-head span { color:var(--fdc-muted);font-size:8px; }.library-head .icon-button { margin-left:auto; }.library-actions { display:flex;gap:4px;padding:8px;border-bottom:1px solid var(--fdc-line); }.library-actions button { min-height:32px;display:flex;align-items:center;justify-content:center;gap:8px;flex:1;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#4d4d4d;font-size:8px;cursor:pointer; }.library-actions button:disabled { opacity:.45;cursor:not-allowed; }.library-actions svg { width:12px;height:12px; }.library-body { min-height:120px;overflow:auto;padding:8px; }.library-section+.library-section { margin-top:12px; }.library-section-head { display:flex;align-items:center;margin:0 4px 8px;color:#666;font-size:8px;text-transform:uppercase;letter-spacing:.04em; }.library-section-head span { margin-left:auto;text-transform:none;letter-spacing:0; }.memory-card { padding:8px;border:1px solid var(--fdc-line);border-radius:8px;background:white; }.memory-card+.memory-card { margin-top:4px; }.memory-card-top { display:flex;align-items:center;gap:8px; }.memory-card-top strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:12px;font-weight:550;white-space:nowrap; }.memory-status { width:8px;height:8px;flex:none;border-radius:50%;background:#2ca67f; }.memory-card p { margin:4px 0 0;color:var(--fdc-muted);font-size:8px;line-height:1.45; }.memory-card-actions { display:flex;gap:4px;margin-top:8px; }.memory-card-actions button { height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#555;font-size:8px;cursor:pointer; }.memory-card-actions button:first-child { flex:1;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.library-empty { padding:20px 12px;color:var(--fdc-muted);font-size:8px;line-height:1.5;text-align:center; }
1158
+ .review-visual { display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-top:8px; }.review-sample { position:relative;min-height:36px;display:grid;place-items:center;overflow:hidden;border:1px solid var(--fdc-line);border-radius:4px;background:#fafafa;color:#777;font-size:8px; }.review-sample::after { content:attr(data-label);position:absolute;left:4px;bottom:4px;padding:4px 4px;border-radius:4px;background:rgb(255 255 255 / 84%);color:#777;font-size:8px; }.review-sample>i { width:32px;height:16px;display:block;border:1px solid #bbb;background:var(--sample-color,#e8e8e8);border-radius:var(--sample-radius,4px);transform:scale(var(--sample-scale,1)); }.review-card.locating { background:#f5f9ff; }.review-group-title .included-count { margin-left:auto;color:#23715c; }.review-group-title .group-total { margin-left:4px; }.baseline-badge { display:inline-flex;align-items:center;gap:4px;margin-top:8px;padding:4px 8px;border-radius:4px;color:#23715c;background:#edf8f4;font-size:8px; }.baseline-badge::before { content:"";width:4px;height:4px;border-radius:50%;background:#2ca67f; }
1159
+ .workbench-matrix { display:grid;grid-template-columns:92px repeat(var(--matrix-columns),minmax(112px,1fr));gap:1px;width:min(900px,100%);margin:0 auto 24px;padding:1px;background:#303030;border-radius:8px;overflow:hidden; }.matrix-cell { min-height:52px;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:4px;padding:8px;border:0;background:#1d1d1d;color:#ddd;font-size:8px;text-align:left;cursor:pointer; }.matrix-cell:hover { background:#252525; }.matrix-cell.header { min-height:32px;color:#888;background:#181818;cursor:default; }.matrix-cell strong { font-size:8px;font-weight:500; }.matrix-cell span { color:#777;font-size:8px; }.matrix-cell.verified span { color:#68caa8; }.workbench-stage.matrix-mode { display:block; }.workbench-stage.matrix-mode .frame-shell { margin:0 auto; }
1160
+ .component-actions { display:flex;gap:4px;padding:0 8px 8px 44px; }.component-actions button,.component-variants button { height:24px;padding:0 8px;border:1px solid #e6e1f7;border-radius:4px;color:#66598c;background:#faf9ff;font-size:8px;cursor:pointer; }.component-actions button:hover,.component-variants button:hover { border-color:#c8bdf1;background:#f4f0ff; }
1161
+ .token-provenance { grid-column:2;display:flex;align-items:center;gap:4px;margin-top:4px;color:#23715c;font-size:8px; }.token-provenance.literal { color:#985033; }.token-provenance::before { content:"";width:4px;height:4px;border-radius:50%;background:currentColor; }
1085
1162
  .workbench-matrix[hidden] { display:none; }
1086
1163
  /* Foundry dark instrument theme */
1087
- .panel,.layers-panel,.health-panel,.library-panel,.tool-shelf,.onboarding-card,.compare-bar,.command-palette,.status-popover,.canvas-variant { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line);box-shadow:0 1px 2px rgb(0 0 0 / 24%),0 14px 36px rgb(0 0 0 / 36%); }
1164
+ .panel,.layers-panel,.health-panel,.library-panel,.tool-shelf,.onboarding-card,.compare-bar,.command-palette,.status-popover,.canvas-variant { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line);box-shadow:0 1px 4px rgb(0 0 0 / 24%),0 16px 36px rgb(0 0 0 / 36%); }
1088
1165
  .top,.top-actions,.selection,.scope,.controls,.property-section,.change-dock,.footer,.review-view,.review-head,.review-group,.review-group-title,.review-actions,.layers-head,.layer-tree,.health-head,.health-list,.health-footer,.library-head,.library-actions,.library-body,.memory-card,.context-tools,.native-panel { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }
1089
1166
  .inspector-heading,.review-toolbar { background:rgb(28 28 31 / 96%);border-color:var(--fdc-line); }
1090
1167
  .section-head,.section-head:hover,.onboarding-step { color:var(--fdc-ink);background:var(--fdc-surface); }
@@ -1099,106 +1176,208 @@ var PANEL_CSS = `
1099
1176
  .scope select,.property-control input,.property-control select,.compact-control input,.compact-control select,.native-search,.command-palette input { color:var(--fdc-ink);background:var(--fdc-paper);border-color:var(--fdc-line); }
1100
1177
  .scope select option,.property-control select option,.compact-control select option { color:var(--fdc-ink);background:var(--fdc-paper); }
1101
1178
  .property-label,.section-head,.color-value,.layer-row,.command-item,.library-section-head { color:#d1d1d6; }.field-prefix,.unit,.control-field .unit-select,.section-toggle>svg,.layer-row .chevron,.layer-row .layer-icon,.command-item svg,.command-item small { color:var(--fdc-muted); }
1102
- .layer-row.selected { color:#a9cbff;background:var(--fdc-signal-soft); }.layer-row.selected .layer-icon { color:#86b7ff; }
1179
+ .layer-row.selected { color:#a9cbff;background:transparent; }.layer-row.selected .layer-icon { color:#86b7ff; }
1103
1180
  .layer-row .layer-meta { color:#b5b5bc;background:var(--fdc-elevated); }.layer-row.selected .layer-meta { color:#a9cbff;background:#23416d; }
1104
1181
  .layers-search { background:var(--fdc-paper); }.layers-switch { background:var(--fdc-paper);border-color:var(--fdc-line); }.layers-switch button { color:var(--fdc-muted);background:transparent; }.layers-switch button:hover,.layers-switch button.active { color:var(--fdc-ink);background:var(--fdc-elevated); }.layers-switch button[data-layer-view="components"].active,.layers-switch button[data-layer-view="components"].active span { color:#c1b5f5;background:var(--fdc-component-soft); }
1105
1182
  .token-chip { color:#d1d1d6;background:var(--fdc-paper);border-color:var(--fdc-line); }.token-chip:hover { color:#9ec5ff;background:var(--fdc-signal-soft);border-color:#315482; }
1183
+ .section-actions { flex:none;display:flex;align-items:center;gap:4px; }.section-action,.section-actions button,.category-action,.token-menu-trigger { height:28px;display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:0 8px;border:1px solid transparent;border-radius:4px;color:var(--fdc-muted);background:transparent;font:500 8px/1 var(--fdc-font);cursor:pointer; }.section-action:hover,.section-actions button:hover,.category-action:hover,.token-menu-trigger:hover { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.section-action svg,.category-action svg,.token-menu-trigger svg { width:12px;height:12px; }.type-presets button { width:28px;padding:0; }.category-action { margin-left:auto; }.inspector-heading .property-count { margin-left:4px; }
1184
+ .token-menu-wrap { position:relative;display:flex;align-items:center;margin-top:4px; }.token-menu-trigger { width:28px;padding:0; }.token-menu { position:absolute;z-index:8;top:32px;right:0;width:232px;max-height:220px;overflow:auto;padding:4px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-elevated);box-shadow:0 16px 36px rgb(0 0 0 / 38%); }.token-menu[hidden] { display:none; }.token-option { width:100%;height:32px;display:grid;grid-template-columns:16px minmax(0,1fr) auto;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:4px;color:var(--fdc-ink);background:transparent;text-align:left;cursor:pointer; }.token-option:hover { background:var(--fdc-subtle); }.token-option .swatch { width:12px;height:12px;border:1px solid rgb(255 255 255 / 14%);border-radius:4px;background:var(--token-color); }.token-option span { overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:8px; }.token-option code { color:var(--fdc-muted);font:400 8px/1 var(--fdc-font); }
1185
+ .color-picker-trigger { width:100%;height:32px;display:flex;align-items:center;gap:8px;padding:0 32px 0 8px;border:0;background:transparent;color:var(--fdc-ink);font:400 12px/1 var(--fdc-font);text-align:left;cursor:pointer; }.color-picker-trigger .color-swatch { margin-left:0; }.color-popover { position:fixed;z-index:2147483647;width:280px;padding:12px;border:1px solid var(--fdc-line);border-radius:12px;color:var(--fdc-ink);background:var(--fdc-elevated);box-shadow:0 20px 60px rgb(0 0 0 / 48%);pointer-events:auto; }.color-popover[hidden] { display:none; }.color-popover-head { height:28px;display:flex;align-items:center;margin-bottom:8px; }.color-popover-head strong { font-size:12px;font-weight:550; }.color-popover-head button { margin-left:auto; }.color-plane { position:relative;width:100%;height:152px;overflow:hidden;border-radius:8px;background:linear-gradient(to top,#000,transparent),linear-gradient(to right,#fff,transparent),hsl(var(--picker-hue) 100% 50%);cursor:crosshair;touch-action:none; }.color-plane-handle { position:absolute;width:12px;height:12px;transform:translate(-50%,-50%);border:4px solid white;border-radius:50%;box-shadow:0 1px 4px #000;pointer-events:none; }.color-sliders { display:grid;gap:8px;margin-top:8px; }.color-sliders label { display:grid;grid-template-columns:36px minmax(0,1fr);align-items:center;gap:8px;color:var(--fdc-muted);font-size:8px; }.color-sliders input[type="range"] { width:100%;accent-color:var(--fdc-signal); }.color-fields { display:grid;grid-template-columns:minmax(0,1fr) 36px;gap:8px;margin-top:8px; }.color-fields input { min-width:0;height:32px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;color:var(--fdc-ink);background:var(--fdc-paper);font:400 12px/1 var(--fdc-font);outline:none; }.color-fields button { height:32px;display:grid;place-items:center;padding:0;border:1px solid var(--fdc-line);border-radius:4px;color:var(--fdc-muted);background:var(--fdc-paper);cursor:pointer; }.color-fields button:hover { color:var(--fdc-ink); }.color-fields svg { width:12px;height:12px; }.color-popover-section { margin-top:12px;padding-top:8px;border-top:1px solid var(--fdc-line); }.color-popover-section strong { display:block;margin-bottom:8px;color:var(--fdc-muted);font-size:8px;font-weight:500;text-transform:uppercase;letter-spacing:.04em; }.color-swatches { display:flex;flex-wrap:wrap;gap:8px; }.color-swatches button { width:24px;height:24px;padding:0;border:1px solid rgb(255 255 255 / 16%);border-radius:4px;background:var(--picker-swatch);cursor:pointer; }.color-swatches button:hover { box-shadow:0 0 0 4px var(--fdc-signal); }
1106
1186
  .review-summary { background:var(--fdc-paper); }.review-before { color:var(--fdc-muted);background:var(--fdc-subtle); }.review-sample { color:var(--fdc-muted);background:var(--fdc-paper);border-color:var(--fdc-line); }.review-sample::after { color:var(--fdc-muted);background:rgb(28 28 31 / 88%); }
1107
1187
  .confidence-pill { color:#9ec5ff;background:var(--fdc-signal-soft); }.confidence-pill.unresolved { color:#f2ae8f;background:#42271d; }
1108
1188
  .session-status,.session-status.saved { color:#83d8bb;background:#18352c; }.session-status.saving { color:#efd979;background:#3d3417; }.session-status.error,.session-status.offline { color:#f0a18b;background:#40251f; }
1109
1189
  .empty-state-icon { color:#9ec5ff;background:var(--fdc-signal-soft); }.onboarding-card-head span { color:#e7a68c;background:#36231d; }
1110
1190
  .change-count { color:var(--fdc-ink);background:var(--fdc-paper); }
1191
+ .compare-bar button:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }
1192
+ .compare-bar button.active { color:#141416;background:#f0f1f3; }
1193
+ .toast { color:#141416;background:#f0f1f3;border:1px solid #ffffff;box-shadow:0 8px 20px rgb(0 0 0 / 30%); }
1111
1194
  .change-dock .dock-review,.footer .review,.review-actions .apply,.onboarding-actions .onboarding-start,.health-actions .health-fix,.health-footer .health-rescan,.memory-card-actions button:first-child,.empty-state-actions button:first-child { color:#141416;background:#f0f1f3;border-color:#f0f1f3; }.change-dock .dock-review:hover,.footer .review:hover,.review-actions .apply:hover { color:#141416;background:#ffffff; }
1112
1195
  .panel-resizer::after { background:#4a4a50; }
1113
- .empty-state { min-height:220px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:36px 30px;text-align:center; }.empty-state-icon { width:38px;height:38px;display:grid;place-items:center;margin-bottom:14px;border-radius:10px; }.empty-state-icon svg { width:16px;height:16px; }.empty-state strong { font-size:13px;font-weight:550;letter-spacing:-.01em; }.empty-state p { max-width:230px;margin:7px 0 0;color:var(--fdc-muted);font-size:11px;line-height:1.55; }.empty-state-actions { display:flex;align-items:center;gap:6px;margin-top:16px; }.empty-state-actions button { height:30px;padding:0 10px;border:1px solid var(--fdc-line);border-radius:6px;font-size:10px;cursor:pointer; }.empty-state kbd { margin-top:12px;color:var(--fdc-muted);font:400 9px/1.4 var(--fdc-font); }
1114
- .review-head strong { font-size:13px; }.review-summary { padding:13px 14px 12px;border-bottom:1px solid var(--fdc-line);background:#fcfcfc; }.review-summary strong { display:block;font-size:12px;font-weight:550;letter-spacing:-.01em; }.review-summary span { display:block;margin-top:4px;color:var(--fdc-muted);font-size:10px;line-height:1.45; }.review-summary.attention strong { color:#8b4d3d; }.review-toolbar button { height:28px;padding:0 9px;font-size:10px; }
1115
- .onboarding-card { bottom:82px;width:340px;padding:16px;border-radius:12px;box-shadow:0 14px 38px rgb(0 0 0 / 15%); }.onboarding-card-head { gap:9px; }.onboarding-card-head span { width:26px;height:26px;display:grid;place-items:center;color:#a75031;background:#fbf1ed;border-radius:7px; }.onboarding-card-head svg { width:14px;height:14px;color:inherit; }.onboarding-card-head strong { font-size:13px;letter-spacing:-.015em; }.onboarding-card>p { margin:9px 0 14px;font-size:11px;line-height:1.55; }.onboarding-steps { display:grid;grid-template-columns:1fr;gap:1px;border:1px solid var(--fdc-line);border-radius:8px;overflow:hidden;background:var(--fdc-line); }.onboarding-step { display:grid;grid-template-columns:24px 1fr;gap:9px;padding:9px 10px;background:white;text-align:left; }.onboarding-step b { color:#8a8a8a;font-size:9px;font-weight:500;letter-spacing:.04em; }.onboarding-step strong { display:block;font-size:10px;font-weight:550; }.onboarding-step small { display:block;margin-top:2px;color:var(--fdc-muted);font-size:9px;line-height:1.35; }.onboarding-actions { gap:6px;margin-top:13px; }.onboarding-actions button { height:32px;padding:0 11px;border-radius:6px;font-size:10px; }
1196
+ .empty-state { min-height:220px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:36px 32px;text-align:center; }.empty-state-icon { width:40px;height:40px;display:grid;place-items:center;margin-bottom:16px;border-radius:12px; }.empty-state-icon svg { width:16px;height:16px; }.empty-state strong { font-size:12px;font-weight:550;letter-spacing:-.01em; }.empty-state p { max-width:232px;margin:8px 0 0;color:var(--fdc-muted);font-size:12px;line-height:1.55; }.empty-state-actions { display:flex;align-items:center;gap:8px;margin-top:16px; }.empty-state-actions button { height:32px;padding:0 12px;border:1px solid var(--fdc-line);border-radius:8px;font-size:12px;cursor:pointer; }.empty-state kbd { margin-top:12px;color:var(--fdc-muted);font:400 8px/1.4 var(--fdc-font); }
1197
+ .review-head strong { font-size:12px; }.review-summary { padding:12px 16px 12px;border-bottom:1px solid var(--fdc-line);background:#fcfcfc; }.review-summary strong { display:block;font-size:12px;font-weight:550;letter-spacing:-.01em; }.review-summary span { display:block;margin-top:4px;color:var(--fdc-muted);font-size:12px;line-height:1.45; }.review-summary.attention strong { color:#8b4d3d; }.review-toolbar button { height:28px;padding:0 8px;font-size:12px; }
1198
+ .onboarding-card { bottom:84px;width:340px;padding:16px;border-radius:12px;box-shadow:0 16px 40px rgb(0 0 0 / 15%); }.onboarding-card-head { gap:8px; }.onboarding-card-head span { width:28px;height:28px;display:grid;place-items:center;color:#a75031;background:#fbf1ed;border-radius:8px; }.onboarding-card-head svg { width:16px;height:16px;color:inherit; }.onboarding-card-head strong { font-size:12px;letter-spacing:-.015em; }.onboarding-card>p { margin:8px 0 16px;font-size:12px;line-height:1.55; }.onboarding-steps { display:grid;grid-template-columns:1fr;gap:1px;border:1px solid var(--fdc-line);border-radius:8px;overflow:hidden;background:var(--fdc-line); }.onboarding-step { display:grid;grid-template-columns:24px 1fr;gap:8px;padding:8px 12px;background:white;text-align:left; }.onboarding-step b { color:#8a8a8a;font-size:8px;font-weight:500;letter-spacing:.04em; }.onboarding-step strong { display:block;font-size:12px;font-weight:550; }.onboarding-step small { display:block;margin-top:4px;color:var(--fdc-muted);font-size:8px;line-height:1.35; }.onboarding-actions { gap:8px;margin-top:12px; }.onboarding-actions button { height:32px;padding:0 12px;border-radius:8px;font-size:12px; }
1116
1199
  .onboarding-card,.onboarding-step { color:var(--fdc-ink);background:var(--fdc-surface); }.onboarding-card-head span { color:#e7a68c;background:#36231d; }.onboarding-actions button { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.onboarding-actions .onboarding-start { color:#141416;background:#f0f1f3;border-color:#f0f1f3; }
1117
1200
  .review-summary { color:var(--fdc-ink);background:var(--fdc-paper); }.empty-state-icon { color:#9ec5ff;background:var(--fdc-signal-soft); }
1118
- .component-card,.health-card { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }.component-card.selected { color:var(--fdc-ink);background:var(--fdc-component-soft);border-color:#5c4b9e;box-shadow:0 0 0 2px rgb(155 135 245 / 10%); }.component-variants span,.component-actions button,.component-variants button { color:#c1b5f5;background:var(--fdc-component-soft);border-color:#4a406f; }.health-score::before { background:var(--fdc-surface); }.health-filters button { color:var(--fdc-muted); }.health-filters button:hover,.health-filters button.active { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.health-card p,.health-evidence { color:var(--fdc-muted); }.mapping-chooser { color:#f0c9a8;background:#35291d;border-color:#665039; }.mapping-chooser>strong,.mapping-option,.mapping-option small { color:#e7c29f; }.review-card.locating { background:var(--fdc-signal-soft); }.baseline-badge { color:#83d8bb;background:#18352c; }
1201
+ .component-card,.health-card { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }.component-card.selected { color:var(--fdc-ink);background:var(--fdc-component-soft);border-color:#5c4b9e;box-shadow:0 0 0 4px rgb(155 135 245 / 10%); }.component-variants span,.component-actions button,.component-variants button { color:#c1b5f5;background:var(--fdc-component-soft);border-color:#4a406f; }.health-score::before { background:var(--fdc-surface); }.health-filters button { color:var(--fdc-muted); }.health-filters button:hover,.health-filters button.active { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.health-card p,.health-evidence { color:var(--fdc-muted); }.mapping-chooser { color:#f0c9a8;background:#35291d;border-color:#665039; }.mapping-chooser>strong,.mapping-option,.mapping-option small { color:#e7c29f; }.review-card.locating { background:var(--fdc-signal-soft); }.baseline-badge { color:#83d8bb;background:#18352c; }
1119
1202
  /* Workspace ownership */
1120
- .workspace-bar { position:fixed;z-index:2147483647;top:12px;left:50%;min-height:48px;display:flex;align-items:center;gap:5px;padding:6px;transform:translateX(-50%);color:var(--fdc-ink);background:rgb(28 28 31 / 96%);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 2px 2px rgb(0 0 0 / 20%),0 14px 34px rgb(0 0 0 / 34%);backdrop-filter:blur(14px);pointer-events:auto; }.workspace-bar .brand { flex:none;padding:0 7px; }.workspace-bar .brand-copy b { font-size:12px; }.workspace-bar .session-status { margin:0; }.workspace-actions { display:flex;align-items:center;gap:2px; }.workspace-divider { width:1px;height:24px;background:var(--fdc-line); }.workspace-bar .icon-button { width:34px;height:34px; }.workspace-bar .icon-button.active { color:#9ec5ff;background:var(--fdc-signal-soft); }.workspace-bar .status-popover { top:44px;right:auto;left:58px; }
1121
- .panel { top:72px;bottom:12px;max-height:none;overflow:clip; }.panel[hidden] { display:none; }.inspector-head { min-height:44px;display:flex;align-items:center;gap:7px;padding:0 8px 0 13px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-surface); }.inspector-head strong { font-size:12px;font-weight:550; }.inspector-head span { color:var(--fdc-muted);font-size:9px; }.inspector-head .icon-button { margin-left:auto; }.controls { min-height:0;flex:1; }.inspector-baseline { padding:0 12px 8px;border-bottom:1px solid var(--fdc-line); }.inspector-category { border-bottom:1px solid var(--fdc-line); }.inspector-category>.inspector-heading { position:sticky;top:0;z-index:2;height:44px;padding:0 8px 0 4px;background:rgb(28 28 31 / 97%); }.inspector-category>.inspector-heading .section-toggle { min-height:43px; }.inspector-category>.inspector-heading .section-toggle>svg { width:15px;height:15px;color:var(--fdc-muted);transform:none; }.inspector-category.collapsed>.category-body { display:none; }.inspector-category.collapsed>.inspector-heading .section-toggle>svg { transform:rotate(-90deg); }.inspector-category .property-section { margin-left:10px;border-left:1px solid var(--fdc-line); }.inspector-category .property-section .section-head { padding-left:6px; }.inspector-category[data-category="position"]>.category-body>.property-section>.section-head { display:none; }.category-body>.context-tools,.category-body>.native-panel,.category-body>.design-health { margin-left:10px; }
1203
+ .workspace-bar { position:fixed;z-index:2147483647;top:12px;left:50%;min-height:48px;display:flex;align-items:center;gap:4px;padding:8px;transform:translateX(-50%);color:var(--fdc-ink);background:rgb(28 28 31 / 96%);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 4px 4px rgb(0 0 0 / 20%),0 16px 36px rgb(0 0 0 / 34%);backdrop-filter:blur(16px);pointer-events:auto; }.workspace-bar .brand { flex:none;padding:0 8px; }.workspace-bar .brand-copy b { font-size:12px; }.workspace-bar .session-status { margin:0; }.workspace-actions { display:flex;align-items:center;gap:4px; }.workspace-divider { width:1px;height:24px;background:var(--fdc-line); }.workspace-bar .icon-button { width:36px;height:36px; }.workspace-bar .icon-button.active { color:#9ec5ff;background:var(--fdc-signal-soft); }.workspace-bar .status-popover { top:44px;right:auto;left:60px; }
1204
+ .panel { top:72px;bottom:12px;max-height:none;overflow:clip; }.panel[hidden] { display:none; }.inspector-head { min-height:44px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-surface); }.inspector-head strong { font-size:12px;font-weight:550; }.inspector-head span { color:var(--fdc-muted);font-size:8px; }.inspector-head .icon-button { margin-left:auto; }.controls { min-height:0;flex:1; }.inspector-baseline { padding:0 12px 8px;border-bottom:1px solid var(--fdc-line); }.inspector-category { border-bottom:1px solid var(--fdc-line); }.inspector-category>.inspector-heading { position:sticky;top:0;z-index:2;height:44px;padding:0 8px 0 4px;background:rgb(28 28 31 / 97%); }.inspector-category>.inspector-heading .section-toggle { min-height:44px; }.inspector-category>.inspector-heading .section-toggle>svg { width:16px;height:16px;color:var(--fdc-muted);transform:none; }.inspector-category.collapsed>.category-body { display:none; }.inspector-category.collapsed>.inspector-heading .section-toggle>svg { transform:rotate(-90deg); }.inspector-category .property-section { margin-left:12px;border-left:1px solid var(--fdc-line); }.inspector-category .property-section .section-head { padding-left:8px; }.inspector-category[data-category="position"]>.category-body>.property-section>.section-head { display:none; }.category-body>.context-tools,.category-body>.native-panel,.category-body>.design-health { margin-left:12px; }
1122
1205
  .inspector-scroll { min-width:0;min-height:0;flex:1;overflow-x:hidden;overflow-y:auto;background:var(--fdc-surface); }
1123
- .inspector-scroll::-webkit-scrollbar { width:6px; }
1206
+ .inspector-scroll::-webkit-scrollbar { width:8px; }
1124
1207
  .inspector-scroll::-webkit-scrollbar-track { background:transparent; }
1125
- .inspector-scroll::-webkit-scrollbar-thumb { background:#4a4a50;border-radius:999px; }
1208
+ .inspector-scroll::-webkit-scrollbar-thumb { background:#4a4a50;border-radius:1000px; }
1126
1209
  .inspector-scroll::-webkit-scrollbar-thumb:hover { background:#626269; }
1127
1210
  .inspector-scroll>.selection,.inspector-scroll>.scope,.inspector-scroll>.controls { width:100%;box-sizing:border-box; }
1128
1211
  .inspector-scroll>.controls { min-height:0;overflow:visible;flex:none; }
1129
1212
  /* Fluid inspector controls */
1130
1213
  .inspector-category .property-section { width:100%;margin-left:0;border-left:0; }
1131
- .inspector-category .property-section .section-head { padding-left:10px; }
1214
+ .inspector-category .property-section .section-head { padding-left:12px; }
1132
1215
  .category-body>.context-tools,.category-body>.native-panel { width:100%;margin-left:0; }
1133
- .category-body>.design-health { width:auto;margin:12px 14px 0; }
1134
- .section-grid { width:100%;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:12px 14px 14px;box-sizing:border-box; }
1216
+ .category-body>.design-health { width:auto;margin:12px 16px 0; }
1217
+ .section-grid { width:100%;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:12px 16px 16px;box-sizing:border-box; }
1135
1218
  .section-grid.stacked { grid-template-columns:minmax(0,1fr); }
1136
1219
  .section-grid:not(.stacked)>:last-child:nth-child(odd) { grid-column:1/-1; }
1137
- .property-control { min-width:0;display:flex;flex-direction:column;align-items:stretch;gap:6px; }
1138
- .property-control .property-label { min-height:13px;line-height:13px; }
1139
- .property-control .control-field { width:100%;height:34px; }
1220
+ .property-control { min-width:0;display:flex;flex-direction:column;align-items:stretch;gap:8px; }
1221
+ .property-control .property-label { min-height:12px;line-height:12px; }
1222
+ .property-control .control-field { width:100%;height:36px; }
1140
1223
  .property-control input,.property-control select { height:32px; }
1141
1224
  .section-grid.two { grid-template-columns:repeat(2,minmax(0,1fr));gap:8px; }
1142
1225
  .section-grid.two .compact-control { position:relative;display:block; }
1143
- .compact-control .field-prefix,.compact-control .field-prefix.wide { width:44px;min-width:44px;box-sizing:border-box;padding-left:10px; }
1144
- .section-grid.two .control-field { width:100%;height:34px; }
1226
+ .compact-control .field-prefix,.compact-control .field-prefix.wide { width:44px;min-width:44px;box-sizing:border-box;padding-left:12px; }
1227
+ .section-grid.two .control-field { width:100%;height:36px; }
1145
1228
  .section-grid.two .compact-control input,.section-grid.two .compact-control select { height:32px; }
1146
1229
  .control-field>.control-reset { position:absolute;z-index:2;top:4px;right:4px;width:24px;height:24px; }
1147
1230
  .control-field>input { padding-right:32px; }
1148
- .control-field:has(>select:not(.unit-select))>.control-reset { right:30px; }
1231
+ .control-field:has(>select:not(.unit-select))>.control-reset { right:32px; }
1149
1232
  .control-field:has(>select:not(.unit-select))>select:not(.unit-select) { padding-right:56px!important; }
1150
- .control-field:has(>.unit-select)>.control-reset { right:49px; }
1151
- .control-field:has(>.unit)>.control-reset { right:25px; }
1233
+ .control-field:has(>.unit-select)>.control-reset { right:48px; }
1234
+ .control-field:has(>.unit)>.control-reset { right:24px; }
1152
1235
  /* Consistent inset chevrons for every select input */
1153
- select { -webkit-appearance:none;appearance:none;padding-right:30px!important;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%238f8f96' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 6.5 3 3 3-3'/%3E%3C/svg%3E")!important;background-repeat:no-repeat!important;background-position:right 9px center!important;background-size:16px 16px!important; }
1154
- .control-field .unit-select { width:48px;padding-right:20px!important;padding-left:3px!important;background-position:right 3px center!important;background-size:14px 14px!important; }
1155
- .layers-panel { top:72px;bottom:12px;max-height:none; }.layers-panel[hidden] { display:none; }
1156
- .utility-panel { z-index:2147483646;max-height:none;min-width:280px;min-height:280px;box-shadow:0 2px 2px rgb(0 0 0 / 22%),0 18px 48px rgb(0 0 0 / 42%); }.utility-panel[hidden] { display:none; }.utility-handle { cursor:grab;user-select:none;touch-action:none; }.utility-handle:active { cursor:grabbing; }.utility-resizer { position:absolute;right:2px;bottom:2px;width:18px;height:18px;padding:0;border:0;background:transparent;cursor:nwse-resize; }.utility-resizer::after { content:"";position:absolute;right:3px;bottom:3px;width:7px;height:7px;border-right:1px solid var(--fdc-muted);border-bottom:1px solid var(--fdc-muted); }.health-panel,.library-panel { right:auto;max-height:none; }.health-list,.library-body { min-height:0;flex:1; }
1157
- .change-tray { position:fixed;z-index:2147483646;right:var(--fdc-canvas-right,376px);bottom:12px;left:var(--fdc-canvas-left,276px);min-height:0;display:flex;flex-direction:column;align-items:stretch;padding:0;overflow:hidden;color:var(--fdc-ink);background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:11px;box-shadow:0 2px 2px rgb(0 0 0 / 22%),0 18px 48px rgb(0 0 0 / 36%);pointer-events:auto; }.change-tray[hidden] { display:none; }.change-tray-summary { min-height:48px;display:grid;grid-template-columns:minmax(0,1fr) auto 32px 72px;align-items:center;gap:7px;padding:6px 7px 6px 11px; }.change-tray-summary .change-count { margin-right:2px; }.change-tray-summary button { height:32px;border:1px solid var(--fdc-line);border-radius:6px;color:var(--fdc-ink);background:var(--fdc-elevated);cursor:pointer; }.change-tray-summary .tray-compare { width:32px;display:grid;place-items:center;padding:0; }.change-tray-summary .tray-compare svg { width:13px;height:13px; }.change-tray-summary button:disabled { opacity:.35;cursor:not-allowed; }.change-tray.expanded { height:min(420px,45vh); }.change-tray.expanded .change-tray-summary { border-bottom:1px solid var(--fdc-line); }.change-tray .review-view:not([hidden]) { min-width:0;min-height:0;display:flex; }.change-tray .review-body { min-height:0;flex:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));align-content:start;overflow:auto; }.change-tray .review-group { min-width:0;border-right:1px solid var(--fdc-line); }.change-tray .review-actions { flex:none;grid-template-columns:100px minmax(180px,280px);justify-content:end; }.change-tray .review-head { flex:none; }.change-tray .review-head span { margin-left:auto; }
1236
+ select { -webkit-appearance:none;appearance:none;padding-right:32px!important;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%238f8f96' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 6.5 3 3 3-3'/%3E%3C/svg%3E")!important;background-repeat:no-repeat!important;background-position:right 8px center!important;background-size:16px 16px!important; }
1237
+ .control-field .unit-select { width:48px;padding-right:20px!important;padding-left:4px!important;background-position:right 4px center!important;background-size:16px 16px!important; }
1238
+ .layers-panel { top:72px;bottom:auto;max-height:min(560px,calc(100vh - 84px)); }.layers-panel[hidden] { display:none; }.layers-switch { flex:none; }
1239
+ /* Compact tree rhythm: rows use the panel width while hierarchy remains legible. */
1240
+ .layer-tree { padding:4px 4px;scrollbar-gutter:auto;scrollbar-width:thin;scrollbar-color:#4a4a50 transparent; }
1241
+ .layer-tree::-webkit-scrollbar { width:8px; }
1242
+ .layer-tree::-webkit-scrollbar-track { background:transparent; }
1243
+ .layer-tree::-webkit-scrollbar-thumb { background:#4a4a50;border-radius:1000px; }
1244
+ .layer-row { padding-left:calc(4px + var(--layer-depth) * 12px);padding-right:4px; }
1245
+ .layer-selection-glide { right:4px;left:4px; }
1246
+ .layer-toggle,.layer-select { height:32px; }
1247
+ .layer-select { padding-right:4px;padding-left:4px; }
1248
+ .layer-row .layer-meta { margin-right:4px; }
1249
+ .component-list { padding-right:0;padding-left:0; }
1250
+ .component-main { padding-right:8px;padding-left:8px; }
1251
+ .component-variants,.component-actions { padding-right:8px;padding-left:40px; }
1252
+ /* Keep every inspector field on the same 36px interaction rhythm. */
1253
+ .property-control .control-field,.section-grid.two .control-field,.compact-control .control-field { height:36px; }
1254
+ .property-control input,.property-control select,.section-grid.two .compact-control input,.section-grid.two .compact-control select { height:36px; }
1255
+ .control-field>.control-reset { top:4px; }
1256
+ .utility-panel { z-index:2147483646;max-height:none;min-width:280px;min-height:280px;box-shadow:0 4px 4px rgb(0 0 0 / 22%),0 20px 48px rgb(0 0 0 / 42%); }.utility-panel[hidden] { display:none; }.utility-handle { cursor:grab;user-select:none;touch-action:none; }.utility-handle:active { cursor:grabbing; }.utility-resizer { position:absolute;right:4px;bottom:4px;width:20px;height:20px;padding:0;border:0;background:transparent;cursor:nwse-resize; }.utility-resizer::after { content:"";position:absolute;right:4px;bottom:4px;width:8px;height:8px;border-right:1px solid var(--fdc-muted);border-bottom:1px solid var(--fdc-muted); }.health-panel,.library-panel { right:auto;max-height:none; }.health-list,.library-body { min-height:0;flex:1; }
1257
+ .change-tray { position:fixed;z-index:2147483646;right:var(--fdc-canvas-right,376px);bottom:12px;left:var(--fdc-canvas-left,276px);min-height:0;display:flex;flex-direction:column;align-items:stretch;padding:0;overflow:hidden;color:var(--fdc-ink);background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 4px 4px rgb(0 0 0 / 22%),0 20px 48px rgb(0 0 0 / 36%);pointer-events:auto; }.change-tray[hidden] { display:none; }.change-tray-summary { min-height:48px;display:grid;grid-template-columns:minmax(0,1fr) auto 32px 72px;align-items:center;gap:8px;padding:8px 8px 8px 12px; }.change-tray-summary .change-count { margin-right:4px; }.change-tray-summary button { height:32px;border:1px solid var(--fdc-line);border-radius:8px;color:var(--fdc-ink);background:var(--fdc-elevated);cursor:pointer; }.change-tray-summary .tray-compare { width:32px;display:grid;place-items:center;padding:0; }.change-tray-summary .tray-compare svg { width:12px;height:12px; }.change-tray-summary button:disabled { opacity:.35;cursor:not-allowed; }.change-tray.expanded { height:min(420px,45vh); }.change-tray.expanded .change-tray-summary { border-bottom:1px solid var(--fdc-line); }.change-tray .review-view:not([hidden]) { min-width:0;min-height:0;display:flex; }.change-tray .review-body { min-height:0;flex:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));align-content:start;overflow:auto; }.change-tray .review-group { min-width:0;border-right:1px solid var(--fdc-line); }.change-tray .review-actions { flex:none;grid-template-columns:100px minmax(180px,280px);justify-content:end; }.change-tray .review-head { flex:none; }.change-tray .review-head span { margin-left:auto; }
1158
1258
  /* Focused review list */
1159
1259
  .change-tray .review-body { display:block;overflow-x:hidden;overflow-y:auto; }
1160
- .review-overview { position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:12px;min-height:52px;padding:8px 12px;border-bottom:1px solid var(--fdc-line);background:rgb(20 20 22 / 97%);backdrop-filter:blur(10px); }
1260
+ .review-overview { position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:12px;min-height:52px;padding:8px 12px;border-bottom:1px solid var(--fdc-line);background:rgb(20 20 22 / 97%);backdrop-filter:blur(12px); }
1161
1261
  .review-overview .review-summary { min-width:0;flex:1;padding:0;border:0;background:transparent; }
1162
- .review-overview .review-summary strong { overflow:hidden;text-overflow:ellipsis;font-size:11px;white-space:nowrap; }
1163
- .review-overview .review-summary span { overflow:hidden;text-overflow:ellipsis;margin-top:2px;font-size:9px;white-space:nowrap; }
1262
+ .review-overview .review-summary strong { overflow:hidden;text-overflow:ellipsis;font-size:12px;white-space:nowrap; }
1263
+ .review-overview .review-summary span { overflow:hidden;text-overflow:ellipsis;margin-top:4px;font-size:8px;white-space:nowrap; }
1164
1264
  .review-overview .review-toolbar { position:static;z-index:auto;flex:none;padding:0;border:0;background:transparent;backdrop-filter:none; }
1165
- .review-overview .review-toolbar button { height:28px;padding:0 8px;border-color:transparent;background:transparent;color:var(--fdc-muted);font-size:9px; }
1265
+ .review-overview .review-toolbar button { height:28px;padding:0 8px;border-color:transparent;background:transparent;color:var(--fdc-muted);font-size:8px; }
1166
1266
  .review-overview .review-toolbar button:hover { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }
1167
1267
  .change-tray .review-group { border-right:0;border-bottom:1px solid var(--fdc-line); }
1168
- .change-tray .review-group-title { position:sticky;top:52px;z-index:2;min-height:38px;padding:0 12px;background:rgb(28 28 31 / 98%); }
1169
- .review-group-title .included-count { font-size:9px; }
1170
- .review-card { min-height:50px;grid-template-columns:18px minmax(0,1fr);align-items:start;gap:9px;padding:8px 12px; }
1171
- .review-card input[type="checkbox"] { margin-top:7px; }
1172
- .review-card-line { min-height:32px;display:grid;grid-template-columns:minmax(120px,1fr) auto minmax(220px,320px) 30px;align-items:center;gap:8px; }
1173
- .review-card-line>strong { font-size:10px; }
1174
- .review-values { min-width:0;display:grid;grid-template-columns:minmax(72px,1fr) 12px minmax(90px,1fr);align-items:center;gap:5px;margin:0; }
1175
- .review-before { min-width:0;overflow:hidden;text-overflow:ellipsis;padding:0 8px;color:var(--fdc-muted);background:transparent;font-size:10px;text-align:right;white-space:nowrap; }
1176
- .review-after { height:30px;font-size:10px; }
1268
+ .change-tray .review-group-title { position:sticky;top:52px;z-index:2;min-height:40px;padding:0 12px;background:rgb(28 28 31 / 98%); }
1269
+ .review-group-title .included-count { font-size:8px; }
1270
+ .review-card { min-height:52px;grid-template-columns:20px minmax(0,1fr);align-items:start;gap:8px;padding:8px 12px; }
1271
+ .review-card input[type="checkbox"] { margin-top:8px; }
1272
+ .review-card-line { min-height:32px;display:grid;grid-template-columns:minmax(120px,1fr) auto minmax(220px,320px) 32px;align-items:center;gap:8px; }
1273
+ .review-card-line>strong { font-size:12px; }
1274
+ .review-values { min-width:0;display:grid;grid-template-columns:minmax(72px,1fr) 12px minmax(92px,1fr);align-items:center;gap:4px;margin:0; }
1275
+ .review-before { min-width:0;overflow:hidden;text-overflow:ellipsis;padding:0 8px;color:var(--fdc-muted);background:transparent;font-size:12px;text-align:right;white-space:nowrap; }
1276
+ .review-after { height:32px;font-size:12px; }
1177
1277
  .review-more { position:relative;justify-self:end; }
1178
- .review-more>summary { width:28px;height:28px;display:grid;place-items:center;border:1px solid transparent;border-radius:5px;color:var(--fdc-muted);font:600 11px/1 var(--fdc-font);letter-spacing:1px;list-style:none;cursor:pointer; }
1278
+ .review-more>summary { width:28px;height:28px;display:grid;place-items:center;border:1px solid transparent;border-radius:4px;color:var(--fdc-muted);font:600 12px/1 var(--fdc-font);letter-spacing:1px;list-style:none;cursor:pointer; }
1179
1279
  .review-more>summary::-webkit-details-marker { display:none; }
1180
1280
  .review-more>summary:hover,.review-more[open]>summary { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }
1181
- .review-more .review-card-tools { position:absolute;z-index:5;right:0;top:32px;width:260px;display:flex;flex-direction:column;gap:2px;padding:4px;border:1px solid var(--fdc-line);border-radius:7px;background:var(--fdc-elevated);box-shadow:0 10px 24px rgb(0 0 0 / 34%); }
1182
- .review-more .review-card-tools button { width:100%;height:27px;padding:0 7px;border:0;text-align:left;background:transparent; }
1281
+ .review-more .review-card-tools { position:absolute;z-index:5;right:0;top:32px;width:260px;display:flex;flex-direction:column;gap:4px;padding:4px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-elevated);box-shadow:0 12px 24px rgb(0 0 0 / 34%); }
1282
+ .review-more .review-card-tools button { width:100%;height:28px;padding:0 8px;border:0;text-align:left;background:transparent; }
1183
1283
  .review-more .review-card-tools button:hover { background:var(--fdc-subtle); }
1184
- .review-details { margin-top:3px;padding-top:3px;border-top:1px solid var(--fdc-line); }
1185
- .review-details summary { min-height:27px;display:flex;align-items:center;padding:0 7px;color:var(--fdc-muted);font-size:8px;cursor:pointer; }
1186
- .review-details[open] { padding-bottom:6px; }
1187
- .review-details .review-source,.review-details .impact-list { padding-right:7px;padding-left:7px; }
1284
+ .review-details { margin-top:4px;padding-top:4px;border-top:1px solid var(--fdc-line); }
1285
+ .review-details summary { min-height:28px;display:flex;align-items:center;padding:0 8px;color:var(--fdc-muted);font-size:8px;cursor:pointer; }
1286
+ .review-details[open] { padding-bottom:8px; }
1287
+ .review-details .review-source,.review-details .impact-list { padding-right:8px;padding-left:8px; }
1188
1288
  .review-visual { display:none; }
1189
- @media (max-width:980px){.review-card-line{grid-template-columns:minmax(100px,1fr) auto minmax(190px,260px) 30px}.review-overview .review-summary span{display:none}}
1190
- @media (max-width:760px){.review-card-line{grid-template-columns:minmax(0,1fr) auto 30px}.review-values{grid-column:1/-1;width:100%}.review-overview{align-items:flex-start}.review-overview .review-toolbar{margin-left:auto}.review-overview .review-toolbar button{padding:0 6px}}
1191
- .tool-shelf { bottom:calc(18px + var(--fdc-tray-lift,0px)); }.tool-select[hidden],.tool-divider[hidden] { display:none; }.tool-select.interact.active { color:white;background:var(--fdc-signal); }.mode-copy { min-width:88px; }.canvas-actions-divider { margin-left:2px; }.multi-actions-divider { margin-left:2px; }
1192
- .compare-bar { bottom:calc(78px + var(--fdc-tray-lift,0px)); }
1193
- @keyframes fdc-selection-title { from { opacity:.45;transform:translateY(2px) } to { opacity:1;transform:none } }
1194
- @media (max-width:680px){.workspace-bar{right:8px;left:8px;transform:none;overflow-x:auto}.workspace-bar .brand{padding-right:3px}.workspace-bar .brand-copy{display:none}.workspace-bar .status-popover{position:fixed;top:66px;right:8px;left:8px;width:auto}.panel{top:auto;right:8px;bottom:74px;left:8px;width:auto;max-height:56vh}.layers-panel{top:68px;right:8px;bottom:auto;left:8px;width:auto;max-height:42vh}.utility-panel{top:68px!important;right:8px!important;bottom:74px!important;left:8px!important;width:auto!important;height:auto!important;max-height:none}.utility-resizer{display:none}.scope{display:grid;grid-template-columns:1fr 1fr}.controls{min-height:170px}.change-tray{right:8px;bottom:8px;left:8px}.change-tray.expanded{height:48vh}.change-tray .review-body{grid-template-columns:1fr}.tool-shelf{right:8px;bottom:calc(8px + var(--fdc-tray-lift,0px));left:8px;transform:none;max-width:none}.mode-copy{min-width:0}.mode-copy span{display:none}.tool-select::after,.tab::after{display:none}.onboarding-card{right:12px;bottom:68px;left:12px;width:auto;transform:none}.workbench-controls select,.workbench-controls button:not(.icon-button){max-width:92px}.workbench-matrix{grid-template-columns:76px repeat(var(--matrix-columns),minmax(90px,1fr))}}
1195
- @media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}}
1289
+ @media (max-width:980px){.review-card-line{grid-template-columns:minmax(100px,1fr) auto minmax(192px,260px) 32px}.review-overview .review-summary span{display:none}}
1290
+ @media (max-width:760px){.review-card-line{grid-template-columns:minmax(0,1fr) auto 32px}.review-values{grid-column:1/-1;width:100%}.review-overview{align-items:flex-start}.review-overview .review-toolbar{margin-left:auto}.review-overview .review-toolbar button{padding:0 8px}}
1291
+ .tool-shelf { bottom:calc(20px + var(--fdc-tray-lift,0px)); }.tool-select[hidden],.tool-divider[hidden] { display:none; }.tool-select.interact.active { color:white;background:var(--fdc-signal); }.mode-copy { min-width:88px; }.canvas-actions-divider { margin-left:4px; }.multi-actions-divider { margin-left:4px; }
1292
+ .compare-bar { bottom:calc(80px + var(--fdc-tray-lift,0px)); }
1293
+ @keyframes fdc-selection-title { from { opacity:.45;transform:translateY(4px) } to { opacity:1;transform:none } }
1294
+ @media (max-width:680px){.workspace-bar{right:8px;left:8px;transform:none;overflow-x:auto}.workspace-bar .brand{padding-right:4px}.workspace-bar .brand-copy{display:none}.workspace-bar .status-popover{position:fixed;top:68px;right:8px;left:8px;width:auto}.panel{top:calc(76px + min(32vh,220px));right:8px;bottom:76px;left:8px;width:auto;max-height:none}.layers-panel{top:68px;right:8px;bottom:auto;left:8px;width:auto;max-height:min(32vh,220px)}.utility-panel{top:68px!important;right:8px!important;bottom:76px!important;left:8px!important;width:auto!important;height:auto!important;max-height:none}.utility-resizer{display:none}.scope{display:grid;grid-template-columns:1fr 1fr}.controls{min-height:172px}.change-tray{right:8px;bottom:8px;left:8px}.change-tray.expanded{height:48vh}.change-tray .review-body{grid-template-columns:1fr}.tool-shelf{right:8px;bottom:calc(8px + var(--fdc-tray-lift,0px));left:8px;transform:none;max-width:none}.mode-copy{min-width:0}.mode-copy span{display:none}.tool-select::after,.tab::after{display:none}.onboarding-card{right:12px;bottom:68px;left:12px;width:auto;transform:none}.workbench-controls select,.workbench-controls button:not(.icon-button){max-width:92px}.workbench-matrix{grid-template-columns:76px repeat(var(--matrix-columns),minmax(92px,1fr))}}
1295
+ /* Shared dock geometry and focused review takeover. */
1296
+ .panel,.layers-panel,.change-tray { width:var(--fdc-dock-width,384px); }
1297
+ .layers-panel { max-width:min(520px,calc(100vw - 24px)); }
1298
+ .change-tray { z-index:2147483647;right:12px;bottom:12px;left:auto;height:48px;min-height:48px; }
1299
+ .change-tray-summary { min-height:48px;grid-template-columns:minmax(0,1fr) 32px 72px; }
1300
+ .panel.change-summary-visible .inspector-scroll { padding-bottom:60px;scroll-padding-bottom:60px; }
1301
+ .tool-shelf { bottom:20px; }
1302
+ .compare-bar { bottom:80px; }
1303
+ .review-takeover { position:fixed;z-index:2147483647;inset:0;display:grid;place-items:center;padding:24px;background:rgb(8 8 10 / 72%);backdrop-filter:blur(8px);pointer-events:auto; }
1304
+ .review-takeover[hidden] { display:none; }
1305
+ .review-modal { width:min(1120px,calc(100vw - 48px));height:min(760px,calc(100vh - 48px));display:flex;overflow:hidden;color:var(--fdc-ink);background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 24px 80px rgb(0 0 0 / 52%); }
1306
+ .review-modal .review-view { width:100%;min-width:0;min-height:0;display:flex; }
1307
+ .review-modal .review-head { flex:none;min-height:52px;padding:0 16px; }
1308
+ .review-modal .review-body { min-height:0;flex:1;display:block;overflow-x:hidden;overflow-y:auto; }
1309
+ .review-modal .review-group { border-right:0;border-bottom:1px solid var(--fdc-line); }
1310
+ .review-modal .review-group-title { position:sticky;top:52px;z-index:2;background:rgb(28 28 31 / 98%); }
1311
+ .review-modal .review-actions { position:sticky;bottom:0;flex:none;grid-template-columns:100px minmax(220px,320px);justify-content:end;padding:12px 16px;background:rgb(28 28 31 / 98%);backdrop-filter:blur(12px); }
1312
+ /* Review is a reading surface, so it uses a larger type scale than the dense inspector. */
1313
+ .review-modal .review-head strong { font-size:16px;font-weight:600;letter-spacing:-.015em; }
1314
+ .review-modal .review-head span { font-size:12px; }
1315
+ .review-modal .review-overview { min-height:60px;padding:12px 16px; }
1316
+ .review-modal .review-overview .review-summary strong { font-size:16px;font-weight:600; }
1317
+ .review-modal .review-overview .review-summary span { margin-top:4px;font-size:12px;line-height:1.45; }
1318
+ .review-modal .review-overview .review-toolbar button { height:36px;padding:0 12px;font-size:12px; }
1319
+ .review-modal .review-group-title { min-height:48px;padding:0 16px;font-size:12px; }
1320
+ .review-modal .review-group-title strong { font-size:16px;font-weight:600; }
1321
+ .review-modal .review-group-title .included-count,.review-modal .review-group-title .group-total { font-size:12px; }
1322
+ .review-modal .review-card { min-height:64px;gap:12px;padding:12px 16px; }
1323
+ .review-modal .review-card input[type="checkbox"] { width:16px;height:16px;margin-top:8px; }
1324
+ .review-modal .review-card-line { min-height:36px;gap:12px; }
1325
+ .review-modal .review-card-line>strong { font-size:16px;font-weight:550; }
1326
+ .review-modal .confidence-pill { padding:4px 8px;font-size:12px; }
1327
+ .review-modal .review-before { padding:0 8px;font-size:12px; }
1328
+ .review-modal .review-after { height:36px;padding:0 12px;font-size:12px; }
1329
+ .review-modal .review-more>summary { width:32px;height:32px;font-size:12px; }
1330
+ .review-modal .review-more .review-card-tools { top:36px; }
1331
+ .review-modal .review-more .review-card-tools button { height:32px;padding:0 8px;font-size:12px; }
1332
+ .review-modal .review-details summary { min-height:32px;font-size:12px; }
1333
+ .review-modal .review-source { font-size:12px;line-height:1.5; }
1334
+ .review-modal .impact-list,.review-modal .impact-list li { font-size:12px;line-height:1.5; }
1335
+ .review-modal .review-actions button { min-height:44px;font-size:12px;font-weight:550; }
1336
+ .review-modal .run-state strong { font-size:16px; }
1337
+ .review-modal .run-summary p { font-size:12px; }
1338
+ .review-modal .run-step strong,.review-modal .result-row { font-size:12px; }
1339
+ .review-modal .run-step p,.review-modal .run-files { font-size:12px; }
1340
+ .interface-theme-menu { position:fixed;z-index:2147483647;width:164px;padding:4px;border:1px solid var(--fdc-line);border-radius:8px;color:var(--fdc-ink);background:var(--fdc-elevated);box-shadow:0 16px 36px rgb(0 0 0 / 34%);pointer-events:auto; }
1341
+ .interface-theme-menu[hidden] { display:none; }
1342
+ .interface-theme-menu button { width:100%;height:32px;display:grid;grid-template-columns:minmax(0,1fr) 16px;align-items:center;padding:0 8px;border:0;border-radius:4px;color:var(--fdc-muted);background:transparent;font-size:12px;text-align:left;cursor:pointer; }
1343
+ .interface-theme-menu button:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }
1344
+ .interface-theme-menu button[aria-checked="true"] { color:var(--fdc-ink);background:var(--fdc-subtle); }
1345
+ .interface-theme-menu button svg { width:12px;height:12px;color:var(--fdc-signal); }
1346
+ .interface-theme-menu button:not([aria-checked="true"]) svg { visibility:hidden; }
1347
+ :host([data-interface-theme="light"]) { color-scheme:light;--fdc-ink:#141416;--fdc-paper:#f0f1f3;--fdc-surface:#ffffff;--fdc-subtle:#f0f1f3;--fdc-elevated:#f7f7f8;--fdc-line:#dedfe2;--fdc-signal:#2563eb;--fdc-signal-soft:#e8f0ff;--fdc-component:#7259d6;--fdc-component-soft:#f0edff;--fdc-muted:#666870; }
1348
+ :host([data-interface-theme="light"]) .panel,:host([data-interface-theme="light"]) .layers-panel,:host([data-interface-theme="light"]) .health-panel,:host([data-interface-theme="light"]) .library-panel,:host([data-interface-theme="light"]) .tool-shelf,:host([data-interface-theme="light"]) .onboarding-card,:host([data-interface-theme="light"]) .compare-bar,:host([data-interface-theme="light"]) .command-palette,:host([data-interface-theme="light"]) .status-popover,:host([data-interface-theme="light"]) .canvas-variant,:host([data-interface-theme="light"]) .workspace-bar,:host([data-interface-theme="light"]) .change-tray,:host([data-interface-theme="light"]) .review-modal { color:var(--fdc-ink);background:rgb(255 255 255 / 97%);border-color:var(--fdc-line);box-shadow:0 1px 4px rgb(0 0 0 / 8%),0 16px 36px rgb(0 0 0 / 14%); }
1349
+ :host([data-interface-theme="light"]) .top,:host([data-interface-theme="light"]) .top-actions,:host([data-interface-theme="light"]) .selection,:host([data-interface-theme="light"]) .scope,:host([data-interface-theme="light"]) .controls,:host([data-interface-theme="light"]) .property-section,:host([data-interface-theme="light"]) .change-dock,:host([data-interface-theme="light"]) .footer,:host([data-interface-theme="light"]) .review-view,:host([data-interface-theme="light"]) .review-head,:host([data-interface-theme="light"]) .review-group,:host([data-interface-theme="light"]) .review-group-title,:host([data-interface-theme="light"]) .review-actions,:host([data-interface-theme="light"]) .layers-head,:host([data-interface-theme="light"]) .layer-tree,:host([data-interface-theme="light"]) .health-head,:host([data-interface-theme="light"]) .health-list,:host([data-interface-theme="light"]) .health-footer,:host([data-interface-theme="light"]) .library-head,:host([data-interface-theme="light"]) .library-actions,:host([data-interface-theme="light"]) .library-body,:host([data-interface-theme="light"]) .memory-card,:host([data-interface-theme="light"]) .context-tools,:host([data-interface-theme="light"]) .native-panel,:host([data-interface-theme="light"]) .section-head,:host([data-interface-theme="light"]) .onboarding-step { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }
1350
+ :host([data-interface-theme="light"]) .inspector-heading,:host([data-interface-theme="light"]) .review-toolbar,:host([data-interface-theme="light"]) .review-overview,:host([data-interface-theme="light"]) .review-modal .review-actions { color:var(--fdc-ink);background:rgb(255 255 255 / 97%);border-color:var(--fdc-line); }
1351
+ :host([data-interface-theme="light"]) .review-modal .review-group-title { background:rgb(247 247 248 / 98%); }
1352
+ :host([data-interface-theme="light"]) .property-label,:host([data-interface-theme="light"]) .section-head,:host([data-interface-theme="light"]) .color-value,:host([data-interface-theme="light"]) .layer-row,:host([data-interface-theme="light"]) .command-item,:host([data-interface-theme="light"]) .library-section-head { color:#303136; }
1353
+ :host([data-interface-theme="light"]) .selection-path button,:host([data-interface-theme="light"]) .control-field,:host([data-interface-theme="light"]) .native-search,:host([data-interface-theme="light"]) .layers-search input,:host([data-interface-theme="light"]) .review-after,:host([data-interface-theme="light"]) .review-toolbar button,:host([data-interface-theme="light"]) .review-card-tools button,:host([data-interface-theme="light"]) .review-actions button,:host([data-interface-theme="light"]) .change-dock button,:host([data-interface-theme="light"]) .footer button,:host([data-interface-theme="light"]) .status-popover button,:host([data-interface-theme="light"]) .health-actions button,:host([data-interface-theme="light"]) .health-footer button,:host([data-interface-theme="light"]) .context-tools button,:host([data-interface-theme="light"]) .native-chip,:host([data-interface-theme="light"]) .variant-button,:host([data-interface-theme="light"]) .library-actions button,:host([data-interface-theme="light"]) .memory-card-actions button,:host([data-interface-theme="light"]) .empty-state-actions button,:host([data-interface-theme="light"]) .onboarding-actions button { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }
1354
+ :host([data-interface-theme="light"]) .scope select,:host([data-interface-theme="light"]) .property-control input,:host([data-interface-theme="light"]) .property-control select,:host([data-interface-theme="light"]) .compact-control input,:host([data-interface-theme="light"]) .compact-control select,:host([data-interface-theme="light"]) .native-search,:host([data-interface-theme="light"]) .command-palette input { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }
1355
+ :host([data-interface-theme="light"]) .scope select option,:host([data-interface-theme="light"]) .property-control select option,:host([data-interface-theme="light"]) .compact-control select option { color:var(--fdc-ink);background:var(--fdc-surface); }
1356
+ :host([data-interface-theme="light"]) .layers-search,:host([data-interface-theme="light"]) .layers-switch,:host([data-interface-theme="light"]) .review-summary { background:var(--fdc-paper);border-color:var(--fdc-line); }
1357
+ :host([data-interface-theme="light"]) .layers-switch button:hover,:host([data-interface-theme="light"]) .layers-switch button.active,:host([data-interface-theme="light"]) .health-filters button:hover,:host([data-interface-theme="light"]) .health-filters button.active { color:var(--fdc-ink);background:var(--fdc-surface); }
1358
+ :host([data-interface-theme="light"]) .component-card,:host([data-interface-theme="light"]) .health-card { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }
1359
+ :host([data-interface-theme="light"]) .layer-row.selected { color:#1458b8;background:transparent; }
1360
+ :host([data-interface-theme="light"]) .layer-row .layer-meta { color:#65676e;background:var(--fdc-subtle); }
1361
+ :host([data-interface-theme="light"]) .layer-row.selected .layer-meta { color:#1458b8;background:#dceaff; }
1362
+ :host([data-interface-theme="light"]) .tool-select.active,:host([data-interface-theme="light"]) .tab.active { color:var(--fdc-ink);background:#e4e5e8; }
1363
+ :host([data-interface-theme="light"]) .tool-select.inspect.active { color:white;background:var(--fdc-signal); }
1364
+ :host([data-interface-theme="light"]) .change-dock .dock-review,:host([data-interface-theme="light"]) .review-actions .apply,:host([data-interface-theme="light"]) .health-footer .health-rescan { color:#f0f1f3;background:#141416;border-color:#141416; }
1365
+ :host([data-interface-theme="light"]) .session-status,:host([data-interface-theme="light"]) .session-status.saved { color:#236c59;background:#eef8f4; }
1366
+ :host([data-interface-theme="light"]) .interface-theme-menu { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line);box-shadow:0 16px 36px rgb(0 0 0 / 16%); }
1367
+ .control-field { height:36px;border-radius:8px; }
1368
+ .compact-control .field-prefix,.compact-control .field-prefix.wide { width:36px;min-width:36px;height:100%;display:grid;place-items:center;padding:0;border-right:1px solid var(--fdc-line);background:rgb(255 255 255 / 2%);color:var(--fdc-muted);font:500 12px/1 var(--fdc-font); }
1369
+ .field-prefix svg { width:12px;height:12px; }
1370
+ .property-control input,.property-control select,.compact-control input,.compact-control select { height:36px;font-size:12px;font-weight:400; }
1371
+ .control-field .unit-select { width:44px;padding-right:24px!important;background-position:right 8px center!important; }
1372
+ .section-grid { gap:8px;padding:0 16px 16px; }
1373
+ @media (max-width:680px){.panel,.layers-panel{width:auto}.panel-resizer{display:none}.change-tray{right:8px;bottom:8px;left:auto;width:calc(100vw - 16px)}.review-takeover{padding:8px}.review-modal{width:calc(100vw - 16px);height:calc(100vh - 16px);border-radius:12px}.review-modal .review-actions{grid-template-columns:84px 1fr}.panel.change-summary-visible .inspector-scroll{padding-bottom:60px}}
1374
+ @media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}.layer-row.entering,.layer-branch{animation:none!important}}
1196
1375
  `;
1197
1376
  function numberFrom(value) {
1198
1377
  const parsed = Number.parseFloat(value);
1199
1378
  return Number.isFinite(parsed) ? parsed : 0;
1200
1379
  }
1201
- function pxControl(element, computed, category, property, label, max = 600) {
1380
+ function pxControl(element, computed, category, property, label, max = 600, min = 0) {
1202
1381
  return {
1203
1382
  category,
1204
1383
  property: String(property),
@@ -1206,7 +1385,7 @@ function pxControl(element, computed, category, property, label, max = 600) {
1206
1385
  kind: "number",
1207
1386
  value: numberFrom(String(computed[property])),
1208
1387
  unit: "px",
1209
- min: 0,
1388
+ min,
1210
1389
  max,
1211
1390
  step: 1,
1212
1391
  read: () => numberFrom(getComputedStyle(element)[property]),
@@ -1248,6 +1427,45 @@ function numberStyleControl(element, computed, category, property, label, min, m
1248
1427
  )
1249
1428
  };
1250
1429
  }
1430
+ function degreeControl(element, computed) {
1431
+ const read = () => numberFrom(getComputedStyle(element).rotate || "0");
1432
+ return {
1433
+ category: "layout",
1434
+ property: "rotate",
1435
+ label: "Rotation",
1436
+ kind: "number",
1437
+ value: numberFrom(computed.rotate || "0"),
1438
+ unit: "deg",
1439
+ min: -360,
1440
+ max: 360,
1441
+ step: 1,
1442
+ read,
1443
+ apply: (value) => element.style.setProperty("rotate", `${value}deg`)
1444
+ };
1445
+ }
1446
+ function scaleAxisControl(element, computed, axis) {
1447
+ const readScale = () => {
1448
+ const raw = getComputedStyle(element).scale;
1449
+ if (!raw || raw === "none") return [1, 1];
1450
+ const values = raw.split(/\s+/).map(numberFrom);
1451
+ return [values[0] || 1, values[1] ?? values[0] ?? 1];
1452
+ };
1453
+ const initial = computed.scale && computed.scale !== "none" ? readScale() : [1, 1];
1454
+ return {
1455
+ category: "layout",
1456
+ property: axis === "x" ? "scaleX" : "scaleY",
1457
+ label: axis === "x" ? "Flip horizontal" : "Flip vertical",
1458
+ kind: "select",
1459
+ options: ["1", "-1"],
1460
+ value: String(axis === "x" ? initial[0] : initial[1]),
1461
+ read: () => String(axis === "x" ? readScale()[0] : readScale()[1]),
1462
+ apply: (value) => {
1463
+ const current = readScale();
1464
+ current[axis === "x" ? 0 : 1] = Number(value);
1465
+ element.style.setProperty("scale", `${current[0]} ${current[1]}`);
1466
+ }
1467
+ };
1468
+ }
1251
1469
  function sizingModeControl(element, computed, axis) {
1252
1470
  const capitalized = axis === "width" ? "Width" : "Height";
1253
1471
  const minProperty = axis === "width" ? "minWidth" : "minHeight";
@@ -1292,6 +1510,10 @@ function sizingModeControl(element, computed, axis) {
1292
1510
  function controlsFor(element) {
1293
1511
  const computed = getComputedStyle(element);
1294
1512
  const controls = [
1513
+ ...computed.position !== "static" ? [
1514
+ pxControl(element, computed, "layout", "left", "X position", 5e3, -5e3),
1515
+ pxControl(element, computed, "layout", "top", "Y position", 5e3, -5e3)
1516
+ ] : [],
1295
1517
  sizingModeControl(element, computed, "width"),
1296
1518
  sizingModeControl(element, computed, "height"),
1297
1519
  styleControl(element, computed, "layout", "minWidth", "Minimum width"),
@@ -1304,6 +1526,9 @@ function controlsFor(element) {
1304
1526
  "auto",
1305
1527
  "scroll"
1306
1528
  ]),
1529
+ degreeControl(element, computed),
1530
+ scaleAxisControl(element, computed, "x"),
1531
+ scaleAxisControl(element, computed, "y"),
1307
1532
  pxControl(element, computed, "layout", "width", "Width", 1600),
1308
1533
  pxControl(element, computed, "layout", "height", "Height", 1200),
1309
1534
  styleControl(element, computed, "layout", "display", "Display", "select", [
@@ -1360,6 +1585,10 @@ function controlsFor(element) {
1360
1585
  numberStyleControl(element, computed, "color", "opacity", "Opacity", 0, 1, 0.05),
1361
1586
  styleControl(element, computed, "color", "backgroundImage", "Gradient"),
1362
1587
  pxControl(element, computed, "effects", "borderRadius", "Corner radius", 200),
1588
+ pxControl(element, computed, "effects", "borderTopLeftRadius", "Top left radius", 200),
1589
+ pxControl(element, computed, "effects", "borderTopRightRadius", "Top right radius", 200),
1590
+ pxControl(element, computed, "effects", "borderBottomLeftRadius", "Bottom left radius", 200),
1591
+ pxControl(element, computed, "effects", "borderBottomRightRadius", "Bottom right radius", 200),
1363
1592
  pxControl(element, computed, "effects", "borderWidth", "Border width", 32),
1364
1593
  styleControl(element, computed, "effects", "borderColor", "Border color", "color"),
1365
1594
  styleControl(element, computed, "effects", "boxShadow", "Shadow"),
@@ -1465,15 +1694,67 @@ function controlsFor(element) {
1465
1694
  }
1466
1695
  });
1467
1696
  }
1468
- return controls;
1697
+ const textBearing = element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || Boolean(element.textContent?.trim());
1698
+ const editableText = element.childElementCount === 0 || ["BUTTON", "A", "LABEL", "SUMMARY"].includes(element.tagName);
1699
+ return controls.filter((control) => {
1700
+ if (control.category === "typography") return textBearing;
1701
+ if (control.property === "textContent") return textBearing && editableText;
1702
+ if (control.property === "color") return textBearing;
1703
+ return true;
1704
+ });
1469
1705
  }
1470
1706
  function colorForInput(value) {
1471
1707
  const canvas = document.createElement("canvas");
1472
1708
  canvas.width = canvas.height = 1;
1473
1709
  const context = canvas.getContext("2d");
1474
1710
  if (!context) return "#000000";
1711
+ context.fillStyle = "#000000";
1475
1712
  context.fillStyle = value;
1476
- return context.fillStyle.startsWith("#") ? context.fillStyle : "#000000";
1713
+ const normalized = context.fillStyle;
1714
+ if (normalized.startsWith("#")) return normalized;
1715
+ const channels = normalized.match(/[\d.]+/g)?.slice(0, 3).map(Number);
1716
+ if (!channels || channels.length < 3) return "#000000";
1717
+ return `#${channels.map((channel2) => Math.round(channel2).toString(16).padStart(2, "0")).join("")}`;
1718
+ }
1719
+ function hexChannels(value) {
1720
+ const hex = colorForInput(value).slice(1);
1721
+ return [
1722
+ Number.parseInt(hex.slice(0, 2), 16),
1723
+ Number.parseInt(hex.slice(2, 4), 16),
1724
+ Number.parseInt(hex.slice(4, 6), 16)
1725
+ ];
1726
+ }
1727
+ function colorAlpha(value) {
1728
+ const slash = value.match(/\/\s*([\d.]+)%?\s*\)/);
1729
+ if (slash) return value.includes("%") ? Number(slash[1]) / 100 : Number(slash[1]);
1730
+ const comma = value.match(/rgba?\([^)]*,\s*([\d.]+)\s*\)$/);
1731
+ return comma ? Number(comma[1]) : isTransparentColor(value) ? 0 : 1;
1732
+ }
1733
+ function rgbToHsv(red, green, blue) {
1734
+ const r = red / 255;
1735
+ const g = green / 255;
1736
+ const b = blue / 255;
1737
+ const maximum = Math.max(r, g, b);
1738
+ const minimum = Math.min(r, g, b);
1739
+ const delta = maximum - minimum;
1740
+ let hue = 0;
1741
+ if (delta) {
1742
+ if (maximum === r) hue = 60 * ((g - b) / delta % 6);
1743
+ else if (maximum === g) hue = 60 * ((b - r) / delta + 2);
1744
+ else hue = 60 * ((r - g) / delta + 4);
1745
+ }
1746
+ if (hue < 0) hue += 360;
1747
+ return [hue, maximum ? delta / maximum : 0, maximum];
1748
+ }
1749
+ function hsvToRgb(hue, saturation, value) {
1750
+ const chroma = value * saturation;
1751
+ const x = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
1752
+ const match = value - chroma;
1753
+ const [r, g, b] = hue < 60 ? [chroma, x, 0] : hue < 120 ? [x, chroma, 0] : hue < 180 ? [0, chroma, x] : hue < 240 ? [0, x, chroma] : hue < 300 ? [x, 0, chroma] : [chroma, 0, x];
1754
+ return [r, g, b].map((channel2) => Math.round((channel2 + match) * 255));
1755
+ }
1756
+ function rgbHex(red, green, blue) {
1757
+ return `#${[red, green, blue].map((channel2) => Math.max(0, Math.min(255, channel2)).toString(16).padStart(2, "0")).join("")}`;
1477
1758
  }
1478
1759
  function escapeHtml(value) {
1479
1760
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
@@ -1497,7 +1778,7 @@ function renderControlInput(control, index) {
1497
1778
  const rawValue = String(control.value);
1498
1779
  const value2 = colorForInput(rawValue);
1499
1780
  const transparent = isTransparentColor(rawValue);
1500
- return `<span class="color-swatch ${transparent ? "transparent" : ""}" style="--swatch-color:${value2}"></span><span class="color-value">${transparent ? "Transparent" : escapeHtml(value2.toUpperCase())}</span><input class="color-picker" id="${id}" data-control="${index}" aria-label="${escapeHtml(control.label)}" type="color" value="${escapeHtml(value2)}"/>`;
1781
+ return `<button type="button" class="color-picker-trigger" id="${id}" data-color-control="${index}" aria-label="Edit ${escapeHtml(control.label)}"><span class="color-swatch ${transparent ? "transparent" : ""}" style="--swatch-color:${value2}"></span><span class="color-value">${transparent ? "Transparent" : escapeHtml(value2.toUpperCase())}</span></button>`;
1501
1782
  }
1502
1783
  const type = control.kind === "number" ? "number" : "text";
1503
1784
  const value = displayValue(control);
@@ -1513,7 +1794,9 @@ function renderPropertyControl(control, index, prefix) {
1513
1794
  const reset = `<button type="button" class="control-reset" data-reset-control="${index}" title="Reset ${escapeHtml(control.label)}" aria-label="Reset ${escapeHtml(control.label)}"><i data-foundry-icon="rotate-ccw"></i></button>`;
1514
1795
  const scrubAttributes = control.kind === "number" ? ` data-scrub-for="${index}" title="Drag left or right to adjust ${escapeHtml(control.label)}. Hold Shift for larger steps or Option for finer steps."` : "";
1515
1796
  if (prefix) {
1516
- return `<label class="compact-control"><span class="sr-only">${escapeHtml(control.label)}</span><span class="control-field"><span class="field-prefix ${prefix.length > 2 ? "wide" : ""}"${scrubAttributes}>${escapeHtml(prefix)}</span>${field}${reset}</span></label>`;
1797
+ const prefixIcon = prefix === "Ratio" ? "maximize-2" : prefix === "Clip" ? "box" : void 0;
1798
+ const prefixContent = prefixIcon ? `<i data-foundry-icon="${prefixIcon}"></i>` : escapeHtml(prefix);
1799
+ return `<label class="compact-control"><span class="sr-only">${escapeHtml(control.label)}</span><span class="control-field"><span class="field-prefix" aria-hidden="true" title="${escapeHtml(control.label)}"${scrubAttributes}>${prefixContent}</span>${field}${reset}</span></label>`;
1517
1800
  }
1518
1801
  return `<label class="property-control"><span class="property-label"${scrubAttributes}>${escapeHtml(control.label)}</span><span class="control-field">${field}${reset}</span></label>`;
1519
1802
  }
@@ -1535,7 +1818,14 @@ function installFoundryInspector(options = {}) {
1535
1818
  const sessionId = options.sessionId ?? query.get("__foundry_session") ?? "";
1536
1819
  const token = options.token ?? query.get("__foundry_token") ?? "";
1537
1820
  const host = document.createElement("div");
1821
+ const interfaceThemeKey = "__foundry_interface_theme";
1822
+ const systemDarkTheme = window.matchMedia("(prefers-color-scheme: dark)");
1823
+ const storedInterfaceTheme = localStorage.getItem(interfaceThemeKey);
1824
+ let interfaceThemePreference = storedInterfaceTheme === "light" || storedInterfaceTheme === "dark" ? storedInterfaceTheme : "system";
1825
+ const resolvedInterfaceTheme = () => resolveInterfaceTheme(interfaceThemePreference, systemDarkTheme.matches);
1538
1826
  host.dataset.foundryOverlay = "true";
1827
+ host.dataset.interfaceTheme = resolvedInterfaceTheme();
1828
+ host.dataset.interfaceThemePreference = interfaceThemePreference;
1539
1829
  const shadow = host.attachShadow({ mode: "open" });
1540
1830
  shadow.innerHTML = `<style>${PANEL_CSS}</style>
1541
1831
  <div class="outline" hidden><span class="cross"></span><span class="measure"></span></div>
@@ -1551,13 +1841,15 @@ function installFoundryInspector(options = {}) {
1551
1841
  <button class="icon-button open-workbench" title="State workbench" aria-label="Open state workbench" aria-pressed="false"><i data-foundry-icon="play"></i></button>
1552
1842
  <button class="icon-button open-library" title="Design memory" aria-label="Open design memory" aria-pressed="false"><i data-foundry-icon="bookmark"></i></button>
1553
1843
  <button class="icon-button open-commands" title="Commands" aria-label="Open commands"><i data-foundry-icon="command"></i></button>
1844
+ <button class="icon-button interface-theme-trigger" title="Interface theme: System" aria-label="Interface theme: System" aria-haspopup="menu" aria-expanded="false"><i data-foundry-icon="contrast"></i></button>
1554
1845
  </nav>
1555
1846
  <span class="workspace-divider"></span>
1556
1847
  <button class="icon-button close" title="Exit Foundry" aria-label="Exit Foundry"><i data-foundry-icon="x"></i></button>
1557
1848
  </header>
1849
+ <div class="interface-theme-menu" role="menu" aria-label="Interface theme" hidden><button role="menuitemradio" aria-checked="true" data-interface-theme-choice="system"><span>System</span><i data-foundry-icon="check"></i></button><button role="menuitemradio" aria-checked="false" data-interface-theme-choice="light"><span>Light</span><i data-foundry-icon="check"></i></button><button role="menuitemradio" aria-checked="false" data-interface-theme-choice="dark"><span>Dark</span><i data-foundry-icon="check"></i></button></div>
1558
1850
  <aside class="layers-panel" aria-label="Foundry layers" hidden>
1559
1851
  <div class="layers-head"><i data-foundry-icon="layers-3"></i><strong>Layers</strong><span data-layer-count></span><button class="icon-button close-layers" aria-label="Close layers"><i data-foundry-icon="x"></i></button></div>
1560
- <div class="layers-search"><input type="search" aria-label="Search layers" placeholder="Search layers" /></div><div class="layer-tree"></div>
1852
+ <div class="layers-search"><input type="search" aria-label="Search layers" placeholder="Search layers" /></div><div class="layer-tree" role="tree" aria-label="Canvas layers"></div>
1561
1853
  </aside>
1562
1854
  <aside class="health-panel utility-panel" data-utility="health" aria-label="Design health" hidden>
1563
1855
  <div class="health-head utility-handle"><i data-foundry-icon="activity"></i><strong>Design health</strong><button class="icon-button close-health" aria-label="Close design health"><i data-foundry-icon="x"></i></button></div>
@@ -1572,8 +1864,10 @@ function installFoundryInspector(options = {}) {
1572
1864
  </div>
1573
1865
  </aside>
1574
1866
  <section class="change-dock change-tray" aria-label="Foundry changes" hidden>
1575
- <div class="change-tray-summary"><div class="change-dock-copy"><strong data-dock-count>No changes</strong><span data-dock-last>Edits will appear here</span></div><span class="change-count" hidden>0</span><button class="tray-compare" title="Compare changes" aria-label="Compare changes" disabled><i data-foundry-icon="contrast"></i></button><button class="dock-review">Review</button></div>
1576
- <div class="review-view" hidden><div class="review-head"><button class="review-back" aria-label="Collapse change tray"><i data-foundry-icon="chevron-down"></i></button><strong>Review and apply</strong><span class="review-count"></span></div><div class="review-body"></div><div class="review-actions"><button class="review-cancel">Collapse</button><button class="apply">Apply with agent</button></div></div>
1867
+ <div class="change-tray-summary"><div class="change-dock-copy"><strong data-dock-count>No changes</strong><span data-dock-last>Edits will appear here</span></div><button class="tray-compare" title="Compare changes" aria-label="Compare changes" disabled><i data-foundry-icon="contrast"></i></button><button class="dock-review">Review</button></div>
1868
+ </section>
1869
+ <section class="review-takeover" role="dialog" aria-modal="true" aria-label="Review and apply changes" hidden>
1870
+ <div class="review-modal"><div class="review-view"><div class="review-head"><button class="review-back" aria-label="Back to canvas"><i data-foundry-icon="arrow-left"></i></button><strong>Review and apply</strong><span class="review-count"></span></div><div class="review-body"></div><div class="review-actions"><button class="review-cancel">Back</button><button class="apply">Apply with agent</button></div></div></div>
1577
1871
  </section>
1578
1872
  <div class="tool-shelf" role="toolbar" aria-label="Canvas tools"><button class="tool-select inspect" data-tooltip="Select" title="Select: click any element" aria-label="Select mode" aria-pressed="true"><i data-foundry-icon="mouse-pointer-2"></i></button><button class="tool-select interact" data-tooltip="Interact" title="Interact with the app" aria-label="Interact mode" aria-pressed="false"><i data-foundry-icon="interact"></i></button></div>
1579
1873
  <div class="toast"></div>`;
@@ -1611,8 +1905,15 @@ function installFoundryInspector(options = {}) {
1611
1905
  commandPalette.className = "command-palette";
1612
1906
  commandPalette.hidden = true;
1613
1907
  commandPalette.setAttribute("aria-label", "Foundry commands");
1614
- commandPalette.innerHTML = `<input type="search" aria-label="Search commands" placeholder="Type a command"/><div class="command-list"></div>`;
1908
+ commandPalette.setAttribute("role", "dialog");
1909
+ commandPalette.innerHTML = `<div class="command-search"><input type="search" aria-label="Search commands" placeholder="Type a command"/><button class="icon-button close-commands" aria-label="Close commands" title="Close commands"><i data-foundry-icon="x"></i></button></div><div class="command-list"></div>`;
1615
1910
  shadow.append(commandPalette);
1911
+ const colorPopover = document.createElement("section");
1912
+ colorPopover.className = "color-popover";
1913
+ colorPopover.hidden = true;
1914
+ colorPopover.setAttribute("role", "dialog");
1915
+ colorPopover.setAttribute("aria-label", "Color editor");
1916
+ shadow.append(colorPopover);
1616
1917
  const libraryPanel = document.createElement("aside");
1617
1918
  libraryPanel.className = "library-panel utility-panel";
1618
1919
  libraryPanel.dataset.utility = "memory";
@@ -1673,6 +1974,10 @@ function installFoundryInspector(options = {}) {
1673
1974
  const inspectButton = shadow.querySelector(".inspect");
1674
1975
  const interactButton = shadow.querySelector(".interact");
1675
1976
  const workspaceBar = shadow.querySelector(".workspace-bar");
1977
+ const interfaceThemeTrigger = shadow.querySelector(
1978
+ ".interface-theme-trigger"
1979
+ );
1980
+ const interfaceThemeMenu = shadow.querySelector(".interface-theme-menu");
1676
1981
  const sessionStatus = shadow.querySelector(".session-status");
1677
1982
  const statusPopover = shadow.querySelector(".status-popover");
1678
1983
  const changeDock = shadow.querySelector(".change-dock");
@@ -1709,21 +2014,66 @@ function installFoundryInspector(options = {}) {
1709
2014
  const healthSummary = shadow.querySelector(".health-summary");
1710
2015
  const healthFilters = shadow.querySelector(".health-filters");
1711
2016
  const healthList = shadow.querySelector(".health-list");
1712
- const changeCount = shadow.querySelector(".change-count");
1713
2017
  const scope = shadow.querySelector("[data-scope]");
1714
2018
  const breakpoint = shadow.querySelector("[data-breakpoint]");
1715
2019
  const theme = shadow.querySelector("[data-theme]");
1716
2020
  const state = shadow.querySelector("[data-state]");
1717
- const reviewView = shadow.querySelector(".review-view");
2021
+ const reviewTakeover = shadow.querySelector(".review-takeover");
2022
+ const reviewModal = shadow.querySelector(".review-modal");
1718
2023
  const reviewBody = shadow.querySelector(".review-body");
1719
2024
  const reviewCount = shadow.querySelector(".review-count");
1720
2025
  const applyButton = shadow.querySelector(".review-actions .apply");
1721
2026
  const reviewCancel = shadow.querySelector(".review-cancel");
2027
+ function applyInterfaceTheme(preference, persist = true) {
2028
+ interfaceThemePreference = preference;
2029
+ const resolved = resolvedInterfaceTheme();
2030
+ host.dataset.interfaceTheme = resolved;
2031
+ host.dataset.interfaceThemePreference = preference;
2032
+ const label = preference[0].toUpperCase() + preference.slice(1);
2033
+ interfaceThemeTrigger.title = `Interface theme: ${label}`;
2034
+ interfaceThemeTrigger.setAttribute("aria-label", `Interface theme: ${label}`);
2035
+ interfaceThemeMenu.querySelectorAll("[data-interface-theme-choice]").forEach(
2036
+ (button) => button.setAttribute(
2037
+ "aria-checked",
2038
+ String(button.dataset.interfaceThemeChoice === preference)
2039
+ )
2040
+ );
2041
+ if (persist) localStorage.setItem(interfaceThemeKey, preference);
2042
+ }
2043
+ function closeInterfaceThemeMenu(restoreFocus = false) {
2044
+ interfaceThemeMenu.hidden = true;
2045
+ interfaceThemeTrigger.setAttribute("aria-expanded", "false");
2046
+ if (restoreFocus) interfaceThemeTrigger.focus();
2047
+ }
2048
+ function openInterfaceThemeMenu() {
2049
+ const rect = interfaceThemeTrigger.getBoundingClientRect();
2050
+ const menuWidth = 164;
2051
+ interfaceThemeMenu.style.top = `${Math.round(rect.bottom + 8)}px`;
2052
+ interfaceThemeMenu.style.left = `${Math.round(Math.min(window.innerWidth - menuWidth - 8, Math.max(8, rect.right - menuWidth)))}px`;
2053
+ interfaceThemeMenu.hidden = false;
2054
+ interfaceThemeTrigger.setAttribute("aria-expanded", "true");
2055
+ interfaceThemeMenu.querySelector('[aria-checked="true"]')?.focus();
2056
+ }
2057
+ applyInterfaceTheme(interfaceThemePreference, false);
2058
+ const handleSystemThemeChange = () => {
2059
+ if (interfaceThemePreference === "system") applyInterfaceTheme("system", false);
2060
+ };
2061
+ systemDarkTheme.addEventListener("change", handleSystemThemeChange);
2062
+ const handleInterfaceThemeDismiss = (event) => {
2063
+ if (interfaceThemeMenu.hidden) return;
2064
+ const path = event.composedPath();
2065
+ if (!path.includes(interfaceThemeMenu) && !path.includes(interfaceThemeTrigger)) {
2066
+ closeInterfaceThemeMenu();
2067
+ }
2068
+ };
2069
+ document.addEventListener("pointerdown", handleInterfaceThemeDismiss, true);
1722
2070
  let workspaceState = { ...DEFAULT_WORKSPACE_STATE };
1723
2071
  let selected = null;
1724
2072
  let selectedElements = [];
1725
2073
  let layerEntries = [];
1726
2074
  const collapsedLayers = /* @__PURE__ */ new WeakSet();
2075
+ let visibleLayerElements = /* @__PURE__ */ new Set();
2076
+ let layerGlideTop = null;
1727
2077
  const layerViewPreferenceKey = "__foundry_layer_view";
1728
2078
  let layerView = sessionStorage.getItem(layerViewPreferenceKey) === "components" ? "components" : "layers";
1729
2079
  let clickCycle = { x: -1, y: -1, at: 0, index: -1, signature: "" };
@@ -1740,18 +2090,34 @@ function installFoundryInspector(options = {}) {
1740
2090
  }
1741
2091
  })();
1742
2092
  let reviewShowRejected = false;
2093
+ const collapsedReviewGroups = /* @__PURE__ */ new Set();
1743
2094
  let reviewPoll;
1744
2095
  let lastReviewTrigger = null;
2096
+ let reviewScrollTop = 0;
2097
+ let reviewSuspended = false;
2098
+ let suspendedPreviewRestore;
2099
+ const dockReviewButton = shadow.querySelector(".dock-review");
2100
+ const dockWidthKey = "__foundry_dock_width";
2101
+ const legacyDockWidthKey = "__foundry_panel_width";
2102
+ const storedDockWidth = Number(
2103
+ localStorage.getItem(dockWidthKey) ?? localStorage.getItem(legacyDockWidthKey)
2104
+ );
2105
+ let dockWidth = Number.isFinite(storedDockWidth) ? Math.max(340, Math.min(520, storedDockWidth)) : 384;
2106
+ host.style.setProperty("--fdc-dock-width", `${Math.round(dockWidth)}px`);
1745
2107
  let designGraph = null;
1746
2108
  const previewHistory = [];
1747
2109
  let historyCursor = 0;
1748
2110
  let paddingLinked = true;
2111
+ let radiusLinked = true;
1749
2112
  let tokenOnly = false;
1750
2113
  let activeControlProperty = "";
2114
+ const recentColors = /* @__PURE__ */ new Set();
2115
+ let activeColor;
1751
2116
  let lastRecordedSummary = "";
1752
2117
  let statusResetTimer;
1753
2118
  let hydratedOnce = false;
1754
2119
  const collapsedSections = /* @__PURE__ */ new Set();
2120
+ let sectionPreferenceTouched = sessionStorage.getItem("__foundry_collapsed_sections") != null;
1755
2121
  try {
1756
2122
  for (const key of JSON.parse(sessionStorage.getItem("__foundry_collapsed_sections") ?? "[]")) {
1757
2123
  if (typeof key === "string") collapsedSections.add(key);
@@ -1841,10 +2207,7 @@ function installFoundryInspector(options = {}) {
1841
2207
  "--fdc-canvas-right",
1842
2208
  `${Math.max(12, window.innerWidth - bounds.right)}px`
1843
2209
  );
1844
- host.style.setProperty(
1845
- "--fdc-tray-lift",
1846
- workspaceState.tray !== "hidden" ? `${Math.max(0, window.innerHeight - bounds.bottom)}px` : "0px"
1847
- );
2210
+ host.style.setProperty("--fdc-tray-lift", "0px");
1848
2211
  if (workspaceState.utility) applyUtilityRect(workspaceState.utility);
1849
2212
  }
1850
2213
  function persistUtilityRect(utility, rect) {
@@ -1958,15 +2321,17 @@ function installFoundryInspector(options = {}) {
1958
2321
  }
1959
2322
  }
1960
2323
  function updateChangeCount(count, latest) {
1961
- changeCount.textContent = String(count);
1962
- changeCount.hidden = count === 0;
1963
2324
  changeDock.hidden = count === 0;
1964
2325
  workspaceState = updateWorkspace(workspaceState, {
1965
- type: "set-tray",
1966
- tray: count === 0 ? "hidden" : workspaceState.tray === "expanded" ? "expanded" : "collapsed"
2326
+ type: "set-change-summary",
2327
+ visible: count > 0
1967
2328
  });
1968
- if (count === 0) reviewView.hidden = true;
1969
- changeDock.classList.toggle("expanded", workspaceState.tray === "expanded");
2329
+ panel.classList.toggle("change-summary-visible", count > 0);
2330
+ if (count === 0) {
2331
+ reviewTakeover.hidden = true;
2332
+ reviewSuspended = false;
2333
+ dockReviewButton.textContent = "Review";
2334
+ }
1970
2335
  trayCompare.disabled = count === 0 || historyCursor === 0;
1971
2336
  changeDock.querySelector("[data-dock-count]").textContent = `${count} ${count === 1 ? "change" : "changes"} recorded`;
1972
2337
  if (latest) {
@@ -2511,15 +2876,38 @@ function installFoundryInspector(options = {}) {
2511
2876
  );
2512
2877
  const range = visible.length > 120 && !queryValue ? virtualRange(visible.length, previousScrollTop, layerTree.clientHeight || 320, 30, 8) : { start: 0, end: visible.length, before: 0, after: 0 };
2513
2878
  const rendered = visible.slice(range.start, range.end);
2514
- layerTree.innerHTML = visible.length ? `${range.before ? `<div class="layer-spacer" style="height:${range.before}px"></div>` : ""}${rendered.map((entry) => {
2879
+ const hasRenderedSelection = rendered.some((entry) => selectedElements.includes(entry.element));
2880
+ const previouslyVisible = visibleLayerElements;
2881
+ visibleLayerElements = new Set(visible.map((entry) => entry.element));
2882
+ layerTree.innerHTML = visible.length ? `${range.before ? `<div class="layer-spacer" style="height:${range.before}px"></div>` : ""}${rendered.map((entry, renderedPosition) => {
2515
2883
  const index = layerEntries.indexOf(entry);
2516
2884
  const meta = entry.instrumented ? "Mapped" : entry.kind;
2517
2885
  const collapsed = collapsedLayers.has(entry.element);
2518
- return `<div class="layer-row ${selectedElements.includes(entry.element) ? "selected" : ""}" style="--layer-depth:${Math.min(entry.depth, 8)}" data-layer-row="${index}" draggable="true"><button class="layer-toggle" data-layer-toggle="${index}" aria-label="${collapsed ? "Expand" : "Collapse"} ${escapeHtml(entry.label)}" aria-expanded="${!collapsed}" ${entry.hasChildren ? "" : "disabled"}><i data-foundry-icon="${collapsed ? "chevron-right" : "chevron-down"}"></i></button><button class="layer-select" data-layer-index="${index}" aria-label="Select ${escapeHtml(entry.label)}"><i class="layer-icon" data-foundry-icon="${entry.kind === "component" ? "component" : "box"}"></i><span class="layer-label">${escapeHtml(entry.label)}</span><span class="layer-meta">${escapeHtml(meta)}</span></button></div>`;
2886
+ const position = range.start + renderedPosition;
2887
+ const depth = Math.min(entry.depth, 8);
2888
+ const selectedLayer = selectedElements.includes(entry.element);
2889
+ const entering = previouslyVisible.has(entry.element) ? "" : " entering";
2890
+ const branch = depth ? `<span class="layer-branch" aria-hidden="true"></span>` : "";
2891
+ return `<div class="layer-row ${selectedLayer ? "selected" : ""}${entering}" style="--layer-depth:${depth};--layer-position:${Math.min(renderedPosition, 5)};--layer-branch-left:${10 + (depth - 1) * 10}px" data-layer-row="${index}" draggable="true">${branch}<button class="layer-toggle" data-layer-toggle="${index}" aria-label="${collapsed ? "Expand" : "Collapse"} ${escapeHtml(entry.label)}" aria-expanded="${!collapsed}" ${entry.hasChildren ? "" : "disabled"}><i data-foundry-icon="${collapsed ? "chevron-right" : "chevron-down"}"></i></button><button class="layer-select" data-layer-index="${index}" role="treeitem" aria-level="${depth + 1}" aria-posinset="${position + 1}" aria-setsize="${visible.length}" aria-selected="${selectedLayer}" ${entry.hasChildren ? `aria-expanded="${!collapsed}"` : ""} tabindex="${selectedLayer || !hasRenderedSelection && renderedPosition === 0 ? "0" : "-1"}" aria-label="Select ${escapeHtml(entry.label)}"><i class="layer-icon" data-foundry-icon="${entry.kind === "component" ? "component" : "box"}"></i><span class="layer-label">${escapeHtml(entry.label)}</span><span class="layer-meta">${escapeHtml(meta)}</span></button></div>`;
2519
2892
  }).join(
2520
2893
  ""
2521
2894
  )}${range.after ? `<div class="layer-spacer" style="height:${range.after}px"></div>` : ""}` : '<div class="layers-empty">No visible layers match this search.</div>';
2522
2895
  layerTree.scrollTop = previousScrollTop;
2896
+ const selectedRow = layerTree.querySelector(".layer-row.selected");
2897
+ if (selectedRow) {
2898
+ const targetTop = selectedRow.offsetTop;
2899
+ const glide = document.createElement("span");
2900
+ glide.className = "layer-selection-glide";
2901
+ glide.setAttribute("aria-hidden", "true");
2902
+ glide.style.setProperty("--layer-glide-y", `${layerGlideTop ?? targetTop}px`);
2903
+ layerTree.prepend(glide);
2904
+ requestAnimationFrame(() => {
2905
+ glide.style.setProperty("--layer-glide-y", `${targetTop}px`);
2906
+ });
2907
+ layerGlideTop = targetTop;
2908
+ } else {
2909
+ layerGlideTop = null;
2910
+ }
2523
2911
  renderIcons(layerTree);
2524
2912
  layerTree.querySelectorAll("[data-layer-row]").forEach((row) => {
2525
2913
  const entry = layerEntries[Number(row.dataset.layerRow)];
@@ -2601,6 +2989,73 @@ function installFoundryInspector(options = {}) {
2601
2989
  select(entry.element, event.shiftKey);
2602
2990
  entry.element.scrollIntoView({ block: "nearest", inline: "nearest" });
2603
2991
  });
2992
+ button.addEventListener("keydown", (event) => {
2993
+ const buttons = [...layerTree.querySelectorAll("[data-layer-index]")];
2994
+ const currentIndex = buttons.indexOf(button);
2995
+ const focusAt = (index) => {
2996
+ const target = buttons[index];
2997
+ if (!target) return;
2998
+ buttons.forEach((item) => item.tabIndex = item === target ? 0 : -1);
2999
+ target.focus();
3000
+ target.closest(".layer-row")?.scrollIntoView({ block: "nearest" });
3001
+ };
3002
+ if (event.key === "ArrowDown") {
3003
+ event.preventDefault();
3004
+ focusAt(Math.min(buttons.length - 1, currentIndex + 1));
3005
+ return;
3006
+ }
3007
+ if (event.key === "ArrowUp") {
3008
+ event.preventDefault();
3009
+ focusAt(Math.max(0, currentIndex - 1));
3010
+ return;
3011
+ }
3012
+ if (event.key === "Home") {
3013
+ event.preventDefault();
3014
+ focusAt(0);
3015
+ return;
3016
+ }
3017
+ if (event.key === "End") {
3018
+ event.preventDefault();
3019
+ focusAt(buttons.length - 1);
3020
+ return;
3021
+ }
3022
+ if (event.key === "ArrowRight" && entry.hasChildren) {
3023
+ event.preventDefault();
3024
+ if (collapsedLayers.has(entry.element)) {
3025
+ collapsedLayers.delete(entry.element);
3026
+ renderLayers(false);
3027
+ requestAnimationFrame(
3028
+ () => layerTree.querySelector(
3029
+ `[data-layer-index="${layerEntries.indexOf(entry)}"]`
3030
+ )?.focus()
3031
+ );
3032
+ } else {
3033
+ const next = buttons[currentIndex + 1];
3034
+ const nextEntry = next ? layerEntries[Number(next.dataset.layerIndex)] : void 0;
3035
+ if (nextEntry && nextEntry.depth > entry.depth) focusAt(currentIndex + 1);
3036
+ }
3037
+ return;
3038
+ }
3039
+ if (event.key !== "ArrowLeft") return;
3040
+ event.preventDefault();
3041
+ if (entry.hasChildren && !collapsedLayers.has(entry.element)) {
3042
+ collapsedLayers.add(entry.element);
3043
+ renderLayers(false);
3044
+ requestAnimationFrame(
3045
+ () => layerTree.querySelector(
3046
+ `[data-layer-index="${layerEntries.indexOf(entry)}"]`
3047
+ )?.focus()
3048
+ );
3049
+ return;
3050
+ }
3051
+ for (let index = currentIndex - 1; index >= 0; index -= 1) {
3052
+ const candidate2 = layerEntries[Number(buttons[index]?.dataset.layerIndex)];
3053
+ if (candidate2 && candidate2.depth < entry.depth) {
3054
+ focusAt(index);
3055
+ break;
3056
+ }
3057
+ }
3058
+ });
2604
3059
  });
2605
3060
  }
2606
3061
  const layersPreferenceKey = "__foundry_layers_visibility";
@@ -2954,11 +3409,12 @@ function installFoundryInspector(options = {}) {
2954
3409
  const unresolvedCount = changes.filter(
2955
3410
  (change) => change.confidence === "unresolved" || change.mappingCandidates?.length > 1 && !change.selectedMappingId
2956
3411
  ).length;
2957
- reviewBody.innerHTML = changes.length || rejectedCount ? `<div class="review-overview"><div class="review-summary" data-unresolved="${unresolvedCount}" aria-live="polite"><strong>Preparing review\u2026</strong><span>Only included, exactly mapped changes will be sent to your agent.</span></div><div class="review-toolbar"><button data-review-approve-exact>Include all</button><button data-review-toggle-rejected>${reviewShowRejected ? "Hide removed" : rejectedCount ? `${rejectedCount} removed` : "Removed"}</button></div></div>${[
3412
+ reviewBody.innerHTML = changes.length || rejectedCount ? `<div class="review-overview"><div class="review-summary" data-unresolved="${unresolvedCount}" aria-live="polite"><strong>Preparing review\u2026</strong><span>Only included, exactly mapped changes will be sent to your agent.</span></div><div class="review-toolbar"><button data-review-compare>Compare</button><button data-review-approve-exact>Include all</button><button data-review-toggle-rejected>${reviewShowRejected ? "Hide removed" : rejectedCount ? `${rejectedCount} removed` : "Removed"}</button></div></div>${[
2958
3413
  ...groups.values()
2959
3414
  ].map((group) => {
2960
3415
  const target = group[0].target;
2961
- return `<section class="review-group" data-review-target="${escapeHtml(target.id)}"><button class="review-group-title" aria-expanded="true"><i data-foundry-icon="chevron-down"></i><strong>${escapeHtml(target.label)}</strong><span class="included-count"></span><span class="group-total">${group.length}</span></button>${group.map((change) => {
3416
+ const collapsed = collapsedReviewGroups.has(target.id);
3417
+ return `<section class="review-group ${collapsed ? "collapsed" : ""}" data-review-target="${escapeHtml(target.id)}"><button class="review-group-title" aria-expanded="${String(!collapsed)}"><i data-foundry-icon="chevron-down"></i><strong>${escapeHtml(target.label)}</strong><span class="included-count"></span><span class="group-total">${group.length}</span></button>${group.map((change) => {
2962
3418
  const unresolved = change.confidence === "unresolved" || change.mappingCandidates?.length > 1 && !change.selectedMappingId;
2963
3419
  const selectable = !unresolved && change.status !== "rejected";
2964
3420
  const checked = selectable && reviewSelection(reviewDraft, change.id, true);
@@ -3005,6 +3461,9 @@ function installFoundryInspector(options = {}) {
3005
3461
  const group = button.closest(".review-group");
3006
3462
  if (!group) return;
3007
3463
  group.classList.toggle("collapsed");
3464
+ const targetId = group.dataset.reviewTarget;
3465
+ if (group.classList.contains("collapsed")) collapsedReviewGroups.add(targetId);
3466
+ else collapsedReviewGroups.delete(targetId);
3008
3467
  button.setAttribute("aria-expanded", String(!group.classList.contains("collapsed")));
3009
3468
  })
3010
3469
  );
@@ -3020,6 +3479,10 @@ function installFoundryInspector(options = {}) {
3020
3479
  reviewShowRejected = !reviewShowRejected;
3021
3480
  if (activeReviewPayload) renderReviewPayload(activeReviewPayload);
3022
3481
  });
3482
+ reviewBody.querySelector("[data-review-compare]")?.addEventListener("click", () => {
3483
+ suspendReview();
3484
+ showComparison("after");
3485
+ });
3023
3486
  reviewBody.querySelectorAll("[data-review-status]").forEach(
3024
3487
  (button) => button.addEventListener("click", async () => {
3025
3488
  button.disabled = true;
@@ -3043,10 +3506,15 @@ function installFoundryInspector(options = {}) {
3043
3506
  if (!element) return;
3044
3507
  const before = () => rawElementValue(element, change.property, change.before, change.unit);
3045
3508
  const after = () => rawElementValue(element, change.property, change.after, change.unit);
3046
- button.addEventListener("pointerdown", before);
3047
- button.addEventListener("pointerup", after);
3048
- button.addEventListener("pointercancel", after);
3049
- button.addEventListener("pointerleave", after);
3509
+ button.title = "Show the before value on the canvas";
3510
+ button.addEventListener("click", () => {
3511
+ before();
3512
+ suspendedPreviewRestore = after;
3513
+ select(element);
3514
+ suspendReview();
3515
+ element.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
3516
+ showToast("Before value shown \xB7 Return to continue reviewing");
3517
+ });
3050
3518
  });
3051
3519
  reviewBody.querySelectorAll("[data-review-locate]").forEach((button) => {
3052
3520
  const change = changes.find((item) => item.id === button.dataset.reviewLocate);
@@ -3061,9 +3529,9 @@ function installFoundryInspector(options = {}) {
3061
3529
  button.addEventListener("mouseleave", () => previewLayer(null));
3062
3530
  button.addEventListener("click", () => {
3063
3531
  select(element);
3064
- closeReview();
3532
+ suspendReview();
3065
3533
  element.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
3066
- showToast("Located on the live canvas");
3534
+ showToast("Located on the live canvas \xB7 Return to continue reviewing");
3067
3535
  });
3068
3536
  });
3069
3537
  reviewBody.querySelectorAll("[data-mapping-choice]").forEach(
@@ -3085,7 +3553,7 @@ function installFoundryInspector(options = {}) {
3085
3553
  updateReviewSelection();
3086
3554
  }
3087
3555
  const runStateLabels = {
3088
- queued: "Waiting for agent",
3556
+ queued: "Queued for agent",
3089
3557
  claimed: "Agent connected",
3090
3558
  applying: "Applying source changes",
3091
3559
  rebuilding: "Rebuilding and checking",
@@ -3134,11 +3602,11 @@ function installFoundryInspector(options = {}) {
3134
3602
  const attention = ["needs_attention", "failed"].includes(run.state);
3135
3603
  const passed = run.state === "passed";
3136
3604
  const active = ["queued", "claimed", "applying", "rebuilding", "verifying"].includes(run.state);
3137
- const latestMessage = run.messages.at(-1)?.message ?? run.error ?? "Apply run created.";
3605
+ const latestMessage = run.state === "queued" ? "The reviewed changes are queued. Keep your coding agent active, or ask it to apply your reviewed Foundry changes." : run.messages.at(-1)?.message ?? run.error ?? "Apply run created.";
3138
3606
  captureVerifiedRun(run);
3139
3607
  reviewCount.textContent = `Attempt ${run.attempts}`;
3140
3608
  reviewBody.innerHTML = `<div class="run-summary"><div class="run-state"><i class="${passed ? "passed" : attention ? "attention" : active ? "active" : ""}"></i><strong>${escapeHtml(runStateLabels[run.state] ?? run.state)}</strong></div><p>${escapeHtml(latestMessage)}</p></div><div class="run-steps">${run.messages.map(
3141
- (message, index) => `<div class="run-step"><span>${String(index + 1).padStart(2, "0")}</span><div><strong>${escapeHtml(runStateLabels[message.state] ?? message.state)}</strong><p>${escapeHtml(message.message)}</p></div></div>`
3609
+ (message, index) => `<div class="run-step"><span>${String(index + 1).padStart(2, "0")}</span><div><strong>${escapeHtml(runStateLabels[message.state] ?? message.state)}</strong><p>${escapeHtml(message.state === "queued" ? "Ready for the active coding agent to claim." : message.message)}</p></div></div>`
3142
3610
  ).join(
3143
3611
  ""
3144
3612
  )}</div>${run.changedFiles.length ? `<div class="run-files"><strong>Changed files</strong>${run.changedFiles.map((file) => `<code>${escapeHtml(file)}</code>`).join("")}</div>` : ""}${run.validationResults.length ? `<div class="result-list">${run.validationResults.map((result) => `<div class="result-row ${result.passed ? "pass" : "fail"}"><span>${result.passed ? "Passed" : "Failed"} \xB7 ${escapeHtml(result.name)}</span><span>${escapeHtml(result.summary ?? "")}</span></div>`).join("")}</div>` : ""}${run.verificationResults.length ? `<div class="result-list">${run.verificationResults.map((result) => `<div class="result-row ${result.passed ? "pass" : "fail"}"><span>${result.passed ? "Matched" : "Mismatch"} \xB7 ${escapeHtml(result.property)}</span><span>${escapeHtml(reviewValue(result.requested))} \u2192 ${escapeHtml(reviewValue(result.rendered))}</span></div>`).join("")}</div>` : ""}`;
@@ -3168,6 +3636,7 @@ function installFoundryInspector(options = {}) {
3168
3636
  }
3169
3637
  }
3170
3638
  function renderReviewPayload(payload) {
3639
+ const preservedScrollTop = reviewBody.scrollTop || reviewScrollTop;
3171
3640
  activeReviewPayload = payload;
3172
3641
  const activeChanges = payload.changeSet.changes.filter(
3173
3642
  (change) => change.status !== "rejected" && String(change.before) !== String(change.after)
@@ -3183,14 +3652,21 @@ function installFoundryInspector(options = {}) {
3183
3652
  "needs_attention",
3184
3653
  "failed"
3185
3654
  ].includes(latestRun.state);
3655
+ if (activeOrAttention) {
3656
+ const latestMessage = latestRun.messages?.at(-1)?.message;
3657
+ changeDock.querySelector("[data-dock-last]").textContent = latestMessage ?? runStateLabels[latestRun.state] ?? latestRun.state;
3658
+ }
3186
3659
  const pending = payload.changeSet.changes.filter(
3187
3660
  (change) => String(change.before) !== String(change.after) && (["draft", "approved", "unresolved"].includes(change.status) || reviewShowRejected && change.status === "rejected")
3188
3661
  );
3189
3662
  if (activeOrAttention || !pending.length && latestRun) renderApplyRun(latestRun);
3190
3663
  else renderReviewList(pending);
3664
+ requestAnimationFrame(() => {
3665
+ if (workspaceState.reviewOpen) reviewBody.scrollTop = preservedScrollTop;
3666
+ });
3191
3667
  }
3192
3668
  async function refreshReview() {
3193
- if (workspaceState.tray !== "expanded" || !sessionId || !token) return;
3669
+ if (!workspaceState.reviewOpen || !sessionId || !token) return;
3194
3670
  try {
3195
3671
  const payload = await sessionRequest();
3196
3672
  const latestRun = payload.applyRuns?.at(-1);
@@ -3217,29 +3693,38 @@ function installFoundryInspector(options = {}) {
3217
3693
  showToast("Session connection is missing");
3218
3694
  return;
3219
3695
  }
3220
- if (shadow.activeElement instanceof HTMLElement) lastReviewTrigger = shadow.activeElement;
3221
- workspaceState = updateWorkspace(workspaceState, { type: "set-tray", tray: "expanded" });
3222
- changeDock.classList.add("expanded");
3223
- reviewView.hidden = false;
3696
+ if (!reviewSuspended && shadow.activeElement instanceof HTMLElement)
3697
+ lastReviewTrigger = shadow.activeElement;
3698
+ suspendedPreviewRestore?.();
3699
+ suspendedPreviewRestore = void 0;
3700
+ reviewSuspended = false;
3701
+ dockReviewButton.textContent = "Review";
3702
+ workspaceState = updateWorkspace(workspaceState, { type: "set-review", open: true });
3703
+ reviewTakeover.hidden = false;
3224
3704
  outline.hidden = true;
3225
- positionWorkspaceSurfaces();
3226
3705
  renderReviewPayload(await sessionRequest());
3706
+ requestAnimationFrame(() => {
3707
+ reviewBody.scrollTop = reviewScrollTop;
3708
+ shadow.querySelector(".review-back")?.focus();
3709
+ });
3227
3710
  clearInterval(reviewPoll);
3228
3711
  clearInterval(healthPoll);
3229
3712
  reviewPoll = setInterval(() => void refreshReview(), 1e3);
3230
3713
  }
3231
- function closeReview() {
3232
- workspaceState = updateWorkspace(workspaceState, {
3233
- type: "set-tray",
3234
- tray: changeDock.hidden ? "hidden" : "collapsed"
3235
- });
3236
- changeDock.classList.remove("expanded");
3237
- reviewView.hidden = true;
3714
+ function closeReview(restoreFocus = true) {
3715
+ reviewScrollTop = reviewBody.scrollTop;
3716
+ workspaceState = updateWorkspace(workspaceState, { type: "set-review", open: false });
3717
+ reviewTakeover.hidden = true;
3238
3718
  clearInterval(reviewPoll);
3239
3719
  reviewPoll = void 0;
3240
3720
  updateOutline();
3241
- positionWorkspaceSurfaces();
3242
- lastReviewTrigger?.focus();
3721
+ if (restoreFocus) lastReviewTrigger?.focus();
3722
+ }
3723
+ function suspendReview() {
3724
+ reviewSuspended = true;
3725
+ dockReviewButton.textContent = "Return";
3726
+ closeReview(false);
3727
+ dockReviewButton.focus();
3243
3728
  }
3244
3729
  async function submitReviewedRun() {
3245
3730
  if (!activeReviewPayload) return;
@@ -3716,13 +4201,8 @@ function installFoundryInspector(options = {}) {
3716
4201
  }
3717
4202
  function renderContextPanel(category) {
3718
4203
  if (!selected) return "";
3719
- const supportsTokens = ["layout", "typography", "color", "effects"].includes(category);
3720
- const tokens = supportsTokens ? tokensForCategory(category).slice(0, 24) : [];
3721
4204
  const component = selectedComponent();
3722
4205
  const variants = component?.variants ?? [];
3723
- const tokenPanel = tokens.length ? `<section class="native-panel"><div class="native-panel-head"><strong>Project ${category === "typography" ? "styles" : "tokens"}</strong><span>${tokens.length}</span></div><input class="native-search" type="search" placeholder="Search project values" aria-label="Search project values"/><div class="native-grid">${tokens.map(
3724
- (token2) => `<button class="native-chip" data-native-token="${escapeHtml(token2.id)}" data-token-search="${escapeHtml(`${token2.name} ${token2.value}`.toLowerCase())}" title="${escapeHtml(token2.value)}">${category === "color" ? `<span class="swatch" style="--token-color:${escapeHtml(token2.value)}"></span>` : ""}<span>${escapeHtml(token2.name)}</span></button>`
3725
- ).join("")}</div></section>` : "";
3726
4206
  const contrast = category === "color" ? contrastRatio(getComputedStyle(selected).color, opaqueBackground(selected)) : null;
3727
4207
  const health = category === "color" && contrast != null ? `<div class="design-health ${contrast >= 4.5 ? "pass" : "fail"}"><i data-foundry-icon="contrast"></i><span>${contrast}:1 contrast \xB7 ${contrast >= 4.5 ? "AA pass" : "Needs attention"}</span></div>` : "";
3728
4208
  const variantPanel = category === "content" && variants.length ? `<section class="native-panel"><div class="native-panel-head"><strong>${escapeHtml(component.name)} variants</strong><span>${component.instances} instances</span></div><div class="variant-list">${variants.map(
@@ -3730,9 +4210,7 @@ function installFoundryInspector(options = {}) {
3730
4210
  Object.entries(variant.props).map(([key, value]) => `${key}=${value}`).join(" \xB7 ")
3731
4211
  )}</code></button>`
3732
4212
  ).join("")}</div></section>` : "";
3733
- const categoryTools = category === "layout" ? `<div class="context-tools"><button data-layout-action="tidy"><i data-foundry-icon="wand-sparkles"></i>Tidy layout</button><button data-layout-action="up"><i data-foundry-icon="arrow-up"></i>Move up</button><button data-layout-action="down"><i data-foundry-icon="arrow-down"></i>Move down</button><button data-layout-action="lock"><i data-foundry-icon="lock"></i>Lock ratio</button></div>` : category === "typography" ? `<div class="context-tools"><button data-type-preset="compact">Compact</button><button data-type-preset="body">Body</button><button data-type-preset="display">Display</button></div>` : category === "color" ? `<div class="context-tools"><button data-color-action="gradient">Linear gradient</button><button data-color-action="clear">Clear fill</button></div>` : "";
3734
- const tokenMode = category === "layout" && (designGraph?.tokens.length ?? 0) ? `<div class="context-tools"><button class="${tokenOnly ? "active" : ""}" data-token-only><i data-foundry-icon="${tokenOnly ? "lock" : "unlink-2"}"></i>${tokenOnly ? "Token-only on" : "Token-only off"}</button></div>` : "";
3735
- return `${categoryTools}${tokenMode}${health}${variantPanel}${tokenPanel}`;
4213
+ return `${health}${variantPanel}`;
3736
4214
  }
3737
4215
  async function applyControlValue(control, value, operationLabel) {
3738
4216
  if (!selected) return;
@@ -3844,13 +4322,18 @@ function installFoundryInspector(options = {}) {
3844
4322
  });
3845
4323
  controlsRoot.querySelectorAll("[data-color-action]").forEach((button) => {
3846
4324
  button.addEventListener("click", () => {
3847
- const control = controls.find((item) => item.property === "backgroundImage");
3848
- if (!control) return;
3849
- const value = button.dataset.colorAction === "clear" ? "none" : "linear-gradient(135deg, currentColor 0%, transparent 100%)";
4325
+ const gradient = controls.find((item) => item.property === "backgroundImage");
4326
+ if (!gradient) return;
4327
+ if (button.dataset.colorAction === "clear") {
4328
+ const fill = controls.find((item) => item.property === "backgroundColor");
4329
+ if (fill) void applyControlValue(fill, "transparent", "Clear fill color");
4330
+ void applyControlValue(gradient, "none", "Clear fill gradient");
4331
+ return;
4332
+ }
3850
4333
  void applyControlValue(
3851
- control,
3852
- value,
3853
- button.dataset.colorAction === "clear" ? "Clear fill" : "Add linear gradient"
4334
+ gradient,
4335
+ "linear-gradient(135deg, currentColor 0%, transparent 100%)",
4336
+ "Add linear gradient"
3854
4337
  );
3855
4338
  });
3856
4339
  });
@@ -3878,6 +4361,13 @@ function installFoundryInspector(options = {}) {
3878
4361
  const siblings = [...parent.children].filter((item) => item !== element);
3879
4362
  const index = Math.max(0, Math.min(Number(value), siblings.length));
3880
4363
  parent.insertBefore(element, siblings[index] ?? null);
4364
+ } else if (property === "rotate") element.style.rotate = `${value}${unit ?? "deg"}`;
4365
+ else if (property === "scaleX" || property === "scaleY") {
4366
+ const raw = getComputedStyle(element).scale;
4367
+ const parts = !raw || raw === "none" ? [1, 1] : raw.split(/\s+/).map(numberFrom);
4368
+ const x = property === "scaleX" ? Number(value) : parts[0] ?? 1;
4369
+ const y = property === "scaleY" ? Number(value) : parts[1] ?? parts[0] ?? 1;
4370
+ element.style.scale = `${x} ${y}`;
3881
4371
  } else if (property === "textContent") element.textContent = String(value);
3882
4372
  else if (["aria-label", "role", "tabindex", "alt", "src"].includes(property))
3883
4373
  element.setAttribute(property, String(value));
@@ -4049,8 +4539,14 @@ function installFoundryInspector(options = {}) {
4049
4539
  { id: "redo", label: "Redo preview", shortcut: "\u21E7\u2318Z", icon: "redo-2" },
4050
4540
  { id: "review", label: "Review changes", shortcut: "", icon: "file-text" }
4051
4541
  ];
4052
- function runCommand(id) {
4542
+ let commandReturnFocus = null;
4543
+ function closeCommands(restoreFocus = true) {
4053
4544
  commandPalette.hidden = true;
4545
+ if (restoreFocus && commandReturnFocus?.isConnected) commandReturnFocus.focus();
4546
+ commandReturnFocus = null;
4547
+ }
4548
+ function runCommand(id) {
4549
+ closeCommands(false);
4054
4550
  if (id === "health") openHealth();
4055
4551
  if (id === "layers") toggleLayers(true);
4056
4552
  if (id === "compare") showComparison("after");
@@ -4082,6 +4578,7 @@ function installFoundryInspector(options = {}) {
4082
4578
  );
4083
4579
  }
4084
4580
  function openCommands() {
4581
+ commandReturnFocus = shadow.activeElement;
4085
4582
  commandPalette.hidden = false;
4086
4583
  const input = commandPalette.querySelector("input");
4087
4584
  input.value = "";
@@ -4388,6 +4885,180 @@ function installFoundryInspector(options = {}) {
4388
4885
  );
4389
4886
  });
4390
4887
  }
4888
+ function activeColorValue() {
4889
+ if (!activeColor) return "#000000";
4890
+ const [red, green, blue] = hsvToRgb(activeColor.hue, activeColor.saturation, activeColor.value);
4891
+ return activeColor.alpha >= 0.999 ? rgbHex(red, green, blue) : `rgba(${red}, ${green}, ${blue}, ${Math.round(activeColor.alpha * 100) / 100})`;
4892
+ }
4893
+ function refreshColorPopover() {
4894
+ if (!activeColor) return;
4895
+ const plane = colorPopover.querySelector(".color-plane");
4896
+ const handle = colorPopover.querySelector(".color-plane-handle");
4897
+ const hex = colorPopover.querySelector("[data-color-hex]");
4898
+ const hue = colorPopover.querySelector("[data-color-hue]");
4899
+ const alpha = colorPopover.querySelector("[data-color-alpha]");
4900
+ if (plane) plane.style.setProperty("--picker-hue", String(activeColor.hue));
4901
+ if (handle) {
4902
+ handle.style.left = `${activeColor.saturation * 100}%`;
4903
+ handle.style.top = `${(1 - activeColor.value) * 100}%`;
4904
+ }
4905
+ if (hex) hex.value = colorForInput(activeColorValue()).toUpperCase();
4906
+ if (hue) hue.value = String(Math.round(activeColor.hue));
4907
+ if (alpha) alpha.value = String(Math.round(activeColor.alpha * 100));
4908
+ }
4909
+ function previewActiveColor() {
4910
+ if (!activeColor) return;
4911
+ const value = activeColorValue();
4912
+ activeColor.control.apply(value);
4913
+ const trigger = controlsRoot.querySelector(
4914
+ `[data-color-control="${activeColor.index}"]`
4915
+ );
4916
+ const swatch = trigger?.querySelector(".color-swatch");
4917
+ const label = trigger?.querySelector(".color-value");
4918
+ if (swatch) {
4919
+ swatch.classList.toggle("transparent", activeColor.alpha === 0);
4920
+ swatch.style.setProperty("--swatch-color", colorForInput(value));
4921
+ }
4922
+ if (label) label.textContent = activeColor.alpha === 0 ? "Transparent" : value.toUpperCase();
4923
+ refreshColorPopover();
4924
+ updateOutline();
4925
+ }
4926
+ function commitActiveColor(before) {
4927
+ if (!activeColor) return;
4928
+ const after = activeColor.control.read();
4929
+ if (String(before) === String(after)) return;
4930
+ recentColors.delete(String(after));
4931
+ recentColors.add(String(after));
4932
+ while (recentColors.size > 8) recentColors.delete(recentColors.values().next().value);
4933
+ pushHistory({
4934
+ element: activeColor.element,
4935
+ property: activeColor.control.property,
4936
+ before,
4937
+ after,
4938
+ category: activeColor.control.category,
4939
+ label: activeColor.control.label
4940
+ });
4941
+ void record(activeColor.control, before, after, activeColor.element, "Choose color");
4942
+ }
4943
+ function setActiveColor(value) {
4944
+ if (!activeColor) return;
4945
+ const [red, green, blue] = hexChannels(value);
4946
+ const [hue, saturation, brightness] = rgbToHsv(red, green, blue);
4947
+ activeColor.hue = hue;
4948
+ activeColor.saturation = saturation;
4949
+ activeColor.value = brightness;
4950
+ activeColor.alpha = colorAlpha(value);
4951
+ previewActiveColor();
4952
+ }
4953
+ function openColorEditor(trigger, index) {
4954
+ const control = selectedControls[index];
4955
+ if (!control || control.kind !== "color" || !selected) return;
4956
+ const [red, green, blue] = hexChannels(String(control.read()));
4957
+ const [hue, saturation, value] = rgbToHsv(red, green, blue);
4958
+ activeColor = {
4959
+ index,
4960
+ control,
4961
+ element: selected,
4962
+ hue,
4963
+ saturation,
4964
+ value,
4965
+ alpha: colorAlpha(String(control.read()))
4966
+ };
4967
+ const tokens = tokensForCategory("color").slice(0, 18);
4968
+ colorPopover.innerHTML = `<div class="color-popover-head"><strong>${escapeHtml(control.label)}</strong><button class="icon-button" data-close-color aria-label="Close color editor"><i data-foundry-icon="x"></i></button></div><div class="color-plane" style="--picker-hue:${hue}"><span class="color-plane-handle"></span></div><div class="color-sliders"><label>Hue<input data-color-hue type="range" min="0" max="359" value="${Math.round(hue)}"/></label><label>Alpha<input data-color-alpha type="range" min="0" max="100" value="${Math.round(activeColor.alpha * 100)}"/></label></div><div class="color-fields"><input data-color-hex aria-label="Hex color" value="${colorForInput(String(control.read())).toUpperCase()}"/><button data-eyedropper aria-label="Pick color from page" title="Eyedropper"><i data-foundry-icon="palette"></i></button></div>${tokens.length ? `<div class="color-popover-section"><strong>Project colors</strong><div class="color-swatches">${tokens.map((token2) => `<button data-color-value="${escapeHtml(token2.value)}" style="--picker-swatch:${escapeHtml(token2.value)}" aria-label="Use ${escapeHtml(token2.name)}" title="${escapeHtml(`${token2.name} \xB7 ${token2.value}`)}"></button>`).join("")}</div></div>` : ""}${recentColors.size ? `<div class="color-popover-section"><strong>Recent</strong><div class="color-swatches">${[
4969
+ ...recentColors
4970
+ ].reverse().map(
4971
+ (color) => `<button data-color-value="${escapeHtml(color)}" style="--picker-swatch:${escapeHtml(color)}" aria-label="Use recent color ${escapeHtml(color)}"></button>`
4972
+ ).join("")}</div></div>` : ""}`;
4973
+ renderIcons(colorPopover);
4974
+ colorPopover.hidden = false;
4975
+ const triggerRect = trigger.getBoundingClientRect();
4976
+ const popoverRect = colorPopover.getBoundingClientRect();
4977
+ const left = Math.max(8, Math.min(window.innerWidth - popoverRect.width - 8, triggerRect.left));
4978
+ const preferredTop = triggerRect.bottom + 6;
4979
+ const top = preferredTop + popoverRect.height <= window.innerHeight - 8 ? preferredTop : Math.max(8, triggerRect.top - popoverRect.height - 6);
4980
+ colorPopover.style.left = `${Math.round(left)}px`;
4981
+ colorPopover.style.top = `${Math.round(top)}px`;
4982
+ refreshColorPopover();
4983
+ colorPopover.querySelector("[data-close-color]")?.addEventListener("click", () => {
4984
+ colorPopover.hidden = true;
4985
+ activeColor = void 0;
4986
+ trigger.focus();
4987
+ });
4988
+ const plane = colorPopover.querySelector(".color-plane");
4989
+ plane.addEventListener("pointerdown", (event) => {
4990
+ if (!activeColor) return;
4991
+ const before = activeColor.control.read();
4992
+ plane.setPointerCapture(event.pointerId);
4993
+ const update = (pointer) => {
4994
+ if (!activeColor) return;
4995
+ const rect = plane.getBoundingClientRect();
4996
+ activeColor.saturation = Math.max(
4997
+ 0,
4998
+ Math.min(1, (pointer.clientX - rect.left) / rect.width)
4999
+ );
5000
+ activeColor.value = 1 - Math.max(0, Math.min(1, (pointer.clientY - rect.top) / rect.height));
5001
+ previewActiveColor();
5002
+ };
5003
+ const finish = (pointer) => {
5004
+ update(pointer);
5005
+ commitActiveColor(before);
5006
+ plane.removeEventListener("pointermove", update);
5007
+ plane.removeEventListener("pointerup", finish);
5008
+ plane.removeEventListener("pointercancel", finish);
5009
+ };
5010
+ update(event);
5011
+ plane.addEventListener("pointermove", update);
5012
+ plane.addEventListener("pointerup", finish);
5013
+ plane.addEventListener("pointercancel", finish);
5014
+ });
5015
+ const bindSlider = (selector, apply) => {
5016
+ const slider = colorPopover.querySelector(selector);
5017
+ let before = control.read();
5018
+ slider.addEventListener("pointerdown", () => {
5019
+ before = control.read();
5020
+ });
5021
+ slider.addEventListener("input", () => {
5022
+ apply(Number(slider.value));
5023
+ previewActiveColor();
5024
+ });
5025
+ slider.addEventListener("change", () => commitActiveColor(before));
5026
+ };
5027
+ bindSlider("[data-color-hue]", (next) => {
5028
+ if (activeColor) activeColor.hue = next;
5029
+ });
5030
+ bindSlider("[data-color-alpha]", (next) => {
5031
+ if (activeColor) activeColor.alpha = next / 100;
5032
+ });
5033
+ const hexField = colorPopover.querySelector("[data-color-hex]");
5034
+ let hexBefore = control.read();
5035
+ hexField.addEventListener("focus", () => {
5036
+ hexBefore = control.read();
5037
+ });
5038
+ hexField.addEventListener("change", () => {
5039
+ setActiveColor(hexField.value);
5040
+ commitActiveColor(hexBefore);
5041
+ });
5042
+ colorPopover.querySelectorAll("[data-color-value]").forEach((button) => {
5043
+ button.addEventListener("click", () => {
5044
+ const before = control.read();
5045
+ setActiveColor(button.dataset.colorValue ?? "#000000");
5046
+ commitActiveColor(before);
5047
+ });
5048
+ });
5049
+ colorPopover.querySelector("[data-eyedropper]")?.addEventListener("click", async () => {
5050
+ const EyeDropper = window.EyeDropper;
5051
+ if (!EyeDropper) {
5052
+ showToast("Eyedropper is not available in this browser");
5053
+ return;
5054
+ }
5055
+ const before = control.read();
5056
+ const result = await new EyeDropper().open().catch(() => void 0);
5057
+ if (!result) return;
5058
+ setActiveColor(result.sRGBHex);
5059
+ commitActiveColor(before);
5060
+ });
5061
+ }
4391
5062
  function renderControls() {
4392
5063
  renderToolTabs();
4393
5064
  if (!selected) {
@@ -4405,20 +5076,55 @@ function installFoundryInspector(options = {}) {
4405
5076
  {
4406
5077
  key: "layout",
4407
5078
  category: "layout",
4408
- label: "Layout and spacing",
5079
+ label: "Layout",
4409
5080
  icon: CATEGORY_ICONS.layout,
4410
5081
  sectionLabels: ["Flow", "Padding", "Margin"],
4411
5082
  showContext: true
4412
5083
  },
4413
- ...["typography", "color", "effects", "content", "accessibility"].map(
4414
- (category) => ({
4415
- key: category,
4416
- category,
4417
- label: CATEGORY_LABELS[category],
4418
- icon: CATEGORY_ICONS[category],
4419
- showContext: true
4420
- })
4421
- )
5084
+ {
5085
+ key: "typography",
5086
+ category: "typography",
5087
+ label: "Typography",
5088
+ icon: CATEGORY_ICONS.typography,
5089
+ showContext: true
5090
+ },
5091
+ {
5092
+ key: "appearance",
5093
+ category: "color",
5094
+ label: "Appearance",
5095
+ icon: "eye",
5096
+ sectionLabels: ["Appearance"]
5097
+ },
5098
+ {
5099
+ key: "fill",
5100
+ category: "color",
5101
+ label: "Fill",
5102
+ icon: CATEGORY_ICONS.color,
5103
+ sectionLabels: ["Fill"],
5104
+ showContext: true
5105
+ },
5106
+ {
5107
+ key: "stroke",
5108
+ category: "effects",
5109
+ label: "Stroke",
5110
+ icon: "box",
5111
+ sectionLabels: ["Stroke"]
5112
+ },
5113
+ {
5114
+ key: "effects",
5115
+ category: "effects",
5116
+ label: "Effects",
5117
+ icon: CATEGORY_ICONS.effects,
5118
+ sectionLabels: ["Corners", "Effects"],
5119
+ showContext: true
5120
+ },
5121
+ ...["content", "accessibility"].map((category) => ({
5122
+ key: category,
5123
+ category,
5124
+ label: CATEGORY_LABELS[category],
5125
+ icon: CATEGORY_ICONS[category],
5126
+ showContext: true
5127
+ }))
4422
5128
  ];
4423
5129
  const indexedControls = selectedControls.map((control, index) => ({ control, index })).filter(
4424
5130
  ({ control }) => tokenOnly ? matchingTokens(
@@ -4445,7 +5151,8 @@ function installFoundryInspector(options = {}) {
4445
5151
  entries.forEach(({ control }) => renderedProperties.add(control.property));
4446
5152
  if (!entries.length) return "";
4447
5153
  const sectionKey = `${group.key}:${section.label}`;
4448
- return `<section class="property-section ${collapsedSections.has(sectionKey) ? "collapsed" : ""}" data-section-key="${escapeHtml(sectionKey)}"><div class="section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(sectionKey))}"><i data-foundry-icon="chevron-down"></i><strong>${escapeHtml(section.label)}</strong></button>${section.label === "Padding" ? `<button class="section-action ${paddingLinked ? "active" : ""}" data-padding-link aria-label="${paddingLinked ? "Unlink padding values" : "Link padding values"}"><i data-foundry-icon="${paddingLinked ? "link-2" : "unlink-2"}"></i></button>` : ""}</div><div class="section-grid ${section.columns === 2 ? "two" : ""} ${section.stacked ? "stacked" : ""}">${entries.map(
5154
+ const sectionActions = section.label === "Position and size" ? '<span class="section-actions"><button class="section-action" data-layout-action="lock" aria-label="Lock aspect ratio" title="Lock aspect ratio"><i data-foundry-icon="lock"></i></button></span>' : section.label === "Padding" ? `<span class="section-actions"><button class="section-action ${paddingLinked ? "active" : ""}" data-padding-link aria-label="${paddingLinked ? "Unlink padding values" : "Link padding values"}"><i data-foundry-icon="${paddingLinked ? "link-2" : "unlink-2"}"></i></button></span>` : section.label === "Typeface" ? '<span class="section-actions type-presets"><button data-type-preset="compact">S</button><button data-type-preset="body">M</button><button data-type-preset="display">L</button></span>' : section.label === "Fill" ? '<span class="section-actions"><button class="section-action" data-color-action="gradient" aria-label="Add linear gradient" title="Add gradient"><i data-foundry-icon="sparkles"></i></button><button class="section-action" data-color-action="clear" aria-label="Clear fill" title="Clear fill"><i data-foundry-icon="x"></i></button></span>' : section.label === "Corners" ? `<span class="section-actions"><button class="section-action ${radiusLinked ? "active" : ""}" data-radius-link aria-label="${radiusLinked ? "Edit corner radii independently" : "Link corner radii"}"><i data-foundry-icon="${radiusLinked ? "link-2" : "unlink-2"}"></i></button></span>` : "";
5155
+ return `<section class="property-section ${collapsedSections.has(sectionKey) ? "collapsed" : ""}" data-section-key="${escapeHtml(sectionKey)}"><div class="section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(sectionKey))}"><i data-foundry-icon="chevron-down"></i><strong>${escapeHtml(section.label)}</strong></button>${sectionActions}</div><div class="section-grid ${section.columns === 2 ? "two" : ""} ${section.stacked ? "stacked" : ""}">${entries.map(
4449
5156
  ({ control, index }) => renderPropertyControl(control, index, section.prefixes?.[control.property])
4450
5157
  ).join("")}</div></section>`;
4451
5158
  }).join("");
@@ -4454,7 +5161,8 @@ function installFoundryInspector(options = {}) {
4454
5161
  );
4455
5162
  const remainingSection = remaining.length ? `<section class="property-section ${collapsedSections.has(`${group.key}:Other`) ? "collapsed" : ""}" data-section-key="${escapeHtml(`${group.key}:Other`)}"><div class="section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(`${group.key}:Other`))}"><i data-foundry-icon="chevron-down"></i><strong>Other</strong></button></div><div class="section-grid">${remaining.map(({ control, index }) => renderPropertyControl(control, index)).join("")}</div></section>` : "";
4456
5163
  const categoryKey = `category:${group.key}`;
4457
- return `<section class="inspector-category property-section ${collapsedSections.has(categoryKey) ? "collapsed" : ""}" data-category="${group.key}" data-section-key="${categoryKey}"><div class="inspector-heading section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(categoryKey))}"><i data-foundry-icon="${group.icon}"></i><strong>${group.label}</strong></button><span class="property-count">${controls.length}</span></div><div class="category-body">${group.showContext ? renderContextPanel(group.category) : ""}${sections}${remainingSection}</div></section>`;
5164
+ const categoryAction = group.key === "layout" ? '<button class="category-action" data-layout-action="tidy"><i data-foundry-icon="wand-sparkles"></i><span>Tidy</span></button>' : "";
5165
+ return `<section class="inspector-category property-section ${collapsedSections.has(categoryKey) ? "collapsed" : ""}" data-category="${group.key}" data-section-key="${categoryKey}"><div class="inspector-heading section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(categoryKey))}"><i data-foundry-icon="${group.icon}"></i><strong>${group.label}</strong></button>${categoryAction}<span class="property-count">${controls.length}</span></div><div class="category-body">${group.showContext ? renderContextPanel(group.category) : ""}${sections}${remainingSection}</div></section>`;
4458
5166
  }).join("");
4459
5167
  const currentBaseline = baselineForContext(
4460
5168
  designMemory,
@@ -4476,6 +5184,7 @@ function installFoundryInspector(options = {}) {
4476
5184
  button.setAttribute("aria-expanded", String(!collapsed));
4477
5185
  if (collapsed) collapsedSections.add(key);
4478
5186
  else collapsedSections.delete(key);
5187
+ sectionPreferenceTouched = true;
4479
5188
  sessionStorage.setItem(
4480
5189
  "__foundry_collapsed_sections",
4481
5190
  JSON.stringify([...collapsedSections])
@@ -4488,6 +5197,12 @@ function installFoundryInspector(options = {}) {
4488
5197
  renderControls();
4489
5198
  })
4490
5199
  );
5200
+ controlsRoot.querySelectorAll("[data-radius-link]").forEach(
5201
+ (button) => button.addEventListener("click", () => {
5202
+ radiusLinked = !radiusLinked;
5203
+ renderControls();
5204
+ })
5205
+ );
4491
5206
  indexedControls.forEach(({ control, index }) => {
4492
5207
  const matches = matchingTokens(
4493
5208
  designGraph?.tokens ?? [],
@@ -4495,7 +5210,8 @@ function installFoundryInspector(options = {}) {
4495
5210
  `${control.value}${control.unit ?? ""}`
4496
5211
  );
4497
5212
  const tokenEligible = control.category === "layout" && /gap|padding|margin/i.test(control.property) || control.category === "typography" && /font|lineHeight|letterSpacing/i.test(control.property) || control.category === "color" && /color|background|fill|stroke/i.test(control.property) || control.category === "effects" && /radius|shadow|blur/i.test(control.property);
4498
- if (!tokenEligible || !tokensForCategory(control.category).length) return;
5213
+ const availableTokens = tokensForCategory(control.category);
5214
+ if (!tokenEligible || !availableTokens.length) return;
4499
5215
  const field = controlsRoot.querySelector(`[data-control="${index}"]`);
4500
5216
  const label = field?.closest("label");
4501
5217
  if (!label) return;
@@ -4503,14 +5219,27 @@ function installFoundryInspector(options = {}) {
4503
5219
  "beforeend",
4504
5220
  matches.length ? `<span class="token-provenance">Uses ${escapeHtml(matches[0].name)}</span>` : '<span class="token-provenance literal">Literal value \xB7 consider a project token</span>'
4505
5221
  );
4506
- if (!matches.length) return;
4507
5222
  label.insertAdjacentHTML(
4508
5223
  "beforeend",
4509
- `<span class="token-row">${matches.map(
4510
- (token2) => `<button type="button" class="token-chip" data-token-control="${index}" data-token-value="${escapeHtml(token2.value)}" title="${escapeHtml(token2.value)}">${escapeHtml(token2.name)}</button>`
4511
- ).join("")}</span>`
5224
+ `<span class="token-menu-wrap"><button type="button" class="token-menu-trigger" data-token-menu-trigger="${index}" aria-expanded="false" aria-label="Choose a project token"><i data-foundry-icon="bookmark"></i></button><span class="token-menu" data-token-menu="${index}" hidden>${availableTokens.map(
5225
+ (token2) => `<button type="button" class="token-option" data-token-control="${index}" data-token-value="${escapeHtml(token2.value)}" title="${escapeHtml(token2.value)}">${control.category === "color" ? `<span class="swatch" style="--token-color:${escapeHtml(token2.value)}"></span>` : ""}<span>${escapeHtml(token2.name)}</span><code>${escapeHtml(token2.value)}</code></button>`
5226
+ ).join("")}</span></span>`
4512
5227
  );
4513
5228
  });
5229
+ renderIcons(controlsRoot);
5230
+ controlsRoot.querySelectorAll("[data-token-menu-trigger]").forEach((button) => {
5231
+ button.addEventListener("click", () => {
5232
+ const menu = controlsRoot.querySelector(
5233
+ `[data-token-menu="${button.dataset.tokenMenuTrigger}"]`
5234
+ );
5235
+ if (!menu) return;
5236
+ controlsRoot.querySelectorAll("[data-token-menu]").forEach((candidate2) => {
5237
+ if (candidate2 !== menu) candidate2.hidden = true;
5238
+ });
5239
+ menu.hidden = !menu.hidden;
5240
+ button.setAttribute("aria-expanded", String(!menu.hidden));
5241
+ });
5242
+ });
4514
5243
  controlsRoot.querySelectorAll("[data-reset-control]").forEach((button) => {
4515
5244
  button.addEventListener("click", () => {
4516
5245
  const control = selectedControls[Number(button.dataset.resetControl)];
@@ -4628,10 +5357,38 @@ function installFoundryInspector(options = {}) {
4628
5357
  fieldRecorders.get(linkedIndex)?.push(linkedBefore, value);
4629
5358
  });
4630
5359
  }
5360
+ const radiusProperties = [
5361
+ "borderTopLeftRadius",
5362
+ "borderTopRightRadius",
5363
+ "borderBottomLeftRadius",
5364
+ "borderBottomRightRadius"
5365
+ ];
5366
+ if (radiusLinked && (control.property === "borderRadius" || radiusProperties.includes(control.property))) {
5367
+ indexedControls.forEach(({ control: linkedControl, index: linkedIndex }) => {
5368
+ if (linkedControl === control || !radiusProperties.includes(linkedControl.property))
5369
+ return;
5370
+ const linkedBefore = linkedControl.read();
5371
+ linkedControl.apply(value);
5372
+ const linkedField = controlsRoot.querySelector(
5373
+ `[data-control="${linkedIndex}"]`
5374
+ );
5375
+ if (linkedField) linkedField.value = String(value);
5376
+ fieldRecorders.get(linkedIndex)?.push(linkedBefore, value);
5377
+ });
5378
+ }
4631
5379
  updateOutline();
4632
5380
  recorder.push(before, value);
4633
5381
  });
4634
5382
  });
5383
+ controlsRoot.querySelectorAll("[data-color-control]").forEach((button) => {
5384
+ button.addEventListener("click", () => {
5385
+ const index = Number(button.dataset.colorControl);
5386
+ const control = selectedControls[index];
5387
+ if (!control) return;
5388
+ activeControlProperty = control.property;
5389
+ openColorEditor(button, index);
5390
+ });
5391
+ });
4635
5392
  controlsRoot.querySelectorAll("[data-token-control]").forEach((button) => {
4636
5393
  button.addEventListener("click", () => {
4637
5394
  const index = Number(button.dataset.tokenControl);
@@ -4639,8 +5396,16 @@ function installFoundryInspector(options = {}) {
4639
5396
  `[data-control="${index}"]`
4640
5397
  );
4641
5398
  const control = selectedControls[index];
4642
- if (!field || !control) return;
5399
+ if (!control) return;
4643
5400
  const raw = button.dataset.tokenValue ?? "";
5401
+ if (control.kind === "color") {
5402
+ void applyControlValue(control, raw, "Use project color").then(() => {
5403
+ if (selected) selectedControls = controlsFor(selected);
5404
+ renderControls();
5405
+ });
5406
+ return;
5407
+ }
5408
+ if (!field) return;
4644
5409
  field.value = control.kind === "number" ? String(numberFrom(raw)) : raw;
4645
5410
  field.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
4646
5411
  });
@@ -4651,6 +5416,8 @@ function installFoundryInspector(options = {}) {
4651
5416
  }
4652
5417
  function select(element, additive = false) {
4653
5418
  if (element === host || host.contains(element)) return;
5419
+ colorPopover.hidden = true;
5420
+ activeColor = void 0;
4654
5421
  if (additive && selectedElements.includes(element)) {
4655
5422
  selectedElements = selectedElements.filter((item) => item !== element);
4656
5423
  if (!selectedElements.length) {
@@ -4666,6 +5433,40 @@ function installFoundryInspector(options = {}) {
4666
5433
  selectedElements = [element];
4667
5434
  selected = element;
4668
5435
  }
5436
+ if (!sectionPreferenceTouched) {
5437
+ const categoryKeys = [
5438
+ "position",
5439
+ "layout",
5440
+ "typography",
5441
+ "appearance",
5442
+ "fill",
5443
+ "stroke",
5444
+ "effects",
5445
+ "content",
5446
+ "accessibility",
5447
+ "motion"
5448
+ ];
5449
+ categoryKeys.forEach((key) => collapsedSections.add(`category:${key}`));
5450
+ collapsedSections.delete("category:position");
5451
+ collapsedSections.delete("category:layout");
5452
+ collapsedSections.delete("category:appearance");
5453
+ collapsedSections.delete("category:fill");
5454
+ const isText = element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element.children.length === 0 && Boolean(element.textContent?.trim());
5455
+ const isMedia = element instanceof HTMLImageElement;
5456
+ if (isText) {
5457
+ collapsedSections.delete("category:typography");
5458
+ collapsedSections.delete("category:content");
5459
+ }
5460
+ if (isMedia) {
5461
+ collapsedSections.delete("category:content");
5462
+ collapsedSections.delete("category:accessibility");
5463
+ }
5464
+ if (Number.parseFloat(getComputedStyle(element).borderWidth) > 0)
5465
+ collapsedSections.delete("category:stroke");
5466
+ if (getComputedStyle(element).boxShadow !== "none" || Number.parseFloat(getComputedStyle(element).borderRadius) > 0)
5467
+ collapsedSections.delete("category:effects");
5468
+ if (element.getAnimations().length) collapsedSections.delete("category:motion");
5469
+ }
4669
5470
  selectedControls = controlsFor(element);
4670
5471
  const target = targetFor(element);
4671
5472
  panel.classList.add("has-selection");
@@ -4702,6 +5503,8 @@ function installFoundryInspector(options = {}) {
4702
5503
  });
4703
5504
  }
4704
5505
  function clearSelection() {
5506
+ colorPopover.hidden = true;
5507
+ activeColor = void 0;
4705
5508
  selected = null;
4706
5509
  selectedElements = [];
4707
5510
  selectedControls = [];
@@ -5067,25 +5870,25 @@ function installFoundryInspector(options = {}) {
5067
5870
  method: "POST",
5068
5871
  body: JSON.stringify({ runId, results })
5069
5872
  });
5070
- if (workspaceState.tray === "expanded") renderReviewPayload(payload);
5873
+ if (workspaceState.reviewOpen) renderReviewPayload(payload);
5071
5874
  showToast(
5072
5875
  `${results.filter((result) => result.passed).length}/${results.length} changes verified`
5073
5876
  );
5074
5877
  }
5075
5878
  function installPanelResizer() {
5076
5879
  const resizer = shadow.querySelector(".panel-resizer");
5077
- const savedWidth = Number(localStorage.getItem("__foundry_panel_width"));
5078
- if (Number.isFinite(savedWidth) && savedWidth >= 300) panel.style.width = `${savedWidth}px`;
5079
5880
  resizer.addEventListener("pointerdown", (event) => {
5080
- if (event.button !== 0) return;
5881
+ if (event.button !== 0 || window.matchMedia("(max-width: 680px)").matches) return;
5081
5882
  const startX = event.clientX;
5082
- const startWidth = panel.getBoundingClientRect().width;
5883
+ const startWidth = dockWidth;
5083
5884
  resizer.setPointerCapture(event.pointerId);
5084
5885
  event.preventDefault();
5085
5886
  const move = (pointer) => {
5086
5887
  const maximum = Math.min(520, window.innerWidth - 24);
5087
- const next = Math.max(300, Math.min(maximum, startWidth + startX - pointer.clientX));
5088
- panel.style.width = `${Math.round(next)}px`;
5888
+ const next = Math.max(340, Math.min(maximum, startWidth + startX - pointer.clientX));
5889
+ dockWidth = Math.round(next);
5890
+ host.style.setProperty("--fdc-dock-width", `${dockWidth}px`);
5891
+ positionWorkspaceSurfaces();
5089
5892
  };
5090
5893
  const finish = (pointer) => {
5091
5894
  resizer.removeEventListener("pointermove", move);
@@ -5093,10 +5896,8 @@ function installFoundryInspector(options = {}) {
5093
5896
  resizer.removeEventListener("pointercancel", finish);
5094
5897
  if (resizer.hasPointerCapture(pointer.pointerId))
5095
5898
  resizer.releasePointerCapture(pointer.pointerId);
5096
- localStorage.setItem(
5097
- "__foundry_panel_width",
5098
- String(Math.round(panel.getBoundingClientRect().width))
5099
- );
5899
+ localStorage.setItem(dockWidthKey, String(dockWidth));
5900
+ localStorage.removeItem(legacyDockWidthKey);
5100
5901
  };
5101
5902
  resizer.addEventListener("pointermove", move);
5102
5903
  resizer.addEventListener("pointerup", finish);
@@ -5232,6 +6033,16 @@ function installFoundryInspector(options = {}) {
5232
6033
  }
5233
6034
  });
5234
6035
  statusPopover.querySelector("[data-status-retry]").addEventListener("click", () => void hydrateSession());
6036
+ interfaceThemeTrigger.addEventListener("click", () => {
6037
+ if (interfaceThemeMenu.hidden) openInterfaceThemeMenu();
6038
+ else closeInterfaceThemeMenu();
6039
+ });
6040
+ interfaceThemeMenu.querySelectorAll("[data-interface-theme-choice]").forEach(
6041
+ (button) => button.addEventListener("click", () => {
6042
+ applyInterfaceTheme(button.dataset.interfaceThemeChoice);
6043
+ closeInterfaceThemeMenu(true);
6044
+ })
6045
+ );
5235
6046
  changeDock.querySelector(".dock-undo")?.addEventListener("click", () => void replayHistory(-1));
5236
6047
  changeDock.querySelector(".dock-review")?.addEventListener("click", () => void openReview());
5237
6048
  onboarding.querySelector(".onboarding-start")?.addEventListener("click", () => {
@@ -5332,13 +6143,14 @@ function installFoundryInspector(options = {}) {
5332
6143
  );
5333
6144
  comparisonStage.querySelector("[data-close-comparison-stage]").addEventListener("click", closeSplitComparison);
5334
6145
  const commandInput = commandPalette.querySelector("input");
6146
+ commandPalette.querySelector(".close-commands")?.addEventListener("click", () => closeCommands());
5335
6147
  commandInput.addEventListener("input", () => renderCommands(commandInput.value));
5336
6148
  commandInput.addEventListener("keydown", (event) => {
5337
6149
  if (event.key === "Enter") {
5338
6150
  const active = commandPalette.querySelector(".command-item.active");
5339
6151
  if (active) runCommand(active.dataset.command);
5340
6152
  }
5341
- if (event.key === "Escape") commandPalette.hidden = true;
6153
+ if (event.key === "Escape") closeCommands();
5342
6154
  });
5343
6155
  shadow.querySelector(".close")?.addEventListener("click", destroyInspector);
5344
6156
  shadow.querySelector(".open-workbench")?.addEventListener("click", openWorkbench);
@@ -5364,7 +6176,7 @@ function installFoundryInspector(options = {}) {
5364
6176
  shadow.querySelector(".redo")?.addEventListener("click", () => void replayHistory(1));
5365
6177
  shadow.querySelector(".align")?.addEventListener("click", () => void alignSelected());
5366
6178
  shadow.querySelector(".distribute")?.addEventListener("click", () => void distributeSelected());
5367
- shadow.querySelector(".review-back")?.addEventListener("click", closeReview);
6179
+ shadow.querySelector(".review-back")?.addEventListener("click", () => closeReview());
5368
6180
  reviewCancel.addEventListener("click", () => {
5369
6181
  if (reviewCancel.dataset.action === "cancel") void cancelRun();
5370
6182
  else closeReview();
@@ -5374,6 +6186,25 @@ function installFoundryInspector(options = {}) {
5374
6186
  if (applyButton.dataset.action === "retry") void retryRun();
5375
6187
  });
5376
6188
  function handleGlobalShortcuts(event) {
6189
+ if (workspaceState.reviewOpen && event.key === "Tab") {
6190
+ const focusable = [
6191
+ ...reviewModal.querySelectorAll(
6192
+ 'button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex="-1"])'
6193
+ )
6194
+ ].filter((element) => element.offsetParent !== null);
6195
+ if (focusable.length) {
6196
+ const first = focusable[0];
6197
+ const last = focusable.at(-1);
6198
+ if (event.shiftKey && shadow.activeElement === first) {
6199
+ event.preventDefault();
6200
+ last.focus();
6201
+ } else if (!event.shiftKey && shadow.activeElement === last) {
6202
+ event.preventDefault();
6203
+ first.focus();
6204
+ }
6205
+ }
6206
+ return;
6207
+ }
5377
6208
  const editable = event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLSelectElement || event.target instanceof HTMLElement && event.target.isContentEditable;
5378
6209
  if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
5379
6210
  event.preventDefault();
@@ -5412,13 +6243,22 @@ function installFoundryInspector(options = {}) {
5412
6243
  return;
5413
6244
  }
5414
6245
  if (event.key !== "Escape") return;
5415
- if (!comparisonStage.hidden) closeSplitComparison();
5416
- else if (!commandPalette.hidden) commandPalette.hidden = true;
6246
+ if (workspaceState.reviewOpen) {
6247
+ const nested = reviewModal.querySelector("details[open]");
6248
+ if (nested) nested.open = false;
6249
+ else closeReview();
6250
+ return;
6251
+ }
6252
+ if (!interfaceThemeMenu.hidden) closeInterfaceThemeMenu(true);
6253
+ else if (!colorPopover.hidden) {
6254
+ colorPopover.hidden = true;
6255
+ activeColor = void 0;
6256
+ } else if (!comparisonStage.hidden) closeSplitComparison();
6257
+ else if (!commandPalette.hidden) closeCommands();
5417
6258
  else if (!libraryPanel.hidden) closeDesignMemory();
5418
6259
  else if (!healthPanel.hidden) closeHealth();
5419
6260
  else if (comparisonActive) closeComparison();
5420
6261
  else if (!workbench.hidden) closeWorkbench();
5421
- else if (workspaceState.tray === "expanded") closeReview();
5422
6262
  else clearSelection();
5423
6263
  }
5424
6264
  document.addEventListener("keydown", handleGlobalShortcuts);
@@ -5452,6 +6292,8 @@ function installFoundryInspector(options = {}) {
5452
6292
  cancelAnimationFrame(layerScrollFrame);
5453
6293
  cancelAnimationFrame(mutationFrame);
5454
6294
  layerMutationObserver.disconnect();
6295
+ systemDarkTheme.removeEventListener("change", handleSystemThemeChange);
6296
+ document.removeEventListener("pointerdown", handleInterfaceThemeDismiss, true);
5455
6297
  clearInterval(reviewPoll);
5456
6298
  document.removeEventListener("click", handlePointer, true);
5457
6299
  document.removeEventListener("dblclick", handleTextEdit, true);