profile-pane 3.1.1-0a928621 → 3.1.1-86f82dc8

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.
@@ -78,7 +78,7 @@ function presentSocial(subject, store) {
78
78
  }
79
79
 
80
80
  // we need to load the social media accounts ontology to be able to query all data needed
81
- (0, _rdfFormsHelper.loadDocument)(socialMediaFormName, socialMediaForm, store);
81
+ (0, _rdfFormsHelper.loadDocument)(store, socialMediaForm, socialMediaFormName);
82
82
  const accountNodes = store.each(subject, _solidUi.ns.foaf('account'));
83
83
  const accountThings = accountNodes.flatMap(node => expandRdfList(store, node));
84
84
  if (!accountThings.length) return {
@@ -1 +1 @@
1
- {"version":3,"file":"EditCVCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditCVCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAC,MAAM,QAAQ,CAAA;AAOxC,wBAAgB,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,eA+BxH"}
1
+ {"version":3,"file":"EditCVCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditCVCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAC,MAAM,QAAQ,CAAA;AAOxC,wBAAgB,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,eAgCxH"}
@@ -13,8 +13,9 @@ const resumeFormName = 'resumeForm.ttl'; // The name of the form file
13
13
 
14
14
  function EditCVSection(context, me, editableProfile, store) {
15
15
  const section = context.dom.createElement('section');
16
+ section.setAttribute('data-testid', 'edit-cv-section');
16
17
  section.setAttribute('aria-labelledby', 'edit-profile-cv-heading');
17
- section.classList.add('profileSection', 'section-bg');
18
+ section.classList.add('profileSection', 'section-bg', 'profile-form');
18
19
  const header = context.dom.createElement('header');
19
20
  header.classList.add('text-center', 'mb-md');
20
21
  const heading = context.dom.createElement('h2');
@@ -1 +1 @@
1
- {"version":3,"file":"EditCommunitiesCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditCommunitiesCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAIlC,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,eAqC9I"}
1
+ {"version":3,"file":"EditCommunitiesCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditCommunitiesCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAIlC,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,eA6C9I"}
@@ -19,20 +19,29 @@ function EditProfileCommunitiesSection(context, me, editableProfile, profile) {
19
19
  header.appendChild(heading);
20
20
  section.appendChild(header);
21
21
  const comment1 = context.dom.createElement('p');
22
+ comment1.id = 'edit-profile-communities-description';
22
23
  comment1.classList.add('p-md');
23
24
  comment1.textContent = 'These are organizations and projects whose stuff you share';
24
25
  section.appendChild(comment1);
26
+ let comment2 = null;
25
27
  if (editableProfile) {
26
- const comment2 = context.dom.createElement('p');
28
+ comment2 = context.dom.createElement('p');
29
+ comment2.id = 'edit-profile-communities-help';
27
30
  comment2.classList.add('p-md');
28
31
  comment2.textContent = 'Drag organizations onto the target below to add organizations.';
29
32
  section.appendChild(comment2);
30
33
  }
31
- section.appendChild(_solidUi.widgets.attachmentList(context.dom, me, section, {
34
+ const attachmentList = _solidUi.widgets.attachmentList(context.dom, me, section, {
32
35
  doc: profile,
33
36
  modify: !!editableProfile,
34
37
  predicate: _solidUi.ns.solid('community'),
35
38
  noun: 'community'
36
- }));
39
+ });
40
+ const descriptions = [comment1.id];
41
+ if (comment2?.id) {
42
+ descriptions.push(comment2.id);
43
+ }
44
+ attachmentList.setAttribute('aria-describedby', descriptions.join(' '));
45
+ section.appendChild(attachmentList);
37
46
  return section;
38
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EditFriendsCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditFriendsCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAIlC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,eAsCnI"}
1
+ {"version":3,"file":"EditFriendsCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditFriendsCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAIlC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,eA8CnI"}
@@ -19,20 +19,29 @@ function EditFriendsSection(context, me, editableProfile, profile) {
19
19
  header.appendChild(heading);
20
20
  section.appendChild(header);
21
21
  const comment1 = context.dom.createElement('p');
22
+ comment1.id = 'edit-profile-friends-description';
22
23
  comment1.classList.add('p-md');
23
24
  comment1.textContent = 'This is your public social network. Only put people here to whom you are happy to be publicly connected. (You can always keep private track of friends and family in your contacts.)';
24
25
  section.appendChild(comment1);
26
+ let comment2 = null;
25
27
  if (editableProfile) {
26
- const comment2 = context.dom.createElement('p');
28
+ comment2 = context.dom.createElement('p');
29
+ comment2.id = 'edit-profile-friends-help';
27
30
  comment2.classList.add('p-md');
28
31
  comment2.textContent = 'Drag people onto the target below to add people.';
29
32
  section.appendChild(comment2);
30
33
  }
31
- section.appendChild(_solidUi.widgets.attachmentList(context.dom, me, section, {
34
+ const attachmentList = _solidUi.widgets.attachmentList(context.dom, me, section, {
32
35
  doc: profile,
33
36
  modify: !!editableProfile,
34
37
  predicate: _solidUi.ns.foaf('knows'),
35
38
  noun: 'friend'
36
- }));
39
+ });
40
+ const descriptions = [comment1.id];
41
+ if (comment2?.id) {
42
+ descriptions.push(comment2.id);
43
+ }
44
+ attachmentList.setAttribute('aria-describedby', descriptions.join(' '));
45
+ section.appendChild(attachmentList);
37
46
  return section;
38
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EditOtherPreferences.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditOtherPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAC,MAAM,QAAQ,CAAA;AAOxC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,eAmBtI"}
1
+ {"version":3,"file":"EditOtherPreferences.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditOtherPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAC,MAAM,QAAQ,CAAA;AAOxC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,eAoBtI"}
@@ -13,8 +13,9 @@ const otherPreferencesFormName = 'otherPreferencesForm.ttl'; // The name of the
13
13
 
14
14
  function EditOtherPreferencesSection(context, me, editableProfile, store) {
15
15
  const section = context.dom.createElement('section');
16
+ section.setAttribute('data-testid', 'edit-other-preferences-section');
16
17
  section.setAttribute('aria-labelledby', 'edit-profile-other-preferences-heading');
17
- section.classList.add('profileSection', 'section-bg');
18
+ section.classList.add('profileSection', 'section-bg', 'profile-form');
18
19
  const header = context.dom.createElement('header');
19
20
  header.classList.add('text-center', 'mb-md');
20
21
  const heading = context.dom.createElement('h2');
@@ -1 +1 @@
1
- {"version":3,"file":"EditProfileView.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditProfileView.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAO9C,OAAO,yBAAyB,CAAA;AAChC,OAAO,gCAAgC,CAAA;AAIvC,QAAA,MAAM,eAAe,EAAE,cAiFtB,CAAA;AAED,eAAe,eAAe,CAAA"}
1
+ {"version":3,"file":"EditProfileView.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditProfileView.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAO9C,OAAO,yBAAyB,CAAA;AAChC,OAAO,gCAAgC,CAAA;AAIvC,QAAA,MAAM,eAAe,EAAE,cAoGtB,CAAA;AAED,eAAe,eAAe,CAAA"}
@@ -45,14 +45,26 @@ const editProfileView = {
45
45
  // Use <main> for the main content area, styled as a grid like ProfileView
46
46
  const main = dom.createElement('main');
47
47
  main.setAttribute('id', 'profile-edit-main-content');
48
- main.classList.add('profile-grid');
48
+ main.setAttribute('aria-busy', 'true');
49
+ main.setAttribute('tabindex', '-1');
50
+ main.classList.add('profile-grid', 'no-focus-ring');
51
+ const mainHeading = dom.createElement('h1');
52
+ mainHeading.classList.add('visually-hidden');
53
+ mainHeading.textContent = 'Edit Profile';
54
+ main.appendChild(mainHeading);
49
55
  div.appendChild(main);
50
56
 
51
57
  // Use <aside> for the status area
52
58
  const statusArea = dom.createElement('aside');
53
59
  statusArea.classList.add('p-sm');
60
+ statusArea.setAttribute('role', 'status');
54
61
  statusArea.setAttribute('aria-live', 'polite');
55
- div.appendChild(statusArea);
62
+ statusArea.setAttribute('aria-atomic', 'true');
63
+ const ensureStatusArea = () => {
64
+ if (!statusArea.isConnected) {
65
+ div.appendChild(statusArea);
66
+ }
67
+ };
56
68
  const profileContext = {
57
69
  dom: dom,
58
70
  div: main,
@@ -70,6 +82,7 @@ const editProfileView = {
70
82
  } else if (store.updater.editable(profile.uri, store)) {
71
83
  editableProfile = profile;
72
84
  } else {
85
+ ensureStatusArea();
73
86
  statusArea.appendChild(_solidUi.widgets.errorMessageBlock(dom, `⚠️ Your profile ${profile} is not editable, so we cannot do much here.`, 'straw'));
74
87
  return;
75
88
  }
@@ -78,12 +91,12 @@ const editProfileView = {
78
91
  // Your contact information Section
79
92
  main.appendChild((0, _EditContactsCard.EditContactsSection)(context, me));
80
93
 
81
- // Social Accounts Section
82
- main.appendChild((0, _EditSocialCard.EditSocialSection)(context, me, editableProfile, store));
83
-
84
94
  // Resume Section
85
95
  main.appendChild((0, _EditCVCard.EditCVSection)(context, me, editableProfile, store));
86
96
 
97
+ // Social Accounts Section
98
+ main.appendChild((0, _EditSocialCard.EditSocialSection)(context, me, editableProfile, store));
99
+
87
100
  // Other preferences Section
88
101
  main.appendChild((0, _EditOtherPreferences.EditOtherPreferencesSection)(context, me, editableProfile, store));
89
102
 
@@ -92,8 +105,12 @@ const editProfileView = {
92
105
 
93
106
  // Communities you participate in Section
94
107
  main.appendChild((0, _EditCommunitiesCard.EditProfileCommunitiesSection)(context, me, editableProfile, profile));
108
+ main.setAttribute('aria-busy', 'false');
109
+ main.focus();
95
110
  }).catch(error => {
111
+ ensureStatusArea();
96
112
  statusArea.appendChild(_solidUi.widgets.errorMessageBlock(dom, error, '#fee'));
113
+ main.setAttribute('aria-busy', 'false');
97
114
  });
98
115
  return div;
99
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EditSocialCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditSocialCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAC,MAAM,QAAQ,CAAA;AAOxC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,eA+B5H"}
1
+ {"version":3,"file":"EditSocialCard.d.ts","sourceRoot":"","sources":["../../src/editProfilePane/EditSocialCard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAC,MAAM,QAAQ,CAAA;AAOxC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,eAgC5H"}
@@ -13,8 +13,9 @@ const socialMediaFormName = 'socialMedia.ttl'; // The name of the form file
13
13
 
14
14
  function EditSocialSection(context, me, editableProfile, store) {
15
15
  const section = context.dom.createElement('section');
16
+ section.setAttribute('data-testid', 'edit-social-section');
16
17
  section.setAttribute('aria-labelledby', 'edit-profile-social-heading');
17
- section.classList.add('profileSection', 'section-bg');
18
+ section.classList.add('profileSection', 'section-bg', 'profile-form');
18
19
  const header = context.dom.createElement('header');
19
20
  header.classList.add('text-center', 'mb-md');
20
21
  const heading = context.dom.createElement('h2');
@@ -550,6 +550,8 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/* Solid-UI form sizing fixes scoped t
550
550
  max-width: 100%;
551
551
  min-width: 0;
552
552
  box-sizing: border-box ;
553
+ background-color: #eef !important;
554
+ border: .05em solid #88c
553
555
  }
554
556
 
555
557
  .profile-form input[type="url"] {
@@ -658,7 +660,20 @@ section[aria-labelledby="edit-profile-contact-heading"] .profile-form > div:firs
658
660
  margin-right: 0 !important;
659
661
  }
660
662
 
661
- `, "",{"version":3,"sources":["webpack://./src/styles/rdfFormsEnforced.css"],"names":[],"mappings":"AAAA,yDAAyD;AACzD;EACE,iDAAiD;AACnD;;AAEA;EACE,wCAAwC;EACxC,uBAAuB;EACvB,oBAAoB;EACpB,2BAA2B;EAC3B,yBAAyB;EACzB,eAAe;EACf,oBAAoB;EACpB,mBAAmB;EACnB,uBAAuB;AACzB;;AAEA;EACE,uBAAuB;EACvB,wBAAwB;EACxB,cAAc;EACd,wBAAwB;EACxB,yBAAyB;EACzB,0BAA0B;EAC1B,+BAA+B;AACjC;;AAEA;EACE,oBAAoB;EACpB,mBAAmB;EACnB,kBAAkB;AACpB;;AAEA;EACE,oBAAoB;EACpB,mBAAmB;AACrB;;AAEA;EACE,kBAAkB;AACpB;;AAEA;EACE,wCAAwC;AAC1C;;AAEA;EACE,wCAAwC;EACxC,uBAAuB;EACvB,oBAAoB;EACpB,2BAA2B;AAC7B;;AAEA;;AAEA;;AAEA;;;EAGE,eAAe;EACf,YAAY;EACZ,uBAAuB;AACzB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,YAAY;EACZ,gCAAgC;AAClC;;AAEA;EACE,oBAAoB;EACpB,qBAAqB;AACvB;;AAEA;EACE,qBAAqB;AACvB;;AAEA;;;EAGE,WAAW;EACX,eAAe;AACjB;;AAEA;EACE,WAAW;EACX,cAAc;EACd,sBAAsB;EACtB,yBAAyB;EACzB,0BAA0B;AAC5B;;AAEA;EACE,yBAAyB;EACzB,sBAAsB;AACxB;;AAEA,oFAAoF;AACpF;;EAEE,uBAAuB;EACvB,qBAAqB;AACvB;;AAEA,0FAA0F;AAC1F;EACE,uBAAuB;EACvB,qBAAqB;AACvB;;AAEA,sEAAsE;AACtE;EACE,uBAAuB;EACvB,qBAAqB;AACvB;;AAEA,8FAA8F;AAC9F;;;;;EAKE,oBAAoB;EACpB,mBAAmB;EACnB,sBAAsB;AACxB;;AAEA;;;;;EAKE,oBAAoB;EACpB,mBAAmB;EACnB,sBAAsB;AACxB;;AAEA;EACE,WAAW;EACX,sBAAsB;EACtB,6BAA6B;EAC7B,yBAAyB;EACzB,0BAA0B;AAC5B;;AAEA,gFAAgF;AAChF;EACE,8BAA8B;AAChC;;AAEA,mDAAmD;AACnD;EACE,uBAAuB;AACzB;;AAEA;EACE,8BAA8B;AAChC;;AAEA;EACE,WAAW;EACX,yBAAyB;EACzB,0BAA0B;AAC5B","sourcesContent":["/* Solid-UI form sizing fixes scoped to Edit CV section */\n.profile-form .hoverControl:not(:has(> img:first-child)) {\n border: 0.1em solid rgb(136, 136, 136) !important;\n}\n\n.profile-form .hoverControl:has(> img:first-child) {\n background-color: transparent !important;\n border: none !important;\n margin: 0 !important;\n border-radius: 0 !important;\n padding: 0.7em !important;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.profile-form .hoverControlHide {\n width: 1.5em !important;\n height: 1.5em !important;\n display: block;\n margin-top: 0 !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n margin-bottom: 0.3em !important;\n}\n\n.profile-form .hoverControl:has(> img:first-child) > span {\n display: inline-flex;\n align-items: center;\n margin-left: 0.3em;\n}\n\n.profile-form div[style*=\"padding: 0.5em\"]:has(> img) {\n display: inline-flex;\n align-items: center;\n}\n\n.profile-form div[style*=\"padding: 0.5em\"]:has(> img) > span {\n margin-left: 0.3em;\n}\n\n.profile-form .hoverControl:has(> img:first-child):hover {\n background-color: transparent !important;\n}\n\n.profile-form button:has(> img[src$=\".svg\"]) {\n background-color: transparent !important;\n border: none !important;\n margin: 0 !important;\n border-radius: 0 !important;\n}\n\n.profile-form button {\n\n}\n\n.profile-form input:not([type=\"color\"]),\n.profile-form textarea,\n.profile-form select {\n max-width: 100%;\n min-width: 0;\n box-sizing: border-box ;\n}\n\n.profile-form input[type=\"url\"] {\n width: 100%;\n}\n\n.profile-form .formFieldValue {\n min-width: 0;\n margin-bottom: var(--spacing-sm);\n}\n\n.profile-form .formFieldValue table {\n margin: 0 !important;\n padding: 0 !important;\n}\n\n.profile-form .formFieldValue td {\n padding: 0 !important;\n}\n\n.profile-form .formFieldValue input:not([type=\"color\"]),\n.profile-form .formFieldValue textarea,\n.profile-form .formFieldValue select {\n width: 100%;\n max-width: 100%;\n}\n\n.profile-form select#formSelect {\n width: 100%;\n max-width: 97%;\n box-sizing: border-box;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n.profile-form span select {\n max-width: 96% !important;\n box-sizing: border-box;\n}\n\n/* Remove border/padding from the first wrapper div (and its first child wrapper). */\n.profile-form > div:first-of-type,\n.profile-form > div:first-of-type > div:first-of-type {\n border: none !important;\n padding: 0 !important;\n}\n\n/* Remove border/padding from the inner div of the first wrapper in the contact section. */\nsection[aria-labelledby=\"edit-profile-contact-heading\"] .profile-form > div:first-of-type > div:first-of-type {\n border: none !important;\n padding: 0 !important;\n}\n\n/* In contactPane, remove border/padding from all direct child divs. */\n.contactPane > div {\n border: none !important;\n padding: 0 !important;\n}\n\n/* Align schema.org, solid terms, FOAF, vCard, and org field labels with their input values. */\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://schema.org/\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/solid/terms#\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://xmlns.com/foaf/0.1/\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/2006/vcard/ns\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/org#\"]) {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://schema.org/\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/solid/terms#\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://xmlns.com/foaf/0.1/\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/2006/vcard/ns\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/org#\"]) + .formFieldValue {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n.profile-form textarea {\n width: 100%;\n box-sizing: border-box;\n margin-top: var(--spacing-xs);\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n/* Add horizontal gap between label and textarea for all label+textarea pairs. */\n.profile-form div:has(> a) + div:has(textarea) {\n margin-left: var(--spacing-sm);\n}\n\n/* Center textarea label vertically in flex rows. */\n.profile-form div[style*=\"display: flex\"][style*=\"flex-direction: row\"]:has(textarea) {\n align-items: flex-start;\n}\n\n.profile-form div[style*=\"display: flex\"][style*=\"flex-direction: row\"]:has(textarea) > div:has(> a) {\n padding-top: var(--spacing-xs);\n}\n\n.profile-form input:not([type=\"color\"]) {\n width: 100%;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n"],"sourceRoot":""}]);
663
+ /* Remove padding from table cells within webidControl */
664
+ .webidControl table td {
665
+ padding: 0 !important;
666
+ }
667
+
668
+ /* Remove padding from contactPane divs inside webidControl table cells */
669
+ .webidControl table td div.contactPane.namedPane.fullWidth.individualPane {
670
+ padding: 0 !important;
671
+ }
672
+
673
+ .webidControl table td div.contactPane.namedPane {
674
+ border: none !important;
675
+ }
676
+ `, "",{"version":3,"sources":["webpack://./src/styles/rdfFormsEnforced.css"],"names":[],"mappings":"AAAA,yDAAyD;AACzD;EACE,iDAAiD;AACnD;;AAEA;EACE,wCAAwC;EACxC,uBAAuB;EACvB,oBAAoB;EACpB,2BAA2B;EAC3B,yBAAyB;EACzB,eAAe;EACf,oBAAoB;EACpB,mBAAmB;EACnB,uBAAuB;AACzB;;AAEA;EACE,uBAAuB;EACvB,wBAAwB;EACxB,cAAc;EACd,wBAAwB;EACxB,yBAAyB;EACzB,0BAA0B;EAC1B,+BAA+B;AACjC;;AAEA;EACE,oBAAoB;EACpB,mBAAmB;EACnB,kBAAkB;AACpB;;AAEA;EACE,oBAAoB;EACpB,mBAAmB;AACrB;;AAEA;EACE,kBAAkB;AACpB;;AAEA;EACE,wCAAwC;AAC1C;;AAEA;EACE,wCAAwC;EACxC,uBAAuB;EACvB,oBAAoB;EACpB,2BAA2B;AAC7B;;AAEA;;AAEA;;AAEA;;;EAGE,eAAe;EACf,YAAY;EACZ,uBAAuB;EACvB,iCAAiC;EACjC;AACF;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,YAAY;EACZ,gCAAgC;AAClC;;AAEA;EACE,oBAAoB;EACpB,qBAAqB;AACvB;;AAEA;EACE,qBAAqB;AACvB;;AAEA;;;EAGE,WAAW;EACX,eAAe;AACjB;;AAEA;EACE,WAAW;EACX,cAAc;EACd,sBAAsB;EACtB,yBAAyB;EACzB,0BAA0B;AAC5B;;AAEA;EACE,yBAAyB;EACzB,sBAAsB;AACxB;;AAEA,oFAAoF;AACpF;;EAEE,uBAAuB;EACvB,qBAAqB;AACvB;;AAEA,0FAA0F;AAC1F;EACE,uBAAuB;EACvB,qBAAqB;AACvB;;AAEA,sEAAsE;AACtE;EACE,uBAAuB;EACvB,qBAAqB;AACvB;;AAEA,8FAA8F;AAC9F;;;;;EAKE,oBAAoB;EACpB,mBAAmB;EACnB,sBAAsB;AACxB;;AAEA;;;;;EAKE,oBAAoB;EACpB,mBAAmB;EACnB,sBAAsB;AACxB;;AAEA;EACE,WAAW;EACX,sBAAsB;EACtB,6BAA6B;EAC7B,yBAAyB;EACzB,0BAA0B;AAC5B;;AAEA,gFAAgF;AAChF;EACE,8BAA8B;AAChC;;AAEA,mDAAmD;AACnD;EACE,uBAAuB;AACzB;;AAEA;EACE,8BAA8B;AAChC;;AAEA;EACE,WAAW;EACX,yBAAyB;EACzB,0BAA0B;AAC5B;;AAEA,wDAAwD;AACxD;EACE,qBAAqB;AACvB;;AAEA,yEAAyE;AACzE;EACE,qBAAqB;AACvB;;AAEA;EACE,uBAAuB;AACzB","sourcesContent":["/* Solid-UI form sizing fixes scoped to Edit CV section */\n.profile-form .hoverControl:not(:has(> img:first-child)) {\n border: 0.1em solid rgb(136, 136, 136) !important;\n}\n\n.profile-form .hoverControl:has(> img:first-child) {\n background-color: transparent !important;\n border: none !important;\n margin: 0 !important;\n border-radius: 0 !important;\n padding: 0.7em !important;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.profile-form .hoverControlHide {\n width: 1.5em !important;\n height: 1.5em !important;\n display: block;\n margin-top: 0 !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n margin-bottom: 0.3em !important;\n}\n\n.profile-form .hoverControl:has(> img:first-child) > span {\n display: inline-flex;\n align-items: center;\n margin-left: 0.3em;\n}\n\n.profile-form div[style*=\"padding: 0.5em\"]:has(> img) {\n display: inline-flex;\n align-items: center;\n}\n\n.profile-form div[style*=\"padding: 0.5em\"]:has(> img) > span {\n margin-left: 0.3em;\n}\n\n.profile-form .hoverControl:has(> img:first-child):hover {\n background-color: transparent !important;\n}\n\n.profile-form button:has(> img[src$=\".svg\"]) {\n background-color: transparent !important;\n border: none !important;\n margin: 0 !important;\n border-radius: 0 !important;\n}\n\n.profile-form button {\n\n}\n\n.profile-form input:not([type=\"color\"]),\n.profile-form textarea,\n.profile-form select {\n max-width: 100%;\n min-width: 0;\n box-sizing: border-box ;\n background-color: #eef !important;\n border: .05em solid #88c\n}\n\n.profile-form input[type=\"url\"] {\n width: 100%;\n}\n\n.profile-form .formFieldValue {\n min-width: 0;\n margin-bottom: var(--spacing-sm);\n}\n\n.profile-form .formFieldValue table {\n margin: 0 !important;\n padding: 0 !important;\n}\n\n.profile-form .formFieldValue td {\n padding: 0 !important;\n}\n\n.profile-form .formFieldValue input:not([type=\"color\"]),\n.profile-form .formFieldValue textarea,\n.profile-form .formFieldValue select {\n width: 100%;\n max-width: 100%;\n}\n\n.profile-form select#formSelect {\n width: 100%;\n max-width: 97%;\n box-sizing: border-box;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n.profile-form span select {\n max-width: 96% !important;\n box-sizing: border-box;\n}\n\n/* Remove border/padding from the first wrapper div (and its first child wrapper). */\n.profile-form > div:first-of-type,\n.profile-form > div:first-of-type > div:first-of-type {\n border: none !important;\n padding: 0 !important;\n}\n\n/* Remove border/padding from the inner div of the first wrapper in the contact section. */\nsection[aria-labelledby=\"edit-profile-contact-heading\"] .profile-form > div:first-of-type > div:first-of-type {\n border: none !important;\n padding: 0 !important;\n}\n\n/* In contactPane, remove border/padding from all direct child divs. */\n.contactPane > div {\n border: none !important;\n padding: 0 !important;\n}\n\n/* Align schema.org, solid terms, FOAF, vCard, and org field labels with their input values. */\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://schema.org/\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/solid/terms#\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://xmlns.com/foaf/0.1/\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/2006/vcard/ns\"]),\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/org#\"]) {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://schema.org/\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/solid/terms#\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://xmlns.com/foaf/0.1/\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/2006/vcard/ns\"]) + .formFieldValue,\n.profile-form :not(.choiceBox) > .formFieldName:has(a[href*=\"http://www.w3.org/ns/org#\"]) + .formFieldValue {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n}\n\n.profile-form textarea {\n width: 100%;\n box-sizing: border-box;\n margin-top: var(--spacing-xs);\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n/* Add horizontal gap between label and textarea for all label+textarea pairs. */\n.profile-form div:has(> a) + div:has(textarea) {\n margin-left: var(--spacing-sm);\n}\n\n/* Center textarea label vertically in flex rows. */\n.profile-form div[style*=\"display: flex\"][style*=\"flex-direction: row\"]:has(textarea) {\n align-items: flex-start;\n}\n\n.profile-form div[style*=\"display: flex\"][style*=\"flex-direction: row\"]:has(textarea) > div:has(> a) {\n padding-top: var(--spacing-xs);\n}\n\n.profile-form input:not([type=\"color\"]) {\n width: 100%;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n/* Remove padding from table cells within webidControl */\n.webidControl table td {\n padding: 0 !important;\n}\n\n/* Remove padding from contactPane divs inside webidControl table cells */\n.webidControl table td div.contactPane.namedPane.fullWidth.individualPane {\n padding: 0 !important;\n}\n\n.webidControl table td div.contactPane.namedPane {\n border: none !important;\n}\n"],"sourceRoot":""}]);
662
677
  // Exports
663
678
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
664
679
 
@@ -836,6 +851,11 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/* Utility-first CSS classes for layou
836
851
  outline: none;
837
852
  }
838
853
 
854
+ .no-focus-ring:focus-visible {
855
+ outline: none;
856
+ box-shadow: none;
857
+ }
858
+
839
859
  /* ARIA live regions */
840
860
  .live-region {
841
861
  position: absolute;
@@ -1005,7 +1025,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/* Utility-first CSS classes for layou
1005
1025
  .btn-transparent:hover {
1006
1026
  background-color: transparent;
1007
1027
  }
1008
- `, "",{"version":3,"sources":["webpack://./src/styles/utilities.css"],"names":[],"mappings":"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","sourcesContent":["/* Utility-first CSS classes for layout, spacing, and responsiveness */\n\n.actionButton {\n width: 100%;\n min-width: 180px;\n max-width: 320px;\n box-sizing: border-box;\n display: inline-block;\n}\n\n/* ===========================================\n PROFILE GRID LAYOUT\n =========================================== */\n\n.profile-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(30em, 1fr));\n gap: var(--spacing-lg);\n background: var(--color-background);\n}\n\n.profile-header,\n.profile-footer {\n grid-column: 1 / -1;\n}\n\n.center {\n justify-content: center;\n align-items: center;\n}\n\n.flex {\n display: flex;\n}\n.grid {\n display: grid;\n}\n\n/* Spacing utilities using CSS variables */\n.gap-xs { gap: var(--spacing-xs); }\n.gap-sm { gap: var(--spacing-sm); }\n.gap-md { gap: var(--spacing-md); }\n.gap-lg { gap: var(--spacing-lg); }\n.gap-xl { gap: var(--spacing-xl); }\n\n.mt-xs { margin-top: var(--spacing-xs); }\n.mt-sm { margin-top: var(--spacing-sm); }\n.mt-md { margin-top: var(--spacing-md); }\n.mt-lg { margin-top: var(--spacing-lg); }\n\n.mb-xs { margin-bottom: var(--spacing-xs); }\n.mb-sm { margin-bottom: var(--spacing-sm); }\n.mb-md { margin-bottom: var(--spacing-md); }\n.mb-lg { margin-bottom: var(--spacing-lg); }\n\n.p-xs { padding: var(--spacing-xs); }\n.p-sm { padding: var(--spacing-sm); }\n.p-md { padding: var(--spacing-md); }\n.p-lg { padding: var(--spacing-lg); }\n\n.rounded { border-radius: var(--border-radius-full); }\n.rounded-sm { border-radius: var(--border-radius-base); }\n\n.shadow { box-shadow: var(--box-shadow); }\n.shadow-sm { box-shadow: var(--box-shadow-sm); }\n\n.bg-primary {\n background: var(--color-primary);\n color: #fff;\n}\n.bg-card {\n background: var(--color-card-bg);\n}\n\n/* Accessibility utilities */\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.min-touch-target {\n min-height: var(--min-touch-target);\n min-width: var(--min-touch-target);\n}\n\n/* Enhanced accessibility utilities */\n.visually-hidden {\n position: absolute !important;\n width: 1px !important;\n height: 1px !important;\n padding: 0 !important;\n margin: -1px !important;\n overflow: hidden !important;\n clip: rect(0, 0, 0, 0) !important;\n white-space: nowrap !important;\n border: 0 !important;\n}\n\n.visually-hidden.focusable:focus,\n.visually-hidden.focusable:active {\n position: static !important;\n width: auto !important;\n height: auto !important;\n padding: inherit !important;\n margin: inherit !important;\n overflow: visible !important;\n clip: auto !important;\n white-space: inherit !important;\n}\n\n/* Skip links utility */\n.skip-links {\n position: absolute;\n top: -100px;\n left: 0;\n z-index: 1000;\n}\n\n.skip-links a {\n position: absolute;\n left: 6px;\n top: 6px;\n padding: var(--spacing-sm);\n background: var(--color-primary);\n color: white;\n text-decoration: none;\n border-radius: var(--border-radius-base);\n}\n\n.skip-links a:focus {\n top: 6px;\n}\n\n.reduced-motion {\n animation: none !important;\n transition: none !important;\n}\n\n/* Focus management */\n.focus-ring {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\n.no-focus-ring {\n outline: none;\n}\n\n/* ARIA live regions */\n.live-region {\n position: absolute;\n left: -10000px;\n width: 1px;\n height: 1px;\n overflow: hidden;\n}\n\n/* Note: Use aria-live=\"polite\" or aria-live=\"assertive\" HTML attributes with .live-region */\n\n/* Text scaling utilities */\n.text-scale-friendly {\n line-height: 1.5;\n max-width: 70ch; /* Optimal reading length */\n}\n\n/* Text accessibility utilities */\n.text-readable {\n line-height: var(--line-height-base);\n max-width: 65ch;\n}\n\n.text-lg {\n font-size: var(--font-size-lg);\n line-height: var(--line-height-base);\n}\n\n.text-small {\n font-size: max(var(--font-size-sm), var(--min-font-size));\n line-height: var(--min-line-height);\n}\n\n.text-contrast-high {\n color: var(--color-text);\n font-weight: 600;\n}\n\n:focus-visible {\n outline: var(--focus-ring-width) solid var(--color-primary);\n outline-offset: 2px;\n box-shadow: 0 0 0 1px var(--color-background);\n}\n\n:focus:not(:focus-visible) {\n outline: none;\n box-shadow: none;\n}\n\n/* Better focus for text elements */\n.focusable-text:focus {\n background-color: rgba(124, 77, 255, 0.1);\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n border-radius: 2px;\n}\n\n/* High contrast text */\n.high-contrast {\n color: var(--color-text);\n background: var(--color-background);\n border: 1px solid var(--color-border-pale);\n}\n\n/* ===========================================\n CONSOLIDATED COMPONENT PATTERNS\n =========================================== */\n\n/* Primary Button - used by ChatWithMe, ProfileCard */\n.btn-primary {\n min-height: var(--min-touch-target);\n padding: var(--spacing-sm) var(--spacing-md);\n border: 1px solid var(--color-primary);\n border-radius: var(--border-radius-base);\n background: var(--color-primary);\n color: white;\n font-weight: 600;\n cursor: pointer;\n transition: all var(--animation-duration) ease;\n}\n\n.btn-primary:hover {\n background: color-mix(in srgb, var(--color-primary) 90%, black);\n box-shadow: 0 2px 4px rgba(124, 77, 255, 0.2);\n}\n\n.btn-primary:active {\n box-shadow: 0 1px 2px rgba(124, 77, 255, 0.2);\n}\n\n.btn-primary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n transform: none;\n}\n\n/* Action Button Focus - used by ChatWithMe, ProfileCard */\n.action-button-focus:focus,\n.action-button-focus:focus-visible {\n outline: 3px solid var(--color-primary) !important;\n outline-offset: 2px !important;\n box-shadow: 0 0 0 2px var(--color-background), 0 0 0 5px rgba(124, 77, 255, 0.25) !important;\n z-index: 1;\n}\n\n/* List Reset - used by FriendList, SocialCard, nav */\n.list-reset {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n/* Zebra Striping - used by FriendList, StuffCard tables */\n.zebra-stripe tr:nth-child(even),\n.zebra-stripe > *:nth-child(even) {\n background-color: rgba(0, 0, 0, 0.02);\n}\n\n/* Section Title - primary colored heading */\n.section-title {\n font-size: 1.25em;\n font-weight: 600;\n color: var(--color-primary);\n margin: 0;\n}\n\n/* Text Overflow - used by ProfileCard, SocialCard */\n.text-truncate {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.text-wrap-anywhere {\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n/* Loading Text - primary colored centered loading indicator */\n.loading-text {\n color: var(--color-primary);\n text-align: center;\n margin: var(--spacing-md) 0;\n}\n\n/* Centered Section - flex column with center alignment */\n.section-centered {\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* Card Section Background */\n.section-bg {\n background: var(--color-section-bg);\n border-radius: var(--border-radius-full);\n box-shadow: var(--box-shadow);\n padding: var(--spacing-md);\n}\n\n\n/* Transparent button override (for solid-ui integration) */\n.btn-transparent {\n background-color: transparent;\n}\n\n.btn-transparent:hover {\n background-color: transparent;\n}\n"],"sourceRoot":""}]);
1028
+ `, "",{"version":3,"sources":["webpack://./src/styles/utilities.css"],"names":[],"mappings":"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","sourcesContent":["/* Utility-first CSS classes for layout, spacing, and responsiveness */\n\n.actionButton {\n width: 100%;\n min-width: 180px;\n max-width: 320px;\n box-sizing: border-box;\n display: inline-block;\n}\n\n/* ===========================================\n PROFILE GRID LAYOUT\n =========================================== */\n\n.profile-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(30em, 1fr));\n gap: var(--spacing-lg);\n background: var(--color-background);\n}\n\n.profile-header,\n.profile-footer {\n grid-column: 1 / -1;\n}\n\n.center {\n justify-content: center;\n align-items: center;\n}\n\n.flex {\n display: flex;\n}\n.grid {\n display: grid;\n}\n\n/* Spacing utilities using CSS variables */\n.gap-xs { gap: var(--spacing-xs); }\n.gap-sm { gap: var(--spacing-sm); }\n.gap-md { gap: var(--spacing-md); }\n.gap-lg { gap: var(--spacing-lg); }\n.gap-xl { gap: var(--spacing-xl); }\n\n.mt-xs { margin-top: var(--spacing-xs); }\n.mt-sm { margin-top: var(--spacing-sm); }\n.mt-md { margin-top: var(--spacing-md); }\n.mt-lg { margin-top: var(--spacing-lg); }\n\n.mb-xs { margin-bottom: var(--spacing-xs); }\n.mb-sm { margin-bottom: var(--spacing-sm); }\n.mb-md { margin-bottom: var(--spacing-md); }\n.mb-lg { margin-bottom: var(--spacing-lg); }\n\n.p-xs { padding: var(--spacing-xs); }\n.p-sm { padding: var(--spacing-sm); }\n.p-md { padding: var(--spacing-md); }\n.p-lg { padding: var(--spacing-lg); }\n\n.rounded { border-radius: var(--border-radius-full); }\n.rounded-sm { border-radius: var(--border-radius-base); }\n\n.shadow { box-shadow: var(--box-shadow); }\n.shadow-sm { box-shadow: var(--box-shadow-sm); }\n\n.bg-primary {\n background: var(--color-primary);\n color: #fff;\n}\n.bg-card {\n background: var(--color-card-bg);\n}\n\n/* Accessibility utilities */\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.min-touch-target {\n min-height: var(--min-touch-target);\n min-width: var(--min-touch-target);\n}\n\n/* Enhanced accessibility utilities */\n.visually-hidden {\n position: absolute !important;\n width: 1px !important;\n height: 1px !important;\n padding: 0 !important;\n margin: -1px !important;\n overflow: hidden !important;\n clip: rect(0, 0, 0, 0) !important;\n white-space: nowrap !important;\n border: 0 !important;\n}\n\n.visually-hidden.focusable:focus,\n.visually-hidden.focusable:active {\n position: static !important;\n width: auto !important;\n height: auto !important;\n padding: inherit !important;\n margin: inherit !important;\n overflow: visible !important;\n clip: auto !important;\n white-space: inherit !important;\n}\n\n/* Skip links utility */\n.skip-links {\n position: absolute;\n top: -100px;\n left: 0;\n z-index: 1000;\n}\n\n.skip-links a {\n position: absolute;\n left: 6px;\n top: 6px;\n padding: var(--spacing-sm);\n background: var(--color-primary);\n color: white;\n text-decoration: none;\n border-radius: var(--border-radius-base);\n}\n\n.skip-links a:focus {\n top: 6px;\n}\n\n.reduced-motion {\n animation: none !important;\n transition: none !important;\n}\n\n/* Focus management */\n.focus-ring {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\n.no-focus-ring {\n outline: none;\n}\n\n.no-focus-ring:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n/* ARIA live regions */\n.live-region {\n position: absolute;\n left: -10000px;\n width: 1px;\n height: 1px;\n overflow: hidden;\n}\n\n/* Note: Use aria-live=\"polite\" or aria-live=\"assertive\" HTML attributes with .live-region */\n\n/* Text scaling utilities */\n.text-scale-friendly {\n line-height: 1.5;\n max-width: 70ch; /* Optimal reading length */\n}\n\n/* Text accessibility utilities */\n.text-readable {\n line-height: var(--line-height-base);\n max-width: 65ch;\n}\n\n.text-lg {\n font-size: var(--font-size-lg);\n line-height: var(--line-height-base);\n}\n\n.text-small {\n font-size: max(var(--font-size-sm), var(--min-font-size));\n line-height: var(--min-line-height);\n}\n\n.text-contrast-high {\n color: var(--color-text);\n font-weight: 600;\n}\n\n:focus-visible {\n outline: var(--focus-ring-width) solid var(--color-primary);\n outline-offset: 2px;\n box-shadow: 0 0 0 1px var(--color-background);\n}\n\n:focus:not(:focus-visible) {\n outline: none;\n box-shadow: none;\n}\n\n/* Better focus for text elements */\n.focusable-text:focus {\n background-color: rgba(124, 77, 255, 0.1);\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n border-radius: 2px;\n}\n\n/* High contrast text */\n.high-contrast {\n color: var(--color-text);\n background: var(--color-background);\n border: 1px solid var(--color-border-pale);\n}\n\n/* ===========================================\n CONSOLIDATED COMPONENT PATTERNS\n =========================================== */\n\n/* Primary Button - used by ChatWithMe, ProfileCard */\n.btn-primary {\n min-height: var(--min-touch-target);\n padding: var(--spacing-sm) var(--spacing-md);\n border: 1px solid var(--color-primary);\n border-radius: var(--border-radius-base);\n background: var(--color-primary);\n color: white;\n font-weight: 600;\n cursor: pointer;\n transition: all var(--animation-duration) ease;\n}\n\n.btn-primary:hover {\n background: color-mix(in srgb, var(--color-primary) 90%, black);\n box-shadow: 0 2px 4px rgba(124, 77, 255, 0.2);\n}\n\n.btn-primary:active {\n box-shadow: 0 1px 2px rgba(124, 77, 255, 0.2);\n}\n\n.btn-primary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n transform: none;\n}\n\n/* Action Button Focus - used by ChatWithMe, ProfileCard */\n.action-button-focus:focus,\n.action-button-focus:focus-visible {\n outline: 3px solid var(--color-primary) !important;\n outline-offset: 2px !important;\n box-shadow: 0 0 0 2px var(--color-background), 0 0 0 5px rgba(124, 77, 255, 0.25) !important;\n z-index: 1;\n}\n\n/* List Reset - used by FriendList, SocialCard, nav */\n.list-reset {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n/* Zebra Striping - used by FriendList, StuffCard tables */\n.zebra-stripe tr:nth-child(even),\n.zebra-stripe > *:nth-child(even) {\n background-color: rgba(0, 0, 0, 0.02);\n}\n\n/* Section Title - primary colored heading */\n.section-title {\n font-size: 1.25em;\n font-weight: 600;\n color: var(--color-primary);\n margin: 0;\n}\n\n/* Text Overflow - used by ProfileCard, SocialCard */\n.text-truncate {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.text-wrap-anywhere {\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n/* Loading Text - primary colored centered loading indicator */\n.loading-text {\n color: var(--color-primary);\n text-align: center;\n margin: var(--spacing-md) 0;\n}\n\n/* Centered Section - flex column with center alignment */\n.section-centered {\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* Card Section Background */\n.section-bg {\n background: var(--color-section-bg);\n border-radius: var(--border-radius-full);\n box-shadow: var(--box-shadow);\n padding: var(--spacing-md);\n}\n\n\n/* Transparent button override (for solid-ui integration) */\n.btn-transparent {\n background-color: transparent;\n}\n\n.btn-transparent:hover {\n background-color: transparent;\n}\n"],"sourceRoot":""}]);
1009
1029
  // Exports
1010
1030
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
1011
1031
 
@@ -5190,27 +5210,26 @@ const socialMedia_namespaceObject = "@prefix rdf: <http://www.w3.org/1999/02/22-
5190
5210
  const baseUri = 'https://solidos.github.io/profile-pane/src/ontology/';
5191
5211
  function renderForm(div, subject, // Represents the RDF that fills the form
5192
5212
  formSource, // The imported form Turtle source
5193
- formName, // The name of the form file (e.g., 'profileForm.ttl')
5194
- store, dom, editableProfile) {
5213
+ formName, // The name of the form file (e.g., 'socialMedia.ttl')
5214
+ store, dom, editableProfile, whichForm) {
5195
5215
  // --- Form resource setup ---
5196
5216
  const formUri = baseUri + formName; // Full URI to the form file
5197
- const formThis = (0,external_rdflib_.Namespace)(formUri + '#')('this'); // NamedNode for #this in the form
5198
- loadDocument(formName, formSource, store);
5199
- div.setAttribute('data-testid', 'profile-editor');
5200
- div.classList.add('profile-form');
5217
+ const exactForm = whichForm || 'this'; // If there are more 'a ui:Form' elements in a form file
5218
+ const formThis = (0,external_rdflib_.Namespace)(formUri + '#')(exactForm); // NamedNode for #this in the form
5219
+ loadDocument(store, formSource, formName, formUri);
5201
5220
  external_UI_.widgets.appendForm(dom, div, {}, subject, formThis, editableProfile, (ok, mes) => {
5202
5221
  if (!ok)
5203
5222
  external_UI_.widgets.errorMessageBlock(dom, mes);
5204
5223
  });
5205
5224
  } // renderForm
5206
5225
  // we need to load into the store some additional information about Social Media accounts
5207
- function loadDocument(documentName, documentSource, store) {
5208
- const documentUri = baseUri + documentName; // Full URI to the file
5209
- const document = (0,external_rdflib_.sym)(documentUri); // rdflib NamedNode for the document
5226
+ function loadDocument(store, documentSource, documentName, documentURI) {
5227
+ const finalDocumentUri = documentURI || baseUri + documentName; // Full URI to the file
5228
+ const document = (0,external_rdflib_.sym)(finalDocumentUri); // rdflib NamedNode for the document
5210
5229
  if (!store.holds(undefined, undefined, undefined, document)) {
5211
5230
  // we are using the social media form because it contains the information we need
5212
5231
  // the form can be used for both use cases: create UI for edit and render UI for display
5213
- (0,external_rdflib_.parse)(documentSource, store, documentUri, 'text/turtle', () => null); // Load doc directly
5232
+ (0,external_rdflib_.parse)(documentSource, store, finalDocumentUri, 'text/turtle', () => null); // Load doc directly
5214
5233
  }
5215
5234
  }
5216
5235
 
@@ -5291,7 +5310,7 @@ function presentSocial(subject, store) {
5291
5310
  };
5292
5311
  }
5293
5312
  // we need to load the social media accounts ontology to be able to query all data needed
5294
- loadDocument(socialMediaFormName, socialMedia_namespaceObject, store);
5313
+ loadDocument(store, socialMedia_namespaceObject, socialMediaFormName);
5295
5314
  const accountNodes = store.each(subject, external_UI_.ns.foaf('account'));
5296
5315
  const accountThings = accountNodes.flatMap(node => SocialPresenter_expandRdfList(store, node));
5297
5316
  if (!accountThings.length)
@@ -6007,21 +6026,30 @@ function EditFriendsSection(context, me, editableProfile, profile) {
6007
6026
  header.appendChild(heading);
6008
6027
  section.appendChild(header);
6009
6028
  const comment1 = context.dom.createElement('p');
6029
+ comment1.id = 'edit-profile-friends-description';
6010
6030
  comment1.classList.add('p-md');
6011
6031
  comment1.textContent = 'This is your public social network. Only put people here to whom you are happy to be publicly connected. (You can always keep private track of friends and family in your contacts.)';
6012
6032
  section.appendChild(comment1);
6033
+ let comment2 = null;
6013
6034
  if (editableProfile) {
6014
- const comment2 = context.dom.createElement('p');
6035
+ comment2 = context.dom.createElement('p');
6036
+ comment2.id = 'edit-profile-friends-help';
6015
6037
  comment2.classList.add('p-md');
6016
6038
  comment2.textContent = 'Drag people onto the target below to add people.';
6017
6039
  section.appendChild(comment2);
6018
6040
  }
6019
- section.appendChild(external_UI_.widgets.attachmentList(context.dom, me, section, {
6041
+ const attachmentList = external_UI_.widgets.attachmentList(context.dom, me, section, {
6020
6042
  doc: profile,
6021
6043
  modify: !!editableProfile,
6022
6044
  predicate: external_UI_.ns.foaf('knows'),
6023
6045
  noun: 'friend'
6024
- }));
6046
+ });
6047
+ const descriptions = [comment1.id];
6048
+ if (comment2 === null || comment2 === void 0 ? void 0 : comment2.id) {
6049
+ descriptions.push(comment2.id);
6050
+ }
6051
+ attachmentList.setAttribute('aria-describedby', descriptions.join(' '));
6052
+ section.appendChild(attachmentList);
6025
6053
  return section;
6026
6054
  }
6027
6055
 
@@ -6032,8 +6060,9 @@ function EditFriendsSection(context, me, editableProfile, profile) {
6032
6060
  const EditSocialCard_socialMediaFormName = 'socialMedia.ttl'; // The name of the form file
6033
6061
  function EditSocialSection(context, me, editableProfile, store) {
6034
6062
  const section = context.dom.createElement('section');
6063
+ section.setAttribute('data-testid', 'edit-social-section');
6035
6064
  section.setAttribute('aria-labelledby', 'edit-profile-social-heading');
6036
- section.classList.add('profileSection', 'section-bg');
6065
+ section.classList.add('profileSection', 'section-bg', 'profile-form');
6037
6066
  const header = context.dom.createElement('header');
6038
6067
  header.classList.add('text-center', 'mb-md');
6039
6068
  const heading = context.dom.createElement('h2');
@@ -6074,21 +6103,30 @@ function EditProfileCommunitiesSection(context, me, editableProfile, profile) {
6074
6103
  header.appendChild(heading);
6075
6104
  section.appendChild(header);
6076
6105
  const comment1 = context.dom.createElement('p');
6106
+ comment1.id = 'edit-profile-communities-description';
6077
6107
  comment1.classList.add('p-md');
6078
6108
  comment1.textContent = 'These are organizations and projects whose stuff you share';
6079
6109
  section.appendChild(comment1);
6110
+ let comment2 = null;
6080
6111
  if (editableProfile) {
6081
- const comment2 = context.dom.createElement('p');
6112
+ comment2 = context.dom.createElement('p');
6113
+ comment2.id = 'edit-profile-communities-help';
6082
6114
  comment2.classList.add('p-md');
6083
6115
  comment2.textContent = 'Drag organizations onto the target below to add organizations.';
6084
6116
  section.appendChild(comment2);
6085
6117
  }
6086
- section.appendChild(external_UI_.widgets.attachmentList(context.dom, me, section, {
6118
+ const attachmentList = external_UI_.widgets.attachmentList(context.dom, me, section, {
6087
6119
  doc: profile,
6088
6120
  modify: !!editableProfile,
6089
6121
  predicate: external_UI_.ns.solid('community'),
6090
6122
  noun: 'community'
6091
- }));
6123
+ });
6124
+ const descriptions = [comment1.id];
6125
+ if (comment2 === null || comment2 === void 0 ? void 0 : comment2.id) {
6126
+ descriptions.push(comment2.id);
6127
+ }
6128
+ attachmentList.setAttribute('aria-describedby', descriptions.join(' '));
6129
+ section.appendChild(attachmentList);
6092
6130
  return section;
6093
6131
  }
6094
6132
 
@@ -6130,8 +6168,9 @@ const resumeForm_namespaceObject = "@prefix os: <http://www.w3.org/2000/10/swap/
6130
6168
  const resumeFormName = 'resumeForm.ttl'; // The name of the form file
6131
6169
  function EditCVSection(context, me, editableProfile, store) {
6132
6170
  const section = context.dom.createElement('section');
6171
+ section.setAttribute('data-testid', 'edit-cv-section');
6133
6172
  section.setAttribute('aria-labelledby', 'edit-profile-cv-heading');
6134
- section.classList.add('profileSection', 'section-bg');
6173
+ section.classList.add('profileSection', 'section-bg', 'profile-form');
6135
6174
  const header = context.dom.createElement('header');
6136
6175
  header.classList.add('text-center', 'mb-md');
6137
6176
  const heading = context.dom.createElement('h2');
@@ -6165,8 +6204,9 @@ const otherPreferencesForm_namespaceObject = "@prefix os: <http://www.w3.org/200
6165
6204
  const otherPreferencesFormName = 'otherPreferencesForm.ttl'; // The name of the form file
6166
6205
  function EditOtherPreferencesSection(context, me, editableProfile, store) {
6167
6206
  const section = context.dom.createElement('section');
6207
+ section.setAttribute('data-testid', 'edit-other-preferences-section');
6168
6208
  section.setAttribute('aria-labelledby', 'edit-profile-other-preferences-heading');
6169
- section.classList.add('profileSection', 'section-bg');
6209
+ section.classList.add('profileSection', 'section-bg', 'profile-form');
6170
6210
  const header = context.dom.createElement('header');
6171
6211
  header.classList.add('text-center', 'mb-md');
6172
6212
  const heading = context.dom.createElement('h2');
@@ -6216,13 +6256,25 @@ const editProfileView = {
6216
6256
  // Use <main> for the main content area, styled as a grid like ProfileView
6217
6257
  const main = dom.createElement('main');
6218
6258
  main.setAttribute('id', 'profile-edit-main-content');
6219
- main.classList.add('profile-grid');
6259
+ main.setAttribute('aria-busy', 'true');
6260
+ main.setAttribute('tabindex', '-1');
6261
+ main.classList.add('profile-grid', 'no-focus-ring');
6262
+ const mainHeading = dom.createElement('h1');
6263
+ mainHeading.classList.add('visually-hidden');
6264
+ mainHeading.textContent = 'Edit Profile';
6265
+ main.appendChild(mainHeading);
6220
6266
  div.appendChild(main);
6221
6267
  // Use <aside> for the status area
6222
6268
  const statusArea = dom.createElement('aside');
6223
6269
  statusArea.classList.add('p-sm');
6270
+ statusArea.setAttribute('role', 'status');
6224
6271
  statusArea.setAttribute('aria-live', 'polite');
6225
- div.appendChild(statusArea);
6272
+ statusArea.setAttribute('aria-atomic', 'true');
6273
+ const ensureStatusArea = () => {
6274
+ if (!statusArea.isConnected) {
6275
+ div.appendChild(statusArea);
6276
+ }
6277
+ };
6226
6278
  const profileContext = {
6227
6279
  dom: dom,
6228
6280
  div: main,
@@ -6243,24 +6295,29 @@ const editProfileView = {
6243
6295
  editableProfile = profile;
6244
6296
  }
6245
6297
  else {
6298
+ ensureStatusArea();
6246
6299
  statusArea.appendChild(external_UI_.widgets.errorMessageBlock(dom, `⚠️ Your profile ${profile} is not editable, so we cannot do much here.`, 'straw'));
6247
6300
  return;
6248
6301
  }
6249
6302
  // Render each section as a card with consistent classes
6250
6303
  // Your contact information Section
6251
6304
  main.appendChild(EditContactsSection(context, me));
6252
- // Social Accounts Section
6253
- main.appendChild(EditSocialSection(context, me, editableProfile, store));
6254
6305
  // Resume Section
6255
6306
  main.appendChild(EditCVSection(context, me, editableProfile, store));
6307
+ // Social Accounts Section
6308
+ main.appendChild(EditSocialSection(context, me, editableProfile, store));
6256
6309
  // Other preferences Section
6257
6310
  main.appendChild(EditOtherPreferencesSection(context, me, editableProfile, store));
6258
6311
  // People you know Section
6259
6312
  main.appendChild(EditFriendsSection(context, me, editableProfile, profile));
6260
6313
  // Communities you participate in Section
6261
6314
  main.appendChild(EditProfileCommunitiesSection(context, me, editableProfile, profile));
6315
+ main.setAttribute('aria-busy', 'false');
6316
+ main.focus();
6262
6317
  }).catch(error => {
6318
+ ensureStatusArea();
6263
6319
  statusArea.appendChild(external_UI_.widgets.errorMessageBlock(dom, error, '#fee'));
6320
+ main.setAttribute('aria-busy', 'false');
6264
6321
  });
6265
6322
  return div;
6266
6323
  }