/* ============================================================
   Harrington Compliance — page-specific modules
   Loaded by courses.html, data-protection.html, platform.html
   ============================================================ */

/* ---------- A. Course catalogue ---------- */
/* Ratio tuned so the index sits at ~560px and the panel at ~545px; --maxw
   carries the extra 8px that needs. The gap caps at 48px rather than 60 —
   the container is already capped, so a growing gap only ate the columns
   back as the viewport widened. */
.cat-layout{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.973fr);gap:clamp(26px,3.6vw,48px);align-items:start}
@media(max-width:940px){.cat-layout{grid-template-columns:minmax(0,1fr)}}

.cat-hint{
  display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;
  padding:.85rem 1.15rem;border-radius:var(--r-pill);
  background:var(--blue-50);border:1px solid var(--blue-100);
  font-size:.88rem;color:var(--blue-800);font-weight:550;
  margin-bottom:1.6rem;
}
.cat-hint svg{width:17px;height:17px;color:var(--blue-600);flex:none}

.cat-group{margin-bottom:clamp(24px,3vw,40px)}
.cat-group-head{
  display:flex;align-items:center;gap:.8rem;
  padding:.5rem 0 .9rem;margin-bottom:.4rem;
  border-bottom:1px solid var(--line);
}
.cat-group-head h2{font-size:.95rem;margin:0;letter-spacing:-.01em;font-weight:800}
.cat-group-head .n{margin-left:auto;font-family:var(--f-mono);font-size:.7rem;color:var(--ink-muted);letter-spacing:.1em}
.cat-group-head .swatch{width:10px;height:10px;border-radius:3px;flex:none}

.cat-row{
  display:flex;align-items:center;gap:1rem;width:100%;text-align:left;
  padding:.9rem 1rem;border-radius:14px;
  border:1px solid transparent;background:none;cursor:pointer;
  transition:background .28s,border-color .28s,transform .3s var(--ease-out),box-shadow .3s;
}
.cat-row:hover{background:var(--paper);border-color:var(--line);transform:translateX(3px)}
.cat-row.is-active{background:var(--paper);border-color:var(--blue-300);box-shadow:0 10px 26px -14px rgba(18,86,232,.5)}
.cat-row.is-active .cat-ico{background:linear-gradient(140deg,var(--blue-600),var(--blue-800));color:#fff;border-color:transparent}
.cat-ico{
  width:42px;height:42px;border-radius:13px;flex:none;display:grid;place-items:center;
  background:var(--paper);border:1px solid var(--line);color:var(--blue-700);
  transition:background .3s,color .3s,border-color .3s;
}
.cat-ico .icon{width:26px;height:26px}
.cat-row b{display:block;font-family:var(--f-display);font-weight:700;font-size:.98rem;color:var(--ink);letter-spacing:-.015em;line-height:1.25}
.cat-row small{display:block;font-family:var(--f-mono);font-size:.68rem;color:var(--ink-muted);margin-top:3px;letter-spacing:.04em}
.cat-row .pinmark{
  margin-left:auto;flex:none;width:22px;height:22px;border-radius:50%;
  display:grid;place-items:center;color:var(--blue-600);
  opacity:0;transform:scale(.6);transition:opacity .3s,transform .35s var(--ease-spring);
}
.cat-row .pinmark svg{width:13px;height:13px}
.cat-row.is-pinned .pinmark{opacity:1;transform:none}
.cat-row.is-pinned{border-color:var(--blue-500);box-shadow:0 0 0 3px var(--blue-100)}

/* ---------- Jump pills ----------
   The interactive counterpart to .pill — used for the sector jump links
   in the sectors.html hero. */
.chip{
  display:inline-flex;align-items:center;
  padding:.55rem 1.1rem;border-radius:var(--r-pill);
  font-family:var(--f-display);font-weight:650;font-size:.86rem;
  background:var(--paper);color:var(--ink-2);text-decoration:none;
  border:1px solid var(--line);cursor:pointer;
  transition:border-color .25s var(--ease-out),color .25s,transform .25s var(--ease-out),box-shadow .25s;
}
.chip:hover{border-color:var(--blue-300);color:var(--blue-700);transform:translateY(-2px);box-shadow:var(--sh-sm)}

.cat-panel{position:sticky;top:100px}
/* Below the two-column layout the preview has nowhere useful to sit, so the
   catalogue becomes a plain list and each row goes straight to its course. */
@media(max-width:940px){.cat-panel{display:none}}

.cpanel{border-radius:var(--r-xl);border:1px solid var(--line);background:var(--paper);box-shadow:var(--sh-lg);overflow:hidden}
.cpanel-vis{position:relative;padding:clamp(20px,2.6vw,30px);background:linear-gradient(150deg,#0A2A66,#1046B5 55%,#062250);color:#fff;overflow:hidden}
.cpanel-vis::before{
  content:"";position:absolute;inset:0;
  background-image:linear-gradient(rgba(255,255,255,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.06) 1px,transparent 1px);
  background-size:34px 34px;
}
.cpanel-vis::after{
  content:"";position:absolute;width:320px;height:320px;border-radius:50%;
  background:radial-gradient(circle,rgba(0,195,240,.42),transparent 66%);
  top:-140px;right:-100px;
}
.cpanel-vis>*{position:relative;z-index:1}
.cpanel-ico{
  width:64px;height:64px;border-radius:19px;display:grid;place-items:center;
  background:rgba(255,255,255,.13);border:1px solid rgba(255,255,255,.26);
  backdrop-filter:blur(8px);margin-bottom:1rem;
}
.cpanel-ico .icon{width:34px;height:34px;stroke-width:1.5}
.cpanel-cat{font-family:var(--f-mono);font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;color:var(--cyan-300);font-weight:600;display:block;margin-bottom:.5rem}
/* A label on the decorative panel, not a section heading — kept as a span so
   it stops duplicating the H1 in the document outline. */
.cpanel-title{display:block;font-family:var(--f-display);font-weight:800;letter-spacing:-.03em;font-size:clamp(1.4rem,2.4vw,1.85rem);color:#fff;line-height:1.1;margin:0}
.cpanel-body{padding:clamp(20px,2.6vw,30px)}
.cpanel-blurb{font-size:.98rem;color:var(--ink-3);line-height:1.6;margin-bottom:1.3rem}
.cpanel-meta{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;
  background:var(--line-soft);border:1px solid var(--line-soft);border-radius:14px;
  overflow:hidden;margin:0 0 1.4rem;
}
.cpanel-meta div{background:var(--paper-2);padding:.85rem .9rem}
.cpanel-meta dt{font-family:var(--f-mono);font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-muted);margin-bottom:.3rem}
.cpanel-meta dd{margin:0;font-family:var(--f-display);font-weight:700;font-size:.9rem;color:var(--ink);letter-spacing:-.01em}
.cpanel-sub{font-family:var(--f-mono);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:var(--blue-600);font-weight:600;margin-bottom:.7rem}
.cpanel-outline{list-style:none;padding:0;margin:0 0 1.5rem;display:grid;gap:.1rem}
.cpanel-outline li{display:flex;gap:.7rem;align-items:flex-start;margin:0;font-size:.91rem;color:var(--ink-2);line-height:1.5;padding:.4rem 0}
.cpanel-outline li::before{content:"";width:6px;height:6px;border-radius:2px;margin-top:.55em;flex:none;background:linear-gradient(140deg,var(--cyan-500),var(--blue-600))}
.cpanel-legal{
  display:flex;gap:.7rem;align-items:flex-start;padding:.9rem 1rem;
  background:var(--blue-50);border:1px solid var(--blue-100);border-radius:12px;
  font-size:.85rem;color:var(--blue-800);line-height:1.5;margin-bottom:1.4rem;
}
.cpanel-legal svg{width:16px;height:16px;flex:none;margin-top:2px;color:var(--blue-600)}
.cpanel-body,.cpanel-vis>*{transition:opacity .2s,transform .2s}
.cpanel.is-swapping .cpanel-body,.cpanel.is-swapping .cpanel-vis>*{opacity:.2;transform:translateY(5px)}
@media(max-width:940px){
  .cpanel-outline,.cpanel-legal{display:none}
  .cpanel-vis{padding:16px 20px}
  .cpanel-ico{width:46px;height:46px;border-radius:14px;margin-bottom:.7rem}
  .cpanel-ico .icon{width:26px;height:26px}
  .cpanel-body{padding:18px 20px}
  .cpanel-blurb{font-size:.9rem;margin-bottom:1rem}
}

/* ---------- B. Live interactions ---------- */
.ix-card{border-radius:var(--r-xl);border:1px solid var(--line);background:var(--paper);box-shadow:var(--sh-md);overflow:hidden;height:100%;display:flex;flex-direction:column}
.ix-head{
  padding:clamp(18px,2.2vw,26px);border-bottom:1px solid var(--line-soft);
  display:flex;gap:1rem;align-items:flex-start;
  background:linear-gradient(140deg,var(--blue-50),rgba(255,255,255,0));
}
.ix-head .iconwell{width:44px;height:44px;border-radius:13px}
.ix-head .iconwell .icon{width:22px;height:22px}
.ix-head h3{font-size:1.06rem;margin:0 0 .25rem}
.ix-head p{font-size:.88rem;color:var(--ink-3);margin:0}
.ix-head .score{
  margin-left:auto;flex:none;font-family:var(--f-mono);font-size:.78rem;font-weight:600;
  padding:.35rem .75rem;border-radius:var(--r-pill);
  background:var(--paper);border:1px solid var(--line);color:var(--ink-2);white-space:nowrap;
}
.ix-body{padding:clamp(18px,2.2vw,26px);flex:1;display:flex;flex-direction:column}
.ix-foot{
  padding:.9rem clamp(18px,2.2vw,26px);border-top:1px solid var(--line-soft);
  background:var(--paper-2);display:flex;align-items:center;gap:1rem;
  font-size:.84rem;color:var(--ink-muted);min-height:56px;
}
.ix-foot .status{font-weight:600;color:var(--ink-2)}
.ix-reset{margin-left:auto;font-family:var(--f-display);font-weight:650;font-size:.82rem;color:var(--blue-700);display:inline-flex;align-items:center;gap:.35rem}
.ix-reset svg{width:14px;height:14px}
.ix-reset:hover{text-decoration:underline}

/* Wide column gap leaves room for the connector arrows to read. Terms are
   short and definitions long, so the split is deliberately uneven. */
.match-grid{
  position:relative;
  display:grid;grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
  gap:.5rem clamp(26px,5vw,58px);
}
.match-col{display:grid;gap:.5rem;align-content:start}
/* Spread the short terms down the full height so each arrow has its own lane. */
.match-col[data-match-terms]{align-content:space-between}

/* Connector overlay — sits above the buttons but never intercepts a tap. */
.match-links{
  position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;z-index:2;overflow:visible;
  color:var(--mint-500);
}
.match-links path{
  stroke-dasharray:1000;stroke-dashoffset:1000;
  animation:matchDraw .55s var(--ease-out) forwards;
}
@keyframes matchDraw{to{stroke-dashoffset:0}}

.match-btn{
  padding:.75rem .9rem;border-radius:12px;text-align:left;
  background:var(--paper-2);border:1.5px solid var(--line);
  font-size:.87rem;line-height:1.35;color:var(--ink-2);font-weight:550;
  transition:all .25s var(--ease-out);
}
/* Terms carry their own mark. */
.match-btn--term{display:flex;align-items:center;gap:.6rem}
.match-btn--term .icon{width:22px;height:22px;flex:none;color:var(--blue-600);transition:color .25s}
.match-btn--term.ok .icon{color:#0A8A6C}
.match-btn--term span{min-width:0}
/* Solved buttons stay put — a hover lift would pull them off their arrow. */
.match-btn:hover:not(:disabled):not(.ok){border-color:var(--blue-300);background:var(--paper);transform:translateY(-1px)}
.match-btn.sel{border-color:var(--blue-600);background:var(--blue-50);color:var(--blue-800);box-shadow:0 0 0 3px var(--blue-100)}
.match-btn.ok{border-color:#8FE4CE;background:linear-gradient(110deg,#EFFCF8,#fff);color:#0A6A54;cursor:default}
.match-btn.ok::after{content:" \2713";font-weight:800}

/* Completion mark, injected by interactions.js when the last pair lands, so
   no page needs it in its markup. The ring draws round, then the tick draws
   through it, then the whole thing lifts away and leaves the board visible. */
.match-done{
  position:absolute;inset:0;z-index:5;display:grid;place-items:center;
  pointer-events:none;
  background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.9) 20%,rgba(255,255,255,0) 68%);
  animation:matchDoneIn .28s var(--ease-out) both,matchDoneOut .55s var(--ease-out) 2.05s both;
}
.match-done svg{width:78px;height:78px;overflow:visible;filter:drop-shadow(0 6px 16px rgba(18,198,155,.4))}
/* 170 is the circumference at r=27; 41 is the length of the tick path. */
.match-done .ring{
  stroke:var(--mint-500);stroke-dasharray:170;stroke-dashoffset:170;
  transform:rotate(-90deg);transform-origin:32px 32px;
  animation:matchDraw .5s var(--ease-out) .04s forwards;
}
.match-done .tick{
  stroke:var(--mint-500);stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:41;stroke-dashoffset:41;
  animation:matchDraw .34s var(--ease-out) .46s forwards;
}
@keyframes matchDraw{to{stroke-dashoffset:0}}
@keyframes matchDoneIn{from{opacity:0;transform:scale(.8)}to{opacity:1;transform:none}}
@keyframes matchDoneOut{to{opacity:0;transform:scale(1.08)}}
/* The arrow already marks the term as solved — the tick belongs on the definition. */
.match-btn--term.ok::after{content:none}
.match-btn.bad{animation:shake .42s}
@keyframes shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-7px)}40%{transform:translateX(6px)}60%{transform:translateX(-4px)}80%{transform:translateX(3px)}}
/* On narrow screens the term needs to fit its column without eating the arrow lane. */
@media(max-width:600px){
  .match-grid{gap:.5rem 22px;grid-template-columns:min-content minmax(0,1fr)}
  .match-btn{padding:.6rem .65rem;font-size:.8rem}
  .match-btn--term{gap:.4rem}
  .match-btn--term .icon{width:17px;height:17px}
}

.judge-progress{display:flex;gap:5px;margin-bottom:1.1rem}
.judge-progress i{height:4px;flex:1;border-radius:2px;background:var(--line);transition:background .3s}
.judge-progress i.hit{background:var(--mint-500)}
.judge-progress i.miss{background:var(--rose-500)}
.judge-progress i.now{background:var(--blue-500)}
.judge-q{font-family:var(--f-display);font-weight:700;font-size:1.04rem;color:var(--ink);line-height:1.4;letter-spacing:-.018em;margin-bottom:.6rem}
.judge-scenario{font-size:.94rem;color:var(--ink-3);line-height:1.6;margin-bottom:1.2rem;flex:1}
.judge-btns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.7rem}
.judge-btn{
  padding:.9rem 1rem;border-radius:13px;font-family:var(--f-display);font-weight:700;font-size:.94rem;
  border:1.5px solid var(--line);background:var(--paper-2);color:var(--ink);
  transition:all .25s var(--ease-out);
}
.judge-btn:hover:not(:disabled){transform:translateY(-2px);box-shadow:var(--sh-sm);border-color:var(--blue-300)}
.judge-btn.right{background:linear-gradient(140deg,#12C69B,#0A9E7B);color:#fff;border-color:transparent}
.judge-btn.wrong{background:linear-gradient(140deg,#F04E6E,#D02A4C);color:#fff;border-color:transparent}
.judge-feedback{
  margin-top:1rem;padding:.85rem 1rem;border-radius:12px;font-size:.89rem;line-height:1.55;
  background:var(--blue-50);border:1px solid var(--blue-100);color:var(--blue-900);display:none;
}
.judge-feedback.show{display:block;animation:popin .35s var(--ease-out)}
@keyframes popin{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}

.seq-list{display:grid;gap:.55rem;margin-bottom:1rem}
.seq-btn{
  display:flex;align-items:center;gap:.85rem;text-align:left;
  padding:.8rem .9rem;border-radius:13px;
  background:var(--paper-2);border:1.5px solid var(--line);
  font-size:.9rem;color:var(--ink-2);font-weight:550;line-height:1.35;
  transition:all .28s var(--ease-out);
}
.seq-btn:hover:not(:disabled){border-color:var(--blue-300);background:var(--paper);transform:translateX(3px)}
.seq-btn .sn{
  width:26px;height:26px;border-radius:8px;flex:none;display:grid;place-items:center;
  font-family:var(--f-mono);font-size:.72rem;font-weight:700;
  background:var(--paper-3);color:var(--ink-muted);border:1px solid var(--line);
}
.seq-btn.done{border-color:#8FE4CE;background:linear-gradient(110deg,#EFFCF8,#fff);color:#0A6A54;cursor:default}
.seq-btn.done .sn{background:linear-gradient(140deg,var(--mint-500),#0A9E7B);color:#fff;border-color:transparent}
.seq-btn.bad{animation:shake .42s;border-color:var(--rose-500)}

.blank-sentence{font-size:1.02rem;line-height:2.15;color:var(--ink-2);margin-bottom:1.3rem;flex:1}
.blank-slot{
  display:inline-block;min-width:118px;padding:.15em .7em;margin:0 .12em;
  border-bottom:2.5px dashed var(--blue-300);border-radius:6px 6px 0 0;
  text-align:center;font-weight:700;color:var(--blue-800);font-family:var(--f-display);
  background:var(--blue-50);transition:all .3s var(--ease-out);
}
.blank-slot.filled{border-bottom-style:solid;border-bottom-color:var(--mint-500);background:#EFFCF8;color:#0A6A54}
.blank-slot.bad{animation:shake .42s;border-bottom-color:var(--rose-500);background:var(--rose-100)}
.blank-bank{display:flex;flex-wrap:wrap;gap:.5rem}
.blank-word{
  padding:.5rem .95rem;border-radius:var(--r-pill);
  background:var(--paper-2);border:1.5px solid var(--line);
  font-family:var(--f-display);font-weight:650;font-size:.87rem;color:var(--ink-2);
  transition:all .25s var(--ease-out);
}
.blank-word:hover:not(:disabled){border-color:var(--blue-400);color:var(--blue-700);transform:translateY(-2px)}
.blank-word.used{opacity:.3;cursor:default;text-decoration:line-through}

/* ---------- C. Harrington Hub dashboard ---------- */
.hub{position:relative;border-radius:var(--r-xl);overflow:hidden;border:1px solid var(--line);background:var(--paper);box-shadow:var(--sh-xl)}

/* ---------- Demo cursor ----------
   The outer span is a zero-size anchor point: translate puts it exactly on a
   target's centre and the arrow hangs off it, so the tip lands on the thing
   being clicked. Travel time comes from --cur-ms, set per move by the script.
   The hub's own overflow:hidden keeps it inside the browser frame. */
.hub-cursor{
  position:absolute;top:0;left:0;width:0;height:0;z-index:40;
  pointer-events:none;opacity:0;
  transition:transform var(--cur-ms,800ms) cubic-bezier(.5,.05,.2,1),opacity .45s linear;
}
.hub-cursor.is-on{opacity:1}
.hub-cursor svg{
  position:absolute;left:-3px;top:-3px;width:30px;height:30px;display:block;
  filter:drop-shadow(0 4px 10px rgba(9,28,66,.55));
  transition:transform .16s var(--ease-out);
}
.hub-cursor.is-click svg{transform:scale(.78)}
/* Click ripple, centred on the same anchor point. */
.hub-cursor i{
  position:absolute;left:-22px;top:-22px;width:44px;height:44px;
  border-radius:50%;border:2.5px solid var(--blue-600);opacity:0;
}
.hub-cursor.is-click i{animation:hubPress .6s var(--ease-out)}
@keyframes hubPress{from{opacity:.9;transform:scale(.25)}to{opacity:0;transform:scale(1.15)}}
.hub-bar{display:flex;align-items:center;gap:.6rem;padding:.75rem 1.1rem;background:var(--paper-2);border-bottom:1px solid var(--line)}
/* Windows-style title bar controls: minimise, maximise, close, sat hard against
   the top right. The negative margins pull them back out of .hub-bar's own
   padding so they meet the frame edge as a real title bar does, and the hub's
   overflow:hidden clips the close button to the rounded corner. */
.hub-winctl{
  margin:-.75rem -1.1rem -.75rem auto;
  align-self:stretch;display:flex;flex:none;
}
.hub-winctl i{
  width:38px;display:grid;place-items:center;
  color:var(--ink-3);transition:background .18s,color .18s;
}
.hub-winctl svg{width:11px;height:11px;fill:none;stroke:currentColor;stroke-width:1.2}
.hub-winctl i:hover{background:rgba(9,28,66,.07)}
/* Windows tints the close button alone, and only on hover. */
.hub-winctl i.x:hover{background:#E81123;color:#fff}
.hub-url{
  flex:1;max-width:330px;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r-pill);
  padding:.3rem .9rem;font-family:var(--f-mono);font-size:.72rem;color:var(--ink-muted);
  display:flex;align-items:center;gap:.4rem;white-space:nowrap;overflow:hidden;
}
.hub-url svg{width:12px;height:12px;color:var(--mint-500);flex:none}

.hub-main{display:grid;grid-template-columns:198px minmax(0,1fr)}
@media(max-width:820px){.hub-main{grid-template-columns:minmax(0,1fr)}.hub-side{display:none}}
.hub-side{border-right:1px solid var(--line-soft);padding:1.1rem .8rem;background:var(--paper-2)}
.hub-side .lbl{font-family:var(--f-mono);font-size:.58rem;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-muted);padding:.5rem .7rem}
.hub-nav{display:grid;gap:2px}
.hub-nav span{
  display:flex;align-items:center;gap:.65rem;padding:.55rem .7rem;border-radius:10px;
  font-size:.85rem;font-weight:600;color:var(--ink-2);font-family:var(--f-display);
}
.hub-nav span svg{width:17px;height:17px;color:var(--ink-muted)}
.hub-nav span.on{background:linear-gradient(120deg,var(--blue-600),var(--blue-800));color:#fff}
.hub-nav span.on svg{color:#fff}

.hub-content{padding:clamp(16px,2vw,24px);display:grid;gap:1rem;align-content:start}
.hub-greet h3{margin:0 0 .2rem;font-size:1.22rem}
.hub-greet span{font-family:var(--f-mono);font-size:.72rem;color:var(--ink-muted);letter-spacing:.04em}
.hub-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}
@media(max-width:640px){.hub-cards{grid-template-columns:minmax(0,1fr)}}
.hub-card{border:1px solid var(--line);border-radius:var(--r-md);padding:1.1rem;background:var(--paper)}
.hub-card h4{font-family:var(--f-mono);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-muted);font-weight:600;margin-bottom:.9rem}

/* ---------- Hub panels ----------
   The dashboard walks itself through Courses and Learners before settling on
   the summary, so the mockup reads as a product with a catalogue and a roster
   behind it rather than one clever button. The dashboard panel carries .is-on
   in the markup, so the card still renders if the script never runs. */
/* Every panel sits in the same grid cell, so the stack is always as tall as
   the tallest one (the dashboard) and the browser mock never resizes mid-tour.
   That rules out display:none — a hidden panel still has to take part in
   sizing — so they are hidden with visibility and cross-faded instead. */
.hub-panels{display:grid}
.hub-panel{
  grid-area:1/1;
  display:grid;gap:1rem;align-content:start;
  opacity:0;visibility:hidden;pointer-events:none;transform:translateY(10px);
  transition:opacity .42s var(--ease-out),transform .42s var(--ease-out),visibility 0s .42s;
}
.hub-panel.is-on{
  opacity:1;visibility:visible;pointer-events:auto;transform:none;
  transition:opacity .42s var(--ease-out),transform .42s var(--ease-out),visibility 0s;
}

.hub-table{width:100%;border-collapse:collapse;font-size:.8rem}
.hub-table th{
  font-family:var(--f-mono);font-size:.57rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-muted);font-weight:600;text-align:left;
  padding:0 .6rem .55rem;border-bottom:1px solid var(--line-soft);
}
.hub-table th:not(:first-child){text-align:right}
.hub-table td{padding:.58rem .6rem;border-bottom:1px solid var(--line-soft);color:var(--ink-2)}
.hub-table tbody tr:last-child td{border-bottom:0}
.hub-table td:not(:first-child){text-align:right;font-family:var(--f-mono);font-size:.75rem}
.hub-table tbody tr{transition:background .2s}
.hub-table tbody tr:hover{background:var(--paper-2)}
.ht-name{display:flex;align-items:center;gap:.6rem;font-weight:650;color:var(--ink);font-family:var(--f-display)}
.ht-ico,.ht-av{width:26px;height:26px;border-radius:8px;flex:none;display:grid;place-items:center}
.ht-ico{background:var(--blue-50);border:1px solid var(--blue-100)}
.ht-ico svg{width:15px;height:15px;color:var(--blue-700)}
.ht-av{font-family:var(--f-display);font-weight:700;font-size:.62rem;color:#fff;background:linear-gradient(140deg,var(--blue-500),var(--blue-800))}
.ht-rate{display:flex;align-items:center;justify-content:flex-end;gap:.55rem}
.ht-bar{display:block;width:52px;height:5px;border-radius:99px;background:var(--paper-3);overflow:hidden;flex:none}
.ht-bar i{display:block;height:5px;border-radius:99px;background:linear-gradient(90deg,var(--cyan-500),var(--blue-600))}
.ht-tag{
  display:inline-block;padding:.22em .62em;border-radius:var(--r-pill);
  font-family:var(--f-mono);font-size:.58rem;letter-spacing:.08em;
  text-transform:uppercase;font-weight:600;
}
.ht-tag.ok{background:var(--mint-100);color:#0A7A5F}
.ht-tag.mid{background:var(--blue-50);color:var(--blue-800)}
.ht-tag.late{background:var(--amber-100);color:#8A5A05}
/* The middle column is the first thing to lose when the browser mock narrows. */
@media(max-width:640px){.hub-table th:nth-child(2),.hub-table td:nth-child(2){display:none}}

.donut{display:flex;align-items:center;gap:1.1rem}
.donut-mid{position:relative;flex:none}
.donut svg{transform:rotate(-90deg);display:block}
.donut .tr{stroke:var(--paper-3)}
.donut .pg{stroke:url(#ringGrad);stroke-linecap:round;transition:stroke-dashoffset 1.3s var(--ease-out)}
.donut-mid b{position:absolute;inset:0;display:grid;place-items:center;font-family:var(--f-display);font-weight:800;font-size:1.02rem;color:var(--ink);letter-spacing:-.03em}
.donut-legend{display:grid;gap:.42rem;font-size:.81rem;flex:1;min-width:0}
.donut-legend span{display:flex;align-items:center;gap:.5rem;color:var(--ink-3)}
.donut-legend i{width:9px;height:9px;border-radius:3px;flex:none}
.donut-legend b{color:var(--ink);font-family:var(--f-display);margin-left:auto;padding-left:.6rem}

.hub-btn{
  width:100%;padding:.7rem 1rem;border-radius:11px;
  font-family:var(--f-display);font-weight:700;font-size:.86rem;
  background:linear-gradient(135deg,var(--blue-600),var(--blue-800));color:#fff;
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  box-shadow:0 8px 20px -8px rgba(18,86,232,.55);
  transition:transform .25s var(--ease-out),box-shadow .25s,filter .25s;
}
.hub-btn:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 14px 30px -10px rgba(18,86,232,.6)}
.hub-btn:disabled{filter:grayscale(.45);opacity:.65;cursor:default}
.hub-btn svg{width:15px;height:15px}
/* Both of these are <span>s in the markup — without an explicit display
   they stay inline, height is ignored and the bar balloons to line height. */
.hub-meter{display:block;height:7px;border-radius:99px;background:var(--paper-3);overflow:hidden;margin:.85rem 0 .55rem}
/* Short transition only: the fill is driven frame by frame from JS, so a
   long one would leave the bar trailing behind the count. */
.hub-meter i{display:block;height:7px;width:0;border-radius:99px;background:linear-gradient(90deg,var(--cyan-500),var(--blue-600));transition:width .09s linear}
.hub-note{display:block;font-size:.78rem;color:var(--ink-muted);font-family:var(--f-mono);letter-spacing:.02em;line-height:1.45}

.hub-feed{display:grid;gap:.4rem;min-height:150px;align-content:start}
.hub-feed-row{
  display:flex;align-items:center;gap:.7rem;padding:.55rem .7rem;border-radius:10px;
  background:var(--paper-2);font-size:.82rem;color:var(--ink-2);
  animation:slidein .45s var(--ease-out);
}
@keyframes slidein{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
.hub-feed-row .av{
  width:26px;height:26px;border-radius:8px;flex:none;display:grid;place-items:center;
  font-family:var(--f-display);font-weight:700;font-size:.64rem;color:#fff;
  background:linear-gradient(140deg,var(--blue-500),var(--blue-800));
}
.hub-feed-row time{margin-left:auto;font-family:var(--f-mono);font-size:.69rem;color:var(--ink-muted);flex:none}
.hub-feed-row b{color:var(--ink);font-weight:650}

.hub-sched{display:grid;gap:.5rem}
.hub-sched-row{display:flex;align-items:center;gap:.7rem;padding:.6rem .75rem;border-radius:10px;border:1px solid var(--line-soft);font-size:.82rem;color:var(--ink-2)}
.hub-sched-row svg{width:16px;height:16px;color:var(--blue-500);flex:none}
.hub-sched-row b{color:var(--ink);font-weight:650}
.hub-sched-row .when{margin-left:auto;font-family:var(--f-mono);font-size:.69rem;color:var(--ink-muted);text-align:right;flex:none}
.hub-caption{text-align:center;font-size:.83rem;color:var(--ink-muted);margin-top:1.1rem}

/* ---------- D. Email mockups ---------- */
.mail{border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;background:var(--paper);box-shadow:var(--sh-sm);transition:transform .4s var(--ease-out),box-shadow .4s}
.mail:hover{transform:translateY(-4px);box-shadow:var(--sh-md)}
.mail-head{padding:.8rem 1rem;background:var(--paper-2);border-bottom:1px solid var(--line-soft);font-family:var(--f-mono);font-size:.69rem;color:var(--ink-muted);line-height:1.65;word-break:break-word}
.mail-subj{font-family:var(--f-display);font-weight:700;font-size:.95rem;color:var(--ink);padding:.9rem 1rem .3rem;letter-spacing:-.015em}
.mail-body{padding:0 1rem 1rem;font-size:.87rem;color:var(--ink-3);line-height:1.6}
.mail-body ul{margin:.6rem 0;padding-left:1.1rem}
.mail-body li{margin-bottom:.25rem;font-size:.85rem}
.mail-body b{color:var(--ink)}
/* The call to action inside the mock email. A span, not a link: nothing else
   in these cards is interactive, and a dead anchor invites a click that goes
   nowhere. Sized down from the site buttons so it reads as being inside an
   email rather than part of the page. */
.mail-btn{
  display:inline-block;margin:.9rem 0 .2rem;
  padding:.52rem 1.05rem;border-radius:9px;
  background:linear-gradient(135deg,var(--blue-600),var(--blue-800));color:#fff;
  font-family:var(--f-display);font-weight:700;font-size:.82rem;letter-spacing:-.01em;
  box-shadow:0 6px 16px -7px rgba(18,86,232,.6);
}
.mail-sign{margin:.9rem 0 0;font-size:.87rem;color:var(--ink-3);line-height:1.6}
.mail-sign b{display:block;color:var(--ink-2);font-weight:650}
.mail-tag{display:inline-flex;align-items:center;gap:.4rem;margin:0 1rem 1rem;padding:.3rem .7rem;border-radius:var(--r-pill);font-family:var(--f-mono);font-size:.63rem;letter-spacing:.1em;text-transform:uppercase;font-weight:600}
.mail-tag.t14{background:var(--blue-50);color:var(--blue-800)}
.mail-tag.esc{background:var(--amber-100);color:#8A5A05}
.mail-tag.done{background:var(--mint-100);color:#0A6A54}

/* ---------- E. Alternating split
   DOM stays text-first (correct reading order); only the visual
   column order flips, and only where there are two columns. ---------- */
@media(min-width:761px){
  .split--flip > *:first-child{order:2}
  .split--flip > *:last-child{order:1}
}

/* ---------- F. Section list (course outline pages) ---------- */
.modlist{display:grid;gap:.6rem;counter-reset:m}
.modrow{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:1.1rem;align-items:center;
  padding:1.1rem 1.2rem;border-radius:var(--r-md);
  background:var(--paper);border:1px solid var(--line);
  transition:transform .35s var(--ease-out),box-shadow .35s,border-color .3s;
}
.modrow:hover{transform:translateY(-3px);box-shadow:var(--sh-md);border-color:var(--blue-200)}
.modrow:hover .iconwell{color:#fff}
.modrow:hover .iconwell::after{opacity:1}
.modrow .iconwell{width:46px;height:46px;border-radius:14px}
.modrow .iconwell .icon{width:24px;height:24px}
.modrow b{display:block;font-family:var(--f-display);font-size:1.02rem;color:var(--ink);letter-spacing:-.018em;line-height:1.3}
.modrow p{margin:.25rem 0 0;font-size:.91rem;color:var(--ink-3);line-height:1.5}
.modrow .mn{
  font-family:var(--f-mono);font-size:.7rem;color:var(--ink-muted);
  letter-spacing:.1em;white-space:nowrap;
}
@media(max-width:600px){.modrow{grid-template-columns:auto minmax(0,1fr)}.modrow .mn{display:none}}

/* ---------- Book a demo ---------- */
.demo-layout{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.92fr);
  gap:clamp(28px,4vw,56px);align-items:start;margin-top:1.6rem;
}
@media(max-width:900px){.demo-layout{grid-template-columns:minmax(0,1fr)}}
.demo-points{list-style:none;padding:0;margin:1.9rem 0 0;display:grid;gap:.7rem}
.demo-points li{display:flex;gap:.7rem;align-items:center;font-size:.95rem;color:var(--ink-2);font-weight:550;margin:0}
.demo-points .tick{
  width:21px;height:21px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:linear-gradient(140deg,var(--mint-500),#0FA582);
}
.demo-points .tick svg{width:11px;height:11px;stroke:#fff;stroke-width:3.2}
.demo-alt{margin-top:2.2rem;padding-top:1.5rem;border-top:1px solid var(--line-soft)}
.demo-alt p{font-weight:650;color:var(--ink-2);margin-bottom:.7rem}
/* Faces before the phone number, so "talk to a person" has people attached. */
.demo-photo{
  margin:0 0 1.05rem;border-radius:var(--r-md);overflow:hidden;
  border:1px solid var(--line);box-shadow:var(--sh-md);
}
.demo-photo picture{display:block}
.demo-photo img{display:block;width:100%;height:auto;aspect-ratio:1024/680;object-fit:cover}
/* .f-contact is built for the dark footer, where #A9BEE0 reads well on navy.
   Reused here on a white panel it drops to about 1.9:1, far below the 4.5:1
   minimum, so the colours are restated for a light background. Scoped to
   .demo-alt, which exists only on this page — the footer is untouched. */
.demo-alt .f-contact li{color:var(--ink-2)}
.demo-alt .f-contact a{color:var(--blue-800);font-weight:600}
.demo-alt .f-contact a:hover{color:var(--blue-600)}
.demo-alt .f-contact svg{color:var(--blue-600)}

.demo-card{
  border-radius:var(--r-xl);border:1px solid var(--line);background:var(--paper);
  box-shadow:var(--sh-lg);padding:clamp(22px,2.8vw,34px);
}
.demo-form{display:grid;gap:1rem}
.fieldrow{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}
@media(max-width:520px){.fieldrow{grid-template-columns:minmax(0,1fr)}}
.field{display:grid;gap:.4rem}
.field>span{font-size:.83rem;font-weight:650;color:var(--ink-2);letter-spacing:-.01em}
.field>span b{color:var(--blue-600);font-weight:650}
.field input,.field select,.field textarea{
  width:100%;font:inherit;font-size:.94rem;color:var(--ink);
  padding:.72rem .85rem;border-radius:var(--r-sm);
  border:1.5px solid var(--line);background:var(--paper-2);
  transition:border-color .2s,box-shadow .2s,background .2s;
}
.field textarea{resize:vertical;min-height:96px}
.field input::placeholder,.field textarea::placeholder{color:var(--ink-muted)}
.field input:hover,.field select:hover,.field textarea:hover{border-color:var(--blue-300)}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;background:var(--paper);
  border-color:var(--blue-500);box-shadow:0 0 0 3px var(--blue-100);
}
.field.is-bad input,.field.is-bad select,.field.is-bad textarea{border-color:#E4384D;box-shadow:0 0 0 3px #FDE7EA}
.field-err{
  margin:0;padding:.7rem .85rem;border-radius:var(--r-sm);
  background:#FDE7EA;border:1px solid #F6C2C9;color:#9C1526;
  font-size:.87rem;font-weight:600;
}
.demo-privacy{margin:0;font-size:.8rem;color:var(--ink-muted);text-align:center;line-height:1.5}
.demo-form.is-sending button[type=submit]{opacity:.65;pointer-events:none}
/* Spam honeypot. Off-screen rather than display:none, which some bots skip. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.thanks-in{max-width:660px;margin:0 auto;text-align:center;padding-block:clamp(20px,4vw,48px)}
.thanks-mark{
  width:72px;height:72px;border-radius:50%;margin:0 auto 1.6rem;
  display:grid;place-items:center;color:#fff;
  background:linear-gradient(140deg,var(--mint-500),#0FA582);
  box-shadow:0 14px 34px -14px rgba(18,198,155,.9);
}
.thanks-mark svg{width:32px;height:32px}
.thanks-in .lede{margin-bottom:1.9rem}

/* ---------- Sector hub cards ---------- */
.sector-card{display:flex;flex-direction:column;text-decoration:none}
.sector-card h3{margin:1rem 0 .5rem;font-size:1.15rem;letter-spacing:-.02em}
.sector-card>p{color:var(--ink-3);font-size:.95rem;line-height:1.6;margin:0}
.sector-card-pts{list-style:none;padding:0;margin:1.1rem 0 1.3rem;display:grid;gap:.45rem}
.sector-card-pts li{
  display:flex;gap:.6rem;align-items:flex-start;margin:0;
  font-size:.88rem;color:var(--ink-2);line-height:1.5;
}
.sector-card-pts li::before{
  content:"";width:6px;height:6px;border-radius:2px;margin-top:.5em;flex:none;
  background:linear-gradient(140deg,var(--cyan-500),var(--blue-600));
}
.sector-card .cc-foot{margin-top:auto}

/* ---------- CPD accreditation mark ----------
   Reads as a credential rather than another pill: the awarding bodies, the
   code and the hours, so a compliance officer can verify it.
   The code is a placeholder — see tools/README-cpd.md before launch. */
.cpd-badge{
  display:inline-flex;align-items:center;gap:.7rem;flex:none;
  padding:.5rem .95rem .5rem .6rem;border-radius:var(--r-pill);
  background:var(--paper);border:1px solid var(--blue-100);
  box-shadow:var(--sh-sm);
}
/* A credential mark should never squash into two lines beside the pills. */
.cpd-badge b,.cpd-badge small{white-space:nowrap}
.cpd-badge .cpd-seal{
  width:30px;height:30px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:linear-gradient(140deg,var(--blue-600),var(--blue-800));color:#fff;
}
.cpd-badge .cpd-seal svg{width:16px;height:16px;stroke-width:1.8}
.cpd-badge b{
  display:block;font-family:var(--f-display);font-weight:700;
  font-size:.82rem;color:var(--ink);letter-spacing:-.01em;line-height:1.2;
}
.cpd-badge small{
  display:block;font-family:var(--f-mono);font-size:.64rem;
  letter-spacing:.08em;color:var(--ink-muted);margin-top:2px;
}

/* ---------- Blog articles ---------- */
.post-layout{display:grid;grid-template-columns:minmax(0,220px) minmax(0,1fr);gap:clamp(28px,4vw,60px);align-items:start}
@media(max-width:900px){.post-layout{grid-template-columns:minmax(0,1fr)}}
.post-toc{position:sticky;top:110px}
@media(max-width:900px){.post-toc{position:static;padding-bottom:1.2rem;border-bottom:1px solid var(--line-soft)}}
.post-toc ol{list-style:none;padding:0;margin:.7rem 0 0;display:grid;gap:.1rem;counter-reset:toc}
.post-toc li{margin:0;counter-increment:toc}
.post-toc a{
  display:block;padding:.4rem .6rem;border-radius:8px;
  font-size:.84rem;line-height:1.4;color:var(--ink-3);
  border-left:2px solid var(--line);transition:background .16s,color .16s,border-color .16s;
}
.post-toc a:hover{background:var(--blue-50);color:var(--blue-700);border-left-color:var(--blue-500)}

.post-body{max-width:68ch}
.post-sec + .post-sec{margin-top:clamp(26px,3vw,40px)}
.post-body h2{font-size:clamp(1.3rem,2.2vw,1.65rem);letter-spacing:-.025em;margin-bottom:.7rem}
.post-body h3{font-size:1.02rem;letter-spacing:-.015em;margin:1.4rem 0 .5rem;color:var(--ink)}
.post-body p{font-size:1rem;line-height:1.72;color:var(--ink-3);margin:0 0 .9rem}
.post-body strong{color:var(--ink-2);font-weight:650}
.post-note{
  padding:.9rem 1.1rem;border-radius:var(--r-sm);
  background:var(--blue-50);border:1px solid var(--blue-100);
  color:var(--blue-800);font-size:.94rem;line-height:1.62;
}
/* The marker is positioned rather than a flex item: these list items open with
   a bold term and run straight into the sentence, and flex would break every
   one of them into separate items with a gap before the comma. */
.post-list{list-style:none;padding:0;margin:0 0 1rem;display:grid;gap:.55rem}
.post-list li{
  position:relative;padding-left:1.35rem;margin:0;
  font-size:.97rem;line-height:1.65;color:var(--ink-3);
}
.post-list li::before{
  content:"";position:absolute;left:0;top:.62em;
  width:6px;height:6px;border-radius:2px;
  background:linear-gradient(140deg,var(--cyan-500),var(--blue-600));
}
.post-list--num{counter-reset:pl}
.post-list--num li{counter-increment:pl;padding-left:1.7rem}
.post-list--num li::before{
  content:counter(pl) ".";top:0;width:auto;height:auto;border-radius:0;background:none;
  font-family:var(--f-mono);font-size:.8rem;font-weight:600;color:var(--blue-600);
}

/* ---------- G. Sector photo band ----------
   Sits at the foot of the intro section on each sector page, where the copy
   is densest. The caption is a gradient overlay rather than a bar underneath,
   so the image keeps its full height and the band stays one object. */
.sector-photo{
  position:relative;margin:clamp(30px,4vw,52px) 0 0;
  border-radius:var(--r-xl);overflow:hidden;
  border:1px solid var(--line);box-shadow:var(--sh-lg);
  background:var(--paper-2);
}
/* <picture> is inline by default, so it would generate a line box and leave a
   few pixels of dead space under the image inside the rounded frame. */
.sector-photo picture{display:block}
.sector-photo img{
  display:block;width:100%;height:auto;
  aspect-ratio:1600/640;object-fit:cover;
}
.sector-photo figcaption{
  position:absolute;left:0;right:0;bottom:0;
  padding:clamp(28px,5vw,44px) clamp(16px,2.6vw,30px) clamp(14px,2.2vw,22px);
  background:linear-gradient(to top,rgba(6,34,80,.9),rgba(6,34,80,.55) 48%,rgba(6,34,80,0));
  color:#D8E6FB;font-size:clamp(.84rem,1.35vw,.97rem);line-height:1.55;
  text-shadow:0 1px 12px rgba(3,17,44,.45);
}
.sector-photo figcaption b{
  display:block;color:#fff;font-family:var(--f-display);font-weight:700;
  font-size:clamp(.96rem,1.7vw,1.16rem);letter-spacing:-.02em;margin-bottom:.22rem;
}
@media(max-width:600px){
  .sector-photo img{aspect-ratio:3/2}
  .sector-photo figcaption{background:linear-gradient(to top,rgba(6,34,80,.94),rgba(6,34,80,.6) 58%,rgba(6,34,80,0))}
}

/* ---------- Judge scene ----------
   A banner at the head of the "You be the judge" card. It carries the standing
   question as its caption, so the label that used to sit above the scenario is
   now part of the image rather than another line of text. flex:none because
   .ix-body is a flex column and the aspect-ratio box would otherwise be
   squeezed by the scenario below it. */
.judge-scene{
  position:relative;flex:none;margin:0 0 1.1rem;
  border-radius:12px;overflow:hidden;border:1px solid var(--line);
  background:var(--navy-900);
}
.judge-scene picture{display:block}
/* Six photos from six different shoots, so they arrive in six different
   colour temperatures. Desaturating and laying a navy wash over the top
   makes them read as one set instead of a slideshow. */
.judge-scene img{
  display:block;width:100%;height:auto;aspect-ratio:1000/300;object-fit:cover;
  filter:saturate(.42) contrast(1.06) brightness(.86);
  transition:opacity .26s var(--ease-out);
}
.judge-scene::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(140deg,rgba(9,38,96,.62),rgba(0,120,180,.34));
  mix-blend-mode:multiply;
}
.judge-scene.is-swapping img{opacity:0}
.judge-scene .judge-q{
  position:absolute;left:0;right:0;bottom:0;margin:0;z-index:2;
  padding:1.6rem .95rem .62rem;
  background:linear-gradient(to top,rgba(4,20,52,.94),rgba(4,20,52,.4) 62%,transparent);
  font-family:var(--f-mono);font-weight:600;font-size:.78rem;
  letter-spacing:.15em;text-transform:uppercase;color:var(--cyan-300);
  line-height:1.3;
}
