paneltir 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/INSTALL.md CHANGED
@@ -19,7 +19,7 @@ identity** — never another project's.
19
19
  npm install paneltir
20
20
 
21
21
  # or, without npm access, straight from the repository:
22
- # npm install github:daifukus/paneltir#v0.10.1
22
+ # npm install github:daifukus/paneltir#v0.11.0
23
23
  ```
24
24
 
25
25
  (Use the tag you were given; never install without pinning a version.)
@@ -237,7 +237,7 @@ identity** — never another project's.
237
237
 
238
238
  ```bash
239
239
  npx paneltir version # version, fingerprint, where it came from
240
- npx paneltir check 0.10.1 # exits non-zero if that is not what is installed
240
+ npx paneltir check 0.11.0 # exits non-zero if that is not what is installed
241
241
  npx paneltir board # read the board and say what is wrong with it
242
242
  ```
243
243
 
package/README.md CHANGED
@@ -54,7 +54,7 @@ tag rather than a branch, so an unfinished push cannot reach a project:
54
54
  npm install paneltir
55
55
 
56
56
  # or, without npm access, straight from the repository:
57
- # npm install github:daifukus/paneltir#v0.10.1
57
+ # npm install github:daifukus/paneltir#v0.11.0
58
58
  ```
59
59
 
60
60
  Installing from Git runs the `prepare` script, which builds `dist/`, so the
package/dist/index.d.ts CHANGED
@@ -284,6 +284,14 @@ interface BoardColumnData<TCard extends BoardCardData = BoardCardData> {
284
284
  */
285
285
  hint?: string;
286
286
  cards: TCard[];
287
+ /**
288
+ * Drawn under the cards, inside the column's own scroll.
289
+ *
290
+ * It exists for what a column has to say about cards it is *not* showing —
291
+ * a done column hiding what was finished last month still owes the reader a
292
+ * line saying so, or the cards have not been hidden, they have been lost.
293
+ */
294
+ footer?: React.ReactNode;
287
295
  }
288
296
  interface BoardMoveResult {
289
297
  cardId: string;
@@ -1055,6 +1063,32 @@ declare function newId(): string;
1055
1063
  declare function today(): string;
1056
1064
  /** A card is created empty and named second — the same as tapping "+" on paper. */
1057
1065
  declare function emptyCard(column: string, area: string): Card;
1066
+ /**
1067
+ * How long a finished card stays on the board before it becomes history.
1068
+ *
1069
+ * A done column only grows. It is the one column nothing ever removes from,
1070
+ * so a board that is being worked turns into a wall of things already
1071
+ * finished, and the three columns that need reading get a third of the screen
1072
+ * between them. A week is the window in which "what did we ship" is still a
1073
+ * live question; after that it is a record, and a record does not need to be
1074
+ * in the way.
1075
+ */
1076
+ declare const ARCHIVE_AFTER_DAYS = 7;
1077
+ /**
1078
+ * Whether a finished card has been finished long enough to stop being drawn.
1079
+ *
1080
+ * Derived on every render and never written, which is the arrangement
1081
+ * `boardFacts()` already uses: a flag stored on the card would be wrong the
1082
+ * day after it was set, and setting it would mark the panel dirty for the
1083
+ * passage of time. Here the answer simply becomes true on its own.
1084
+ *
1085
+ * **A card with no `completedAt` is never archived**, whatever column it sits
1086
+ * in. It reached done without being stamped — a board edited by hand, or one
1087
+ * from before the stamp existed — so its age is not known, and hiding a card
1088
+ * whose age nobody knows is the same mistake as reporting a token missing
1089
+ * because the check could not run. `unknown` is not `old`.
1090
+ */
1091
+ declare function isArchived(card: Card, doneColumns: ReadonlySet<string>, now?: string, afterDays?: number): boolean;
1058
1092
  /**
1059
1093
  * Applies the column's own meaning to a card that just moved into it: a card
1060
1094
  * entering the working column is started, one reaching a done column is
@@ -1386,6 +1420,9 @@ interface UiStrings {
1386
1420
  needTokenEnables: string;
1387
1421
  needRepo: string;
1388
1422
  needRepoEnables: string;
1423
+ archivedOne: string;
1424
+ archivedMany: string;
1425
+ archivedHide: string;
1389
1426
  needGate: string;
1390
1427
  needGateEnables: string;
1391
1428
  fixGate: string;
@@ -1847,4 +1884,4 @@ interface CardSheetProps {
1847
1884
  }
1848
1885
  declare function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }: CardSheetProps): React.JSX.Element | null;
1849
1886
 
1850
- export { ANALYSIS_SECTIONS, AlertBanner, type AlertBannerProps, type Analysis, type AnalysisSection, AnalysisView, BOARD_VERSION, Board, type BoardCardData, type BoardCheck, type BoardColumnData, type BoardFacts, type BoardMoveResult, type BoardProblem, type BoardProps, type BoardTag, CAPABILITIES, type Capability, Card$1 as Card, type CardProps, CardSheet, type Check, type Choice, type ChoiceOption, type ColumnDef, type Competitor, type Constraint, CopyBlock, type CopyBlockLabels, type CopyBlockProps, type Counts, DashboardHeader, type DashboardHeaderProps, type DashboardThemeForm, DashboardThemeProvider, type DashboardThemeTokens, DetailSection, type DetailSectionProps, DetailSheet, type DetailSheetProps, FilterChip, type FilterChipProps, FilterChipRow, type GateReading, type GateStamp, type GateVerdict, type Goal, GuideNote, type GuideNoteProps, GuideTour, type GuideTourProps, type HealthFact, HealthPill, type HealthPillProps, HealthPillRow, type HealthStatus, INTENTS, INTENT_COPY, type ImportedTheme, type InstallState, type Intent, type IntentCopy, LANGS, LANG_LABELS, LEVELS, type Lang, type Level, MARKETPLACE_NAME, MARKETPLACE_URL, type Market, type MarketplaceReport, type MarketplaceTool, MarketplaceView, type Metric, type Note, NotificationBell, type NotificationBellProps, type NotificationLabels, type NotificationTone, OWNERS, type Owner, PANELTIR_FILE_COUNT, PANELTIR_FINGERPRINT, PANELTIR_TEMPLATE_HASH, PANELTIR_VERSION, PRESET_PANEL_THEMES, PanelApp, type PanelAppProps, type Card as PanelCard, type PanelNotification, type PanelState, type PanelTheme, type PanelThemes, type Preferences, type Reading, type Run, SetupGuide, type SetupGuideProps, type SetupRequirement, type SetupStatus, SetupWizard, type SetupWizardLabels, type SetupWizardProps, type Severity, StatTile, StatTileGrid, type StatTileProps, type Strategy, type Suggestion, type SuggestionStatus, THEME_FORMS, THEME_PRESETS, type Text, type ThemeFormName, type ThemePresetName, type Trend, UI, type UiStrings, type Weight, type WizardStep, applyMove, boardFacts, checkProgress, claimedWithoutStarting, claudeTheme, commandSnippet, countCards, cyberpunkTheme, decided, emptyCard, explainBoard, gateStatus, isCard, isFirstRun, ledgerForm, midnightTheme, moveCardInColumns, newId, offeredThemes, oldMoneyTheme, panelForm, paneltirBuild, paperForm, readBoard, readStoredLang, repositorySnippet, resetGuide, sparkPoints, stampForColumn, storeLang, text, today, trendOf, undecided, untranslated, useDashboardForm, useDashboardTheme, useDelegatedClick, useGuideNote, useMediaQuery, validateBoard, wizardStep, writeText };
1887
+ export { ANALYSIS_SECTIONS, ARCHIVE_AFTER_DAYS, AlertBanner, type AlertBannerProps, type Analysis, type AnalysisSection, AnalysisView, BOARD_VERSION, Board, type BoardCardData, type BoardCheck, type BoardColumnData, type BoardFacts, type BoardMoveResult, type BoardProblem, type BoardProps, type BoardTag, CAPABILITIES, type Capability, Card$1 as Card, type CardProps, CardSheet, type Check, type Choice, type ChoiceOption, type ColumnDef, type Competitor, type Constraint, CopyBlock, type CopyBlockLabels, type CopyBlockProps, type Counts, DashboardHeader, type DashboardHeaderProps, type DashboardThemeForm, DashboardThemeProvider, type DashboardThemeTokens, DetailSection, type DetailSectionProps, DetailSheet, type DetailSheetProps, FilterChip, type FilterChipProps, FilterChipRow, type GateReading, type GateStamp, type GateVerdict, type Goal, GuideNote, type GuideNoteProps, GuideTour, type GuideTourProps, type HealthFact, HealthPill, type HealthPillProps, HealthPillRow, type HealthStatus, INTENTS, INTENT_COPY, type ImportedTheme, type InstallState, type Intent, type IntentCopy, LANGS, LANG_LABELS, LEVELS, type Lang, type Level, MARKETPLACE_NAME, MARKETPLACE_URL, type Market, type MarketplaceReport, type MarketplaceTool, MarketplaceView, type Metric, type Note, NotificationBell, type NotificationBellProps, type NotificationLabels, type NotificationTone, OWNERS, type Owner, PANELTIR_FILE_COUNT, PANELTIR_FINGERPRINT, PANELTIR_TEMPLATE_HASH, PANELTIR_VERSION, PRESET_PANEL_THEMES, PanelApp, type PanelAppProps, type Card as PanelCard, type PanelNotification, type PanelState, type PanelTheme, type PanelThemes, type Preferences, type Reading, type Run, SetupGuide, type SetupGuideProps, type SetupRequirement, type SetupStatus, SetupWizard, type SetupWizardLabels, type SetupWizardProps, type Severity, StatTile, StatTileGrid, type StatTileProps, type Strategy, type Suggestion, type SuggestionStatus, THEME_FORMS, THEME_PRESETS, type Text, type ThemeFormName, type ThemePresetName, type Trend, UI, type UiStrings, type Weight, type WizardStep, applyMove, boardFacts, checkProgress, claimedWithoutStarting, claudeTheme, commandSnippet, countCards, cyberpunkTheme, decided, emptyCard, explainBoard, gateStatus, isArchived, isCard, isFirstRun, ledgerForm, midnightTheme, moveCardInColumns, newId, offeredThemes, oldMoneyTheme, panelForm, paneltirBuild, paperForm, readBoard, readStoredLang, repositorySnippet, resetGuide, sparkPoints, stampForColumn, storeLang, text, today, trendOf, undecided, untranslated, useDashboardForm, useDashboardTheme, useDelegatedClick, useGuideNote, useMediaQuery, validateBoard, wizardStep, writeText };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/version.ts
2
- var PANELTIR_VERSION = "0.10.1";
3
- var PANELTIR_FINGERPRINT = "sha256:b2d1daf120972ce3bfc54f3a9f09bccaddd6ceb306a65a1682b810012d85f33d";
2
+ var PANELTIR_VERSION = "0.11.0";
3
+ var PANELTIR_FINGERPRINT = "sha256:2739462e763939de1d1aeb8ab97779149c2ddb0ec2d2fb45644c4c45ef9dc9fa";
4
4
  var PANELTIR_FILE_COUNT = 163;
5
5
  var PANELTIR_TEMPLATE_HASH = "sha256:034ba27266408af4f2ba5793d9cefbe448b168570d6a0b87dfe698dfe639feb1";
6
6
  var paneltirBuild = {
@@ -306,7 +306,8 @@ function Column({ column, renderCard, onAddCard }) {
306
306
  renderCard(card, index, column.id)
307
307
  ] }, card.id);
308
308
  }),
309
- dnd.isDragging && dnd.dropTarget?.columnId === column.id && dnd.dropTarget.index === column.cards.length && /* @__PURE__ */ jsx8("div", { className: "pt-card-placeholder" })
309
+ dnd.isDragging && dnd.dropTarget?.columnId === column.id && dnd.dropTarget.index === column.cards.length && /* @__PURE__ */ jsx8("div", { className: "pt-card-placeholder" }),
310
+ column.footer ? /* @__PURE__ */ jsx8("div", { className: "pt-column__footer", children: column.footer }) : null
310
311
  ] })
311
312
  ] });
312
313
  }
@@ -1148,6 +1149,18 @@ function emptyCard(column, area) {
1148
1149
  completedAt: null
1149
1150
  };
1150
1151
  }
1152
+ var ARCHIVE_AFTER_DAYS = 7;
1153
+ function daysBefore(from, days) {
1154
+ const at = /* @__PURE__ */ new Date(`${from}T00:00:00Z`);
1155
+ at.setUTCDate(at.getUTCDate() - days);
1156
+ return at.toISOString().slice(0, 10);
1157
+ }
1158
+ function isArchived(card, doneColumns, now = today(), afterDays = ARCHIVE_AFTER_DAYS) {
1159
+ if (!doneColumns.has(card.column)) return false;
1160
+ const finished = card.completedAt;
1161
+ if (typeof finished !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(finished)) return false;
1162
+ return finished < daysBefore(now, afterDays);
1163
+ }
1151
1164
  function stampForColumn(card, columns) {
1152
1165
  const column = columns.find((candidate) => candidate.id === card.column);
1153
1166
  if (!column) return card;
@@ -1615,6 +1628,9 @@ var UI = {
1615
1628
  needTokenEnables: "Lets Save commit the board back to the repository. Without it everything else works and Save fails.",
1616
1629
  needRepo: "The repository to write to",
1617
1630
  needRepoEnables: "Which repository the board is committed to. There is no default on purpose: writing to the wrong one is worse than not writing.",
1631
+ archivedOne: "archived \u2014 finished over a week ago",
1632
+ archivedMany: "archived \u2014 finished over a week ago",
1633
+ archivedHide: "Hide them again",
1618
1634
  needGate: "The gate this project copied",
1619
1635
  needGateEnables: "The sign-in, the session and the write-back are files this project owns, copied once and never updated with the library. When one of them is older than the package, the panel does not look misconfigured \u2014 it looks broken.",
1620
1636
  fixGate: "The gate is older than the installed kit. See what changed before replacing anything:",
@@ -1939,6 +1955,9 @@ var UI = {
1939
1955
  needTokenEnables: "Permite que Guardar confirme el tablero en el repositorio. Sin \xE9l todo lo dem\xE1s funciona y Guardar falla.",
1940
1956
  needRepo: "El repositorio donde escribir",
1941
1957
  needRepoEnables: "En qu\xE9 repositorio se confirma el tablero. No hay valor por defecto a prop\xF3sito: escribir en el equivocado es peor que no escribir.",
1958
+ archivedOne: "archivada \u2014 terminada hace m\xE1s de una semana",
1959
+ archivedMany: "archivadas \u2014 terminadas hace m\xE1s de una semana",
1960
+ archivedHide: "Volver a esconderlas",
1942
1961
  needGate: "La puerta que copi\xF3 este proyecto",
1943
1962
  needGateEnables: "El acceso, la sesi\xF3n y la escritura de vuelta son archivos de este proyecto, copiados una vez y que no se actualizan con la librer\xEDa. Cuando uno se queda m\xE1s viejo que el paquete, el panel no parece mal configurado: parece roto.",
1944
1963
  fixGate: "La puerta es m\xE1s vieja que el kit instalado. Mira qu\xE9 cambi\xF3 antes de reemplazar nada:",
@@ -3032,6 +3051,7 @@ function PanelApp({
3032
3051
  );
3033
3052
  const [state, setState] = useState10(initialState);
3034
3053
  const [filter, setFilter] = useState10("all");
3054
+ const [showArchived, setShowArchived] = useState10(() => /* @__PURE__ */ new Set());
3035
3055
  const [openCardId, setOpenCardId] = useState10(null);
3036
3056
  const [settingsOpen, setSettingsOpen] = useState10(false);
3037
3057
  const [update, setUpdate] = useState10(null);
@@ -3155,13 +3175,31 @@ function PanelApp({
3155
3175
  );
3156
3176
  const visibleCards = useMemo5(() => state.cards.filter(matches), [state.cards, matches]);
3157
3177
  const boardColumns = useMemo5(
3158
- () => state.columns.map((column) => ({
3159
- id: column.id,
3160
- title: t(column.title),
3161
- hint: column.hint ? t(column.hint) : void 0,
3162
- cards: visibleCards.filter((card) => card.column === column.id)
3163
- })),
3164
- [state.columns, visibleCards, t]
3178
+ () => state.columns.map((column) => {
3179
+ const mine = visibleCards.filter((card) => card.column === column.id);
3180
+ const archived = mine.filter((card) => isArchived(card, doneColumns));
3181
+ const showing = showArchived.has(column.id) ? mine : mine.filter((card) => !archived.includes(card));
3182
+ return {
3183
+ id: column.id,
3184
+ title: t(column.title),
3185
+ hint: column.hint ? t(column.hint) : void 0,
3186
+ cards: showing,
3187
+ footer: archived.length ? /* @__PURE__ */ jsx20(
3188
+ "button",
3189
+ {
3190
+ type: "button",
3191
+ onClick: () => setShowArchived((current) => {
3192
+ const next = new Set(current);
3193
+ if (next.has(column.id)) next.delete(column.id);
3194
+ else next.add(column.id);
3195
+ return next;
3196
+ }),
3197
+ children: showArchived.has(column.id) ? ui.archivedHide : `${archived.length} ${archived.length === 1 ? ui.archivedOne : ui.archivedMany}`
3198
+ }
3199
+ ) : void 0
3200
+ };
3201
+ }),
3202
+ [state.columns, visibleCards, doneColumns, showArchived, t, ui]
3165
3203
  );
3166
3204
  const notifications = useMemo5(() => {
3167
3205
  const items = [];
@@ -4263,6 +4301,7 @@ var CAPABILITIES = [
4263
4301
  ];
4264
4302
  export {
4265
4303
  ANALYSIS_SECTIONS,
4304
+ ARCHIVE_AFTER_DAYS,
4266
4305
  AlertBanner,
4267
4306
  AnalysisView,
4268
4307
  BOARD_VERSION,
@@ -4316,6 +4355,7 @@ export {
4316
4355
  emptyCard,
4317
4356
  explainBoard,
4318
4357
  gateStatus,
4358
+ isArchived,
4319
4359
  isCard,
4320
4360
  isFirstRun,
4321
4361
  ledgerForm,
package/dist/style.css CHANGED
@@ -594,6 +594,28 @@
594
594
  background: var(--pt-color-panel);
595
595
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
596
596
  }
597
+ .pt-column__footer {
598
+ padding-top: var(--pt-space-sm);
599
+ border-top: var(--pt-border-width) solid var(--pt-color-line-faint);
600
+ font-size: 11.5px;
601
+ color: var(--pt-color-ink-faint);
602
+ }
603
+ .pt-column__footer button {
604
+ border: none;
605
+ background: none;
606
+ padding: 0;
607
+ font: inherit;
608
+ color: inherit;
609
+ cursor: pointer;
610
+ text-decoration: underline;
611
+ text-underline-offset: 2px;
612
+ }
613
+ .pt-column__footer button:hover {
614
+ color: var(--pt-color-ink-dim);
615
+ }
616
+ .pt-column__list > * {
617
+ flex-shrink: 0;
618
+ }
597
619
 
598
620
  /* src/components/DetailSheet/DetailSheet.css */
599
621
  .pt-sheet-backdrop {
package/fingerprint.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "paneltir",
3
- "version": "0.10.1",
4
- "hash": "sha256:b2d1daf120972ce3bfc54f3a9f09bccaddd6ceb306a65a1682b810012d85f33d",
3
+ "version": "0.11.0",
4
+ "hash": "sha256:2739462e763939de1d1aeb8ab97779149c2ddb0ec2d2fb45644c4c45ef9dc9fa",
5
5
  "fileCount": 163,
6
6
  "templateHash": "sha256:034ba27266408af4f2ba5793d9cefbe448b168570d6a0b87dfe698dfe639feb1",
7
- "generatedAt": "2026-09-11T07:08:17.308Z"
7
+ "generatedAt": "2026-09-13T08:39:02.027Z"
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paneltir",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "A React UI kit for admin panels: page frame, a board with touch-ready drag and drop, detail sheets, and a whole panel in one component. Structure and behaviour are fixed; colour and brand belong to each project.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "DFKlabs (https://DFKlabs.com)",
@@ -99,56 +99,28 @@
99
99
  "node": ">=20"
100
100
  },
101
101
  "paneltirRelease": {
102
- "version": "0.10.1",
103
- "date": "2026-09-11",
102
+ "version": "0.11.0",
103
+ "date": "2026-09-13",
104
104
  "entries": [
105
105
  {
106
- "kind": "fix",
106
+ "kind": "feature",
107
107
  "text": {
108
- "en": "Re-running `paneltir init` no longer tells the panel a stale gate is current. It stamped the new template over files it had not written, so a project that updated and re-ran init was told its gate was up to date when it was not.",
109
- "es": "Re-ejecutar `paneltir init` ya no le dice al panel que una puerta vieja está al día. Sellaba la plantilla nueva sobre archivos que no había escrito, así que un proyecto que actualizaba y re-ejecutaba init recibía un «todo correcto» que no era cierto."
108
+ "en": "A card finished more than a week ago stops being drawn in its column. The column says how many it is holding and one tap shows them nothing is hidden without being accounted for.",
109
+ "es": "Una tarjeta terminada hace más de una semana deja de dibujarse en su columna. La columna dice cuántas guarda y un toque las enseña nada se esconde sin quedar contado."
110
110
  }
111
111
  },
112
112
  {
113
- "kind": "fix",
113
+ "kind": "feature",
114
114
  "text": {
115
- "en": "The save endpoint's own board check had drifted to a shallow one that accepted a board with no areas, an unknown intent, an unknown area and any version at all. All three copies of that check are now held to the same verdict.",
116
- "es": "La comprobación del tablero en el endpoint de guardado había derivado a una superficial que aceptaba un tablero sin áreas, un intent desconocido, un área desconocida y cualquier versión. Las tres copias de esa comprobación se sujetan ahora al mismo veredicto."
117
- }
118
- },
119
- {
120
- "kind": "fix",
121
- "text": {
122
- "en": "`paneltir run` appends to the end of the revisions log instead of the front, so a new pass reads as the newest and not the oldest — and accepts `--cards a,b` and `--by you`, the spaced form its own usage line prints.",
123
- "es": "`paneltir run` añade al final del registro de revisiones en vez de al principio, así una pasada nueva se lee como la más reciente y no como la más antigua — y acepta `--cards a,b` y `--by you`, la forma con espacio que imprime su propio uso."
124
- }
125
- },
126
- {
127
- "kind": "fix",
128
- "text": {
129
- "en": "A board naming a theme that only exists on Object's prototype — `constructor`, `toString` — no longer resolves as a theme and draws the panel in the browser's default colours.",
130
- "es": "Un tablero que nombra un tema que sólo existe en el prototipo de Object — `constructor`, `toString` — ya no se resuelve como tema ni dibuja el panel con los colores por defecto del navegador."
131
- }
132
- },
133
- {
134
- "kind": "fix",
135
- "text": {
136
- "en": "Saving no longer breaks permanently once a board reaches two hundred revisions. The limit was refused on the write path and applied nowhere; it is bounded where the log is appended instead.",
137
- "es": "Guardar ya no se rompe para siempre cuando un tablero llega a doscientas revisiones. El límite se rechazaba al escribir y no se aplicaba en ningún sitio; ahora se acota donde se añade al registro."
138
- }
139
- },
140
- {
141
- "kind": "fix",
142
- "text": {
143
- "en": "The copied gate's row in the setup list no longer parks the walkthrough on a step its one action cannot clear, nor makes every other step report that the panel could not reach its own server.",
144
- "es": "La fila de la puerta copiada en la lista de configuración ya no deja el asistente atascado en un paso que su única acción no puede resolver, ni hace que el resto de pasos digan que el panel no pudo alcanzar su propio servidor."
115
+ "en": "A board column can carry a footer, drawn inside its own scroll so it takes no height from the cards.",
116
+ "es": "Una columna del tablero puede llevar un pie, dibujado dentro de su propio scroll para que no le quite alto a las tarjetas."
145
117
  }
146
118
  },
147
119
  {
148
120
  "kind": "chore",
149
121
  "text": {
150
- "en": "Two checks that could stop checking were closed: a travelling document that cannot be read is now a failure rather than a pass, and no gate file may read the environment at module scope — where no error can be caught.",
151
- "es": "Se cerraron dos comprobaciones que podían dejar de comprobar: un documento que viaja y no se puede leer ahora falla en vez de pasar, y ningún archivo de la puerta puede leer el entorno a nivel de módulo, donde ningún error se puede capturar."
122
+ "en": "A card in a scrolling column can never shrink below its own content, so a title can never be cut in half.",
123
+ "es": "Una tarjeta en una columna con scroll no puede encogerse por debajo de su contenido, así que un título no puede quedar cortado por la mitad."
152
124
  }
153
125
  }
154
126
  ]