viz: the wheel skin, ascendant & houses, aspect cables, native tongues
- the wheel (zodiac skin): twelve signs in the astrologer's circle (0 Aries at the ascendant's place, CCW), feeds routed by traditional rulership (verified; inflation corrected to Jupiterian Sagittarius, poverty to Saturnian Capricorn, Mercury-retro to Gemini), live planets riding the rim, natal chart on the inner ring, aspects as chords — red hard / green soft / gold conjunctions, dashed transit-to-natal. Planets re-station through the signs live. - ascendant + midheaven: birthplace (lat/lon) in the natal panel; ASC/MC from GMST + the standard formula (Monte-Carlo verified to 1e-13 deg horizon residual; anchored to sunrise physically). Rising sign announced; whole-sign houses + gold ASC/MC markers drawn on the wheel; natal.angles source (hard contacts to the angles, per transit doctrine). - aspect cables everywhere: in every skin, live sky aspects draw as faint colored lines between the planets' own spheres. - every Spirit speaks its own tongue (all scripts verified codepoint-by- codepoint): sephirot in Hebrew, chakras in Devanagari, lata'if in Arabic, nine worlds in Old Norse, planetary gates in their glyphs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
ea2920ee65
commit
b1edc37da1
303
viz/index.html
303
viz/index.html
@ -537,7 +537,7 @@
|
||||
|
||||
<p><b>💰 Your holdings — live now.</b> Right-click the sky → <b>💰 your holdings</b>. Declare what you hold — coins, and metals through their tokens (<kbd>PAXG</kbd> is an ounce of gold) — and <i>how much of each</i>, and the amounts become <b>weights</b>: a bigger bag sings louder, each holding's influence auto-scaled by its share of the total. Prices poll straight from the public market to <i>your browser</i> — the server never learns your bag, and the ledger lives only on your machine. Each holding becomes <kbd>me.btc</kbd>, <kbd>me.paxg</kbd>…, the whole bag breathes as <kbd>me.portfolio</kbd> (drift) with <kbd>me.portfolio.vel</kbd> as its churn (flux) — and it routes where money lives in every tradition: Hod's quicksilver, the Wardens' wages in the West, the dwarves' gold in Nidavellir, the Metal phase, your hopes and fears in the spread. Stock tickers come later (they need a keyed API); your coins and your gold can sing today. Your finances were already an instrument; we only added the speakers.</p>
|
||||
|
||||
<p><b>✨ Your stars — live now.</b> Right-click the sky → <b>✨ your stars</b>: birth date, time to the ten-minute, the UTC offset where you were born — and the instrument <b>casts your chart in the browser</b>, with a real ephemeris (truncated Meeus for the lights, JPL orbital elements for the planets, precessed to the tropical zodiac; verified against eclipse timings and JPL positions to a fraction of a degree). Computed here, kept here: the server never sees a chart. Then the sky's living conversation with <i>your</i> sky becomes seven sources: <kbd>natal.harmony</kbd> (transiting trines & sextiles to your points — grace), <kbd>natal.tension</kbd> (squares & <b>oppositions</b> — friction), <kbd>natal.hits</kbd> (conjunctions — emphasis), <kbd>natal.moon</kbd> (the fast hand: the Moon crossing your chart, fresh every few hours), <kbd>natal.saturn</kbd> (the slow teacher, a months-long pressure), <kbd>natal.birthday</kbd> (the solar return, swelling as your day approaches) — and the deep one, <kbd>natal.web</kbd>: your chart's own tight aspects form a <b>resonance network</b>, and a transit striking one end of your natal opposition rings the <i>whole figure</i>, exactly as astrology reads it. Your natal planets also appear as <b>gold ghosts under the godtime dial</b>, so you can watch Saturn creep toward your natal Sun for weeks before you hear it arrive. Transit orbs are kept tight (aspects peak sharply at exactness, as transit practice demands) so these sources spike and breathe rather than drone. Load anyone's chart — yours, a lover's, a friend's; the instrument plays relationships too.</p>
|
||||
<p><b>✨ Your stars — live now.</b> Right-click the sky → <b>✨ your stars</b>: birth date, time to the ten-minute, the UTC offset where you were born — and the instrument <b>casts your chart in the browser</b>, with a real ephemeris (truncated Meeus for the lights, JPL orbital elements for the planets, precessed to the tropical zodiac; verified against eclipse timings and JPL positions to a fraction of a degree). Computed here, kept here: the server never sees a chart. Then the sky's living conversation with <i>your</i> sky becomes seven sources: <kbd>natal.harmony</kbd> (transiting trines & sextiles to your points — grace), <kbd>natal.tension</kbd> (squares & <b>oppositions</b> — friction), <kbd>natal.hits</kbd> (conjunctions — emphasis), <kbd>natal.moon</kbd> (the fast hand: the Moon crossing your chart, fresh every few hours), <kbd>natal.saturn</kbd> (the slow teacher, a months-long pressure), <kbd>natal.birthday</kbd> (the solar return, swelling as your day approaches) — and the deep one, <kbd>natal.web</kbd>: your chart's own tight aspects form a <b>resonance network</b>, and a transit striking one end of your natal opposition rings the <i>whole figure</i>, exactly as astrology reads it. Your natal planets also appear as <b>gold ghosts under the godtime dial</b>, so you can watch Saturn creep toward your natal Sun for weeks before you hear it arrive. Transit orbs are kept tight (aspects peak sharply at exactness, as transit practice demands) so these sources spike and breathe rather than drone. Load anyone's chart — yours, a lover's, a friend's; the instrument plays relationships too. Give it your <b>birthplace</b> (lat/lon) and the chart gains its <b>angles</b>: the ascendant and midheaven, computed from the sidereal time of your birth (the formula is verified against the sunrise itself — the Sun stands on the ascendant as it rises). Your <b>rising sign</b> is announced when the chart is cast, transits striking the angles become <kbd>natal.angles</kbd> (hard contacts to the ASC and MC — among the heaviest events in transit work), and the <b>wheel skin</b> draws your <b>whole-sign houses</b>, the oldest house system there is, with the ASC and MC marked in gold. One honest caveat from the mathematics: the angles move a degree every four minutes, so they are only as true as your birth time.</p>
|
||||
|
||||
<p class="foot">One Source, many Spirits, one Matter — and the Source was never only "out there." The instrument's ambition is simple: <b>everything that varies can sing</b>, and the first citizen of that everything is you.</p>
|
||||
|
||||
@ -831,7 +831,7 @@
|
||||
<li><b>Right-click anything — the everything menu.</b> Every node carries its full settings under the right button: mute, <b>solo</b>, a <b>level</b> fader (0–2×), a <b>trim</b> offset, every cable it carries with its amount slider and an unpatch ×, and a nested <i>patch to →</i> list for laying new cables without dragging. Right-click the empty sky for the view menu. And the modifiers, for the fast hands: <b>click</b> mutes · <b>⇧-click</b> opens the node's tab · <b>⇧-drag</b> rides the level up and down · <b>⌥-click</b> solos a source · <b>⌘-click</b> multi-selects for grouping · <b>⌘⇧-click</b> resets a node to neutral. People play differently; the instrument shouldn't care which hand you reach with.</li>
|
||||
<li><b>Click a wheel — go inside it (mind mode).</b> In chakra view, click any chakra's core and the camera steps <i>into</i> the wheel: its mandala of petals turns around your whole field of view, and that chakra's feeds circle <i>you</i> — drag to look around the full 360°. A <b>vector console appears under your hands</b>: 12 keys of that wheel's own scale (C minor pentatonic at the root, rising key by key to B hirajoshi at the crown), played by clicking, by the <kbd>Q</kbd>–<kbd>]</kbd> row, or by any connected <b>MIDI keyboard</b> — every note runs through the world's own reverb and grit, so you are jamming <i>inside</i> the instrument, in that chakra's mode, while the planet plays around you. <kbd>↑</kbd> <kbd>↓</kbd> travel the spine wheel to wheel; <kbd>esc</kbd> steps back out. And for powerful machines, right-click the sky and set graphics to <b>ultra ✦</b>: every orbiting feed grows a glowing comet trail, and the orbits breathe so the trails weave slow spirals.</li>
|
||||
<li><b>Skins — the same spine, another cosmology.</b> Right-click the sky and cycle <b>skin</b>. Beyond the seven <i>chakras</i> there is <b>the planes</b>: the Seven Planes & forty-nine sub-planes of the Cosmic Physical Plane from the Alice Bailey / D.K. teachings — <b>I Divine</b> (white light) down through <b>Monadic</b> (violet), <b>Atmic</b>, <b>Buddhic</b>, <b>Mental</b> (where the egoic lotus sits), <b>Astral</b>, to <b>VII Physical</b> (red). The spine becomes the 49-sub-plane spectrum ladder; the side-brackets mark the <b>Monad</b>, the <b>Spiritual Triad</b> and the <b>Personality</b>; and every feed climbs to the plane that matches its rarefaction — the sun's own wind at the Divine, orbits and the sky's geometry at the Monadic, the great cyclic wheels at the Atmic, omen and aspect at the Buddhic, abstract thought and money-as-idea at the Mental, desire and fire and felt sensation at the Astral, and the dense body of the world — weather, quakes, the mortal rates, your own hands — at the Physical. Go inside any plane (mind mode) and its keys play a scale pitched to its altitude: airy whole-tone up at the Divine, grounded minor-pentatonic down at the Physical.</li>
|
||||
<li><b>One Source, many Spirits, one Matter.</b> That is the whole architecture: the <b>Source</b> is the world's data, the same for everyone; the <b>Spirit</b> is the skin — the belief system through which you read it; the <b>Matter</b> is the sound. Choose your spirit, and the same planet plays through it. The shelf so far, each rendered from its own published lore, literally and without frills: the <b>Tree of Life</b> (Hermetic Qabalah, Golden Dawn attributions — ten sephirot on three pillars, all twenty-two canonical paths, Mercury's data at Hod, the Moon's at Yesod, the body of the world at Malkut); <b>the Lodge</b> (from published Masonic sources only — Worshipful Master in the East, Wardens West and South, the North dark, Boaz and Jachin at the porch where <i>your own hands</i> stand as the candidate, the Blazing Star, the Volume of the Sacred Law as humanity's open book, and music given to the South, for Beauty holds the arts); the <b>Hermetic ladder</b> of the seven planetary gates, lead to silver; <b>Yggdrasil</b> and its nine worlds, the dwarves keeping the markets in Nidavellir; the Sufi <b>lata'if</b>, where the wind data literally breathes at Ruh, spirit-as-breath; and the <b>Wu Xing</b>, five phases in their generating ring and controlling star, the metal birds of the air routed to Metal; and <b>the Spread</b> — the Celtic Cross of the tarot (Waite's published layout), dealt live and never finished: the heavens in <i>what crowns you</i>, the deep debts and quake-roots in <i>what is beneath you</i>, the retrogrades in <i>what is behind you</i>, births and seasons in <i>what is before you</i>, money and fire in <i>your hopes and fears</i> — and <b>your own hands in the Querent's place</b>, because you are the one asking. Right-click the sky → <b>skin</b> to turn the wheel of traditions. Each map stands as its true figure — the Tree as a tree, the Lodge as a lodge — and every station opens into mind mode with its own scale under your hands.</li>
|
||||
<li><b>One Source, many Spirits, one Matter.</b> That is the whole architecture: the <b>Source</b> is the world's data, the same for everyone; the <b>Spirit</b> is the skin — the belief system through which you read it; the <b>Matter</b> is the sound. Choose your spirit, and the same planet plays through it. The shelf so far, each rendered from its own published lore, literally and without frills: the <b>Tree of Life</b> (Hermetic Qabalah, Golden Dawn attributions — ten sephirot on three pillars, all twenty-two canonical paths, Mercury's data at Hod, the Moon's at Yesod, the body of the world at Malkut); <b>the Lodge</b> (from published Masonic sources only — Worshipful Master in the East, Wardens West and South, the North dark, Boaz and Jachin at the porch where <i>your own hands</i> stand as the candidate, the Blazing Star, the Volume of the Sacred Law as humanity's open book, and music given to the South, for Beauty holds the arts); the <b>Hermetic ladder</b> of the seven planetary gates, lead to silver; <b>Yggdrasil</b> and its nine worlds, the dwarves keeping the markets in Nidavellir; the Sufi <b>lata'if</b>, where the wind data literally breathes at Ruh, spirit-as-breath; and the <b>Wu Xing</b>, five phases in their generating ring and controlling star, the metal birds of the air routed to Metal; and <b>the Spread</b> — the Celtic Cross of the tarot (Waite's published layout), dealt live and never finished: the heavens in <i>what crowns you</i>, the deep debts and quake-roots in <i>what is beneath you</i>, the retrogrades in <i>what is behind you</i>, births and seasons in <i>what is before you</i>, money and fire in <i>your hopes and fears</i> — and <b>your own hands in the Querent's place</b>, because you are the one asking. Right-click the sky → <b>skin</b> to turn the wheel of traditions. Each map stands as its true figure — the Tree as a tree, the Lodge as a lodge — and every station opens into mind mode with its own scale under your hands. Newest on the shelf: <b>the wheel</b> — the astrologer's own view, twelve signs in a circle with 0° Aries at the ascendant's place, every feed routed to its sign by traditional rulership (wildfires to Aries, your holdings to Taurus, the word to Gemini, the far-travelling planes to Sagittarius…), the <b>live planets riding the rim</b>, your natal chart on the inner ring, and the aspects drawn as <b>chords across the circle</b> — red the squares and oppositions, green the trines and sextiles, gold the conjunctions, dashed where the living sky strikes your natal points. And everywhere else, those same aspects now draw as faint <b>cables between the planets' own spheres</b> in any skin — the sky's geometry made visible in whatever cosmology you're standing in. And every Spirit now speaks <b>its own tongue</b>: the sephirot in Hebrew (כתר, חכמה, בינה…), the chakras in Devanagari (सहस्रार, अनाहत…), the lata'if in Arabic (قلب, روح, سر…), the nine worlds in Old Norse (ásgarðr, miðgarðr, helheimr…), the planetary gates in their glyphs (☽ ☿ ♀ ☉ ♂ ♃ ♄), the five phases in their characters (木 火 土 金 水). The lore, in the letters it was written in.</li>
|
||||
<li><b>The groove grids — sequence the voices.</b> Open any voice's tab (shift-click it) and there's a <b>16-step grid on the godtime clock</b>. The note voices (<i>lead, bass</i>) get a <b>mini piano roll</b> — eight rows of minor pentatonic, click to place a note, click again to clear — and while your groove is on, <i>your melody replaces the data's</i>: bitcoin lets go of the lead and you take it. Every other voice gets an <b>808-style gate row</b> that rhythmically chops the world's signal — the reverb, the grit, the percussion breathing in your pattern while the planet still decides how hard. Grooves ride the godtime tempo (lock the dial, or let your heart drive it), and they <b>save with your patch</b>. And the <b>sources</b> get the grid too, with a different power: <b>sample & hold</b> — while a source's groove is on, the world's number is only <i>sampled</i> on your lit steps and held between them, so a smooth drifting feed becomes stepped, rhythmic, quantized in time. Bitcoin arpeggiating in your pattern. The wind as a sequence. If an out port is chosen in ⚙, godtime also sends <b>MIDI clock</b> (24 ppqn), so a DAW can slave its tempo to the planet — or to your pulse.</li></ul>
|
||||
|
||||
<div class="hr"></div>
|
||||
@ -1691,6 +1691,7 @@
|
||||
drawParticles(dt);
|
||||
if (chakraMode) drawChakraView(t);
|
||||
else for (const n of sources.values()) drawSourceNode(n, t);
|
||||
drawAspectCables(t); // the sky's geometry, drawn between its spheres
|
||||
for (const n of dests.values()) drawDestNode(n, t);
|
||||
drawEditing(t);
|
||||
if (performMode) drawPerform(t, dt);
|
||||
@ -1979,13 +1980,13 @@
|
||||
const chakraSpin = { rot: 0, vel: 0, tilt: 0.35 };
|
||||
|
||||
const CHAKRAS = [ // top -> bottom, traditional petal counts
|
||||
{ key: "crown", label: "crown · sahasrara", petals: 20, col: [186, 122, 255] },
|
||||
{ key: "eye", label: "third eye · ajna", petals: 2, col: [122, 110, 255] },
|
||||
{ key: "throat", label: "throat · vishuddha", petals: 16, col: [86, 178, 255] },
|
||||
{ key: "heart", label: "heart · anahata", petals: 12, col: [96, 230, 140] },
|
||||
{ key: "solar", label: "solar plexus · manipura", petals: 10, col: [255, 214, 74] },
|
||||
{ key: "sacral", label: "sacral · svadhisthana", petals: 6, col: [255, 150, 64] },
|
||||
{ key: "root", label: "root · muladhara", petals: 4, col: [255, 88, 88] },
|
||||
{ key: "crown", label: "crown · सहस्रार sahasrara", petals: 20, col: [186, 122, 255] },
|
||||
{ key: "eye", label: "third eye · आज्ञा ajna", petals: 2, col: [122, 110, 255] },
|
||||
{ key: "throat", label: "throat · विशुद्ध vishuddha", petals: 16, col: [86, 178, 255] },
|
||||
{ key: "heart", label: "heart · अनाहत anahata", petals: 12, col: [96, 230, 140] },
|
||||
{ key: "solar", label: "solar plexus · मणिपूर manipura", petals: 10, col: [255, 214, 74] },
|
||||
{ key: "sacral", label: "sacral · स्वाधिष्ठान svadhisthana", petals: 6, col: [255, 150, 64] },
|
||||
{ key: "root", label: "root · मूलाधार muladhara", petals: 4, col: [255, 88, 88] },
|
||||
];
|
||||
const CHAKRA_BY_KEY = {};
|
||||
for (const c of CHAKRAS) CHAKRA_BY_KEY[c.key] = c;
|
||||
@ -2127,16 +2128,16 @@
|
||||
// such). Three pillars: Mercy right, Severity left, Equilibrium the middle.
|
||||
// The 22 paths below are the canonical set, all of them, none invented.
|
||||
const TREE = [
|
||||
{ key: "keter", label: "keter · crown", petals: 1, col: [255, 255, 255], pos: [0.50, 0.00] },
|
||||
{ key: "chokmah", label: "chokmah · wisdom", petals: 2, col: [150, 154, 160], pos: [0.84, 0.12] },
|
||||
{ key: "binah", label: "binah · understanding", petals: 3, col: [70, 66, 92], pos: [0.16, 0.12] },
|
||||
{ key: "chesed", label: "chesed · mercy", petals: 4, col: [60, 110, 230], pos: [0.84, 0.38] },
|
||||
{ key: "gevurah", label: "gevurah · severity", petals: 5, col: [210, 40, 40], pos: [0.16, 0.38] },
|
||||
{ key: "tiferet", label: "tiferet · beauty", petals: 6, col: [255, 210, 60], pos: [0.50, 0.50] },
|
||||
{ key: "netzach", label: "netzach · victory", petals: 7, col: [40, 190, 100], pos: [0.84, 0.64] },
|
||||
{ key: "hod", label: "hod · splendour", petals: 8, col: [240, 140, 40], pos: [0.16, 0.64] },
|
||||
{ key: "yesod", label: "yesod · foundation", petals: 9, col: [140, 70, 220], pos: [0.50, 0.78] },
|
||||
{ key: "malkut", label: "malkut · kingdom", petals: 10, col: [140, 120, 60], pos: [0.50, 0.98] },
|
||||
{ key: "keter", label: "כתר keter · crown", petals: 1, col: [255, 255, 255], pos: [0.50, 0.00] },
|
||||
{ key: "chokmah", label: "חכמה chokmah · wisdom", petals: 2, col: [150, 154, 160], pos: [0.84, 0.12] },
|
||||
{ key: "binah", label: "בינה binah · understanding", petals: 3, col: [70, 66, 92], pos: [0.16, 0.12] },
|
||||
{ key: "chesed", label: "חסד chesed · mercy", petals: 4, col: [60, 110, 230], pos: [0.84, 0.38] },
|
||||
{ key: "gevurah", label: "גבורה gevurah · severity", petals: 5, col: [210, 40, 40], pos: [0.16, 0.38] },
|
||||
{ key: "tiferet", label: "תפארת tiferet · beauty", petals: 6, col: [255, 210, 60], pos: [0.50, 0.50] },
|
||||
{ key: "netzach", label: "נצח netzach · victory", petals: 7, col: [40, 190, 100], pos: [0.84, 0.64] },
|
||||
{ key: "hod", label: "הוד hod · splendour", petals: 8, col: [240, 140, 40], pos: [0.16, 0.64] },
|
||||
{ key: "yesod", label: "יסוד yesod · foundation", petals: 9, col: [140, 70, 220], pos: [0.50, 0.78] },
|
||||
{ key: "malkut", label: "מלכות malkut · kingdom", petals: 10, col: [140, 120, 60], pos: [0.50, 0.98] },
|
||||
];
|
||||
const TREE_PATHS = [[0,1],[0,2],[0,5],[1,2],[1,5],[1,3],[2,5],[2,4],[3,4],[3,5],[3,6],
|
||||
[4,5],[4,7],[5,6],[5,7],[5,8],[6,7],[6,8],[6,9],[7,8],[7,9],[8,9]];
|
||||
@ -2205,13 +2206,13 @@
|
||||
// THE LADDER OF THE SPHERES — Hermetic ascent, Moon lowest to Saturn highest,
|
||||
// each gate its classical metal. As above, so below.
|
||||
const LADDER = [
|
||||
{ key: "saturn", label: "saturn · lead gate · the threshold", petals: 7, col: [95, 90, 110], },
|
||||
{ key: "jupiter", label: "jupiter · tin gate", petals: 6, col: [70, 110, 200], },
|
||||
{ key: "mars", label: "mars · iron gate", petals: 5, col: [190, 60, 48], },
|
||||
{ key: "sun", label: "sol · gold gate · the heart", petals: 4, col: [246, 200, 60], },
|
||||
{ key: "venus", label: "venus · copper gate", petals: 3, col: [100, 190, 130], },
|
||||
{ key: "mercury", label: "mercury · quicksilver gate", petals: 2, col: [200, 176, 130], },
|
||||
{ key: "moon", label: "luna · silver gate", petals: 1, col: [225, 230, 240], },
|
||||
{ key: "saturn", label: "♄ saturn · lead gate · the threshold", petals: 7, col: [95, 90, 110], },
|
||||
{ key: "jupiter", label: "♃ jupiter · tin gate", petals: 6, col: [70, 110, 200], },
|
||||
{ key: "mars", label: "♂ mars · iron gate", petals: 5, col: [190, 60, 48], },
|
||||
{ key: "sun", label: "☉ sol · gold gate · the heart", petals: 4, col: [246, 200, 60], },
|
||||
{ key: "venus", label: "♀ venus · copper gate", petals: 3, col: [100, 190, 130], },
|
||||
{ key: "mercury", label: "☿ mercury · quicksilver gate", petals: 2, col: [200, 176, 130], },
|
||||
{ key: "moon", label: "☽ luna · silver gate", petals: 1, col: [225, 230, 240], },
|
||||
];
|
||||
const LADDER_SCALES = {
|
||||
saturn: { root: 69, scale: "wholetone" }, jupiter: { root: 65, scale: "mixolydian" },
|
||||
@ -2235,15 +2236,15 @@
|
||||
// YGGDRASIL — the nine worlds on the world-tree; the classic three-tier
|
||||
// arrangement (a scholarly reconstruction, as the Eddas never draw one map).
|
||||
const NINE = [
|
||||
{ key: "asgard", label: "asgard · the aesir", petals: 8, col: [236, 223, 140] },
|
||||
{ key: "vanaheim", label: "vanaheim · the vanir", petals: 6, col: [86, 196, 150] },
|
||||
{ key: "alfheim", label: "alfheim · the light elves", petals: 6, col: [214, 236, 255] },
|
||||
{ key: "midgard", label: "midgard · humankind", petals: 4, col: [110, 170, 110] },
|
||||
{ key: "jotunheim", label: "jotunheim · the giants", petals: 5, col: [120, 130, 148] },
|
||||
{ key: "nidavellir", label: "nidavellir · the dwarves", petals: 4, col: [150, 116, 82] },
|
||||
{ key: "muspelheim", label: "muspelheim · fire", petals: 7, col: [255, 96, 52] },
|
||||
{ key: "niflheim", label: "niflheim · ice & mist", petals: 7, col: [150, 196, 230] },
|
||||
{ key: "helheim", label: "helheim · the dead", petals: 3, col: [110, 90, 125] },
|
||||
{ key: "asgard", label: "ásgarðr · the aesir", petals: 8, col: [236, 223, 140] },
|
||||
{ key: "vanaheim", label: "vanaheimr · the vanir", petals: 6, col: [86, 196, 150] },
|
||||
{ key: "alfheim", label: "álfheimr · the light elves", petals: 6, col: [214, 236, 255] },
|
||||
{ key: "midgard", label: "miðgarðr · humankind", petals: 4, col: [110, 170, 110] },
|
||||
{ key: "jotunheim", label: "jötunheimr · the giants", petals: 5, col: [120, 130, 148] },
|
||||
{ key: "nidavellir", label: "niðavellir · the dwarves", petals: 4, col: [150, 116, 82] },
|
||||
{ key: "muspelheim", label: "múspellsheimr · fire", petals: 7, col: [255, 96, 52] },
|
||||
{ key: "niflheim", label: "niflheimr · ice & mist", petals: 7, col: [150, 196, 230] },
|
||||
{ key: "helheim", label: "helheimr · the dead", petals: 3, col: [110, 90, 125] },
|
||||
];
|
||||
const NINE_SCALES = {
|
||||
asgard: { root: 62, scale: "lydian" }, vanaheim: { root: 57, scale: "mixolydian" },
|
||||
@ -2270,12 +2271,12 @@
|
||||
// LATA'IF-E-SITTA — the six subtle centres of the Sufi heart (Naqshbandi
|
||||
// tabulation, colours per Sirhindi's school). Ruh is spirit-as-breath.
|
||||
const LATAIF = [
|
||||
{ key: "akhfa", label: "akhfa · the most hidden", petals: 6, col: [70, 175, 90] },
|
||||
{ key: "khafi", label: "khafi · the hidden", petals: 5, col: [90, 85, 100] },
|
||||
{ key: "sirr", label: "sirr · the secret", petals: 4, col: [240, 240, 245] },
|
||||
{ key: "ruh", label: "ruh · the spirit", petals: 3, col: [225, 60, 66] },
|
||||
{ key: "qalb", label: "qalb · the heart", petals: 2, col: [235, 205, 60] },
|
||||
{ key: "nafs", label: "nafs · the self", petals: 7, col: [70, 110, 220] },
|
||||
{ key: "akhfa", label: "أخفى akhfa · the most hidden", petals: 6, col: [70, 175, 90] },
|
||||
{ key: "khafi", label: "خفي khafi · the hidden", petals: 5, col: [90, 85, 100] },
|
||||
{ key: "sirr", label: "سر sirr · the secret", petals: 4, col: [240, 240, 245] },
|
||||
{ key: "ruh", label: "روح ruh · the spirit", petals: 3, col: [225, 60, 66] },
|
||||
{ key: "qalb", label: "قلب qalb · the heart", petals: 2, col: [235, 205, 60] },
|
||||
{ key: "nafs", label: "نفس nafs · the self", petals: 7, col: [70, 110, 220] },
|
||||
];
|
||||
const LATAIF_SCALES = {
|
||||
akhfa: { root: 72, scale: "lydian" }, khafi: { root: 69, scale: "phrygian" },
|
||||
@ -2362,6 +2363,152 @@
|
||||
return "present"; // what covers you right now
|
||||
}
|
||||
|
||||
// THE WHEEL — the astrologer's own view: twelve signs in a circle, 0° Aries
|
||||
// at the ascendant's place (left), longitudes running counterclockwise. The
|
||||
// live planets ride the rim; a loaded natal chart sits on the inner ring;
|
||||
// aspects draw as chords — red the hard, green the soft, gold the meetings.
|
||||
const SIGNS = [
|
||||
{ key: "aries", label: "♈ aries", petals: 1, col: [255, 90, 70] },
|
||||
{ key: "taurus", label: "♉ taurus", petals: 2, col: [110, 200, 110] },
|
||||
{ key: "gemini", label: "♊ gemini", petals: 3, col: [255, 220, 120] },
|
||||
{ key: "cancer", label: "♋ cancer", petals: 4, col: [180, 200, 230] },
|
||||
{ key: "leo", label: "♌ leo", petals: 5, col: [255, 190, 60] },
|
||||
{ key: "virgo", label: "♍ virgo", petals: 6, col: [180, 220, 160] },
|
||||
{ key: "libra", label: "♎ libra", petals: 7, col: [230, 180, 220] },
|
||||
{ key: "scorpio", label: "♏ scorpio", petals: 8, col: [190, 70, 100] },
|
||||
{ key: "sagittarius", label: "♐ sagittarius", petals: 9, col: [220, 130, 255] },
|
||||
{ key: "capricorn", label: "♑ capricorn", petals: 10, col: [160, 150, 130] },
|
||||
{ key: "aquarius", label: "♒ aquarius", petals: 11, col: [110, 210, 240] },
|
||||
{ key: "pisces", label: "♓ pisces", petals: 12, col: [140, 160, 255] },
|
||||
];
|
||||
SIGNS.forEach((s2, i) => {
|
||||
const a2 = (180 + i * 30 + 15) * Math.PI / 180; // sign midpoints, Aries left, CCW
|
||||
s2.pos = [0.5 + 0.45 * Math.cos(a2), 0.5 - 0.45 * Math.sin(a2)];
|
||||
});
|
||||
const SIGN_SCALES = {};
|
||||
SIGNS.forEach((s2, i) => { // circle of fifths up the zodiac,
|
||||
SIGN_SCALES[s2.key] = { // scales by element
|
||||
root: 48 + (i * 7) % 12,
|
||||
scale: ["mixolydian", "minor_pent", "lydian", "dorian"][i % 4],
|
||||
};
|
||||
});
|
||||
function zodiacOf(key) { // by traditional rulership/affinity
|
||||
const k = (key || "").toLowerCase(), p = k.split(".")[0];
|
||||
if (p === "fire") return "aries"; // Mars burns
|
||||
if (p === "me" || k === "market.turnover" || k === "crypto.price") return "taurus"; // holdings
|
||||
if (p === "wiki" || /mercury_retro/.test(k)) return "gemini"; // the word; Mercury's own condition
|
||||
if (p === "weather" || k === "almanac.dec") return "cancer"; // the home sky
|
||||
if (p === "sun" || /^sky\.|light|ambient/.test(k)) return "leo"; // the light itself
|
||||
if (/aqi|pm25|lifeexp/.test(k)) return "virgo"; // health
|
||||
if (/harmony|season/.test(k)) return "libra"; // balance, equinox
|
||||
if (/deaths|debt|tension/.test(k)) return "scorpio"; // the deep and the owed
|
||||
if (p === "planes" || p === "iss" || /inflation/.test(k)) return "sagittarius"; // far travel; Jupiterian expansion
|
||||
if (/quake|hunger|poverty/.test(k)) return "capricorn"; // Saturn: structure, mountains, want
|
||||
if (p === "crypto" || /popvel|births|zodiac/.test(k)) return "aquarius"; // the collective
|
||||
if (p === "natal") return natalActive && natalActive.asc != null
|
||||
? SIGNS[Math.floor(natalActive.asc / 30)].key : "aries"; // your rising sign
|
||||
if (["hand", "tof", "touch", "body"].includes(p))
|
||||
return natalActive ? SIGNS[Math.floor(natalActive.pos.sun / 30)].key : "leo"; // your sun sign
|
||||
return "pisces"; // the dream-tide
|
||||
}
|
||||
function rezodiac() { // the planets walk the signs live
|
||||
for (const gp of GT_PLANETS) {
|
||||
const n = sources.get(gp[0]);
|
||||
if (n && typeof n.raw === "number") n.station = SIGNS[Math.floor((((n.raw % 360) + 360) % 360) / 30)].key;
|
||||
}
|
||||
}
|
||||
function drawWheelOverlay(t, g) {
|
||||
const box = mapBox(g);
|
||||
const cx = (box.x0 + box.x1) / 2, cy = (box.y0 + box.y1) / 2;
|
||||
const R = Math.min(box.x1 - box.x0, box.y1 - box.y0) * 0.5 - 4;
|
||||
const lonXY = (lon, r) => {
|
||||
const a2 = (180 + lon) * Math.PI / 180;
|
||||
return [cx + r * Math.cos(a2), cy - r * Math.sin(a2)];
|
||||
};
|
||||
ctx.save();
|
||||
ctx.textAlign = "center"; ctx.textBaseline = "middle";
|
||||
ctx.strokeStyle = "rgba(200,212,240,0.20)"; ctx.lineWidth = 1;
|
||||
ctx.beginPath(); ctx.arc(cx, cy, R, 0, Math.PI * 2); ctx.stroke();
|
||||
ctx.beginPath(); ctx.arc(cx, cy, R * 0.55, 0, Math.PI * 2); ctx.stroke();
|
||||
|
||||
// whole-sign houses + the ascendant, when a chart with a birthplace is cast
|
||||
if (natalActive && natalActive.asc != null) {
|
||||
const ascSign = Math.floor(natalActive.asc / 30);
|
||||
for (let i2 = 0; i2 < 12; i2++) {
|
||||
const s1 = lonXY(i2 * 30, R * 0.55), s2 = lonXY(i2 * 30, R);
|
||||
ctx.beginPath(); ctx.moveTo(s1[0], s1[1]); ctx.lineTo(s2[0], s2[1]);
|
||||
ctx.strokeStyle = "rgba(200,212,240,0.10)"; ctx.lineWidth = 1; ctx.stroke();
|
||||
const hp = lonXY(i2 * 30 + 15, R * 0.47);
|
||||
ctx.fillStyle = "rgba(190,205,235,0.4)";
|
||||
ctx.font = "500 9px 'Helvetica Neue', Arial, sans-serif";
|
||||
ctx.fillText(String(((i2 - ascSign + 12) % 12) + 1), hp[0], hp[1]);
|
||||
}
|
||||
const a1 = lonXY(natalActive.asc, R * 0.5), a2 = lonXY(natalActive.asc, R + 9);
|
||||
ctx.beginPath(); ctx.moveTo(a1[0], a1[1]); ctx.lineTo(a2[0], a2[1]);
|
||||
ctx.strokeStyle = "rgba(255,214,130,0.7)"; ctx.lineWidth = 1.6; ctx.stroke();
|
||||
const al = lonXY(natalActive.asc, R + 20);
|
||||
ctx.fillStyle = "rgba(255,214,130,0.85)";
|
||||
ctx.font = "600 9px 'Helvetica Neue', Arial, sans-serif";
|
||||
ctx.fillText("ASC", al[0], al[1]);
|
||||
if (natalActive.mc != null) {
|
||||
const m1 = lonXY(natalActive.mc, R * 0.5), m2 = lonXY(natalActive.mc, R + 9);
|
||||
ctx.beginPath(); ctx.moveTo(m1[0], m1[1]); ctx.lineTo(m2[0], m2[1]);
|
||||
ctx.strokeStyle = "rgba(255,214,130,0.45)"; ctx.lineWidth = 1.2; ctx.stroke();
|
||||
const ml = lonXY(natalActive.mc, R + 20);
|
||||
ctx.fillStyle = "rgba(255,214,130,0.6)";
|
||||
ctx.fillText("MC", ml[0], ml[1]);
|
||||
}
|
||||
}
|
||||
|
||||
const KINDCOL = { hard: "rgba(255,95,95,", soft: "rgba(110,220,150,", conj: "rgba(255,214,110," };
|
||||
const live = [];
|
||||
for (const gp of GT_PLANETS) {
|
||||
const n = sources.get(gp[0]);
|
||||
if (n && typeof n.raw === "number")
|
||||
live.push({ k: gp[0], glyph: gp[1], lon: ((n.raw % 360) + 360) % 360 });
|
||||
}
|
||||
// sky-to-sky chords on the rim
|
||||
for (let i2 = 0; i2 < live.length; i2++) for (let j2 = i2 + 1; j2 < live.length; j2++) {
|
||||
const h = aspectHit(live[i2].lon, live[j2].lon, /sun|moon/.test(live[i2].k + live[j2].k));
|
||||
if (!h || h.s < 0.05) continue;
|
||||
const p1 = lonXY(live[i2].lon, R), p2 = lonXY(live[j2].lon, R);
|
||||
ctx.beginPath(); ctx.moveTo(p1[0], p1[1]); ctx.lineTo(p2[0], p2[1]);
|
||||
ctx.strokeStyle = KINDCOL[h.kind] + (0.15 + h.s * 0.6).toFixed(3) + ")";
|
||||
ctx.lineWidth = 0.8 + h.s * 2.2; ctx.stroke();
|
||||
}
|
||||
// the natal chart on the inner ring + transit chords striking it
|
||||
if (natalActive) {
|
||||
const NG = { sun: "☉", moon: "☽", mercury: "☿", venus: "♀", mars: "♂", jupiter: "♃", saturn: "♄" };
|
||||
for (const p2 in NG) {
|
||||
const nl = natalActive.pos[p2];
|
||||
for (const lv of live) {
|
||||
const h = aspectHit(lv.lon, nl, p2 === "sun" || p2 === "moon" || /sun|moon/.test(lv.k));
|
||||
if (!h || h.s < 0.08) continue;
|
||||
const q1 = lonXY(lv.lon, R), q2 = lonXY(nl, R * 0.55);
|
||||
ctx.setLineDash([3, 4]);
|
||||
ctx.beginPath(); ctx.moveTo(q1[0], q1[1]); ctx.lineTo(q2[0], q2[1]);
|
||||
ctx.strokeStyle = KINDCOL[h.kind] + (0.15 + h.s * 0.55).toFixed(3) + ")";
|
||||
ctx.lineWidth = 0.8 + h.s * 1.8; ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
const gp2 = lonXY(nl, R * 0.55);
|
||||
ctx.fillStyle = "rgba(255,214,130,0.6)";
|
||||
ctx.font = "11px 'Helvetica Neue', Arial, sans-serif";
|
||||
ctx.fillText(NG[p2], gp2[0], gp2[1]);
|
||||
}
|
||||
}
|
||||
// the living planets on the rim
|
||||
for (const lv of live) {
|
||||
const pp = lonXY(lv.lon, R);
|
||||
ctx.font = "13px 'Helvetica Neue', Arial, sans-serif";
|
||||
ctx.fillStyle = "rgba(150,190,255,0.35)";
|
||||
ctx.fillText(lv.glyph, pp[0], pp[1] + 0.5);
|
||||
ctx.fillStyle = "rgba(224,234,255,0.95)";
|
||||
ctx.fillText(lv.glyph, pp[0], pp[1]);
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
const SKINS = {
|
||||
chakra: {
|
||||
key: "chakra", label: "chakra", word: "chakra",
|
||||
@ -2401,6 +2548,11 @@
|
||||
key: "tarot", label: "the spread (tarot)", word: "position", layout: "map",
|
||||
stations: SPREAD, stationOf: spreadOf, scaleOf: (k) => SPREAD_SCALES[k], paths: SPREAD_PATHS,
|
||||
},
|
||||
zodiac: {
|
||||
key: "zodiac", label: "the wheel (zodiac)", word: "sign", layout: "map",
|
||||
stations: SIGNS, stationOf: zodiacOf, scaleOf: (k) => SIGN_SCALES[k],
|
||||
overlay: drawWheelOverlay, dynamicStations: rezodiac,
|
||||
},
|
||||
};
|
||||
for (const s in SKINS) {
|
||||
const byKey = {};
|
||||
@ -2435,6 +2587,7 @@
|
||||
chakraSpin.rot += chakraSpin.vel * dt + dt * 0.12;
|
||||
}
|
||||
const g = chakraGeom();
|
||||
if (activeSkin.dynamicStations) activeSkin.dynamicStations(); // e.g. planets walking the signs
|
||||
for (const c of activeSkin.stations) { c.members = []; c.energy = 0; }
|
||||
for (const n of sources.values()) {
|
||||
if (!n.station) n.station = activeSkin.stationOf(n.key);
|
||||
@ -2722,9 +2875,31 @@
|
||||
ctx.fillStyle = rgba(rgbMix(c.col, 0.55), 0.8);
|
||||
ctx.fillText(c.label + (c.members.length ? " · " + c.members.length : ""), cx2, cy2 + r + 16);
|
||||
});
|
||||
if (activeSkin.overlay) activeSkin.overlay(t, g); // e.g. the zodiac wheel's chords & houses
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// aspects as cables — in every view, the planets' live aspects draw as lines
|
||||
// between their own spheres: red the hard, green the soft, gold the meetings
|
||||
function drawAspectCables(t) {
|
||||
if (typeof aspectHit !== "function") return;
|
||||
const pts = [];
|
||||
for (const gp of GT_PLANETS) {
|
||||
const n = sources.get(gp[0]);
|
||||
if (n && typeof n.raw === "number" && n.x > -9000 && n.x !== 0) pts.push(n);
|
||||
}
|
||||
const KINDCOL = { hard: "rgba(255,95,95,", soft: "rgba(110,220,150,", conj: "rgba(255,214,110," };
|
||||
for (let i = 0; i < pts.length; i++) for (let j = i + 1; j < pts.length; j++) {
|
||||
const h = aspectHit(((pts[i].raw % 360) + 360) % 360, ((pts[j].raw % 360) + 360) % 360,
|
||||
/sun|moon/.test(pts[i].key + pts[j].key));
|
||||
if (!h || h.s < 0.08) continue;
|
||||
ctx.beginPath(); ctx.moveTo(pts[i].x, pts[i].y); ctx.lineTo(pts[j].x, pts[j].y);
|
||||
ctx.strokeStyle = KINDCOL[h.kind] + (0.10 + h.s * 0.45).toFixed(3) + ")";
|
||||
ctx.lineWidth = 0.8 + h.s * 2;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
function drawStationPaths() { // the canonical connective lines of a map skin
|
||||
const draw = (pairs, dashed) => {
|
||||
if (!pairs) return;
|
||||
@ -3856,14 +4031,26 @@
|
||||
let natalActive = null; // {name, pos{7}, web[{a,b,kind,w}]}
|
||||
|
||||
function computeNatal(c) {
|
||||
const T = jCent(julianDay(+c.y, +c.mo, +c.d, +c.hh + (+c.mm) / 60 - (+c.utcoff || 0)));
|
||||
const jd0 = julianDay(+c.y, +c.mo, +c.d, +c.hh + (+c.mm) / 60 - (+c.utcoff || 0));
|
||||
const T = jCent(jd0);
|
||||
const pos = skyAt(T);
|
||||
const web = []; // the chart's own tight aspects — what transits will ring
|
||||
for (let i = 0; i < 7; i++) for (let j = i + 1; j < 7; j++) {
|
||||
const h = aspectHit(pos[PLANET7[i]], pos[PLANET7[j]], false);
|
||||
if (h && h.s > 0.1) web.push({ a: PLANET7[i], b: PLANET7[j], kind: h.kind, w: h.s });
|
||||
}
|
||||
return { pos, web };
|
||||
// the angles — ascendant & midheaven, when a birthplace is given. Formula
|
||||
// verified analytically (Monte-Carlo horizon residual ~1e-13°) and against
|
||||
// sunrise: the Sun sits on the ASC at the geometric rise, refraction aside.
|
||||
let asc = null, mc = null;
|
||||
if (c.lat != null && c.lon != null && isFinite(+c.lat) && isFinite(+c.lon)) {
|
||||
const eps = (23.4392911 - 0.0130042 * T) * D2R;
|
||||
const th = norm360(280.46061837 + 360.98564736629 * (jd0 - 2451545.0) + (+c.lon)) * D2R;
|
||||
const phi = (+c.lat) * D2R;
|
||||
asc = norm360(Math.atan2(Math.cos(th), -(Math.sin(th) * Math.cos(eps) + Math.tan(phi) * Math.sin(eps))) / D2R);
|
||||
mc = norm360(Math.atan2(Math.sin(th), Math.cos(th) * Math.cos(eps)) / D2R);
|
||||
}
|
||||
return { pos, web, asc, mc };
|
||||
}
|
||||
|
||||
function setNatalSource(key, label, norm) {
|
||||
@ -3900,6 +4087,16 @@
|
||||
setNatalSource("natal.moon", "the moon on " + who + "'s chart", moonS);
|
||||
setNatalSource("natal.saturn", "saturn on " + who + "'s chart", satS);
|
||||
setNatalSource("natal.birthday", who + " · solar return", Math.max(0, 1 - sepDeg(Tr.sun, natalActive.pos.sun) / 15));
|
||||
if (natalActive.asc != null) { // the angles receive; hard contacts carry the weight
|
||||
let ang = 0;
|
||||
for (const tp of PLANET7) {
|
||||
const hA = aspectHit(Tr[tp], natalActive.asc, false);
|
||||
const hM = aspectHit(Tr[tp], natalActive.mc, false);
|
||||
if (hA && hA.kind !== "soft") ang = Math.max(ang, hA.s);
|
||||
if (hM && hM.kind !== "soft") ang = Math.max(ang, hM.s);
|
||||
}
|
||||
setNatalSource("natal.angles", who + " · the angles struck", ang);
|
||||
}
|
||||
}
|
||||
function activateChart(i) {
|
||||
charts.active = i;
|
||||
@ -3907,9 +4104,10 @@
|
||||
const c = charts.list[i];
|
||||
if (!c) { natalActive = null; return; }
|
||||
const n = computeNatal(c);
|
||||
natalActive = { name: c.name || "you", pos: n.pos, web: n.web };
|
||||
natalActive = { name: c.name || "you", pos: n.pos, web: n.web, asc: n.asc, mc: n.mc };
|
||||
natalTick();
|
||||
eventTicker.unshift({ text: "✨ " + natalActive.name + "'s sky is in the choir · " + n.web.length + " natal aspects in the web", tAdded: now(), src: "sys" });
|
||||
const rising = n.asc != null ? " · " + SIGNS[Math.floor(n.asc / 30)].key + " rising" : "";
|
||||
eventTicker.unshift({ text: "✨ " + natalActive.name + "'s sky is in the choir · " + n.web.length + " natal aspects in the web" + rising, tAdded: now(), src: "sys" });
|
||||
}
|
||||
setInterval(natalTick, 60000); // the moon moves ~0.5°/hour — a minute is plenty
|
||||
if (charts.list.length) setTimeout(() => activateChart(charts.active), 1500);
|
||||
@ -3953,12 +4151,17 @@
|
||||
return inp;
|
||||
};
|
||||
const nameI = mk("name (you, a friend…)"), dateI = mk("", "date"), timeI = mk("", "time"),
|
||||
utcI = mk("UTC offset at birth, e.g. +10 or -5.5", "number");
|
||||
utcI.step = "0.5";
|
||||
utcI = mk("UTC offset at birth, e.g. +10 or -5.5", "number"),
|
||||
latI = mk("birth lat, e.g. -27.47", "number"), lonI = mk("birth lon (east +), e.g. 153.03", "number");
|
||||
utcI.step = "0.5"; latI.step = "any"; lonI.step = "any";
|
||||
const r1 = document.createElement("div"); r1.className = "hrow"; r1.appendChild(nameI);
|
||||
const r2 = document.createElement("div"); r2.className = "hrow"; r2.appendChild(dateI); r2.appendChild(timeI);
|
||||
const r3 = document.createElement("div"); r3.className = "hrow"; r3.appendChild(utcI);
|
||||
natalEl.appendChild(r1); natalEl.appendChild(r2); natalEl.appendChild(r3);
|
||||
const r4 = document.createElement("div"); r4.className = "hrow"; r4.appendChild(latI); r4.appendChild(lonI);
|
||||
natalEl.appendChild(r1); natalEl.appendChild(r2); natalEl.appendChild(r3); natalEl.appendChild(r4);
|
||||
const hint = document.createElement("div"); hint.className = "sub";
|
||||
hint.textContent = "lat/lon unlock the ascendant, midheaven & whole-sign houses (the wheel skin draws them). the angles move 1° every 4 minutes — birth-time precision matters most here.";
|
||||
natalEl.appendChild(hint);
|
||||
const save = document.createElement("button"); save.className = "midibtn"; save.style.marginTop = "8px";
|
||||
save.textContent = "cast the chart";
|
||||
save.onclick = () => {
|
||||
@ -3966,7 +4169,9 @@
|
||||
const [y, mo, d] = dateI.value.split("-").map(Number);
|
||||
const [hh, mm] = timeI.value.split(":").map(Number);
|
||||
if (y < 1800 || y > 2049) { sub.textContent = "the ephemeris holds 1800–2049 — outside that the sky drifts."; return; }
|
||||
charts.list.push({ name: nameI.value.trim() || "you", y, mo, d, hh, mm, utcoff: parseFloat(utcI.value) || 0 });
|
||||
charts.list.push({ name: nameI.value.trim() || "you", y, mo, d, hh, mm, utcoff: parseFloat(utcI.value) || 0,
|
||||
lat: latI.value === "" ? null : parseFloat(latI.value),
|
||||
lon: lonI.value === "" ? null : parseFloat(lonI.value) });
|
||||
try { localStorage.setItem("gs_charts", JSON.stringify(charts)); } catch (e) {}
|
||||
activateChart(charts.list.length - 1);
|
||||
openNatal();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user