A Pen by mode-mercury on CodePen.
Created
October 17, 2025 06:11
-
-
Save mode-mercury/863248ad89d0c457919bdfb4ca750d3c to your computer and use it in GitHub Desktop.
Untitled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Text Nexus - Complete Text Analysis & Transformation</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&family=Crimson+Text:wght@400;600&family=Playfair+Display:wght@400;600&family=Roboto:wght@400;500&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --primary: #6366f1; | |
| --primary-dark: #4f46e5; | |
| --secondary: #10b981; | |
| --accent: #f59e0b; | |
| --danger: #ef4444; | |
| --dark: #1f2937; | |
| --light: #f8fafc; | |
| --gray: #6b7280; | |
| --card-bg: #ffffff; | |
| --sidebar-bg: #f8fafc; | |
| } | |
| body { | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: var(--dark); | |
| min-height: 100vh; | |
| } | |
| .app-container { | |
| max-width: 1800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| } | |
| .header-section { | |
| background: var(--card-bg); | |
| border-radius: 16px; | |
| padding: 24px; | |
| box-shadow: 0 10px 25px rgba(0,0,0,0.1); | |
| margin-bottom: 24px; | |
| } | |
| .logo { | |
| text-align: center; | |
| margin-bottom: 20px; | |
| } | |
| .logo h1 { | |
| font-size: 2rem; | |
| font-weight: 700; | |
| color: var(--primary); | |
| margin-bottom: 4px; | |
| } | |
| .logo p { | |
| color: var(--gray); | |
| font-size: 1rem; | |
| } | |
| .input-container { | |
| margin-bottom: 20px; | |
| } | |
| .main-textarea { | |
| width: 100%; | |
| height: 120px; | |
| padding: 16px; | |
| border: 2px solid #e5e7eb; | |
| border-radius: 12px; | |
| resize: vertical; | |
| font-size: 1rem; | |
| transition: all 0.3s ease; | |
| font-family: inherit; | |
| } | |
| .main-textarea:focus { | |
| outline: none; | |
| border-color: var(--primary); | |
| box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); | |
| } | |
| .controls-row { | |
| display: flex; | |
| gap: 20px; | |
| flex-wrap: wrap; | |
| justify-content: center; | |
| } | |
| .toggle-group { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| background: var(--sidebar-bg); | |
| padding: 10px 16px; | |
| border-radius: 8px; | |
| } | |
| .toggle-label { | |
| font-size: 0.875rem; | |
| font-weight: 500; | |
| white-space: nowrap; | |
| } | |
| .switch { | |
| position: relative; | |
| display: inline-block; | |
| width: 44px; | |
| height: 24px; | |
| } | |
| .switch input { | |
| opacity: 0; | |
| width: 0; | |
| height: 0; | |
| } | |
| .slider { | |
| position: absolute; | |
| cursor: pointer; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-color: #d1d5db; | |
| transition: .4s; | |
| border-radius: 24px; | |
| } | |
| .slider:before { | |
| position: absolute; | |
| content: ""; | |
| height: 18px; | |
| width: 18px; | |
| left: 3px; | |
| bottom: 3px; | |
| background-color: white; | |
| transition: .4s; | |
| border-radius: 50%; | |
| } | |
| input:checked + .slider { | |
| background-color: var(--primary); | |
| } | |
| input:checked + .slider:before { | |
| transform: translateX(20px); | |
| } | |
| /* Metrics Overview - Compact */ | |
| .metrics-compact { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); | |
| gap: 12px; | |
| margin-bottom: 20px; | |
| } | |
| .metric-compact { | |
| background: var(--card-bg); | |
| padding: 16px; | |
| border-radius: 12px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.05); | |
| text-align: center; | |
| border-left: 4px solid var(--primary); | |
| } | |
| .metric-compact.structural { | |
| border-left-color: #10b981; | |
| } | |
| .metric-compact.linguistic { | |
| border-left-color: #f59e0b; | |
| } | |
| .metric-compact.gematria { | |
| border-left-color: #ef4444; | |
| } | |
| .metric-compact.composite { | |
| border-left-color: #8b5cf6; | |
| } | |
| .metric-compact.ngram { | |
| border-left-color: #ec4899; | |
| } | |
| .metric-value-compact { | |
| font-size: 1.25rem; | |
| font-weight: 700; | |
| color: var(--dark); | |
| margin-bottom: 4px; | |
| } | |
| .metric-label-compact { | |
| font-size: 0.75rem; | |
| color: var(--gray); | |
| font-weight: 500; | |
| } | |
| /* Analysis Sections - Compact */ | |
| .analysis-compact { | |
| background: var(--card-bg); | |
| border-radius: 12px; | |
| padding: 20px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.05); | |
| height: fit-content; | |
| } | |
| .section-header-compact { | |
| display: flex; | |
| align-items: center; | |
| margin-bottom: 16px; | |
| padding-bottom: 12px; | |
| border-bottom: 2px solid #f1f5f9; | |
| } | |
| .section-header-compact h3 { | |
| font-size: 1.1rem; | |
| font-weight: 600; | |
| color: var(--dark); | |
| } | |
| .section-badge-compact { | |
| background: var(--primary); | |
| color: white; | |
| padding: 2px 8px; | |
| border-radius: 6px; | |
| font-size: 0.7rem; | |
| font-weight: 600; | |
| margin-left: 10px; | |
| } | |
| /* N-gram Display - Compact */ | |
| .ngram-grid-compact { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); | |
| gap: 8px; | |
| margin-top: 12px; | |
| } | |
| .ngram-item-compact { | |
| background: #f8fafc; | |
| padding: 8px; | |
| border-radius: 6px; | |
| border-left: 3px solid #ec4899; | |
| font-size: 0.75rem; | |
| } | |
| .ngram-text-compact { | |
| font-weight: 600; | |
| margin-bottom: 2px; | |
| } | |
| .ngram-score-compact { | |
| color: var(--gray); | |
| font-size: 0.7rem; | |
| } | |
| .ngram-type-compact { | |
| display: inline-block; | |
| background: #ec4899; | |
| color: white; | |
| padding: 1px 4px; | |
| border-radius: 4px; | |
| font-size: 0.65rem; | |
| margin-right: 4px; | |
| } | |
| /* Transformation Display - Compact */ | |
| .transform-list-compact { | |
| max-height: 200px; | |
| overflow-y: auto; | |
| margin-top: 12px; | |
| } | |
| .transform-item-compact { | |
| padding: 8px; | |
| margin-bottom: 6px; | |
| background: #f8fafc; | |
| border-radius: 6px; | |
| border-left: 3px solid var(--primary); | |
| font-size: 0.8rem; | |
| } | |
| .transform-original-compact { | |
| font-weight: 600; | |
| color: var(--dark); | |
| margin-bottom: 2px; | |
| } | |
| .transform-replacement-compact { | |
| color: var(--primary); | |
| font-weight: 500; | |
| font-size: 0.75rem; | |
| } | |
| /* Dictionary Display - Compact */ | |
| .dict-list-compact { | |
| max-height: 150px; | |
| overflow-y: auto; | |
| margin-top: 12px; | |
| } | |
| .dict-item-compact { | |
| padding: 6px 8px; | |
| margin-bottom: 4px; | |
| background: #f8fafc; | |
| border-radius: 4px; | |
| font-size: 0.75rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .dict-word-compact { | |
| font-weight: 600; | |
| color: var(--dark); | |
| } | |
| .dict-gematria-compact { | |
| color: var(--primary); | |
| font-weight: 500; | |
| font-size: 0.7rem; | |
| } | |
| /* Word Analysis - Compact */ | |
| .word-analysis-compact { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 12px; | |
| margin-top: 12px; | |
| } | |
| .word-column-compact { | |
| background: #f8fafc; | |
| border-radius: 6px; | |
| padding: 12px; | |
| } | |
| .word-column-compact h4 { | |
| font-size: 0.8rem; | |
| color: var(--gray); | |
| margin-bottom: 8px; | |
| text-align: center; | |
| } | |
| .word-item-compact { | |
| display: flex; | |
| justify-content: space-between; | |
| padding: 4px 0; | |
| font-size: 0.75rem; | |
| border-bottom: 1px solid #e5e7eb; | |
| } | |
| .word-item-compact:last-child { | |
| border-bottom: none; | |
| } | |
| .word-name-compact { | |
| font-weight: 500; | |
| } | |
| .word-value-compact { | |
| color: var(--primary); | |
| font-weight: 600; | |
| } | |
| /* Tabs Styling */ | |
| .tabs-container { | |
| background: var(--card-bg); | |
| border-radius: 16px; | |
| overflow: hidden; | |
| box-shadow: 0 10px 25px rgba(0,0,0,0.1); | |
| margin-bottom: 24px; | |
| } | |
| .tabs-header { | |
| display: flex; | |
| background: var(--sidebar-bg); | |
| border-bottom: 1px solid #e5e7eb; | |
| } | |
| .tab-button { | |
| flex: 1; | |
| padding: 16px 24px; | |
| background: none; | |
| border: none; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| color: var(--gray); | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .tab-button.active { | |
| color: var(--primary); | |
| background: var(--card-bg); | |
| border-bottom: 3px solid var(--primary); | |
| } | |
| .tab-content { | |
| display: none; | |
| padding: 24px; | |
| } | |
| .tab-content.active { | |
| display: block; | |
| } | |
| /* Letter Lab Styling */ | |
| .letter-grid { | |
| display: grid; | |
| grid-template-columns: repeat(2, 1fr); | |
| grid-template-rows: repeat(2, 1fr); | |
| border: 3px solid #6B7280; | |
| width: 70px; | |
| height: 70px; | |
| font-size: 28px; | |
| position: relative; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| background: white; | |
| } | |
| .letter-quarter { | |
| border: 1px solid #eee; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| position: relative; | |
| overflow: hidden; | |
| user-select: none; | |
| } | |
| .letter-quarter:hover { | |
| background-color: rgba(59, 130, 246, 0.1); | |
| } | |
| .letter-quarter.selected { | |
| background-color: #3B82F6; | |
| color: white; | |
| } | |
| .letter-quarter.replaced { | |
| background-color: rgba(16, 185, 129, 0.8); | |
| color: white; | |
| border: 2px solid #10B981; | |
| } | |
| .letter-full { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| pointer-events: none; | |
| z-index: 1; | |
| transition: transform 0.2s; | |
| } | |
| .workspace-letter { | |
| margin: 4px; | |
| display: inline-block; | |
| position: relative; | |
| } | |
| .workspace-letter.selected { | |
| box-shadow: 0 0 0 3px #5D5CDE; | |
| border-radius: 8px; | |
| } | |
| .quarter-content { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 12px; | |
| font-weight: bold; | |
| z-index: 2; | |
| } | |
| .waiting-area { | |
| min-height: 60px; | |
| border: 3px dashed #9CA3AF; | |
| background: rgba(249, 250, 251, 0.8); | |
| border-radius: 8px; | |
| padding: 10px; | |
| } | |
| .workspace-grid { | |
| background-image: | |
| linear-gradient(to right, rgba(156, 163, 175, 0.2) 1px, transparent 1px), | |
| linear-gradient(to bottom, rgba(156, 163, 175, 0.2) 1px, transparent 1px); | |
| background-size: 35px 35px; | |
| } | |
| /* Font classes */ | |
| .font-times { font-family: "Times New Roman", Times, serif; } | |
| .font-courier { font-family: "Courier New", Courier, monospace; } | |
| .font-arial { font-family: Arial, Helvetica, sans-serif; } | |
| .font-georgia { font-family: Georgia, serif; } | |
| .font-verdana { font-family: Verdana, sans-serif; } | |
| .font-trebuchet { font-family: "Trebuchet MS", sans-serif; } | |
| .font-comic { font-family: "Comic Sans MS", cursive; } | |
| .font-impact { font-family: Impact, sans-serif; } | |
| .font-lucida { font-family: "Lucida Console", Monaco, monospace; } | |
| .font-tahoma { font-family: Tahoma, sans-serif; } | |
| .font-palatino { font-family: Palatino, "Palatino Linotype", serif; } | |
| /* Transformation Results Styling */ | |
| .result-card { | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| border-left: 4px solid transparent; | |
| } | |
| .result-card:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 25px rgba(0,0,0,0.1); | |
| } | |
| .result-card.active { | |
| border-left-color: var(--primary); | |
| } | |
| .transformation-header { | |
| background: linear-gradient(to right, var(--primary), var(--primary-dark)); | |
| color: white; | |
| padding: 12px 16px; | |
| cursor: pointer; | |
| border-radius: 8px 8px 0 0; | |
| } | |
| .collapse-content { | |
| max-height: 0; | |
| overflow: hidden; | |
| transition: max-height 0.3s ease-out; | |
| } | |
| .collapse-content.active { | |
| max-height: 500px; | |
| } | |
| .toggle-icon { | |
| transition: transform 0.3s ease; | |
| } | |
| .toggle-icon.rotated { | |
| transform: rotate(180deg); | |
| } | |
| .result-text { | |
| font-size: 0.875rem; | |
| line-height: 1.25rem; | |
| max-height: 4rem; | |
| overflow-y: auto; | |
| } | |
| /* Character Keyboard */ | |
| .character-card { | |
| transition: all 0.2s; | |
| cursor: pointer; | |
| } | |
| .character-card:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 8px rgba(0,0,0,0.1); | |
| } | |
| /* Scrollbar Styling */ | |
| .transform-list-compact::-webkit-scrollbar, | |
| .dict-list-compact::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .transform-list-compact::-webkit-scrollbar-track, | |
| .dict-list-compact::-webkit-scrollbar-track { | |
| background: #f1f5f9; | |
| border-radius: 3px; | |
| } | |
| .transform-list-compact::-webkit-scrollbar-thumb, | |
| .dict-list-compact::-webkit-scrollbar-thumb { | |
| background: #cbd5e1; | |
| border-radius: 3px; | |
| } | |
| .transform-list-compact::-webkit-scrollbar-thumb:hover, | |
| .dict-list-compact::-webkit-scrollbar-thumb:hover { | |
| background: #94a3b8; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="app-container"> | |
| <!-- Header with Text Input --> | |
| <div class="header-section"> | |
| <div class="logo"> | |
| <h1>Text Nexus</h1> | |
| <p>Complete Text Analysis, Transformation & Letter Manipulation</p> | |
| </div> | |
| <div class="input-container"> | |
| <textarea class="main-textarea" id="text-input" placeholder="Enter your text here for complete analysis, transformation, and letter manipulation..."></textarea> | |
| </div> | |
| <div class="controls-row"> | |
| <div class="toggle-group"> | |
| <span class="toggle-label">Spell Out Characters</span> | |
| <label class="switch"> | |
| <input type="checkbox" id="spell-toggle"> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="toggle-group"> | |
| <span class="toggle-label">N-gram Analysis</span> | |
| <label class="switch"> | |
| <input type="checkbox" id="ngram-toggle" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="toggle-group"> | |
| <span class="toggle-label">Show Transformations</span> | |
| <label class="switch"> | |
| <input type="checkbox" id="transform-toggle" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="toggle-group"> | |
| <span class="toggle-label">Dictionary Lookup</span> | |
| <label class="switch"> | |
| <input type="checkbox" id="dict-toggle" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| </div> | |
| <!-- Compact Metrics --> | |
| <div class="metrics-compact"> | |
| <div class="metric-compact structural"> | |
| <div class="metric-value-compact" id="structural-score">0</div> | |
| <div class="metric-label-compact">Structural</div> | |
| </div> | |
| <div class="metric-compact linguistic"> | |
| <div class="metric-value-compact" id="linguistic-score">0</div> | |
| <div class="metric-label-compact">Linguistic</div> | |
| </div> | |
| <div class="metric-compact gematria"> | |
| <div class="metric-value-compact" id="gematria-score">0</div> | |
| <div class="metric-label-compact">Gematria</div> | |
| </div> | |
| <div class="metric-compact ngram"> | |
| <div class="metric-value-compact" id="ngram-score">0</div> | |
| <div class="metric-label-compact">N-gram</div> | |
| </div> | |
| <div class="metric-compact composite"> | |
| <div class="metric-value-compact" id="composite-score">0.00</div> | |
| <div class="metric-label-compact">Composite</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Tabs Container --> | |
| <div class="tabs-container"> | |
| <div class="tabs-header"> | |
| <button class="tab-button active" data-tab="analysis">Text Analysis</button> | |
| <button class="tab-button" data-tab="transformation">Text Transformation</button> | |
| <button class="tab-button" data-tab="letterlab">Letter Lab</button> | |
| </div> | |
| <!-- Analysis Tab --> | |
| <div id="analysis-tab" class="tab-content active"> | |
| <!-- Main Analysis Grid --> | |
| <div class="main-grid"> | |
| <!-- Left Column --> | |
| <div class="left-column"> | |
| <!-- N-gram Analysis --> | |
| <div class="analysis-compact"> | |
| <div class="section-header-compact"> | |
| <h3>N-gram Patterns</h3> | |
| <div class="section-badge-compact">LIVE</div> | |
| </div> | |
| <div class="ngram-grid-compact" id="ngram-results"> | |
| <!-- N-grams will appear here --> | |
| </div> | |
| </div> | |
| <!-- Word Analysis --> | |
| <div class="analysis-compact"> | |
| <div class="section-header-compact"> | |
| <h3>Word Analysis</h3> | |
| <div class="section-badge-compact">COMPARISON</div> | |
| </div> | |
| <div class="word-analysis-compact"> | |
| <div class="word-column-compact"> | |
| <h4>Complex Words</h4> | |
| <div id="complex-words"> | |
| <!-- Complex words will appear here --> | |
| </div> | |
| </div> | |
| <div class="word-column-compact"> | |
| <h4>Dictionary Matches</h4> | |
| <div id="core-matches"> | |
| <!-- Core matches will appear here --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Right Column --> | |
| <div class="right-column"> | |
| <!-- Transformations --> | |
| <div class="analysis-compact"> | |
| <div class="section-header-compact"> | |
| <h3>Transformations</h3> | |
| <div class="section-badge-compact">GEMATRIA</div> | |
| </div> | |
| <div class="transform-list-compact" id="transformation-output"> | |
| <!-- Transformations will appear here --> | |
| </div> | |
| </div> | |
| <!-- Dictionary --> | |
| <div class="analysis-compact"> | |
| <div class="section-header-compact"> | |
| <h3>Dictionary</h3> | |
| <div class="section-badge-compact">500+ WORDS</div> | |
| </div> | |
| <div class="dict-list-compact" id="dictionary-output"> | |
| <!-- Dictionary matches will appear here --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Transformation Tab --> | |
| <div id="transformation-tab" class="tab-content"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <!-- Transform 1: Consonant Flip --> | |
| <div class="result-card bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden"> | |
| <div class="transformation-header bg-gradient-to-r from-primary to-emerald-600 text-white p-3 cursor-pointer" data-target="collapse1"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h3 class="font-semibold text-sm">🔄 Consonant Flip</h3> | |
| <p class="text-xs opacity-90">b↔z, c↔x, d↔w...</p> | |
| </div> | |
| <span class="toggle-icon text-xl">▼</span> | |
| </div> | |
| </div> | |
| <div id="collapse1" class="collapse-content active"> | |
| <div class="p-3"> | |
| <div id="result1" class="result-text p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm break-words border"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Transform 2: Consonant + Vowel Flip --> | |
| <div class="result-card bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden"> | |
| <div class="transformation-header bg-gradient-to-r from-secondary to-violet-600 text-white p-3 cursor-pointer" data-target="collapse2"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h3 class="font-semibold text-sm">🎯 Consonant + Vowel</h3> | |
| <p class="text-xs opacity-90">+ a↔y, e↔u, i↔o</p> | |
| </div> | |
| <span class="toggle-icon text-xl">▼</span> | |
| </div> | |
| </div> | |
| <div id="collapse2" class="collapse-content active"> | |
| <div class="p-3"> | |
| <div id="result2" class="result-text p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm break-words border"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Transform 3: Upside Down Mirror --> | |
| <div class="result-card bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden"> | |
| <div class="transformation-header bg-gradient-to-r from-accent to-blue-600 text-white p-3 cursor-pointer" data-target="collapse3"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h3 class="font-semibold text-sm">🪞 Upside Down Mirror</h3> | |
| <p class="text-xs opacity-90">Custom character mapping</p> | |
| </div> | |
| <span class="toggle-icon text-xl">▼</span> | |
| </div> | |
| </div> | |
| <div id="collapse3" class="collapse-content active"> | |
| <div class="p-3 space-y-2"> | |
| <div> | |
| <p class="text-xs text-gray-600 dark:text-gray-400 mb-1">Original vowels:</p> | |
| <div id="result3a" class="result-text p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm break-words border"></div> | |
| </div> | |
| <div> | |
| <p class="text-xs text-gray-600 dark:text-gray-400 mb-1">Replaced vowels:</p> | |
| <div id="result3b" class="result-text p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm break-words border"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Transform 4: Position Rearrange --> | |
| <div class="result-card bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden"> | |
| <div class="transformation-header bg-gradient-to-r from-indigo-600 to-purple-600 text-white p-3 cursor-pointer" data-target="collapse4"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h3 class="font-semibold text-sm">🔀 Position Rearrange</h3> | |
| <p class="text-xs opacity-90">2,1,3,5,6,4,7,8 pattern</p> | |
| </div> | |
| <span class="toggle-icon text-xl">▼</span> | |
| </div> | |
| </div> | |
| <div id="collapse4" class="collapse-content active"> | |
| <div class="p-3"> | |
| <div id="result4" class="result-text p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm break-words border"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Transform 5: Letter Spin --> | |
| <div class="result-card bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden md:col-span-2"> | |
| <div class="transformation-header bg-gradient-to-r from-teal-600 to-cyan-600 text-white p-3 cursor-pointer" data-target="collapse5"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h3 class="font-semibold text-sm">🌀 Letter Spin/Flip</h3> | |
| <p class="text-xs opacity-90">Visual character rotation</p> | |
| </div> | |
| <span class="toggle-icon text-xl">▼</span> | |
| </div> | |
| </div> | |
| <div id="collapse5" class="collapse-content active"> | |
| <div class="p-3"> | |
| <div id="result5" class="result-text p-2 bg-gray-50 dark:bg-gray-700 rounded text-sm break-words border"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Letter Lab Tab --> | |
| <div id="letterlab-tab" class="tab-content"> | |
| <div class="mb-3"> | |
| <div class="flex justify-between items-center mb-1"> | |
| <h3 class="text-sm font-semibold">Workspace</h3> | |
| <div class="flex gap-1"> | |
| <button onclick="clearWorkspace()" class="px-2 py-1 bg-red-500 text-white rounded text-xs hover:bg-red-600">Clear</button> | |
| </div> | |
| </div> | |
| <div class="min-h-16 p-2 border-2 border-dashed border-gray-300 dark:border-gray-600 rounded bg-gray-50 dark:bg-gray-800 workspace-grid" id="workspace-line1"> | |
| <div class="text-gray-500 dark:text-gray-400 text-center text-sm" id="workspace-placeholder">Letters from main input will appear here</div> | |
| </div> | |
| </div> | |
| <div class="mb-3"> | |
| <h3 class="text-sm font-semibold mb-1">Character Keyboard</h3> | |
| <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 p-4"> | |
| <div class="grid grid-cols-6 md:grid-cols-10 gap-2"> | |
| <!-- QWERTY row 1 --> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="Q">Q</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="W">W</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="E">E</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="R">R</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="T">T</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="Y">Y</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="U">U</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="I">I</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="O">O</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="P">P</div> | |
| <!-- QWERTY row 2 --> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="A">A</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="S">S</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="D">D</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="F">F</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="G">G</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="H">H</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="J">J</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="K">K</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="L">L</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char=";">;</div> | |
| <!-- QWERTY row 3 --> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="Z">Z</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="X">X</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="C">C</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="V">V</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="B">B</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="N">N</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="M">M</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char=",">,</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char=".">.</div> | |
| <div class="character-card p-2 bg-white dark:bg-gray-700 rounded text-center border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 font-mono" data-char="/">/</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-2 mb-3"> | |
| <button onclick="rotateSelectedLetter(90)" class="px-2 py-1 bg-primary text-white rounded text-xs hover:bg-primary-dark">↻ 90°</button> | |
| <button onclick="rotateSelectedLetter(180)" class="px-2 py-1 bg-primary text-white rounded text-xs hover:bg-primary-dark">↻ 180°</button> | |
| <button onclick="flipSelectedLetter('h')" class="px-2 py-1 bg-secondary text-white rounded text-xs hover:bg-secondary-dark">⇄ Flip H</button> | |
| <button onclick="flipSelectedLetter('v')" class="px-2 py-1 bg-secondary text-white rounded text-xs hover:bg-secondary-dark">⇅ Flip V</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Tab functionality | |
| document.querySelectorAll('.tab-button').forEach(button => { | |
| button.addEventListener('click', function() { | |
| const tabId = this.getAttribute('data-tab'); | |
| // Update tab buttons | |
| document.querySelectorAll('.tab-button').forEach(btn => { | |
| btn.classList.remove('active'); | |
| }); | |
| this.classList.add('active'); | |
| // Update tab contents | |
| document.querySelectorAll('.tab-content').forEach(content => { | |
| content.classList.remove('active'); | |
| }); | |
| document.getElementById(`${tabId}-tab`).classList.add('active'); | |
| }); | |
| }); | |
| // Collapsible panels | |
| document.querySelectorAll('.transformation-header').forEach(header => { | |
| header.addEventListener('click', function() { | |
| const target = this.getAttribute('data-target'); | |
| const content = document.getElementById(target); | |
| const icon = this.querySelector('.toggle-icon'); | |
| if (content.classList.contains('active')) { | |
| content.classList.remove('active'); | |
| icon.classList.add('rotated'); | |
| } else { | |
| content.classList.add('active'); | |
| icon.classList.remove('rotated'); | |
| } | |
| }); | |
| }); | |
| // Character keyboard functionality | |
| document.querySelectorAll('.character-card').forEach(card => { | |
| card.addEventListener('click', function() { | |
| const char = this.getAttribute('data-char'); | |
| addCharacterToWorkspace(char); | |
| }); | |
| }); | |
| // Global state for Letter Lab | |
| let selectedLetter = null; | |
| let letterCounter = 0; | |
| // Text analysis functions (from Nexus Analyzer Pro) | |
| const EXPANDED_LINGUISTIC_DB = ["I", "YOU", "WE", "THIS", "THAT", "WHO", "WHAT", "MAN", "WOMAN", "PERSON"]; | |
| const DIPHTHONG_REPLACEMENTS = { | |
| "AE": ["AI", "AY", "EI", "EY"], | |
| "AI": ["AE", "AY", "EI", "EY"], | |
| "AU": ["AW", "OU", "OW"], | |
| "AW": ["AU", "OU", "OW"], | |
| "EA": ["EE", "EI", "IE"], | |
| "EE": ["EA", "EI", "IE"] | |
| }; | |
| const NGRAM_SCORING = { | |
| unigram: { base: 1, multiplier: 1 }, | |
| bigram: { base: 3, multiplier: 2 }, | |
| trigram: { base: 6, multiplier: 3 }, | |
| tetragram: { base: 10, multiplier: 4 } | |
| }; | |
| const CHAR_DB = { | |
| 'A': { L: 18, EG: 1 }, 'B': { L: 15, EG: 2 }, 'C': { L: 8, EG: 3 }, 'D': { L: 6, EG: 4 }, | |
| 'E': { L: 12, EG: 5 }, 'F': { L: 9, EG: 6 }, 'G': { L: 9, EG: 7 }, 'H': { L: 9, EG: 8 }, | |
| 'I': { L: 6, EG: 9 }, 'J': { L: 6, EG: 10 }, 'K': { L: 9, EG: 11 }, 'L': { L: 9, EG: 12 }, | |
| 'M': { L: 12, EG: 13 }, 'N': { L: 12, EG: 14 }, 'O': { L: 12, EG: 15 }, 'P': { L: 9, EG: 16 }, | |
| 'Q': { L: 9, EG: 17 }, 'R': { L: 12, EG: 18 }, 'S': { L: 9, EG: 19 }, 'T': { L: 9, EG: 20 }, | |
| 'U': { L: 9, EG: 21 }, 'V': { L: 9, EG: 22 }, 'W': { L: 12, EG: 23 }, 'X': { L: 9, EG: 24 }, | |
| 'Y': { L: 9, EG: 25 }, 'Z': { L: 9, EG: 26 } | |
| }; | |
| function calculateGematria(text) { | |
| return text.toUpperCase().split('').reduce((sum, char) => { | |
| return sum + (CHAR_DB[char]?.EG || 0); | |
| }, 0); | |
| } | |
| function findGematriaPreservingReplacements(text) { | |
| const originalGematria = calculateGematria(text); | |
| const replacements = []; | |
| for (const [diphthong, alternatives] of Object.entries(DIPHTHONG_REPLACEMENTS)) { | |
| if (text.toUpperCase().includes(diphthong)) { | |
| for (const replacement of alternatives) { | |
| const newText = text.toUpperCase().replace(diphthong, replacement); | |
| const newGematria = calculateGematria(newText); | |
| if (newGematria === originalGematria) { | |
| replacements.push({ | |
| original: diphthong, | |
| replacement: replacement, | |
| score: diphthong.length * 2 | |
| }); | |
| } | |
| } | |
| } | |
| } | |
| return replacements; | |
| } | |
| function detectNGrams(text, maxN = 4) { | |
| const ngrams = { | |
| unigrams: new Map(), | |
| bigrams: new Map(), | |
| trigrams: new Map(), | |
| tetragrams: new Map() | |
| }; | |
| const cleanText = text.toUpperCase().replace(/[^A-Z]/g, ''); | |
| for (let char of cleanText) { | |
| ngrams.unigrams.set(char, (ngrams.unigrams.get(char) || 0) + 1); | |
| } | |
| for (let i = 0; i < cleanText.length - 1; i++) { | |
| const bigram = cleanText.substr(i, 2); | |
| if (bigram.length === 2) ngrams.bigrams.set(bigram, (ngrams.bigrams.get(bigram) || 0) + 1); | |
| } | |
| for (let i = 0; i < cleanText.length - 2; i++) { | |
| const trigram = cleanText.substr(i, 3); | |
| if (trigram.length === 3) ngrams.trigrams.set(trigram, (ngrams.trigrams.get(trigram) || 0) + 1); | |
| } | |
| for (let i = 0; i < cleanText.length - 3; i++) { | |
| const tetragram = cleanText.substr(i, 4); | |
| if (tetragram.length === 4) ngrams.tetragrams.set(tetragram, (ngrams.tetragrams.get(tetragram) || 0) + 1); | |
| } | |
| return ngrams; | |
| } | |
| function calculateNGramScores(ngrams) { | |
| let totalScore = 0; | |
| const scoredNGrams = []; | |
| for (let [gram, count] of ngrams.unigrams) { | |
| const score = NGRAM_SCORING.unigram.base * NGRAM_SCORING.unigram.multiplier * count; | |
| totalScore += score; | |
| scoredNGrams.push({ text: gram, type: 'unigram', count, totalScore: score }); | |
| } | |
| for (let [gram, count] of ngrams.bigrams) { | |
| const score = NGRAM_SCORING.bigram.base * NGRAM_SCORING.bigram.multiplier * count; | |
| totalScore += score; | |
| scoredNGrams.push({ text: gram, type: 'bigram', count, totalScore: score }); | |
| } | |
| for (let [gram, count] of ngrams.trigrams) { | |
| const score = NGRAM_SCORING.trigram.base * NGRAM_SCORING.trigram.multiplier * count; | |
| totalScore += score; | |
| scoredNGrams.push({ text: gram, type: 'trigram', count, totalScore: score }); | |
| } | |
| for (let [gram, count] of ngrams.tetragrams) { | |
| const score = NGRAM_SCORING.tetragram.base * NGRAM_SCORING.tetragram.multiplier * count; | |
| totalScore += score; | |
| scoredNGrams.push({ text: gram, type: 'tetragram', count, totalScore: score }); | |
| } | |
| scoredNGrams.sort((a, b) => b.totalScore - a.totalScore); | |
| return { totalScore, ngrams: scoredNGrams }; | |
| } | |
| function displayNGramResults(ngramResults) { | |
| const container = document.getElementById('ngram-results'); | |
| container.innerHTML = ''; | |
| const topNGrams = ngramResults.ngrams.slice(0, 8); | |
| topNGrams.forEach(ngram => { | |
| const ngramEl = document.createElement('div'); | |
| ngramEl.className = 'ngram-item-compact'; | |
| ngramEl.innerHTML = ` | |
| <div class="ngram-text-compact"> | |
| <span class="ngram-type-compact">${ngram.type.charAt(0).toUpperCase()}</span> | |
| ${ngram.text} | |
| </div> | |
| <div class="ngram-score-compact">${ngram.totalScore}</div> | |
| `; | |
| container.appendChild(ngramEl); | |
| }); | |
| document.getElementById('ngram-score').textContent = ngramResults.totalScore; | |
| } | |
| function displayTransformations(text) { | |
| const container = document.getElementById('transformation-output'); | |
| container.innerHTML = ''; | |
| const words = text.toUpperCase().split(/\s+/).filter(word => word.length > 0); | |
| words.forEach(word => { | |
| if (word.length >= 2) { | |
| const replacements = findGematriaPreservingReplacements(word); | |
| if (replacements.length > 0) { | |
| const item = document.createElement('div'); | |
| item.className = 'transform-item-compact'; | |
| const rep = replacements[0]; | |
| const newWord = word.replace(rep.original, rep.replacement); | |
| item.innerHTML = ` | |
| <div class="transform-original-compact">${word}</div> | |
| <div class="transform-replacement-compact">→ ${newWord}</div> | |
| `; | |
| container.appendChild(item); | |
| } | |
| } | |
| }); | |
| if (container.children.length === 0) { | |
| container.innerHTML = '<div class="transform-item-compact">No transformations found</div>'; | |
| } | |
| } | |
| function displayDictionaryMatches(text) { | |
| const container = document.getElementById('dictionary-output'); | |
| container.innerHTML = ''; | |
| const words = text.toUpperCase().split(/\s+/).filter(word => word.length > 2); | |
| const matches = []; | |
| words.forEach(word => { | |
| EXPANDED_LINGUISTIC_DB.forEach(dictWord => { | |
| if (dictWord.includes(word) || word.includes(dictWord)) { | |
| const gematria = calculateGematria(dictWord); | |
| matches.push({ word: dictWord, gematria: gematria }); | |
| } | |
| }); | |
| }); | |
| matches.sort((a, b) => b.word.length - a.word.length).slice(0, 8).forEach(match => { | |
| const item = document.createElement('div'); | |
| item.className = 'dict-item-compact'; | |
| item.innerHTML = ` | |
| <span class="dict-word-compact">${match.word}</span> | |
| <span class="dict-gematria-compact">${match.gematria}</span> | |
| `; | |
| container.appendChild(item); | |
| }); | |
| if (container.children.length === 0) { | |
| container.innerHTML = '<div class="dict-item-compact">No matches found</div>'; | |
| } | |
| } | |
| function updateWordAnalysis(text) { | |
| const complexContainer = document.getElementById('complex-words'); | |
| const matchesContainer = document.getElementById('core-matches'); | |
| const words = text.toUpperCase().split(/\s+/).filter(word => word.length > 0); | |
| const complexWords = words.map(word => ({ word, length: word.length })) | |
| .sort((a, b) => b.length - a.length).slice(0, 5); | |
| complexContainer.innerHTML = ''; | |
| complexWords.forEach(item => { | |
| const el = document.createElement('div'); | |
| el.className = 'word-item-compact'; | |
| el.innerHTML = ` | |
| <span class="word-name-compact">${item.word}</span> | |
| <span class="word-value-compact">${item.length}</span> | |
| `; | |
| complexContainer.appendChild(el); | |
| }); | |
| matchesContainer.innerHTML = ''; | |
| const matches = EXPANDED_LINGUISTIC_DB.filter(word => | |
| words.some(w => word.includes(w) || w.includes(word)) | |
| ).slice(0, 5); | |
| matches.forEach(word => { | |
| const el = document.createElement('div'); | |
| el.className = 'word-item-compact'; | |
| el.innerHTML = ` | |
| <span class="word-name-compact">${word}</span> | |
| <span class="word-value-compact">${calculateGematria(word)}</span> | |
| `; | |
| matchesContainer.appendChild(el); | |
| }); | |
| } | |
| // Text transformation functions (from Text Transformer) | |
| const consonantFlip = { | |
| 'b': 'z', 'z': 'b', 'B': 'Z', 'Z': 'B', | |
| 'c': 'x', 'x': 'c', 'C': 'X', 'X': 'C', | |
| 'd': 'w', 'w': 'd', 'D': 'W', 'W': 'D', | |
| 'f': 'v', 'v': 'f', 'F': 'V', 'V': 'F', | |
| 'g': 't', 't': 'g', 'G': 'T', 'T': 'G', | |
| 'h': 's', 's': 'h', 'H': 'S', 'S': 'H', | |
| 'j': 'r', 'r': 'j', 'J': 'R', 'R': 'J', | |
| 'k': 'q', 'q': 'k', 'K': 'Q', 'Q': 'K', | |
| 'l': 'p', 'p': 'l', 'L': 'P', 'P': 'L', | |
| 'm': 'n', 'n': 'm', 'M': 'N', 'N': 'M' | |
| }; | |
| const vowelFlip = { | |
| 'a': 'y', 'y': 'a', 'A': 'Y', 'Y': 'A', | |
| 'e': 'u', 'u': 'e', 'E': 'U', 'U': 'E', | |
| 'i': 'o', 'o': 'i', 'I': 'O', 'O': 'I' | |
| }; | |
| function transform1(text) { | |
| return text.split('').map(char => { | |
| return consonantFlip[char] || char; | |
| }).join(''); | |
| } | |
| function transform2(text) { | |
| return text.split('').map(char => { | |
| let mapped = consonantFlip[char] || char; | |
| if (vowelFlip[char]) { | |
| mapped = vowelFlip[char]; | |
| } | |
| return mapped; | |
| }).join(''); | |
| } | |
| function transform3(text, replaceVowels = false) { | |
| const upsideDownMap = { | |
| 'a': 'e', 'A': 'E', 'b': 'p', 'B': 'P', 'c': 'j', 'C': 'J', | |
| 'd': 'q', 'D': 'Q', 'e': 'a', 'E': 'A', 'f': 't', 'F': 'T', | |
| 'g': 'a', 'G': 'A', 'h': 'y', 'H': 'Y', 'i': '!', 'I': '!', | |
| 'j': 'l', 'J': 'L', 'k': 'y', 'K': 'Y', 'l': 'l', 'L': 'L', | |
| 'm': 'w', 'M': 'W', 'n': 'u', 'N': 'U', 'o': 'o', 'O': 'O', 'p': 'q', 'P': 'Q', 'q': 'p', 'Q': 'P', | |
| 'r': 'l', 'R': 'L', 's': 'z', 'S': 'Z', 't': 'f', 'T': 'F', 'u': 'n', 'U': 'N', | |
| 'v': 'n', 'V': 'N', 'w': 'm', 'W': 'M', | |
| 'x': 'x', 'X': 'X', 'y': 'h', 'Y': 'H', 'z': 's', 'Z': 'S' | |
| }; | |
| return text.split('').map(char => { | |
| let mapped = upsideDownMap[char] || char; | |
| if (replaceVowels && vowelFlip[char]) { | |
| mapped = vowelFlip[char]; | |
| } | |
| return mapped; | |
| }).join(''); | |
| } | |
| function transform4(text) { | |
| const pattern = [1, 0, 2, 4, 5, 3, 6, 7]; // 2,1,3,5,6,4,7,8 pattern (0-indexed) | |
| let result = ''; | |
| for (let i = 0; i < text.length; i += pattern.length) { | |
| const chunk = text.slice(i, i + pattern.length); | |
| let rearranged = ''; | |
| for (let j = 0; j < pattern.length; j++) { | |
| const sourceIndex = pattern[j]; | |
| if (sourceIndex < chunk.length && sourceIndex >= 0) { | |
| rearranged += chunk[sourceIndex]; | |
| } | |
| } | |
| result += rearranged; | |
| } | |
| return result; | |
| } | |
| const letterSpin = { | |
| 'a': 'ɐ', 'A': '∀', 'b': 'd', 'B': 'ᗺ', 'c': 'ɔ', 'C': 'Ɔ', 'd': 'b', 'D': 'ᗡ', | |
| 'e': 'ǝ', 'E': 'Ǝ', 'f': 'ɟ', 'F': 'ᖴ', 'g': 'ƃ', 'G': 'פ', 'h': 'ɥ', 'H': 'H', | |
| 'i': 'ᴉ', 'I': 'I', 'j': 'ſ', 'J': 'ſ', 'k': 'ʞ', 'K': 'ʞ', 'l': 'l', 'L': '˥', | |
| 'm': 'ɯ', 'M': 'W', 'n': 'u', 'N': 'N', 'o': 'o', 'O': 'O', 'p': 'd', 'P': 'Ԁ', | |
| 'q': 'b', 'Q': 'Q', 'r': 'ɹ', 'R': 'ᴿ', 's': 's', 'S': 'S', 't': 'ʇ', 'T': '┴', | |
| 'u': 'n', 'U': '∩', 'v': 'ʌ', 'V': 'Λ', 'w': 'ʍ', 'W': 'M', 'x': 'x', 'X': 'X', | |
| 'y': 'ʎ', 'Y': '⅄', 'z': 'z', 'Z': 'Z' | |
| }; | |
| function transform5(text) { | |
| return text.split('').map(char => { | |
| return letterSpin[char] || char; | |
| }).join(''); | |
| } | |
| // Letter Lab functions | |
| function addCharacterToWorkspace(char) { | |
| const workspace = document.getElementById('workspace-line1'); | |
| const placeholder = document.getElementById('workspace-placeholder'); | |
| if (placeholder && !placeholder.classList.contains('hidden')) { | |
| placeholder.classList.add('hidden'); | |
| } | |
| const letterElement = createLetterElement(char, `work-${char}-${letterCounter++}`); | |
| letterElement.className = `workspace-letter font-mono`; | |
| // Make full character slightly translucent so quarters are visible but still readable | |
| const fullChar = letterElement.querySelector('.letter-full'); | |
| fullChar.style.opacity = '0.7'; // Less grayed out but quarters still visible | |
| workspace.appendChild(letterElement); | |
| } | |
| function createLetterElement(char, id) { | |
| const container = document.createElement('div'); | |
| container.className = 'letter-grid'; | |
| container.dataset.char = char; | |
| container.dataset.id = id; | |
| container.dataset.rotation = '0'; | |
| container.dataset.flip = 'none'; | |
| container.onclick = () => selectLetter(container); | |
| // Create full character overlay | |
| const fullChar = document.createElement('div'); | |
| fullChar.className = 'letter-full'; | |
| fullChar.textContent = char; | |
| container.appendChild(fullChar); | |
| // Create quarters | |
| for (let i = 0; i < 4; i++) { | |
| const quarter = document.createElement('div'); | |
| quarter.className = 'letter-quarter'; | |
| quarter.dataset.quarter = i; | |
| quarter.onclick = (e) => { | |
| e.stopPropagation(); | |
| toggleQuarterSelection(container, i); | |
| }; | |
| // Add quarter content if needed | |
| const quarterContent = document.createElement('div'); | |
| quarterContent.className = 'quarter-content'; | |
| quarter.appendChild(quarterContent); | |
| container.appendChild(quarter); | |
| } | |
| return container; | |
| } | |
| function selectLetter(letterElement) { | |
| // Clear previous selection | |
| document.querySelectorAll('.workspace-letter').forEach(el => { | |
| el.classList.remove('selected'); | |
| }); | |
| selectedLetter = letterElement; | |
| letterElement.classList.add('selected'); | |
| } | |
| function toggleQuarterSelection(letterElement, quarterIndex) { | |
| const quarter = letterElement.children[quarterIndex + 1]; // +1 for full letter overlay | |
| if (quarter.classList.contains('selected')) { | |
| quarter.classList.remove('selected'); | |
| } else { | |
| quarter.classList.add('selected'); | |
| } | |
| } | |
| function rotateSelectedLetter(degrees) { | |
| if (!selectedLetter) return; | |
| const currentRotation = parseInt(selectedLetter.dataset.rotation) || 0; | |
| const newRotation = (currentRotation + degrees) % 360; | |
| selectedLetter.dataset.rotation = newRotation; | |
| updateLetterTransform(); | |
| } | |
| function flipSelectedLetter(direction) { | |
| if (!selectedLetter) return; | |
| const currentFlip = selectedLetter.dataset.flip || 'none'; | |
| let newFlip; | |
| if (direction === 'h') { | |
| newFlip = currentFlip === 'h' ? 'none' : currentFlip === 'v' ? 'both' : currentFlip === 'both' ? 'v' : 'h'; | |
| } else if (direction === 'v') { | |
| newFlip = currentFlip === 'v' ? 'none' : currentFlip === 'h' ? 'both' : currentFlip === 'both' ? 'h' : 'v'; | |
| } | |
| selectedLetter.dataset.flip = newFlip; | |
| updateLetterTransform(); | |
| } | |
| function updateLetterTransform() { | |
| if (!selectedLetter) return; | |
| const rotation = selectedLetter.dataset.rotation || '0'; | |
| const flip = selectedLetter.dataset.flip || 'none'; | |
| const fullChar = selectedLetter.querySelector('.letter-full'); | |
| // Clear all transform classes | |
| fullChar.className = 'letter-full'; | |
| // Add rotation class | |
| if (rotation !== '0') { | |
| fullChar.classList.add(`rotate-${rotation}`); | |
| } | |
| // Add flip class | |
| if (flip !== 'none') { | |
| fullChar.classList.add(`flip-${flip}`); | |
| } | |
| } | |
| function clearWorkspace() { | |
| const line1 = document.getElementById('workspace-line1'); | |
| line1.innerHTML = '<div class="text-gray-500 dark:text-gray-400 text-center text-sm" id="workspace-placeholder">Letters from main input will appear here</div>'; | |
| selectedLetter = null; | |
| } | |
| // Main text input handler - connects all functionality | |
| document.getElementById('text-input').addEventListener('input', function() { | |
| const text = this.value; | |
| // Update analysis tab | |
| analyzeText(text); | |
| // Update transformation tab | |
| updateTransformationResults(text); | |
| // Update letter lab tab | |
| updateLetterLabFromText(text); | |
| }); | |
| function analyzeText(text) { | |
| const useNGrams = document.getElementById('ngram-toggle').checked; | |
| const useTransform = document.getElementById('transform-toggle').checked; | |
| const useDict = document.getElementById('dict-toggle').checked; | |
| // Update basic metrics | |
| document.getElementById('structural-score').textContent = text.length * 2; | |
| document.getElementById('linguistic-score').textContent = Math.round(text.length * 1.5); | |
| document.getElementById('gematria-score').textContent = calculateGematria(text); | |
| document.getElementById('composite-score').textContent = (text.length * 3.5).toFixed(1); | |
| if (!text.trim()) { | |
| document.getElementById('ngram-results').innerHTML = '<div class="ngram-item-compact">Enter text</div>'; | |
| document.getElementById('transformation-output').innerHTML = '<div class="transform-item-compact">Enter text</div>'; | |
| document.getElementById('dictionary-output').innerHTML = '<div class="dict-item-compact">Enter text</div>'; | |
| return; | |
| } | |
| if (useNGrams) { | |
| const ngrams = detectNGrams(text); | |
| const ngramScores = calculateNGramScores(ngrams); | |
| displayNGramResults(ngramScores); | |
| } | |
| if (useTransform) displayTransformations(text); | |
| if (useDict) displayDictionaryMatches(text); | |
| updateWordAnalysis(text); | |
| } | |
| function updateTransformationResults(text) { | |
| if (!text.trim()) { | |
| document.getElementById('result1').textContent = ''; | |
| document.getElementById('result2').textContent = ''; | |
| document.getElementById('result3a').textContent = ''; | |
| document.getElementById('result3b').textContent = ''; | |
| document.getElementById('result4').textContent = ''; | |
| document.getElementById('result5').textContent = ''; | |
| return; | |
| } | |
| document.getElementById('result1').textContent = transform1(text); | |
| document.getElementById('result2').textContent = transform2(text); | |
| document.getElementById('result3a').textContent = transform3(text, false); | |
| document.getElementById('result3b').textContent = transform3(text, true); | |
| document.getElementById('result4').textContent = transform4(text); | |
| document.getElementById('result5').textContent = transform5(text); | |
| } | |
| function updateLetterLabFromText(text) { | |
| clearWorkspace(); | |
| for (let char of text) { | |
| if (char.trim() !== '') { // Skip whitespace characters | |
| addCharacterToWorkspace(char); | |
| } | |
| } | |
| } | |
| // Initialize | |
| analyzeText(''); | |
| updateTransformationResults(''); | |
| updateLetterLabFromText(''); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment