crtc page: add 5-min-read TL;DR + collapsible deep-detail sections (non-destructive JS/CSS enhancement)
This commit is contained in:
parent
4f52d12629
commit
0562fd2bd3
3 changed files with 247 additions and 2 deletions
104
site/public/js/pw-crtc-collapse.css
Normal file
104
site/public/js/pw-crtc-collapse.css
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/* pw-crtc-collapse.css — styles for the CRTC page reading aid (TL;DR + accordions). */
|
||||||
|
|
||||||
|
.pw-tldr {
|
||||||
|
border: 1px solid #cfe0f5;
|
||||||
|
background: linear-gradient(135deg, #f0f6ff 0%, #eef9f3 100%);
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 1.1rem 1.25rem;
|
||||||
|
margin: 0 0 1.75rem;
|
||||||
|
}
|
||||||
|
.pw-tldr-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
color: #1a2744;
|
||||||
|
}
|
||||||
|
.pw-tldr-badge {
|
||||||
|
background: #059669;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 0.18rem 0.5rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
.pw-tldr-lead {
|
||||||
|
margin: 0 0 0.85rem;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 0.96rem;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
.pw-tldr-jump {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.45rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
.pw-tldr-jump > span {
|
||||||
|
color: #64748b;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-right: 0.15rem;
|
||||||
|
}
|
||||||
|
.pw-tldr-chip {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.28rem 0.7rem;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 999px;
|
||||||
|
color: #1d4ed8;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
transition: background 0.12s, border-color 0.12s;
|
||||||
|
}
|
||||||
|
.pw-tldr-chip:hover {
|
||||||
|
background: #1d4ed8;
|
||||||
|
color: #fff;
|
||||||
|
border-color: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collapsible section */
|
||||||
|
.pw-collapse {
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin: 0.75rem 0;
|
||||||
|
background: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.pw-collapse[open] {
|
||||||
|
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.06);
|
||||||
|
}
|
||||||
|
.pw-collapse-summary {
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0.95rem 1.15rem;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
color: #1a2744;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.pw-collapse-summary::-webkit-details-marker { display: none; }
|
||||||
|
.pw-collapse-summary::before {
|
||||||
|
content: "";
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 0.5rem;
|
||||||
|
height: 0.5rem;
|
||||||
|
border-right: 2px solid #2d4e78;
|
||||||
|
border-bottom: 2px solid #2d4e78;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transition: transform 0.15s ease;
|
||||||
|
}
|
||||||
|
.pw-collapse[open] > .pw-collapse-summary::before {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
.pw-collapse-summary:hover { background: #f8fafc; }
|
||||||
|
.pw-collapse-body {
|
||||||
|
padding: 0 1.15rem 1.1rem;
|
||||||
|
}
|
||||||
|
.pw-collapse-body > h2 { display: none; }
|
||||||
141
site/public/js/pw-crtc-collapse.js
Normal file
141
site/public/js/pw-crtc-collapse.js
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* pw-crtc-collapse.js — progressive-enhancement reading aid for the long
|
||||||
|
* Canada CRTC carrier page (public/services/telecom/canada-crtc/index.html).
|
||||||
|
*
|
||||||
|
* Why a runtime script instead of editing the HTML: that page is a single
|
||||||
|
* 183 KB minified file with auto-generated markup whose section headings sit
|
||||||
|
* at inconsistent DOM depths. Rewriting it by hand risks corrupting the markup
|
||||||
|
* and is hard to maintain. This script enhances it non-destructively:
|
||||||
|
*
|
||||||
|
* 1. Injects a "5-minute read" TL;DR + jump menu at the top of the article.
|
||||||
|
* 2. Collapses a curated set of deep-detail H2 sections into <details>-style
|
||||||
|
* accordions (collapsed by default) so the page reads short, while every
|
||||||
|
* word remains present for SEO and for anyone who expands it.
|
||||||
|
*
|
||||||
|
* It is idempotent (guards against double-run) and degrades gracefully: with
|
||||||
|
* JS off, the full page renders exactly as before.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
if (window.__pwCrtcCollapse) return;
|
||||||
|
window.__pwCrtcCollapse = true;
|
||||||
|
|
||||||
|
// H2 headings (matched by normalized text prefix) to collapse by default.
|
||||||
|
// Order here is also the order used in the TL;DR jump menu.
|
||||||
|
var COLLAPSE = [
|
||||||
|
{ key: "why canada", label: "Why Canada: FCC vs CRTC" },
|
||||||
|
{ key: "corporate tax comparison", label: "Corporate tax comparison (BC vs US)" },
|
||||||
|
{ key: "canada telecom m&a", label: "Canada telecom M&A climate" },
|
||||||
|
{ key: "step 6: canadian business banking", label: "Canadian business banking" },
|
||||||
|
{ key: "included: canadian wholesale", label: "Wholesale vendor directory" },
|
||||||
|
{ key: "frequently asked questions", label: "FAQ", open: false },
|
||||||
|
{ key: "us wholesale voice market", label: "US wholesale / DID restrictions" },
|
||||||
|
{ key: "the growing burden", label: "The growing burden of a US carrier" },
|
||||||
|
{ key: "what you'll need", label: "What you'll need to get started" }
|
||||||
|
];
|
||||||
|
|
||||||
|
function norm(s) {
|
||||||
|
return (s || "").replace(/\s+/g, " ").trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function ready(fn) {
|
||||||
|
if (document.readyState !== "loading") fn();
|
||||||
|
else document.addEventListener("DOMContentLoaded", fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function () {
|
||||||
|
var h2s = Array.prototype.slice.call(document.querySelectorAll("h2"));
|
||||||
|
if (!h2s.length) return;
|
||||||
|
|
||||||
|
var made = [];
|
||||||
|
|
||||||
|
COLLAPSE.forEach(function (cfg) {
|
||||||
|
var h2 = h2s.find(function (h) {
|
||||||
|
return norm(h.textContent).indexOf(cfg.key) === 0 ||
|
||||||
|
norm(h.textContent).indexOf(cfg.key) !== -1;
|
||||||
|
});
|
||||||
|
if (!h2 || h2.dataset.pwCollapsed) return;
|
||||||
|
|
||||||
|
var parent = h2.parentNode;
|
||||||
|
// Collect this H2 plus its following siblings up to the next H2 sibling.
|
||||||
|
var nodes = [h2];
|
||||||
|
var n = h2.nextSibling;
|
||||||
|
while (n) {
|
||||||
|
if (n.nodeType === 1 && n.tagName === "H2") break;
|
||||||
|
var next = n.nextSibling;
|
||||||
|
nodes.push(n);
|
||||||
|
n = next;
|
||||||
|
}
|
||||||
|
if (nodes.length < 2) {
|
||||||
|
// Heading has no sibling body at this level (body nested elsewhere);
|
||||||
|
// skip rather than risk an empty/incorrect accordion.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var details = document.createElement("details");
|
||||||
|
details.className = "pw-collapse";
|
||||||
|
if (cfg.open) details.open = true;
|
||||||
|
|
||||||
|
var summary = document.createElement("summary");
|
||||||
|
summary.className = "pw-collapse-summary";
|
||||||
|
summary.textContent = h2.textContent.replace(/\s+/g, " ").trim();
|
||||||
|
details.appendChild(summary);
|
||||||
|
|
||||||
|
var body = document.createElement("div");
|
||||||
|
body.className = "pw-collapse-body";
|
||||||
|
|
||||||
|
// Move the original H2 (hidden, keeps heading in DOM for SEO) + siblings in.
|
||||||
|
h2.style.display = "none";
|
||||||
|
h2.dataset.pwCollapsed = "1";
|
||||||
|
parent.insertBefore(details, nodes[0]);
|
||||||
|
nodes.forEach(function (node) { body.appendChild(node); });
|
||||||
|
details.appendChild(body);
|
||||||
|
|
||||||
|
var id = "crtc-" + cfg.key.replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
||||||
|
details.id = id;
|
||||||
|
made.push({ id: id, label: cfg.label });
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!made.length) return;
|
||||||
|
|
||||||
|
// Build the TL;DR + jump menu and insert it right after the hero/pricing card.
|
||||||
|
var anchor = document.querySelector("nav[aria-label], .max-w-4xl") || document.body;
|
||||||
|
var tldr = document.createElement("div");
|
||||||
|
tldr.className = "pw-tldr";
|
||||||
|
tldr.innerHTML =
|
||||||
|
'<div class="pw-tldr-head">' +
|
||||||
|
'<span class="pw-tldr-badge">5-min read</span>' +
|
||||||
|
'<strong>The short version</strong></div>' +
|
||||||
|
'<p class="pw-tldr-lead">Become a single <strong>Canadian CRTC/BITS carrier</strong> ' +
|
||||||
|
'and lawfully serve US & international customers \u2014 without taking on the US ' +
|
||||||
|
'FCC 499/USF, RMD, STIR/SHAKEN and state-PUC stack a US carrier carries. ' +
|
||||||
|
'A Canadian carrier serving US customers as one entity is a common, established ' +
|
||||||
|
'structure (per public FCC records). Details below are optional \u2014 tap any to expand.</p>' +
|
||||||
|
'<div class="pw-tldr-jump"><span>Jump to:</span></div>';
|
||||||
|
|
||||||
|
var jump = tldr.querySelector(".pw-tldr-jump");
|
||||||
|
made.forEach(function (m) {
|
||||||
|
var a = document.createElement("a");
|
||||||
|
a.href = "#" + m.id;
|
||||||
|
a.className = "pw-tldr-chip";
|
||||||
|
a.textContent = m.label;
|
||||||
|
a.addEventListener("click", function (e) {
|
||||||
|
var d = document.getElementById(m.id);
|
||||||
|
if (d) {
|
||||||
|
d.open = true;
|
||||||
|
e.preventDefault();
|
||||||
|
d.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
jump.appendChild(a);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Insert TL;DR before the first collapsed section for a clean top-of-article placement.
|
||||||
|
var firstDetails = document.querySelector("details.pw-collapse");
|
||||||
|
if (firstDetails && firstDetails.parentNode) {
|
||||||
|
firstDetails.parentNode.insertBefore(tldr, firstDetails);
|
||||||
|
} else {
|
||||||
|
anchor.insertBefore(tldr, anchor.firstChild);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue