Testing347 commited on
Commit
44f9261
·
verified ·
1 Parent(s): 0d30589

Update capabilities.html

Browse files
Files changed (1) hide show
  1. capabilities.html +24 -28
capabilities.html CHANGED
@@ -8,9 +8,9 @@
8
  <!-- Tailwind -->
9
  <script src="https://cdn.tailwindcss.com"></script>
10
 
11
- <!-- Three.js + Vanta -->
12
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
13
- <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script>
14
 
15
  <!-- Icons + Font -->
16
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
@@ -165,7 +165,7 @@
165
  <!-- MCAP -->
166
  <button type="button"
167
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
168
- data-dossier="mcap" aria-label="Open dossier: MCAP">
169
  <div class="flex items-start justify-between gap-4">
170
  <div>
171
  <div class="text-lg font-semibold text-gray-100">MCAP</div>
@@ -185,7 +185,7 @@
185
  <!-- CHAI -->
186
  <button type="button"
187
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
188
- data-dossier="chai" aria-label="Open dossier: CHAI">
189
  <div class="flex items-start justify-between gap-4">
190
  <div>
191
  <div class="text-lg font-semibold text-gray-100">CHAI</div>
@@ -205,7 +205,7 @@
205
  <!-- Quantum Lambda -->
206
  <button type="button"
207
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
208
- data-dossier="quantum_lambda" aria-label="Open dossier: Quantum Lambda">
209
  <div class="flex items-start justify-between gap-4">
210
  <div>
211
  <div class="text-lg font-semibold text-gray-100">Quantum Lambda</div>
@@ -225,7 +225,7 @@
225
  <!-- AI Scientist -->
226
  <button type="button"
227
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
228
- data-dossier="ai_scientist" aria-label="Open dossier: AI Scientist">
229
  <div class="flex items-start justify-between gap-4">
230
  <div>
231
  <div class="text-lg font-semibold text-gray-100">AI Scientist</div>
@@ -245,7 +245,7 @@
245
  <!-- Agentic Workforce -->
246
  <button type="button"
247
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element md:col-span-2"
248
- data-dossier="agentic_workforce" aria-label="Open dossier: Agentic Workforce">
249
  <div class="flex items-start justify-between gap-4">
250
  <div>
251
  <div class="text-lg font-semibold text-gray-100">Agentic Workforce</div>
@@ -550,7 +550,7 @@
550
  window.addEventListener('resize', () => vantaEffect.resize());
551
 
552
  /* -------------------------------------------------------------
553
- MODAL HELPERS
554
  ------------------------------------------------------------- */
555
  function trapFocus(modal) {
556
  const focusable = modal.querySelectorAll('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');
@@ -565,8 +565,6 @@
565
  } else {
566
  if (document.activeElement === last) { e.preventDefault(); first.focus(); }
567
  }
568
- } else if (e.key === 'Escape') {
569
- toggleModal(modal, false);
570
  }
571
  }
572
  modal.addEventListener('keydown', handler);
@@ -582,6 +580,7 @@
582
 
583
  const toggleModal = (modal, show) => {
584
  if (show) {
 
585
  modal.classList.remove('modal-hidden');
586
  modal.classList.add('modal-visible');
587
  document.body.style.overflow = 'hidden';
@@ -591,12 +590,16 @@
591
  modal.classList.add('modal-hidden');
592
  document.body.style.overflow = '';
593
  untrapFocus(modal);
 
 
 
 
594
  }
595
  };
596
 
597
  /* -------------------------------------------------------------
598
  ACCESS MODAL + INLINE FEEDBACK (replaces alerts)
599
- ------------------------------------------------------------- */
600
  const accessModal = document.getElementById('access-modal');
601
  const accessBtn = document.getElementById('access-btn');
602
  const closeAccessModal = document.getElementById('close-access-modal');
@@ -622,10 +625,13 @@
622
  }
623
 
624
  function clearAccessFeedback() {
625
- accessFeedback.classList.add('hidden');
626
  accessFeedback.textContent = '';
627
- accessFeedback.className = 'hidden mb-4 rounded-lg border border-gray-800 bg-black/25 px-4 py-3 text-sm';
628
- // Restore base classes in case they were overwritten by className (above line sets baseline)
 
 
 
 
629
  }
630
 
631
  accessBtn.addEventListener('click', () => {
@@ -638,7 +644,6 @@
638
  accessModal.addEventListener('click', (e) => { if (e.target === accessModal) toggleModal(accessModal, false); });
639
 
640
  function isValidEmail(email) {
641
- // Lightweight sanity check (not exhaustive)
642
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
643
  }
644
 
@@ -659,11 +664,8 @@
659
  return;
660
  }
661
 
662
- // Static-only behavior: confirm receipt, keep it calm and “lab-like”.
663
  setAccessFeedback('success', 'Request received. You will be contacted after review.');
664
  accessForm.reset();
665
-
666
- // Optional auto-close after a brief pause (keeps the flow, but not abrupt)
667
  setTimeout(() => toggleModal(accessModal, false), 900);
668
  });
669
 
@@ -695,7 +697,7 @@
695
  /* -------------------------------------------------------------
696
  DOSSIERS
697
  + Hash deep-linking (#mcap, #chai, etc.)
698
- + Active-card state
699
  ------------------------------------------------------------- */
700
  const DOSSIERS = {
701
  mcap: {
@@ -812,7 +814,8 @@
812
  programCards.forEach(btn => {
813
  const isMatch = btn.getAttribute('data-dossier') === key;
814
  btn.classList.toggle('is-active', isMatch);
815
- btn.setAttribute('aria-current', isMatch ? 'true' : 'false');
 
816
  });
817
  }
818
 
@@ -861,18 +864,14 @@
861
  if (opts.setActive) setActiveCard(key);
862
  if (opts.setHash) updateHash(key, opts.replaceHash);
863
 
864
- // Keep the dossier panel in view on small screens without changing layout
865
- // (only when user selects a card)
866
  if (!opts.replaceHash) {
867
  const isSmall = window.matchMedia && window.matchMedia('(max-width: 1023px)').matches;
868
  if (isSmall) {
869
- // subtle nudge: bring dossier header into view
870
  dossierTitle.scrollIntoView({ behavior: 'smooth', block: 'start' });
871
  }
872
  }
873
  }
874
 
875
- // Card click: render dossier + update hash + active state
876
  programCards.forEach(btn => {
877
  btn.addEventListener('click', () => {
878
  const key = btn.getAttribute('data-dossier');
@@ -881,15 +880,12 @@
881
  });
882
  });
883
 
884
- // Hash deep-link: initial load
885
  (function initFromHashOrDefault() {
886
  const keyFromHash = normalizeHashToKey();
887
  const key = keyFromHash || 'mcap';
888
- // replaceHash avoids adding an extra history entry on first load
889
  renderDossier(key, { setHash: true, replaceHash: true, setActive: true });
890
  })();
891
 
892
- // Respond to manual hash changes / back-forward navigation
893
  window.addEventListener('hashchange', () => {
894
  const keyFromHash = normalizeHashToKey();
895
  if (keyFromHash) {
@@ -898,7 +894,7 @@
898
  });
899
 
900
  /* -------------------------------------------------------------
901
- GLOBAL ESC BEHAVIOR
902
  ------------------------------------------------------------- */
903
  document.addEventListener('keydown', (e) => {
904
  if (e.key === 'Escape') {
 
8
  <!-- Tailwind -->
9
  <script src="https://cdn.tailwindcss.com"></script>
10
 
11
+ <!-- Three.js + Vanta (pinned) -->
12
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
13
+ <script src="https://cdn.jsdelivr.net/npm/vanta@0.5.24/dist/vanta.net.min.js"></script>
14
 
15
  <!-- Icons + Font -->
16
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
165
  <!-- MCAP -->
166
  <button type="button"
167
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
168
+ data-dossier="mcap" aria-label="Open dossier: MCAP" aria-pressed="false">
169
  <div class="flex items-start justify-between gap-4">
170
  <div>
171
  <div class="text-lg font-semibold text-gray-100">MCAP</div>
 
185
  <!-- CHAI -->
186
  <button type="button"
187
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
188
+ data-dossier="chai" aria-label="Open dossier: CHAI" aria-pressed="false">
189
  <div class="flex items-start justify-between gap-4">
190
  <div>
191
  <div class="text-lg font-semibold text-gray-100">CHAI</div>
 
205
  <!-- Quantum Lambda -->
206
  <button type="button"
207
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
208
+ data-dossier="quantum_lambda" aria-label="Open dossier: Quantum Lambda" aria-pressed="false">
209
  <div class="flex items-start justify-between gap-4">
210
  <div>
211
  <div class="text-lg font-semibold text-gray-100">Quantum Lambda</div>
 
225
  <!-- AI Scientist -->
226
  <button type="button"
227
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element"
228
+ data-dossier="ai_scientist" aria-label="Open dossier: AI Scientist" aria-pressed="false">
229
  <div class="flex items-start justify-between gap-4">
230
  <div>
231
  <div class="text-lg font-semibold text-gray-100">AI Scientist</div>
 
245
  <!-- Agentic Workforce -->
246
  <button type="button"
247
  class="program-card text-left rounded-2xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/55 hover:bg-gray-900/45 transition p-5 conscious-element md:col-span-2"
248
+ data-dossier="agentic_workforce" aria-label="Open dossier: Agentic Workforce" aria-pressed="false">
249
  <div class="flex items-start justify-between gap-4">
250
  <div>
251
  <div class="text-lg font-semibold text-gray-100">Agentic Workforce</div>
 
550
  window.addEventListener('resize', () => vantaEffect.resize());
551
 
552
  /* -------------------------------------------------------------
553
+ MODAL HELPERS (focus trap + restore opener focus)
554
  ------------------------------------------------------------- */
555
  function trapFocus(modal) {
556
  const focusable = modal.querySelectorAll('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');
 
565
  } else {
566
  if (document.activeElement === last) { e.preventDefault(); first.focus(); }
567
  }
 
 
568
  }
569
  }
570
  modal.addEventListener('keydown', handler);
 
580
 
581
  const toggleModal = (modal, show) => {
582
  if (show) {
583
+ modal._opener = document.activeElement; // restore target on close
584
  modal.classList.remove('modal-hidden');
585
  modal.classList.add('modal-visible');
586
  document.body.style.overflow = 'hidden';
 
590
  modal.classList.add('modal-hidden');
591
  document.body.style.overflow = '';
592
  untrapFocus(modal);
593
+ if (modal._opener && typeof modal._opener.focus === 'function') {
594
+ modal._opener.focus();
595
+ }
596
+ modal._opener = null;
597
  }
598
  };
599
 
600
  /* -------------------------------------------------------------
601
  ACCESS MODAL + INLINE FEEDBACK (replaces alerts)
602
+ ------------------------------------------------------------- */
603
  const accessModal = document.getElementById('access-modal');
604
  const accessBtn = document.getElementById('access-btn');
605
  const closeAccessModal = document.getElementById('close-access-modal');
 
625
  }
626
 
627
  function clearAccessFeedback() {
 
628
  accessFeedback.textContent = '';
629
+ accessFeedback.classList.add('hidden');
630
+ accessFeedback.classList.remove(
631
+ 'border-red-500/30','bg-red-900/10','text-red-200',
632
+ 'border-emerald-500/30','bg-emerald-900/10','text-emerald-200',
633
+ 'border-indigo-500/30','bg-indigo-900/10','text-indigo-200'
634
+ );
635
  }
636
 
637
  accessBtn.addEventListener('click', () => {
 
644
  accessModal.addEventListener('click', (e) => { if (e.target === accessModal) toggleModal(accessModal, false); });
645
 
646
  function isValidEmail(email) {
 
647
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
648
  }
649
 
 
664
  return;
665
  }
666
 
 
667
  setAccessFeedback('success', 'Request received. You will be contacted after review.');
668
  accessForm.reset();
 
 
669
  setTimeout(() => toggleModal(accessModal, false), 900);
670
  });
671
 
 
697
  /* -------------------------------------------------------------
698
  DOSSIERS
699
  + Hash deep-linking (#mcap, #chai, etc.)
700
+ + Active-card state (aria-pressed)
701
  ------------------------------------------------------------- */
702
  const DOSSIERS = {
703
  mcap: {
 
814
  programCards.forEach(btn => {
815
  const isMatch = btn.getAttribute('data-dossier') === key;
816
  btn.classList.toggle('is-active', isMatch);
817
+ btn.setAttribute('aria-pressed', String(isMatch));
818
+ btn.removeAttribute('aria-current');
819
  });
820
  }
821
 
 
864
  if (opts.setActive) setActiveCard(key);
865
  if (opts.setHash) updateHash(key, opts.replaceHash);
866
 
 
 
867
  if (!opts.replaceHash) {
868
  const isSmall = window.matchMedia && window.matchMedia('(max-width: 1023px)').matches;
869
  if (isSmall) {
 
870
  dossierTitle.scrollIntoView({ behavior: 'smooth', block: 'start' });
871
  }
872
  }
873
  }
874
 
 
875
  programCards.forEach(btn => {
876
  btn.addEventListener('click', () => {
877
  const key = btn.getAttribute('data-dossier');
 
880
  });
881
  });
882
 
 
883
  (function initFromHashOrDefault() {
884
  const keyFromHash = normalizeHashToKey();
885
  const key = keyFromHash || 'mcap';
 
886
  renderDossier(key, { setHash: true, replaceHash: true, setActive: true });
887
  })();
888
 
 
889
  window.addEventListener('hashchange', () => {
890
  const keyFromHash = normalizeHashToKey();
891
  if (keyFromHash) {
 
894
  });
895
 
896
  /* -------------------------------------------------------------
897
+ GLOBAL ESC BEHAVIOR (single source of truth)
898
  ------------------------------------------------------------- */
899
  document.addEventListener('keydown', (e) => {
900
  if (e.key === 'Escape') {