+
${escHtml(t("deadlines.search.pills.heading"))}
${rulePills.map((p) => renderPill(p, lang)).join("")}
`;
const triggerSection = triggerPills.length === 0 ? "" : `
-
+
${escHtml(t("deadlines.search.pills.cross_cutting"))}
${triggerPills.map((p) => renderPill(p, lang)).join("")}
`;
@@ -2423,6 +2511,17 @@ interface EventCategoryNode {
let eventCategoryTree: EventCategoryNode[] | null = null;
let eventCategoryFetchInflight: Promise
| null = null;
+// Top-level cascade roots that represent forward-looking workflows ("I
+// want to file X, what deadlines does my action trigger?") rather than
+// the backward-looking calc the Fristenrechner is built for ("event Y
+// happened, what deadlines spawn?"). m's 2026-05-20 ask (m/paliad#57):
+// remove these from the "Was ist passiert?" picker — they belong in a
+// future forward-workflow tool, not here. The DB rows stay so that
+// future tool can pick them back up; we just hide them at the UI layer.
+const HIDDEN_CASCADE_ROOTS: ReadonlySet = new Set([
+ "ich-moechte-einreichen",
+]);
+
async function loadEventCategoryTree(): Promise {
if (eventCategoryTree) return eventCategoryTree;
if (eventCategoryFetchInflight) return eventCategoryFetchInflight;
@@ -2431,7 +2530,8 @@ async function loadEventCategoryTree(): Promise {
const r = await fetch("/api/tools/fristenrechner/event-categories");
if (!r.ok) throw new Error(`HTTP ${r.status}`);
const data = await r.json();
- eventCategoryTree = (data.tree || []) as EventCategoryNode[];
+ const raw = (data.tree || []) as EventCategoryNode[];
+ eventCategoryTree = raw.filter((n) => !HIDDEN_CASCADE_ROOTS.has(n.slug));
return eventCategoryTree;
} finally {
eventCategoryFetchInflight = null;
diff --git a/frontend/src/client/i18n.ts b/frontend/src/client/i18n.ts
index 5922a53c..413367f3 100644
--- a/frontend/src/client/i18n.ts
+++ b/frontend/src/client/i18n.ts
@@ -272,10 +272,10 @@ const translations: Record> = {
"deadlines.step1.divider.new": "oder eine neue Akte",
"deadlines.step1.divider.adhoc": "oder ad-hoc, ohne Akte",
"deadlines.step1.new.cta": "+ Neue Akte anlegen",
- "deadlines.step1.adhoc.upc": "Custom UPC-Verfahren",
- "deadlines.step1.adhoc.de": "Custom DE-Verfahren",
- "deadlines.step1.adhoc.epa": "Custom EPA-Verfahren",
- "deadlines.step1.adhoc.dpma": "Custom DPMA-Verfahren",
+ "deadlines.step1.adhoc.upc": "UPC-Verfahren",
+ "deadlines.step1.adhoc.de": "DE-Verfahren",
+ "deadlines.step1.adhoc.epa": "EPA-Verfahren",
+ "deadlines.step1.adhoc.dpma": "DPMA-Verfahren",
"deadlines.step1.selected": "Akte:",
"deadlines.step1.reselect": "Andere Akte",
"deadlines.step1.summary.adhoc.suffix": "ohne Akte (Erkundung)",
@@ -345,6 +345,8 @@ const translations: Record> = {
"deadlines.card.calc.expand_hint": "Frist berechnen oder zu Akte hinzufügen",
"deadlines.card.calc.close": "schließen",
"deadlines.card.calc.pill_picker.label": "Welcher Kontext?",
+ "deadlines.card.calc.pill_picker.locked_label": "Kontext:",
+ "deadlines.card.calc.pill_picker.change": "ändern",
"deadlines.card.calc.trigger.label": "Datum des auslösenden Ereignisses",
"deadlines.card.calc.flags.label": "Bedingungen:",
"deadlines.card.calc.flag.with_ccr": "Mit Nichtigkeitswiderklage",
@@ -2960,10 +2962,10 @@ const translations: Record> = {
"deadlines.step1.divider.new": "or a new matter",
"deadlines.step1.divider.adhoc": "or ad-hoc, without a matter",
"deadlines.step1.new.cta": "+ Create new matter",
- "deadlines.step1.adhoc.upc": "Custom UPC proceeding",
- "deadlines.step1.adhoc.de": "Custom DE proceeding",
- "deadlines.step1.adhoc.epa": "Custom EPA proceeding",
- "deadlines.step1.adhoc.dpma": "Custom DPMA proceeding",
+ "deadlines.step1.adhoc.upc": "UPC proceeding",
+ "deadlines.step1.adhoc.de": "DE proceeding",
+ "deadlines.step1.adhoc.epa": "EPA proceeding",
+ "deadlines.step1.adhoc.dpma": "DPMA proceeding",
"deadlines.step1.selected": "Matter:",
"deadlines.step1.reselect": "Other matter",
"deadlines.step1.summary.adhoc.suffix": "no matter (exploration)",
@@ -3040,6 +3042,8 @@ const translations: Record> = {
"deadlines.card.calc.expand_hint": "Calculate deadline or add to project",
"deadlines.card.calc.close": "close",
"deadlines.card.calc.pill_picker.label": "Which context?",
+ "deadlines.card.calc.pill_picker.locked_label": "Context:",
+ "deadlines.card.calc.pill_picker.change": "change",
"deadlines.card.calc.trigger.label": "Date of triggering event",
"deadlines.card.calc.flags.label": "Conditions:",
"deadlines.card.calc.flag.with_ccr": "With counterclaim for revocation",
diff --git a/frontend/src/fristenrechner.tsx b/frontend/src/fristenrechner.tsx
index cfaea26a..95f46946 100644
--- a/frontend/src/fristenrechner.tsx
+++ b/frontend/src/fristenrechner.tsx
@@ -161,19 +161,19 @@ export function renderFristenrechner(): string {
diff --git a/frontend/src/i18n-keys.ts b/frontend/src/i18n-keys.ts
index f415d1e2..2154a45b 100644
--- a/frontend/src/i18n-keys.ts
+++ b/frontend/src/i18n-keys.ts
@@ -971,7 +971,9 @@ export type I18nKey =
| "deadlines.card.calc.flag.with_cci"
| "deadlines.card.calc.flag.with_ccr"
| "deadlines.card.calc.flags.label"
+ | "deadlines.card.calc.pill_picker.change"
| "deadlines.card.calc.pill_picker.label"
+ | "deadlines.card.calc.pill_picker.locked_label"
| "deadlines.card.calc.result.calculating"
| "deadlines.card.calc.result.court_set"
| "deadlines.card.calc.result.due"
diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css
index b91192e3..6a463754 100644
--- a/frontend/src/styles/global.css
+++ b/frontend/src/styles/global.css
@@ -2670,6 +2670,61 @@ input[type="range"]::-moz-range-thumb {
font-family: ui-monospace, monospace;
}
+/* m/paliad#57 part 4 — once a card is expanded into a calc panel,
+ the rule-pill list is redundant with the calc panel's context
+ picker (locked caption or fieldset). Hide it so the user isn't
+ asked the same thing twice. The cross-cutting section stays —
+ those pills are alternative concepts to explore, not the same
+ proceeding context. */
+.fristen-card.is-expanded .fristen-card-pills-section--rules {
+ display: none;
+}
+
+/* Locked-context caption when the user clicked a specific rule pill
+ to expand. Shows the picked (proceeding, rule) tuple compactly
+ with a small "ändern" button to swap back to the radio picker. */
+.fristen-card-calc-pill-locked {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: baseline;
+ gap: 0.4rem;
+ padding: 0.35rem 0.55rem;
+ border: 1px solid var(--color-border-subtle, #ececec);
+ border-radius: 5px;
+ background: rgba(198, 244, 28, 0.06);
+ font-size: 0.88rem;
+}
+.fristen-card-calc-pill-locked-label {
+ font-weight: 600;
+ color: var(--color-muted, #777);
+ text-transform: uppercase;
+ font-size: 0.74rem;
+ letter-spacing: 0.04em;
+}
+.fristen-card-calc-pill-locked-proc {
+ font-weight: 600;
+ color: var(--color-text, #222);
+}
+.fristen-card-calc-pill-locked-rule {
+ color: var(--color-text, #222);
+}
+.fristen-card-calc-pill-locked-source {
+ font-size: 0.8rem;
+ color: var(--color-muted, #888);
+ font-family: ui-monospace, monospace;
+}
+.fristen-card-calc-pill-change {
+ margin-left: auto;
+ background: transparent;
+ border: 0;
+ padding: 0;
+ color: var(--color-link, #1267a8);
+ cursor: pointer;
+ font-size: 0.82rem;
+ text-decoration: underline;
+}
+.fristen-card-calc-pill-change:hover { text-decoration: none; }
+
.fristen-card-calc-inputs {
display: flex;
flex-wrap: wrap;