solid-panes
Version:
Solid-compatible Panes: applets and views for the mashlib and databrowser
1 lines • 1.17 MB
JavaScript
!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n(require("UI"),require("SolidLogic"),require("rdflib")):"function"==typeof define&&define.amd?define(["UI","SolidLogic","rdflib"],n):"object"==typeof exports?exports.SolidPanes=n(require("UI"),require("SolidLogic"),require("rdflib")):e.SolidPanes=n(e.UI,e.SolidLogic,e.rdflib)}(this,(e,n,t)=>(()=>{var i={6305(e){e.exports&&(e.exports=function(e,n){if(void 0===t)var t=n.dom;var i=t.querySelectorAll(e),a={init:function(e,n){this.counter=0,this.el=e,this.$items=e.querySelectorAll("figure"),this.numItems=this.$items.length,(n=n||{}).auto=n.auto||!1,this.opts={auto:void 0!==n.auto&&n.auto,speed:void 0===n.auto.speed?1500:n.auto.speed,pauseOnHover:void 0!==n.auto.pauseOnHover&&n.auto.pauseOnHover,fullScreen:void 0!==n.fullScreen&&n.fullScreen,swipe:void 0!==n.swipe&&n.swipe},this.$items[0].classList.add("bss-show"),this.injectControls(e),this.addEventListeners(e),this.opts.auto&&this.autoCycle(this.el,this.opts.speed,this.opts.pauseOnHover),this.opts.fullScreen&&this.addFullScreen(this.el),this.opts.swipe&&this.addSwipe(this.el)},showCurrent:function(e){this.counter=e>0?this.counter+1===this.numItems?0:this.counter+1:this.counter-1<0?this.numItems-1:this.counter-1,[].forEach.call(this.$items,function(e){e.classList.remove("bss-show")}),this.$items[this.counter].classList.add("bss-show")},injectControls:function(e){var n=t.createElement("span"),i=t.createElement("span"),a=t.createDocumentFragment();n.classList.add("bss-prev"),i.classList.add("bss-next"),n.innerHTML="«",i.innerHTML="»",a.appendChild(n),a.appendChild(i),e.appendChild(a)},addEventListeners:function(e){var n=this;e.querySelector(".bss-next").addEventListener("click",function(){n.showCurrent(1)},!1),e.querySelector(".bss-prev").addEventListener("click",function(){n.showCurrent(-1)},!1),e.onkeydown=function(e){37===(e=e||window.event).keyCode?n.showCurrent(-1):39===e.keyCode&&n.showCurrent(1)}},autoCycle:function(e,n,t){var i=this,a=window.setInterval(function(){i.showCurrent(1)},n);t&&(e.addEventListener("mouseover",function(){a=clearInterval(a)},!1),e.addEventListener("mouseout",function(){a=window.setInterval(function(){i.showCurrent(1)},n)},!1))},addFullScreen:function(e){var n=this,i=t.createElement("span");i.classList.add("bss-fullscreen"),e.appendChild(i),e.querySelector(".bss-fullscreen").addEventListener("click",function(){n.toggleFullScreen(e)},!1)},addSwipe:function(e){var n=this,t=new Hammer(e);t.on("swiperight",function(e){n.showCurrent(-1)}),t.on("swipeleft",function(e){n.showCurrent(1)})},toggleFullScreen:function(e){t.fullscreenElement||t.mozFullScreenElement||t.webkitFullscreenElement||t.msFullscreenElement?t.exitFullscreen?t.exitFullscreen():t.msExitFullscreen?t.msExitFullscreen():t.mozCancelFullScreen?t.mozCancelFullScreen():t.webkitExitFullscreen&&t.webkitExitFullscreen():t.documentElement.requestFullscreen?e.requestFullscreen():t.documentElement.msRequestFullscreen?e.msRequestFullscreen():t.documentElement.mozRequestFullScreen?e.mozRequestFullScreen():t.documentElement.webkitRequestFullscreen&&e.webkitRequestFullscreen(e.ALLOW_KEYBOARD_INPUT)}};[].forEach.call(i,function(e){Object.create(a).init(e,n)})})},701(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.findChat=s,n.getChat=async function(e,n=!0){const{me:t,chatContainer:l,exists:c}=await s(e);if(c)return new o.NamedNode(l.value+r.longChatPane.CHAT_LOCATION_IN_CONTAINER);if(n){const n=await async function(e,n){const t=await r.longChatPane.mintNew({session:{store:a.store}},{me:n,newBase:e.value});return t.newInstance}(l,t);return await async function(e,n){await a.store.fetcher.load(e.doc());const t=a.store.any(e,i.ns.ldp("inbox"),void 0,e.doc());if(!t)throw new Error(`Invitee inbox not found! ${e.value}`);const o=`\n<> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;\n${i.ns.rdf("seeAlso")} <${n.value}> . \n `,r=await a.store.fetcher.webOperation("POST",t.value,{data:o,contentType:"text/turtle"});if(!r.headers.get("location"))throw new Error(`Invite sending returned a ${r.status}`)}(e,n),await async function(e,n,t){await a.store.fetcher.load(e);const i=a.store.any(e,new o.NamedNode("http://www.iana.org/assignments/link-relations/acl"));if(!i)throw new Error("Chat ACL doc not found!");const r=`\n@prefix acl: <http://www.w3.org/ns/auth/acl#>.\n<#owner>\n a acl:Authorization;\n acl:agent <${n.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Write, acl:Control.\n<#invitee>\n a acl:Authorization;\n acl:agent <${t.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Append.\n`;await a.store.fetcher.webOperation("PUT",i.value,{data:r,contentType:"text/turtle"})}(l,t,e),await async function(e,n){const t=a.store.any(n,i.ns.solid("privateTypeIndex"));if(!t)throw new Error("Private type index not found!");await a.store.fetcher.load(t);const r=i.widgets.newThing(t),s=[(0,o.st)(r,i.ns.rdf("type"),i.ns.solid("TypeRegistration"),t.doc()),(0,o.st)(r,i.ns.solid("forClass"),i.ns.meeting("LongChat"),t.doc()),(0,o.st)(r,i.ns.solid("instance"),e,t.doc())];await new Promise((e,n)=>{a.store.updater.update([],s,function(t,i,a){i?e():n(new Error(a))})})}(n,t),n}throw new Error("Chat does not exist and createIfMissing is false")};var i=t(9426),a=t(5663),o=t(5491),r=t(8055);async function s(e){const n=await async function(){const e=a.authn.currentUser();if(null===e)throw new Error("Current user not found! Not logged in?");return await a.store.fetcher.load(e.doc()),e}(),t=await async function(e){const n=a.store.any(e,i.ns.space("storage"),void 0,e.doc());if(!n)throw new Error("Current user pod root not found!");return n}(n),s=function(e,n){const t=new URL(`IndividualChats/${new URL(e.value).host}/`,n.value).toString();return new o.NamedNode(t)}(e,t);let l=!0;try{await a.store.fetcher.load(new o.NamedNode(s.value+r.longChatPane.CHAT_LOCATION_IN_CONTAINER))}catch(e){l=!1}return{me:n,chatContainer:s,exists:l}}},8055(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.longChatPane=void 0;var i=t(5663),a=r(t(9426)),o=r(t(5491));function r(e,n){if("function"==typeof WeakMap)var t=new WeakMap,i=new WeakMap;return(r=function(e,n){if(!n&&e&&e.__esModule)return e;var a,o,r={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return r;if(a=n?i:t){if(a.has(e))return a.get(e);a.set(e,r)}for(const n in e)"default"!==n&&{}.hasOwnProperty.call(e,n)&&((o=(a=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,n))&&(o.get||o.set)?a(r,n,o):r[n]=e[n]);return r})(e,n)}const s=a.ns,l=s.meeting("LongChat"),c="index.ttl#this",u=a.style.sidebarComponentStyle||" padding: 0.5em; width: 100%;",d=a.style.sidebarStyle||"overflow-x: auto; overflow-y: auto; border-radius: 1em; border: 0.1em solid white;";n.longChatPane={CHAT_LOCATION_IN_CONTAINER:c,icon:a.icons.iconBase+"noun_1689339.svg",name:"long chat",label:function(e,n){const t=n.session.store;return t.holds(e,s.rdf("type"),s.meeting("LongChat"))?"Chat channnel":t.holds(e,s.rdf("type"),s.sioc("Thread"))?"Thread":t.any(e,s.sioc("content"))&&t.any(e,s.dct("created"))?"message":null},mintClass:l,mintNew:function(e,n){const t=e.session.store,i=t.updater;if(n.me&&!n.me.uri)throw new Error("chat mintNew: Invalid userid "+n.me);const a=n.newInstance=n.newInstance||t.sym(n.newBase+c),o=a.doc();t.add(a,s.rdf("type"),s.meeting("LongChat"),o),t.add(a,s.dc("title"),"Chat channel",o),t.add(a,s.dc("created"),new Date,o),n.me&&t.add(a,s.dc("author"),n.me,o);const r=(e,n,t)=>`\n @prefix : <#>.\n @prefix acl: <http://www.w3.org/ns/auth/acl#>.\n @prefix foaf: <http://xmlns.com/foaf/0.1/>.\n @prefix lon: <./${n}>.\n\n :ControlReadWrite\n a acl:Authorization;\n acl:accessTo lon:;\n acl:agent <${e.uri}>;\n acl:default lon:;\n acl:mode acl:Control, acl:Read, acl:Write.\n :Read\n a acl:Authorization;\n acl:accessTo lon:;\n acl:agentClass foaf:Agent;\n acl:default lon:;\n acl:mode acl:Read.\n :Read${t}\n a acl:Authorization;\n acl:accessTo lon:;\n acl:agentClass acl:AuthenticatedAgent;\n acl:default lon:;\n acl:mode acl:Read, acl:${t}.`;return new Promise(function(e,a){i.put(o,t.statementsMatching(void 0,void 0,void 0,o),"text/turtle",function(t,i,o){i?e(n):a(new Error("FAILED to save new chat channel at: "+t+" : "+o))}).then(e=>new Promise((e,i)=>{n.me&&(t.fetcher.webOperation("PUT",n.newBase+".acl",{data:r(n.me,"","Append"),contentType:"text/turtle"}),t.fetcher.webOperation("PUT",n.newBase+"index.ttl.acl",{data:r(n.me,"index.ttl","Write"),contentType:"text/turtle"})),e(n)}))})},render:function(e,n,t){const r=n.dom,c=n.session.store,p=c.sym("https://solid.github.io/solid-panes/longCharPane/preferencesForm.ttl#this"),m=p.doc();c.holds(void 0,void 0,void 0,m)||o.parse('\n @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.\n @prefix solid: <http://www.w3.org/ns/solid/terms#>.\n @prefix ui: <http://www.w3.org/ns/ui#>.\n @prefix : <#>.\n\n :this\n <http://purl.org/dc/elements/1.1/title> "Chat preferences" ;\n a ui:Form ;\n ui:parts ( :colorizeByAuthor :expandImagesInline :newestFirst :inlineImageHeightEms\n :shiftEnterSendsMessage :authorDateOnLeft :showDeletedMessages).\n\n :colorizeByAuthor a ui:TristateField; ui:property solid:colorizeByAuthor;\n ui:label "Color user input by user".\n\n :expandImagesInline a ui:TristateField; ui:property solid:expandImagesInline;\n ui:label "Expand image URLs inline".\n\n :newestFirst a ui:TristateField; ui:property solid:newestFirst;\n ui:label "Newest messages at the top".\n\n :inlineImageHeightEms a ui:IntegerField; ui:property solid:inlineImageHeightEms;\n ui:label "Inline image height (lines)".\n\n :shiftEnterSendsMessage a ui:TristateField; ui:property solid:shiftEnterSendsMessage;\n ui:label "Shift-Enter sends message".\n\n :authorDateOnLeft a ui:TristateField; ui:property solid:authorDateOnLeft;\n ui:label "Author & date of message on left".\n\n :showDeletedMessages a ui:TristateField; ui:property solid:showDeletedMessages;\n ui:label "Show placeholders for deleted messages".\n',c,m.uri,"text/turtle");const f=c.statementsMatching(null,s.ui.property,null,m).map(e=>e.object);function h(e){const t=a.widgets.button(n.dom,a.icons.iconBase+"noun_1180156.svg","close",function(){e.parentNode.removeChild(e)});return t.style.float="right",t.style.margin="0.7em",delete t.style.backgroundColor,t}function g(e,t){const o=r.createElement("div"),s=i.authn.currentUser(),l={div:o,dom:r,noun:t,statusArea:o,me:s,refreshTarget:e},c=[n.session.paneRegistry.byName("chat")];return a.create.newThingUI(l,n,c),o}let b,A=null;let v=e,y=null,w=null;if(c.holds(e,s.rdf("type"),s.meeting("LongChat")))console.log("@@@ Chat channnel");else if(c.holds(e,s.rdf("type"),s.sioc("Thread"))){console.log("Thread is subject "+e.uri),w=e;const n=c.the(null,s.sioc("has_reply"),w,w.doc());if(!n)throw new Error("Thread has no root message "+w);if(v=c.any(null,s.wf("message"),n),!v)throw new Error("Thread root has no link to chatChannel")}else if(c.any(e,s.sioc("content"))&&c.any(e,s.dct("created"))&&(console.log("message is subject "+e.uri),y=e,v=c.any(null,s.wf("message"),y),!v))throw new Error("Message has no link to chatChannel");const x=r.createElement("div"),C="20cm",E=x.appendChild(r.createElement("table"));E.style.maxHeight='12"';const k=E.appendChild(r.createElement("tr")),B=k.appendChild(r.createElement("td")),S=k.appendChild(r.createElement("td")),T=k.appendChild(r.createElement("td")),P=k.appendChild(r.createElement("td")),F=E.appendChild(r.createElement("tr"));B.style=d,B.style.paddingRight="1em",T.style=d,T.style.paddingLeft="1em",P.style=d,P.style.paddingLeft="1em",F.appendChild(r.createElement("td"));const L=F.appendChild(r.createElement("td"));F.appendChild(r.createElement("td"));const N=a.widgets.button(r,a.icons.iconBase+"noun_339237.svg","participants ...");L.appendChild(N),N.addEventListener("click",function(e){if(!b){b=r.createElement("div"),b.style=u,b.style.maxHeight=C,b.appendChild(h(b));const e=i.authn.currentUser();e||alert("Should be logeed in for partipants panel"),a.pad.manageParticipation(r,b,v.doc(),v,e,{})}B.contains(b)?(b.parentNode.removeChild(b),b=null):B.appendChild(b)});const I=a.widgets.button(r,a.icons.iconBase+"noun_1689339.svg","List of other chats ...");L.appendChild(I),I.addEventListener("click",async function(e){A||(A=r.createElement("div"),A.style=u,A.style.maxHeight=C,A.appendChild(h(A)),A.appendChild(await async function(e,n){const t=r.createElement("div"),i={dom:r,div:t,noun:n};return await a.login.registrationList(i,{public:!0,private:!0,type:e}),t.appendChild(g(t,n)),t}(s.meeting("LongChat"),"chat"))),B.contains(A)?A.parentNode.removeChild(A):B.appendChild(A)});let D=null;const _=a.widgets.button(r,a.icons.iconBase+"noun_344563.svg","Setting ...");L.appendChild(_),_.style.float="right",_.addEventListener("click",async function(e){D||(D=await async function(e){const{dom:n,noun:t}=e,o=n.createElement("div");o.appendChild(h(o)),o.style=u,o.style.minWidth="25em",o.style.maxHeight=C;const r=o.appendChild(n.createElement("table")),s=r.appendChild(n.createElement("tr")),d=r.appendChild(n.createElement("tr")),m=i.authn.currentUser();return m&&(await a.login.registrationControl({noun:t,me:m,statusArea:d,dom:n,div:s},v,l),console.log("Registration control finsished."),o.appendChild(a.preferences.renderPreferencesForm(v,l,p,{noun:t,me:m,statusArea:d,div:o,dom:n,kb:c}))),o}({dom:r,noun:"chat room"})),P.contains(D)?(D.parentNode.removeChild(D),D=null):P.appendChild(D)}),x.setAttribute("class","chatPane");const R={infinite:!0},O={noun:"chat room",div:x,dom:r};async function M(e,n){console.log("@@@@ showThread thread "+e);const t={};t.thread=e,t.includeRemoveButton=!0,t.authorDateOnLeft=n.authorDateOnLeft,t.newestFirst=n.newestFirst,T.innerHTML="",console.log("Options for showThread message Area",t);const i=await a.infiniteMessageArea(r,c,v,t);i.style.resize="both",i.style.overflow="auto",i.style.maxHeight=C,T.appendChild(i)}return O.me=i.authn.currentUser(),async function(){let e;try{e=await a.preferences.getPreferencesForClass(v,l,f,O)}catch(e){a.widgets.complain(O,e)}for(const n in e)R[n.split("#")[1]]=e[n];y&&(R.selectedMessage=y),t.solo&&(R.solo=!0),w?R.thread=w:R.showThread=M;const n=await a.infiniteMessageArea(r,c,v,R);n.style.resize="both",n.style.overflow="auto",n.style.maxHeight=C,S.appendChild(n)}().then(console.log("async - chat pane built")),x}}},7052(e,n,t){"use strict";Object.defineProperty(n,"Pq",{enumerable:!0,get:function(){return a.longChatPane}}),Object.defineProperty(n,"bz",{enumerable:!0,get:function(){return i.shortChatPane}});var i=t(6303),a=t(8055),o=t(701)},6303(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.shortChatPane=void 0;var i=t(5663),a=function(e,n){if("function"==typeof WeakMap)var t=new WeakMap,i=new WeakMap;return function(e,n){if(!n&&e&&e.__esModule)return e;var a,o,r={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return r;if(a=n?i:t){if(a.has(e))return a.get(e);a.set(e,r)}for(const n in e)"default"!==n&&{}.hasOwnProperty.call(e,n)&&((o=(a=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,n))&&(o.get||o.set)?a(r,n,o):r[n]=e[n]);return r}(e,n)}(t(9426));const o=a.ns;n.shortChatPane={icon:a.icons.iconBase+"noun_346319.svg",name:"chat",audience:[o.solid("PowerUser")],label:function(e,n){const t=n.session.store,i=t.each(e,o.wf("message")).length;return i>0?"Chat ("+i+")":t.holds(e,o.rdf("type"),o.meeting("Chat"))?"Meeting chat":t.holds(void 0,o.rdf("type"),o.foaf("ChatChannel"),e)?"IRC log":null},mintClass:o.meeting("Chat"),mintNew:function(e,n){if(!confirm("short Chat is deprecated in favor of long Chat.\nEmbedded chat for comments and existing short Chats will work.\nYou can report any issues at https://github.com/SolidOS/chat-pane ?\n\nDo you really want to create a new deprecated short Chat?"))return;const t=e.session.store,i=t.updater;if(n.me&&!n.me.uri)throw new Error("chat mintNew: Invalid userid "+n.me);const a=n.newInstance=n.newInstance||t.sym(n.newBase+"index.ttl#this"),r=a.doc();return t.add(a,o.rdf("type"),o.meeting("Chat"),r),t.add(a,o.dc("title"),"Chat",r),t.add(a,o.dc("created"),new Date,r),n.me&&t.add(a,o.dc("author"),n.me,r),new Promise(function(e,a){i.put(r,t.statementsMatching(void 0,void 0,void 0,r),"text/turtle",function(t,i,o){i?e(n):a(new Error("FAILED to save new tool at: "+t+" : "+o))})})},render:function(e,n){const t=n.session.store,r=n.dom,s=r.createElement("div");s.setAttribute("class","chatPane");const l={};let c;if(t.holds(e,o.rdf("type"),o.meeting("Chat")))c=e.doc();else if(t.any(e,a.ns.wf("message")))c=i.store.any(e,a.ns.wf("message")).doc();else if(t.holds(void 0,o.rdf("type"),o.foaf("ChatChannel"),e)||t.holds(e,o.rdf("type"),o.foaf("ChatChannel"))){const n=function(){const e=new $rdf.Query("IRC log entries"),n=[];return["chan","msg","date","list","pred","creator","content"].forEach(function(t){e.vars.push(n[t]=$rdf.variable(t))}),e.pat.add(n.chan,o.foaf("chatEventList"),n.list),e.pat.add(n.list,n.pred,n.msg),e.pat.add(n.msg,o.dc("date"),n.date),e.pat.add(n.msg,o.dc("creator"),n.creator),e.pat.add(n.msg,o.dc("description"),n.content),e};c=e.doc(),l.query=n()}else!function(e,n){const t=r.createElement("pre");t.setAttribute("style","background-color: "+n||0),s.appendChild(t),t.appendChild(r.createTextNode(e))}("Unknown chat type");return s.appendChild(a.messageArea(r,t,e,c,l)),t.updater.addDownstreamChangeListener(c,function(){a.widgets.refreshTree(s)}),s}}},3955(e,n,t){var i;globalThis,i=(e,n,t)=>(()=>{"use strict";var i={903(e,n,t){t.d(n,{A:()=>p});var i=t(354),a=t.n(i),o=t(314),r=t.n(o),s=t(417),l=t.n(s),c=new URL(t(102),t.b),u=r()(a()),d=l()(c);u.push([e.id,`/* Focus indicator for keyboard navigation */\n.contactPane table tr[tabindex="0"]:focus {\n outline: var(--focus-ring-width) solid var(--color-primary);\n outline-offset: 2px;\n background: var(--color-info-bg);\n}\n/* contactsPane styles — extracted from inline styles in contactsPane.js */\n/* Uses CSS custom properties from the global stylesheet (dev-global.css / mashlib) */\n\n/* ── Layout: Three-column browser ────────────────────────────── */\n\n.contactPane .peopleSection .selected {\n background-color: var(--color-info-bg) !important;\n}\n\n.contactPane .detailSection,\n.contactPane .addressBookSection {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n flex: 1 1 0; /* allow it to grow but not force wrap */\n min-width: 300px;\n box-sizing: border-box;\n background: var(--color-section-bg);\n}\n\n.contactPane .detailsSectionContent {\n flex: 1 1 auto;\n min-height: 200px;\n padding: var(--spacing-lg);\n max-width: 900px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.contactPane .detailsSectionContent--wide {\n max-width: 900px;\n}\n\n.contactPane .cardFooter {\n display: flex;\n flex-wrap: nowrap; /* keep buttons inline */\n align-items: center; /* vertical centering if varied heights */\n gap: var(--spacing-xs);\n padding-top: var(--spacing-md);\n margin-top: var(--spacing-md);\n}\n\n.contactPane .detailsSectionContent {\n margin: 0;\n}\n\n/* ── Contact type chooser ───────────────────────────────────── */\n\n.contactPane .contactTypeChooser {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-sm);\n max-width: 360px;\n}\n\n.contactPane .contactTypeChooser h3 {\n margin: 0 0 var(--spacing-xs) 0;\n font-size: var(--font-size-lg);\n}\n\n.contactPane .contactTypeSelect {\n height: var(--min-touch-target);\n border: 1px solid var(--color-border-pale);\n border-radius: var(--border-radius-base);\n padding: 0 var(--spacing-sm);\n font-size: var(--font-size-sm);\n background: var(--color-section-bg);\n}\n\n/* ── Search ──────────────────────────────────────────────────── */\n\n.contactPane .allGroupsButton {\n border-radius: var(--border-radius-full) !important;\n /* existing styles */\n}\n/* wrapper to position clear icon/button */\n.contactPane .searchDiv {\n position: relative;\n}\n\n.contactPane .searchInput {\n height: var(--min-touch-target);\n border: 1px solid var(--color-border-pale);\n background-color: var(--color-section-bg);\n background-image: url(${d});\n background-repeat: no-repeat;\n background-position: 8px center;\n background-size: 20px 20px;\n border-radius: var(--border-radius-base);\n padding: 0 var(--spacing-sm) 0 34px;\n font-size: var(--font-size-base);\n width: 100%;\n box-sizing: border-box;\n}\n\n/* clear button inside search input */\n.contactPane .searchClearButton {\n position: absolute;\n right: var(--spacing-sm);\n top: 50%;\n transform: translateY(-50%);\n border: none;\n background: transparent;\n font-size: var(--font-size-base);\n line-height: 1;\n padding: 0;\n cursor: pointer;\n color: var(--color-text-muted);\n /* visibility is controlled via the generic \`.hidden\` utility class */\n display: block;\n}\n.contactPane .searchClearButton.hidden {\n display: none;\n}\n.contactPane .searchClearButton:hover {\n color: var(--color-text);\n}\n\n/* ── Contact toolbar (top-right link + delete) ──────────────── */\n\n.contactPane .contact-toolbar {\n display: flex;\n align-items: center;\n gap: var(--spacing-sm);\n padding: var(--spacing-xs) 0;\n}\n\n.contactPane .contact-toolbar a {\n margin: 0.3em;\n}\n\n.contactPane .contact-toolbar a img {\n width: 1.3em;\n height: 1em;\n margin: 0;\n}\n\n.contact-toolbar .deleteButton {\n margin-left: auto; /* keeps delete icon on the right */\n margin-right: 0.2em;\n width: 1em;\n height: 1em;\n float: none; /* important: prevents overlap behavior */\n}\n\n/* ── "All" groups button ─────────────────────────────────────── */\n\n.contactPane .allGroupsButton {\n margin-left: var(--spacing-md);\n font-size: var(--font-size-base);\n}\n\n.contactPane .allGroupsButton--loading {\n background-color: var(--color-primary);\n}\n\n.contactPane .allGroupsButton--active {\n background-color: var(--color-primary);\n color: var(--color-background);\n}\n\n.contactPane .allGroupsButton--loaded {\n background-color: var(--color-primary);\n}\n\n/* ── Selection & visibility states ───────────────────────────── */\n\n.contactPane .group-loading {\n}\n\n/* ── Mint new address book ───────────────────────────────────── */\n\n.contactPane .claimSuccess {\n font-size: var(--font-size-xl);\n}\n\n.contactPane {\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\n.contactPane .addressBook-grid {\n display: flex;\n flex-wrap: nowrap; /* keep sections side-by-side */\n flex: 1;\n min-width: 50%;\n align-items: stretch;\n width: 100%;\n box-sizing: border-box;\n overflow-x: auto; /* allow horizontal scroll if needed */\n}\n\n@media ((min-width: 500px) and (max-width: 900px)) {\n .contactPane .addressBookSection {\n max-width: 900px;\n }\n .contactPane .addressBookSection section {\n max-width: 485px;\n }\n}\n\n.contactPane .contactPane--narrow .addressBook-grid {\n flex-direction: column !important;\n flex-wrap: wrap !important;\n}\n\n.contactPane .contactPane--narrow .addressBookSection,\n.contactPane .contactPane--narrow .detailSection {\n flex: 1 1 100% !important;\n max-width: 100% !important;\n min-width: 0 !important;\n width: 100% !important;\n}\n\n@media (max-width: 1000px) {\n /* Stack sidebar + details vertically on narrow screens */\n .contactPane {\n min-height: auto !important;\n }\n\n .contactPane .addressBook-grid {\n flex-direction: column !important;\n flex-wrap: nowrap !important;\n min-height: auto !important;\n height: auto !important;\n }\n\n .contactPane .addressBookSection,\n .contactPane .detailSection {\n order: initial !important;\n flex: none !important;\n width: 100% !important;\n max-width: 100% !important;\n min-width: 0 !important;\n }\n\n .contactPane .addressBookSection {\n max-height: 60vh !important;\n min-height: auto !important;\n overflow-y: auto !important;\n padding-bottom: var(--spacing-lg) !important;\n }\n\n .contactPane .detailSection {\n max-height: none !important;\n min-height: auto !important;\n overflow-y: visible !important;\n }\n\n .contactPane .detailsSectionContent {\n display: flex !important;\n flex-direction: column !important;\n justify-content: flex-start !important;\n align-items: stretch !important;\n min-height: auto !important;\n height: auto !important;\n overflow-y: visible !important;\n }\n\n .contactPane .detailSection > .detailsSectionContent {\n padding-top: var(--spacing-sm) !important;\n box-sizing: border-box !important;\n }\n\n /* Small-screen larger text and spacing */\n .contactPane,\n .contactPane * {\n font-size: 2rem !important;\n }\n\n .contactPane .actionButton,\n .contactPane .searchInput,\n .contactPane .flatButton,\n .contactPane .buttonSection button,\n .contactPane .groupButtonsList button {\n min-height: calc(var(--min-touch-target) + 0.5em) !important;\n font-size: 2rem !important;\n padding: 1em 1em !important;\n }\n\n .contactPane .group-membership-item .group-membership-toolbar > img.hoverControlHide, .contactPane .group-membership-item .group-membership-toolbar > [data-testid="deleteButtonWithCheck"],\n .individualPane .hoverControl img.hoverControlHide, \n .individualPane .hoverControl [data-testid="deleteButtonWithCheck"] {\n display: inline-flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n}\n\n\n/* Card Section Background */\n.contactPane .section-bg {\n background: var(--color-section-bg);\n padding: var(--spacing-md);\n box-sizing: border-box;\n border: none !important;\n border-radius: 0 !important;\n}\n\n/* Keep detail section content anchored at top */\n.contactPane .detailSection {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: stretch;\n}\n\n.contactPane .detailsSectionContent {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: stretch;\n}\n\n/* ── Button section: horizontal scrollable row ──────────────── */\n\n.contactPane .buttonSection {\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n padding: var(--spacing-sm);\n padding-bottom: 0;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: thin;\n margin-bottom: 0;\n}\n\n.contactPane .buttonSection::-webkit-scrollbar {\n height: 6px;\n}\n\n.contactPane .buttonSection::-webkit-scrollbar-thumb {\n background: var(--color-border-pale);\n border-radius: var(--border-radius-base);\n}\n\n.contactPane .buttonSection::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.contactPane .buttonSection .selected {\n background: none !important;\n}\n\n.contactPane .groupButtonsList {\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: var(--spacing-xs);\n list-style: none;\n}\n\n.contactPane .buttonSection .groupButtonsList {\n margin-left: var(--spacing-xs);\n margin-right: var(--spacing-xs);\n padding-left: 0;\n}\n\n.contactPane .groupButtonsList li {\n flex-shrink: 0;\n}\n\n.contactPane .groupButtonsList button {\n white-space: nowrap;\n flex-shrink: 0;\n min-width: max-content;\n margin-left: 0;\n}\n\n/* Groups list in details section — flexible 2-column grid */\n.contactPane .detailsSectionContent .groupButtonsList {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: var(--spacing-sm);\n list-style: none;\n padding: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.contactPane .detailsSectionContent .groupButtonsList li {\n width: 100%;\n aspect-ratio: auto;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--spacing-xs);\n}\n\n.contactPane .detailsSectionContent .groupButtonsList button {\n width: 100%;\n height: auto;\n text-align: center;\n border-radius: var(--border-radius-base);\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.contactPane .detailsSectionContent .groupButtonsList li > img.hoverControlHide,\n.contactPane .detailsSectionContent .groupButtonsList li > img[data-testid="deleteButtonWithCheck"] {\n display: block;\n align-self: flex-end;\n float: none !important;\n margin: 0 !important;\n}\n\n@media (max-width: 599px) {\n .contactPane .detailsSectionContent .groupButtonsList {\n grid-template-columns: repeat(2, 1fr);\n gap: var(--spacing-xs);\n }\n\n .contactPane .detailsSectionContent .groupButtonsList button {\n font-size: var(--font-size-sm);\n border-radius: var(--border-radius-base);\n }\n}\n\n@media (min-width: 900px) {\n .contactPane .detailsSectionContent .groupButtonsList {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n.contactPane .detailsSectionContent .newGroupBtn {\n width: 100%;\n box-sizing: border-box;\n margin-top: var(--spacing-sm);\n}\n\n.contactPane .detailsSectionContent h3 {\n font-size: var(--font-size-xl);\n margin-bottom: var(--spacing-sm);\n padding-left: 0;\n}\n\n/* Delete confirmation POPUP — centered overlay in details section */\n.contactPane .detailSection {\n position: relative;\n}\n\n.contactPane .webidControl div[style*="position: relative"]:has(> div[style*="display: grid"]) {\n position: static !important;\n}\n\n\n.contactPane .webidControl .personaRow--webid td > div[style*="position: relative"] > div,\n.contactPane .detailsSectionContent .groupButtonsList li > div[style*="position: relative"] > div,\n.contactPane .detailsSectionContent .contact-toolbar > div[style*="position: relative"] > div {\n position: absolute !important;\n left: auto !important;\n z-index: 9999 !important;\n display: grid !important;\n pointer-events: auto !important;\n opacity: 1 !important;\n visibility: visible !important;\n padding: var(--spacing-btn) !important;\n min-width: 12em !important;\n background: var(--color-background) !important;\n border: var(--border-width-sm) solid var(--color-primary) !important;\n border-radius: var(--border-radius-base) !important;\n box-shadow: var(--box-shadow-popup) !important;\n grid-template-columns: auto auto !important;\n gap: var(--spacing-xxs) !important;\n}\n\n.contactPane .detailsSectionContent .contact-toolbar > div[style*="position: relative"] > div > button:has(> img[src$=".svg"]),\n.contactPane .detailsSectionContent .group-membership-item .group-membership-toolbar > div[style*="position: relative"] > div > button:has(> img[src$=".svg"]),\n.contactPane .webidControl .personaRow--webid td > div[style*="position: relative"] > div > button:has(> img[src$=".svg"]) {\n background-color: transparent !important;\n}\n\n/* Selected state for All contacts button */\n.contactPane .allGroupsButton--selected {\n background-color: var(--color-primary);\n color: var(--color-background);\n}\n\n/* ── Header section ──────────────────────────────────────────── */\n\n.contactPane .headerSection {\n background: var(--color-background);\n padding: var(--spacing-sm);\n border-top-left-radius: var(--border-radius-full);\n border-top-right-radius: var(--border-radius-full);\n margin-bottom: 0;\n}\n\n.contactPane .headerSection header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0;\n}\n\n.contactPane .headerSection h2 {\n margin-bottom: 0;\n}\n\n/* ── Dotted horizontal rule ─────────────────────────────────── */\n\n.contactPane .dottedHr {\n border: none;\n border-top: 1px dotted var(--color-text-muted);\n margin: 0;\n}\n\n/* ── Search section ─────────────────────────────────────────── */\n\n.contactPane .searchSection {\n padding: var(--spacing-sm);\n padding-bottom: 0;\n margin-bottom: 0;\n}\n\n/* ── People list section ────────────────────────────────────── */\n\n.contactPane .peopleSection {\n display: flex;\n background: var(--color-background);\n border-top: 1px dotted var(--color-text-muted);\n margin-bottom: 0;\n}\n\n.contactPane .peopleSection ul {\n list-style: none;\n padding: 0;\n margin: 0;\n width: 100%;\n max-height: 70vh;\n overflow-y: auto;\n}\n\n.contactPane .peopleSection li {\n border-top: 1px solid var(--color-border-pale);\n padding: var(--spacing-xs);\n}\n\n/* ── Person list item (addressBookPresenter) ─────────────────── */\n\n.contactPane .personLi-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.contactPane .personLi-avatar {\n width: 45px;\n height: 45px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.contactPane .personLi-avatar .avatar-placeholder {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.contactPane .personLi-avatar img {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n object-fit: cover;\n}\n\n.contactPane .personLi-info {\n flex: 1;\n margin-left: var(--spacing-sm);\n overflow: hidden;\n}\n\n.contactPane .personLi-name {\n font-weight: bold;\n font-size: var(--font-size-base);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.contactPane .personLi-arrow {\n margin-left: auto;\n display: flex;\n align-items: center;\n}\n\n.contactPane .personLi--error {\n opacity: 0.5;\n}`,"",{version:3,sources:["webpack://./src/styles/contactsPane.css"],names:[],mappings:"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",sourcesContent:['/* Focus indicator for keyboard navigation */\n.contactPane table tr[tabindex="0"]:focus {\n outline: var(--focus-ring-width) solid var(--color-primary);\n outline-offset: 2px;\n background: var(--color-info-bg);\n}\n/* contactsPane styles — extracted from inline styles in contactsPane.js */\n/* Uses CSS custom properties from the global stylesheet (dev-global.css / mashlib) */\n\n/* ── Layout: Three-column browser ────────────────────────────── */\n\n.contactPane .peopleSection .selected {\n background-color: var(--color-info-bg) !important;\n}\n\n.contactPane .detailSection,\n.contactPane .addressBookSection {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n flex: 1 1 0; /* allow it to grow but not force wrap */\n min-width: 300px;\n box-sizing: border-box;\n background: var(--color-section-bg);\n}\n\n.contactPane .detailsSectionContent {\n flex: 1 1 auto;\n min-height: 200px;\n padding: var(--spacing-lg);\n max-width: 900px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.contactPane .detailsSectionContent--wide {\n max-width: 900px;\n}\n\n.contactPane .cardFooter {\n display: flex;\n flex-wrap: nowrap; /* keep buttons inline */\n align-items: center; /* vertical centering if varied heights */\n gap: var(--spacing-xs);\n padding-top: var(--spacing-md);\n margin-top: var(--spacing-md);\n}\n\n.contactPane .detailsSectionContent {\n margin: 0;\n}\n\n/* ── Contact type chooser ───────────────────────────────────── */\n\n.contactPane .contactTypeChooser {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-sm);\n max-width: 360px;\n}\n\n.contactPane .contactTypeChooser h3 {\n margin: 0 0 var(--spacing-xs) 0;\n font-size: var(--font-size-lg);\n}\n\n.contactPane .contactTypeSelect {\n height: var(--min-touch-target);\n border: 1px solid var(--color-border-pale);\n border-radius: var(--border-radius-base);\n padding: 0 var(--spacing-sm);\n font-size: var(--font-size-sm);\n background: var(--color-section-bg);\n}\n\n/* ── Search ──────────────────────────────────────────────────── */\n\n.contactPane .allGroupsButton {\n border-radius: var(--border-radius-full) !important;\n /* existing styles */\n}\n/* wrapper to position clear icon/button */\n.contactPane .searchDiv {\n position: relative;\n}\n\n.contactPane .searchInput {\n height: var(--min-touch-target);\n border: 1px solid var(--color-border-pale);\n background-color: var(--color-section-bg);\n background-image: url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' fill=\'%23999\' viewBox=\'0 0 24 24\' width=\'20\' height=\'20\'%3E%3Cpath d=\'M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99c.41.41 1.09.41 1.5 0s.41-1.09 0-1.5l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z\'/%3E%3C/svg%3E");\n background-repeat: no-repeat;\n background-position: 8px center;\n background-size: 20px 20px;\n border-radius: var(--border-radius-base);\n padding: 0 var(--spacing-sm) 0 34px;\n font-size: var(--font-size-base);\n width: 100%;\n box-sizing: border-box;\n}\n\n/* clear button inside search input */\n.contactPane .searchClearButton {\n position: absolute;\n right: var(--spacing-sm);\n top: 50%;\n transform: translateY(-50%);\n border: none;\n background: transparent;\n font-size: var(--font-size-base);\n line-height: 1;\n padding: 0;\n cursor: pointer;\n color: var(--color-text-muted);\n /* visibility is controlled via the generic `.hidden` utility class */\n display: block;\n}\n.contactPane .searchClearButton.hidden {\n display: none;\n}\n.contactPane .searchClearButton:hover {\n color: var(--color-text);\n}\n\n/* ── Contact toolbar (top-right link + delete) ──────────────── */\n\n.contactPane .contact-toolbar {\n display: flex;\n align-items: center;\n gap: var(--spacing-sm);\n padding: var(--spacing-xs) 0;\n}\n\n.contactPane .contact-toolbar a {\n margin: 0.3em;\n}\n\n.contactPane .contact-toolbar a img {\n width: 1.3em;\n height: 1em;\n margin: 0;\n}\n\n.contact-toolbar .deleteButton {\n margin-left: auto; /* keeps delete icon on the right */\n margin-right: 0.2em;\n width: 1em;\n height: 1em;\n float: none; /* important: prevents overlap behavior */\n}\n\n/* ── "All" groups button ─────────────────────────────────────── */\n\n.contactPane .allGroupsButton {\n margin-left: var(--spacing-md);\n font-size: var(--font-size-base);\n}\n\n.contactPane .allGroupsButton--loading {\n background-color: var(--color-primary);\n}\n\n.contactPane .allGroupsButton--active {\n background-color: var(--color-primary);\n color: var(--color-background);\n}\n\n.contactPane .allGroupsButton--loaded {\n background-color: var(--color-primary);\n}\n\n/* ── Selection & visibility states ───────────────────────────── */\n\n.contactPane .group-loading {\n}\n\n/* ── Mint new address book ───────────────────────────────────── */\n\n.contactPane .claimSuccess {\n font-size: var(--font-size-xl);\n}\n\n.contactPane {\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\n.contactPane .addressBook-grid {\n display: flex;\n flex-wrap: nowrap; /* keep sections side-by-side */\n flex: 1;\n min-width: 50%;\n align-items: stretch;\n width: 100%;\n box-sizing: border-box;\n overflow-x: auto; /* allow horizontal scroll if needed */\n}\n\n@media ((min-width: 500px) and (max-width: 900px)) {\n .contactPane .addressBookSection {\n max-width: 900px;\n }\n .contactPane .addressBookSection section {\n max-width: 485px;\n }\n}\n\n.contactPane .contactPane--narrow .addressBook-grid {\n flex-direction: column !important;\n flex-wrap: wrap !important;\n}\n\n.contactPane .contactPane--narrow .addressBookSection,\n.contactPane .contactPane--narrow .detailSection {\n flex: 1 1 100% !important;\n max-width: 100% !important;\n min-width: 0 !important;\n width: 100% !important;\n}\n\n@media (max-width: 1000px) {\n /* Stack sidebar + details vertically on narrow screens */\n .contactPane {\n min-height: auto !important;\n }\n\n .contactPane .addressBook-grid {\n flex-direction: column !important;\n flex-wrap: nowrap !important;\n min-height: auto !important;\n height: auto !important;\n }\n\n .contactPane .addressBookSection,\n .contactPane .detailSection {\n order: initial !important;\n flex: none !important;\n width: 100% !important;\n max-width: 100% !important;\n min-width: 0 !important;\n }\n\n .contactPane .addressBookSection {\n max-height: 60vh !important;\n min-height: auto !important;\n overflow-y: auto !important;\n padding-bottom: var(--spacing-lg) !important;\n }\n\n .contactPane .detailSection {\n max-height: none !important;\n min-height: auto !important;\n overflow-y: visible !important;\n }\n\n .contactPane .detailsSectionContent {\n display: flex !important;\n flex-direction: column !important;\n justify-content: flex-start !important;\n align-items: stretch !important;\n min-height: auto !important;\n height: auto !important;\n overflow-y: visible !important;\n }\n\n .contactPane .detailSection > .detailsSectionContent {\n padding-top: var(--spacing-sm) !important;\n box-sizing: border-box !important;\n }\n\n /* Small-screen larger text and spacing */\n .contactPane,\n .contactPane * {\n font-size: 2rem !important;\n }\n\n .contactPane .actionButton,\n .contactPane .searchInput,\n .contactPane .flatButton,\n .contactPane .buttonSection button,\n .contactPane .groupButtonsList button {\n min-height: calc(var(--min-touch-target) + 0.5em) !important;\n font-size: 2rem !important;\n padding: 1em 1em !important;\n }\n\n .contactPane .group-membership-item .group-membership-toolbar > img.hoverControlHide, .contactPane .group-membership-item .group-membership-toolbar > [data-testid="deleteButtonWithCheck"],\n .individualPane .hoverControl img.hoverControlHide, \n .individualPane .hoverControl [data-testid="deleteButtonWithCheck"] {\n display: inline-flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n}\n\n\n/* Card Section Background */\n.contactPane .section-bg {\n background: var(--color-section-bg);\n padding: var(--spacing-md);\n box-sizing: border-box;\n border: none !important;\n border-radius: 0 !important;\n}\n\n/* Keep detail section content anchored at top */\n.contactPane .detailSection {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: stretch;\n}\n\n.contactPane .detailsSectionContent {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: stretch;\n}\n\n/* ── Button section: horizontal scrollable row ──────────────── */\n\n.contactPane .buttonSection {\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n padding: var(--spacing-sm);\n padding-bottom: 0;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: thin;\n margin-bottom: 0;\n}\n\n.contactPane .buttonSection::-webkit-scrollbar {\n height: 6px;\n}\n\n.contactPane .buttonSection::-webkit-scrollbar-thumb {\n background: var(--color-border-pale);\n border-radius: var(--border-radius-base);\n}\n\n.contactPane .buttonSection::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.contactPane .buttonSection .selected {\n background: none !important;\n}\n\n.contactPane .groupButtonsList {\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: var(--spacing-xs);\n list-style: none;\n}\n\n.contactPane .buttonSection .groupButtonsList {\n margin-left: var(--spacing-xs);\n margin-right: var(--spacing-xs);\n padding-left: 0;\n}\n\n.contactPane .groupButtonsList li {\n flex-shrink: 0;\n}\n\n.contactPane .groupButtonsList button {\n white-space: nowrap;\n flex-shrink: 0;\n min-width: max-content;\n margin-left: 0;\n}\n\n/* Groups list in details section — flexible 2-column grid */\n.contactPane .detailsSectionContent .groupButtonsList {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: var(--spacing-sm);\n list-style: none;\n padding: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.contactPane .detailsSectionContent .groupButtonsList li {\n width: 100%;\n aspect-ratio: auto;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--spacing-xs);\n}\n\n.contactPane .detailsSectionContent .groupButtonsList button {\n width: 100%;\n height: auto;\n text-align: center;\n border-radius: var(--border-radius-base);\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.contactPane .detailsSectionContent .groupButtonsList li > img.hoverControlHide,\n.contactPane .detailsSectionContent .groupButtonsList li > img[data-testid="deleteButtonWithCheck"] {\n display: block;\n align-self: flex-end;\n float: none !important;\n margin: 0 !important;\n}\n\n@media (max-width: 599px) {\n .contactPane .detailsSectionContent .groupButtonsList {\n grid-template-columns: repeat(2, 1fr);\n gap: var(--spacing-xs);\n }\n\n .contactPane .detailsSectionContent .groupButtonsList button {\n font-size: var(--font-size-sm);\n border-radius: var(--border-radius-base);\n }\n}\n\n@media (min-width: 900px) {\n .co