diff --git a/CHANGELOG.md b/CHANGELOG.md
index e62e75e4..525097e3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -107,6 +107,8 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Under the hood
+- **Conditions that end at a rest.** The builder's CONDITIONS page can end a condition AT A REST,
+ with the rests that end it ticked beside it; the RESTS page's WEARS OFF is the same setting.
- **The builder's RESTS page.** Between CONDITIONS and TRY IT: switch the standard rests on or off,
rename them, add the system's own, say which other rests each one counts as, what it refills
(health, a number on the sheet, or a whole section, with amounts as numbers, formulas or dice),
diff --git a/README.md b/README.md
index bccb91f8..3696bb15 100644
--- a/README.md
+++ b/README.md
@@ -723,7 +723,7 @@ CITY_NET/
│ │ │ ├── SheetPage.tsx # CHARACTER SHEET: automatic until CUSTOMIZE copies the starter; a tree of tabs, sections and fields to move and edit, who sees and who changes each field, a tray of stats not placed yet, and a live preview. Also edits NPCS' stat block of its own (GM-only preview)
│ │ │ ├── SheetPreview.tsx # The sheet designer's live preview, drawn by the real SheetRenderer, as its owner, the GM and everyone else see it
│ │ │ ├── NpcsPage.tsx # NPCS: the stat block (the character sheet, or one of its own) and TIERS, each box a number, a formula with @level or dice, typed text kept as typed, a TRY IT roll at a level
-│ │ │ ├── ConditionsPage.tsx # CONDITIONS: the standard set with switches and a system's own (+ CONDITION, DELETE after asking), up to 60; each one's name (the standard name as placeholder), chip label, icon (ConditionIconPicker), description, how it ends (when removed or after rounds) and modifiers on all rolls, a stat or a formula, typed numbers kept as typed
+│ │ │ ├── ConditionsPage.tsx # CONDITIONS: the standard set with switches and a system's own (+ CONDITION, DELETE after asking), up to 60; each one's name (the standard name as placeholder), chip label, icon (ConditionIconPicker), description, how it ends (when removed, after rounds, or at the rests ticked, the same setting as RESTS' WEARS OFF) and modifiers on all rolls, a stat or a formula, typed numbers kept as typed
│ │ │ ├── RestsPage.tsx # RESTS: the standard four with switches and a system's own (+ REST, DELETE after asking), up to 12; each one's name (the standard name as placeholder), ALSO COUNTS AS (a rest that would loop greyed), refills in order (what from the sheet the server previews, how, an amount, a track in a two-track system; one naming something gone said so), the refills of rests it counts as shown above its own, and WEARS OFF (the conditions, rounds ones greyed, one ending through a counted rest said so)
│ │ │ ├── ConditionIcon.tsx # A condition's icon: one drawn for CITY_NET, stroked in the theme's color, or an uploaded picture through only; anything unknown draws the target
│ │ │ ├── ConditionIconPicker.tsx # A condition's icon picked: the 24 drawn ones, or UPLOAD for a small PNG, WebP or SVG (a refusal said); the builder's CONDITIONS page and the GAME tab's both use it
@@ -801,7 +801,7 @@ CITY_NET/
│ │ │ ├── NpcsPage.test.tsx # The stat block shared or its own, tiers whose boxes keep what was typed, and TRY IT rolling one, all through the server's own code
│ │ │ ├── mapConditions.test.tsx # Condition icons over tokens: four then +N naming the rest, on every kind of token for anyone with token health off too, nothing for none, and one shared request for the game's list (again after a system changes or a request fails)
│ │ │ ├── TokenConditions.test.tsx # The HEALTH folder's conditions: chips with rounds, descriptions and modifiers for whoever may change them, putting one on and taking one off (a refusal said), nothing but which and what for everyone else, nothing drawn for a token with none, the list asked again when a system changes, and the stream overlay showing them
-│ │ │ ├── ConditionsPage.test.tsx # Switches storing only "off", renaming and putting back, icons drawn or uploaded (a refusal said), ends and rounds, modifiers typed negative, a system's own added, named, deleted after asking, and + CONDITION stopping at 60
+│ │ │ ├── ConditionsPage.test.tsx # Switches storing only "off", renaming and putting back, icons drawn or uploaded (a refusal said), ends and rounds, ending at the rests ticked (one turned off offered only to untick), modifiers typed negative, a system's own added, named, deleted after asking, and + CONDITION stopping at 60
│ │ │ ├── RestsPage.test.tsx # Switches storing only "off", own rests added, opened and deleted after asking, stopping at 12, names and their placeholders, counting as rests that are on and never in a loop, refills added and fitted to what they name, from the previewed sheet or health alone, tracks, a refill naming something gone, nothing to refill, and what wears off ticked from the rest's side; every change held to the server's checks
│ │ │ ├── TableConditionsPanel.test.tsx # The GAME tab's conditions against a fake server running the real checks: standard ones folded, the table's own listed, one added with a drawn or uploaded icon and sent whole with the GM's login, removed only once asked, a refusal said with the typing kept, + CONDITION stopping at 60, and the panel only for the main admin under a built-in game
│ │ │ ├── TryItPage.test.tsx # The made-up character and its formulas, SAVE AS THE SAMPLE (absent with nowhere to save), RESET, health on a pretend token under each model, both maximums, and an NPC rolled from a tier
diff --git a/frontend/src/components/ConditionsPage.tsx b/frontend/src/components/ConditionsPage.tsx
index 68107b85..0718b111 100644
--- a/frontend/src/components/ConditionsPage.tsx
+++ b/frontend/src/components/ConditionsPage.tsx
@@ -2,15 +2,17 @@ import React, { useEffect, useState } from 'react';
import type { Definition, systemsApi } from '../sheets/systemsApi';
import {
conditionList, conditionCount, withCondition, withNewCondition, withoutCondition, modifierTargets,
- LIMITS, ALL_ROLLS, STANDARD, type Listed,
+ LIMITS, ALL_ROLLS, STANDARD, type Listed, type ConditionPatch,
} from '../sheets/conditions';
+import { restList } from '../sheets/rests';
import { ConditionIcon } from './ConditionIcon';
import { ConditionIconPicker } from './ConditionIconPicker';
// The builder's CONDITIONS page (4e1b; approved mockup docs/mockups/builder-conditions.html,
// 2026-10-09): what can happen to a character besides losing health. The standard set, each with
// a switch, edited or turned off; the system's own, added and deleted; each one's name, chip label,
-// icon (drawn, or uploaded), description, how it ends, and its modifiers. What it reads and writes
+// icon (drawn, or uploaded), description, how it ends (when removed, after rounds, or at a rest,
+// 4f4b), and its modifiers. What it reads and writes
// is sheets/conditions.ts; every change goes through the builder's `edit`.
interface Props {
@@ -55,6 +57,37 @@ export function Switch({ on, label, onChange }: { on: boolean; label: string; on
);
}
+/**
+ * AT A REST (4f4b; approved mockup builder-rests, 2026-10-09): the rests that end a condition, ticked
+ * here or as WEARS OFF on the RESTS page, the same setting. The rests that are on, and any picked one
+ * since turned off, so it can be unticked.
+ */
+function EndsAt({ c, definition, set }: { c: Listed; definition: Definition; set: (patch: ConditionPatch) => void }) {
+ const at = c.at ?? [];
+ const offered = restList(definition).filter((r) => r.on || at.includes(r.id));
+ return (
+