Skip to content
LAM
Read Home Blog
Make Projects HTML Tools Games
Touch grass Notes Resume Links
Home Blog HTML Projects
Tools Games Notes Resume Links
Back MAT 243 — Discrete Mathematical Structures Math
Download Open
Show description 2,401 chars · Math

MAT 243 — Discrete Mathematical Structures

MAT 243 — Discrete Mathematical Structures

MAT 243

Logic
Proofs
Sets
Functions
Big-O
Number Theory
Induction
Counting
Graphs
Formulas

ASU · Discrete Mathematical Structures

DISCRETEMATHSTRUCTURES

An interactive reference covering logic, proofs, sets, functions, number theory, induction, combinatorics, and graph theory — every formula, concept, and technique you need.

Propositional Logic
Proof Techniques
Set Theory
Big-O Notation
Modular Arithmetic
Mathematical Induction
Combinatorics
Graph Theory

01

PROPOSITIONAL LOGIC

Logical Operators

¬p

Negation

Reverses truth value. If p is T, ¬p is F.

T→F, F→T

p ∧ q

Conjunction (AND)

True only when BOTH p and q are true.

T∧T=T, all others=F

p ∨ q

Disjunction (OR)

True when AT LEAST ONE of p, q is true.

F∨F=F, all others=T

p ⊕ q

Exclusive OR

True when EXACTLY ONE of p, q is true — not both.

T⊕T=F, T⊕F=T, F⊕T=T, F⊕F=F

p → q

Implication (IF-THEN)

FALSE only when p is TRUE and q is FALSE. The most critical operator.

T→F=F, all others=T

p ↔ q

Biconditional (IFF)

True when p and q have IDENTICAL truth values.

T↔T=T, F↔F=T, else F

Conditional Relatives — Know All Four

Name
Form
Equivalent To
Key Fact

Implication
p → q
¬p ∨ q
Original statement

Converse
q → p
—
NOT equivalent to original

Inverse
¬p → ¬q
—
NOT equivalent; equivalent to converse

Contrapositive
¬q → ¬p
p → q
LOGICALLY EQUIVALENT to original ✓

Laws of Logic (Equivalences)

Identity Laws

p ∧ T ≡ pp ∨ F ≡ p

Domination Laws

p ∨ T ≡ Tp ∧ F ≡ F

Idempotent Laws

p ∨ p ≡ pp ∧ p ≡ p

Double Negation

¬(¬p) ≡ p

De Morgan's Laws ⚡

¬(p ∧ q) ≡ ¬p ∨ ¬q¬(p ∨ q) ≡ ¬p ∧ ¬q

Negate → flip AND/OR, distribute negation.

Distributive Laws

p ∧ (q ∨ r) ≡ (p∧q) ∨ (p∧r)p ∨ (q ∧ r) ≡ (p∨q) ∧ (p∨r)

Absorption Laws

p ∨ (p ∧ q) ≡ pp ∧ (p ∨ q) ≡ p

Negation Laws

p ∨ ¬p ≡ T (Tautology)p ∧ ¬p ≡ F (Contradiction)

Quantifiers — Predicate Logic

∀x

Universal Quantifier

"For ALL x in the domain, P(x) is true."To DISPROVE: find ONE counterexample.

Negation: ¬∀x P(x) ≡ ∃x ¬P(x)

∃x

Existential Quantifier

"There EXISTS at least one x such that P(x) is true."To DISPROVE: show P(x) is false for every x.

Negation: ¬∃x P(x) ≡ ∀x ¬P(x)

INTERACTIVE TRUTH TABLE

Select a compound proposition to generate its truth table:

p ∧ q
p ∨ q
p ⊕ q
p → q
p ↔ q
¬(p ∧ q)
¬p ∨ ¬q
¬q → ¬p
(p→q) ∧ (q→r)

02

METHODS OF PROOF

Rules of Inference

Rule
Given
Conclude
F…

MAT 243 — Discrete Mathematical Structures

83,333 bytes · HTML source
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MAT 243 — Discrete Mathematical Structures</title>
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=IBM+Plex+Mono:wght@300;400;600&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<style>
:root {
  --bg: #080808;
  --bg2: #0e0e0e;
  --bg3: #141414;
  --bg4: #1c1c1c;
  --orange: #ff6200;
  --orange-dim: #c44d00;
  --orange-glow: rgba(255,98,0,0.15);
  --orange-border: rgba(255,98,0,0.35);
  --grey: #888;
  --grey-dim: #444;
  --grey-light: #bbb;
  --white: #f0f0f0;
  --mono: 'IBM Plex Mono', monospace;
  --sans: 'IBM Plex Sans', sans-serif;
  --display: 'Bebas Neue', sans-serif;
}

*{margin:0;padding:0;box-sizing:border-box;}

html{scroll-behavior:smooth;}

body{
  background:var(--bg);
  color:var(--white);
  font-family:var(--sans);
  font-size:15px;
  line-height:1.7;
  overflow-x:hidden;
}

/* GRID BACKGROUND */
body::before{
  content:'';
  position:fixed;
  inset:0;
  background-image:
    linear-gradient(rgba(255,98,0,0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,98,0,0.03) 1px, transparent 1px);
  background-size:60px 60px;
  pointer-events:none;
  z-index:0;
}

/* NAV */
nav{
  position:fixed;
  top:0;left:0;right:0;
  z-index:100;
  background:rgba(8,8,8,0.92);
  backdrop-filter:blur(12px);
  border-bottom:1px solid var(--grey-dim);
  padding:0 2rem;
  display:flex;
  align-items:center;
  gap:0;
  height:54px;
  overflow-x:auto;
}

nav .logo{
  font-family:var(--display);
  font-size:1.6rem;
  color:var(--orange);
  letter-spacing:2px;
  margin-right:2rem;
  white-space:nowrap;
  flex-shrink:0;
}

nav a{
  color:var(--grey);
  text-decoration:none;
  font-size:0.72rem;
  font-weight:500;
  letter-spacing:1.5px;
  text-transform:uppercase;
  padding:0 1rem;
  height:54px;
  display:flex;
  align-items:center;
  transition:color 0.2s, border-bottom 0.2s;
  border-bottom:2px solid transparent;
  white-space:nowrap;
  flex-shrink:0;
}

nav a:hover, nav a.active{
  color:var(--orange);
  border-bottom-color:var(--orange);
}

/* HERO */
.hero{
  padding:120px 2rem 60px;
  max-width:1200px;
  margin:0 auto;
  position:relative;
  z-index:1;
}

.hero-label{
  font-family:var(--mono);
  font-size:0.75rem;
  color:var(--orange);
  letter-spacing:4px;
  text-transform:uppercase;
  margin-bottom:1rem;
}

.hero h1{
  font-family:var(--display);
  font-size:clamp(3.5rem,8vw,7rem);
  line-height:0.95;
  letter-spacing:3px;
  color:var(--white);
  margin-bottom:1.5rem;
}

.hero h1 span{color:var(--orange);}

.hero-desc{
  font-size:1rem;
  color:var(--grey-light);
  max-width:620px;
  line-height:1.8;
  margin-bottom:2.5rem;
}

.hero-tags{
  display:flex;
  flex-wrap:wrap;
  gap:0.5rem;
}

.tag{
  font-family:var(--mono);
  font-size:0.65rem;
  letter-spacing:1.5px;
  text-transform:uppercase;
  padding:5px 12px;
  border:1px solid var(--grey-dim);
  color:var(--grey);
  background:var(--bg3);
}

/* SECTION */
section{
  padding:80px 2rem;
  max-width:1200px;
  margin:0 auto;
  position:relative;
  z-index:1;
}

.section-header{
  display:flex;
  align-items:flex-end;
  gap:1rem;
  margin-bottom:3rem;
  padding-bottom:1rem;
  border-bottom:1px solid var(--grey-dim);
}

.section-num{
  font-family:var(--display);
  font-size:4rem;
  color:var(--grey-dim);
  line-height:1;
}

.section-title{
  font-family:var(--display);
  font-size:2.2rem;
  letter-spacing:2px;
  color:var(--white);
  line-height:1;
}

.section-title span{color:var(--orange);}

/* CARDS GRID */
.cards{
  display:grid;
  gap:1px;
  background:var(--grey-dim);
}

.cards-2{grid-template-columns:repeat(auto-fit,minmax(300px,1fr));}
.cards-3{grid-template-columns:repeat(auto-fit,minmax(260px,1fr));}

.card{
  background:var(--bg2);
  padding:1.8rem;
  transition:background 0.2s;
  cursor:default;
}

.card:hover{background:var(--bg3);}

.card-icon{
  font-size:1.5rem;
  margin-bottom:0.8rem;
}

.card-title{
  font-family:var(--mono);
  font-size:0.8rem;
  color:var(--orange);
  letter-spacing:2px;
  text-transform:uppercase;
  margin-bottom:0.6rem;
}

.card-body{
  color:var(--grey-light);
  font-size:0.88rem;
  line-height:1.8;
}

.formula{
  font-family:var(--mono);
  background:var(--bg4);
  border-left:3px solid var(--orange);
  padding:0.8rem 1rem;
  margin:0.8rem 0;
  font-size:0.85rem;
  color:var(--orange);
  overflow-x:auto;
}

.formula .comment{color:var(--grey);}

/* TABLE */
.math-table{
  width:100%;
  border-collapse:collapse;
  font-family:var(--mono);
  font-size:0.82rem;
  margin:1rem 0;
}

.math-table th{
  background:var(--bg4);
  color:var(--orange);
  padding:10px 14px;
  text-align:left;
  letter-spacing:1px;
  text-transform:uppercase;
  font-size:0.7rem;
  border:1px solid var(--grey-dim);
}

.math-table td{
  padding:9px 14px;
  border:1px solid var(--grey-dim);
  color:var(--grey-light);
}

.math-table tr:hover td{background:var(--bg3);}
.math-table .hl{color:var(--orange);}
.math-table .dim{color:var(--grey);}

/* TRUTH TABLE INTERACTIVE */
.truth-builder{
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  padding:2rem;
  margin-top:2rem;
}

.truth-builder h3{
  font-family:var(--display);
  font-size:1.4rem;
  letter-spacing:2px;
  color:var(--orange);
  margin-bottom:1rem;
}

.formula-select{
  display:flex;
  flex-wrap:wrap;
  gap:0.5rem;
  margin-bottom:1.5rem;
}

.formula-btn{
  font-family:var(--mono);
  font-size:0.78rem;
  padding:7px 14px;
  background:var(--bg3);
  border:1px solid var(--grey-dim);
  color:var(--grey-light);
  cursor:pointer;
  transition:all 0.15s;
  letter-spacing:0.5px;
}

.formula-btn:hover{border-color:var(--orange);color:var(--orange);}
.formula-btn.active{background:var(--orange);color:#000;border-color:var(--orange);}

#truth-output{overflow-x:auto;margin-top:1rem;}

/* BIG O CHART */
.bigo-container{
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  padding:2rem;
  margin-top:2rem;
}

.bigo-container h3{
  font-family:var(--display);
  font-size:1.4rem;
  letter-spacing:2px;
  color:var(--orange);
  margin-bottom:1rem;
}

#bigo-canvas{
  width:100%;
  height:300px;
  display:block;
  background:var(--bg);
}

.bigo-legend{
  display:flex;
  flex-wrap:wrap;
  gap:1rem;
  margin-top:1rem;
}

.legend-item{
  display:flex;
  align-items:center;
  gap:8px;
  font-family:var(--mono);
  font-size:0.72rem;
  color:var(--grey-light);
  cursor:pointer;
  transition:opacity 0.2s;
}

.legend-dot{
  width:12px;height:12px;
  border-radius:50%;
  flex-shrink:0;
}

.legend-item.hidden{opacity:0.3;}

/* PROOF STEPS */
.proof-box{
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  margin:1rem 0;
  overflow:hidden;
}

.proof-header{
  display:flex;
  justify-content:space-between;
  align-items:center;
  padding:1rem 1.5rem;
  cursor:pointer;
  transition:background 0.2s;
  user-select:none;
}

.proof-header:hover{background:var(--bg3);}

.proof-header-left{
  display:flex;
  align-items:center;
  gap:1rem;
}

.proof-type-badge{
  font-family:var(--mono);
  font-size:0.65rem;
  letter-spacing:2px;
  text-transform:uppercase;
  padding:3px 10px;
  background:var(--orange-glow);
  border:1px solid var(--orange-border);
  color:var(--orange);
}

.proof-title{
  font-family:var(--sans);
  font-weight:600;
  color:var(--white);
  font-size:0.92rem;
}

.proof-arrow{
  color:var(--grey);
  transition:transform 0.3s;
  font-size:1rem;
}

.proof-body{
  display:none;
  padding:1.5rem;
  border-top:1px solid var(--grey-dim);
}

.proof-body.open{display:block;}
.proof-arrow.open{transform:rotate(90deg);}

.step{
  display:flex;
  gap:1rem;
  margin:0.6rem 0;
  padding:0.8rem;
  background:var(--bg3);
  border-left:2px solid var(--grey-dim);
  align-items:flex-start;
  transition:border-color 0.2s;
}

.step:hover{border-left-color:var(--orange);}

.step-num{
  font-family:var(--mono);
  font-size:0.7rem;
  color:var(--orange);
  min-width:24px;
  margin-top:2px;
}

.step-text{
  font-size:0.86rem;
  color:var(--grey-light);
  line-height:1.7;
  font-family:var(--mono);
}

.step-reason{
  font-size:0.72rem;
  color:var(--grey);
  margin-top:3px;
  font-family:var(--sans);
  font-style:italic;
}

/* MODULAR ARITHMETIC DEMO */
.mod-demo{
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  padding:2rem;
  margin-top:2rem;
}

.mod-demo h3{
  font-family:var(--display);
  font-size:1.4rem;
  color:var(--orange);
  letter-spacing:2px;
  margin-bottom:1rem;
}

.mod-inputs{
  display:flex;
  gap:1rem;
  flex-wrap:wrap;
  align-items:center;
  margin-bottom:1.5rem;
}

.mod-inputs label{
  font-family:var(--mono);
  font-size:0.78rem;
  color:var(--grey);
  text-transform:uppercase;
  letter-spacing:1px;
}

.mod-inputs input{
  background:var(--bg3);
  border:1px solid var(--grey-dim);
  color:var(--orange);
  font-family:var(--mono);
  font-size:1rem;
  padding:8px 14px;
  width:80px;
  outline:none;
  transition:border-color 0.2s;
}

.mod-inputs input:focus{border-color:var(--orange);}

.mod-result{
  font-family:var(--mono);
  font-size:0.9rem;
  color:var(--grey-light);
  background:var(--bg4);
  padding:1rem 1.5rem;
  border-left:3px solid var(--orange);
  margin-top:0.5rem;
}

/* COUNTING CALCULATOR */
.count-calc{
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  padding:2rem;
  margin-top:2rem;
}

.count-calc h3{
  font-family:var(--display);
  font-size:1.4rem;
  color:var(--orange);
  letter-spacing:2px;
  margin-bottom:1.5rem;
}

.calc-tabs{
  display:flex;
  gap:1px;
  background:var(--grey-dim);
  margin-bottom:1.5rem;
}

.calc-tab{
  flex:1;
  padding:10px;
  background:var(--bg3);
  border:none;
  color:var(--grey);
  font-family:var(--mono);
  font-size:0.72rem;
  letter-spacing:1.5px;
  text-transform:uppercase;
  cursor:pointer;
  transition:all 0.15s;
}

.calc-tab.active{background:var(--orange);color:#000;}

.calc-inputs{
  display:flex;
  gap:1.5rem;
  flex-wrap:wrap;
  align-items:center;
  margin-bottom:1rem;
}

.calc-inputs .field{
  display:flex;
  flex-direction:column;
  gap:4px;
}

.calc-inputs label{
  font-family:var(--mono);
  font-size:0.7rem;
  color:var(--grey);
  text-transform:uppercase;
  letter-spacing:1px;
}

.calc-inputs input{
  background:var(--bg3);
  border:1px solid var(--grey-dim);
  color:var(--orange);
  font-family:var(--mono);
  font-size:1.1rem;
  padding:8px 14px;
  width:100px;
  outline:none;
  transition:border-color 0.2s;
}

.calc-inputs input:focus{border-color:var(--orange);}

.calc-output{
  font-family:var(--mono);
  font-size:0.9rem;
  color:var(--grey-light);
  background:var(--bg4);
  padding:1.2rem 1.5rem;
  border-left:3px solid var(--orange);
  min-height:60px;
}

.calc-result-big{
  font-family:var(--display);
  font-size:2rem;
  color:var(--orange);
  letter-spacing:2px;
  display:block;
  margin-bottom:0.3rem;
}

/* OPERATOR REFERENCE */
.op-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(200px,1fr));
  gap:1px;
  background:var(--grey-dim);
  margin:1rem 0;
}

.op-card{
  background:var(--bg2);
  padding:1.3rem;
  display:flex;
  flex-direction:column;
  gap:0.4rem;
  transition:background 0.2s;
}

.op-card:hover{background:var(--bg3);}

.op-symbol{
  font-family:var(--mono);
  font-size:1.8rem;
  color:var(--orange);
  line-height:1;
}

.op-name{
  font-family:var(--sans);
  font-weight:600;
  font-size:0.85rem;
  color:var(--white);
}

.op-desc{
  font-size:0.78rem;
  color:var(--grey);
  line-height:1.6;
}

.op-truth{
  font-family:var(--mono);
  font-size:0.7rem;
  color:var(--grey-dim);
  margin-top:0.3rem;
}

/* SET VENN DIAGRAM */
.venn-container{
  display:flex;
  justify-content:center;
  padding:2rem;
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  margin-top:2rem;
  flex-direction:column;
  align-items:center;
}

.venn-container h3{
  font-family:var(--display);
  font-size:1.4rem;
  color:var(--orange);
  letter-spacing:2px;
  margin-bottom:1.5rem;
  align-self:flex-start;
}

.venn-ops{
  display:flex;
  gap:0.5rem;
  flex-wrap:wrap;
  margin-bottom:1.5rem;
  align-self:flex-start;
}

#venn-svg{overflow:visible;}

.venn-label{
  font-family:var(--mono);
  font-size:0.75rem;
  fill:var(--grey-light);
  text-anchor:middle;
}

/* GRAPH THEORY */
#graph-canvas{
  width:100%;
  height:280px;
  display:block;
  background:var(--bg);
  cursor:grab;
}

#graph-canvas:active{cursor:grabbing;}

.graph-container{
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  padding:2rem;
  margin-top:2rem;
}

.graph-container h3{
  font-family:var(--display);
  font-size:1.4rem;
  color:var(--orange);
  letter-spacing:2px;
  margin-bottom:0.5rem;
}

.graph-info{
  font-family:var(--mono);
  font-size:0.78rem;
  color:var(--grey);
  margin-bottom:1rem;
}

.graph-stats{
  display:flex;
  gap:2rem;
  flex-wrap:wrap;
  margin-top:1rem;
}

.stat-box{
  display:flex;
  flex-direction:column;
  gap:3px;
}

.stat-label{
  font-family:var(--mono);
  font-size:0.65rem;
  text-transform:uppercase;
  letter-spacing:1.5px;
  color:var(--grey);
}

.stat-val{
  font-family:var(--mono);
  font-size:1.2rem;
  color:var(--orange);
}

/* INDUCTION STEPPER */
.induction-demo{
  background:var(--bg2);
  border:1px solid var(--grey-dim);
  padding:2rem;
  margin-top:2rem;
}

.induction-demo h3{
  font-family:var(--display);
  font-size:1.4rem;
  color:var(--orange);
  letter-spacing:2px;
  margin-bottom:0.5rem;
}

.induction-subtitle{
  font-family:var(--mono);
  font-size:0.75rem;
  color:var(--grey);
  margin-bottom:1.5rem;
}

.ind-steps{
  display:flex;
  flex-direction:column;
  gap:1px;
  background:var(--grey-dim);
}

.ind-step{
  background:var(--bg3);
  padding:1.2rem 1.5rem;
  display:flex;
  gap:1.2rem;
  align-items:flex-start;
  cursor:pointer;
  transition:background 0.2s;
  border-left:3px solid transparent;
}

.ind-step.active{
  background:var(--bg4);
  border-left-color:var(--orange);
}

.ind-step-num{
  font-family:var(--display);
  font-size:2rem;
  color:var(--grey-dim);
  line-height:1;
  min-width:32px;
  transition:color 0.2s;
}

.ind-step.active .ind-step-num{color:var(--orange);}

.ind-step-content{}

.ind-step-title{
  font-family:var(--sans);
  font-weight:600;
  color:var(--white);
  font-size:0.88rem;
  margin-bottom:0.2rem;
}

.ind-step-body{
  font-family:var(--mono);
  font-size:0.8rem;
  color:var(--grey-light);
  line-height:1.7;
  display:none;
}

.ind-step.active .ind-step-body{display:block;}

/* FORMULA REFERENCE SECTION */
.formula-grid{
  display:grid;
  gap:1px;
  background:var(--grey-dim);
  grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
}

.formula-card{
  background:var(--bg2);
  padding:1.5rem;
  position:relative;
  transition:background 0.2s;
}

.formula-card:hover{background:var(--bg3);}

.formula-cat{
  font-family:var(--mono);
  font-size:0.62rem;
  text-transform:uppercase;
  letter-spacing:2px;
  color:var(--grey);
  margin-bottom:0.4rem;
}

.formula-name{
  font-family:var(--sans);
  font-weight:600;
  color:var(--white);
  font-size:0.88rem;
  margin-bottom:0.7rem;
}

.formula-expr{
  font-family:var(--mono);
  font-size:0.9rem;
  color:var(--orange);
  background:var(--bg4);
  padding:0.7rem 1rem;
  border-left:3px solid var(--orange);
  margin-bottom:0.6rem;
  overflow-x:auto;
  white-space:nowrap;
}

.formula-note{
  font-size:0.78rem;
  color:var(--grey);
  line-height:1.6;
}

/* SCROLLBAR */
::-webkit-scrollbar{width:6px;height:6px;}
::-webkit-scrollbar-track{background:var(--bg);}
::-webkit-scrollbar-thumb{background:var(--grey-dim);}
::-webkit-scrollbar-thumb:hover{background:var(--orange);}

/* DIVIDER */
.divider{
  height:1px;
  background:linear-gradient(90deg, transparent, var(--grey-dim), transparent);
  margin:0 2rem;
}

/* ANIMATE */
.reveal{
  opacity:0;
  transform:translateY(20px);
  transition:opacity 0.6s, transform 0.6s;
}
.reveal.visible{opacity:1;transform:none;}

/* ORANGE ACCENT LINE */
.accent-line{
  display:flex;
  align-items:center;
  gap:1rem;
  margin-bottom:1.5rem;
}

.accent-line::after{
  content:'';
  flex:1;
  height:1px;
  background:linear-gradient(90deg, var(--orange), transparent);
}

.accent-line span{
  font-family:var(--mono);
  font-size:0.7rem;
  text-transform:uppercase;
  letter-spacing:2px;
  color:var(--orange);
}

/* RESPONSIVE */
@media(max-width:768px){
  nav a{font-size:0.65rem;padding:0 0.6rem;}
  .hero h1{font-size:3rem;}
  .section-num{font-size:2.5rem;}
  .section-title{font-size:1.5rem;}
  section{padding:60px 1rem;}
}

/* QUANTIFIER BOX */
.quant-box{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:1px;
  background:var(--grey-dim);
  margin:1rem 0;
}

.quant-card{
  background:var(--bg2);
  padding:1.5rem;
}

.quant-sym{
  font-family:var(--mono);
  font-size:2.5rem;
  color:var(--orange);
  line-height:1;
  margin-bottom:0.5rem;
}

.quant-title{
  font-family:var(--sans);
  font-weight:600;
  font-size:0.88rem;
  color:var(--white);
  margin-bottom:0.3rem;
}

.quant-desc{
  font-size:0.82rem;
  color:var(--grey-light);
  line-height:1.7;
}

.quant-negate{
  font-family:var(--mono);
  font-size:0.75rem;
  color:var(--grey);
  margin-top:0.5rem;
  padding-top:0.5rem;
  border-top:1px solid var(--grey-dim);
}

@media(max-width:500px){
  .quant-box{grid-template-columns:1fr;}
}

/* ORANGE glow pulse for hero */
@keyframes pulse-glow{
  0%,100%{text-shadow:0 0 20px rgba(255,98,0,0.3);}
  50%{text-shadow:0 0 40px rgba(255,98,0,0.7), 0 0 80px rgba(255,98,0,0.2);}
}

.hero h1 span{animation:pulse-glow 4s ease-in-out infinite;}

/* scroll indicator */
.scroll-line{
  position:fixed;
  top:0;left:0;
  height:2px;
  background:var(--orange);
  z-index:200;
  transition:width 0.1s;
}
</style>
</head>
<body>

<div class="scroll-line" id="scrollLine"></div>

<nav id="nav">
  <div class="logo">MAT 243</div>
  <a href="#logic">Logic</a>
  <a href="#proofs">Proofs</a>
  <a href="#sets">Sets</a>
  <a href="#functions">Functions</a>
  <a href="#bigo">Big-O</a>
  <a href="#numtheory">Number Theory</a>
  <a href="#induction">Induction</a>
  <a href="#counting">Counting</a>
  <a href="#graphs">Graphs</a>
  <a href="#formulas">Formulas</a>
</nav>

<!-- HERO -->
<div class="hero">
  <div class="hero-label">ASU · Discrete Mathematical Structures</div>
  <h1>DISCRETE<br><span>MATH</span><br>STRUCTURES</h1>
  <p class="hero-desc">An interactive reference covering logic, proofs, sets, functions, number theory, induction, combinatorics, and graph theory — every formula, concept, and technique you need.</p>
  <div class="hero-tags">
    <span class="tag">Propositional Logic</span>
    <span class="tag">Proof Techniques</span>
    <span class="tag">Set Theory</span>
    <span class="tag">Big-O Notation</span>
    <span class="tag">Modular Arithmetic</span>
    <span class="tag">Mathematical Induction</span>
    <span class="tag">Combinatorics</span>
    <span class="tag">Graph Theory</span>
  </div>
</div>

<div class="divider"></div>

<!-- ========== SECTION 1: LOGIC ========== -->
<section id="logic" class="reveal">
  <div class="section-header">
    <div class="section-num">01</div>
    <div>
      <div class="section-title">PROPOSITIONAL <span>LOGIC</span></div>
    </div>
  </div>

  <div class="accent-line"><span>Logical Operators</span></div>

  <div class="op-grid">
    <div class="op-card">
      <div class="op-symbol">¬p</div>
      <div class="op-name">Negation</div>
      <div class="op-desc">Reverses truth value. If p is T, ¬p is F.</div>
      <div class="op-truth">T→F, F→T</div>
    </div>
    <div class="op-card">
      <div class="op-symbol">p ∧ q</div>
      <div class="op-name">Conjunction (AND)</div>
      <div class="op-desc">True only when BOTH p and q are true.</div>
      <div class="op-truth">T∧T=T, all others=F</div>
    </div>
    <div class="op-card">
      <div class="op-symbol">p ∨ q</div>
      <div class="op-name">Disjunction (OR)</div>
      <div class="op-desc">True when AT LEAST ONE of p, q is true.</div>
      <div class="op-truth">F∨F=F, all others=T</div>
    </div>
    <div class="op-card">
      <div class="op-symbol">p ⊕ q</div>
      <div class="op-name">Exclusive OR</div>
      <div class="op-desc">True when EXACTLY ONE of p, q is true — not both.</div>
      <div class="op-truth">T⊕T=F, T⊕F=T, F⊕T=T, F⊕F=F</div>
    </div>
    <div class="op-card">
      <div class="op-symbol">p → q</div>
      <div class="op-name">Implication (IF-THEN)</div>
      <div class="op-desc">FALSE only when p is TRUE and q is FALSE. The most critical operator.</div>
      <div class="op-truth">T→F=F, all others=T</div>
    </div>
    <div class="op-card">
      <div class="op-symbol">p ↔ q</div>
      <div class="op-name">Biconditional (IFF)</div>
      <div class="op-desc">True when p and q have IDENTICAL truth values.</div>
      <div class="op-truth">T↔T=T, F↔F=T, else F</div>
    </div>
  </div>

  <div class="accent-line" style="margin-top:2.5rem;"><span>Conditional Relatives — Know All Four</span></div>

  <table class="math-table">
    <thead>
      <tr><th>Name</th><th>Form</th><th>Equivalent To</th><th>Key Fact</th></tr>
    </thead>
    <tbody>
      <tr><td class="hl">Implication</td><td>p → q</td><td>¬p ∨ q</td><td>Original statement</td></tr>
      <tr><td>Converse</td><td>q → p</td><td>—</td><td>NOT equivalent to original</td></tr>
      <tr><td>Inverse</td><td>¬p → ¬q</td><td>—</td><td>NOT equivalent; equivalent to converse</td></tr>
      <tr><td class="hl">Contrapositive</td><td>¬q → ¬p</td><td>p → q</td><td class="hl">LOGICALLY EQUIVALENT to original ✓</td></tr>
    </tbody>
  </table>

  <div class="accent-line" style="margin-top:2.5rem;"><span>Laws of Logic (Equivalences)</span></div>

  <div class="cards cards-2" style="margin-top:0;">
    <div class="card">
      <div class="card-title">Identity Laws</div>
      <div class="formula">p ∧ T ≡ p<br>p ∨ F ≡ p</div>
    </div>
    <div class="card">
      <div class="card-title">Domination Laws</div>
      <div class="formula">p ∨ T ≡ T<br>p ∧ F ≡ F</div>
    </div>
    <div class="card">
      <div class="card-title">Idempotent Laws</div>
      <div class="formula">p ∨ p ≡ p<br>p ∧ p ≡ p</div>
    </div>
    <div class="card">
      <div class="card-title">Double Negation</div>
      <div class="formula">¬(¬p) ≡ p</div>
    </div>
    <div class="card">
      <div class="card-title">De Morgan's Laws ⚡</div>
      <div class="formula">¬(p ∧ q) ≡ ¬p ∨ ¬q<br>¬(p ∨ q) ≡ ¬p ∧ ¬q</div>
      <div class="card-body">Negate → flip AND/OR, distribute negation.</div>
    </div>
    <div class="card">
      <div class="card-title">Distributive Laws</div>
      <div class="formula">p ∧ (q ∨ r) ≡ (p∧q) ∨ (p∧r)<br>p ∨ (q ∧ r) ≡ (p∨q) ∧ (p∨r)</div>
    </div>
    <div class="card">
      <div class="card-title">Absorption Laws</div>
      <div class="formula">p ∨ (p ∧ q) ≡ p<br>p ∧ (p ∨ q) ≡ p</div>
    </div>
    <div class="card">
      <div class="card-title">Negation Laws</div>
      <div class="formula">p ∨ ¬p ≡ T  (Tautology)<br>p ∧ ¬p ≡ F  (Contradiction)</div>
    </div>
  </div>

  <div class="accent-line" style="margin-top:2.5rem;"><span>Quantifiers — Predicate Logic</span></div>

  <div class="quant-box">
    <div class="quant-card">
      <div class="quant-sym">∀x</div>
      <div class="quant-title">Universal Quantifier</div>
      <div class="quant-desc">"For ALL x in the domain, P(x) is true."<br>To DISPROVE: find ONE counterexample.</div>
      <div class="quant-negate">Negation: ¬∀x P(x) ≡ ∃x ¬P(x)</div>
    </div>
    <div class="quant-card">
      <div class="quant-sym">∃x</div>
      <div class="quant-title">Existential Quantifier</div>
      <div class="quant-desc">"There EXISTS at least one x such that P(x) is true."<br>To DISPROVE: show P(x) is false for every x.</div>
      <div class="quant-negate">Negation: ¬∃x P(x) ≡ ∀x ¬P(x)</div>
    </div>
  </div>

  <!-- Interactive Truth Table Builder -->
  <div class="truth-builder">
    <h3>INTERACTIVE TRUTH TABLE</h3>
    <p style="font-size:0.82rem;color:var(--grey);margin-bottom:1rem;">Select a compound proposition to generate its truth table:</p>
    <div class="formula-select" id="formulaSelect">
      <button class="formula-btn active" data-formula="AND">p ∧ q</button>
      <button class="formula-btn" data-formula="OR">p ∨ q</button>
      <button class="formula-btn" data-formula="XOR">p ⊕ q</button>
      <button class="formula-btn" data-formula="IMP">p → q</button>
      <button class="formula-btn" data-formula="BICON">p ↔ q</button>
      <button class="formula-btn" data-formula="DEMORGAN1">¬(p ∧ q)</button>
      <button class="formula-btn" data-formula="DEMORGAN2">¬p ∨ ¬q</button>
      <button class="formula-btn" data-formula="CONTRA">¬q → ¬p</button>
      <button class="formula-btn" data-formula="3VAR">(p→q) ∧ (q→r)</button>
    </div>
    <div id="truth-output"></div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 2: PROOFS ========== -->
<section id="proofs" class="reveal">
  <div class="section-header">
    <div class="section-num">02</div>
    <div><div class="section-title">METHODS OF <span>PROOF</span></div></div>
  </div>

  <div class="accent-line"><span>Rules of Inference</span></div>

  <table class="math-table">
    <thead>
      <tr><th>Rule</th><th>Given</th><th>Conclude</th><th>Form</th></tr>
    </thead>
    <tbody>
      <tr><td class="hl">Modus Ponens</td><td>p → q, p</td><td>q</td><td class="dim">[(p→q) ∧ p] → q</td></tr>
      <tr><td class="hl">Modus Tollens</td><td>p → q, ¬q</td><td>¬p</td><td class="dim">[(p→q) ∧ ¬q] → ¬p</td></tr>
      <tr><td>Hypothetical Syllogism</td><td>p → q, q → r</td><td>p → r</td><td class="dim">Chain rule</td></tr>
      <tr><td>Disjunctive Syllogism</td><td>p ∨ q, ¬p</td><td>q</td><td class="dim">If not this, then that</td></tr>
      <tr><td>Addition</td><td>p</td><td>p ∨ q</td><td class="dim">Can always add disjunct</td></tr>
      <tr><td>Simplification</td><td>p ∧ q</td><td>p</td><td class="dim">Extract from conjunction</td></tr>
      <tr><td>Conjunction</td><td>p, q</td><td>p ∧ q</td><td class="dim">Combine two truths</td></tr>
      <tr><td>Universal Instantiation</td><td>∀x P(x)</td><td>P(c)</td><td class="dim">Any specific c in domain</td></tr>
      <tr><td>Universal Generalization</td><td>P(c) for arbitrary c</td><td>∀x P(x)</td><td class="dim">Must hold for ALL values</td></tr>
      <tr><td>Existential Instantiation</td><td>∃x P(x)</td><td>P(c) for some c</td><td class="dim">Name the witness</td></tr>
    </tbody>
  </table>

  <div class="accent-line" style="margin-top:2.5rem;"><span>Proof Strategies — Click to Expand</span></div>

  <div class="proof-box">
    <div class="proof-header" onclick="toggleProof(this)">
      <div class="proof-header-left">
        <span class="proof-type-badge">Direct</span>
        <span class="proof-title">Direct Proof: "If p, then q"</span>
      </div>
      <span class="proof-arrow">▶</span>
    </div>
    <div class="proof-body">
      <p style="font-size:0.85rem;color:var(--grey-light);margin-bottom:1rem;">Assume <strong>p is true</strong>, then use logical steps to conclude <strong>q is true</strong>.</p>
      <p style="font-size:0.82rem;color:var(--grey);margin-bottom:1rem;font-style:italic;">Example: Prove that if n is odd, then n² is odd.</p>
      <div class="step"><div class="step-num">01</div><div><div class="step-text">Assume n is odd.</div><div class="step-reason">Assume the hypothesis</div></div></div>
      <div class="step"><div class="step-num">02</div><div><div class="step-text">By definition: n = 2k + 1 for some integer k.</div><div class="step-reason">Definition of odd number</div></div></div>
      <div class="step"><div class="step-num">03</div><div><div class="step-text">n² = (2k+1)² = 4k² + 4k + 1 = 2(2k²+2k) + 1</div><div class="step-reason">Expand and factor</div></div></div>
      <div class="step"><div class="step-num">04</div><div><div class="step-text">Let m = 2k²+2k (an integer). Then n² = 2m+1.</div><div class="step-reason">Substitution</div></div></div>
      <div class="step"><div class="step-num">05</div><div><div class="step-text">Therefore n² is odd. □</div><div class="step-reason">Definition of odd — proof complete (QED)</div></div></div>
    </div>
  </div>

  <div class="proof-box">
    <div class="proof-header" onclick="toggleProof(this)">
      <div class="proof-header-left">
        <span class="proof-type-badge">Contrapositive</span>
        <span class="proof-title">Proof by Contrapositive: Prove ¬q → ¬p instead</span>
      </div>
      <span class="proof-arrow">▶</span>
    </div>
    <div class="proof-body">
      <p style="font-size:0.85rem;color:var(--grey-light);margin-bottom:1rem;">Since <strong>p→q ≡ ¬q→¬p</strong>, proving the contrapositive is logically equivalent. Use when the conclusion involves a negative property.</p>
      <p style="font-size:0.82rem;color:var(--grey);margin-bottom:1rem;font-style:italic;">Example: Prove that if n² is odd, then n is odd.</p>
      <div class="step"><div class="step-num">01</div><div><div class="step-text">We prove the contrapositive: if n is EVEN, then n² is EVEN.</div><div class="step-reason">Identify ¬q → ¬p</div></div></div>
      <div class="step"><div class="step-num">02</div><div><div class="step-text">Assume n is even: n = 2k for some integer k.</div><div class="step-reason">Definition of even</div></div></div>
      <div class="step"><div class="step-num">03</div><div><div class="step-text">n² = (2k)² = 4k² = 2(2k²)</div><div class="step-reason">Algebra</div></div></div>
      <div class="step"><div class="step-num">04</div><div><div class="step-text">Since 2k² is an integer, n² is even. □</div><div class="step-reason">Definition of even — contrapositive proven</div></div></div>
    </div>
  </div>

  <div class="proof-box">
    <div class="proof-header" onclick="toggleProof(this)">
      <div class="proof-header-left">
        <span class="proof-type-badge">Contradiction</span>
        <span class="proof-title">Proof by Contradiction: Assume ¬p, derive absurdity</span>
      </div>
      <span class="proof-arrow">▶</span>
    </div>
    <div class="proof-body">
      <p style="font-size:0.85rem;color:var(--grey-light);margin-bottom:1rem;">Assume the statement is <strong>FALSE</strong>. Show this leads to a contradiction (like 1=0 or x is both odd and even). Therefore the statement must be TRUE.</p>
      <p style="font-size:0.82rem;color:var(--grey);margin-bottom:1rem;font-style:italic;">Classic example: Prove √2 is irrational.</p>
      <div class="step"><div class="step-num">01</div><div><div class="step-text">Assume √2 IS rational (negation of what we want to prove).</div><div class="step-reason">Assume ¬p</div></div></div>
      <div class="step"><div class="step-num">02</div><div><div class="step-text">Then √2 = a/b where a, b are integers with gcd(a,b)=1 (fully reduced).</div><div class="step-reason">Definition of rational in lowest terms</div></div></div>
      <div class="step"><div class="step-num">03</div><div><div class="step-text">2 = a²/b² → a² = 2b² → a² is even → a is even.</div><div class="step-reason">Square both sides; even square → even number</div></div></div>
      <div class="step"><div class="step-num">04</div><div><div class="step-text">Write a = 2c. Then 4c² = 2b² → b² = 2c² → b is even.</div><div class="step-reason">Substitute and simplify</div></div></div>
      <div class="step"><div class="step-num">05</div><div><div class="step-text">Both a and b are even — CONTRADICTION. They can't share factor 2 in reduced form. □</div><div class="step-reason">Contradicts gcd(a,b)=1 assumption</div></div></div>
    </div>
  </div>

  <div class="proof-box">
    <div class="proof-header" onclick="toggleProof(this)">
      <div class="proof-header-left">
        <span class="proof-type-badge">Cases</span>
        <span class="proof-title">Proof by Cases: Split domain, prove each case</span>
      </div>
      <span class="proof-arrow">▶</span>
    </div>
    <div class="proof-body">
      <p style="font-size:0.85rem;color:var(--grey-light);margin-bottom:1rem;">Divide the domain into EXHAUSTIVE cases, then prove the statement holds in EVERY case.</p>
      <p style="font-size:0.82rem;color:var(--grey);margin-bottom:1rem;font-style:italic;">Example: Prove n² + n is even for all integers n.</p>
      <div class="step"><div class="step-num">01</div><div><div class="step-text">Case 1: n is even. Write n = 2k. Then n²+n = 4k²+2k = 2(2k²+k). Even. ✓</div><div class="step-reason">Even case</div></div></div>
      <div class="step"><div class="step-num">02</div><div><div class="step-text">Case 2: n is odd. Write n = 2k+1. Then n²+n = (4k²+4k+1)+(2k+1) = 4k²+6k+2 = 2(2k²+3k+1). Even. ✓</div><div class="step-reason">Odd case</div></div></div>
      <div class="step"><div class="step-num">03</div><div><div class="step-text">Every integer is even or odd (exhaustive). In both cases n²+n is even. □</div><div class="step-reason">All cases covered — QED</div></div></div>
    </div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 3: SETS ========== -->
<section id="sets" class="reveal">
  <div class="section-header">
    <div class="section-num">03</div>
    <div><div class="section-title">SET <span>THEORY</span></div></div>
  </div>

  <div class="accent-line"><span>Set Operations</span></div>

  <table class="math-table">
    <thead>
      <tr><th>Operation</th><th>Symbol</th><th>Formal Definition</th><th>Meaning</th></tr>
    </thead>
    <tbody>
      <tr><td class="hl">Union</td><td>A ∪ B</td><td>{x | x∈A ∨ x∈B}</td><td>Everything in A OR B</td></tr>
      <tr><td class="hl">Intersection</td><td>A ∩ B</td><td>{x | x∈A ∧ x∈B}</td><td>Only what's in BOTH</td></tr>
      <tr><td>Difference</td><td>A − B</td><td>{x | x∈A ∧ x∉B}</td><td>A without B's elements</td></tr>
      <tr><td>Complement</td><td>Ā or A'</td><td>{x | x∉A}</td><td>Everything NOT in A</td></tr>
      <tr><td>Cartesian Product</td><td>A × B</td><td>{(a,b) | a∈A, b∈B}</td><td>All ordered pairs</td></tr>
      <tr><td>Power Set</td><td>P(A) or 2^A</td><td>Set of all subsets of A</td><td>|P(A)| = 2^|A|</td></tr>
    </tbody>
  </table>

  <div class="accent-line" style="margin-top:2rem;"><span>Set Identities (Mirror of Logic Laws)</span></div>

  <div class="cards cards-2" style="margin-top:0;">
    <div class="card">
      <div class="card-title">De Morgan's Laws (Sets)</div>
      <div class="formula">̄(A ∪ B) = Ā ∩ B̄<br>̄(A ∩ B) = Ā ∪ B̄</div>
      <div class="card-body">Complement flips ∪ and ∩. Mirrors logic: ¬(p∨q)≡¬p∧¬q</div>
    </div>
    <div class="card">
      <div class="card-title">Inclusion-Exclusion (2 sets)</div>
      <div class="formula">|A ∪ B| = |A| + |B| - |A ∩ B|</div>
      <div class="card-body">Subtract overlap to avoid double-counting.</div>
    </div>
    <div class="card">
      <div class="card-title">Inclusion-Exclusion (3 sets)</div>
      <div class="formula">|A∪B∪C| = |A|+|B|+|C|<br>     - |A∩B| - |A∩C| - |B∩C|<br>     + |A∩B∩C|</div>
    </div>
    <div class="card">
      <div class="card-title">Distributive Laws (Sets)</div>
      <div class="formula">A ∩ (B ∪ C) = (A∩B) ∪ (A∩C)<br>A ∪ (B ∩ C) = (A∪B) ∩ (A∪C)</div>
    </div>
    <div class="card">
      <div class="card-title">Cardinality Key Facts</div>
      <div class="formula">|A × B| = |A| · |B|<br>|P(A)| = 2^|A|</div>
      <div class="card-body">A set with 3 elements has 2³ = 8 subsets (including ∅ and itself).</div>
    </div>
    <div class="card">
      <div class="card-title">Subset Definition</div>
      <div class="formula">A ⊆ B ↔ ∀x(x∈A → x∈B)<br>A = B ↔ A⊆B ∧ B⊆A</div>
      <div class="card-body">∅ ⊆ A for every set A. ∅ is subset of everything.</div>
    </div>
  </div>

  <!-- Venn Diagram -->
  <div class="venn-container">
    <h3>VENN DIAGRAM VISUALIZER</h3>
    <div class="venn-ops">
      <button class="formula-btn active" onclick="setVenn('union',this)">A ∪ B</button>
      <button class="formula-btn" onclick="setVenn('intersect',this)">A ∩ B</button>
      <button class="formula-btn" onclick="setVenn('diff_ab',this)">A − B</button>
      <button class="formula-btn" onclick="setVenn('diff_ba',this)">B − A</button>
      <button class="formula-btn" onclick="setVenn('comp_a',this)">Ā</button>
      <button class="formula-btn" onclick="setVenn('sym_diff',this)">A ⊕ B</button>
    </div>
    <svg id="venn-svg" viewBox="0 0 400 200" width="400" height="200" style="max-width:100%;">
      <defs>
        <clipPath id="clipA"><circle cx="145" cy="100" r="80"/></clipPath>
        <clipPath id="clipB"><circle cx="255" cy="100" r="80"/></clipPath>
        <clipPath id="clipU"><rect x="0" y="0" width="400" height="200"/></clipPath>
      </defs>
      <!-- Universe -->
      <rect x="10" y="10" width="380" height="180" fill="none" stroke="#444" stroke-width="1.5" rx="4"/>
      <!-- Highlight regions -->
      <circle id="venn-left" cx="145" cy="100" r="80" fill="none" opacity="0.5"/>
      <circle id="venn-right" cx="255" cy="100" r="80" fill="none" opacity="0.5"/>
      <circle id="venn-inter-a" cx="145" cy="100" r="80" fill="none" clip-path="url(#clipB)" opacity="0.5"/>
      <circle id="venn-inter-b" cx="255" cy="100" r="80" fill="none" clip-path="url(#clipA)" opacity="0.5"/>
      <!-- Outlines -->
      <circle cx="145" cy="100" r="80" fill="none" stroke="#ff6200" stroke-width="1.5" opacity="0.7"/>
      <circle cx="255" cy="100" r="80" fill="none" stroke="#888" stroke-width="1.5" opacity="0.7"/>
      <!-- Labels -->
      <text x="90" y="105" class="venn-label" font-family="IBM Plex Mono, monospace" font-size="18" fill="#ff6200">A</text>
      <text x="310" y="105" class="venn-label" font-family="IBM Plex Mono, monospace" font-size="18" fill="#aaa">B</text>
      <text x="200" y="35" class="venn-label" font-family="IBM Plex Mono, monospace" font-size="10" fill="#555">U</text>
    </svg>
    <div id="venn-desc" style="font-family:var(--mono);font-size:0.8rem;color:var(--grey);margin-top:1rem;text-align:center;"></div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 4: FUNCTIONS ========== -->
<section id="functions" class="reveal">
  <div class="section-header">
    <div class="section-num">04</div>
    <div><div class="section-title">FUNCTIONS & <span>MAPPINGS</span></div></div>
  </div>

  <div class="accent-line"><span>Function Classification</span></div>

  <div class="cards cards-3">
    <div class="card">
      <div class="card-title">Injective (One-to-One)</div>
      <div class="formula">f(a) = f(b) → a = b</div>
      <div class="card-body">No two inputs map to the same output. Distinct domain elements → distinct codomain elements.<br><br>Test: horizontal line hits graph AT MOST once.</div>
    </div>
    <div class="card">
      <div class="card-title">Surjective (Onto)</div>
      <div class="formula">∀y∈B ∃x∈A: f(x) = y</div>
      <div class="card-body">Every element in the CODOMAIN has at least one preimage. Range = Codomain.<br><br>Test: every output value is achieved.</div>
    </div>
    <div class="card">
      <div class="card-title">Bijective (1-1 Correspondence)</div>
      <div class="formula">Injective AND Surjective</div>
      <div class="card-body">Perfect pairing between domain and codomain. Only bijections have INVERSES.<br><br>Used to prove two sets have same cardinality.</div>
    </div>
    <div class="card">
      <div class="card-title">Floor & Ceiling</div>
      <div class="formula">⌊x⌋ = greatest int ≤ x<br>⌈x⌉ = least int ≥ x</div>
      <div class="card-body">⌊3.7⌋ = 3, ⌈3.2⌉ = 4<br>⌊-2.3⌋ = -3, ⌈-2.7⌉ = -2</div>
    </div>
    <div class="card">
      <div class="card-title">Function Composition</div>
      <div class="formula">(f ∘ g)(x) = f(g(x))</div>
      <div class="card-body">Apply g first, then f. Order matters — composition is not commutative in general.</div>
    </div>
    <div class="card">
      <div class="card-title">Inverse Function</div>
      <div class="formula">f⁻¹: B → A exists<br>iff f is bijective</div>
      <div class="card-body">f⁻¹(y) = x ↔ f(x) = y<br>f ∘ f⁻¹ = Identity<br>f⁻¹ ∘ f = Identity</div>
    </div>
  </div>

  <div class="accent-line" style="margin-top:2rem;"><span>Counting Functions Between Sets</span></div>

  <table class="math-table">
    <thead>
      <tr><th>Type</th><th>Count (|A|=m, |B|=n)</th><th>Condition</th></tr>
    </thead>
    <tbody>
      <tr><td>Any function</td><td class="hl">n^m</td><td>No restrictions</td></tr>
      <tr><td>Injective functions</td><td class="hl">P(n,m) = n!/(n-m)!</td><td>Requires n ≥ m</td></tr>
      <tr><td>Bijective functions</td><td class="hl">n! (if m = n)</td><td>Requires m = n</td></tr>
    </tbody>
  </table>
</section>

<div class="divider"></div>

<!-- ========== SECTION 5: BIG-O ========== -->
<section id="bigo" class="reveal">
  <div class="section-header">
    <div class="section-num">05</div>
    <div><div class="section-title">ALGORITHM <span>COMPLEXITY</span></div></div>
  </div>

  <div class="accent-line"><span>Big-O Definition</span></div>

  <div class="card" style="margin-bottom:1.5rem;">
    <div class="card-title">Formal Big-O Definition</div>
    <div class="formula">f(x) is O(g(x)) if ∃ constants C > 0 and k<br>such that |f(x)| ≤ C|g(x)| for all x > k</div>
    <div class="card-body">Big-O gives an UPPER BOUND on growth rate. We care about behavior as n → ∞, ignoring constants and lower-order terms.</div>
  </div>

  <div class="accent-line"><span>Complexity Classes</span></div>

  <table class="math-table">
    <thead>
      <tr><th>Class</th><th>Name</th><th>Example</th><th>n=10</th><th>n=100</th></tr>
    </thead>
    <tbody>
      <tr><td class="hl">O(1)</td><td>Constant</td><td>Array index access</td><td>1</td><td>1</td></tr>
      <tr><td class="hl">O(log n)</td><td>Logarithmic</td><td>Binary search</td><td>~3</td><td>~7</td></tr>
      <tr><td>O(n)</td><td>Linear</td><td>Linear scan</td><td>10</td><td>100</td></tr>
      <tr><td>O(n log n)</td><td>Linearithmic</td><td>Merge sort</td><td>~33</td><td>~664</td></tr>
      <tr><td>O(n²)</td><td>Quadratic</td><td>Bubble sort</td><td>100</td><td>10,000</td></tr>
      <tr><td>O(n³)</td><td>Cubic</td><td>Matrix multiply (naive)</td><td>1,000</td><td>1,000,000</td></tr>
      <tr><td style="color:#ff4444;">O(2^n)</td><td style="color:#ff4444;">Exponential</td><td>Brute-force TSP</td><td>1,024</td><td>1.27×10³⁰</td></tr>
      <tr><td style="color:#ff4444;">O(n!)</td><td style="color:#ff4444;">Factorial</td><td>All permutations</td><td>3,628,800</td><td>9.3×10¹⁵⁷</td></tr>
    </tbody>
  </table>

  <div class="bigo-container">
    <h3>GROWTH RATE VISUALIZER</h3>
    <canvas id="bigo-canvas"></canvas>
    <div class="bigo-legend" id="bigoLegend"></div>
  </div>

  <div class="accent-line" style="margin-top:2rem;"><span>Big-O Arithmetic Rules</span></div>

  <div class="cards cards-2" style="margin-top:0;">
    <div class="card">
      <div class="card-title">Sum Rule</div>
      <div class="formula">O(f) + O(g) = O(max(f,g))</div>
      <div class="card-body">O(n²) + O(n) = O(n²). The dominant term wins.</div>
    </div>
    <div class="card">
      <div class="card-title">Product Rule</div>
      <div class="formula">O(f) · O(g) = O(f·g)</div>
      <div class="card-body">Nested loops: O(n) inside O(n) = O(n²)</div>
    </div>
    <div class="card">
      <div class="card-title">Drop Constants</div>
      <div class="formula">O(5n) = O(n)<br>O(3n² + 7n) = O(n²)</div>
      <div class="card-body">Multiplicative constants are irrelevant for asymptotic analysis.</div>
    </div>
    <div class="card">
      <div class="card-title">Logarithm Base Doesn't Matter</div>
      <div class="formula">O(log₂ n) = O(log₁₀ n) = O(ln n)</div>
      <div class="card-body">Base change is just a constant factor: logₐ n = log₂ n / log₂ a</div>
    </div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 6: NUMBER THEORY ========== -->
<section id="numtheory" class="reveal">
  <div class="section-header">
    <div class="section-num">06</div>
    <div><div class="section-title">NUMBER <span>THEORY</span></div></div>
  </div>

  <div class="accent-line"><span>Divisibility & Modular Arithmetic</span></div>

  <div class="cards cards-2" style="margin-top:0;margin-bottom:1.5rem;">
    <div class="card">
      <div class="card-title">Divisibility</div>
      <div class="formula">a | b  ↔  ∃k∈Z: b = k·a</div>
      <div class="card-body">Read "a divides b." If 3|12, then 12=4×3. Key property: if a|b and b|c then a|c.</div>
    </div>
    <div class="card">
      <div class="card-title">Division Algorithm</div>
      <div class="formula">a = d·q + r,  0 ≤ r < d</div>
      <div class="card-body">Every integer a, divisor d > 0 gives unique quotient q and remainder r.<br>a mod d = r</div>
    </div>
    <div class="card">
      <div class="card-title">Congruence</div>
      <div class="formula">a ≡ b (mod m)<br>iff m | (a - b)</div>
      <div class="card-body">a and b have the same remainder when divided by m.<br>17 ≡ 5 (mod 12) since 12|(17-5)=12 ✓</div>
    </div>
    <div class="card">
      <div class="card-title">Modular Arithmetic Rules</div>
      <div class="formula">(a+b) mod m = ((a mod m)+(b mod m)) mod m<br>(a·b) mod m = ((a mod m)·(b mod m)) mod m</div>
    </div>
  </div>

  <div class="accent-line"><span>GCD & The Euclidean Algorithm</span></div>

  <div class="card" style="margin-bottom:1.5rem;">
    <div class="card-title">Euclidean Algorithm</div>
    <div class="formula">gcd(a, b) = gcd(b, a mod b)<br>Base case: gcd(a, 0) = a</div>
    <div class="card-body" style="margin-top:0.5rem;">
      Example: gcd(252, 198)<br>
      252 = 1·198 + 54 → gcd(198, 54)<br>
      198 = 3·54 + 36 → gcd(54, 36)<br>
      54 = 1·36 + 18 → gcd(36, 18)<br>
      36 = 2·18 + 0 → gcd = <strong style="color:var(--orange)">18</strong>
    </div>
  </div>

  <div class="accent-line"><span>Key Theorems</span></div>

  <div class="cards cards-2" style="margin-top:0;margin-bottom:1.5rem;">
    <div class="card">
      <div class="card-title">Fermat's Little Theorem</div>
      <div class="formula">a^p ≡ a (mod p)<br>If p∤a: a^(p-1) ≡ 1 (mod p)</div>
      <div class="card-body">p must be PRIME. Used for fast modular exponentiation in RSA encryption.<br>Example: 2^12 mod 13 = 2^(13-1) mod 13 = 1 mod 13 = 1</div>
    </div>
    <div class="card">
      <div class="card-title">Chinese Remainder Theorem</div>
      <div class="formula">System of x ≡ aᵢ (mod mᵢ)<br>has unique solution if all mᵢ pairwise coprime</div>
      <div class="card-body">gcd(mᵢ, mⱼ) = 1 for all i ≠ j ensures a unique solution modulo m₁·m₂···mₖ.</div>
    </div>
    <div class="card">
      <div class="card-title">Fundamental Theorem of Arithmetic</div>
      <div class="formula">Every n > 1 = p₁^a₁ · p₂^a₂ · ... · pₖ^aₖ</div>
      <div class="card-body">Every integer > 1 has a UNIQUE prime factorization. Basis for RSA: easy to multiply primes, computationally hard to factor the product.</div>
    </div>
    <div class="card">
      <div class="card-title">Modular Exponentiation</div>
      <div class="formula">a^n mod m<br>Use repeated squaring</div>
      <div class="card-body">To compute 3^10 mod 7:<br>3²=9≡2, 3⁴≡4, 3⁸≡2 (mod 7)<br>3^10 = 3^8 · 3^2 ≡ 2·2 = 4 (mod 7)</div>
    </div>
  </div>

  <!-- Modular Arithmetic Demo -->
  <div class="mod-demo">
    <h3>MODULAR ARITHMETIC CALCULATOR</h3>
    <div class="mod-inputs">
      <div style="display:flex;align-items:center;gap:8px;">
        <label>a =</label>
        <input type="number" id="mod-a" value="17">
      </div>
      <div style="display:flex;align-items:center;gap:8px;">
        <label>mod</label>
        <input type="number" id="mod-m" value="5">
      </div>
    </div>
    <div id="mod-result" class="mod-result"></div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 7: INDUCTION ========== -->
<section id="induction" class="reveal">
  <div class="section-header">
    <div class="section-num">07</div>
    <div><div class="section-title">MATHEMATICAL <span>INDUCTION</span></div></div>
  </div>

  <div class="accent-line"><span>The Three Flavors</span></div>

  <div class="cards cards-3" style="margin-bottom:2rem;">
    <div class="card">
      <div class="card-title">Weak Induction</div>
      <div class="formula">1. Prove P(1) [base case]<br>2. Prove P(k) → P(k+1)</div>
      <div class="card-body">The classic. Assume the statement holds for k, prove it holds for k+1. Most straightforward approach.</div>
    </div>
    <div class="card">
      <div class="card-title">Strong Induction</div>
      <div class="formula">1. Prove P(1)<br>2. Prove [P(1)∧...∧P(k)] → P(k+1)</div>
      <div class="card-body">Assume it holds for ALL values 1 through k. Stronger inductive hypothesis. Needed for Fibonacci, prime factorization proofs.</div>
    </div>
    <div class="card">
      <div class="card-title">Structural Induction</div>
      <div class="formula">1. Base: prove for initial set elements<br>2. Recursive: prove for new elements built from existing ones</div>
      <div class="card-body">For recursively defined structures (trees, strings, sets). The ASU formal paper topic — write every step in full sentences.</div>
    </div>
  </div>

  <!-- Induction Stepper -->
  <div class="induction-demo">
    <h3>STEP-THROUGH: WEAK INDUCTION PROOF</h3>
    <div class="induction-subtitle">Prove: 1+2+3+···+n = n(n+1)/2 for all n ≥ 1</div>

    <div class="ind-steps">
      <div class="ind-step active" onclick="activateStep(this)">
        <div class="ind-step-num">01</div>
        <div class="ind-step-content">
          <div class="ind-step-title">State the Proposition P(n)</div>
          <div class="ind-step-body">P(n): "1 + 2 + 3 + ··· + n = n(n+1)/2"<br><br>We want to prove this holds for every positive integer n ≥ 1.</div>
        </div>
      </div>
      <div class="ind-step" onclick="activateStep(this)">
        <div class="ind-step-num">02</div>
        <div class="ind-step-content">
          <div class="ind-step-title">Base Case: Prove P(1)</div>
          <div class="ind-step-body">LHS: 1<br>RHS: 1(1+1)/2 = 1(2)/2 = 1<br><br>LHS = RHS = 1. ✓ P(1) is true.</div>
        </div>
      </div>
      <div class="ind-step" onclick="activateStep(this)">
        <div class="ind-step-num">03</div>
        <div class="ind-step-content">
          <div class="ind-step-title">Inductive Hypothesis: Assume P(k)</div>
          <div class="ind-step-body">Assume P(k) is true for some integer k ≥ 1:<br><br>"1 + 2 + ··· + k = k(k+1)/2"<br><br>This is our assumption — we now use it to prove P(k+1).</div>
        </div>
      </div>
      <div class="ind-step" onclick="activateStep(this)">
        <div class="ind-step-num">04</div>
        <div class="ind-step-content">
          <div class="ind-step-title">Inductive Step: Prove P(k+1)</div>
          <div class="ind-step-body">We must show: 1+2+···+k+(k+1) = (k+1)(k+2)/2<br><br>LHS = [1+2+···+k] + (k+1)<br>     = k(k+1)/2 + (k+1)          ← by Inductive Hypothesis<br>     = (k+1)[k/2 + 1]<br>     = (k+1)(k+2)/2             ✓ This is exactly P(k+1)!</div>
        </div>
      </div>
      <div class="ind-step" onclick="activateStep(this)">
        <div class="ind-step-num">05</div>
        <div class="ind-step-content">
          <div class="ind-step-title">Conclusion</div>
          <div class="ind-step-body">By the Principle of Mathematical Induction, since P(1) is true and P(k) → P(k+1) for all k ≥ 1, we conclude that P(n) is true for all positive integers n. □</div>
        </div>
      </div>
    </div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 8: COUNTING ========== -->
<section id="counting" class="reveal">
  <div class="section-header">
    <div class="section-num">08</div>
    <div><div class="section-title">COMBINATORICS & <span>COUNTING</span></div></div>
  </div>

  <div class="accent-line"><span>Fundamental Principles</span></div>

  <div class="cards cards-2" style="margin-bottom:1.5rem;">
    <div class="card">
      <div class="card-title">Product Rule (AND)</div>
      <div class="formula">If task 1 has m ways<br>and task 2 has n ways<br>→ together: m × n ways</div>
      <div class="card-body">Passwords: 26 letters × 10 digits = 260 two-character combos</div>
    </div>
    <div class="card">
      <div class="card-title">Sum Rule (OR)</div>
      <div class="formula">If task can be done in m OR n ways<br>(disjoint sets)<br>→ total: m + n ways</div>
      <div class="card-body">Choose 1 item: 5 from box A OR 7 from box B = 12 choices</div>
    </div>
    <div class="card">
      <div class="card-title">Pigeonhole Principle</div>
      <div class="formula">n objects in k boxes<br>→ ∃ box with ≥ ⌈n/k⌉ objects</div>
      <div class="card-body">13 people → at least 2 share a birth month. Used to prove hash collision existence.</div>
    </div>
    <div class="card">
      <div class="card-title">Complement Counting</div>
      <div class="formula">|A| = |U| - |Ā|</div>
      <div class="card-body">Sometimes easier to count what you DON'T want, then subtract. "At least one" problems.</div>
    </div>
  </div>

  <div class="accent-line"><span>Permutations & Combinations</span></div>

  <table class="math-table">
    <thead>
      <tr><th>Type</th><th>Order Matters?</th><th>Formula</th><th>Example</th></tr>
    </thead>
    <tbody>
      <tr><td class="hl">Permutation P(n,r)</td><td>✓ YES</td><td class="hl">n! / (n-r)!</td><td>Arrange 3 from 5: P(5,3)=60</td></tr>
      <tr><td class="hl">Combination C(n,r)</td><td>✗ NO</td><td class="hl">n! / (r!(n-r)!)</td><td>Choose 3 from 5: C(5,3)=10</td></tr>
      <tr><td>Perm w/ Repetition</td><td>✓ YES</td><td>n^r</td><td>4-digit PIN: 10⁴=10,000</td></tr>
      <tr><td>Combo w/ Repetition</td><td>✗ NO</td><td>C(n+r-1, r)</td><td>Choose 2 flavors from 5 (repeats ok): C(6,2)=15</td></tr>
      <tr><td>Circular Permutation</td><td>✓ YES</td><td>(n-1)!</td><td>Seat 5 at round table: 4!=24</td></tr>
      <tr><td>Multinomial</td><td>✓ YES</td><td>n! / (n₁!n₂!···nₖ!)</td><td>Arrangements of MISSISSIPPI</td></tr>
    </tbody>
  </table>

  <div class="accent-line" style="margin-top:2rem;"><span>Binomial Theorem</span></div>

  <div class="card" style="margin-bottom:2rem;">
    <div class="card-title">Binomial Theorem</div>
    <div class="formula">(x + y)^n = Σ C(n,k) · x^(n-k) · y^k    for k=0 to n</div>
    <div class="card-body" style="margin-top:0.5rem;">
      The k-th term (from k=0): C(n,k) · x^(n-k) · y^k<br><br>
      Pascal's Identity: C(n+1, k) = C(n,k-1) + C(n,k)<br>
      Each entry in Pascal's Triangle = sum of two above it.
    </div>
  </div>

  <!-- Counting Calculator -->
  <div class="count-calc">
    <h3>COUNTING CALCULATOR</h3>
    <div class="calc-tabs">
      <button class="calc-tab active" onclick="setCalcMode('perm',this)">P(n,r)</button>
      <button class="calc-tab" onclick="setCalcMode('comb',this)">C(n,r)</button>
      <button class="calc-tab" onclick="setCalcMode('perm_rep',this)">n^r</button>
      <button class="calc-tab" onclick="setCalcMode('comb_rep',this)">C(n+r-1,r)</button>
      <button class="calc-tab" onclick="setCalcMode('factorial',this)">n!</button>
    </div>
    <div class="calc-inputs">
      <div class="field">
        <label>n =</label>
        <input type="number" id="calc-n" value="10" min="0" max="20">
      </div>
      <div class="field" id="calc-r-field">
        <label>r =</label>
        <input type="number" id="calc-r" value="3" min="0" max="20">
      </div>
    </div>
    <div class="calc-output" id="calc-output"></div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 9: RELATIONS & GRAPHS ========== -->
<section id="graphs" class="reveal">
  <div class="section-header">
    <div class="section-num">09</div>
    <div><div class="section-title">RELATIONS & <span>GRAPH THEORY</span></div></div>
  </div>

  <div class="accent-line"><span>Relation Properties</span></div>

  <table class="math-table" style="margin-bottom:2rem;">
    <thead>
      <tr><th>Property</th><th>Definition</th><th>Formal</th><th>Example on {1,2,3}</th></tr>
    </thead>
    <tbody>
      <tr><td class="hl">Reflexive</td><td>Every element relates to itself</td><td>∀x: (x,x) ∈ R</td><td>{(1,1),(2,2),(3,3),...}</td></tr>
      <tr><td class="hl">Symmetric</td><td>If aRb then bRa</td><td>∀x,y: (x,y)∈R → (y,x)∈R</td><td>If (1,2)∈R then (2,1)∈R</td></tr>
      <tr><td>Antisymmetric</td><td>If aRb and bRa, then a=b</td><td>(x,y)∈R ∧ (y,x)∈R → x=y</td><td>≤ is antisymmetric</td></tr>
      <tr><td>Transitive</td><td>If aRb and bRc then aRc</td><td>(x,y)∈R ∧ (y,z)∈R → (x,z)∈R</td><td>If (1,2),(2,3)∈R then (1,3)∈R</td></tr>
    </tbody>
  </table>

  <div class="cards cards-2" style="margin-bottom:2rem;">
    <div class="card">
      <div class="card-title">Equivalence Relation</div>
      <div class="formula">Reflexive + Symmetric + Transitive</div>
      <div class="card-body">Groups elements into disjoint EQUIVALENCE CLASSES that partition the set.<br>Example: ≡ (mod m), same birthday, same length strings.</div>
    </div>
    <div class="card">
      <div class="card-title">Partial Ordering (POSET)</div>
      <div class="formula">Reflexive + Antisymmetric + Transitive</div>
      <div class="card-body">Models hierarchies. Visualized as Hasse diagram.<br>Examples: ≤ on integers, ⊆ on sets, divisibility on N.</div>
    </div>
  </div>

  <div class="accent-line"><span>Graph Theory Fundamentals</span></div>

  <div class="cards cards-3" style="margin-bottom:2rem;">
    <div class="card">
      <div class="card-title">Graph G = (V, E)</div>
      <div class="formula">V = vertices (nodes)<br>E ⊆ V × V = edges</div>
      <div class="card-body">Undirected: edges are unordered pairs {u,v}<br>Directed: edges are ordered pairs (u,v)</div>
    </div>
    <div class="card">
      <div class="card-title">Degree & Handshaking</div>
      <div class="formula">Σ deg(v) = 2|E|</div>
      <div class="card-body">Sum of all vertex degrees = twice the number of edges. Corollary: number of odd-degree vertices is ALWAYS even.</div>
    </div>
    <div class="card">
      <div class="card-title">Euler vs Hamilton</div>
      <div class="formula">Euler: every EDGE once<br>Hamilton: every VERTEX once</div>
      <div class="card-body">Euler circuit exists ↔ connected + all even degrees. Hamilton path: NP-complete — no simple condition.</div>
    </div>
    <div class="card">
      <div class="card-title">Euler Circuit Condition</div>
      <div class="formula">Connected multigraph has<br>Euler circuit ↔<br>every vertex has even degree</div>
      <div class="card-body">Euler PATH (different endpoints): exactly 2 vertices of odd degree.</div>
    </div>
    <div class="card">
      <div class="card-title">Graph Isomorphism</div>
      <div class="formula">G₁ ≅ G₂ if ∃ bijection f: V₁→V₂<br>preserving adjacency</div>
      <div class="card-body">Same structure, possibly drawn differently. Check: same vertex count, edge count, degree sequence.</div>
    </div>
    <div class="card">
      <div class="card-title">Trees</div>
      <div class="formula">Connected graph with no cycles<br>|E| = |V| - 1</div>
      <div class="card-body">Any two vertices connected by exactly one path. Used in: file systems, decision trees, spanning trees, parse trees.</div>
    </div>
  </div>

  <!-- Graph Visualizer -->
  <div class="graph-container">
    <h3>INTERACTIVE GRAPH</h3>
    <div class="graph-info">Drag vertices to rearrange. Hover to highlight connections.</div>
    <canvas id="graph-canvas"></canvas>
    <div class="graph-stats">
      <div class="stat-box"><div class="stat-label">Vertices |V|</div><div class="stat-val" id="g-vertices">7</div></div>
      <div class="stat-box"><div class="stat-label">Edges |E|</div><div class="stat-val" id="g-edges">9</div></div>
      <div class="stat-box"><div class="stat-label">Σ degrees</div><div class="stat-val" id="g-degsum">18</div></div>
      <div class="stat-box"><div class="stat-label">Euler Circuit</div><div class="stat-val" id="g-euler">—</div></div>
      <div class="stat-box"><div class="stat-label">Max Degree</div><div class="stat-val" id="g-maxdeg">—</div></div>
    </div>
  </div>
</section>

<div class="divider"></div>

<!-- ========== SECTION 10: FORMULA REFERENCE ========== -->
<section id="formulas" class="reveal">
  <div class="section-header">
    <div class="section-num">10</div>
    <div><div class="section-title">MASTER FORMULA <span>REFERENCE</span></div></div>
  </div>

  <div class="formula-grid">
    <div class="formula-card">
      <div class="formula-cat">Logic</div>
      <div class="formula-name">Conditional Equivalence</div>
      <div class="formula-expr">p → q ≡ ¬p ∨ q</div>
      <div class="formula-note">Implication as disjunction. Useful for converting conditionals.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Logic</div>
      <div class="formula-name">Biconditional</div>
      <div class="formula-expr">p ↔ q ≡ (p→q) ∧ (q→p)</div>
      <div class="formula-note">p if and only if q. Both implications must hold.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Logic</div>
      <div class="formula-name">De Morgan #1</div>
      <div class="formula-expr">¬(p ∧ q) ≡ ¬p ∨ ¬q</div>
      <div class="formula-note">Negate AND → flip to OR with negations distributed.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Logic</div>
      <div class="formula-name">De Morgan #2</div>
      <div class="formula-expr">¬(p ∨ q) ≡ ¬p ∧ ¬q</div>
      <div class="formula-note">Negate OR → flip to AND with negations distributed.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Sets</div>
      <div class="formula-name">Inclusion-Exclusion (2)</div>
      <div class="formula-expr">|A ∪ B| = |A| + |B| - |A ∩ B|</div>
      <div class="formula-note">Subtract overlap to avoid counting twice.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Sets</div>
      <div class="formula-name">Power Set Size</div>
      <div class="formula-expr">|P(A)| = 2^|A|</div>
      <div class="formula-note">A set with n elements has 2ⁿ subsets (including ∅ and A itself).</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Counting</div>
      <div class="formula-name">Permutation</div>
      <div class="formula-expr">P(n,r) = n! / (n-r)!</div>
      <div class="formula-note">r items from n, ORDER matters. P(5,3) = 5·4·3 = 60</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Counting</div>
      <div class="formula-name">Combination</div>
      <div class="formula-expr">C(n,r) = n! / (r!(n-r)!)</div>
      <div class="formula-note">r items from n, order does NOT matter. C(5,3) = 10</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Counting</div>
      <div class="formula-name">Pascal's Identity</div>
      <div class="formula-expr">C(n+1,r) = C(n,r-1) + C(n,r)</div>
      <div class="formula-note">Foundation of Pascal's Triangle. Each entry = sum of two above.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Counting</div>
      <div class="formula-name">Binomial Theorem</div>
      <div class="formula-expr">(x+y)^n = Σ C(n,k) x^(n-k) y^k</div>
      <div class="formula-note">Sum from k=0 to n. Coefficient of x^(n-k)y^k is C(n,k).</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Number Theory</div>
      <div class="formula-name">Division Algorithm</div>
      <div class="formula-expr">a = d·q + r,  0 ≤ r &lt; d</div>
      <div class="formula-note">Unique q (quotient) and r (remainder) for any a, d>0.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Number Theory</div>
      <div class="formula-name">Euclidean Algorithm</div>
      <div class="formula-expr">gcd(a,b) = gcd(b, a mod b)</div>
      <div class="formula-note">Repeat until remainder = 0. gcd(a,0) = a.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Number Theory</div>
      <div class="formula-name">Fermat's Little Theorem</div>
      <div class="formula-expr">a^(p-1) ≡ 1 (mod p), if p∤a</div>
      <div class="formula-note">p must be prime. Key tool for fast modular exponentiation and RSA.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Graph Theory</div>
      <div class="formula-name">Handshaking Theorem</div>
      <div class="formula-expr">Σ deg(v) = 2|E|</div>
      <div class="formula-note">Sum of all degrees = 2× edge count. Always even.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Graph Theory</div>
      <div class="formula-name">Tree Edge Count</div>
      <div class="formula-expr">Tree on n vertices has n-1 edges</div>
      <div class="formula-note">Connected, acyclic. Adding any edge creates exactly one cycle.</div>
    </div>
    <div class="formula-card">
      <div class="formula-cat">Probability</div>
      <div class="formula-name">Bayes' Theorem</div>
      <div class="formula-expr">P(A|B) = P(B|A)·P(A) / P(B)</div>
      <div class="formula-note">Conditional probability inversion. Updates beliefs with evidence.</div>
    </div>
  </div>
</section>

<div style="height:80px;"></div>

<script>
// ===== SCROLL PROGRESS =====
window.addEventListener('scroll', () => {
  const pct = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
  document.getElementById('scrollLine').style.width = pct + '%';
});

// ===== NAV ACTIVE =====
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('nav a');

window.addEventListener('scroll', () => {
  let cur = '';
  sections.forEach(s => {
    if (window.scrollY >= s.offsetTop - 80) cur = s.id;
  });
  navLinks.forEach(a => {
    a.classList.toggle('active', a.getAttribute('href') === '#' + cur);
  });
});

// ===== REVEAL ON SCROLL =====
const reveals = document.querySelectorAll('.reveal');
const observer = new IntersectionObserver(entries => {
  entries.forEach(e => { if(e.isIntersecting) e.target.classList.add('visible'); });
}, { threshold: 0.08 });
reveals.forEach(r => observer.observe(r));

// ===== PROOF TOGGLE =====
function toggleProof(header) {
  const body = header.nextElementSibling;
  const arrow = header.querySelector('.proof-arrow');
  body.classList.toggle('open');
  arrow.classList.toggle('open');
}

// ===== INDUCTION STEPS =====
function activateStep(el) {
  document.querySelectorAll('.ind-step').forEach(s => s.classList.remove('active'));
  el.classList.add('active');
}

// ===== TRUTH TABLE =====
const formulaDefs = {
  AND: { header: ['p','q','p ∧ q'], fn: (p,q) => [p,q,p&&q] },
  OR:  { header: ['p','q','p ∨ q'], fn: (p,q) => [p,q,p||q] },
  XOR: { header: ['p','q','p ⊕ q'], fn: (p,q) => [p,q,p!==q] },
  IMP: { header: ['p','q','p → q'], fn: (p,q) => [p,q,!p||q] },
  BICON: { header: ['p','q','p ↔ q'], fn: (p,q) => [p,q,p===q] },
  DEMORGAN1: { header: ['p','q','p ∧ q','¬(p ∧ q)'], fn: (p,q) => [p,q,p&&q,!(p&&q)] },
  DEMORGAN2: { header: ['p','q','¬p','¬q','¬p ∨ ¬q'], fn: (p,q) => [p,q,!p,!q,(!p)||(!q)] },
  CONTRA: { header: ['p','q','p→q','¬q→¬p','≡?'], fn: (p,q) => {
    const orig = !p||q; const contra = !(!q)||(!p); // ¬q→¬p = q || ¬p
    const contra2 = q||(!p);
    return [p,q,orig,contra2, orig===contra2];
  }},
  '3VAR': { header: ['p','q','r','p→q','q→r','(p→q)∧(q→r)','p→r'], fn: (p,q,r) => {
    const pq=!p||q, qr=!q||r, pr=!p||r;
    return [p,q,r,pq,qr,pq&&qr,pr];
  }}
};

let currentFormula = 'AND';

function buildTruthTable(key) {
  currentFormula = key;
  const def = formulaDefs[key];
  const threeVar = def.fn.length === 3;
  const rows = threeVar ?
    [[T,T,T],[T,T,F],[T,F,T],[T,F,F],[F,T,T],[F,T,F],[F,F,T],[F,F,F]] :
    [[true,true],[true,false],[false,true],[false,false]];

  function T(x){ return x; }

  let html = '<table class="math-table"><thead><tr>';
  def.header.forEach((h,i) => {
    const isResult = i === def.header.length - 1;
    html += `<th${isResult?' style="color:#ff6200;"':''}>${h}</th>`;
  });
  html += '</tr></thead><tbody>';

  rows.forEach(row => {
    const vals = threeVar ? def.fn(row[0],row[1],row[2]) : def.fn(row[0],row[1]);
    html += '<tr>';
    vals.forEach((v,i) => {
      const isResult = i === vals.length - 1;
      const bool = (v === true || v === false) ? (v ? 'T' : 'F') : (v ? 'T' : 'F');
      const cls = isResult ? (v ? 'hl' : 'dim') : '';
      html += `<td class="${cls}" style="font-family:var(--mono);text-align:center;">${bool}</td>`;
    });
    html += '</tr>';
  });

  html += '</tbody></table>';
  document.getElementById('truth-output').innerHTML = html;
}

document.querySelectorAll('#formulaSelect .formula-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('#formulaSelect .formula-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    buildTruthTable(btn.dataset.formula);
  });
});

buildTruthTable('AND');

// ===== VENN DIAGRAM =====
const vennDescriptions = {
  union: 'A ∪ B — all elements in A or B (or both)',
  intersect: 'A ∩ B — only elements in BOTH A and B',
  diff_ab: 'A − B — elements in A but NOT in B',
  diff_ba: 'B − A — elements in B but NOT in A',
  comp_a: 'Ā — everything in the universe NOT in A',
  sym_diff: 'A ⊕ B — elements in exactly one of A or B'
};

function setVenn(op, btn) {
  document.querySelectorAll('.venn-ops .formula-btn').forEach(b => b.classList.remove('active'));
  if(btn) btn.classList.add('active');

  const orange = '#ff6200';
  const orangeLight = 'rgba(255,98,0,0.35)';
  const grey = 'rgba(136,136,136,0.3)';
  const none = 'none';

  const left = document.getElementById('venn-left');
  const right = document.getElementById('venn-right');
  const interA = document.getElementById('venn-inter-a');
  const interB = document.getElementById('venn-inter-b');
  const svg = document.getElementById('venn-svg');

  // Reset
  [left,right,interA,interB].forEach(el => el.setAttribute('fill','none'));

  // Remove old universe rect highlight
  let ur = document.getElementById('venn-universe-hl');
  if(ur) ur.remove();

  switch(op) {
    case 'union':
      left.setAttribute('fill', orangeLight);
      right.setAttribute('fill', orangeLight);
      interA.setAttribute('fill', orange);
      interB.setAttribute('fill', orange);
      break;
    case 'intersect':
      interA.setAttribute('fill', orange);
      interB.setAttribute('fill', orange);
      break;
    case 'diff_ab':
      left.setAttribute('fill', orangeLight);
      // Remove intersection
      interA.setAttribute('fill', '#0e0e0e');
      interB.setAttribute('fill', '#0e0e0e');
      break;
    case 'diff_ba':
      right.setAttribute('fill', orangeLight);
      interA.setAttribute('fill', '#0e0e0e');
      interB.setAttribute('fill', '#0e0e0e');
      break;
    case 'comp_a':
      // Highlight everything except A
      // Draw filled rect + mask
      const ur2 = document.createElementNS('http://www.w3.org/2000/svg','rect');
      ur2.setAttribute('id','venn-universe-hl');
      ur2.setAttribute('x','10');ur2.setAttribute('y','10');
      ur2.setAttribute('width','380');ur2.setAttribute('height','180');
      ur2.setAttribute('fill','rgba(255,98,0,0.2)');ur2.setAttribute('rx','4');
      svg.insertBefore(ur2, svg.firstChild.nextSibling.nextSibling);
      left.setAttribute('fill','#080808');
      break;
    case 'sym_diff':
      left.setAttribute('fill', orangeLight);
      right.setAttribute('fill', orangeLight);
      interA.setAttribute('fill', '#080808');
      interB.setAttribute('fill', '#080808');
      break;
  }

  document.getElementById('venn-desc').textContent = vennDescriptions[op] || '';
}

setVenn('union', null);

// ===== BIG-O CHART =====
(function() {
  const canvas = document.getElementById('bigo-canvas');
  const ctx = canvas.getContext('2d');

  const classes = [
    { label: 'O(1)',       color: '#44ff88', fn: n => 1,              hidden: false },
    { label: 'O(log n)',   color: '#88ffff', fn: n => Math.log2(n),   hidden: false },
    { label: 'O(n)',       color: '#ffcc44', fn: n => n,              hidden: false },
    { label: 'O(n log n)', color: '#ff8844', fn: n => n*Math.log2(n), hidden: false },
    { label: 'O(n²)',      color: '#ff6200', fn: n => n*n,            hidden: false },
    { label: 'O(2ⁿ)',      color: '#ff4444', fn: n => Math.pow(2,n),  hidden: false },
  ];

  function draw() {
    const W = canvas.width = canvas.offsetWidth;
    const H = canvas.height = canvas.offsetHeight || 300;
    ctx.clearRect(0,0,W,H);

    const pad = {top:20, right:20, bottom:30, left:40};
    const plotW = W - pad.left - pad.right;
    const plotH = H - pad.top - pad.bottom;
    const maxN = 20;
    const maxY = 200;

    // Grid
    ctx.strokeStyle = 'rgba(255,255,255,0.05)';
    ctx.lineWidth = 1;
    for(let i=0;i<=5;i++){
      const y = pad.top + plotH - (i/5)*plotH;
      ctx.beginPath(); ctx.moveTo(pad.left,y); ctx.lineTo(pad.left+plotW,y); ctx.stroke();
    }
    for(let i=0;i<=10;i++){
      const x = pad.left + (i/10)*plotW;
      ctx.beginPath(); ctx.moveTo(x,pad.top); ctx.lineTo(x,pad.top+plotH); ctx.stroke();
    }

    // Axes
    ctx.strokeStyle = '#444';
    ctx.lineWidth = 1.5;
    ctx.beginPath(); ctx.moveTo(pad.left,pad.top); ctx.lineTo(pad.left,pad.top+plotH); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(pad.left,pad.top+plotH); ctx.lineTo(pad.left+plotW,pad.top+plotH); ctx.stroke();

    // Axis labels
    ctx.fillStyle = '#666'; ctx.font = '10px IBM Plex Mono';
    ctx.fillText('n', pad.left+plotW+4, pad.top+plotH+4);
    ctx.fillText('f(n)', pad.left-30, pad.top+10);

    // Lines
    classes.forEach(cls => {
      if(cls.hidden) return;
      ctx.strokeStyle = cls.color;
      ctx.lineWidth = 2;
      ctx.beginPath();
      let first = true;
      for(let i=0; i<=100; i++) {
        const n = (i/100)*maxN;
        if(n <= 0) continue;
        const y_val = cls.fn(n);
        const x = pad.left + (n/maxN)*plotW;
        const y = pad.top + plotH - Math.min(y_val/maxY,1)*plotH;
        if(first){ ctx.moveTo(x,y); first=false; } else ctx.lineTo(x,y);
      }
      ctx.stroke();
    });
  }

  // Legend
  const legend = document.getElementById('bigoLegend');
  classes.forEach((cls, i) => {
    const item = document.createElement('div');
    item.className = 'legend-item';
    item.innerHTML = `<div class="legend-dot" style="background:${cls.color}"></div><span>${cls.label}</span>`;
    item.addEventListener('click', () => {
      cls.hidden = !cls.hidden;
      item.classList.toggle('hidden');
      draw();
    });
    legend.appendChild(item);
  });

  draw();
  window.addEventListener('resize', draw);
})();

// ===== MODULAR ARITHMETIC =====
function updateMod() {
  const a = parseInt(document.getElementById('mod-a').value) || 0;
  const m = parseInt(document.getElementById('mod-m').value) || 1;
  const r = ((a % m) + m) % m;
  const q = Math.floor(a / m);
  document.getElementById('mod-result').innerHTML =
    `${a} = ${m} × ${q} + ${r}<br><br>` +
    `<span style="color:var(--orange)">${a} mod ${m} = ${r}</span><br><br>` +
    `${a} ≡ ${r} (mod ${m})<br>` +
    (a >= 0 ? `${a} and ${r} have the same remainder when divided by ${m}` :
    `Note: We use ((a % m) + m) % m to handle negative a in code`);
}

document.getElementById('mod-a').addEventListener('input', updateMod);
document.getElementById('mod-m').addEventListener('input', updateMod);
updateMod();

// ===== COUNTING CALCULATOR =====
let calcMode = 'perm';

function factorial(n) {
  if(n < 0) return NaN;
  if(n === 0) return 1;
  let r = 1; for(let i=2;i<=n;i++) r *= i;
  return r;
}

function bigFactorial(n) {
  if(n > 20) return n + '! (too large to display exactly)';
  return factorial(n);
}

function setCalcMode(mode, btn) {
  calcMode = mode;
  document.querySelectorAll('.calc-tab').forEach(b => b.classList.remove('active'));
  if(btn) btn.classList.add('active');
  const rField = document.getElementById('calc-r-field');
  rField.style.display = (mode === 'factorial') ? 'none' : 'flex';
  updateCalc();
}

function updateCalc() {
  const n = parseInt(document.getElementById('calc-n').value) || 0;
  const r = parseInt(document.getElementById('calc-r').value) || 0;
  const out = document.getElementById('calc-output');
  let result, formula, note;

  switch(calcMode) {
    case 'perm':
      if(r > n){ out.innerHTML='<span style="color:#ff4444;">Error: r cannot exceed n</span>'; return; }
      result = factorial(n)/factorial(n-r);
      formula = `P(${n},${r}) = ${n}! / (${n}-${r})! = ${n}! / ${n-r}!`;
      note = `Order matters — number of ways to arrange ${r} items from ${n}`;
      break;
    case 'comb':
      if(r > n){ out.innerHTML='<span style="color:#ff4444;">Error: r cannot exceed n</span>'; return; }
      result = factorial(n)/(factorial(r)*factorial(n-r));
      formula = `C(${n},${r}) = ${n}! / (${r}! × ${n-r}!) `;
      note = `Order does NOT matter — number of ways to choose ${r} from ${n}`;
      break;
    case 'perm_rep':
      result = Math.pow(n,r);
      formula = `${n}^${r}`;
      note = `Arrangements of ${r} items from ${n} with repetition allowed`;
      break;
    case 'comb_rep':
      result = factorial(n+r-1)/(factorial(r)*factorial(n-1));
      formula = `C(${n}+${r}-1, ${r}) = C(${n+r-1},${r})`;
      note = `Choose ${r} from ${n} types, repetition allowed (multiset)`;
      break;
    case 'factorial':
      result = n > 20 ? '> 2.4×10¹⁸' : factorial(n);
      formula = `${n}!`;
      note = `Product of all positive integers up to ${n}`;
      break;
  }

  out.innerHTML = `
    <span class="calc-result-big">${typeof result === 'number' ? result.toLocaleString() : result}</span>
    <span style="color:var(--grey);font-size:0.78rem;">${formula}</span><br>
    <span style="color:var(--grey-dim);font-size:0.75rem;font-family:var(--sans);">${note}</span>
  `;
}

document.getElementById('calc-n').addEventListener('input', updateCalc);
document.getElementById('calc-r').addEventListener('input', updateCalc);
updateCalc();

// ===== GRAPH VISUALIZER =====
(function() {
  const canvas = document.getElementById('graph-canvas');
  const ctx = canvas.getContext('2d');

  const nodes = [
    {id:0, label:'A', x:0.5, y:0.2},
    {id:1, label:'B', x:0.2, y:0.5},
    {id:2, label:'C', x:0.8, y:0.5},
    {id:3, label:'D', x:0.35, y:0.8},
    {id:4, label:'E', x:0.65, y:0.8},
    {id:5, label:'F', x:0.12, y:0.25},
    {id:6, label:'G', x:0.88, y:0.25},
  ];

  const edges = [
    [0,1],[0,2],[0,5],[0,6],
    [1,3],[1,5],[2,4],[2,6],
    [3,4]
  ];

  let dragging = null;
  let hovered = null;
  let W, H;

  function getPos(n) { return {x: n.x * W, y: n.y * H}; }

  function draw() {
    W = canvas.width = canvas.offsetWidth;
    H = canvas.height = canvas.offsetHeight || 280;
    ctx.clearRect(0,0,W,H);

    // Compute degrees
    const deg = new Array(nodes.length).fill(0);
    edges.forEach(([a,b]) => { deg[a]++; deg[b]++; });

    // Edges
    edges.forEach(([a,b]) => {
      const pa = getPos(nodes[a]);
      const pb = getPos(nodes[b]);
      const isHover = (hovered === a || hovered === b);
      ctx.strokeStyle = isHover ? '#ff6200' : '#333';
      ctx.lineWidth = isHover ? 2 : 1.5;
      ctx.beginPath();
      ctx.moveTo(pa.x, pa.y);
      ctx.lineTo(pb.x, pb.y);
      ctx.stroke();
    });

    // Nodes
    nodes.forEach((n,i) => {
      const p = getPos(n);
      const isHover = (hovered === i);
      const isDrag = (dragging === i);

      ctx.beginPath();
      ctx.arc(p.x, p.y, isDrag ? 14 : 12, 0, Math.PI*2);
      ctx.fillStyle = isHover ? '#ff6200' : (isDrag ? '#c44d00' : '#1c1c1c');
      ctx.fill();
      ctx.strokeStyle = isHover ? '#ff6200' : '#555';
      ctx.lineWidth = isHover ? 2 : 1.5;
      ctx.stroke();

      ctx.fillStyle = isHover ? '#000' : '#f0f0f0';
      ctx.font = `bold 11px IBM Plex Mono`;
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(n.label, p.x, p.y);

      // Degree label
      ctx.fillStyle = '#666';
      ctx.font = '9px IBM Plex Mono';
      ctx.fillText('d=' + deg[i], p.x, p.y + 20);
    });

    // Stats
    const maxDeg = Math.max(...deg);
    const degSum = deg.reduce((a,b)=>a+b,0);
    const allEven = deg.every(d => d%2===0);
    document.getElementById('g-vertices').textContent = nodes.length;
    document.getElementById('g-edges').textContent = edges.length;
    document.getElementById('g-degsum').textContent = degSum + ' = 2×' + edges.length;
    document.getElementById('g-euler').textContent = allEven ? '✓ YES' : '✗ NO';
    document.getElementById('g-euler').style.color = allEven ? '#44ff88' : '#ff4444';
    document.getElementById('g-maxdeg').textContent = maxDeg;
  }

  function getHit(x, y) {
    for(let i=nodes.length-1;i>=0;i--) {
      const p = getPos(nodes[i]);
      const dx = x-p.x, dy = y-p.y;
      if(dx*dx+dy*dy < 200) return i;
    }
    return null;
  }

  function evtPos(e) {
    const rect = canvas.getBoundingClientRect();
    const touch = e.touches ? e.touches[0] : e;
    return { x: touch.clientX - rect.left, y: touch.clientY - rect.top };
  }

  canvas.addEventListener('mousedown', e => {
    const p = evtPos(e);
    dragging = getHit(p.x, p.y);
  });

  canvas.addEventListener('mousemove', e => {
    const p = evtPos(e);
    if(dragging !== null) {
      nodes[dragging].x = Math.max(0.05, Math.min(0.95, p.x/W));
      nodes[dragging].y = Math.max(0.05, Math.min(0.95, p.y/H));
      draw();
    } else {
      const h = getHit(p.x, p.y);
      if(h !== hovered) { hovered = h; draw(); }
    }
  });

  canvas.addEventListener('mouseup', () => { dragging = null; });
  canvas.addEventListener('mouseleave', () => { dragging=null; hovered=null; draw(); });

  draw();
  window.addEventListener('resize', draw);
})();
</script>
</body>
</html>