u/Unfortunate_Harvard

Thoughts!

Thoughts!

Couple of thoughts about this book.

  1. It’s a really high-quality book. It’s really nice to see that a lot of money was spent on the presentation of these images. It’s always really sad when I see people not put together the best photo books for their really great photos.

  2. Goddamn can this man shoot a camera!

  3. If you’re looking for a book that contains a ton of Fall Out Boy material this actually isn’t that. Which I actually found more interesting because I think it’s Joe in a lot of ways maybe trying to be himself apart from the band which I think is a really healthy thing when you’re doing a different type of art.

  4. If you’re used to seeing digital photos all the time seeing film photos is such a stark contrast and I forget about that even though I’ve been photographing for 30 years.

  5. By the book it’s well worth the money!

u/Unfortunate_Harvard — 1 day ago
▲ 25 r/guitars

Fuzz

Working in my second song ever (double drop d) and have never been a big fuzz guy. I have a big muff cause you know, 90s nostalgia, but Jesus this thing is great!

u/Unfortunate_Harvard — 5 days ago

Guitar fretboard memorization tool

So I’ve been working on memorizing the fretboard, and it’s really been hard. So I made an ai fretboard flash card system. If it’s helpful great! Just dump it into Claude or any jsx compilers and viola.

It will allow you to choose all six, or just the bottom two strings, you can do fret to note, or note to fret, or limit your notes to a scale.

———————————-

import { useState, useEffect } from “react”;

const NOTES = [‘E’,‘F’,‘F#’,‘G’,‘G#’,‘A’,‘A#’,‘B’,‘C’,‘C#’,‘D’,‘D#’];
const OPEN_IDX = { 6:0, 5:5, 4:10, 3:3, 2:7, 1:0 };
const STR_LABEL = { 6:‘E’, 5:‘A’, 4:‘D’, 3:‘G’, 2:‘B’, 1:‘e’ };
const ALL_KEYS = [‘C’,‘C#’,‘D’,‘D#’,‘E’,‘F’,‘F#’,‘G’,‘G#’,‘A’,‘A#’,‘B’];
const SCALES = {
‘Major’: [0,2,4,5,7,9,11],
‘Minor’: [0,2,3,5,7,8,10],
‘Pent. Major’:[0,2,4,7,9],
‘Pent. Minor’:[0,3,5,7,10],
‘Blues’: [0,3,5,6,7,10],
};
const POS_OFFSETS = [0, 2, 5, 7, -3];

function noteAt(str, fret) {
return NOTES[(OPEN_IDX[str] + fret) % 12];
}
function shuffled(arr) {
const a = […arr];
for (let i = a.length - 1; i > 0; i–) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
function getPosRange(key, posNum) {
const rootFret = NOTES.indexOf(key);
let start = rootFret + POS_OFFSETS[posNum - 1];
if (start < 0) start += 12;
if (start > 12) start -= 12;
return [Math.max(0, start), Math.min(12, start + 4)];
}

const NUT_X = 72;
const FRET_W = 58;
const OPEN_W = 48;
const STR_GAP = 48;
const VPAD = 32;
const FB_TOP = 14;
const SVG_W = NUT_X + 12 * FRET_W + 12;

function cellX(fret) {
return fret === 0 ? NUT_X - OPEN_W / 2 : NUT_X + (fret - 0.5) * FRET_W;
}

export default function App() {
const [strSet, setStrSet] = useState(‘all’);
const [mode, setMode] = useState(‘fret-to-note’);
const [selKey, setSelKey] = useState(null);
const [selScale, setSelScale] = useState(null);
const [selPos, setSelPos] = useState(‘all’);
const [card, setCard] = useState(null);
const [choices, setChoices] = useState([]);
const [picked, setPicked] = useState(null);
const [selFret, setSelFret] = useState(null);
const [feedback, setFeedback] = useState(null);
const [score, setScore] = useState({ c: 0, t: 0 });
const [streak, setStreak] = useState(0);

const strs = strSet === ‘ea’ ? [6, 5] : [6, 5, 4, 3, 2, 1];
const svgH = VPAD + (strs.length - 1) * STR_GAP + VPAD;
const fbH = svgH - 2 * FB_TOP;

const scaleNoteSet = selKey && selScale
? new Set(SCALES[selScale].map(i => NOTES[(NOTES.indexOf(selKey) + i) % 12]))
: null;
const fretRange = selKey && selScale && selPos !== ‘all’
? getPosRange(selKey, selPos)
: [0, 12];
const [fMin, fMax] = fretRange;

function strY(si) { return VPAD + si * STR_GAP; }

function deal() {
const candidates = [];
for (const str of strs) {
for (let fret = fMin; fret <= fMax; fret++) {
const note = noteAt(str, fret);
if (!scaleNoteSet || scaleNoteSet.has(note)) {
candidates.push({ str, fret, note });
}
}
}
if (!candidates.length) return;
const { str, fret, note } = candidates[Math.floor(Math.random() * candidates.length)];
setCard({ str, fret, note });
setPicked(null);
setSelFret(null);
setFeedback(null);
if (mode === ‘fret-to-note’) {
const pool = scaleNoteSet
? […scaleNoteSet].filter(n => n !== note)
: NOTES.filter(n => n !== note);
setChoices(shuffled([note, …shuffled(pool).slice(0, 3)]));
}
}

useEffect(() => { deal(); }, [mode, strSet, selKey, selScale, selPos]);

function handleResult(ok) {
setFeedback(ok ? ‘correct’ : ‘wrong’);
setScore(s => ({ c: s.c + (ok ? 1 : 0), t: s.t + 1 }));
setStreak(s => ok ? s + 1 : 0);
if (ok && mode === ‘fret-to-note’) setTimeout(() => deal(), 900);
}

function answerNote(note) {
if (feedback) return;
setPicked(note);
handleResult(note === card.note);
}

function submit() {
if (!selFret || feedback) return;
handleResult(noteAt(selFret.str, selFret.fret) === card.note);
}

function dotAt(si, fret) {
if (!card) return null;
const str = strs[si];
const n = noteAt(str, fret);
const inRange = fret >= fMin && fret <= fMax;
const inScale = !scaleNoteSet || scaleNoteSet.has(n);
if (mode === ‘fret-to-note’) {
if (str === card.str && fret === card.fret) {
if (!feedback) return { fill: ‘#F5C842’, label: null };
return { fill: feedback === ‘correct’ ? ‘#4ADE80’ : ‘#F87171’, label: card.note };
}
} else {
const isCorrect = n === card.note && inRange && inScale;
const isSel = selFret && str === selFret.str && fret === selFret.fret;
if (feedback) {
if (isCorrect) return { fill: ‘#4ADE80’, label: card.note };
if (isSel && !isCorrect) return { fill: ‘#F87171’, label: n };
} else if (isSel) {
return { fill: ‘#F5C842’, label: null };
}
}
return null;
}

const pct = score.t > 0 ? Math.round(score.c / score.t * 100) : 0;
if (!card || !strs.includes(card.str)) return null;

const hiX1 = fMin === 0 ? NUT_X - OPEN_W : NUT_X + (fMin - 1) * FRET_W;
const hiX2 = NUT_X + fMax * FRET_W;

const fretboard = (
<svg width={SVG_W} height={svgH} viewBox={`0 0 ${SVG_W} ${svgH}`}
style={{ maxWidth: ‘100%’, display: ‘block’, margin: ‘0 auto’ }}>
<defs>
<linearGradient id="wood" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#3C1808" />
<stop offset="100%" stopColor="#200B03" />
</linearGradient>
<linearGradient id="hs" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#16080300" />
<stop offset="100%" stopColor="#160803" />
</linearGradient>
</defs>
<rect x={0} y={FB_TOP} width={NUT_X - 3} height={fbH} fill=“url(#hs)” />
<rect x={NUT_X - 3} y={FB_TOP} width={SVG_W - NUT_X + 3 - 8} height={fbH} fill=“url(#wood)” />
{scaleNoteSet && selPos !== ‘all’ && (
<rect x={hiX1} y={FB_TOP} width={hiX2 - hiX1} height={fbH}
fill=“rgba(245,200,66,0.12)” stroke=“rgba(245,200,66,0.3)” strokeWidth={1.5} rx={2} />
)}
{[3,5,7,9,12].flatMap(f => {
const cx = NUT_X + (f - 0.5) * FRET_W;
if (f === 12 && strs.length > 2)
return [1,2].map(i => <circle key={`inlay-12-${i}`} cx={cx} cy={strY(i)} r={5} fill=”#3A1808” />);
return [<circle key={`inlay-${f}`} cx={cx} cy={svgH / 2} r={5} fill=”#3A1808” />];
})}
{strs.map((str, si) => (
<line key={str} x1={10} y1={strY(si)} x2={SVG_W - 8} y2={strY(si)}
stroke=”#C8A060”
strokeWidth={str===6?2.8:str===5?2.3:str===4?1.9:str===3?1.6:str===2?1.2:0.9}
opacity={0.72} />
))}
<rect x={NUT_X - 5} y={FB_TOP} width={9} height={fbH} fill=”#DCC880” rx={1.5} />
{Array.from({ length: 12 }, (*, i) => i + 1).map(f => (
<rect key={f} x={NUT_X + f * FRET_W - 2.5} y={FB_TOP} width={5} height={fbH} fill=”#907040” rx={1} />
))}
{strs.map((str, si) => (
<text key={str} x={18} y={strY(si) + 6} fill=”#FFFFFF” fontSize={14}
textAnchor=“middle” fontFamily=“Georgia,serif” fontWeight=“bold”>
{STR_LABEL[str]}
</text>
))}
{[0,3,5,7,9,12].map(f => (
<text key={f} x={cellX(f)} y={svgH - 6} fill=”#FFFFFF” fontSize={12}
textAnchor=“middle” fontFamily=“monospace” fontWeight=“bold”>
{f}
</text>
))}
{mode === ‘note-to-fret’ && !feedback && strs.map((str, si) =>
Array.from({ length: fMax - fMin + 1 }, (*, i) => {
const fret = fMin + i;
const n = noteAt(str, fret);
if (scaleNoteSet && !scaleNoteSet.has(n)) return null;
const rx = fret === 0 ? NUT_X - OPEN_W : NUT_X + (fret - 1) * FRET_W;
return (
<rect key={`hit-${str}-${fret}`}
x={rx} y={strY(si) - STR_GAP / 2}
width={fret === 0 ? OPEN_W : FRET_W} height={STR_GAP}
fill=“transparent” style={{ cursor: ‘pointer’ }}
onClick={() => setSelFret({ str, fret })} />
);
})
)}
{strs.map((str, si) =>
Array.from({ length: 13 }, (_, fret) => {
const d = dotAt(si, fret);
if (!d) return null;
const cx = cellX(fret), cy = strY(si);
return (
<g key={`dot-${str}-${fret}`}>
<circle cx={cx} cy={cy} r={15} fill={d.fill} stroke="#080402" strokeWidth={2.5} />
{d.label && (
<text x={cx} y={cy + 5} textAnchor=“middle” fill=”#080402”
fontSize={12} fontWeight=“bold” fontFamily=“monospace”>
{d.label}
</text>
)}
</g>
);
})
)}
</svg>
);

const filterLabel = selKey && selScale
? `${selKey} ${selScale}${selPos !== 'all' ? ` · Position ${selPos}` : ''}`
: ‘Learn the fretboard, one note at a time’;

return (

<div style={{
minHeight: ‘100vh’,
background: ‘linear-gradient(170deg, #060402 0%, #0F0603 60%, #060402 100%)’,
color: ‘#FFFFFF’,
fontFamily: ‘Georgia, serif’,
display: ‘flex’, flexDirection: ‘column’, alignItems: ‘center’,
padding: ‘20px 12px 48px’,
}}>
<style>{\\\`@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Space+Mono:wght@400;700&display=swap'); \\\* { box-sizing: border-box; margin: 0; padding: 0; } .tog { padding:10px 18px; border-radius:4px; cursor:pointer; font-family:Georgia,serif; font-size:14px; border:1.5px solid #3A1E08; background:transparent; color:#A07040; transition:all 0.15s; } .tog.on { background:#2E1A08; border-color:#C08030; color:#F0C060; font-weight:bold; } .tog:hover:not(.on) { border-color:#5A3010; color:#C09050; } .kb { padding:9px 8px; border-radius:5px; cursor:pointer; min-width:50px; font-family:'Space Mono',monospace; font-size:14px; border:1.5px solid #3A1E08; background:#0C0804; color:#C08040; transition:all 0.15s; } .kb.on { background:#3A1C08; border-color:#F5C842; color:#F5C842; } .kb:hover:not(.on) { background:#160C04; border-color:#6A4020; } .sb { padding:9px 14px; border-radius:5px; cursor:pointer; font-family:Georgia,serif; font-size:13px; border:1.5px solid #3A1E08; background:#0C0804; color:#C08040; transition:all 0.15s; } .sb.on { background:#0A2814; border-color:#4ADE80; color:#4ADE80; } .sb:hover:not(.on) { background:#160C04; border-color:#6A4020; } .pb { padding:9px 14px; border-radius:5px; cursor:pointer; font-family:Georgia,serif; font-size:13px; border:1.5px solid #3A1E08; background:#0C0804; color:#C08040; transition:all 0.15s; } .pb.on { background:#14102A; border-color:#A080F0; color:#C0A8FF; } .pb:hover:not(.on) { background:#160C04; border-color:#6A4020; } .choice { background:#141008; border:2px solid #4A3018; color:#FFFFFF; padding:16px 18px; border-radius:6px; cursor:pointer; font-family:'Space Mono',monospace; font-size:20px; min-width:84px; transition:all 0.15s; } .choice:hover:not(:disabled) { background:#201408; border-color:#907040; } .choice:disabled { cursor:default; } .choice.ok { background:#0C2014; border-color:#4ADE80; color:#4ADE80 !important; } .choice.bad { background:#200C0C; border-color:#F87171; color:#F87171 !important; } .sub { background:#141008; border:2px solid #4A3018; color:#FFFFFF; padding:14px 34px; border-radius:6px; cursor:pointer; font-family:Georgia,serif; font-size:15px; transition:all 0.15s; } .sub:disabled { opacity:0.35; cursor:not-allowed; } .sub:hover:not(:disabled) { background:#201408; border-color:#907040; } .nxt { background:#201408; border:2px solid #806030; color:#FFFFFF; padding:14px 44px; border-radius:6px; cursor:pointer; font-family:Georgia,serif; font-size:16px; letter-spacing:0.04em; transition:all 0.2s; } .nxt:hover { background:#301C0A; border-color:#C09040; } .clr { padding:5px 12px; border-radius:4px; cursor:pointer; font-family:Georgia,serif; font-size:12px; border:1px solid #6A3810; background:transparent; color:#A06030; transition:all 0.15s; } .clr:hover { background:#1A0A04; border-color:#9A6030; } .flbl { font-size:11px; color:#FFFFFF; letter-spacing:0.1em; text-transform:uppercase; margin-bottom:8px; opacity:0.5; }\\\`}</style>

```

<h1 style={{ fontFamily:"'Playfair Display',Georgia,serif", fontSize:34, color:'#FFFFFF', marginBottom:6, letterSpacing:'0.02em' }}>
🎸 Guitar Flashcards
</h1>
<p style={{ color:'#FFFFFF', fontSize:15, fontStyle:'italic', marginBottom:24, opacity:0.6 }}>{filterLabel}</p>

{/* Stats */}

<div style={{ display:'flex', gap:36, marginBottom:24, fontFamily:"'Space Mono',monospace" }}>
{\\\[
{ v:\\\`${score.c}/${score.t}\\\`, l:'SCORE', c:'#4ADE80' },
{ v:\\\`${pct}%\\\`, l:'ACCURACY', c:'#F5C842' },
{ v:streak, l:'STREAK', c:'#FB923C' },
\\\].map(({ v,l,c }) => (
<div key={l} style={{ textAlign:'center' }}>
<div style={{ fontSize:28, color:c, fontWeight:'bold' }}>{v}</div>
<div style={{ fontSize:12, color:'#FFFFFF', letterSpacing:'0.1em', marginTop:3, opacity:0.4 }}>{l}</div>
</div>
))}
</div>

{/* Mode + String toggles */}

<div style={{ display:'flex', gap:8, marginBottom:20, flexWrap:'wrap', justifyContent:'center' }}>
<div style={{ display:'flex', gap:3, background:'#080401', padding:3, borderRadius:5 }}>
<button className={\\\`tog${mode==='fret-to-note'?' on':''}\\\`} onClick={() => setMode('fret-to-note')}>Fret → Note</button>
<button className={\\\`tog${mode==='note-to-fret'?' on':''}\\\`} onClick={() => setMode('note-to-fret')}>Note → Fret</button>
</div>
<div style={{ display:'flex', gap:3, background:'#080401', padding:3, borderRadius:5 }}>
<button className={\\\`tog${strSet==='all'?' on':''}\\\`} onClick={() => setStrSet('all')}>All Strings</button>
<button className={\\\`tog${strSet==='ea'?' on':''}\\\`} onClick={() => setStrSet('ea')}>E & A Only</button>
</div>
</div>

{/* Filter panel */}

<div style={{ width:'100%', maxWidth:SVG\\\_W+24, marginBottom:14, background:'#0A0603', border:'1.5px solid #1E0E04', borderRadius:8, padding:'14px 16px' }}>
<div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:10 }}>
<div className="flbl">Key</div>
{selKey && (
<button className="clr" onClick={() => { setSelKey(null); setSelScale(null); setSelPos('all'); }}>
✕ Clear filters
</button>
)}
</div>
<div style={{ display:'flex', gap:5, flexWrap:'wrap', marginBottom: selKey ? 16 : 0 }}>
{ALL\\\_KEYS.map(key => (
<button key={key} className={\\\`kb${selKey===key?' on':''}\\\`}
onClick={() => {
if (selKey === key) { setSelKey(null); setSelScale(null); setSelPos('all'); }
else { setSelKey(key); setSelScale(null); setSelPos('all'); }
}}>
{key}
</button>
))}
</div>
{selKey && (
<>
<div className="flbl">Scale</div>
<div style={{ display:'flex', gap:5, flexWrap:'wrap', marginBottom: selScale ? 16 : 0 }}>
{Object.keys(SCALES).map(scale => (
<button key={scale} className={\\\`sb${selScale===scale?' on':''}\\\`}
onClick={() => {
if (selScale === scale) { setSelScale(null); setSelPos('all'); }
else { setSelScale(scale); setSelPos('all'); }
}}>
{scale}
</button>
))}
</div>
</>
)}
{selKey && selScale && (
<>
<div className="flbl">Position</div>
<div style={{ display:'flex', gap:5, flexWrap:'wrap' }}>
{\\\[{ v:'all', l:'All' }, ...\\\[1,2,3,4,5\\\].map(n => ({ v:n, l:\\\`Pos ${n}\\\` }))\\\].map(({ v, l }) => (
<button key={v} className={\\\`pb${selPos===v?' on':''}\\\`} onClick={() => setSelPos(v)}>
{l}
</button>
))}
</div>
</>
)}
</div>

{/* Fretboard */}

<div style={{ width:'100%', maxWidth:SVG\\\_W+24, background:'#050301', border:'2px solid #1A0A03', borderRadius:8, padding:'14px 8px', marginBottom:22, overflowX:'auto', boxShadow:'0 8px 48px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,200,80,0.05)' }}>
{fretboard}
</div>

{/* Fret → Note */}
{mode === 'fret-to-note' && (

<div style={{ textAlign:'center', marginBottom:16 }}>
<p style={{ color:'#FFFFFF', fontSize:16, marginBottom:18, opacity:0.7 }}>
String <strong style={{ color:'#F5C842', opacity:1 }}>{STR\\\_LABEL\\\[card.str\\\]}</strong>
{' · '}Fret <strong style={{ color:'#F5C842', opacity:1 }}>{card.fret}</strong>
{' — what note is this?'}
</p>
<div style={{ display:'flex', gap:10, flexWrap:'wrap', justifyContent:'center' }}>
{choices.map(note => {
let cls = 'choice';
if (feedback) {
if (note === card.note) cls += ' ok';
else if (note === picked) cls += ' bad';
}
return (
<button key={note} className={cls} onClick={() => answerNote(note)} disabled={!!feedback}>
{note}
</button>
);
})}
</div>
</div>
)}

{/* Note → Fret */}
{mode === 'note-to-fret' && (

<div style={{ textAlign:'center', marginBottom:16 }}>
<div style={{ fontSize:96, fontFamily:"'Space Mono',monospace", fontWeight:'bold', color:'#F5C842', marginBottom:6, lineHeight:1, textShadow:'0 0 60px rgba(245,200,66,0.35)' }}>
{card.note}
</div>
<p style={{ color:'#FFFFFF', fontSize:16, marginBottom:16, opacity:0.6 }}>
{feedback
? feedback === 'correct'
? \\\`✓ Correct! All ${card.note} positions shown in green\\\`
: \\\`✗ All ${card.note} positions shown in green\\\`
: selPos !== 'all'
? \\\`Tap ${card.note} within the highlighted position\\\`
: \\\`Tap any ${card.note} on the neck, then submit\\\`
}
</p>
{!feedback && (
<button className="sub" onClick={submit} disabled={!selFret}>Submit Answer</button>
)}
</div>
)}

{/* Feedback */}
{feedback === 'correct' && mode === 'fret-to-note' && (

<div style={{ textAlign:'center', marginTop:8, fontSize:52, lineHeight:1 }}>👍</div>
)}
{feedback === 'correct' && mode === 'note-to-fret' && (
<div style={{ textAlign:'center', marginTop:8 }}>
<div style={{ fontSize:24, fontFamily:"'Playfair Display',Georgia,serif", color:'#4ADE80', marginBottom:18 }}>
{streak > 1 ? \\\`🔥 ${streak} in a row!\\\` : '👍 Correct!'}
</div>
<button className="nxt" onClick={deal}>Next Card →</button>
</div>
)}
{feedback === 'wrong' && (
<div style={{ textAlign:'center', marginTop:8 }}>
<div style={{ fontSize:24, fontFamily:"'Playfair Display',Georgia,serif", color:'#F87171', marginBottom:18 }}>
The note is {card.note}
</div>
<button className="nxt" onClick={deal}>Next Card →</button>
</div>
)}
</div>
\\\`\\\`\\\`

);
}

———————————-

New updated code

———————————-

import { useState, useEffect } from “react”;

const NOTES = [‘E’,‘F’,‘F#’,‘G’,‘G#’,‘A’,‘A#’,‘B’,‘C’,‘C#’,‘D’,‘D#’];
const OPEN_IDX = { 6:0, 5:5, 4:10, 3:3, 2:7, 1:0 };
const STR_LABEL = { 6:‘E’, 5:‘A’, 4:‘D’, 3:‘G’, 2:‘B’, 1:‘e’ };
const ALL_KEYS = [‘C’,‘C#’,‘D’,‘D#’,‘E’,‘F’,‘F#’,‘G’,‘G#’,‘A’,‘A#’,‘B’];
const SCALES = {
‘Major’: [0,2,4,5,7,9,11],
‘Minor’: [0,2,3,5,7,8,10],
‘Pent. Major’:[0,2,4,7,9],
‘Pent. Minor’:[0,3,5,7,10],
‘Blues’: [0,3,5,6,7,10],
};
const POS_OFFSETS = [0, 2, 5, 7, -3];

function noteAt(str, fret) {
return NOTES[(OPEN_IDX[str] + fret) % 12];
}
function shuffled(arr) {
const a = […arr];
for (let i = a.length - 1; i > 0; i–) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
function getPosRange(key, posNum) {
const rootFret = NOTES.indexOf(key);
let start = rootFret + POS_OFFSETS[posNum - 1];
if (start < 0) start += 12;
if (start > 12) start -= 12;
return [Math.max(0, start), Math.min(12, start + 4)];
}

const NUT_X = 72;
const FRET_W = 58;
const OPEN_W = 48;
const STR_GAP = 48;
const VPAD = 32;
const FB_TOP = 14;
const SVG_W = NUT_X + 12 * FRET_W + 12;

function cellX(fret) {
return fret === 0 ? NUT_X - OPEN_W / 2 : NUT_X + (fret - 0.5) * FRET_W;
}

export default function App() {
const [strSet, setStrSet] = useState(‘all’);
const [mode, setMode] = useState(‘fret-to-note’);
const [selKey, setSelKey] = useState(null);
const [selScale, setSelScale] = useState(null);
const [selPos, setSelPos] = useState(‘all’);
const [card, setCard] = useState(null);
const [choices, setChoices] = useState([]);
const [picked, setPicked] = useState(null);
const [selFret, setSelFret] = useState(null);
const [feedback, setFeedback] = useState(null);
const [score, setScore] = useState({ c: 0, t: 0 });
const [streak, setStreak] = useState(0);

// low E (6) at top, high e (1) at bottom — enumerate high→low, invert y
const strs = strSet === ‘ea’ ? [5, 6] : [1, 2, 3, 4, 5, 6];
const svgH = VPAD + (strs.length - 1) * STR_GAP + VPAD;
const fbH = svgH - 2 * FB_TOP;

const scaleNoteSet = selKey && selScale
? new Set(SCALES[selScale].map(i => NOTES[(NOTES.indexOf(selKey) + i) % 12]))
: null;
const fretRange = selKey && selScale && selPos !== ‘all’
? getPosRange(selKey, selPos)
: [0, 12];
const [fMin, fMax] = fretRange;

function strY(si) { return VPAD + (strs.length - 1 - si) * STR_GAP; }

function deal() {
const candidates = [];
for (const str of strs) {
for (let fret = fMin; fret <= fMax; fret++) {
const note = noteAt(str, fret);
if (!scaleNoteSet || scaleNoteSet.has(note)) {
candidates.push({ str, fret, note });
}
}
}
if (!candidates.length) return;
const { str, fret, note } = candidates[Math.floor(Math.random() * candidates.length)];
setCard({ str, fret, note });
setPicked(null);
setSelFret(null);
setFeedback(null);
if (mode === ‘fret-to-note’) {
const pool = scaleNoteSet
? […scaleNoteSet].filter(n => n !== note)
: NOTES.filter(n => n !== note);
setChoices(shuffled([note, …shuffled(pool).slice(0, 3)]));
}
}

useEffect(() => { deal(); }, [mode, strSet, selKey, selScale, selPos]);

function handleResult(ok) {
setFeedback(ok ? ‘correct’ : ‘wrong’);
setScore(s => ({ c: s.c + (ok ? 1 : 0), t: s.t + 1 }));
setStreak(s => ok ? s + 1 : 0);
if (ok && mode === ‘fret-to-note’) setTimeout(() => deal(), 900);
}

function answerNote(note) {
if (feedback) return;
setPicked(note);
handleResult(note === card.note);
}

function submit() {
if (!selFret || feedback) return;
handleResult(noteAt(selFret.str, selFret.fret) === card.note);
}

function dotAt(si, fret) {
if (!card) return null;
const str = strs[si];
const n = noteAt(str, fret);
const inRange = fret >= fMin && fret <= fMax;
const inScale = !scaleNoteSet || scaleNoteSet.has(n);
if (mode === ‘fret-to-note’) {
if (str === card.str && fret === card.fret) {
if (!feedback) return { fill: ‘#F5C842’, label: null };
return { fill: feedback === ‘correct’ ? ‘#4ADE80’ : ‘#F87171’, label: card.note };
}
} else {
const isCorrect = n === card.note && inRange && inScale;
const isSel = selFret && str === selFret.str && fret === selFret.fret;
if (feedback) {
if (isCorrect) return { fill: ‘#4ADE80’, label: card.note };
if (isSel && !isCorrect) return { fill: ‘#F87171’, label: n };
} else if (isSel) {
return { fill: ‘#F5C842’, label: null };
}
}
return null;
}

const pct = score.t > 0 ? Math.round(score.c / score.t * 100) : 0;
if (!card || !strs.includes(card.str)) return null;

const hiX1 = fMin === 0 ? NUT_X - OPEN_W : NUT_X + (fMin - 1) * FRET_W;
const hiX2 = NUT_X + fMax * FRET_W;

const fretboard = (
<svg width={SVG_W} height={svgH} viewBox={`0 0 ${SVG_W} ${svgH}`}
style={{ maxWidth: ‘100%’, display: ‘block’, margin: ‘0 auto’ }}>
<defs>
<linearGradient id="wood" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#3C1808" />
<stop offset="100%" stopColor="#200B03" />
</linearGradient>
<linearGradient id="hs" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#16080300" />
<stop offset="100%" stopColor="#160803" />
</linearGradient>
</defs>
<rect x={0} y={FB_TOP} width={NUT_X - 3} height={fbH} fill=“url(#hs)” />
<rect x={NUT_X - 3} y={FB_TOP} width={SVG_W - NUT_X + 3 - 8} height={fbH} fill=“url(#wood)” />
{scaleNoteSet && selPos !== ‘all’ && (
<rect x={hiX1} y={FB_TOP} width={hiX2 - hiX1} height={fbH}
fill=“rgba(245,200,66,0.12)” stroke=“rgba(245,200,66,0.3)” strokeWidth={1.5} rx={2} />
)}
{[3,5,7,9,12].flatMap(f => {
const cx = NUT_X + (f - 0.5) * FRET_W;
if (f === 12 && strs.length > 2)
return [1,2].map(i => <circle key={`inlay-12-${i}`} cx={cx} cy={strY(i)} r={5} fill=”#3A1808” />);
return [<circle key={`inlay-${f}`} cx={cx} cy={svgH / 2} r={5} fill=”#3A1808” />];
})}
{strs.map((str, si) => (
<line key={str} x1={10} y1={strY(si)} x2={SVG_W - 8} y2={strY(si)}
stroke=”#C8A060”
strokeWidth={str===6?2.8:str===5?2.3:str===4?1.9:str===3?1.6:str===2?1.2:0.9}
opacity={0.72} />
))}
<rect x={NUT_X - 5} y={FB_TOP} width={9} height={fbH} fill=”#DCC880” rx={1.5} />
{Array.from({ length: 12 }, (*, i) => i + 1).map(f => (
<rect key={f} x={NUT_X + f * FRET_W - 2.5} y={FB_TOP} width={5} height={fbH} fill=”#907040” rx={1} />
))}
{strs.map((str, si) => (
<text key={str} x={18} y={strY(si) + 6} fill=”#FFFFFF” fontSize={14}
textAnchor=“middle” fontFamily=“Georgia,serif” fontWeight=“bold”>
{STR_LABEL[str]}
</text>
))}
{[0,3,5,7,9,12].map(f => (
<text key={f} x={cellX(f)} y={svgH - 6} fill=”#FFFFFF” fontSize={12}
textAnchor=“middle” fontFamily=“monospace” fontWeight=“bold”>
{f}
</text>
))}
{mode === ‘note-to-fret’ && !feedback && strs.map((str, si) =>
Array.from({ length: fMax - fMin + 1 }, (*, i) => {
const fret = fMin + i;
const n = noteAt(str, fret);
if (scaleNoteSet && !scaleNoteSet.has(n)) return null;
const rx = fret === 0 ? NUT_X - OPEN_W : NUT_X + (fret - 1) * FRET_W;
return (
<rect key={`hit-${str}-${fret}`}
x={rx} y={strY(si) - STR_GAP / 2}
width={fret === 0 ? OPEN_W : FRET_W} height={STR_GAP}
fill=“transparent” style={{ cursor: ‘pointer’ }}
onClick={() => setSelFret({ str, fret })} />
);
})
)}
{strs.map((str, si) =>
Array.from({ length: 13 }, (_, fret) => {
const d = dotAt(si, fret);
if (!d) return null;
const cx = cellX(fret), cy = strY(si);
return (
<g key={`dot-${str}-${fret}`}>
<circle cx={cx} cy={cy} r={15} fill={d.fill} stroke="#080402" strokeWidth={2.5} />
{d.label && (
<text x={cx} y={cy + 5} textAnchor=“middle” fill=”#080402”
fontSize={12} fontWeight=“bold” fontFamily=“monospace”>
{d.label}
</text>
)}
</g>
);
})
)}
</svg>
);

const filterLabel = selKey && selScale
? `${selKey} ${selScale}${selPos !== 'all' ? ` · Position ${selPos}` : ''}`
: ‘Learn the fretboard, one note at a time’;

return (
<div style={{
minHeight: ‘100vh’,
background: ‘linear-gradient(170deg, #060402 0%, #0F0603 60%, #060402 100%)’,
color: ‘#FFFFFF’,
fontFamily: ‘Georgia, serif’,
display: ‘flex’, flexDirection: ‘column’, alignItems: ‘center’,
padding: ‘20px 12px 48px’,
}}>
<style>{`@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Space+Mono:wght@400;700&display=swap'); * { box-sizing: border-box; margin: 0; padding: 0; } .tog { padding:10px 18px; border-radius:4px; cursor:pointer; font-family:Georgia,serif; font-size:14px; border:1.5px solid #3A1E08; background:transparent; color:#A07040; transition:all 0.15s; } .tog.on { background:#2E1A08; border-color:#C08030; color:#F0C060; font-weight:bold; } .tog:hover:not(.on) { border-color:#5A3010; color:#C09050; } .kb { padding:9px 8px; border-radius:5px; cursor:pointer; min-width:50px; font-family:'Space Mono',monospace; font-size:14px; border:1.5px solid #3A1E08; background:#0C0804; color:#C08040; transition:all 0.15s; } .kb.on { background:#3A1C08; border-color:#F5C842; color:#F5C842; } .kb:hover:not(.on) { background:#160C04; border-color:#6A4020; } .sb { padding:9px 14px; border-radius:5px; cursor:pointer; font-family:Georgia,serif; font-size:13px; border:1.5px solid #3A1E08; background:#0C0804; color:#C08040; transition:all 0.15s; } .sb.on { background:#0A2814; border-color:#4ADE80; color:#4ADE80; } .sb:hover:not(.on) { background:#160C04; border-color:#6A4020; } .pb { padding:9px 14px; border-radius:5px; cursor:pointer; font-family:Georgia,serif; font-size:13px; border:1.5px solid #3A1E08; background:#0C0804; color:#C08040; transition:all 0.15s; } .pb.on { background:#14102A; border-color:#A080F0; color:#C0A8FF; } .pb:hover:not(.on) { background:#160C04; border-color:#6A4020; } .choice { background:#141008; border:2px solid #4A3018; color:#FFFFFF; padding:16px 18px; border-radius:6px; cursor:pointer; font-family:'Space Mono',monospace; font-size:20px; min-width:84px; transition:all 0.15s; } .choice:hover:not(:disabled) { background:#201408; border-color:#907040; } .choice:disabled { cursor:default; } .choice.ok { background:#0C2014; border-color:#4ADE80; color:#4ADE80 !important; } .choice.bad { background:#200C0C; border-color:#F87171; color:#F87171 !important; } .sub { background:#141008; border:2px solid #4A3018; color:#FFFFFF; padding:14px 34px; border-radius:6px; cursor:pointer; font-family:Georgia,serif; font-size:15px; transition:all 0.15s; } .sub:disabled { opacity:0.35; cursor:not-allowed; } .sub:hover:not(:disabled) { background:#201408; border-color:#907040; } .nxt { background:#201408; border:2px solid #806030; color:#FFFFFF; padding:14px 44px; border-radius:6px; cursor:pointer; font-family:Georgia,serif; font-size:16px; letter-spacing:0.04em; transition:all 0.2s; } .nxt:hover { background:#301C0A; border-color:#C09040; } .clr { padding:5px 12px; border-radius:4px; cursor:pointer; font-family:Georgia,serif; font-size:12px; border:1px solid #6A3810; background:transparent; color:#A06030; transition:all 0.15s; } .clr:hover { background:#1A0A04; border-color:#9A6030; } .flbl { font-size:11px; color:#FFFFFF; letter-spacing:0.1em; text-transform:uppercase; margin-bottom:8px; opacity:0.5; }`}</style>

```
<h1 style={{ fontFamily:"'Playfair Display',Georgia,serif", fontSize:34, color:'#FFFFFF', marginBottom:6, letterSpacing:'0.02em' }}>
** **🎸 Guitar Flashcards
</h1>
<p style={{ color:'#FFFFFF', fontSize:15, fontStyle:'italic', marginBottom:24, opacity:0.6 }}>{filterLabel}</p>

{/* Stats */}
<div style={{ display:'flex', gap:36, marginBottom:24, fontFamily:"'Space Mono',monospace" }}>
{[
{ v:`${score.c}/${score.t}`, l:'SCORE', c:'#4ADE80' },
{ v:`${pct}%`, l:'ACCURACY', c:'#F5C842' },
{ v:streak, l:'STREAK', c:'#FB923C' },
].map(({ v,l,c }) => (
<div key={l} style={{ textAlign:'center' }}>
<div style={{ fontSize:28, color:c, fontWeight:'bold' }}>{v}</div>
<div style={{ fontSize:12, color:'#FFFFFF', letterSpacing:'0.1em', marginTop:3, opacity:0.4 }}>{l}</div>
</div>
))}
</div>

{/* Mode + String toggles */}
<div style={{ display:'flex', gap:8, marginBottom:20, flexWrap:'wrap', justifyContent:'center' }}>
<div style={{ display:'flex', gap:3, background:'#080401', padding:3, borderRadius:5 }}>
<button className={`tog${mode==='fret-to-note'?' on':''}`} onClick={() => setMode('fret-to-note')}>Fret → Note</button>
<button className={`tog${mode==='note-to-fret'?' on':''}`} onClick={() => setMode('note-to-fret')}>Note → Fret</button>
</div>
<div style={{ display:'flex', gap:3, background:'#080401', padding:3, borderRadius:5 }}>
<button className={`tog${strSet==='all'?' on':''}`} onClick={() => setStrSet('all')}>All Strings</button>
<button className={`tog${strSet==='ea'?' on':''}`} onClick={() => setStrSet('ea')}>E & A Only</button>
</div>
</div>

{/* Filter panel */}
<div style={{ width:'100%', maxWidth:SVG_W+24, marginBottom:14, background:'#0A0603', border:'1.5px solid #1E0E04', borderRadius:8, padding:'14px 16px' }}>
<div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:10 }}>
<div className="flbl">Key</div>
{selKey && (
<button className="clr" onClick={() => { setSelKey(null); setSelScale(null); setSelPos('all'); }}>
** **✕ Clear filters
</button>
)}
</div>
<div style={{ display:'flex', gap:5, flexWrap:'wrap', marginBottom: selKey ? 16 : 0 }}>
{ALL_KEYS.map(key => (
<button key={key} className={`kb${selKey===key?' on':''}`}
onClick={() => {
if (selKey === key) { setSelKey(null); setSelScale(null); setSelPos('all'); }
else { setSelKey(key); setSelScale(null); setSelPos('all'); }
}}>
{key}
</button>
))}
</div>
{selKey && (
<>
<div className="flbl">Scale</div>
<div style={{ display:'flex', gap:5, flexWrap:'wrap', marginBottom: selScale ? 16 : 0 }}>
{Object.keys(SCALES).map(scale => (
<button key={scale} className={`sb${selScale===scale?' on':''}`}
onClick={() => {
if (selScale === scale) { setSelScale(null); setSelPos('all'); }
else { setSelScale(scale); setSelPos('all'); }
}}>
{scale}
</button>
))}
</div>
</>
)}
{selKey && selScale && (
<>
<div className="flbl">Position</div>
<div style={{ display:'flex', gap:5, flexWrap:'wrap' }}>
{[{ v:'all', l:'All' }, ...[1,2,3,4,5].map(n => ({ v:n, l:`Pos ${n}` }))].map(({ v, l }) => (
<button key={v} className={`pb${selPos===v?' on':''}`} onClick={() => setSelPos(v)}>
{l}
</button>
))}
</div>
</>
)}
</div>

{/* Fretboard */}
<div style={{ width:'100%', maxWidth:SVG_W+24, background:'#050301', border:'2px solid #1A0A03', borderRadius:8, padding:'14px 8px', marginBottom:22, overflowX:'auto', boxShadow:'0 8px 48px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,200,80,0.05)' }}>
{fretboard}
</div>

{/* Fret → Note */}
{mode === 'fret-to-note' && (
<div style={{ textAlign:'center', marginBottom:16 }}>
<p style={{ color:'#FFFFFF', fontSize:16, marginBottom:18, opacity:0.7 }}>
String <strong style={{ color:'#F5C842', opacity:1 }}>{STR_LABEL[card.str]}</strong>
{' · '}Fret <strong style={{ color:'#F5C842', opacity:1 }}>{card.fret}</strong>
{' — what note is this?'}
</p>
<div style={{ display:'flex', gap:10, flexWrap:'wrap', justifyContent:'center' }}>
{choices.map(note => {
let cls = 'choice';
if (feedback) {
if (note === card.note) cls += ' ok';
else if (note === picked) cls += ' bad';
}
return (
<button key={note} className={cls} onClick={() => answerNote(note)} disabled={!!feedback}>
{note}
</button>
);
})}
</div>
</div>
)}

{/* Note → Fret */}
{mode === 'note-to-fret' && (
<div style={{ textAlign:'center', marginBottom:16 }}>
<div style={{ fontSize:96, fontFamily:"'Space Mono',monospace", fontWeight:'bold', color:'#F5C842', marginBottom:6, lineHeight:1, textShadow:'0 0 60px rgba(245,200,66,0.35)' }}>
{card.note}
</div>
<p style={{ color:'#FFFFFF', fontSize:16, marginBottom:16, opacity:0.6 }}>
{feedback
? feedback === 'correct'
? `✓ Correct! All ${card.note} positions shown in green`
: `✗ All ${card.note} positions shown in green`
: selPos !== 'all'
? `Tap ${card.note} within the highlighted position`
: `Tap any ${card.note} on the neck, then submit`
}
</p>
{!feedback && (
<button className="sub" onClick={submit} disabled={!selFret}>Submit Answer</button>
)}
</div>
)}

{/* Feedback */}
{feedback === 'correct' && mode === 'fret-to-note' && (
<div style={{ textAlign:'center', marginTop:8, fontSize:52, lineHeight:1 }}>👍**</div>**
)}
{feedback === 'correct' && mode === 'note-to-fret' && (
<div style={{ textAlign:'center', marginTop:8 }}>
<div style={{ fontSize:24, fontFamily:"'Playfair Display',Georgia,serif", color:'#4ADE80', marginBottom:18 }}>
{streak > 1 ? `🔥 ${streak} in a row!` : '👍 Correct!'}
</div>
<button className="nxt" onClick={deal}>Next Card →</button>
</div>
)}
{feedback === 'wrong' && (
<div style={{ textAlign:'center', marginTop:8 }}>
<div style={{ fontSize:24, fontFamily:"'Playfair Display',Georgia,serif", color:'#F87171', marginBottom:18 }}>
The note is {card.note}
</div>
<button className="nxt" onClick={deal}>Next Card →</button>
</div>
)}
</div>
```

);
}

reddit.com
u/Unfortunate_Harvard — 8 days ago

We have a black and an orange cat who have been super duper bonded since they were very small.

He had to go to the vet the other day and get some teeth pulled. Since then she wants to be near him, but hisses and grumbles at him. This clearly upsets him because he wants to be near her too.

He does everything he can. Lays on his back, shows his belly, turns away gives her space. He is not aggressive in any way.

We have tried:

Pheromones
Rubbing scented items in them both
Separating them
Cat nip
Putting them back together

He’s 24 hours after medication and it seems to keep going. He was on cat ibuprofen.

She hasn’t swiped at him, or anything violent it would be funny it it wasn’t so sad she misses him, and then goes to find him, only to smell him, and grumble and hiss at him.

Anything else we should do?

reddit.com
u/Unfortunate_Harvard — 19 days ago
▲ 120 r/cutecats

My wife and I are pretty sure our cat is the spirit animal to WWE’s Dan Hausen. Thoughts?

“Very nice, very evil.”

u/Unfortunate_Harvard — 22 days ago

Hi!

I'm UnfortunateHarvard (in Troy McClure voice), you may remember from posts such as:

"No, That's Not How Hollywood Works,"

"AITA For Telling My Therapist John Cena Was Working Babyface But Clearly Had Heel Energy"

"My Wife Keeps Calling Spock Overrated And I Need To Know If This Is A Dealbreaker"

And "20 Years In Poly, What No One Ever Told Me' and the comment section argument where I genuinely tried to explain empathy to someone called Alphamale251!" (CHEAP PLUG!)

I wanted to write today about what I see as the dangers of poly bashing. Not only is it pretty explicitly against the rules of r/monogamy, it's also dangerous, and most importantly wildly ineffective!

Section 1: What the FUCK am I talking about?

To catch you up so you don't have to read my prior post. There is no scientific basis for Polyamory or ENM as anything that is naturally occurring, there is actually a ton of evidence to the contrary. What there is evidence of is that poly is really a sort of pseudo coping mechanism for desires the person finds shameful, and is then used to remove responsibility from the person acting out those desires. "It's not me, it's genetic!"

Let's start as I try to always with Empathy.

LOTS OF PEOPLE LEAVE POLY RELATIONSHIPS HURT. REALLY HURT. And when you are hurt it is one of the most natural and sometimes healthy responses to want to hurt the person who hurt you. It is not a healthy thing to act on it, but more on that later. But the feeling is fine.

I think so far I've seen two very distinct separate camps of poly bashers.

Camp 1: The Hurt People Hurt People

I think this is probably the larger of the two camps, and it's the one I have the most empathy for. I've been there, we all have. They hurt you, and you want to yell at them "fuck you, and your friends!" I think that's totally fine, and if coming here helps that person get out of that camp and into the camp of Helped People Help People, then I'm here for it! But just be aware at some point you have to let that go. (More on that below)

Camp 2: The Justification Camp

This is a super interesting thing, and I can't tell if it's a group that just exists on the internet and legitimately thinks everyone was born yesterday?

They tend to come in a few varieties:

  1. The person who hates poly people and will comment only on posts on the Reddit that are about poly people.
  2. The person who wants to equate polyamory or ENM as an immoral behavior, or some sort of genetic anomaly.
  3. Jerks.

Let's start with the first group of camp 2. If you are on this Reddit as much as I am, you see them. You can actually see it on my post in one of the first comments. Simply put, these folks in my mind have unresolved trauma; the word poly, ENM, Swinger, any of those words just trigger the hell out of them.

The second is much more insidious. The problem with that as a belief is that it assumes that morals are a thing that can be measured (they can't; only ethics can be measured), and that they believe themselves in a position to judge others. The genetic anomaly portion is interesting, as believing this legitimizes the very thing they are sitting in judgment over. And thus, it becomes a self-fulfilling prophecy. The person is afraid of something, creates what sounds like a reasonable explanation, then they have a defensible position to be crappy to other people. The problem with that legitimization is historically those arguments hand in hand have a lot of bad history.

"Sure being gay is a genetic thing, I just still think it's a sin." Anyone alive in the early 2000s remembers that.

And the last, well that's the most obvious. It seems that the rage of these people is always directed at women, that any woman who has a "higher body count" is irredeemable. The problem is that kind of thinking is just good old fashioned sexism, and they always seem to have screen names (THESE ARE NOT REAL BUT EXAMPLES… OR, GOD I HOPE THEY AREN'T REAL) like "Makehercrawl4it" or "Alphamale251" or "MisoJohn1st" and a quick breeze through their comment history shows you that they direct this ire only at women, and that anything that happened to a woman in a relationship is judged as deserved or undeserved based on her "body count." That is to say women are sex objects to them, and their value is only in the purity of those objects. In short… jerks.

Oh, and the other thing about these guys: they don't want to learn; their opinion is fact to them, and facts that don't match their opinion lead to the tired refrain of "I stand by my statement" because they don't want in good faith to learn anything. They are the experts in all things, and thus don't wish to be bothered with empathy, humanity, etc.

This is a value in my mind that is antithetical to healthy monogamy. When my wife says something, as a healthy relationship I'm kinda required to at least consider it.

Additionally, an interesting trend I've seen on this Reddit. The more those comments are on there with a female poster, the faster that post gets deleted. In short, I believe they actually shamed that person out of the conversation here.

Section 2: Why is Polybashing Dangerous?

Look, I don't need to moralize to you, or teach you ethics. Open any history book, for any country in the world, and you can see that othering doesn't work and never creates anything positive. It does create a lot of bad behaviors in the people doing the othering.

Enough said.

Let's get to something that I think is more a topic of discussion that I would love some community input on.

Why is it ineffective? What do you think? What could we do as a community to better invite poly people back to being monogamous?

In my mind there are three specific thrusts. Pun maybe intended?

Point 1: It doesn't deter behavior.

Point 2: It actually lends credibility to poly and ENM talking points.

Point 3: It actually makes it less likely for someone to come back to being monogamous.

Let's take some examples pulled from this Reddit and apply each point:

Point 1 - Example:

Person who is in a relationship that is now open. They felt pressured by their partner to enter into this behavior, and they are having regrets.

Group one's response: "I went through this too, they are the most evil, scummy people on earth!"

Result… You just insulted their partner who they clearly love, and may want to love in the future. Not a great way to get people to change things.

Group two's response: "Well, I think it's a sin to do it, and against God's wishes. I would never have anything to do with those people; once you've been tainted you can't come back!"

Result… You just wrote them off as a person. Anything you say after that is just suspect, and going to reinforce the poly talking point that all monogamous people are about is controlling people.

Group Three's response:

"Oh man, good luck finding a husband after that, your body count is so high that most people won't even want to know you, because everyone knows poly women can never change."

Result… you managed to do the trifecta; you insulted them, moralized at them, and objectified them all at the same time.

Point 2 - Example:

Person's partner is talking about experimenting.

Group one's response: "Dump him, poly and ENM people just want to brainwash you and use you."

Result: You have no idea who that person is. Some people are into being controlled; you might have just sold them on that. I'm not joking. Additionally, you have no idea how long they've been together, and people get scared to start over. I'm 44; it was hella scary to start over 6 years ago. This is the equivalent of people screaming at each other online about politics. Dude, you aren't even talking to them, you are talking to your phone about them.

Group two's response:

"Well, you should put your foot down; once you enter moral gray areas, you basically never come back."

Result: This again isn't a deterrent. Almost anything in life besides certain criminal behavior can be walked back. Most people know this, and it comes off, actually oddly, as more of group one's response was, but inverted. You just come off as someone who wants to control people.

Group three's response:

"I wouldn't; once you do that, men won't want to date you after. Your body count is too high, you will be used up." (I'm not joking, I've seen that response.)

Result: You just projected… You projected all over reality, and all over that person. Shame never stopped anyone from doing things since the internet was invented; we are a shameless society. All the shame, and none of the concerns. Great taste, less filling.

Point 3 - Example:

Person posts that they've been poly for several years, it isn't working the way they hoped, and they're starting to wonder if monogamy might actually be what they want. They're vulnerable. They're questioning. They are literally standing in the doorway.

Group one's response: "Finally you woke up! Those people are predators and you were their victim; you should be furious!"

Result: This person didn't come here to be told they were a victim. They came here to think out loud. You just handed them an identity they didn't ask for, and now their next post is back on r/polyamory explaining why monogamous people are judgmental and cruel. Door closed. You closed it.

Group two's response: "Once you've lived that lifestyle it's very hard to come back; you've essentially rewired your brain, and most monogamous people won't want someone with that history."

Result: You just told someone standing at the exit that the exit might not actually be an exit. Congratulations, you just made monogamy sound like a club with a velvet rope they probably can't get past. Why would they keep walking toward that?

Group three's response: "Wow, took you long enough. Good luck finding a real man after all that."

Result: They closed the tab. They're gone. You didn't lose the argument; you forfeited before it started.

Personal Anecdote:

What actually got me to leave being poly:

As I've mentioned in my prior post, self-examination brought me there. But it was through a conversation that involved curiosity, not judgment. It was someone asking me over and over why I believed something, and then introducing new verifiable facts, be they about the human condition or about my relationships.

The five most magic words when someone says "I'm Poly, but… I'm not real happy" or "I'm not poly, and my partner is doing something I'm unsure about" are not "DO WHAT YOU'RE TOLD!" They're… "Tell me more about that?"

Even if they've written a lot there is always more to the story, and you have valuable insight because you are outside. You can always see things from outside that you can't from inside those situations. By asking, you lead the person to draw their own conclusions, that are in line with reality vs. forcing, shaming, and objectifying. So treat that space like a responsible person and try to use it for the greater good. You never know, you could be the person who empowers that person to a better life.

You never know whose life you can change for the better by just being curious.

A Note 1: THE URGE TO FIGHT FIRE WITH FIRE!

One of the first things I learned about public safety — mind you I learned it when I was about 15 — was watching a grown adult, someone who for sure knew better, throw bacon fat on a fire. The resulting fireball luckily injured no one, but was an important literal and allegorical lesson. Don't throw flammable liquid at an open flame.

I think it's fair to say many people here would consider the ENM community as an open dumpster fire. A charge hard to refute… though the concern for me is the language of absolutism, anti-sex, anti-woman, and dehumanization of people in that fire. Which I think, unbeknownst to those people, isn't fighting the fire they think, but throwing gas on it. It makes it easier for Polyamory to attack our position, and certainly gives credence to the idea that monogamy is a system of control.

To anyone inside the poly community who thinks that… and thinks some of those comments are actually made by Incels…. Well... They are… BUT! If you think that's something relegated to simply the Monogamous community, I have some bad news (Wade Barrett voice) — those same beliefs permeate the poly community as well; they just hid it as a type of kink.

Note 2: ANOTHER THOUGHT ON KINK:

It is interesting to me, the rise of antifeminism as a kink. Taking my own advice of "the internet is not a real place," I am unsure how much of a real thing this is, but there are thousands of communities that seem like they are populated with the most awful misogynists, people who you would think would be pretty anti-ENM, and yet… There seems to be a non-zero amount of overlap.

I think more than anything here, I would say that my concern for people in those spaces is going to be that they understand both this type of sexual politicization and ENM are just as extreme as anti-sex, Incels, etc. are. If it looks like a duck, walks like a duck, it's probably not a cheeseburger.

It's a great example of people trying to show themselves as apart from something while engaging in it. I'm not even sure hypocrisy is the right word.

Section 3: So… why does this matter?

I'll just be blunt… In the war of ideas, monogamy is not winning it seems. Not that the fight against human complication can be "won," but we certainly aren't the favored style for young people to talk about.

Why is that?

Maybe humans only learn the hard way. Maybe access to bad ideas is just easier. I found myself reflecting though, as my journey started long before the internet had its current form.

At my most hardcore point of being poly, I held easily more extreme views than are on display in some of these forums. But I also wasn't even 28 yet. As a male, my brain wasn't even done growing. Why was that?

I've written about how I think my parents, who were quite a bit older than most parents, struggled to keep up with a world that was changing underneath them, and instead of validating, opted for control.

In many ways I have realized this likely created a great deal of anger. Now outside of polyamory many years, and happily monogamous, I found myself realizing when I talk to an actual poly person they are often… very angry people. Hurt as well…

As I was writing this I was searching for an allegory, something to use as a framework for a suggestion of how to talk with a poly person you are seeking to help understand that they aren't as enlightened and happy as they think, deprogram, for lack of a better word, and I was reading a book about Schizophrenia in family units (yes I know I have way WAY too much time on my hands.)

There was a whole section in the book that talked about how to have a conversation with someone who is delusional and experiencing hallucinations. The book highlighted the danger of treating the hallucinations like they aren't real to the person having them, because to that person, they ARE REAL. But you also cannot validate what does not exist, because as the party most healthy in that equation, you need to keep one foot on the ground, so to speak. And to clarify, I am in no way making the claim that ENM is a mental illness. I think the style of communication used to de-escalate a situation and help someone help themselves is probably a really effective tool to use with people seeking help!

"Validate what you can, never validate what is invalid."

Let's try this out with some poly concepts:

  1. "Humans like group sex."

This is true; the most common fantasy is group sex. But liking something and doing something all the time aren't the same. Humans like alcohol — what do we call someone who has to go to the bar every single day and get blackout drunk?

  1. "I can love more than one person."

You can; it's possible and history is replete with examples of this. But those stories are tragedies in the Shakespearean sense that the only people who don't know that this will end poorly are the people in them. Everyone outside knows that it's a car crash.

To quote Star Trek: "I knew Brutus was going to kill Caesar in the first act; but Caesar didn't figure it out until the knife was in his back."

Is that what you want for yourself?

  1. "Humans are tribal."

Yes, for hundreds of thousands of years they were, before recorded history. But if you truly believe that, give me your phone, your car, your computer, your digital cameras, etc., because if you believe that only things that could have been done since the dawn of time are valid, none of those existed. Do you really want to live in a world like that?

Notice how none of these directly attack the speaker, nor do they validate the invalid. I think this is a powerful framework that can help us all here on this Reddit when we deal with people coming here seeking understanding. Sure the "dump them" response that comes sailing in first always gets the likes, but if the number of posts that are deleted by the poster are any indication, I'd say that the shame, "dump them," anti-sex responses are actually not helping convince anyone.

As a final note I wanted to speak directly to people who DO hold the belief that a woman's worth is only in how sexually pure she is, and that her body count matters. These are beliefs and thoughts held by the manosphere, for those who don't know, feel free to look that up.

An interesting factoid: humans protect their pain. We often hold it like it's part of us. We do it physically , ever seen someone get punched in the stomach? They literally bend over and clutch the place they were hit. Evolutionarily this is a great example, because once in a ball on the ground while you are protecting the injured area, you are totally open to attack and vulnerable.

This isn't that dissimilar to what happens when someone gets hurt emotionally. I've seen people on here who define themselves clearly not by who they are, not what they do, not their passions, but their pain from being with someone in the ENM community. When that incident occurs, it's understandable, but I've seen people say "5 years ago I went on a date with…" and they are still taking the time to write about those people.

Not saying their experience is invalid, because it's totally valid, but I'd argue there is more to life than that, and if that keeps you from finding love, or gives you all this time and energy to make comment after comment about it, I'd argue that you gave the game up.

Ladies and gents, if ENM has cult-like beliefs, I gotta tell you, so is the camp of letting your pain define who you are that you are in. People have loved sex, been having it, for better or worse since the beginning of time. They will continue to do so. The ENM partners or people you encountered who hurt you were just as misguided and hurt as you are.

And it's valid to be angry with people who hurt you. Those people should know better , they should. But "should" is a dangerous word. And if your goal is to do more than come on here and bash on ENM people, and you want to find love in your life, it's going to require you to do something VERY HARD… You will need to humanize the people you are angry at. Notice I didn't say forgive them, or not hold them to account , humanize them. They are behaving in error, and they are hurting people, but they may not believe that they are because their fear and hurt blinds them. If you want a better world, and to really undo that pain and anger you carry around, you are going to have to let it go.

As someone very wise once said: "you cannot change the world with your fists."

Because without that, it will take you much longer to find the love you so richly deserve. And as a community, we can not define ourselves as anti something else. Because we miss all the most awesome parts of our culture, our relationship contained.

Examples:

I wake up every morning, and I make my wife coffee. I promised this to her on our first date, and I've done it every day since. I only make ONE cup of coffee for someone. I don't have to run a fucking Starbucks.

When I want time to myself to play guitar, read, write long reddit posts that will likely upset someone, because I have only one partner, I don't have to throw it on a scheduling app.

Never again do I have to sit in a STD testing clinic and wonder if one of my many partners is lying to me. Cause, my wife and I value far more our relationship than any wild fantasy that porn or romance novels told us we should have... Except tentacles... J/K... (Squidward runs away.)

So, the question I pose to the community is… What do we want? How do we want to be perceived? Because we critique poly people for not policing their environments and communicating how they do, how do we want to police our community? And make sure its healthy?

Call me an optimist, but I think monogamy is due for a comeback. And I hope it starts with us!

See you on the next essay!

reddit.com
u/Unfortunate_Harvard — 26 days ago