spec-up-t 1.6.1 → 1.6.3-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ See the [user manual](https://trustoverip.github.io/spec-up-t-website/)
@@ -113,7 +113,7 @@ function tokenInput(){document.querySelector(".button-token-input").addEventList
113
113
  function insertTrefs(e){!function(e){const n=[];document.querySelectorAll("dl.terms-and-definitions-list dt span.term-external").forEach((e=>{const t=e.dataset.originalTerm,r=e.closest("dt");if(r){const e=r.nextElementSibling;if(e?.classList.contains("term-external")&&e.classList.contains("meta-info-content-wrapper"))return}n.push({element:e,textContent:t,dt:r,parent:r?.parentNode})}));const t=n.map((n=>{const{textContent:t,dt:r,parent:o}=n;if(!r||!o)return null;const i=e.xtrefs.find((e=>e.term===t)),a=document.createDocumentFragment(),s=document.createElement("dd");if(s.classList.add("term-external","meta-info-content-wrapper","collapsed"),i){const e=i.avatarUrl?`![avatar](${i.avatarUrl})`:"",n=i.owner||"Unknown",r=i.repo&&i.repoUrl?`[${i.repo}](${i.repoUrl})`:"Unknown",o=i.commitHash||"Unknown",d=i.ghPageUrl?new URL(`#term:${i.term}`,i.ghPageUrl).href:"Unknown",l=`\n| Property | Value |\n| -------- | ----- |\n| Original Term | ${t} |\n| Link | ${d} |\n| Owner | ${e} ${n} |\n| Repo | ${r} |\n| Commit hash | ${o} |\n `;s.innerHTML=md.render(l),a.appendChild(s);let c=i.content.split("\n").map((e=>e.replace(/^\s*~\s*/,""))).join("\n").replace(/\]\]/g,"");const m=document.createElement("div");m.innerHTML=md.render(c),m.querySelectorAll("a").forEach((e=>{const n=e=>{try{return null!==document.getElementById(e)}catch{return!1}};try{const t=new URL(e.href);if(t.hostname!==window.location.hostname)return;if(t.hash&&n(t.hash.slice(1)))return;e.replaceWith(...e.childNodes)}catch{if(e.href.startsWith("#")&&n(e.href.slice(1)))return;e.replaceWith(...e.childNodes)}})),c=m.innerHTML;const f=document.createElement("div");f.innerHTML=md.render(c);const p=f.querySelectorAll("dd");if(p.length>0)Array.from(p).forEach((e=>{const n=e.cloneNode(!0);n.classList.add("term-external","term-external-embedded"),a.appendChild(n)}));else{const e=document.createElement("dd");e.classList.add("term-external","term-external-embedded"),e.innerHTML=f.innerHTML,a.appendChild(e)}}else{s.innerHTML=md.render("\n| Property | Value |\n| -------- | ----- |\n| Owner | Unknown |\n| Repo | Unknown |\n| Commit hash | not found |\n "),a.appendChild(s);const e=document.createElement("dd");e.innerHTML="<p>This term was not found in the external repository.</p>",a.appendChild(e)}return{dt:r,parent:o,fragment:a}})).filter(Boolean);requestAnimationFrame((()=>{t.forEach((e=>{const{dt:n,parent:t,fragment:r}=e;t.insertBefore(r,n.nextSibling)})),document.dispatchEvent(new CustomEvent("trefs-inserted",{detail:{count:t.length}}))}))}(e)}function initializeOnTrefsInserted(e){let n=!1;document.addEventListener("trefs-inserted",(function(t){n||(n=!0,e(),t.detail&&console.log(`Collapsible definitions initialized after ${t.detail.count} xrefs were inserted`))})),setTimeout((()=>{n||(console.warn("trefs-inserted event was not received, initializing collapsible definitions anyway"),e(),n=!0)}),1e3)}document.addEventListener("DOMContentLoaded",(()=>{"undefined"!=typeof allXTrefs&&allXTrefs?.xtrefs?insertTrefs(allXTrefs):(console.error("allXTrefs is undefined or missing xtrefs property"),document.dispatchEvent(new CustomEvent("trefs-inserted",{detail:{count:0,error:"Missing xtrefs data"}})))}));
114
114
  function insertIrefs(){!function(){const e=document.querySelectorAll("span.iref-placeholder");if(0===e.length)return void document.dispatchEvent(new CustomEvent("irefs-inserted",{detail:{count:0}}));const t=[];e.forEach((e=>{const n=e.dataset.irefTerm,r=e.dataset.irefOriginal;if(!n)return void console.warn("iref placeholder missing data-iref-term attribute",e);const o=`term:${n}`,i=document.getElementById(o);if(!i){console.warn(`iref: term "${r}" (id: ${n}) not found in terms-and-definitions-list`);const o=document.createElement("div");o.className="iref-not-found",o.innerHTML=`<p class="text-warning"><em>[[iref: ${r}]] - Term not found in definitions list</em></p>`;const i=document.createDocumentFragment();return i.appendChild(o),void t.push({placeholder:e,fragment:i})}const d=i.closest("dt");if(!d)return void console.warn(`iref: could not find <dt> element for term "${r}"`);const s=document.createDocumentFragment(),l=document.createElement("div");l.className="iref-content";const c=document.createElement("dl");c.className="iref-definition-list";const a=d.cloneNode(!0);a.classList.add("iref-term"),a.classList.add("term-reference");const m=a.querySelector("a.toc-anchor");m&&m.remove();a.querySelectorAll("[id]").forEach((e=>{e.removeAttribute("id")}));a.querySelectorAll(".edit-term-buttons").forEach((e=>{e.remove()}));const f=d.querySelector('[id^="term:"]');if(f){const e=f.getAttribute("id"),t=document.createElement("a");t.href=`#${e}`,t.className="iref-go-to-glossary-button btn btn-sm btn-outline-secondary py-1",t.innerHTML='<span class="iref-button-icon"></span>Glossary',t.title=`Go to original definition of ${r}`,a.appendChild(t)}c.appendChild(a);let u=d.nextElementSibling;for(;u&&"dd"===u.tagName.toLowerCase();){const e=u.cloneNode(!0);e.classList.add("iref-definition"),c.appendChild(e),u=u.nextElementSibling}l.appendChild(c),s.appendChild(l),t.push({placeholder:e,fragment:s})})),requestAnimationFrame((()=>{t.forEach((e=>{const{placeholder:t,fragment:n}=e;t.parentNode.replaceChild(n,t)})),document.dispatchEvent(new CustomEvent("irefs-inserted",{detail:{count:t.length}})),console.log(`Inserted ${t.length} inline reference(s)`)}))}()}document.addEventListener("DOMContentLoaded",(()=>{document.querySelectorAll("span.iref-placeholder").length>0&&document.querySelectorAll("dl.terms-and-definitions-list dt.term-external").length>0?document.addEventListener("trefs-inserted",(()=>{insertIrefs()}),{once:!0}):insertIrefs()}));
115
115
  function getOrCreateButtonContainer(t){let n=t.querySelector(".definition-buttons-container");return n||(n=document.createElement("div"),n.classList.add("definition-buttons-container"),t.appendChild(n)),n}function addButtonToContainer(t,n,e=!1){const i=getOrCreateButtonContainer(t);return e?i.insertBefore(n,i.firstChild):i.appendChild(n),i}
116
- function collapseDefinitions(){let{dds:t,dts:e,regularDds:s,specialDds:a}=function(){const t=document.querySelectorAll("#content dl.terms-and-definitions-list > dd");return{dds:t,dts:document.querySelectorAll("#content dl.terms-and-definitions-list > dt"),regularDds:Array.from(t).filter((t=>!i(t.textContent.trim()))),specialDds:Array.from(t).filter((t=>i(t.textContent.trim())))}}();function i(t){return["Source","See also","More in","Also see","See:","See also","See more","See more in","See more about","See more on","See more at","More:","Note:","Paraphrased by","Beware:","eSSIF-Lab: ","W3C VC:","NIST:","Supporting definitions:"].some((e=>t.startsWith(e)))}a.forEach((t=>{t.classList.add("terms-def-extra-info")})),e.forEach((t=>{if(t.querySelector(".collapse-all-defs-button"))return;const e=document.createElement("button");e.classList.add("collapse-all-defs-button","btn-outline-secondary","d-print-none","btn","p-0","fs-5","d-flex","align-items-center","justify-content-center"),e.innerHTML='<span class="state-indicator" data-state="0">①</span><span class="state-indicator" data-state="1">②</span><span class="state-indicator" data-state="2">③</span>',e.setAttribute("id","toggleButton"),e.setAttribute("title","Change how much info is shown"),e.setAttribute("data-state","2"),e.querySelector('.state-indicator[data-state="2"]').classList.add("active"),addButtonToContainer(t,e)})),document.addEventListener("click",(e=>{if(e.target.classList.contains("collapse-all-defs-button")||e.target.classList.contains("state-indicator")){const i=e.target.classList.contains("collapse-all-defs-button")?e.target:e.target.closest(".collapse-all-defs-button"),n=i.getBoundingClientRect();document.documentElement.classList.add("definitions-transitioning"),i.style.position="fixed",i.style.top=`${n.top}px`,i.style.right=window.innerWidth-n.right+"px",i.style.zIndex="1000",function(){const e=document.querySelectorAll(".collapse-all-defs-button");switch((parseInt(e[0].dataset.state||0)+1)%3){case 0:t.forEach((t=>{t.classList.add("hidden"),t.classList.remove("visible")})),e.forEach((t=>{t.dataset.state=0,t.title="Show basic definitions",t.querySelectorAll(".state-indicator").forEach((t=>{0===parseInt(t.dataset.state)?t.classList.add("active"):t.classList.remove("active")}))})),document.querySelector("html").classList.add("defs-hidden");break;case 1:s.forEach((t=>{t.classList.remove("hidden"),t.classList.add("visible")})),a.forEach((t=>{t.classList.add("hidden"),t.classList.remove("visible")})),e.forEach((t=>{t.dataset.state=1,t.title="Show all definitions",t.querySelectorAll(".state-indicator").forEach((t=>{1===parseInt(t.dataset.state)?t.classList.add("active"):t.classList.remove("active")}))})),document.querySelector("html").classList.remove("defs-hidden");break;case 2:t.forEach((t=>{t.classList.remove("hidden"),t.classList.add("visible")})),a.forEach((t=>{t.classList.add("terms-def-extra-info")})),e.forEach((t=>{t.dataset.state=2,t.title="Hide all definitions",t.querySelectorAll(".state-indicator").forEach((t=>{2===parseInt(t.dataset.state)?t.classList.add("active"):t.classList.remove("active")}))})),document.querySelector("html").classList.remove("defs-hidden")}}(),requestAnimationFrame((()=>{i.style.position="",i.style.top="",i.style.right="",i.style.zIndex="",document.documentElement.classList.remove("definitions-transitioning");const t=i.getBoundingClientRect();window.scrollTo({top:window.scrollY+(t.top-n.top),behavior:"instant"})}))}}))}document.addEventListener("DOMContentLoaded",(function(){initializeOnTrefsInserted(collapseDefinitions)}));
116
+ function collapseDefinitions(){let{dds:t,dts:e,regularDds:s,specialDds:a}=function(){const t=document.querySelectorAll("#content dl.terms-and-definitions-list > dd");return{dds:t,dts:document.querySelectorAll("#content dl.terms-and-definitions-list > dt"),regularDds:Array.from(t).filter((t=>!i(t.textContent.trim()))),specialDds:Array.from(t).filter((t=>i(t.textContent.trim())))}}();function i(t){return["Source","See also","More in","Also see","See:","Mind you:","Explanation:","See also","See more","See more in","See more about","See more on","See more at","More:","Note:","Paraphrased by","Beware:","eSSIF-Lab: ","W3C VC:","NIST:","Supporting definitions:"].some((e=>t.startsWith(e)))}a.forEach((t=>{t.classList.add("terms-def-extra-info")})),e.forEach((t=>{if(t.querySelector(".collapse-all-defs-button"))return;const e=document.createElement("button");e.classList.add("collapse-all-defs-button","btn-outline-secondary","d-print-none","btn","p-0","fs-5","d-flex","align-items-center","justify-content-center"),e.innerHTML='<span class="state-indicator" data-state="0">①</span><span class="state-indicator" data-state="1">②</span><span class="state-indicator" data-state="2">③</span>',e.setAttribute("id","toggleButton"),e.setAttribute("title","Change how much info is shown"),e.setAttribute("data-state","2"),e.querySelector('.state-indicator[data-state="2"]').classList.add("active"),addButtonToContainer(t,e)})),document.addEventListener("click",(e=>{if(e.target.classList.contains("collapse-all-defs-button")||e.target.classList.contains("state-indicator")){const i=e.target.classList.contains("collapse-all-defs-button")?e.target:e.target.closest(".collapse-all-defs-button"),n=i.getBoundingClientRect();document.documentElement.classList.add("definitions-transitioning"),i.style.position="fixed",i.style.top=`${n.top}px`,i.style.right=window.innerWidth-n.right+"px",i.style.zIndex="1000",function(){const e=document.querySelectorAll(".collapse-all-defs-button");switch((parseInt(e[0].dataset.state||0)+1)%3){case 0:t.forEach((t=>{t.classList.add("hidden"),t.classList.remove("visible")})),e.forEach((t=>{t.dataset.state=0,t.title="Show basic definitions",t.querySelectorAll(".state-indicator").forEach((t=>{0===parseInt(t.dataset.state)?t.classList.add("active"):t.classList.remove("active")}))})),document.querySelector("html").classList.add("defs-hidden");break;case 1:s.forEach((t=>{t.classList.remove("hidden"),t.classList.add("visible")})),a.forEach((t=>{t.classList.add("hidden"),t.classList.remove("visible")})),e.forEach((t=>{t.dataset.state=1,t.title="Show all definitions",t.querySelectorAll(".state-indicator").forEach((t=>{1===parseInt(t.dataset.state)?t.classList.add("active"):t.classList.remove("active")}))})),document.querySelector("html").classList.remove("defs-hidden");break;case 2:t.forEach((t=>{t.classList.remove("hidden"),t.classList.add("visible")})),a.forEach((t=>{t.classList.add("terms-def-extra-info")})),e.forEach((t=>{t.dataset.state=2,t.title="Hide all definitions",t.querySelectorAll(".state-indicator").forEach((t=>{2===parseInt(t.dataset.state)?t.classList.add("active"):t.classList.remove("active")}))})),document.querySelector("html").classList.remove("defs-hidden")}}(),requestAnimationFrame((()=>{i.style.position="",i.style.top="",i.style.right="",i.style.zIndex="",document.documentElement.classList.remove("definitions-transitioning");const t=i.getBoundingClientRect();window.scrollTo({top:window.scrollY+(t.top-n.top),behavior:"instant"})}))}}))}document.addEventListener("DOMContentLoaded",(function(){initializeOnTrefsInserted(collapseDefinitions)}));
117
117
  function createToggleButton(e){const t=document.createElement("button");t.classList.add("meta-info-toggle-button","btn","fs-1","d-flex","align-items-center","justify-content-center"),t.innerHTML='<i class="bi bi-info-circle" style="margin-top: -0.5em;"></i>',t.title="Meta info",t.addEventListener("click",(function(t){t.preventDefault(),t.stopPropagation();e.classList.contains("collapsed")?(e.classList.remove("collapsed"),e.getBoundingClientRect()):e.classList.add("collapsed")}));let n=e.previousElementSibling;for(;n&&"DT"!==n.tagName;)n=n.previousElementSibling;n?addButtonToContainer(n,t,!0):e.insertBefore(t,e.firstChild)}function collapseMetaInfo(){document.querySelectorAll("dl > dd:has(table)").forEach((function(e){e.classList.add("meta-info-content-wrapper");const t=document.createElement("div");for(t.classList.add("meta-info-inner-wrapper");e.firstChild&&e.firstChild!==e.querySelector(".meta-info-toggle-button");)t.appendChild(e.firstChild);e.querySelector(".meta-info-toggle-button")||createToggleButton(e),e.appendChild(t),e.classList.add("collapsed")}))}document.addEventListener("DOMContentLoaded",(function(){initializeOnTrefsInserted(collapseMetaInfo)}));
118
118
  function fixLastDd(){document.querySelectorAll("dl.terms-and-definitions-list").forEach((t=>{t.querySelectorAll(":scope > dd").forEach(((t,e)=>{t.classList.remove("last-dd");let s=t.nextElementSibling;s&&"DT"!==s.tagName||t.classList.contains("last-dd")||t.classList.add("last-dd")}))}))}document.addEventListener("trefs-inserted",(function(){fixLastDd()}));
119
119
  /**
@@ -185,6 +185,7 @@ const horizontalScrollHint=A=>{if(!document.getElementById("horizontalScrollHint
185
185
  function addBootstrapClassesToImages(){document.querySelectorAll("#content img").forEach((e=>{if(e.classList.add("img-fluid"),e.classList.add("rounded"),e.classList.add("shadow-sm"),e.classList.add("my-3"),!e.closest("figure")&&!e.parentElement.classList.contains("image-container")){const t=document.createElement("figure");t.classList.add("figure","text-center");if(e.parentElement.replaceChild(t,e),t.appendChild(e),e.alt&&""!==e.alt.trim()){const s=document.createElement("figcaption");s.classList.add("figure-caption","text-center"),s.textContent=e.alt,t.appendChild(s)}}}))}function initImageBootstrapClasses(){const e=document.querySelector("#content");if(e&&(addBootstrapClassesToImages(),"undefined"!=typeof MutationObserver)){new MutationObserver((e=>{let t=!1;e.forEach((e=>{"childList"===e.type&&e.addedNodes.length>0&&e.addedNodes.forEach((e=>{1===e.nodeType&&(t="IMG"===e.tagName||e.querySelector?.("img"))}))})),t&&addBootstrapClassesToImages()})).observe(e,{childList:!0,subtree:!0})}}document.addEventListener("DOMContentLoaded",(()=>{initImageBootstrapClasses()}));
186
186
  const imageFullSize=()=>{const e=document.querySelector("#content");function t(){let e=document.querySelector(".image-container-full-page");e&&document.body.removeChild(e)}e?(e.addEventListener("click",(e=>{if("IMG"===e.target.tagName){let n=e.target;if(null===document.querySelector(".image-container-full-page")){const e=n.cloneNode(!0),o=document.createElement("div");o.classList.add("image-container"),o.classList.add("image-container-full-page"),o.appendChild(e),document.body.appendChild(o),o.addEventListener("click",(function e(){o.removeEventListener("click",e),t()}))}n.classList.toggle("image-full-page")}})),document.addEventListener("keydown",(e=>{"Escape"===e.key&&t()}))):console.log("Element with class '.markdown' not found.")};document.addEventListener("DOMContentLoaded",(()=>{imageFullSize()}));
187
187
  function highlightHeadingSection(i){if(!i||"string"!=typeof i||!i.startsWith("#"))return console.warn("Invalid anchor provided:",i),!1;removeExistingHighlights();const e=i.substring(1),t=document.getElementById(e);if(!t)return console.warn("Element with ID not found:",e),!1;const n=getHeadingLevel(t);if(null===n)return!1;return wrapNodesWithHighlight(collectHeadingSiblings(t,n)),!0}function getHeadingLevel(i){const e=i.tagName.toLowerCase().match(/^h([2-6])$/);return e?parseInt(e[1],10):null}function collectHeadingSiblings(i,e){const t=[i];let n=i.nextElementSibling;for(;n;){const i=getHeadingLevel(n);if(null!==i&&i<=e)break;t.push(n),n=n.nextElementSibling}return t}function wrapNodesWithHighlight(i){if(!i||0===i.length)return null;const e=document.createElement("div");e.className="highlight2";const t=i[0];return t.parentNode.insertBefore(e,t),i.forEach((i=>{e.appendChild(i)})),e}function removeExistingHighlights(){const i=document.querySelectorAll(".highlight2");let e=0;return i.forEach((i=>{const t=i.parentNode;for(;i.firstChild;)t.insertBefore(i.firstChild,i);t.removeChild(i),e++})),e}function handleAnchorClick(i){const e=i.target;if("a"!==e.tagName.toLowerCase())return;const t=e.getAttribute("href");if(!t||!t.includes("#"))return;const n=t.substring(t.indexOf("#"));n.startsWith("#")&&n.length>1&&setTimeout((()=>{highlightHeadingSection(n)}),100)}function initializeAnchorHighlighting(){document.addEventListener("click",handleAnchorClick),window.location.hash&&setTimeout((()=>{highlightHeadingSection(window.location.hash)}),200),window.addEventListener("hashchange",(()=>{window.location.hash?highlightHeadingSection(window.location.hash):removeExistingHighlights()}))}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",initializeAnchorHighlighting):initializeAnchorHighlighting(),"undefined"!=typeof module&&module.exports&&(module.exports={highlightHeadingSection:highlightHeadingSection,getHeadingLevel:getHeadingLevel,collectHeadingSiblings:collectHeadingSiblings,wrapNodesWithHighlight:wrapNodesWithHighlight,removeExistingHighlights:removeExistingHighlights,initializeAnchorHighlighting:initializeAnchorHighlighting});
188
+ const VALIDATOR_CONFIG={classes:{indicator:"external-ref-validation-indicator",missing:"external-ref-missing",changed:"external-ref-changed",valid:"external-ref-valid",error:"external-ref-error"},labels:{missing:"⚠️ Term not found",changed:"🔄 Definition changed",error:"❌ Could not verify",valid:"✓ Verified"},showValidIndicators:!1,cacheTimeout:3e5,similarityThreshold:.95,debug:!0},fetchCache=new Map;function normalizeContent(e){if(!e)return"";const t=document.createElement("div");t.innerHTML=e;let n=t.textContent||t.innerText||"";return n=n.toLowerCase().replace(/[\u200B-\u200D\uFEFF]/g,"").replace(/\s+/g," ").replace(/\s*([.,;:!?])\s*/g,"$1 ").trim(),n}function calculateSimilarity(e,t){if(e===t)return 1;if(!e||!t)return 0;const n=e.length>t.length?e:t,i=e.length>t.length?t:e;if(0===n.length)return 1;const a=levenshteinDistance(i,n);return(n.length-a)/n.length}function levenshteinDistance(e,t){const n=[];for(let e=0;e<=t.length;e++)n[e]=[e];for(let t=0;t<=e.length;t++)n[0][t]=t;for(let i=1;i<=t.length;i++)for(let a=1;a<=e.length;a++)t.charAt(i-1)===e.charAt(a-1)?n[i][a]=n[i-1][a-1]:n[i][a]=Math.min(n[i-1][a-1]+1,n[i][a-1]+1,n[i-1][a]+1);return n[t.length][e.length]}function extractTermsFromHtml(e){const t=new Map;return(new DOMParser).parseFromString(e,"text/html").querySelectorAll("dl.terms-and-definitions-list dt").forEach((e=>{const n=e.querySelector('[id^="term:"]');if(!n)return;const i=n.id,a=i.split(":").pop(),r=[];let o="",l="",s=e.nextElementSibling;for(;s&&"DD"===s.tagName;)s.classList.contains("meta-info-content-wrapper")||r.push(s),s=s.nextElementSibling;r.length>0&&(l=r.map((e=>e.outerHTML)).join("\n"),o=r.map((e=>e.textContent)).join("\n")),t.set(a.toLowerCase(),{content:o.trim(),rawContent:l,termId:i})})),t}async function fetchExternalSpec(e,t){const n=fetchCache.get(e);if(n&&Date.now()-n.timestamp<VALIDATOR_CONFIG.cacheTimeout)return n.data;try{const n=await fetch(e,{mode:"cors",headers:{Accept:"text/html"}});if(!n.ok)return console.warn(`[External Ref Validator] Failed to fetch ${t}: ${n.status}`),null;const i=extractTermsFromHtml(await n.text());return fetchCache.set(e,{timestamp:Date.now(),data:i}),i}catch(e){return console.warn(`[External Ref Validator] Error fetching ${t}:`,e.message),null}}function findTextDifferences(e,t){const n=e.split(/\n+/).filter((e=>e.trim())),i=t.split(/\n+/).filter((e=>e.trim())),a=n.filter((e=>!i.includes(e))),r=i.filter((e=>!n.includes(e)));return{oldUnique:a.length>0?a.join("\n"):"(no removed content)",newUnique:r.length>0?r.join("\n"):"(no added content)",hasDifferences:a.length>0||r.length>0}}function createIndicator(e,t={}){const n=document.createElement("span");n.classList.add(VALIDATOR_CONFIG.classes.indicator,VALIDATOR_CONFIG.classes[e]);const i=t.message||VALIDATOR_CONFIG.labels[e];n.setAttribute("title",i);const a=document.createElement("span");if(a.classList.add("indicator-icon"),a.textContent=VALIDATOR_CONFIG.labels[e].split(" ")[0],n.appendChild(a),"changed"===e&&t.oldContent&&t.newContent){n.classList.add("has-details");const e=findTextDifferences(t.oldContent,t.newContent),i=document.createElement("div");i.classList.add("validation-details");const a=t.similarity?`<div class="validation-similarity">Similarity: ${t.similarity}</div>`:"";e.hasDifferences?i.innerHTML=`\n <div class="validation-details-header">Definition Changed - Showing Differences</div>\n ${a}\n <div class="validation-details-section">\n <strong>Removed from cached version:</strong>\n <div class="validation-content-old">${escapeHtml(truncateText(e.oldUnique,300))}</div>\n </div>\n <div class="validation-details-section">\n <strong>Added in live version:</strong>\n <div class="validation-content-new">${escapeHtml(truncateText(e.newUnique,300))}</div>\n </div>\n <div class="validation-details-footer">\n <em>Rebuild the spec to update the definition</em>\n </div>\n `:i.innerHTML=`\n <div class="validation-details-header">Definition Changed</div>\n ${a}\n <div class="validation-details-section">\n <strong>Cached (at build time):</strong>\n <div class="validation-content-old">${escapeHtml(truncateText(t.oldContent,500))}</div>\n </div>\n <div class="validation-details-section">\n <strong>Current (live):</strong>\n <div class="validation-content-new">${escapeHtml(truncateText(t.newContent,500))}</div>\n </div>\n <div class="validation-details-footer">\n <em>Rebuild the spec to update the definition</em>\n </div>\n `,n.appendChild(i)}if("missing"===e){n.classList.add("has-details");const e=document.createElement("div");e.classList.add("validation-details"),e.innerHTML='\n <div class="validation-details-header">Term Not Found</div>\n <div class="validation-details-section">\n The term referenced here no longer exists in the external specification.\n It may have been renamed, moved, or removed.\n </div>\n <div class="validation-details-footer">\n <em>Check the external specification for updates</em>\n </div>\n ',n.appendChild(e)}return n}function escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function truncateText(e,t){return!e||e.length<=t?e||"":e.substring(0,t)+"..."}function validateXref(e,t,n){if(!n||!n.ghPageUrl)return;const i=t.get(n.ghPageUrl);if(null===i){return void insertIndicatorAfterElement(e,createIndicator("error"))}if(!i)return;const a=n.term.toLowerCase(),r=i.get(a);if(!r){return void insertIndicatorAfterElement(e,createIndicator("missing"))}const o=normalizeContent(n.content),l=normalizeContent(r.rawContent);VALIDATOR_CONFIG.debug&&(console.log("[External Ref Validator] Comparing xref:",n.term),console.log(" Cached length:",o.length,"chars"),console.log(" Live length: ",l.length,"chars"),console.log(" Cached:",o.substring(0,100)),console.log(" Live: ",l.substring(0,100)),o.length!==l.length&&console.log(" Length diff:",Math.abs(o.length-l.length),"chars"));const s=calculateSimilarity(o,l);if(VALIDATOR_CONFIG.debug&&console.log(" Similarity:",(100*s).toFixed(2)+"%"),s<VALIDATOR_CONFIG.similarityThreshold){insertIndicatorAfterElement(e,createIndicator("changed",{oldContent:n.content?extractTextFromHtml(n.content):"No cached content",newContent:r.content||"No live content",similarity:(100*s).toFixed(1)+"%"}))}else if(VALIDATOR_CONFIG.showValidIndicators){insertIndicatorAfterElement(e,createIndicator("valid"))}}function validateTref(e,t,n){if(!n||!n.ghPageUrl)return;const i=t.get(n.ghPageUrl);if(null===i){return void insertIndicatorIntoTref(e,createIndicator("error"))}if(!i)return;const a=n.term.toLowerCase(),r=i.get(a);if(!r){return void insertIndicatorIntoTref(e,createIndicator("missing"))}const o=normalizeContent(n.content),l=normalizeContent(r.rawContent);VALIDATOR_CONFIG.debug&&(console.log("[External Ref Validator] Comparing tref:",n.term),console.log(" Cached length:",o.length,"chars"),console.log(" Live length: ",l.length,"chars"),console.log(" Cached:",o.substring(0,100)),console.log(" Live: ",l.substring(0,100)),o.length!==l.length&&console.log(" Length diff:",Math.abs(o.length-l.length),"chars"));const s=calculateSimilarity(o,l);if(VALIDATOR_CONFIG.debug&&console.log(" Similarity:",(100*s).toFixed(2)+"%"),s<VALIDATOR_CONFIG.similarityThreshold){insertIndicatorIntoTref(e,createIndicator("changed",{oldContent:n.content?extractTextFromHtml(n.content):"No cached content",newContent:r.content||"No live content",similarity:(100*s).toFixed(1)+"%"}))}else if(VALIDATOR_CONFIG.showValidIndicators){insertIndicatorIntoTref(e,createIndicator("valid"))}}function extractTextFromHtml(e){const t=document.createElement("div");return t.innerHTML=e,t.textContent||""}function insertIndicatorAfterElement(e,t){e.nextElementSibling?.classList.contains(VALIDATOR_CONFIG.classes.indicator)||e.insertAdjacentElement("afterend",t)}function insertIndicatorIntoTref(e,t){const n=e.querySelector("span.term-external");n&&(n.querySelector("."+VALIDATOR_CONFIG.classes.indicator)||n.appendChild(t))}function collectExternalSpecs(){const e=new Map;return"undefined"!=typeof allXTrefs&&allXTrefs?.xtrefs?(allXTrefs.xtrefs.forEach((t=>{t.ghPageUrl&&!e.has(t.ghPageUrl)&&e.set(t.ghPageUrl,{url:t.ghPageUrl,specName:t.externalSpec})})),e):(console.warn("[External Ref Validator] allXTrefs data not available"),e)}function findCachedXtrefForXref(e){if("undefined"==typeof allXTrefs||!allXTrefs?.xtrefs)return null;const t=(e.getAttribute("data-local-href")||"").match(/#term:([^:]+):(.+)/);if(!t)return null;const[,n,i]=t;return allXTrefs.xtrefs.find((e=>e.externalSpec===n&&e.term.toLowerCase()===i.toLowerCase()))}function findCachedXtrefForTref(e){if("undefined"==typeof allXTrefs||!allXTrefs?.xtrefs)return null;const t=e.querySelector("[data-original-term]")||e.closest("[data-original-term]");if(!t)return null;const n=t.dataset.originalTerm;return allXTrefs.xtrefs.find((e=>e.term.toLowerCase()===n.toLowerCase()&&e.sourceFiles?.some((e=>"tref"===e.type))))}async function validateExternalRefs(){console.log("[External Ref Validator] Starting validation...");const e=collectExternalSpecs();if(0===e.size)return void console.log("[External Ref Validator] No external specifications to validate");console.log(`[External Ref Validator] Found ${e.size} external specification(s) to validate`);const t=Array.from(e.entries()).map((async([e,t])=>[e,await fetchExternalSpec(e,t.specName)])),n=await Promise.all(t),i=new Map(n),a=document.querySelectorAll("a.x-term-reference");a.forEach((e=>{const t=findCachedXtrefForXref(e);t&&validateXref(e,i,t)}));const r=document.querySelectorAll("dt.term-external");r.forEach((e=>{const t=findCachedXtrefForTref(e);t&&validateTref(e,i,t)})),console.log("[External Ref Validator] Validation complete"),document.dispatchEvent(new CustomEvent("external-refs-validated",{detail:{specsValidated:e.size,xrefsValidated:a.length,trefsValidated:r.length}}))}function initializeValidator(){document.addEventListener("trefs-inserted",(()=>{setTimeout(validateExternalRefs,100)})),setTimeout((()=>{document.querySelector("."+VALIDATOR_CONFIG.classes.indicator)||(console.warn("[External Ref Validator] trefs-inserted event not received, validating anyway"),validateExternalRefs())}),3e3)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",initializeValidator):initializeValidator();
188
189
  /*!
189
190
  * Bootstrap v5.3.3 (https://getbootstrap.com/)
190
191
  * Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
@@ -30,4 +30,5 @@ article a[href^="https://"]:not(.btn)::after,article a[href^=http]:not(.btn)::af
30
30
  #content .figure:has(.scrollHintImage){padding:0;margin:0;width:auto;height:auto}
31
31
  .highlight2{padding-left:1em;padding-right:1em;border:1px dashed #71bbe6;background:#f3f5f53b}
32
32
  #toc ul.toc{counter-reset:toc-section}#toc ul.toc>li{counter-reset:toc-subsection}#toc ul.toc>li>ul>li{counter-reset:toc-subsubsection}#toc ul.toc>li>a::before{counter-increment:toc-section;content:counter(toc-section) ". ";font-weight:700;margin-right:.5em}#toc ul.toc>li>ul>li>a::before{counter-increment:toc-subsection;content:counter(toc-section) "." counter(toc-subsection) " ";font-weight:700;margin-right:.5em}#toc ul.toc>li>ul>li>ul>li>a::before{counter-increment:toc-subsubsection;content:counter(toc-section) "." counter(toc-subsection) "." counter(toc-subsubsection) " ";font-weight:700;margin-right:.5em}main article{counter-reset:main-section}main article h2{counter-reset:main-subsection}main article h3{counter-reset:main-subsubsection}main article h2 .toc-anchor::after{counter-increment:main-section;content:" " counter(main-section) ".";font-weight:700}main article h3 .toc-anchor::after{counter-increment:main-subsection;content:" " counter(main-section) "." counter(main-subsection);font-weight:700}main article h4 .toc-anchor::after{counter-increment:main-subsubsection;content:" " counter(main-section) "." counter(main-subsection) "." counter(main-subsubsection);font-weight:700}main article h5::before,main article h6::before{font-weight:700;margin-right:.5em}@media print{#toc ul.toc>li>a::before,#toc ul.toc>li>ul>li>a::before,#toc ul.toc>li>ul>li>ul>li>a::before,main article h2 .toc-anchor::after,main article h3 .toc-anchor::after,main article h4 .toc-anchor::after{color:#000!important}}
33
+ .external-ref-validation-indicator{display:inline-flex;align-items:center;justify-content:center;position:relative;margin-left:.5em;font-size:1.1em;vertical-align:middle;cursor:help;z-index:10}.external-ref-validation-indicator .indicator-icon{display:inline-flex;align-items:center;justify-content:center;width:1.8em;height:1.8em;border-radius:50%;line-height:1;font-size:1.2em;font-weight:700;transition:all .2s ease-in-out}.external-ref-validation-indicator.external-ref-missing .indicator-icon{background-color:#dc3545;color:#fff;box-shadow:0 0 8px rgba(220,53,69,.6),inset 0 0 4px rgba(0,0,0,.2);animation:pulse-red 2s infinite}.external-ref-validation-indicator.external-ref-changed .indicator-icon{background-color:#ff6b35;color:#fff;box-shadow:0 0 10px rgba(255,107,53,.7),inset 0 0 4px rgba(0,0,0,.2);animation:pulse-orange 2s infinite}.external-ref-validation-indicator.external-ref-error .indicator-icon{background-color:#6c757d;color:#fff;box-shadow:0 0 6px rgba(108,117,125,.5)}.external-ref-validation-indicator.external-ref-valid .indicator-icon{background-color:#28a745;color:#fff;opacity:1;box-shadow:0 0 6px rgba(40,167,69,.4)}.external-ref-validation-indicator:hover .indicator-icon{transform:scale(1.15);box-shadow:0 0 15px rgba(0,0,0,.3)}@keyframes pulse-red{0%,100%{box-shadow:0 0 8px rgba(220,53,69,.6),inset 0 0 4px rgba(0,0,0,.2)}50%{box-shadow:0 0 15px rgba(220,53,69,.9),inset 0 0 4px rgba(0,0,0,.2)}}@keyframes pulse-orange{0%,100%{box-shadow:0 0 10px rgba(255,107,53,.7),inset 0 0 4px rgba(0,0,0,.2)}50%{box-shadow:0 0 18px #ff6b35,inset 0 0 4px rgba(0,0,0,.2)}}.validation-details{display:none;position:absolute;top:100%;left:50%;transform:translateX(-50%);min-width:300px;max-width:450px;padding:12px;margin-top:8px;background:var(--bs-body-bg,#fff);border:1px solid var(--bs-border-color,#dee2e6);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15);font-size:.85rem;text-align:left;line-height:1.4;z-index:1000;color:var(--bs-body-color,#212529)}.validation-details::before{content:'';position:absolute;top:-8px;left:50%;transform:translateX(-50%);border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:8px solid var(--bs-border-color,#dee2e6)}.validation-details::after{content:'';position:absolute;top:-6px;left:50%;transform:translateX(-50%);border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid var(--bs-body-bg,#fff)}.external-ref-validation-indicator.has-details:focus .validation-details,.external-ref-validation-indicator.has-details:hover .validation-details{display:block}.validation-details-header{font-weight:600;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--bs-border-color,#dee2e6)}.validation-similarity{font-size:.75rem;margin-bottom:8px;padding:4px 8px;background:rgba(255,193,7,.1);border-radius:4px;text-align:center;font-weight:500}.external-ref-missing .validation-details-header{color:var(--bs-danger,#dc3545)}.external-ref-changed .validation-details-header{color:var(--bs-warning,#ffc107)}.validation-details-section{margin-bottom:10px}.validation-details-section:last-of-type{margin-bottom:8px}.validation-details-section strong{display:block;margin-bottom:4px;font-size:.8rem;text-transform:uppercase;letter-spacing:.5px;opacity:.7}.validation-content-new,.validation-content-old{padding:8px 10px;border-radius:4px;font-size:.85rem;max-height:100px;overflow-y:auto;word-break:break-word}.validation-content-old{background:rgba(220,53,69,.1);border-left:3px solid var(--bs-danger,#dc3545);text-decoration:line-through;opacity:.8}.validation-content-new{background:rgba(25,135,84,.1);border-left:3px solid var(--bs-success,#198754)}.validation-details-footer{padding-top:8px;border-top:1px solid var(--bs-border-color,#dee2e6);font-size:.75rem;opacity:.8}@media (max-width:576px){.validation-details{min-width:250px;max-width:90vw;left:0;transform:none;font-size:.8rem}.validation-details::after,.validation-details::before{left:15px;transform:none}}[data-bs-theme=dark] .validation-details{background:var(--bs-dark,#212529);border-color:var(--bs-gray-700,#495057)}[data-bs-theme=dark] .validation-details::after{border-bottom-color:var(--bs-dark,#212529)}[data-bs-theme=dark] .validation-content-old{background:rgba(220,53,69,.2)}[data-bs-theme=dark] .validation-content-new{background:rgba(25,135,84,.2)}@keyframes validation-pulse{0%,100%{opacity:1}50%{opacity:.6}}.external-ref-changed .indicator-icon,.external-ref-missing .indicator-icon{animation:validation-pulse 2s ease-in-out infinite}.external-ref-validation-indicator:hover .indicator-icon{animation-play-state:paused;opacity:1}dt.term-external .external-ref-validation-indicator{margin-left:.5em}a.x-term-reference+.external-ref-validation-indicator{margin-right:.25em}@media print{.validation-details{display:none!important}.external-ref-missing::after{content:' [MISSING]';color:#dc3545;font-size:.7em}.external-ref-changed::after{content:' [CHANGED]';color:#ffc107;font-size:.7em}}
33
34
  html{scroll-behavior:smooth;scroll-padding-top:50vh}body:not([hashscroll]) :target{animation:highlight-target 3.5s .25s ease}body:not([hashscroll]) dt:has(:target){animation:highlight-target-parent-dt 3.5s .25s ease}dl.terms-and-definitions-list>.highlight{background-color:#ff0!important;transition:background-color .3s ease-in-out}svg[icon]{width:1.25em;height:1.25em;vertical-align:text-top}@keyframes highlight-target{50%{background-color:#ff0}}@keyframes highlight-target-parent-dt{50%{background-color:#ff0;border:1px solid #00c8ff}}#svg{display:none}main *{overflow-wrap:anywhere;word-break:normal}.table-responsive{overflow-x:auto!important;-webkit-overflow-scrolling:touch;width:100%;max-width:100%}.table-responsive *{overflow-wrap:normal!important;word-break:normal!important;white-space:nowrap!important}dd td img{max-width:30px}.notice{margin:1em 0;padding:.5em .9em .55em .65em;border-left:.5em solid}.notice p{margin:.4em 0 0}.note{background:var(--note-bg);border-color:var(--note-border)}.note .notice-link{display:block;color:var(--note-text)}.issue{background:var(--issue-bg);border-color:var(--issue-border)}.issue .notice-link:before{display:block;color:var(--issue-text)}.warning{background:var(--warning-notice-bg);border-color:var(--warning-notice-border)}.warning .notice-link{display:block;color:var(--warning-notice-text)}.example{color:#cebe00;background:#1a1e23;border-left:.5em solid}.example .notice-link{display:block;color:inherit;font-size:1.1em;font-family:Heebo,sans-serif}.example pre[class*=language-]{padding:0;border-radius:0}.todo{background:var(--todo-bg);border-color:var(--todo-border)}.todo .notice-link{display:block;color:var(--todo-text)}.informative{background:var(--informative-bg);border-color:var(--informative-border)}.informative .notice-link{display:block;color:var(--informative-text)}.alert-primary{background-color:#f9fcff;border-color:#b2ebf2;color:#00838f}.alert-secondary{background-color:#f5f5f5;border-color:#e0e0e0;color:#616161}.alert-success{background-color:#e8f5e9;border-color:#c8e6c9;color:#388e3c}.alert-danger{background-color:#ffebee;border-color:#ef9a9a;color:#d32f2f}.alert-warning{background-color:#fffde7;border-color:#fff9c4;color:#f9a825}.alert-info{background-color:#e1f5fe;border-color:#b3e5fc;color:#0288d1}.alert-light{background-color:#f9f9f9;border-color:#eee;color:#424242}.alert-dark{background-color:#e0e0e0;border-color:#bdbdbd;color:#212121}.alert a{color:inherit;font-weight:700}.alert-primary a{color:#006064}.alert-success a{color:#2e7d32}.alert-danger a{color:#b71c1c}.alert-warning a{color:#f57f17}.alert-info a{color:#01579b}.alert-dark a{color:#000}[data-bs-theme=dark] .alert-primary{background-color:#004d40;border-color:#00695c;color:#b2dfdb}[data-bs-theme=dark] .alert-secondary{background-color:#424242;border-color:#616161;color:#e0e0e0}[data-bs-theme=dark] .alert-success{background-color:#1b5e20;border-color:#2e7d32;color:#a5d6a7}[data-bs-theme=dark] .alert-danger{background-color:#b71c1c;border-color:#c62828;color:#ef9a9a}[data-bs-theme=dark] .alert-warning{background-color:#f57f17;border-color:#ffb300;color:#ffe082}[data-bs-theme=dark] .alert-info{background-color:#01579b;border-color:#0277bd;color:#81d4fa}[data-bs-theme=dark] .alert-light{background-color:#303030;border-color:#424242;color:#e0e0e0}[data-bs-theme=dark] .alert-dark{background-color:#212121;border-color:#424242;color:#bdbdbd}[data-bs-theme=dark] .alert a{color:inherit;font-weight:700}[data-bs-theme=dark] .alert-primary a{color:#80cbc4}[data-bs-theme=dark] .alert-success a{color:#81c784}[data-bs-theme=dark] .alert-danger a{color:#ef5350}[data-bs-theme=dark] .alert-warning a{color:#ffca28}[data-bs-theme=dark] .alert-info a{color:#4fc3f7}[data-bs-theme=dark] .alert-dark a{color:#9e9e9e}#offcanvasSettings .btn-menu-item{border-radius:unset;width:100%;text-align:left;border:1px solid #dee2e6;background-color:var(--card-bg);color:var(--card-text);padding:10px 15px;margin-bottom:5px;transition:background-color .2s ease}#offcanvasSettings .btn-menu-item:hover{background-color:#e9ecef}
@@ -0,0 +1,369 @@
1
+ /**
2
+ * Styles for External Reference Validation Indicators
3
+ *
4
+ * These styles create visual indicators for xref and tref elements
5
+ * that show whether the external reference is still valid:
6
+ * - Missing: Term no longer exists in external spec
7
+ * - Changed: Definition content has been modified
8
+ * - Error: Could not fetch external spec to validate
9
+ * - Valid: Term exists and content matches (optional)
10
+ */
11
+
12
+ /* ===== Base Indicator Styles ===== */
13
+
14
+ /**
15
+ * Base styles for all validation indicators
16
+ * Positioned inline next to the reference
17
+ */
18
+ .external-ref-validation-indicator {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ position: relative;
23
+ margin-left: 0.5em;
24
+ font-size: 1.1em;
25
+ vertical-align: middle;
26
+ cursor: help;
27
+ z-index: 10;
28
+ }
29
+
30
+ /**
31
+ * The icon/emoji display
32
+ * Made larger and more prominent with circular background
33
+ */
34
+ .external-ref-validation-indicator .indicator-icon {
35
+ display: inline-flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ width: 1.8em;
39
+ height: 1.8em;
40
+ border-radius: 50%;
41
+ line-height: 1;
42
+ font-size: 1.2em;
43
+ font-weight: bold;
44
+ transition: all 0.2s ease-in-out;
45
+ }
46
+
47
+ /* ===== Status-specific Styles ===== */
48
+
49
+ /**
50
+ * Missing term indicator - red/warning styling
51
+ * Draws attention to broken references
52
+ */
53
+ .external-ref-validation-indicator.external-ref-missing .indicator-icon {
54
+ background-color: #dc3545;
55
+ color: white;
56
+ box-shadow: 0 0 8px rgba(220, 53, 69, 0.6), inset 0 0 4px rgba(0, 0, 0, 0.2);
57
+ animation: pulse-red 2s infinite;
58
+ }
59
+
60
+ /**
61
+ * Changed definition indicator - orange/red styling
62
+ * Indicates content drift that may need review
63
+ */
64
+ .external-ref-validation-indicator.external-ref-changed .indicator-icon {
65
+ background-color: #ff6b35;
66
+ color: white;
67
+ box-shadow: 0 0 10px rgba(255, 107, 53, 0.7), inset 0 0 4px rgba(0, 0, 0, 0.2);
68
+ animation: pulse-orange 2s infinite;
69
+ }
70
+
71
+ /**
72
+ * Error indicator - gray styling
73
+ * Shows that validation could not be performed
74
+ */
75
+ .external-ref-validation-indicator.external-ref-error .indicator-icon {
76
+ background-color: #6c757d;
77
+ color: white;
78
+ box-shadow: 0 0 6px rgba(108, 117, 125, 0.5);
79
+ }
80
+
81
+ /**
82
+ * Valid indicator - green/success styling
83
+ * Confirms the reference is current (optional visibility)
84
+ */
85
+ .external-ref-validation-indicator.external-ref-valid .indicator-icon {
86
+ background-color: #28a745;
87
+ color: white;
88
+ opacity: 1;
89
+ box-shadow: 0 0 6px rgba(40, 167, 69, 0.4);
90
+ }
91
+
92
+ /**
93
+ * Hover effect - make it even more prominent on hover
94
+ */
95
+ .external-ref-validation-indicator:hover .indicator-icon {
96
+ transform: scale(1.15);
97
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
98
+ }
99
+
100
+ /**
101
+ * Pulse animations for attention-grabbing indicators
102
+ */
103
+ @keyframes pulse-red {
104
+ 0%, 100% {
105
+ box-shadow: 0 0 8px rgba(220, 53, 69, 0.6), inset 0 0 4px rgba(0, 0, 0, 0.2);
106
+ }
107
+ 50% {
108
+ box-shadow: 0 0 15px rgba(220, 53, 69, 0.9), inset 0 0 4px rgba(0, 0, 0, 0.2);
109
+ }
110
+ }
111
+
112
+ @keyframes pulse-orange {
113
+ 0%, 100% {
114
+ box-shadow: 0 0 10px rgba(255, 107, 53, 0.7), inset 0 0 4px rgba(0, 0, 0, 0.2);
115
+ }
116
+ 50% {
117
+ box-shadow: 0 0 18px rgba(255, 107, 53, 1), inset 0 0 4px rgba(0, 0, 0, 0.2);
118
+ }
119
+ }
120
+
121
+ /* ===== Details Popup ===== */
122
+
123
+ /**
124
+ * Container for the details popup
125
+ * Hidden by default, shown on hover
126
+ */
127
+ .validation-details {
128
+ display: none;
129
+ position: absolute;
130
+ top: 100%;
131
+ left: 50%;
132
+ transform: translateX(-50%);
133
+ min-width: 300px;
134
+ max-width: 450px;
135
+ padding: 12px;
136
+ margin-top: 8px;
137
+ background: var(--bs-body-bg, #fff);
138
+ border: 1px solid var(--bs-border-color, #dee2e6);
139
+ border-radius: 8px;
140
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
141
+ font-size: 0.85rem;
142
+ text-align: left;
143
+ line-height: 1.4;
144
+ z-index: 1000;
145
+ color: var(--bs-body-color, #212529);
146
+ }
147
+
148
+ /**
149
+ * Arrow pointer for the popup
150
+ */
151
+ .validation-details::before {
152
+ content: '';
153
+ position: absolute;
154
+ top: -8px;
155
+ left: 50%;
156
+ transform: translateX(-50%);
157
+ border-left: 8px solid transparent;
158
+ border-right: 8px solid transparent;
159
+ border-bottom: 8px solid var(--bs-border-color, #dee2e6);
160
+ }
161
+
162
+ .validation-details::after {
163
+ content: '';
164
+ position: absolute;
165
+ top: -6px;
166
+ left: 50%;
167
+ transform: translateX(-50%);
168
+ border-left: 6px solid transparent;
169
+ border-right: 6px solid transparent;
170
+ border-bottom: 6px solid var(--bs-body-bg, #fff);
171
+ }
172
+
173
+ /**
174
+ * Show details on hover
175
+ */
176
+ .external-ref-validation-indicator.has-details:hover .validation-details,
177
+ .external-ref-validation-indicator.has-details:focus .validation-details {
178
+ display: block;
179
+ }
180
+
181
+ /**
182
+ * Header section of the popup
183
+ */
184
+ .validation-details-header {
185
+ font-weight: 600;
186
+ margin-bottom: 10px;
187
+ padding-bottom: 8px;
188
+ border-bottom: 1px solid var(--bs-border-color, #dee2e6);
189
+ }
190
+
191
+ /**
192
+ * Similarity score display
193
+ */
194
+ .validation-similarity {
195
+ font-size: 0.75rem;
196
+ margin-bottom: 8px;
197
+ padding: 4px 8px;
198
+ background: rgba(255, 193, 7, 0.1);
199
+ border-radius: 4px;
200
+ text-align: center;
201
+ font-weight: 500;
202
+ }
203
+
204
+ /* Missing indicator header - red theme */
205
+ .external-ref-missing .validation-details-header {
206
+ color: var(--bs-danger, #dc3545);
207
+ }
208
+
209
+ /* Changed indicator header - orange theme */
210
+ .external-ref-changed .validation-details-header {
211
+ color: var(--bs-warning, #ffc107);
212
+ }
213
+
214
+ /**
215
+ * Content sections within the popup
216
+ */
217
+ .validation-details-section {
218
+ margin-bottom: 10px;
219
+ }
220
+
221
+ .validation-details-section:last-of-type {
222
+ margin-bottom: 8px;
223
+ }
224
+
225
+ .validation-details-section strong {
226
+ display: block;
227
+ margin-bottom: 4px;
228
+ font-size: 0.8rem;
229
+ text-transform: uppercase;
230
+ letter-spacing: 0.5px;
231
+ opacity: 0.7;
232
+ }
233
+
234
+ /**
235
+ * Content comparison boxes
236
+ */
237
+ .validation-content-old,
238
+ .validation-content-new {
239
+ padding: 8px 10px;
240
+ border-radius: 4px;
241
+ font-size: 0.85rem;
242
+ max-height: 100px;
243
+ overflow-y: auto;
244
+ word-break: break-word;
245
+ }
246
+
247
+ /* Old content - strikethrough styling */
248
+ .validation-content-old {
249
+ background: rgba(220, 53, 69, 0.1);
250
+ border-left: 3px solid var(--bs-danger, #dc3545);
251
+ text-decoration: line-through;
252
+ opacity: 0.8;
253
+ }
254
+
255
+ /* New content - highlight styling */
256
+ .validation-content-new {
257
+ background: rgba(25, 135, 84, 0.1);
258
+ border-left: 3px solid var(--bs-success, #198754);
259
+ }
260
+
261
+ /**
262
+ * Footer section with action hint
263
+ */
264
+ .validation-details-footer {
265
+ padding-top: 8px;
266
+ border-top: 1px solid var(--bs-border-color, #dee2e6);
267
+ font-size: 0.75rem;
268
+ opacity: 0.8;
269
+ }
270
+
271
+ /* ===== Responsive Adjustments ===== */
272
+
273
+ @media (max-width: 576px) {
274
+ .validation-details {
275
+ min-width: 250px;
276
+ max-width: 90vw;
277
+ left: 0;
278
+ transform: none;
279
+ font-size: 0.8rem;
280
+ }
281
+
282
+ .validation-details::before,
283
+ .validation-details::after {
284
+ left: 15px;
285
+ transform: none;
286
+ }
287
+ }
288
+
289
+ /* ===== Dark Mode Support ===== */
290
+
291
+ [data-bs-theme="dark"] .validation-details {
292
+ background: var(--bs-dark, #212529);
293
+ border-color: var(--bs-gray-700, #495057);
294
+ }
295
+
296
+ [data-bs-theme="dark"] .validation-details::after {
297
+ border-bottom-color: var(--bs-dark, #212529);
298
+ }
299
+
300
+ [data-bs-theme="dark"] .validation-content-old {
301
+ background: rgba(220, 53, 69, 0.2);
302
+ }
303
+
304
+ [data-bs-theme="dark"] .validation-content-new {
305
+ background: rgba(25, 135, 84, 0.2);
306
+ }
307
+
308
+ /* ===== Indicator Animation ===== */
309
+
310
+ /**
311
+ * Subtle pulse animation for attention-drawing indicators
312
+ */
313
+ @keyframes validation-pulse {
314
+ 0%, 100% {
315
+ opacity: 1;
316
+ }
317
+ 50% {
318
+ opacity: 0.6;
319
+ }
320
+ }
321
+
322
+ .external-ref-missing .indicator-icon,
323
+ .external-ref-changed .indicator-icon {
324
+ animation: validation-pulse 2s ease-in-out infinite;
325
+ }
326
+
327
+ /* Pause animation on hover to reduce distraction */
328
+ .external-ref-validation-indicator:hover .indicator-icon {
329
+ animation-play-state: paused;
330
+ opacity: 1;
331
+ }
332
+
333
+ /* ===== Integration with Term Styling ===== */
334
+
335
+ /**
336
+ * Ensure indicators work well within dt elements (for trefs)
337
+ */
338
+ dt.term-external .external-ref-validation-indicator {
339
+ margin-left: 0.5em;
340
+ }
341
+
342
+ /**
343
+ * Ensure indicators work well within inline text (for xrefs)
344
+ */
345
+ a.x-term-reference + .external-ref-validation-indicator {
346
+ margin-right: 0.25em;
347
+ }
348
+
349
+ /* ===== Print Styles ===== */
350
+
351
+ @media print {
352
+ /* Hide interactive elements but show status text */
353
+ .validation-details {
354
+ display: none !important;
355
+ }
356
+
357
+ /* Show a simpler indicator for print */
358
+ .external-ref-missing::after {
359
+ content: ' [MISSING]';
360
+ color: #dc3545;
361
+ font-size: 0.7em;
362
+ }
363
+
364
+ .external-ref-changed::after {
365
+ content: ' [CHANGED]';
366
+ color: #ffc107;
367
+ font-size: 0.7em;
368
+ }
369
+ }