fuzzyworld

dm / commit

feat: expand data, add abilities sidebar, setting-filtered foci, quick actions

1b8688e1ddda36512521be835b7197d6ac8c9167 · Pavel Safronov · 2026-05-27 22:43:39 -0700 · parents eabebeeab822

feat: expand data, add abilities sidebar, setting-filtered foci, quick actions

Data expansion:
- DESCRIPTORS: 20 → 34 entries (added Appealing, Brash, Calm, Charming,
  Creative, Empathic, Impulsive, Kind, Learned, Loyal, Rugged, Swift,
  Vicious, Virtuous)
- FOCI: 20 → 69 entries, each tagged with settings array; focus grid
  rebuilds when setting changes, showing only genre-appropriate foci
  (Fantasy: 59, Numenera: 67, Sci-Fi: 56, Modern: 43)

Type starting abilities:
- Each Type gets 3–4 Tier 1 abilities in new startingAbilities field
- Abilities populated into character.abilities on game start
- New Abilities sidebar section renders name, cost, and description

Quick actions updated to Cypher System flavour:
  Assess / Recovery roll / Check gear / Search / Talk

Phase 5 (skill system) documented in plan.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
 plan.md           |  38 +++++++++++
 public/index.html | 198 ++++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 202 insertions(+), 34 deletions(-)

diff --git a/plan.md b/plan.md
index ab7219f..f318048 100644
--- a/plan.md
+++ b/plan.md
@@ -175,9 +175,47 @@ Cypher System is genre-neutral. Offer a setting choice at creation that adjusts
 
 ---
 
+---
+
+## Phase 5 — Skill system
+
+The `skills` array already exists in `gameState.character` as `[{ name, rank: 'trained'|'specialized'|'inability' }]` but nothing populates or displays it yet. Claude knows about skills in the system prompt (trained = difficulty −1, specialized = −2, inability = +1) but the player has no visibility or control.
+
+### 5a — Display
+
+- [ ] New "Skills" section in the sidebar (between Abilities and Equipment)
+- [ ] Each skill shows name + rank badge: green "Trained" / gold "Specialized" / red "Inability"
+- [ ] Empty state: "No skills yet"
+
+### 5b — Type and Descriptor starting skills
+
+Several Type Tier 1 abilities grant skill training ("Physical Skills", "Interaction Skills", "Danger Sense", etc.) but currently these are stored as narrative text in `abilities`, not as actual entries in `skills`. Fix by:
+
+- [ ] Add a `startingSkills` field to each Type (parallel to `startingAbilities`)
+- [ ] Add `descriptorSkills` field to each Descriptor for their trained skills
+- [ ] Populate `character.skills` from both in `beginAdventure()`
+
+### 5c — Skill advancement
+
+The XP advancement path ("train a skill") is currently only narrated. To make it mechanical:
+
+- [ ] Add a "Train a Skill" option to the Spend 4 XP flow — prompts for skill name, adds it as trained
+- [ ] Allow upgrading trained → specialized for another advancement step
+- [ ] Specialization cap at 2 levels; inability cannot be trained away (only reduced to trained via advancement)
+
+### 5d — Skill lookup in task resolution
+
+When a player's message mentions an action, Claude already references skills in its narration. Future enhancement:
+
+- [ ] Pass `character.skills` in the system prompt so Claude can cite which skills apply to a given roll
+- [ ] Expose "I am trained in X" as a quick action or structured input so the player can assert relevant skills before rolling
+
+---
+
 ## Notes
 
 - Phases 1–2 land together (one `SAVE_VERSION` bump to 2) — they're too intertwined to separate safely
 - Phase 3 can ship independently after Phase 2 (UI only, no `gameState` shape change)
 - Phase 4 is cosmetic and can go in any order
+- Phase 5 requires a `SAVE_VERSION` bump when 5b lands (new `startingSkills` field changes character shape)
 - The CSRD is available at [cypher-srd.com](https://cypher-srd.com) for rules reference
diff --git a/public/index.html b/public/index.html
index 5242711..e7c8ade 100644
--- a/public/index.html
+++ b/public/index.html
@@ -616,6 +616,12 @@ body {
 .cypher-use-btn:hover { border-color: var(--gold-dim); color: var(--gold); }
 .cypher-limit-warn { color: #d97706; font-size: 0.72rem; }
 
+/* Abilities section */
+.ability-entry { border: 1px solid var(--border); border-radius: 5px; padding: 6px 9px; margin-bottom: 5px; background: var(--bg-card); }
+.ability-name { display:block; font-family:'Cinzel',serif; font-size:0.68rem; color:var(--gold-light); margin-bottom:2px; }
+.ability-cost { color:var(--text-dim); font-weight:400; }
+.ability-desc { display:block; font-size:0.75rem; color:var(--text-dim); line-height:1.4; }
+
 /* Advancement row */
 .adv-row { display:flex; align-items:center; gap:8px; margin:4px 0 6px; flex-wrap:wrap; }
 .adv-dots { display:flex; gap:4px; }
@@ -1302,11 +1308,11 @@ body {
     <div id="messages"></div>
 
     <div class="quick-actions" id="quick-actions">
-      <button class="quick-btn" data-action="I look around carefully, taking stock of my surroundings.">👁 Look around</button>
-      <button class="quick-btn" data-action="I find a safe spot to rest and recover my strength.">🛌 Rest & recover</button>
-      <button class="quick-btn" data-action="I check my inventory and equipment.">🎒 Check inventory</button>
-      <button class="quick-btn" data-action="I carefully search the area for traps or hidden dangers.">🔍 Search for traps</button>
-      <button class="quick-btn" data-action="I approach the nearest person and try to start a conversation.">💬 Talk to NPC</button>
+      <button class="quick-btn" data-action="I take a moment to assess the situation — scanning for threats, opportunities, and anything unusual.">👁 Assess</button>
+      <button class="quick-btn" data-action="I take a recovery roll to restore my pools. Please narrate a brief rest and tell me which pool benefits most.">🎲 Recovery roll</button>
+      <button class="quick-btn" data-action="I check my equipment and cyphers, taking stock of what I have available.">🎒 Check gear</button>
+      <button class="quick-btn" data-action="I carefully search the area for hidden things — secrets, traps, valuables, or clues.">🔍 Search</button>
+      <button class="quick-btn" data-action="I try to talk my way through this — using whatever approach seems most likely to work.">💬 Talk</button>
     </div>
 
     <div class="input-area">
@@ -1377,6 +1383,12 @@ body {
       <div id="cyphers-list"><span style="font-size:0.78rem;color:var(--text-dim);font-style:italic">No cyphers yet.</span></div>
     </div>
 
+    <!-- Abilities -->
+    <div class="sidebar-section">
+      <div class="sidebar-title">Abilities</div>
+      <div id="abilities-list"></div>
+    </div>
+
     <!-- Equipment -->
     <div class="sidebar-section">
       <div class="sidebar-title">Equipment</div>
@@ -1720,71 +1732,158 @@ const TYPES = [
     edge:  { might: 1,  speed: 0,  intellect: 0 },
     cypherLimit: 2,
     note: 'Practiced with all weapons. Might Edge 1.',
-    equipment: ['Weapon of choice', 'Light armor', "Explorer's pack", 'Moderate-priced item'] },
+    equipment: ['Weapon of choice', 'Light armor', "Explorer's pack", 'Moderate-priced item'],
+    startingAbilities: [
+      { name: 'Practiced with All Weapons', cost: null, description: 'You can use any weapon without penalty.' },
+      { name: 'Physical Skills', cost: null, description: 'Trained in two physical skills of your choice (e.g. climbing, swimming, jumping, running).' },
+      { name: 'Bash', cost: '1 Might', description: 'Your attack inflicts 2 additional points of damage.' },
+    ] },
   { name: 'Adept', icon: '🔮',
     pools: { might: 7, speed: 9, intellect: 12 },
     edge:  { might: 0, speed: 0,  intellect: 1 },
     cypherLimit: 3,
     note: 'Masters esoteries (special abilities). Intellect Edge 1. Cypher Limit 3.',
-    equipment: ['Clothing', 'Book of lore', 'Two expensive items', 'Moderate-priced item'] },
+    equipment: ['Clothing', 'Book of lore', 'Two expensive items', 'Moderate-priced item'],
+    startingAbilities: [
+      { name: 'Practiced with Light Weapons', cost: null, description: 'You can use light weapons without penalty.' },
+      { name: 'Magical Training', cost: null, description: 'Trained in all esoteries as if they were skills.' },
+      { name: 'Hedge Magic', cost: '1 Intellect', description: 'Perform a minor magical trick — small light, move a tiny object, clean something, etc.' },
+      { name: 'Ward', cost: null, description: 'A constant magical field grants you +1 Armor at all times.' },
+    ] },
   { name: 'Explorer', icon: '🧭',
     pools: { might: 10, speed: 9, intellect: 9 },
     edge:  { might: 1,  speed: 0,  intellect: 0 },
     cypherLimit: 2,
     note: 'Balanced adventurer; light/medium weapons. Might Edge 1.',
-    equipment: ['Weapon of choice', 'Light armor', 'Exploration gear', 'Moderate-priced item'] },
+    equipment: ['Weapon of choice', 'Light armor', 'Exploration gear', 'Moderate-priced item'],
+    startingAbilities: [
+      { name: 'Practiced with Light and Medium Weapons', cost: null, description: 'You can use light and medium weapons without penalty.' },
+      { name: 'Practiced in Armor', cost: null, description: 'Wear light armor without any Speed Effort cost.' },
+      { name: 'Danger Sense', cost: null, description: 'Your initiative tasks are eased.' },
+      { name: 'Physical Skills', cost: null, description: 'Trained in two physical skills of your choice.' },
+    ] },
   { name: 'Speaker', icon: '🗣️',
     pools: { might: 8, speed: 9, intellect: 11 },
     edge:  { might: 0, speed: 0,  intellect: 1 },
     cypherLimit: 2,
     note: 'Social and deceptive abilities. Intellect Edge 1.',
-    equipment: ['Light weapon', 'Stylish clothing', 'Two expensive items', 'Moderate-priced item'] },
+    equipment: ['Light weapon', 'Stylish clothing', 'Two expensive items', 'Moderate-priced item'],
+    startingAbilities: [
+      { name: 'Practiced with Light Weapons', cost: null, description: 'You can use light weapons without penalty.' },
+      { name: 'Spin Identity', cost: '2+ Intellect', description: 'Convince others you are someone you are not; lasts the duration of the interaction.' },
+      { name: 'Interaction Skills', cost: null, description: 'Trained in deception, persuasion, and intimidation.' },
+      { name: 'Babel', cost: null, description: 'After listening to any spoken language briefly, you can understand it and make yourself understood.' },
+    ] },
 ];
 
 const DESCRIPTORS = [
+  { name: 'Appealing',    icon: '😊', poolBonus: { speed: 2 },     note: 'Your presence puts others at ease. Trained in pleasant social interactions.' },
+  { name: 'Brash',        icon: '😤', poolBonus: { speed: 2 },     note: 'Act first, think later. Trained in initiative; +2 Speed pool.' },
+  { name: 'Calm',         icon: '🧘', poolBonus: { intellect: 2 }, note: 'Unshakeable under pressure. Trained in resisting persuasion and panic.' },
+  { name: 'Charming',     icon: '💫', poolBonus: { intellect: 2 }, note: 'Hard to dislike and easy to trust. Trained in persuasion and performance.' },
   { name: 'Clever',       icon: '🧠', poolBonus: { intellect: 2 }, note: 'Skilled at lies, trickery, and assessing danger.' },
+  { name: 'Creative',     icon: '🎨', poolBonus: { intellect: 2 }, note: 'Finds unexpected solutions. Trained in all creative tasks (art, music, writing).' },
+  { name: 'Empathic',     icon: '💗', poolBonus: { intellect: 2 }, note: 'Reads emotional states with ease. Trained in sensing motives and first-aid.' },
   { name: 'Fast',         icon: '💨', poolBonus: { speed: 2 },     note: 'Can move and act in the same round.' },
   { name: 'Graceful',     icon: '🌸', poolBonus: { speed: 2 },     note: 'Trained in balance, performance, and Speed defense.' },
-  { name: 'Hardy',        icon: '🪨', poolBonus: { might: 4 },     note: 'Functions one step better on damage track.' },
+  { name: 'Hardy',        icon: '🪨', poolBonus: { might: 4 },     note: 'Functions one step better on the damage track.' },
   { name: 'Honorable',    icon: '🛡️', poolBonus: { might: 2 },     note: 'Trained in pleasant social interactions and detecting lies.' },
+  { name: 'Impulsive',    icon: '⚡', poolBonus: { speed: 2 },     note: 'You go first and think later. Trained in initiative and Speed defense.' },
   { name: 'Inquisitive',  icon: '🔍', poolBonus: { intellect: 4 }, note: 'Trained in learning, geography, and history.' },
   { name: 'Intelligent',  icon: '📚', poolBonus: { intellect: 2 }, note: 'Trained in one knowledge area and memorization.' },
   { name: 'Intuitive',    icon: '✨', poolBonus: { intellect: 2 }, note: 'Trained in perception; can act out of turn once per cycle.' },
+  { name: 'Kind',         icon: '🕊️', poolBonus: { intellect: 2 }, note: 'Genuine warmth that opens doors. Trained in healing and social tasks.' },
+  { name: 'Learned',      icon: '🎓', poolBonus: { intellect: 4 }, note: 'A walking library. Trained in two knowledge areas of your choice.' },
+  { name: 'Loyal',        icon: '🤝', poolBonus: { might: 2 },     note: 'Your allies inspire you. Trained in tasks that help companions directly.' },
   { name: 'Lucky',        icon: '🍀', poolBonus: {},               note: 'Gains a 3-point Luck Pool; bonuses to rerolls.' },
   { name: 'Mighty',       icon: '💪', poolBonus: { might: 4 },     note: 'Trained in lifting/throwing; +1 to recovery rolls.' },
   { name: 'Mysterious',   icon: '🌑', poolBonus: {},               note: 'Trained in stealth and resisting interrogation.' },
   { name: 'Mystical',     icon: '🌙', poolBonus: { intellect: 2 }, note: 'Can detect and cast minor magic; trained in the supernatural.' },
   { name: 'Perceptive',   icon: '👁️', poolBonus: { intellect: 2 }, note: 'Trained in noticing details and recalling trivia.' },
   { name: 'Resilient',    icon: '🌳', poolBonus: { might: 2, intellect: 2 }, note: 'Trained in both Might and Intellect defense; extra recovery roll.' },
-  { name: 'Sharp-Eyed',   icon: '🦅', poolBonus: {},               note: 'Trained in initiative and perception; can find foe weaknesses.' },
+  { name: 'Rugged',       icon: '🏔️', poolBonus: { might: 2, speed: 2 }, note: 'Built for hard conditions. Light armor without penalties; trained in navigation.' },
+  { name: 'Sharp-Eyed',   icon: '🦅', poolBonus: {},               note: 'Trained in initiative and perception; can spot a foe\'s weakness.' },
   { name: 'Stealthy',     icon: '🌫️', poolBonus: { speed: 2 },     note: 'Trained in stealth, trickery, and illusions.' },
   { name: 'Strong',       icon: '🪓', poolBonus: { might: 4 },     note: 'Trained in breaking objects and jumping.' },
   { name: 'Strong-Willed',icon: '🔮', poolBonus: { intellect: 4 }, note: 'Trained in resisting mental effects and concentration.' },
+  { name: 'Swift',        icon: '🐆', poolBonus: { speed: 4 },     note: 'Trained in running and escape; movement is never restricted.' },
   { name: 'Tough',        icon: '🦾', poolBonus: { might: 2 },     note: '+1 Armor; +1 to recovery rolls.' },
+  { name: 'Vicious',      icon: '🩸', poolBonus: { might: 2 },     note: 'You fight to hurt. Attacks deal 1 additional point of damage.' },
+  { name: 'Virtuous',     icon: '⭐', poolBonus: { intellect: 2 }, note: 'Trained in resisting temptation and corruption; allies trust you deeply.' },
   { name: 'Weird',        icon: '🌀', poolBonus: { intellect: 2 }, note: 'Trained in supernatural knowledge; senses nearby strange phenomena.' },
 ];
 
+// settings: which genres this focus fits. 'all' = any setting.
 const FOCI = [
-  { name: 'Controls Beasts',        icon: '🦁', playstyle: 'Communicate with and command animals.' },
-  { name: 'Crafts Illusions',       icon: '🎭', playstyle: 'Fashion images from light so real they deceive all senses.' },
-  { name: 'Crafts Unique Objects',  icon: '⚙️', playstyle: 'Inventor of strange gadgets, gear, and contraptions.' },
-  { name: 'Explores Dark Places',   icon: '🕯️', playstyle: 'Treasure hunter and scavenger of lost and forgotten things.' },
-  { name: 'Fights With Panache',    icon: '🎪', playstyle: 'Swashbuckling daredevil who wins through flamboyant style.' },
-  { name: 'Howls at the Moon',      icon: '🐺', playstyle: 'Transforms into a fearsome beast with dangerous control issues.' },
-  { name: 'Hunts',                  icon: '🏹', playstyle: 'Stalking hunter who tracks and takes down a chosen quarry.' },
-  { name: 'Infiltrates',            icon: '🕵️', playstyle: 'Uses subtlety, guile, and stealth to enter impossible places.' },
-  { name: 'Leads',                  icon: '👑', playstyle: 'Natural commander who maintains a loyal band of followers.' },
-  { name: 'Lives in the Wilderness',icon: '🌲', playstyle: 'Survivalist who thrives where others perish.' },
-  { name: 'Masters Spells',         icon: '📜', playstyle: 'Memorizes and rapidly deploys a variety of arcane spells.' },
-  { name: 'Masters Weaponry',       icon: '🗡️', playstyle: 'Grandmaster of one weapon type, surpassing all others.' },
-  { name: 'Murders',                icon: '🩸', playstyle: 'Assassin specialising in lethal surprise and clean eliminations.' },
-  { name: 'Never Says Die',         icon: '💀', playstyle: 'Unstoppable survivor who keeps fighting past all reason.' },
-  { name: 'Rides the Lightning',    icon: '⚡', playstyle: 'Creates and discharges electrical power to shock and energize.' },
-  { name: 'Slays Monsters',         icon: '🐉', playstyle: 'Dedicated monster hunter with lethal knowledge of creatures.' },
-  { name: 'Solves Mysteries',       icon: '🔎', playstyle: 'Master of deduction who reads evidence to find hidden answers.' },
-  { name: 'Wears a Sheen of Ice',   icon: '❄️', playstyle: 'Commands the wintry power of cold and ice.' },
-  { name: 'Wields Two Weapons',     icon: '🤺', playstyle: 'Dual-wielder who overwhelms enemies with relentless twin attacks.' },
-  { name: 'Works Miracles',         icon: '💫', playstyle: 'Healer and time-bender who restores the injured.' },
+  { name: 'Abides in Stone',          icon: '🗿', settings: ['fantasy','numenera'],            playstyle: 'Your body can merge with rock; you are patient, enduring, and terrifying in close combat.' },
+  { name: 'Acts Without Consequence', icon: '😏', settings: ['all'],                           playstyle: 'Rules, ethics, and consequences never seem to stick to you — a charmed manipulator.' },
+  { name: 'Battles Robots',           icon: '🤖', settings: ['numenera','scifi'],              playstyle: 'Specialised in locating and destroying mechanical threats of all kinds.' },
+  { name: 'Carries a Quiver',         icon: '🏹', settings: ['all'],                           playstyle: 'Master archer who never misses and always has the right arrow for the moment.' },
+  { name: 'Commands Mental Powers',   icon: '🧿', settings: ['all'],                           playstyle: 'Wields psychic force — telepathy, telekinesis, and mind-shattering blasts.' },
+  { name: 'Controls Beasts',          icon: '🦁', settings: ['fantasy','numenera','modern'],   playstyle: 'Communicate with and command animals, from pets to apex predators.' },
+  { name: 'Crafts Illusions',         icon: '🎭', settings: ['fantasy','numenera'],            playstyle: 'Fashion images from light so real they deceive all senses.' },
+  { name: 'Crafts Unique Objects',    icon: '⚙️', settings: ['fantasy','numenera','scifi'],   playstyle: 'Inventor of strange gadgets, gear, and one-of-a-kind contraptions.' },
+  { name: 'Dances with Dark Matter',  icon: '🌌', settings: ['numenera','scifi'],              playstyle: 'Shape the unseen fabric of reality into shields, weapons, and impossible structures.' },
+  { name: 'Defends the Weak',         icon: '🛡️', settings: ['all'],                           playstyle: 'Selfless protector who interposes and shields those who cannot protect themselves.' },
+  { name: 'Doesn\'t Do Much',         icon: '😴', settings: ['all'],                           playstyle: 'Outwardly lazy — secretly formidable. Passive abilities accumulate into devastating effect.' },
+  { name: 'Employs Magnetism',        icon: '🧲', settings: ['numenera','scifi'],              playstyle: 'Attract, repel, and reshape metal at will; a terrifying force on any battlefield.' },
+  { name: 'Entertains',               icon: '🎶', settings: ['all'],                           playstyle: 'Your art — music, acrobatics, oration — captivates crowds and shapes hearts.' },
+  { name: 'Exists Partially Out of Phase', icon: '👻', settings: ['numenera','scifi'],         playstyle: 'Slip through walls and dodge attacks by stepping slightly outside reality.' },
+  { name: 'Explores Dark Places',     icon: '🕯️', settings: ['all'],                           playstyle: 'Treasure hunter and delver of forgotten ruins, always one step from disaster.' },
+  { name: 'Fights Dirty',             icon: '🤛', settings: ['all'],                           playstyle: 'Kicks, bites, throws sand — any tactic that wins is a valid tactic.' },
+  { name: 'Fights With Panache',      icon: '🎪', settings: ['all'],                           playstyle: 'Swashbuckling daredevil who wins through flamboyant style over brute force.' },
+  { name: 'Focuses Mind Over Matter', icon: '🔵', settings: ['all'],                           playstyle: 'Forged by mental discipline; your will shapes the physical world around you.' },
+  { name: 'Fuses Flesh and Steel',    icon: '🦾', settings: ['numenera','scifi'],              playstyle: 'Cybernetic enhancements blur the line between human and machine.' },
+  { name: 'Fuses Mind and Machine',   icon: '💻', settings: ['numenera','scifi'],              playstyle: 'Interface directly with computers, drones, and AI — your mind is the terminal.' },
+  { name: 'Grows to Towering Heights',icon: '🗼', settings: ['numenera','scifi','fantasy'],    playstyle: 'Expand to enormous size, crushing opposition beneath your feet.' },
+  { name: 'Howls at the Moon',        icon: '🐺', settings: ['fantasy','numenera'],            playstyle: 'Transforms into a fearsome beast — power beyond control, control beyond reach.' },
+  { name: 'Hunts',                    icon: '🦌', settings: ['all'],                           playstyle: 'Stalking hunter who tracks and takes down a chosen quarry across any terrain.' },
+  { name: 'Infiltrates',              icon: '🕵️', settings: ['all'],                           playstyle: 'Uses subtlety, guile, and disguise to enter impossible places unseen.' },
+  { name: 'Interprets the Law',       icon: '⚖️', settings: ['all'],                           playstyle: 'Expert in rules, codes, and loopholes — the letter of the law is your weapon.' },
+  { name: 'Is Licensed to Carry',     icon: '🔫', settings: ['modern','scifi'],                playstyle: 'Expert marksman trained in firearms, their maintenance, and lethal application.' },
+  { name: 'Leads',                    icon: '👑', settings: ['all'],                           playstyle: 'Natural commander who earns loyalty and turns individuals into a deadly unit.' },
+  { name: 'Lives in the Wilderness',  icon: '🌲', settings: ['fantasy','numenera','modern'],   playstyle: 'Survivalist who reads terrain, weather, and prey — thrives where others perish.' },
+  { name: 'Looks for Trouble',        icon: '😈', settings: ['all'],                           playstyle: 'Brawler who wades into any conflict and relishes the chaos of open combat.' },
+  { name: 'Masters Defense',          icon: '🛡️', settings: ['all'],                           playstyle: 'Immovable wall who absorbs punishment and keeps allies safe.' },
+  { name: 'Masters Spells',           icon: '📜', settings: ['fantasy','numenera'],            playstyle: 'Memorizes and rapidly deploys a repertoire of arcane spells.' },
+  { name: 'Masters the Swarm',        icon: '🐝', settings: ['fantasy','numenera','scifi'],    playstyle: 'Commands insects, vermin, or nanites as an extension of your will.' },
+  { name: 'Masters Weaponry',         icon: '🗡️', settings: ['all'],                           playstyle: 'Grandmaster of one weapon type — you wield it better than anyone alive.' },
+  { name: 'Metes Out Justice',        icon: '⚖️', settings: ['all'],                           playstyle: 'Vigilante who punishes the guilty and rights wrongs outside official channels.' },
+  { name: 'Moves Like a Cat',         icon: '🐈', settings: ['all'],                           playstyle: 'Acrobat and parkour artist; gravity is a suggestion, not a rule.' },
+  { name: 'Moves Like the Wind',      icon: '🌬️', settings: ['all'],                           playstyle: 'Blur of speed — strikes before enemies react and vanishes before they recover.' },
+  { name: 'Murders',                  icon: '🩸', settings: ['all'],                           playstyle: 'Assassin specialising in lethal surprise and untraceable eliminations.' },
+  { name: 'Needs No Weapon',          icon: '👊', settings: ['all'],                           playstyle: 'Your body is the only weapon you need — fists, feet, and iron will.' },
+  { name: 'Never Says Die',           icon: '💀', settings: ['all'],                           playstyle: 'Unstoppable survivor who keeps fighting long past the point of reason.' },
+  { name: 'Operates Undercover',      icon: '🎭', settings: ['all'],                           playstyle: 'Deep-cover operative; multiple identities, zero trace, infinite patience.' },
+  { name: 'Performs Feats of Strength',icon: '🏋️', settings: ['all'],                          playstyle: 'Immense physical power applied with precision — lift, throw, and crush at will.' },
+  { name: 'Pilots Starcraft',         icon: '🚀', settings: ['numenera','scifi'],              playstyle: 'Born in the cockpit; fly, fight, and fix any spacecraft under any conditions.' },
+  { name: 'Plays Too Many Games',     icon: '♟️', settings: ['all'],                           playstyle: 'Master tactician whose life is one long game — always thinking three moves ahead.' },
+  { name: 'Rages',                    icon: '😡', settings: ['all'],                           playstyle: 'Berserker who trades control for devastating fury, unstoppable in the heat of battle.' },
+  { name: 'Rides the Lightning',      icon: '⚡', settings: ['all'],                           playstyle: 'Creates and discharges electrical power to shock, stun, and energize.' },
+  { name: 'Runs Away',                icon: '🏃', settings: ['all'],                           playstyle: 'Escape artist who knows when to fight and when to vanish — and survives because of it.' },
+  { name: 'Sailed Beneath the Jolly Roger', icon: '☠️', settings: ['fantasy','modern'],        playstyle: 'Pirate captain: seafaring, swashbuckling, plundering — and proud of every bit of it.' },
+  { name: 'Scavenges',                icon: '♻️', settings: ['all'],                           playstyle: 'Improviser who finds tools, weapons, and value where others see only junk.' },
+  { name: 'Sees Beyond',              icon: '🔮', settings: ['fantasy','numenera'],            playstyle: 'Peer into futures, pasts, and hidden truths — visions come unbidden and change everything.' },
+  { name: 'Separates Mind From Body', icon: '🕯️', settings: ['all'],                           playstyle: 'Astral projection lets your mind travel freely while your body waits in safety.' },
+  { name: 'Shreds the Walls of the World', icon: '🌀', settings: ['numenera','scifi','fantasy'], playstyle: 'Tear open dimensional rifts; step between spaces or hurl enemies into the void.' },
+  { name: 'Shrinks to Microscopic Size', icon: '🔬', settings: ['numenera','scifi'],           playstyle: 'Reduce to molecular scale to infiltrate, sabotage, and strike unseen.' },
+  { name: 'Siphons Power',            icon: '🌊', settings: ['fantasy','numenera','scifi'],    playstyle: 'Drain energy from enemies, machines, or the environment and redirect it as your own.' },
+  { name: 'Slays Monsters',           icon: '🐉', settings: ['fantasy','numenera'],            playstyle: 'Dedicated monster hunter with encyclopaedic knowledge of creature weaknesses.' },
+  { name: 'Solves Mysteries',         icon: '🔎', settings: ['all'],                           playstyle: 'Master of deduction who reads evidence to reconstruct hidden truths.' },
+  { name: 'Speaks for the Land',      icon: '🌿', settings: ['fantasy','numenera'],            playstyle: 'Voice of nature itself; plants, winds, and stones obey your call.' },
+  { name: 'Stands Like a Bastion',    icon: '🏰', settings: ['all'],                           playstyle: 'An unmovable point of order amid chaos — your resolve is physically manifest.' },
+  { name: 'Takes Animal Shape',       icon: '🦊', settings: ['fantasy','numenera'],            playstyle: 'Shapeshifter who borrows the bodies of beasts at will.' },
+  { name: 'Talks to Machines',        icon: '🖥️', settings: ['numenera','scifi'],              playstyle: 'Converse with and command technology as naturally as breathing.' },
+  { name: 'Throws with Deadly Accuracy', icon: '🎯', settings: ['all'],                        playstyle: 'Any object becomes a lethal projectile in your hands; range is not a problem.' },
+  { name: 'Thunders',                 icon: '🔊', settings: ['all'],                           playstyle: 'Sonic blasts shatter stone, stun enemies, and shake the air for miles.' },
+  { name: 'Travels Through Time',     icon: '⏳', settings: ['numenera','scifi','fantasy'],    playstyle: 'Skip forward, reach back, and observe branching moments of history.' },
+  { name: 'Wears a Sheen of Ice',     icon: '❄️', settings: ['fantasy','numenera','scifi'],   playstyle: 'Commands the wintry power of cold, frost, and absolute zero.' },
+  { name: 'Wields Power with Precision', icon: '🎯', settings: ['all'],                        playstyle: 'Your special abilities are calibrated to a razor edge — max effect, minimal collateral.' },
+  { name: 'Wields Two Weapons',       icon: '🤺', settings: ['all'],                           playstyle: 'Dual-wielder who overwhelms enemies with relentless twin-blade attacks.' },
+  { name: 'Works Miracles',           icon: '💫', settings: ['fantasy','numenera'],            playstyle: 'Healer and restorer who defies fatal wounds and brings the near-dead back.' },
+  { name: 'Works the Back Alleys',    icon: '🌆', settings: ['all'],                           playstyle: 'Street-level operative: fences, fixers, and the shadow economy are your domain.' },
+  { name: 'Worships the Lunar Nodes', icon: '🌕', settings: ['fantasy','numenera'],            playstyle: 'Moon-bound cultist whose power waxes and wanes with the celestial cycle.' },
+  { name: 'Would Rather Be Reading',  icon: '📖', settings: ['all'],                           playstyle: 'Bookish scholar who always knows exactly the right fact at exactly the right moment.' },
 ];
 
 const DIE_TYPES = [4, 6, 8, 10, 12, 20, 100];
@@ -2088,9 +2187,10 @@ function updateCharSentence() {
 
 function makeSelGrid(gridId, items, getCurrent, setCurrent) {
   const grid = document.getElementById(gridId);
+  grid.innerHTML = '';
   items.forEach(item => {
     const card = document.createElement('div');
-    card.className = 'sel-card';
+    card.className = 'sel-card' + (getCurrent()?.name === item.name ? ' selected' : '');
     card.innerHTML = `<span class="icon">${item.icon}</span><span class="name">${item.name}</span>`;
     card.title = item.note || item.playstyle || '';
     card.addEventListener('click', () => {
@@ -2104,10 +2204,24 @@ function makeSelGrid(gridId, items, getCurrent, setCurrent) {
   });
 }
 
+function filteredFoci() {
+  return FOCI.filter(f => f.settings.includes('all') || f.settings.includes(selectedSetting));
+}
+
+function rebuildFocusGrid() {
+  const filtered = filteredFoci();
+  if (selectedFocus && !filtered.find(f => f.name === selectedFocus.name)) {
+    selectedFocus = null;
+  }
+  makeSelGrid('focus-grid', filtered, () => selectedFocus, v => { selectedFocus = v; });
+  updateCharSentence();
+  checkBeginReady();
+}
+
 async function buildCreationScreen() {
   makeSelGrid('descriptor-grid', DESCRIPTORS, () => selectedDescriptor, v => { selectedDescriptor = v; });
   makeSelGrid('type-grid',       TYPES,       () => selectedType,       v => { selectedType = v; });
-  makeSelGrid('focus-grid',      FOCI,        () => selectedFocus,      v => { selectedFocus = v; });
+  rebuildFocusGrid();
   document.getElementById('begin-btn').addEventListener('click', () => beginAdventure());
   document.getElementById('change-key-btn').addEventListener('click', () => openSetupModal(getSharedBlob() ? 'shared' : 'own'));
 }
@@ -2156,7 +2270,7 @@ async function beginAdventure() {
       cypherLimit: selectedType.cypherLimit,
       cyphers: [],
       skills: [],
-      abilities: [],
+      abilities: [...(selectedType.startingAbilities || [])],
       equipment: [...selectedType.equipment],
       shins: 10,
       xp: 0,
@@ -2263,6 +2377,21 @@ function updateSidebar() {
     cypherList.classList.remove('cypher-limit-warn');
   }
 
+  // Abilities
+  const abList = document.getElementById('abilities-list');
+  abList.innerHTML = '';
+  if (c.abilities?.length) {
+    c.abilities.forEach(ab => {
+      const div = document.createElement('div');
+      div.className = 'ability-entry';
+      div.innerHTML = `<span class="ability-name">${ab.name}${ab.cost ? ` <span class="ability-cost">(${ab.cost})</span>` : ''}</span>`
+        + `<span class="ability-desc">${ab.description}</span>`;
+      abList.appendChild(div);
+    });
+  } else {
+    abList.innerHTML = '<span style="font-size:0.78rem;color:var(--text-dim);font-style:italic">None yet.</span>';
+  }
+
   // Equipment
   const list = document.getElementById('inventory-list');
   list.innerHTML = '';
@@ -2523,6 +2652,7 @@ document.getElementById('setting-row').addEventListener('click', e => {
   document.querySelectorAll('.setting-btn').forEach(b => b.classList.remove('selected'));
   btn.classList.add('selected');
   selectedSetting = btn.dataset.setting;
+  rebuildFocusGrid();
 });
 
 function rollDice() {