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

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,216 @@ 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); }
1267
+ .review-agent { display:grid;grid-template-columns:8px minmax(0,1fr) auto;align-items:center;gap:12px;margin:12px 16px 0;padding:12px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-paper); }
1268
+ .review-agent>i { width:8px;height:8px;border-radius:50%;background:#d16d51; }
1269
+ .review-agent.connected>i { background:#2ca67f;box-shadow:0 0 0 4px rgb(44 166 127 / 12%); }
1270
+ .review-agent strong,.review-agent span { display:block; }
1271
+ .review-agent strong { font-size:12px;font-weight:600; }
1272
+ .review-agent span { margin-top:4px;color:var(--fdc-muted);font-size:12px;line-height:1.45; }
1273
+ .review-agent button { height:32px;padding:0 12px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-elevated);color:var(--fdc-ink);font-size:12px;cursor:pointer; }
1274
+ .review-agent button:hover { border-color:var(--fdc-muted); }
1167
1275
  .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; }
1276
+ .change-tray .review-group-title { position:sticky;top:52px;z-index:2;min-height:40px;padding:0 12px;background:rgb(28 28 31 / 98%); }
1277
+ .review-group-title .included-count { font-size:8px; }
1278
+ .review-card { min-height:52px;grid-template-columns:20px minmax(0,1fr);align-items:start;gap:8px;padding:8px 12px; }
1279
+ .review-card input[type="checkbox"] { margin-top:8px; }
1280
+ .review-card-line { min-height:32px;display:grid;grid-template-columns:minmax(120px,1fr) auto minmax(220px,320px) 32px;align-items:center;gap:8px; }
1281
+ .review-card-line>strong { font-size:12px; }
1282
+ .review-values { min-width:0;display:grid;grid-template-columns:minmax(72px,1fr) 12px minmax(92px,1fr);align-items:center;gap:4px;margin:0; }
1283
+ .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; }
1284
+ .review-after { height:32px;font-size:12px; }
1177
1285
  .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; }
1286
+ .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
1287
  .review-more>summary::-webkit-details-marker { display:none; }
1180
1288
  .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; }
1289
+ .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%); }
1290
+ .review-more .review-card-tools button { width:100%;height:28px;padding:0 8px;border:0;text-align:left;background:transparent; }
1183
1291
  .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; }
1292
+ .review-details { margin-top:4px;padding-top:4px;border-top:1px solid var(--fdc-line); }
1293
+ .review-details summary { min-height:28px;display:flex;align-items:center;padding:0 8px;color:var(--fdc-muted);font-size:8px;cursor:pointer; }
1294
+ .review-details[open] { padding-bottom:8px; }
1295
+ .review-details .review-source,.review-details .impact-list { padding-right:8px;padding-left:8px; }
1188
1296
  .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}}
1297
+ @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}}
1298
+ @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}}
1299
+ .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; }
1300
+ .compare-bar { bottom:calc(80px + var(--fdc-tray-lift,0px)); }
1301
+ @keyframes fdc-selection-title { from { opacity:.45;transform:translateY(4px) } to { opacity:1;transform:none } }
1302
+ @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))}}
1303
+ /* Shared dock geometry and focused review takeover. */
1304
+ .panel,.layers-panel,.change-tray { width:var(--fdc-dock-width,384px); }
1305
+ .layers-panel { max-width:min(520px,calc(100vw - 24px)); }
1306
+ .change-tray { z-index:2147483647;right:12px;bottom:12px;left:auto;height:48px;min-height:48px; }
1307
+ .change-tray-summary { min-height:48px;grid-template-columns:minmax(0,1fr) 32px 72px; }
1308
+ .panel.change-summary-visible .inspector-scroll { padding-bottom:60px;scroll-padding-bottom:60px; }
1309
+ .tool-shelf { bottom:20px; }
1310
+ .compare-bar { bottom:80px; }
1311
+ .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; }
1312
+ .review-takeover[hidden] { display:none; }
1313
+ .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%); }
1314
+ .review-modal .review-view { width:100%;min-width:0;min-height:0;display:flex; }
1315
+ .review-modal .review-head { flex:none;min-height:52px;padding:0 16px; }
1316
+ .review-modal .review-body { min-height:0;flex:1;display:block;overflow-x:hidden;overflow-y:auto; }
1317
+ .review-modal .review-group { border-right:0;border-bottom:1px solid var(--fdc-line); }
1318
+ .review-modal .review-group-title { position:sticky;top:52px;z-index:2;background:rgb(28 28 31 / 98%); }
1319
+ .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); }
1320
+ /* Review is a reading surface, so it uses a larger type scale than the dense inspector. */
1321
+ .review-modal .review-head strong { font-size:16px;font-weight:600;letter-spacing:-.015em; }
1322
+ .review-modal .review-head span { font-size:12px; }
1323
+ .review-modal .review-overview { min-height:60px;padding:12px 16px; }
1324
+ .review-modal .review-overview .review-summary strong { font-size:16px;font-weight:600; }
1325
+ .review-modal .review-overview .review-summary span { margin-top:4px;font-size:12px;line-height:1.45; }
1326
+ .review-modal .review-overview .review-toolbar button { height:36px;padding:0 12px;font-size:12px; }
1327
+ .review-modal .review-group-title { min-height:48px;padding:0 16px;font-size:12px; }
1328
+ .review-modal .review-group-title strong { font-size:16px;font-weight:600; }
1329
+ .review-modal .review-group-title .included-count,.review-modal .review-group-title .group-total { font-size:12px; }
1330
+ .review-modal .review-card { min-height:64px;gap:12px;padding:12px 16px; }
1331
+ .review-modal .review-card input[type="checkbox"] { width:16px;height:16px;margin-top:8px; }
1332
+ .review-modal .review-card-line { min-height:36px;gap:12px; }
1333
+ .review-modal .review-card-line>strong { font-size:16px;font-weight:550; }
1334
+ .review-modal .confidence-pill { padding:4px 8px;font-size:12px; }
1335
+ .review-modal .review-before { padding:0 8px;font-size:12px; }
1336
+ .review-modal .review-after { height:36px;padding:0 12px;font-size:12px; }
1337
+ .review-modal .review-more>summary { width:32px;height:32px;font-size:12px; }
1338
+ .review-modal .review-more .review-card-tools { top:36px; }
1339
+ .review-modal .review-more .review-card-tools button { height:32px;padding:0 8px;font-size:12px; }
1340
+ .review-modal .review-details summary { min-height:32px;font-size:12px; }
1341
+ .review-modal .review-source { font-size:12px;line-height:1.5; }
1342
+ .review-modal .impact-list,.review-modal .impact-list li { font-size:12px;line-height:1.5; }
1343
+ .review-modal .review-actions button { min-height:44px;font-size:12px;font-weight:550; }
1344
+ .review-modal .run-state strong { font-size:16px; }
1345
+ .review-modal .run-summary p { font-size:12px; }
1346
+ .review-modal .run-step strong,.review-modal .result-row { font-size:12px; }
1347
+ .review-modal .run-step p,.review-modal .run-files { font-size:12px; }
1348
+ .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; }
1349
+ .interface-theme-menu[hidden] { display:none; }
1350
+ .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; }
1351
+ .interface-theme-menu button:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }
1352
+ .interface-theme-menu button[aria-checked="true"] { color:var(--fdc-ink);background:var(--fdc-subtle); }
1353
+ .interface-theme-menu button svg { width:12px;height:12px;color:var(--fdc-signal); }
1354
+ .interface-theme-menu button:not([aria-checked="true"]) svg { visibility:hidden; }
1355
+ :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; }
1356
+ :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%); }
1357
+ :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); }
1358
+ :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); }
1359
+ :host([data-interface-theme="light"]) .review-modal .review-group-title { background:rgb(247 247 248 / 98%); }
1360
+ :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; }
1361
+ :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); }
1362
+ :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); }
1363
+ :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); }
1364
+ :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); }
1365
+ :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); }
1366
+ :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); }
1367
+ :host([data-interface-theme="light"]) .layer-row.selected { color:#1458b8;background:transparent; }
1368
+ :host([data-interface-theme="light"]) .layer-row .layer-meta { color:#65676e;background:var(--fdc-subtle); }
1369
+ :host([data-interface-theme="light"]) .layer-row.selected .layer-meta { color:#1458b8;background:#dceaff; }
1370
+ :host([data-interface-theme="light"]) .tool-select.active,:host([data-interface-theme="light"]) .tab.active { color:var(--fdc-ink);background:#e4e5e8; }
1371
+ :host([data-interface-theme="light"]) .tool-select.inspect.active { color:white;background:var(--fdc-signal); }
1372
+ :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; }
1373
+ :host([data-interface-theme="light"]) .session-status,:host([data-interface-theme="light"]) .session-status.saved { color:#236c59;background:#eef8f4; }
1374
+ :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%); }
1375
+ .control-field { height:36px;border-radius:8px; }
1376
+ .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); }
1377
+ .field-prefix svg { width:12px;height:12px; }
1378
+ .property-control input,.property-control select,.compact-control input,.compact-control select { height:36px;font-size:12px;font-weight:400; }
1379
+ .control-field .unit-select { width:44px;padding-right:24px!important;background-position:right 8px center!important; }
1380
+ .section-grid { gap:8px;padding:0 16px 16px; }
1381
+ @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}}
1382
+ @media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}.layer-row.entering,.layer-branch{animation:none!important}}
1196
1383
  `;
1197
1384
  function numberFrom(value) {
1198
1385
  const parsed = Number.parseFloat(value);
1199
1386
  return Number.isFinite(parsed) ? parsed : 0;
1200
1387
  }
1201
- function pxControl(element, computed, category, property, label, max = 600) {
1388
+ function pxControl(element, computed, category, property, label, max = 600, min = 0) {
1202
1389
  return {
1203
1390
  category,
1204
1391
  property: String(property),
@@ -1206,7 +1393,7 @@ function pxControl(element, computed, category, property, label, max = 600) {
1206
1393
  kind: "number",
1207
1394
  value: numberFrom(String(computed[property])),
1208
1395
  unit: "px",
1209
- min: 0,
1396
+ min,
1210
1397
  max,
1211
1398
  step: 1,
1212
1399
  read: () => numberFrom(getComputedStyle(element)[property]),
@@ -1248,6 +1435,45 @@ function numberStyleControl(element, computed, category, property, label, min, m
1248
1435
  )
1249
1436
  };
1250
1437
  }
1438
+ function degreeControl(element, computed) {
1439
+ const read = () => numberFrom(getComputedStyle(element).rotate || "0");
1440
+ return {
1441
+ category: "layout",
1442
+ property: "rotate",
1443
+ label: "Rotation",
1444
+ kind: "number",
1445
+ value: numberFrom(computed.rotate || "0"),
1446
+ unit: "deg",
1447
+ min: -360,
1448
+ max: 360,
1449
+ step: 1,
1450
+ read,
1451
+ apply: (value) => element.style.setProperty("rotate", `${value}deg`)
1452
+ };
1453
+ }
1454
+ function scaleAxisControl(element, computed, axis) {
1455
+ const readScale = () => {
1456
+ const raw = getComputedStyle(element).scale;
1457
+ if (!raw || raw === "none") return [1, 1];
1458
+ const values = raw.split(/\s+/).map(numberFrom);
1459
+ return [values[0] || 1, values[1] ?? values[0] ?? 1];
1460
+ };
1461
+ const initial = computed.scale && computed.scale !== "none" ? readScale() : [1, 1];
1462
+ return {
1463
+ category: "layout",
1464
+ property: axis === "x" ? "scaleX" : "scaleY",
1465
+ label: axis === "x" ? "Flip horizontal" : "Flip vertical",
1466
+ kind: "select",
1467
+ options: ["1", "-1"],
1468
+ value: String(axis === "x" ? initial[0] : initial[1]),
1469
+ read: () => String(axis === "x" ? readScale()[0] : readScale()[1]),
1470
+ apply: (value) => {
1471
+ const current = readScale();
1472
+ current[axis === "x" ? 0 : 1] = Number(value);
1473
+ element.style.setProperty("scale", `${current[0]} ${current[1]}`);
1474
+ }
1475
+ };
1476
+ }
1251
1477
  function sizingModeControl(element, computed, axis) {
1252
1478
  const capitalized = axis === "width" ? "Width" : "Height";
1253
1479
  const minProperty = axis === "width" ? "minWidth" : "minHeight";
@@ -1292,6 +1518,10 @@ function sizingModeControl(element, computed, axis) {
1292
1518
  function controlsFor(element) {
1293
1519
  const computed = getComputedStyle(element);
1294
1520
  const controls = [
1521
+ ...computed.position !== "static" ? [
1522
+ pxControl(element, computed, "layout", "left", "X position", 5e3, -5e3),
1523
+ pxControl(element, computed, "layout", "top", "Y position", 5e3, -5e3)
1524
+ ] : [],
1295
1525
  sizingModeControl(element, computed, "width"),
1296
1526
  sizingModeControl(element, computed, "height"),
1297
1527
  styleControl(element, computed, "layout", "minWidth", "Minimum width"),
@@ -1304,6 +1534,9 @@ function controlsFor(element) {
1304
1534
  "auto",
1305
1535
  "scroll"
1306
1536
  ]),
1537
+ degreeControl(element, computed),
1538
+ scaleAxisControl(element, computed, "x"),
1539
+ scaleAxisControl(element, computed, "y"),
1307
1540
  pxControl(element, computed, "layout", "width", "Width", 1600),
1308
1541
  pxControl(element, computed, "layout", "height", "Height", 1200),
1309
1542
  styleControl(element, computed, "layout", "display", "Display", "select", [
@@ -1360,6 +1593,10 @@ function controlsFor(element) {
1360
1593
  numberStyleControl(element, computed, "color", "opacity", "Opacity", 0, 1, 0.05),
1361
1594
  styleControl(element, computed, "color", "backgroundImage", "Gradient"),
1362
1595
  pxControl(element, computed, "effects", "borderRadius", "Corner radius", 200),
1596
+ pxControl(element, computed, "effects", "borderTopLeftRadius", "Top left radius", 200),
1597
+ pxControl(element, computed, "effects", "borderTopRightRadius", "Top right radius", 200),
1598
+ pxControl(element, computed, "effects", "borderBottomLeftRadius", "Bottom left radius", 200),
1599
+ pxControl(element, computed, "effects", "borderBottomRightRadius", "Bottom right radius", 200),
1363
1600
  pxControl(element, computed, "effects", "borderWidth", "Border width", 32),
1364
1601
  styleControl(element, computed, "effects", "borderColor", "Border color", "color"),
1365
1602
  styleControl(element, computed, "effects", "boxShadow", "Shadow"),
@@ -1465,15 +1702,67 @@ function controlsFor(element) {
1465
1702
  }
1466
1703
  });
1467
1704
  }
1468
- return controls;
1705
+ const textBearing = element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || Boolean(element.textContent?.trim());
1706
+ const editableText = element.childElementCount === 0 || ["BUTTON", "A", "LABEL", "SUMMARY"].includes(element.tagName);
1707
+ return controls.filter((control) => {
1708
+ if (control.category === "typography") return textBearing;
1709
+ if (control.property === "textContent") return textBearing && editableText;
1710
+ if (control.property === "color") return textBearing;
1711
+ return true;
1712
+ });
1469
1713
  }
1470
1714
  function colorForInput(value) {
1471
1715
  const canvas = document.createElement("canvas");
1472
1716
  canvas.width = canvas.height = 1;
1473
1717
  const context = canvas.getContext("2d");
1474
1718
  if (!context) return "#000000";
1719
+ context.fillStyle = "#000000";
1475
1720
  context.fillStyle = value;
1476
- return context.fillStyle.startsWith("#") ? context.fillStyle : "#000000";
1721
+ const normalized = context.fillStyle;
1722
+ if (normalized.startsWith("#")) return normalized;
1723
+ const channels = normalized.match(/[\d.]+/g)?.slice(0, 3).map(Number);
1724
+ if (!channels || channels.length < 3) return "#000000";
1725
+ return `#${channels.map((channel2) => Math.round(channel2).toString(16).padStart(2, "0")).join("")}`;
1726
+ }
1727
+ function hexChannels(value) {
1728
+ const hex = colorForInput(value).slice(1);
1729
+ return [
1730
+ Number.parseInt(hex.slice(0, 2), 16),
1731
+ Number.parseInt(hex.slice(2, 4), 16),
1732
+ Number.parseInt(hex.slice(4, 6), 16)
1733
+ ];
1734
+ }
1735
+ function colorAlpha(value) {
1736
+ const slash = value.match(/\/\s*([\d.]+)%?\s*\)/);
1737
+ if (slash) return value.includes("%") ? Number(slash[1]) / 100 : Number(slash[1]);
1738
+ const comma = value.match(/rgba?\([^)]*,\s*([\d.]+)\s*\)$/);
1739
+ return comma ? Number(comma[1]) : isTransparentColor(value) ? 0 : 1;
1740
+ }
1741
+ function rgbToHsv(red, green, blue) {
1742
+ const r = red / 255;
1743
+ const g = green / 255;
1744
+ const b = blue / 255;
1745
+ const maximum = Math.max(r, g, b);
1746
+ const minimum = Math.min(r, g, b);
1747
+ const delta = maximum - minimum;
1748
+ let hue = 0;
1749
+ if (delta) {
1750
+ if (maximum === r) hue = 60 * ((g - b) / delta % 6);
1751
+ else if (maximum === g) hue = 60 * ((b - r) / delta + 2);
1752
+ else hue = 60 * ((r - g) / delta + 4);
1753
+ }
1754
+ if (hue < 0) hue += 360;
1755
+ return [hue, maximum ? delta / maximum : 0, maximum];
1756
+ }
1757
+ function hsvToRgb(hue, saturation, value) {
1758
+ const chroma = value * saturation;
1759
+ const x = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
1760
+ const match = value - chroma;
1761
+ 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];
1762
+ return [r, g, b].map((channel2) => Math.round((channel2 + match) * 255));
1763
+ }
1764
+ function rgbHex(red, green, blue) {
1765
+ return `#${[red, green, blue].map((channel2) => Math.max(0, Math.min(255, channel2)).toString(16).padStart(2, "0")).join("")}`;
1477
1766
  }
1478
1767
  function escapeHtml(value) {
1479
1768
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
@@ -1497,7 +1786,7 @@ function renderControlInput(control, index) {
1497
1786
  const rawValue = String(control.value);
1498
1787
  const value2 = colorForInput(rawValue);
1499
1788
  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)}"/>`;
1789
+ 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
1790
  }
1502
1791
  const type = control.kind === "number" ? "number" : "text";
1503
1792
  const value = displayValue(control);
@@ -1513,7 +1802,9 @@ function renderPropertyControl(control, index, prefix) {
1513
1802
  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
1803
  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
1804
  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>`;
1805
+ const prefixIcon = prefix === "Ratio" ? "maximize-2" : prefix === "Clip" ? "box" : void 0;
1806
+ const prefixContent = prefixIcon ? `<i data-foundry-icon="${prefixIcon}"></i>` : escapeHtml(prefix);
1807
+ 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
1808
  }
1518
1809
  return `<label class="property-control"><span class="property-label"${scrubAttributes}>${escapeHtml(control.label)}</span><span class="control-field">${field}${reset}</span></label>`;
1519
1810
  }
@@ -1535,7 +1826,14 @@ function installFoundryInspector(options = {}) {
1535
1826
  const sessionId = options.sessionId ?? query.get("__foundry_session") ?? "";
1536
1827
  const token = options.token ?? query.get("__foundry_token") ?? "";
1537
1828
  const host = document.createElement("div");
1829
+ const interfaceThemeKey = "__foundry_interface_theme";
1830
+ const systemDarkTheme = window.matchMedia("(prefers-color-scheme: dark)");
1831
+ const storedInterfaceTheme = localStorage.getItem(interfaceThemeKey);
1832
+ let interfaceThemePreference = storedInterfaceTheme === "light" || storedInterfaceTheme === "dark" ? storedInterfaceTheme : "system";
1833
+ const resolvedInterfaceTheme = () => resolveInterfaceTheme(interfaceThemePreference, systemDarkTheme.matches);
1538
1834
  host.dataset.foundryOverlay = "true";
1835
+ host.dataset.interfaceTheme = resolvedInterfaceTheme();
1836
+ host.dataset.interfaceThemePreference = interfaceThemePreference;
1539
1837
  const shadow = host.attachShadow({ mode: "open" });
1540
1838
  shadow.innerHTML = `<style>${PANEL_CSS}</style>
1541
1839
  <div class="outline" hidden><span class="cross"></span><span class="measure"></span></div>
@@ -1551,13 +1849,15 @@ function installFoundryInspector(options = {}) {
1551
1849
  <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
1850
  <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
1851
  <button class="icon-button open-commands" title="Commands" aria-label="Open commands"><i data-foundry-icon="command"></i></button>
1852
+ <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
1853
  </nav>
1555
1854
  <span class="workspace-divider"></span>
1556
1855
  <button class="icon-button close" title="Exit Foundry" aria-label="Exit Foundry"><i data-foundry-icon="x"></i></button>
1557
1856
  </header>
1857
+ <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
1858
  <aside class="layers-panel" aria-label="Foundry layers" hidden>
1559
1859
  <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>
1860
+ <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
1861
  </aside>
1562
1862
  <aside class="health-panel utility-panel" data-utility="health" aria-label="Design health" hidden>
1563
1863
  <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 +1872,10 @@ function installFoundryInspector(options = {}) {
1572
1872
  </div>
1573
1873
  </aside>
1574
1874
  <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>
1875
+ <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>
1876
+ </section>
1877
+ <section class="review-takeover" role="dialog" aria-modal="true" aria-label="Review and apply changes" hidden>
1878
+ <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
1879
  </section>
1578
1880
  <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
1881
  <div class="toast"></div>`;
@@ -1611,8 +1913,15 @@ function installFoundryInspector(options = {}) {
1611
1913
  commandPalette.className = "command-palette";
1612
1914
  commandPalette.hidden = true;
1613
1915
  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>`;
1916
+ commandPalette.setAttribute("role", "dialog");
1917
+ 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
1918
  shadow.append(commandPalette);
1919
+ const colorPopover = document.createElement("section");
1920
+ colorPopover.className = "color-popover";
1921
+ colorPopover.hidden = true;
1922
+ colorPopover.setAttribute("role", "dialog");
1923
+ colorPopover.setAttribute("aria-label", "Color editor");
1924
+ shadow.append(colorPopover);
1616
1925
  const libraryPanel = document.createElement("aside");
1617
1926
  libraryPanel.className = "library-panel utility-panel";
1618
1927
  libraryPanel.dataset.utility = "memory";
@@ -1673,6 +1982,10 @@ function installFoundryInspector(options = {}) {
1673
1982
  const inspectButton = shadow.querySelector(".inspect");
1674
1983
  const interactButton = shadow.querySelector(".interact");
1675
1984
  const workspaceBar = shadow.querySelector(".workspace-bar");
1985
+ const interfaceThemeTrigger = shadow.querySelector(
1986
+ ".interface-theme-trigger"
1987
+ );
1988
+ const interfaceThemeMenu = shadow.querySelector(".interface-theme-menu");
1676
1989
  const sessionStatus = shadow.querySelector(".session-status");
1677
1990
  const statusPopover = shadow.querySelector(".status-popover");
1678
1991
  const changeDock = shadow.querySelector(".change-dock");
@@ -1709,21 +2022,66 @@ function installFoundryInspector(options = {}) {
1709
2022
  const healthSummary = shadow.querySelector(".health-summary");
1710
2023
  const healthFilters = shadow.querySelector(".health-filters");
1711
2024
  const healthList = shadow.querySelector(".health-list");
1712
- const changeCount = shadow.querySelector(".change-count");
1713
2025
  const scope = shadow.querySelector("[data-scope]");
1714
2026
  const breakpoint = shadow.querySelector("[data-breakpoint]");
1715
2027
  const theme = shadow.querySelector("[data-theme]");
1716
2028
  const state = shadow.querySelector("[data-state]");
1717
- const reviewView = shadow.querySelector(".review-view");
2029
+ const reviewTakeover = shadow.querySelector(".review-takeover");
2030
+ const reviewModal = shadow.querySelector(".review-modal");
1718
2031
  const reviewBody = shadow.querySelector(".review-body");
1719
2032
  const reviewCount = shadow.querySelector(".review-count");
1720
2033
  const applyButton = shadow.querySelector(".review-actions .apply");
1721
2034
  const reviewCancel = shadow.querySelector(".review-cancel");
2035
+ function applyInterfaceTheme(preference, persist = true) {
2036
+ interfaceThemePreference = preference;
2037
+ const resolved = resolvedInterfaceTheme();
2038
+ host.dataset.interfaceTheme = resolved;
2039
+ host.dataset.interfaceThemePreference = preference;
2040
+ const label = preference[0].toUpperCase() + preference.slice(1);
2041
+ interfaceThemeTrigger.title = `Interface theme: ${label}`;
2042
+ interfaceThemeTrigger.setAttribute("aria-label", `Interface theme: ${label}`);
2043
+ interfaceThemeMenu.querySelectorAll("[data-interface-theme-choice]").forEach(
2044
+ (button) => button.setAttribute(
2045
+ "aria-checked",
2046
+ String(button.dataset.interfaceThemeChoice === preference)
2047
+ )
2048
+ );
2049
+ if (persist) localStorage.setItem(interfaceThemeKey, preference);
2050
+ }
2051
+ function closeInterfaceThemeMenu(restoreFocus = false) {
2052
+ interfaceThemeMenu.hidden = true;
2053
+ interfaceThemeTrigger.setAttribute("aria-expanded", "false");
2054
+ if (restoreFocus) interfaceThemeTrigger.focus();
2055
+ }
2056
+ function openInterfaceThemeMenu() {
2057
+ const rect = interfaceThemeTrigger.getBoundingClientRect();
2058
+ const menuWidth = 164;
2059
+ interfaceThemeMenu.style.top = `${Math.round(rect.bottom + 8)}px`;
2060
+ interfaceThemeMenu.style.left = `${Math.round(Math.min(window.innerWidth - menuWidth - 8, Math.max(8, rect.right - menuWidth)))}px`;
2061
+ interfaceThemeMenu.hidden = false;
2062
+ interfaceThemeTrigger.setAttribute("aria-expanded", "true");
2063
+ interfaceThemeMenu.querySelector('[aria-checked="true"]')?.focus();
2064
+ }
2065
+ applyInterfaceTheme(interfaceThemePreference, false);
2066
+ const handleSystemThemeChange = () => {
2067
+ if (interfaceThemePreference === "system") applyInterfaceTheme("system", false);
2068
+ };
2069
+ systemDarkTheme.addEventListener("change", handleSystemThemeChange);
2070
+ const handleInterfaceThemeDismiss = (event) => {
2071
+ if (interfaceThemeMenu.hidden) return;
2072
+ const path = event.composedPath();
2073
+ if (!path.includes(interfaceThemeMenu) && !path.includes(interfaceThemeTrigger)) {
2074
+ closeInterfaceThemeMenu();
2075
+ }
2076
+ };
2077
+ document.addEventListener("pointerdown", handleInterfaceThemeDismiss, true);
1722
2078
  let workspaceState = { ...DEFAULT_WORKSPACE_STATE };
1723
2079
  let selected = null;
1724
2080
  let selectedElements = [];
1725
2081
  let layerEntries = [];
1726
2082
  const collapsedLayers = /* @__PURE__ */ new WeakSet();
2083
+ let visibleLayerElements = /* @__PURE__ */ new Set();
2084
+ let layerGlideTop = null;
1727
2085
  const layerViewPreferenceKey = "__foundry_layer_view";
1728
2086
  let layerView = sessionStorage.getItem(layerViewPreferenceKey) === "components" ? "components" : "layers";
1729
2087
  let clickCycle = { x: -1, y: -1, at: 0, index: -1, signature: "" };
@@ -1731,6 +2089,7 @@ function installFoundryInspector(options = {}) {
1731
2089
  let selectedControls = [];
1732
2090
  let resizeObserver;
1733
2091
  let activeReviewPayload = null;
2092
+ let activeAgentPresence = { connected: false, presence: null };
1734
2093
  const reviewDraftKey = `__foundry_review_draft:${sessionId || "local"}`;
1735
2094
  let reviewDraft = (() => {
1736
2095
  try {
@@ -1740,18 +2099,34 @@ function installFoundryInspector(options = {}) {
1740
2099
  }
1741
2100
  })();
1742
2101
  let reviewShowRejected = false;
2102
+ const collapsedReviewGroups = /* @__PURE__ */ new Set();
1743
2103
  let reviewPoll;
1744
2104
  let lastReviewTrigger = null;
2105
+ let reviewScrollTop = 0;
2106
+ let reviewSuspended = false;
2107
+ let suspendedPreviewRestore;
2108
+ const dockReviewButton = shadow.querySelector(".dock-review");
2109
+ const dockWidthKey = "__foundry_dock_width";
2110
+ const legacyDockWidthKey = "__foundry_panel_width";
2111
+ const storedDockWidth = Number(
2112
+ localStorage.getItem(dockWidthKey) ?? localStorage.getItem(legacyDockWidthKey)
2113
+ );
2114
+ let dockWidth = Number.isFinite(storedDockWidth) ? Math.max(340, Math.min(520, storedDockWidth)) : 384;
2115
+ host.style.setProperty("--fdc-dock-width", `${Math.round(dockWidth)}px`);
1745
2116
  let designGraph = null;
1746
2117
  const previewHistory = [];
1747
2118
  let historyCursor = 0;
1748
2119
  let paddingLinked = true;
2120
+ let radiusLinked = true;
1749
2121
  let tokenOnly = false;
1750
2122
  let activeControlProperty = "";
2123
+ const recentColors = /* @__PURE__ */ new Set();
2124
+ let activeColor;
1751
2125
  let lastRecordedSummary = "";
1752
2126
  let statusResetTimer;
1753
2127
  let hydratedOnce = false;
1754
2128
  const collapsedSections = /* @__PURE__ */ new Set();
2129
+ let sectionPreferenceTouched = sessionStorage.getItem("__foundry_collapsed_sections") != null;
1755
2130
  try {
1756
2131
  for (const key of JSON.parse(sessionStorage.getItem("__foundry_collapsed_sections") ?? "[]")) {
1757
2132
  if (typeof key === "string") collapsedSections.add(key);
@@ -1841,10 +2216,7 @@ function installFoundryInspector(options = {}) {
1841
2216
  "--fdc-canvas-right",
1842
2217
  `${Math.max(12, window.innerWidth - bounds.right)}px`
1843
2218
  );
1844
- host.style.setProperty(
1845
- "--fdc-tray-lift",
1846
- workspaceState.tray !== "hidden" ? `${Math.max(0, window.innerHeight - bounds.bottom)}px` : "0px"
1847
- );
2219
+ host.style.setProperty("--fdc-tray-lift", "0px");
1848
2220
  if (workspaceState.utility) applyUtilityRect(workspaceState.utility);
1849
2221
  }
1850
2222
  function persistUtilityRect(utility, rect) {
@@ -1958,15 +2330,17 @@ function installFoundryInspector(options = {}) {
1958
2330
  }
1959
2331
  }
1960
2332
  function updateChangeCount(count, latest) {
1961
- changeCount.textContent = String(count);
1962
- changeCount.hidden = count === 0;
1963
2333
  changeDock.hidden = count === 0;
1964
2334
  workspaceState = updateWorkspace(workspaceState, {
1965
- type: "set-tray",
1966
- tray: count === 0 ? "hidden" : workspaceState.tray === "expanded" ? "expanded" : "collapsed"
2335
+ type: "set-change-summary",
2336
+ visible: count > 0
1967
2337
  });
1968
- if (count === 0) reviewView.hidden = true;
1969
- changeDock.classList.toggle("expanded", workspaceState.tray === "expanded");
2338
+ panel.classList.toggle("change-summary-visible", count > 0);
2339
+ if (count === 0) {
2340
+ reviewTakeover.hidden = true;
2341
+ reviewSuspended = false;
2342
+ dockReviewButton.textContent = "Review";
2343
+ }
1970
2344
  trayCompare.disabled = count === 0 || historyCursor === 0;
1971
2345
  changeDock.querySelector("[data-dock-count]").textContent = `${count} ${count === 1 ? "change" : "changes"} recorded`;
1972
2346
  if (latest) {
@@ -2511,15 +2885,38 @@ function installFoundryInspector(options = {}) {
2511
2885
  );
2512
2886
  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
2887
  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) => {
2888
+ const hasRenderedSelection = rendered.some((entry) => selectedElements.includes(entry.element));
2889
+ const previouslyVisible = visibleLayerElements;
2890
+ visibleLayerElements = new Set(visible.map((entry) => entry.element));
2891
+ layerTree.innerHTML = visible.length ? `${range.before ? `<div class="layer-spacer" style="height:${range.before}px"></div>` : ""}${rendered.map((entry, renderedPosition) => {
2515
2892
  const index = layerEntries.indexOf(entry);
2516
2893
  const meta = entry.instrumented ? "Mapped" : entry.kind;
2517
2894
  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>`;
2895
+ const position = range.start + renderedPosition;
2896
+ const depth = Math.min(entry.depth, 8);
2897
+ const selectedLayer = selectedElements.includes(entry.element);
2898
+ const entering = previouslyVisible.has(entry.element) ? "" : " entering";
2899
+ const branch = depth ? `<span class="layer-branch" aria-hidden="true"></span>` : "";
2900
+ 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
2901
  }).join(
2520
2902
  ""
2521
2903
  )}${range.after ? `<div class="layer-spacer" style="height:${range.after}px"></div>` : ""}` : '<div class="layers-empty">No visible layers match this search.</div>';
2522
2904
  layerTree.scrollTop = previousScrollTop;
2905
+ const selectedRow = layerTree.querySelector(".layer-row.selected");
2906
+ if (selectedRow) {
2907
+ const targetTop = selectedRow.offsetTop;
2908
+ const glide = document.createElement("span");
2909
+ glide.className = "layer-selection-glide";
2910
+ glide.setAttribute("aria-hidden", "true");
2911
+ glide.style.setProperty("--layer-glide-y", `${layerGlideTop ?? targetTop}px`);
2912
+ layerTree.prepend(glide);
2913
+ requestAnimationFrame(() => {
2914
+ glide.style.setProperty("--layer-glide-y", `${targetTop}px`);
2915
+ });
2916
+ layerGlideTop = targetTop;
2917
+ } else {
2918
+ layerGlideTop = null;
2919
+ }
2523
2920
  renderIcons(layerTree);
2524
2921
  layerTree.querySelectorAll("[data-layer-row]").forEach((row) => {
2525
2922
  const entry = layerEntries[Number(row.dataset.layerRow)];
@@ -2601,6 +2998,73 @@ function installFoundryInspector(options = {}) {
2601
2998
  select(entry.element, event.shiftKey);
2602
2999
  entry.element.scrollIntoView({ block: "nearest", inline: "nearest" });
2603
3000
  });
3001
+ button.addEventListener("keydown", (event) => {
3002
+ const buttons = [...layerTree.querySelectorAll("[data-layer-index]")];
3003
+ const currentIndex = buttons.indexOf(button);
3004
+ const focusAt = (index) => {
3005
+ const target = buttons[index];
3006
+ if (!target) return;
3007
+ buttons.forEach((item) => item.tabIndex = item === target ? 0 : -1);
3008
+ target.focus();
3009
+ target.closest(".layer-row")?.scrollIntoView({ block: "nearest" });
3010
+ };
3011
+ if (event.key === "ArrowDown") {
3012
+ event.preventDefault();
3013
+ focusAt(Math.min(buttons.length - 1, currentIndex + 1));
3014
+ return;
3015
+ }
3016
+ if (event.key === "ArrowUp") {
3017
+ event.preventDefault();
3018
+ focusAt(Math.max(0, currentIndex - 1));
3019
+ return;
3020
+ }
3021
+ if (event.key === "Home") {
3022
+ event.preventDefault();
3023
+ focusAt(0);
3024
+ return;
3025
+ }
3026
+ if (event.key === "End") {
3027
+ event.preventDefault();
3028
+ focusAt(buttons.length - 1);
3029
+ return;
3030
+ }
3031
+ if (event.key === "ArrowRight" && entry.hasChildren) {
3032
+ event.preventDefault();
3033
+ if (collapsedLayers.has(entry.element)) {
3034
+ collapsedLayers.delete(entry.element);
3035
+ renderLayers(false);
3036
+ requestAnimationFrame(
3037
+ () => layerTree.querySelector(
3038
+ `[data-layer-index="${layerEntries.indexOf(entry)}"]`
3039
+ )?.focus()
3040
+ );
3041
+ } else {
3042
+ const next = buttons[currentIndex + 1];
3043
+ const nextEntry = next ? layerEntries[Number(next.dataset.layerIndex)] : void 0;
3044
+ if (nextEntry && nextEntry.depth > entry.depth) focusAt(currentIndex + 1);
3045
+ }
3046
+ return;
3047
+ }
3048
+ if (event.key !== "ArrowLeft") return;
3049
+ event.preventDefault();
3050
+ if (entry.hasChildren && !collapsedLayers.has(entry.element)) {
3051
+ collapsedLayers.add(entry.element);
3052
+ renderLayers(false);
3053
+ requestAnimationFrame(
3054
+ () => layerTree.querySelector(
3055
+ `[data-layer-index="${layerEntries.indexOf(entry)}"]`
3056
+ )?.focus()
3057
+ );
3058
+ return;
3059
+ }
3060
+ for (let index = currentIndex - 1; index >= 0; index -= 1) {
3061
+ const candidate2 = layerEntries[Number(buttons[index]?.dataset.layerIndex)];
3062
+ if (candidate2 && candidate2.depth < entry.depth) {
3063
+ focusAt(index);
3064
+ break;
3065
+ }
3066
+ }
3067
+ });
2604
3068
  });
2605
3069
  }
2606
3070
  const layersPreferenceKey = "__foundry_layers_visibility";
@@ -2939,8 +3403,29 @@ function installFoundryInspector(options = {}) {
2939
3403
  const count = group.querySelector(".included-count");
2940
3404
  if (count) count.textContent = `${included} included`;
2941
3405
  });
2942
- applyButton.textContent = selectedCount ? `Apply ${selectedCount} with agent` : "Apply with agent";
2943
- applyButton.disabled = selectedCount === 0;
3406
+ applyButton.textContent = !activeAgentPresence.connected ? "Connect agent to apply" : selectedCount ? `Apply ${selectedCount} with agent` : "Apply with agent";
3407
+ applyButton.disabled = selectedCount === 0 || !activeAgentPresence.connected;
3408
+ }
3409
+ function agentConnectionMarkup() {
3410
+ const agentName = activeAgentPresence.presence?.agent?.name;
3411
+ return `<div class="review-agent ${activeAgentPresence.connected ? "connected" : "disconnected"}" aria-live="polite"><i></i><div><strong>${activeAgentPresence.connected ? `${escapeHtml(agentName ?? "Coding agent")} is ready` : "Connect your coding agent"}</strong><span>${activeAgentPresence.connected ? "Apply requests will be claimed automatically while this agent keeps listening." : "In the same project, ask your agent to start Foundry and keep listening for Apply requests."}</span></div>${activeAgentPresence.connected ? "" : "<button data-copy-agent-listener>Copy instruction</button>"}</div>`;
3412
+ }
3413
+ function updateAgentConnection() {
3414
+ const current = reviewBody.querySelector(".review-agent");
3415
+ if (!current) {
3416
+ updateReviewSelection();
3417
+ return;
3418
+ }
3419
+ const replacement = document.createElement("div");
3420
+ replacement.innerHTML = agentConnectionMarkup();
3421
+ current.replaceWith(replacement.firstElementChild);
3422
+ reviewBody.querySelector("[data-copy-agent-listener]")?.addEventListener("click", () => {
3423
+ void navigator.clipboard.writeText(
3424
+ "Start Foundry for this project and keep listening for Apply with agent requests."
3425
+ );
3426
+ showToast("Agent instruction copied");
3427
+ });
3428
+ updateReviewSelection();
2944
3429
  }
2945
3430
  function renderReviewList(changes) {
2946
3431
  const groups = /* @__PURE__ */ new Map();
@@ -2954,11 +3439,12 @@ function installFoundryInspector(options = {}) {
2954
3439
  const unresolvedCount = changes.filter(
2955
3440
  (change) => change.confidence === "unresolved" || change.mappingCandidates?.length > 1 && !change.selectedMappingId
2956
3441
  ).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>${[
3442
+ 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>${agentConnectionMarkup()}${[
2958
3443
  ...groups.values()
2959
3444
  ].map((group) => {
2960
3445
  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) => {
3446
+ const collapsed = collapsedReviewGroups.has(target.id);
3447
+ 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
3448
  const unresolved = change.confidence === "unresolved" || change.mappingCandidates?.length > 1 && !change.selectedMappingId;
2963
3449
  const selectable = !unresolved && change.status !== "rejected";
2964
3450
  const checked = selectable && reviewSelection(reviewDraft, change.id, true);
@@ -2987,6 +3473,12 @@ function installFoundryInspector(options = {}) {
2987
3473
  reviewCancel.dataset.action = "back";
2988
3474
  reviewCancel.textContent = "Back";
2989
3475
  renderIcons(reviewBody);
3476
+ reviewBody.querySelector("[data-copy-agent-listener]")?.addEventListener("click", () => {
3477
+ void navigator.clipboard.writeText(
3478
+ "Start Foundry for this project and keep listening for Apply with agent requests."
3479
+ );
3480
+ showToast("Agent instruction copied");
3481
+ });
2990
3482
  reviewBody.querySelectorAll("[data-review-change]").forEach(
2991
3483
  (field) => field.addEventListener("change", () => {
2992
3484
  reviewDraft.selections[field.dataset.reviewChange] = field.checked;
@@ -3005,6 +3497,9 @@ function installFoundryInspector(options = {}) {
3005
3497
  const group = button.closest(".review-group");
3006
3498
  if (!group) return;
3007
3499
  group.classList.toggle("collapsed");
3500
+ const targetId = group.dataset.reviewTarget;
3501
+ if (group.classList.contains("collapsed")) collapsedReviewGroups.add(targetId);
3502
+ else collapsedReviewGroups.delete(targetId);
3008
3503
  button.setAttribute("aria-expanded", String(!group.classList.contains("collapsed")));
3009
3504
  })
3010
3505
  );
@@ -3020,6 +3515,10 @@ function installFoundryInspector(options = {}) {
3020
3515
  reviewShowRejected = !reviewShowRejected;
3021
3516
  if (activeReviewPayload) renderReviewPayload(activeReviewPayload);
3022
3517
  });
3518
+ reviewBody.querySelector("[data-review-compare]")?.addEventListener("click", () => {
3519
+ suspendReview();
3520
+ showComparison("after");
3521
+ });
3023
3522
  reviewBody.querySelectorAll("[data-review-status]").forEach(
3024
3523
  (button) => button.addEventListener("click", async () => {
3025
3524
  button.disabled = true;
@@ -3043,10 +3542,15 @@ function installFoundryInspector(options = {}) {
3043
3542
  if (!element) return;
3044
3543
  const before = () => rawElementValue(element, change.property, change.before, change.unit);
3045
3544
  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);
3545
+ button.title = "Show the before value on the canvas";
3546
+ button.addEventListener("click", () => {
3547
+ before();
3548
+ suspendedPreviewRestore = after;
3549
+ select(element);
3550
+ suspendReview();
3551
+ element.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
3552
+ showToast("Before value shown \xB7 Return to continue reviewing");
3553
+ });
3050
3554
  });
3051
3555
  reviewBody.querySelectorAll("[data-review-locate]").forEach((button) => {
3052
3556
  const change = changes.find((item) => item.id === button.dataset.reviewLocate);
@@ -3061,9 +3565,9 @@ function installFoundryInspector(options = {}) {
3061
3565
  button.addEventListener("mouseleave", () => previewLayer(null));
3062
3566
  button.addEventListener("click", () => {
3063
3567
  select(element);
3064
- closeReview();
3568
+ suspendReview();
3065
3569
  element.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
3066
- showToast("Located on the live canvas");
3570
+ showToast("Located on the live canvas \xB7 Return to continue reviewing");
3067
3571
  });
3068
3572
  });
3069
3573
  reviewBody.querySelectorAll("[data-mapping-choice]").forEach(
@@ -3085,7 +3589,7 @@ function installFoundryInspector(options = {}) {
3085
3589
  updateReviewSelection();
3086
3590
  }
3087
3591
  const runStateLabels = {
3088
- queued: "Waiting for agent",
3592
+ queued: "Queued for agent",
3089
3593
  claimed: "Agent connected",
3090
3594
  applying: "Applying source changes",
3091
3595
  rebuilding: "Rebuilding and checking",
@@ -3134,11 +3638,11 @@ function installFoundryInspector(options = {}) {
3134
3638
  const attention = ["needs_attention", "failed"].includes(run.state);
3135
3639
  const passed = run.state === "passed";
3136
3640
  const active = ["queued", "claimed", "applying", "rebuilding", "verifying"].includes(run.state);
3137
- const latestMessage = run.messages.at(-1)?.message ?? run.error ?? "Apply run created.";
3641
+ 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
3642
  captureVerifiedRun(run);
3139
3643
  reviewCount.textContent = `Attempt ${run.attempts}`;
3140
3644
  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>`
3645
+ (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
3646
  ).join(
3143
3647
  ""
3144
3648
  )}</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 +3672,7 @@ function installFoundryInspector(options = {}) {
3168
3672
  }
3169
3673
  }
3170
3674
  function renderReviewPayload(payload) {
3675
+ const preservedScrollTop = reviewBody.scrollTop || reviewScrollTop;
3171
3676
  activeReviewPayload = payload;
3172
3677
  const activeChanges = payload.changeSet.changes.filter(
3173
3678
  (change) => change.status !== "rejected" && String(change.before) !== String(change.after)
@@ -3183,16 +3688,27 @@ function installFoundryInspector(options = {}) {
3183
3688
  "needs_attention",
3184
3689
  "failed"
3185
3690
  ].includes(latestRun.state);
3691
+ if (activeOrAttention) {
3692
+ const latestMessage = latestRun.messages?.at(-1)?.message;
3693
+ changeDock.querySelector("[data-dock-last]").textContent = latestMessage ?? runStateLabels[latestRun.state] ?? latestRun.state;
3694
+ }
3186
3695
  const pending = payload.changeSet.changes.filter(
3187
3696
  (change) => String(change.before) !== String(change.after) && (["draft", "approved", "unresolved"].includes(change.status) || reviewShowRejected && change.status === "rejected")
3188
3697
  );
3189
3698
  if (activeOrAttention || !pending.length && latestRun) renderApplyRun(latestRun);
3190
3699
  else renderReviewList(pending);
3700
+ requestAnimationFrame(() => {
3701
+ if (workspaceState.reviewOpen) reviewBody.scrollTop = preservedScrollTop;
3702
+ });
3191
3703
  }
3192
3704
  async function refreshReview() {
3193
- if (workspaceState.tray !== "expanded" || !sessionId || !token) return;
3705
+ if (!workspaceState.reviewOpen || !sessionId || !token) return;
3194
3706
  try {
3195
- const payload = await sessionRequest();
3707
+ const [payload, presence] = await Promise.all([
3708
+ sessionRequest(),
3709
+ sessionRequest("/agent-presence")
3710
+ ]);
3711
+ activeAgentPresence = presence;
3196
3712
  const latestRun = payload.applyRuns?.at(-1);
3197
3713
  const runNeedsRefresh = latestRun && [
3198
3714
  "queued",
@@ -3205,6 +3721,7 @@ function installFoundryInspector(options = {}) {
3205
3721
  ].includes(latestRun.state);
3206
3722
  if (applyButton.dataset.action === "apply" && !runNeedsRefresh) {
3207
3723
  activeReviewPayload = payload;
3724
+ updateAgentConnection();
3208
3725
  return;
3209
3726
  }
3210
3727
  renderReviewPayload(payload);
@@ -3217,29 +3734,43 @@ function installFoundryInspector(options = {}) {
3217
3734
  showToast("Session connection is missing");
3218
3735
  return;
3219
3736
  }
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;
3737
+ if (!reviewSuspended && shadow.activeElement instanceof HTMLElement)
3738
+ lastReviewTrigger = shadow.activeElement;
3739
+ suspendedPreviewRestore?.();
3740
+ suspendedPreviewRestore = void 0;
3741
+ reviewSuspended = false;
3742
+ dockReviewButton.textContent = "Review";
3743
+ workspaceState = updateWorkspace(workspaceState, { type: "set-review", open: true });
3744
+ reviewTakeover.hidden = false;
3224
3745
  outline.hidden = true;
3225
- positionWorkspaceSurfaces();
3226
- renderReviewPayload(await sessionRequest());
3746
+ const [payload, presence] = await Promise.all([
3747
+ sessionRequest(),
3748
+ sessionRequest("/agent-presence")
3749
+ ]);
3750
+ activeAgentPresence = presence;
3751
+ renderReviewPayload(payload);
3752
+ requestAnimationFrame(() => {
3753
+ reviewBody.scrollTop = reviewScrollTop;
3754
+ shadow.querySelector(".review-back")?.focus();
3755
+ });
3227
3756
  clearInterval(reviewPoll);
3228
3757
  clearInterval(healthPoll);
3229
3758
  reviewPoll = setInterval(() => void refreshReview(), 1e3);
3230
3759
  }
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;
3760
+ function closeReview(restoreFocus = true) {
3761
+ reviewScrollTop = reviewBody.scrollTop;
3762
+ workspaceState = updateWorkspace(workspaceState, { type: "set-review", open: false });
3763
+ reviewTakeover.hidden = true;
3238
3764
  clearInterval(reviewPoll);
3239
3765
  reviewPoll = void 0;
3240
3766
  updateOutline();
3241
- positionWorkspaceSurfaces();
3242
- lastReviewTrigger?.focus();
3767
+ if (restoreFocus) lastReviewTrigger?.focus();
3768
+ }
3769
+ function suspendReview() {
3770
+ reviewSuspended = true;
3771
+ dockReviewButton.textContent = "Return";
3772
+ closeReview(false);
3773
+ dockReviewButton.focus();
3243
3774
  }
3244
3775
  async function submitReviewedRun() {
3245
3776
  if (!activeReviewPayload) return;
@@ -3258,6 +3789,12 @@ function installFoundryInspector(options = {}) {
3258
3789
  );
3259
3790
  applyButton.disabled = true;
3260
3791
  try {
3792
+ activeAgentPresence = await sessionRequest("/agent-presence");
3793
+ if (!activeAgentPresence.connected) {
3794
+ updateAgentConnection();
3795
+ showToast("No coding agent is listening yet");
3796
+ return;
3797
+ }
3261
3798
  const payload = await sessionRequest("/apply-runs", {
3262
3799
  method: "POST",
3263
3800
  body: JSON.stringify({
@@ -3716,13 +4253,8 @@ function installFoundryInspector(options = {}) {
3716
4253
  }
3717
4254
  function renderContextPanel(category) {
3718
4255
  if (!selected) return "";
3719
- const supportsTokens = ["layout", "typography", "color", "effects"].includes(category);
3720
- const tokens = supportsTokens ? tokensForCategory(category).slice(0, 24) : [];
3721
4256
  const component = selectedComponent();
3722
4257
  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
4258
  const contrast = category === "color" ? contrastRatio(getComputedStyle(selected).color, opaqueBackground(selected)) : null;
3727
4259
  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
4260
  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 +4262,7 @@ function installFoundryInspector(options = {}) {
3730
4262
  Object.entries(variant.props).map(([key, value]) => `${key}=${value}`).join(" \xB7 ")
3731
4263
  )}</code></button>`
3732
4264
  ).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}`;
4265
+ return `${health}${variantPanel}`;
3736
4266
  }
3737
4267
  async function applyControlValue(control, value, operationLabel) {
3738
4268
  if (!selected) return;
@@ -3844,13 +4374,18 @@ function installFoundryInspector(options = {}) {
3844
4374
  });
3845
4375
  controlsRoot.querySelectorAll("[data-color-action]").forEach((button) => {
3846
4376
  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%)";
4377
+ const gradient = controls.find((item) => item.property === "backgroundImage");
4378
+ if (!gradient) return;
4379
+ if (button.dataset.colorAction === "clear") {
4380
+ const fill = controls.find((item) => item.property === "backgroundColor");
4381
+ if (fill) void applyControlValue(fill, "transparent", "Clear fill color");
4382
+ void applyControlValue(gradient, "none", "Clear fill gradient");
4383
+ return;
4384
+ }
3850
4385
  void applyControlValue(
3851
- control,
3852
- value,
3853
- button.dataset.colorAction === "clear" ? "Clear fill" : "Add linear gradient"
4386
+ gradient,
4387
+ "linear-gradient(135deg, currentColor 0%, transparent 100%)",
4388
+ "Add linear gradient"
3854
4389
  );
3855
4390
  });
3856
4391
  });
@@ -3878,6 +4413,13 @@ function installFoundryInspector(options = {}) {
3878
4413
  const siblings = [...parent.children].filter((item) => item !== element);
3879
4414
  const index = Math.max(0, Math.min(Number(value), siblings.length));
3880
4415
  parent.insertBefore(element, siblings[index] ?? null);
4416
+ } else if (property === "rotate") element.style.rotate = `${value}${unit ?? "deg"}`;
4417
+ else if (property === "scaleX" || property === "scaleY") {
4418
+ const raw = getComputedStyle(element).scale;
4419
+ const parts = !raw || raw === "none" ? [1, 1] : raw.split(/\s+/).map(numberFrom);
4420
+ const x = property === "scaleX" ? Number(value) : parts[0] ?? 1;
4421
+ const y = property === "scaleY" ? Number(value) : parts[1] ?? parts[0] ?? 1;
4422
+ element.style.scale = `${x} ${y}`;
3881
4423
  } else if (property === "textContent") element.textContent = String(value);
3882
4424
  else if (["aria-label", "role", "tabindex", "alt", "src"].includes(property))
3883
4425
  element.setAttribute(property, String(value));
@@ -4049,8 +4591,14 @@ function installFoundryInspector(options = {}) {
4049
4591
  { id: "redo", label: "Redo preview", shortcut: "\u21E7\u2318Z", icon: "redo-2" },
4050
4592
  { id: "review", label: "Review changes", shortcut: "", icon: "file-text" }
4051
4593
  ];
4052
- function runCommand(id) {
4594
+ let commandReturnFocus = null;
4595
+ function closeCommands(restoreFocus = true) {
4053
4596
  commandPalette.hidden = true;
4597
+ if (restoreFocus && commandReturnFocus?.isConnected) commandReturnFocus.focus();
4598
+ commandReturnFocus = null;
4599
+ }
4600
+ function runCommand(id) {
4601
+ closeCommands(false);
4054
4602
  if (id === "health") openHealth();
4055
4603
  if (id === "layers") toggleLayers(true);
4056
4604
  if (id === "compare") showComparison("after");
@@ -4082,6 +4630,7 @@ function installFoundryInspector(options = {}) {
4082
4630
  );
4083
4631
  }
4084
4632
  function openCommands() {
4633
+ commandReturnFocus = shadow.activeElement;
4085
4634
  commandPalette.hidden = false;
4086
4635
  const input = commandPalette.querySelector("input");
4087
4636
  input.value = "";
@@ -4388,6 +4937,180 @@ function installFoundryInspector(options = {}) {
4388
4937
  );
4389
4938
  });
4390
4939
  }
4940
+ function activeColorValue() {
4941
+ if (!activeColor) return "#000000";
4942
+ const [red, green, blue] = hsvToRgb(activeColor.hue, activeColor.saturation, activeColor.value);
4943
+ return activeColor.alpha >= 0.999 ? rgbHex(red, green, blue) : `rgba(${red}, ${green}, ${blue}, ${Math.round(activeColor.alpha * 100) / 100})`;
4944
+ }
4945
+ function refreshColorPopover() {
4946
+ if (!activeColor) return;
4947
+ const plane = colorPopover.querySelector(".color-plane");
4948
+ const handle = colorPopover.querySelector(".color-plane-handle");
4949
+ const hex = colorPopover.querySelector("[data-color-hex]");
4950
+ const hue = colorPopover.querySelector("[data-color-hue]");
4951
+ const alpha = colorPopover.querySelector("[data-color-alpha]");
4952
+ if (plane) plane.style.setProperty("--picker-hue", String(activeColor.hue));
4953
+ if (handle) {
4954
+ handle.style.left = `${activeColor.saturation * 100}%`;
4955
+ handle.style.top = `${(1 - activeColor.value) * 100}%`;
4956
+ }
4957
+ if (hex) hex.value = colorForInput(activeColorValue()).toUpperCase();
4958
+ if (hue) hue.value = String(Math.round(activeColor.hue));
4959
+ if (alpha) alpha.value = String(Math.round(activeColor.alpha * 100));
4960
+ }
4961
+ function previewActiveColor() {
4962
+ if (!activeColor) return;
4963
+ const value = activeColorValue();
4964
+ activeColor.control.apply(value);
4965
+ const trigger = controlsRoot.querySelector(
4966
+ `[data-color-control="${activeColor.index}"]`
4967
+ );
4968
+ const swatch = trigger?.querySelector(".color-swatch");
4969
+ const label = trigger?.querySelector(".color-value");
4970
+ if (swatch) {
4971
+ swatch.classList.toggle("transparent", activeColor.alpha === 0);
4972
+ swatch.style.setProperty("--swatch-color", colorForInput(value));
4973
+ }
4974
+ if (label) label.textContent = activeColor.alpha === 0 ? "Transparent" : value.toUpperCase();
4975
+ refreshColorPopover();
4976
+ updateOutline();
4977
+ }
4978
+ function commitActiveColor(before) {
4979
+ if (!activeColor) return;
4980
+ const after = activeColor.control.read();
4981
+ if (String(before) === String(after)) return;
4982
+ recentColors.delete(String(after));
4983
+ recentColors.add(String(after));
4984
+ while (recentColors.size > 8) recentColors.delete(recentColors.values().next().value);
4985
+ pushHistory({
4986
+ element: activeColor.element,
4987
+ property: activeColor.control.property,
4988
+ before,
4989
+ after,
4990
+ category: activeColor.control.category,
4991
+ label: activeColor.control.label
4992
+ });
4993
+ void record(activeColor.control, before, after, activeColor.element, "Choose color");
4994
+ }
4995
+ function setActiveColor(value) {
4996
+ if (!activeColor) return;
4997
+ const [red, green, blue] = hexChannels(value);
4998
+ const [hue, saturation, brightness] = rgbToHsv(red, green, blue);
4999
+ activeColor.hue = hue;
5000
+ activeColor.saturation = saturation;
5001
+ activeColor.value = brightness;
5002
+ activeColor.alpha = colorAlpha(value);
5003
+ previewActiveColor();
5004
+ }
5005
+ function openColorEditor(trigger, index) {
5006
+ const control = selectedControls[index];
5007
+ if (!control || control.kind !== "color" || !selected) return;
5008
+ const [red, green, blue] = hexChannels(String(control.read()));
5009
+ const [hue, saturation, value] = rgbToHsv(red, green, blue);
5010
+ activeColor = {
5011
+ index,
5012
+ control,
5013
+ element: selected,
5014
+ hue,
5015
+ saturation,
5016
+ value,
5017
+ alpha: colorAlpha(String(control.read()))
5018
+ };
5019
+ const tokens = tokensForCategory("color").slice(0, 18);
5020
+ 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">${[
5021
+ ...recentColors
5022
+ ].reverse().map(
5023
+ (color) => `<button data-color-value="${escapeHtml(color)}" style="--picker-swatch:${escapeHtml(color)}" aria-label="Use recent color ${escapeHtml(color)}"></button>`
5024
+ ).join("")}</div></div>` : ""}`;
5025
+ renderIcons(colorPopover);
5026
+ colorPopover.hidden = false;
5027
+ const triggerRect = trigger.getBoundingClientRect();
5028
+ const popoverRect = colorPopover.getBoundingClientRect();
5029
+ const left = Math.max(8, Math.min(window.innerWidth - popoverRect.width - 8, triggerRect.left));
5030
+ const preferredTop = triggerRect.bottom + 6;
5031
+ const top = preferredTop + popoverRect.height <= window.innerHeight - 8 ? preferredTop : Math.max(8, triggerRect.top - popoverRect.height - 6);
5032
+ colorPopover.style.left = `${Math.round(left)}px`;
5033
+ colorPopover.style.top = `${Math.round(top)}px`;
5034
+ refreshColorPopover();
5035
+ colorPopover.querySelector("[data-close-color]")?.addEventListener("click", () => {
5036
+ colorPopover.hidden = true;
5037
+ activeColor = void 0;
5038
+ trigger.focus();
5039
+ });
5040
+ const plane = colorPopover.querySelector(".color-plane");
5041
+ plane.addEventListener("pointerdown", (event) => {
5042
+ if (!activeColor) return;
5043
+ const before = activeColor.control.read();
5044
+ plane.setPointerCapture(event.pointerId);
5045
+ const update = (pointer) => {
5046
+ if (!activeColor) return;
5047
+ const rect = plane.getBoundingClientRect();
5048
+ activeColor.saturation = Math.max(
5049
+ 0,
5050
+ Math.min(1, (pointer.clientX - rect.left) / rect.width)
5051
+ );
5052
+ activeColor.value = 1 - Math.max(0, Math.min(1, (pointer.clientY - rect.top) / rect.height));
5053
+ previewActiveColor();
5054
+ };
5055
+ const finish = (pointer) => {
5056
+ update(pointer);
5057
+ commitActiveColor(before);
5058
+ plane.removeEventListener("pointermove", update);
5059
+ plane.removeEventListener("pointerup", finish);
5060
+ plane.removeEventListener("pointercancel", finish);
5061
+ };
5062
+ update(event);
5063
+ plane.addEventListener("pointermove", update);
5064
+ plane.addEventListener("pointerup", finish);
5065
+ plane.addEventListener("pointercancel", finish);
5066
+ });
5067
+ const bindSlider = (selector, apply) => {
5068
+ const slider = colorPopover.querySelector(selector);
5069
+ let before = control.read();
5070
+ slider.addEventListener("pointerdown", () => {
5071
+ before = control.read();
5072
+ });
5073
+ slider.addEventListener("input", () => {
5074
+ apply(Number(slider.value));
5075
+ previewActiveColor();
5076
+ });
5077
+ slider.addEventListener("change", () => commitActiveColor(before));
5078
+ };
5079
+ bindSlider("[data-color-hue]", (next) => {
5080
+ if (activeColor) activeColor.hue = next;
5081
+ });
5082
+ bindSlider("[data-color-alpha]", (next) => {
5083
+ if (activeColor) activeColor.alpha = next / 100;
5084
+ });
5085
+ const hexField = colorPopover.querySelector("[data-color-hex]");
5086
+ let hexBefore = control.read();
5087
+ hexField.addEventListener("focus", () => {
5088
+ hexBefore = control.read();
5089
+ });
5090
+ hexField.addEventListener("change", () => {
5091
+ setActiveColor(hexField.value);
5092
+ commitActiveColor(hexBefore);
5093
+ });
5094
+ colorPopover.querySelectorAll("[data-color-value]").forEach((button) => {
5095
+ button.addEventListener("click", () => {
5096
+ const before = control.read();
5097
+ setActiveColor(button.dataset.colorValue ?? "#000000");
5098
+ commitActiveColor(before);
5099
+ });
5100
+ });
5101
+ colorPopover.querySelector("[data-eyedropper]")?.addEventListener("click", async () => {
5102
+ const EyeDropper = window.EyeDropper;
5103
+ if (!EyeDropper) {
5104
+ showToast("Eyedropper is not available in this browser");
5105
+ return;
5106
+ }
5107
+ const before = control.read();
5108
+ const result = await new EyeDropper().open().catch(() => void 0);
5109
+ if (!result) return;
5110
+ setActiveColor(result.sRGBHex);
5111
+ commitActiveColor(before);
5112
+ });
5113
+ }
4391
5114
  function renderControls() {
4392
5115
  renderToolTabs();
4393
5116
  if (!selected) {
@@ -4405,20 +5128,55 @@ function installFoundryInspector(options = {}) {
4405
5128
  {
4406
5129
  key: "layout",
4407
5130
  category: "layout",
4408
- label: "Layout and spacing",
5131
+ label: "Layout",
4409
5132
  icon: CATEGORY_ICONS.layout,
4410
5133
  sectionLabels: ["Flow", "Padding", "Margin"],
4411
5134
  showContext: true
4412
5135
  },
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
- )
5136
+ {
5137
+ key: "typography",
5138
+ category: "typography",
5139
+ label: "Typography",
5140
+ icon: CATEGORY_ICONS.typography,
5141
+ showContext: true
5142
+ },
5143
+ {
5144
+ key: "appearance",
5145
+ category: "color",
5146
+ label: "Appearance",
5147
+ icon: "eye",
5148
+ sectionLabels: ["Appearance"]
5149
+ },
5150
+ {
5151
+ key: "fill",
5152
+ category: "color",
5153
+ label: "Fill",
5154
+ icon: CATEGORY_ICONS.color,
5155
+ sectionLabels: ["Fill"],
5156
+ showContext: true
5157
+ },
5158
+ {
5159
+ key: "stroke",
5160
+ category: "effects",
5161
+ label: "Stroke",
5162
+ icon: "box",
5163
+ sectionLabels: ["Stroke"]
5164
+ },
5165
+ {
5166
+ key: "effects",
5167
+ category: "effects",
5168
+ label: "Effects",
5169
+ icon: CATEGORY_ICONS.effects,
5170
+ sectionLabels: ["Corners", "Effects"],
5171
+ showContext: true
5172
+ },
5173
+ ...["content", "accessibility"].map((category) => ({
5174
+ key: category,
5175
+ category,
5176
+ label: CATEGORY_LABELS[category],
5177
+ icon: CATEGORY_ICONS[category],
5178
+ showContext: true
5179
+ }))
4422
5180
  ];
4423
5181
  const indexedControls = selectedControls.map((control, index) => ({ control, index })).filter(
4424
5182
  ({ control }) => tokenOnly ? matchingTokens(
@@ -4445,7 +5203,8 @@ function installFoundryInspector(options = {}) {
4445
5203
  entries.forEach(({ control }) => renderedProperties.add(control.property));
4446
5204
  if (!entries.length) return "";
4447
5205
  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(
5206
+ 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>` : "";
5207
+ 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
5208
  ({ control, index }) => renderPropertyControl(control, index, section.prefixes?.[control.property])
4450
5209
  ).join("")}</div></section>`;
4451
5210
  }).join("");
@@ -4454,7 +5213,8 @@ function installFoundryInspector(options = {}) {
4454
5213
  );
4455
5214
  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
5215
  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>`;
5216
+ const categoryAction = group.key === "layout" ? '<button class="category-action" data-layout-action="tidy"><i data-foundry-icon="wand-sparkles"></i><span>Tidy</span></button>' : "";
5217
+ 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
5218
  }).join("");
4459
5219
  const currentBaseline = baselineForContext(
4460
5220
  designMemory,
@@ -4476,6 +5236,7 @@ function installFoundryInspector(options = {}) {
4476
5236
  button.setAttribute("aria-expanded", String(!collapsed));
4477
5237
  if (collapsed) collapsedSections.add(key);
4478
5238
  else collapsedSections.delete(key);
5239
+ sectionPreferenceTouched = true;
4479
5240
  sessionStorage.setItem(
4480
5241
  "__foundry_collapsed_sections",
4481
5242
  JSON.stringify([...collapsedSections])
@@ -4488,6 +5249,12 @@ function installFoundryInspector(options = {}) {
4488
5249
  renderControls();
4489
5250
  })
4490
5251
  );
5252
+ controlsRoot.querySelectorAll("[data-radius-link]").forEach(
5253
+ (button) => button.addEventListener("click", () => {
5254
+ radiusLinked = !radiusLinked;
5255
+ renderControls();
5256
+ })
5257
+ );
4491
5258
  indexedControls.forEach(({ control, index }) => {
4492
5259
  const matches = matchingTokens(
4493
5260
  designGraph?.tokens ?? [],
@@ -4495,7 +5262,8 @@ function installFoundryInspector(options = {}) {
4495
5262
  `${control.value}${control.unit ?? ""}`
4496
5263
  );
4497
5264
  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;
5265
+ const availableTokens = tokensForCategory(control.category);
5266
+ if (!tokenEligible || !availableTokens.length) return;
4499
5267
  const field = controlsRoot.querySelector(`[data-control="${index}"]`);
4500
5268
  const label = field?.closest("label");
4501
5269
  if (!label) return;
@@ -4503,14 +5271,27 @@ function installFoundryInspector(options = {}) {
4503
5271
  "beforeend",
4504
5272
  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
5273
  );
4506
- if (!matches.length) return;
4507
5274
  label.insertAdjacentHTML(
4508
5275
  "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>`
5276
+ `<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(
5277
+ (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>`
5278
+ ).join("")}</span></span>`
4512
5279
  );
4513
5280
  });
5281
+ renderIcons(controlsRoot);
5282
+ controlsRoot.querySelectorAll("[data-token-menu-trigger]").forEach((button) => {
5283
+ button.addEventListener("click", () => {
5284
+ const menu = controlsRoot.querySelector(
5285
+ `[data-token-menu="${button.dataset.tokenMenuTrigger}"]`
5286
+ );
5287
+ if (!menu) return;
5288
+ controlsRoot.querySelectorAll("[data-token-menu]").forEach((candidate2) => {
5289
+ if (candidate2 !== menu) candidate2.hidden = true;
5290
+ });
5291
+ menu.hidden = !menu.hidden;
5292
+ button.setAttribute("aria-expanded", String(!menu.hidden));
5293
+ });
5294
+ });
4514
5295
  controlsRoot.querySelectorAll("[data-reset-control]").forEach((button) => {
4515
5296
  button.addEventListener("click", () => {
4516
5297
  const control = selectedControls[Number(button.dataset.resetControl)];
@@ -4628,10 +5409,38 @@ function installFoundryInspector(options = {}) {
4628
5409
  fieldRecorders.get(linkedIndex)?.push(linkedBefore, value);
4629
5410
  });
4630
5411
  }
5412
+ const radiusProperties = [
5413
+ "borderTopLeftRadius",
5414
+ "borderTopRightRadius",
5415
+ "borderBottomLeftRadius",
5416
+ "borderBottomRightRadius"
5417
+ ];
5418
+ if (radiusLinked && (control.property === "borderRadius" || radiusProperties.includes(control.property))) {
5419
+ indexedControls.forEach(({ control: linkedControl, index: linkedIndex }) => {
5420
+ if (linkedControl === control || !radiusProperties.includes(linkedControl.property))
5421
+ return;
5422
+ const linkedBefore = linkedControl.read();
5423
+ linkedControl.apply(value);
5424
+ const linkedField = controlsRoot.querySelector(
5425
+ `[data-control="${linkedIndex}"]`
5426
+ );
5427
+ if (linkedField) linkedField.value = String(value);
5428
+ fieldRecorders.get(linkedIndex)?.push(linkedBefore, value);
5429
+ });
5430
+ }
4631
5431
  updateOutline();
4632
5432
  recorder.push(before, value);
4633
5433
  });
4634
5434
  });
5435
+ controlsRoot.querySelectorAll("[data-color-control]").forEach((button) => {
5436
+ button.addEventListener("click", () => {
5437
+ const index = Number(button.dataset.colorControl);
5438
+ const control = selectedControls[index];
5439
+ if (!control) return;
5440
+ activeControlProperty = control.property;
5441
+ openColorEditor(button, index);
5442
+ });
5443
+ });
4635
5444
  controlsRoot.querySelectorAll("[data-token-control]").forEach((button) => {
4636
5445
  button.addEventListener("click", () => {
4637
5446
  const index = Number(button.dataset.tokenControl);
@@ -4639,8 +5448,16 @@ function installFoundryInspector(options = {}) {
4639
5448
  `[data-control="${index}"]`
4640
5449
  );
4641
5450
  const control = selectedControls[index];
4642
- if (!field || !control) return;
5451
+ if (!control) return;
4643
5452
  const raw = button.dataset.tokenValue ?? "";
5453
+ if (control.kind === "color") {
5454
+ void applyControlValue(control, raw, "Use project color").then(() => {
5455
+ if (selected) selectedControls = controlsFor(selected);
5456
+ renderControls();
5457
+ });
5458
+ return;
5459
+ }
5460
+ if (!field) return;
4644
5461
  field.value = control.kind === "number" ? String(numberFrom(raw)) : raw;
4645
5462
  field.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
4646
5463
  });
@@ -4651,6 +5468,8 @@ function installFoundryInspector(options = {}) {
4651
5468
  }
4652
5469
  function select(element, additive = false) {
4653
5470
  if (element === host || host.contains(element)) return;
5471
+ colorPopover.hidden = true;
5472
+ activeColor = void 0;
4654
5473
  if (additive && selectedElements.includes(element)) {
4655
5474
  selectedElements = selectedElements.filter((item) => item !== element);
4656
5475
  if (!selectedElements.length) {
@@ -4666,6 +5485,40 @@ function installFoundryInspector(options = {}) {
4666
5485
  selectedElements = [element];
4667
5486
  selected = element;
4668
5487
  }
5488
+ if (!sectionPreferenceTouched) {
5489
+ const categoryKeys = [
5490
+ "position",
5491
+ "layout",
5492
+ "typography",
5493
+ "appearance",
5494
+ "fill",
5495
+ "stroke",
5496
+ "effects",
5497
+ "content",
5498
+ "accessibility",
5499
+ "motion"
5500
+ ];
5501
+ categoryKeys.forEach((key) => collapsedSections.add(`category:${key}`));
5502
+ collapsedSections.delete("category:position");
5503
+ collapsedSections.delete("category:layout");
5504
+ collapsedSections.delete("category:appearance");
5505
+ collapsedSections.delete("category:fill");
5506
+ const isText = element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element.children.length === 0 && Boolean(element.textContent?.trim());
5507
+ const isMedia = element instanceof HTMLImageElement;
5508
+ if (isText) {
5509
+ collapsedSections.delete("category:typography");
5510
+ collapsedSections.delete("category:content");
5511
+ }
5512
+ if (isMedia) {
5513
+ collapsedSections.delete("category:content");
5514
+ collapsedSections.delete("category:accessibility");
5515
+ }
5516
+ if (Number.parseFloat(getComputedStyle(element).borderWidth) > 0)
5517
+ collapsedSections.delete("category:stroke");
5518
+ if (getComputedStyle(element).boxShadow !== "none" || Number.parseFloat(getComputedStyle(element).borderRadius) > 0)
5519
+ collapsedSections.delete("category:effects");
5520
+ if (element.getAnimations().length) collapsedSections.delete("category:motion");
5521
+ }
4669
5522
  selectedControls = controlsFor(element);
4670
5523
  const target = targetFor(element);
4671
5524
  panel.classList.add("has-selection");
@@ -4702,6 +5555,8 @@ function installFoundryInspector(options = {}) {
4702
5555
  });
4703
5556
  }
4704
5557
  function clearSelection() {
5558
+ colorPopover.hidden = true;
5559
+ activeColor = void 0;
4705
5560
  selected = null;
4706
5561
  selectedElements = [];
4707
5562
  selectedControls = [];
@@ -5067,25 +5922,25 @@ function installFoundryInspector(options = {}) {
5067
5922
  method: "POST",
5068
5923
  body: JSON.stringify({ runId, results })
5069
5924
  });
5070
- if (workspaceState.tray === "expanded") renderReviewPayload(payload);
5925
+ if (workspaceState.reviewOpen) renderReviewPayload(payload);
5071
5926
  showToast(
5072
5927
  `${results.filter((result) => result.passed).length}/${results.length} changes verified`
5073
5928
  );
5074
5929
  }
5075
5930
  function installPanelResizer() {
5076
5931
  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
5932
  resizer.addEventListener("pointerdown", (event) => {
5080
- if (event.button !== 0) return;
5933
+ if (event.button !== 0 || window.matchMedia("(max-width: 680px)").matches) return;
5081
5934
  const startX = event.clientX;
5082
- const startWidth = panel.getBoundingClientRect().width;
5935
+ const startWidth = dockWidth;
5083
5936
  resizer.setPointerCapture(event.pointerId);
5084
5937
  event.preventDefault();
5085
5938
  const move = (pointer) => {
5086
5939
  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`;
5940
+ const next = Math.max(340, Math.min(maximum, startWidth + startX - pointer.clientX));
5941
+ dockWidth = Math.round(next);
5942
+ host.style.setProperty("--fdc-dock-width", `${dockWidth}px`);
5943
+ positionWorkspaceSurfaces();
5089
5944
  };
5090
5945
  const finish = (pointer) => {
5091
5946
  resizer.removeEventListener("pointermove", move);
@@ -5093,10 +5948,8 @@ function installFoundryInspector(options = {}) {
5093
5948
  resizer.removeEventListener("pointercancel", finish);
5094
5949
  if (resizer.hasPointerCapture(pointer.pointerId))
5095
5950
  resizer.releasePointerCapture(pointer.pointerId);
5096
- localStorage.setItem(
5097
- "__foundry_panel_width",
5098
- String(Math.round(panel.getBoundingClientRect().width))
5099
- );
5951
+ localStorage.setItem(dockWidthKey, String(dockWidth));
5952
+ localStorage.removeItem(legacyDockWidthKey);
5100
5953
  };
5101
5954
  resizer.addEventListener("pointermove", move);
5102
5955
  resizer.addEventListener("pointerup", finish);
@@ -5232,6 +6085,16 @@ function installFoundryInspector(options = {}) {
5232
6085
  }
5233
6086
  });
5234
6087
  statusPopover.querySelector("[data-status-retry]").addEventListener("click", () => void hydrateSession());
6088
+ interfaceThemeTrigger.addEventListener("click", () => {
6089
+ if (interfaceThemeMenu.hidden) openInterfaceThemeMenu();
6090
+ else closeInterfaceThemeMenu();
6091
+ });
6092
+ interfaceThemeMenu.querySelectorAll("[data-interface-theme-choice]").forEach(
6093
+ (button) => button.addEventListener("click", () => {
6094
+ applyInterfaceTheme(button.dataset.interfaceThemeChoice);
6095
+ closeInterfaceThemeMenu(true);
6096
+ })
6097
+ );
5235
6098
  changeDock.querySelector(".dock-undo")?.addEventListener("click", () => void replayHistory(-1));
5236
6099
  changeDock.querySelector(".dock-review")?.addEventListener("click", () => void openReview());
5237
6100
  onboarding.querySelector(".onboarding-start")?.addEventListener("click", () => {
@@ -5332,13 +6195,14 @@ function installFoundryInspector(options = {}) {
5332
6195
  );
5333
6196
  comparisonStage.querySelector("[data-close-comparison-stage]").addEventListener("click", closeSplitComparison);
5334
6197
  const commandInput = commandPalette.querySelector("input");
6198
+ commandPalette.querySelector(".close-commands")?.addEventListener("click", () => closeCommands());
5335
6199
  commandInput.addEventListener("input", () => renderCommands(commandInput.value));
5336
6200
  commandInput.addEventListener("keydown", (event) => {
5337
6201
  if (event.key === "Enter") {
5338
6202
  const active = commandPalette.querySelector(".command-item.active");
5339
6203
  if (active) runCommand(active.dataset.command);
5340
6204
  }
5341
- if (event.key === "Escape") commandPalette.hidden = true;
6205
+ if (event.key === "Escape") closeCommands();
5342
6206
  });
5343
6207
  shadow.querySelector(".close")?.addEventListener("click", destroyInspector);
5344
6208
  shadow.querySelector(".open-workbench")?.addEventListener("click", openWorkbench);
@@ -5364,7 +6228,7 @@ function installFoundryInspector(options = {}) {
5364
6228
  shadow.querySelector(".redo")?.addEventListener("click", () => void replayHistory(1));
5365
6229
  shadow.querySelector(".align")?.addEventListener("click", () => void alignSelected());
5366
6230
  shadow.querySelector(".distribute")?.addEventListener("click", () => void distributeSelected());
5367
- shadow.querySelector(".review-back")?.addEventListener("click", closeReview);
6231
+ shadow.querySelector(".review-back")?.addEventListener("click", () => closeReview());
5368
6232
  reviewCancel.addEventListener("click", () => {
5369
6233
  if (reviewCancel.dataset.action === "cancel") void cancelRun();
5370
6234
  else closeReview();
@@ -5374,6 +6238,25 @@ function installFoundryInspector(options = {}) {
5374
6238
  if (applyButton.dataset.action === "retry") void retryRun();
5375
6239
  });
5376
6240
  function handleGlobalShortcuts(event) {
6241
+ if (workspaceState.reviewOpen && event.key === "Tab") {
6242
+ const focusable = [
6243
+ ...reviewModal.querySelectorAll(
6244
+ 'button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex="-1"])'
6245
+ )
6246
+ ].filter((element) => element.offsetParent !== null);
6247
+ if (focusable.length) {
6248
+ const first = focusable[0];
6249
+ const last = focusable.at(-1);
6250
+ if (event.shiftKey && shadow.activeElement === first) {
6251
+ event.preventDefault();
6252
+ last.focus();
6253
+ } else if (!event.shiftKey && shadow.activeElement === last) {
6254
+ event.preventDefault();
6255
+ first.focus();
6256
+ }
6257
+ }
6258
+ return;
6259
+ }
5377
6260
  const editable = event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLSelectElement || event.target instanceof HTMLElement && event.target.isContentEditable;
5378
6261
  if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
5379
6262
  event.preventDefault();
@@ -5412,13 +6295,22 @@ function installFoundryInspector(options = {}) {
5412
6295
  return;
5413
6296
  }
5414
6297
  if (event.key !== "Escape") return;
5415
- if (!comparisonStage.hidden) closeSplitComparison();
5416
- else if (!commandPalette.hidden) commandPalette.hidden = true;
6298
+ if (workspaceState.reviewOpen) {
6299
+ const nested = reviewModal.querySelector("details[open]");
6300
+ if (nested) nested.open = false;
6301
+ else closeReview();
6302
+ return;
6303
+ }
6304
+ if (!interfaceThemeMenu.hidden) closeInterfaceThemeMenu(true);
6305
+ else if (!colorPopover.hidden) {
6306
+ colorPopover.hidden = true;
6307
+ activeColor = void 0;
6308
+ } else if (!comparisonStage.hidden) closeSplitComparison();
6309
+ else if (!commandPalette.hidden) closeCommands();
5417
6310
  else if (!libraryPanel.hidden) closeDesignMemory();
5418
6311
  else if (!healthPanel.hidden) closeHealth();
5419
6312
  else if (comparisonActive) closeComparison();
5420
6313
  else if (!workbench.hidden) closeWorkbench();
5421
- else if (workspaceState.tray === "expanded") closeReview();
5422
6314
  else clearSelection();
5423
6315
  }
5424
6316
  document.addEventListener("keydown", handleGlobalShortcuts);
@@ -5452,6 +6344,8 @@ function installFoundryInspector(options = {}) {
5452
6344
  cancelAnimationFrame(layerScrollFrame);
5453
6345
  cancelAnimationFrame(mutationFrame);
5454
6346
  layerMutationObserver.disconnect();
6347
+ systemDarkTheme.removeEventListener("change", handleSystemThemeChange);
6348
+ document.removeEventListener("pointerdown", handleInterfaceThemeDismiss, true);
5455
6349
  clearInterval(reviewPoll);
5456
6350
  document.removeEventListener("click", handlePointer, true);
5457
6351
  document.removeEventListener("dblclick", handleTextEdit, true);