@justai/cuts 0.119.0 → 0.121.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justai/cuts",
3
- "version": "0.119.0",
3
+ "version": "0.121.0",
4
4
  "description": "A persona's named parts \u2014 the page shell that holds them, and the cuts themselves.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -41,8 +41,8 @@
41
41
  "access": "public"
42
42
  },
43
43
  "dependencies": {
44
- "@justai/core": "^0.26.0",
45
- "@justai/ui": "^0.17.0",
44
+ "@justai/core": "^0.28.0",
45
+ "@justai/ui": "^0.19.0",
46
46
  "@justai/atrium": "^0.1.9"
47
47
  }
48
48
  }
package/src/Posts.astro CHANGED
@@ -118,7 +118,7 @@ const vars = [
118
118
  connects every comment & reply (they're all replies to the post). ---- */
119
119
  /* the cut owns its own landing offset (was `#kernel, #posts { scroll-margin-top }` in each persona —
120
120
  which orphaned once #posts moved here and carried this component's scope cid instead of the persona's). */
121
- .posts { border-block-start: 1px solid var(--border); scroll-margin-top: 82px; }
121
+ .posts { border-block-start: 1px solid var(--border); scroll-margin-top: 82px; scroll-margin-top: var(--shell-top, 82px); }
122
122
  /* A post is hoverable because it is a link to its own page, and the hover used to say so with a grey wash
123
123
  — `--text` at 3.5% — which reads as dimming rather than as lifting. It now uses the card material, so
124
124
  hovering a post looks like the same gesture as hovering a catalogue card.
package/src/Preroll.astro CHANGED
@@ -209,9 +209,7 @@ const safeId = "game-" + (id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/
209
209
  radial-gradient(90cqw 52cqh at 8% -12%, color-mix(in srgb, var(--accent) 26%, transparent), transparent 62%),
210
210
  radial-gradient(76cqw 46cqh at 96% 4%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 60%),
211
211
  radial-gradient(rgba(255, 255, 255, 0.055) 1px, transparent 1px) 0 0 / 24px 24px,
212
- /* The room's floor and its walls are one colour: @justai/ui declares --game-ground and paints
213
- the seam below the kernel with it, and a literal here would be a second black. */
214
- var(--game-ground, #080b12);
212
+ #080b12;
215
213
  color: #f5f7fa;
216
214
  }
217
215
  .pr-door[hidden] { display: none; }
package/src/Toolbar.astro CHANGED
@@ -82,8 +82,6 @@ interface Props {
82
82
  // half's default, which means copying core's `.pname` / `.handle` selectors into a second place
83
83
  // that nothing keeps in step. The strip is one line and its vocabulary should be one kind of
84
84
  // thing — names or sections, not one of each — so the API says so out loud.
85
- kernelTitle?: string;
86
- postsTitle?: string;
87
85
 
88
86
  // queries: toolbar shows a generic person icon · the profile icon is not my persona ·
89
87
  // how do I put my own mark in the toolbar · avatar
@@ -155,7 +153,7 @@ interface Props {
155
153
  import BackToZone from "./BackToZone.astro";
156
154
  const {
157
155
  sectionsLabel, profileLabel, kernelLabel, postsLabel,
158
- files = true, filesLabel = "Files", kernelTitle, postsTitle, avatar = "/icon.svg", parent,
156
+ files = true, filesLabel = "Files", avatar = "/icon.svg", parent,
159
157
  } = Astro.props;
160
158
  // A child's row answers UP to its parent, not out to the zone, and has no stream of its own — so
161
159
  // both default off the moment `parent` is given, rather than each consumer remembering to say so.
@@ -166,109 +164,108 @@ import AuthMount from "./AuthMount.astro";
166
164
  <!-- The two titles reach the script as data attributes rather than through `define:vars`, which would
167
165
  make this script inline and it has an import. Astro drops an attribute whose value is undefined,
168
166
  so a persona that passes neither leaves no trace in the markup at all. -->
169
- <header class="toolbar" data-kernel-title={kernelTitle} data-posts-title={postsTitle}>
170
- <div class="tb-row">
171
- <div class="tb-left">
172
- {home && <BackToZone apex={apex} />}
173
- <nav class="tb-nav-group" aria-label={sectionsLabel}>
174
- {/* POSITION ONE OF A CHILD'S ROW: the persona this one is mounted inside. `/icon.svg` is the
175
- parent's face here, because a child runs in the parent's origin — the same path, read from
176
- a different address. `#kernel` rather than `/` so the way back lands on the parent's work
177
- and not on its biography, which is where a person who came from there was standing. */}
178
- {parent && (
179
- <a class="tb-nav tb-mark" id="navParent" href={parent.href ?? "/#kernel"} aria-label={parent.label ?? "Home"} title={parent.label ?? "Home"}>
180
- <img src={parent.icon ?? "/icon.svg"} alt="" width="20" height="20" loading="lazy" decoding="async" />
167
+ <header class="toolbar">
168
+ <div class="tb-row">
169
+ <div class="tb-left">
170
+ {home && <BackToZone apex={apex} />}
171
+ <nav class="tb-nav-group" aria-label={sectionsLabel}>
172
+ {/* POSITION ONE OF A CHILD'S ROW: the persona this one is mounted inside. `/icon.svg` is the
173
+ parent's face here, because a child runs in the parent's origin — the same path, read from
174
+ a different address. `#kernel` rather than `/` so the way back lands on the parent's work
175
+ and not on its biography, which is where a person who came from there was standing. */}
176
+ {parent && (
177
+ <a class="tb-nav tb-mark" id="navParent" href={parent.href ?? "/#kernel"} aria-label={parent.label ?? "Home"} title={parent.label ?? "Home"}>
178
+ <img src={parent.icon ?? "/icon.svg"} alt="" width="20" height="20" loading="lazy" decoding="async" />
179
+ </a>
180
+ )}
181
+ {/* THE PROFILE ICON IS THE PERSONA'S OWN FACE. Always — the founder's rule, and app.zone and
182
+ qr had already settled it while thirteen siblings still showed a generic bust.
183
+
184
+ The bust is gone rather than demoted. A fallback that renders something plausible is how a
185
+ persona ships wearing nobody's face for months: nothing is broken, nothing is red, and the
186
+ only reader who notices is somebody comparing two personas side by side. `/icon.svg` is
187
+ not a guess — it is the ecosystem's one-face rule, the same path `persona.yml` declares
188
+ and the registry stores.
189
+
190
+ `tb-mark` is set whichever way the face arrives, because it is what the sizing rule looks
191
+ for: a mark runs to the edge of its viewBox and a glyph does not, so they need different
192
+ boxes to put the same ink on screen. */}
193
+ {/* `tb-mark` says "a solid MARK is in this box" — it is what the sizing rule looks for, and a
194
+ mark runs to the edge of its viewBox where a stroke glyph sits inside 75% of one. A
195
+ persona's face is always a mark, so a persona always carries the class.
196
+
197
+ A CHILD IS THE OTHER CASE, and it was measured rather than assumed: files passes a stroke
198
+ folder, and with `tb-mark` on it, it rendered at 19px beside a 25.33px bolt — one size
199
+ smaller, which is exactly the defect the 25.33 rule exists to remove. So in child mode the
200
+ slotted icon takes the GLYPH box and the row reads level. A child that draws a solid mark
201
+ instead should say so in its own CSS; every child in the fleet draws a glyph today. */}
202
+ <a class:list={["tb-nav", { "tb-mark": !parent }]} id="navProfile" href="#profile" aria-label={profileLabel} title={profileLabel}>
203
+ {/* A CHILD MUST PASS ITS OWN MARK. The default `/icon.svg` is the face of whoever owns this
204
+ origin — right for a persona, and its PARENT for a child, which would put the same
205
+ picture in two places and say nothing in either. So when `parent` is given there is no
206
+ fallback: a child that passes nothing renders an empty box, which is a defect somebody
207
+ sees, rather than a duplicate face, which is a defect nobody reports. */}
208
+ {Astro.slots.has("profileIcon")
209
+ ? <slot name="profileIcon" />
210
+ : (!parent && <img src={avatar} alt="" width="20" height="20" loading="lazy" decoding="async" />)}
181
211
  </a>
182
- )}
183
- {/* THE PROFILE ICON IS THE PERSONA'S OWN FACE. Always — the founder's rule, and app.zone and
184
- qr had already settled it while thirteen siblings still showed a generic bust.
185
-
186
- The bust is gone rather than demoted. A fallback that renders something plausible is how a
187
- persona ships wearing nobody's face for months: nothing is broken, nothing is red, and the
188
- only reader who notices is somebody comparing two personas side by side. `/icon.svg` is
189
- not a guess — it is the ecosystem's one-face rule, the same path `persona.yml` declares
190
- and the registry stores.
191
-
192
- `tb-mark` is set whichever way the face arrives, because it is what the sizing rule looks
193
- for: a mark runs to the edge of its viewBox and a glyph does not, so they need different
194
- boxes to put the same ink on screen. */}
195
- {/* `tb-mark` says "a solid MARK is in this box" — it is what the sizing rule looks for, and a
196
- mark runs to the edge of its viewBox where a stroke glyph sits inside 75% of one. A
197
- persona's face is always a mark, so a persona always carries the class.
198
-
199
- A CHILD IS THE OTHER CASE, and it was measured rather than assumed: files passes a stroke
200
- folder, and with `tb-mark` on it, it rendered at 19px beside a 25.33px bolt — one size
201
- smaller, which is exactly the defect the 25.33 rule exists to remove. So in child mode the
202
- slotted icon takes the GLYPH box and the row reads level. A child that draws a solid mark
203
- instead should say so in its own CSS; every child in the fleet draws a glyph today. */}
204
- <a class:list={["tb-nav", { "tb-mark": !parent }]} id="navProfile" href="#profile" aria-label={profileLabel} title={profileLabel}>
205
- {/* A CHILD MUST PASS ITS OWN MARK. The default `/icon.svg` is the face of whoever owns this
206
- origin — right for a persona, and its PARENT for a child, which would put the same
207
- picture in two places and say nothing in either. So when `parent` is given there is no
208
- fallback: a child that passes nothing renders an empty box, which is a defect somebody
209
- sees, rather than a duplicate face, which is a defect nobody reports. */}
210
- {Astro.slots.has("profileIcon")
211
- ? <slot name="profileIcon" />
212
- : (!parent && <img src={avatar} alt="" width="20" height="20" loading="lazy" decoding="async" />)}
213
- </a>
214
- {/* THE KERNEL IS ALWAYS THE BOLT. The founder's rule, and it is the shell's to draw rather
215
- than the persona's to remember.
216
-
217
- It was a bare `<slot name="kernelIcon" />` with NO fallback, which is the worst shape a
218
- slot can have: a persona that passed nothing shipped a live, invisible tap target where
219
- every sibling showed a mark — no error, no warning, and visible only beside another
220
- persona. Fourteen of fifteen passed their own drawing instead, so the row said something
221
- different in every repo about the same thing.
222
-
223
- The bolt says WHAT THE SECTION IS — the persona's one job, its live surface — and the
224
- profile icon two places to the left already says WHO. An icon that repeats the identity
225
- spends the row's only distinction on a thing the row has already said. */}
226
- <a class="tb-nav" id="navKernel" href="#kernel" aria-label={kernelLabel} title={kernelLabel}>
227
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.9 3L5.7 13.35h5.4L10.2 21l8.1-10.8h-5.4l.9-7.2z"/></svg>
228
- </a>
229
- {posts && (
230
- <a class="tb-nav" id="navPosts" href="#posts" aria-label={postsLabel} title={postsLabel}>
231
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.4 8.4 0 0 1-9 8.3 9.6 9.6 0 0 1-4-.9L3 21l1.1-5A8.4 8.4 0 1 1 21 11.5z"/></svg>
212
+ {/* THE KERNEL IS ALWAYS THE BOLT. The founder's rule, and it is the shell's to draw rather
213
+ than the persona's to remember.
214
+
215
+ It was a bare `<slot name="kernelIcon" />` with NO fallback, which is the worst shape a
216
+ slot can have: a persona that passed nothing shipped a live, invisible tap target where
217
+ every sibling showed a mark — no error, no warning, and visible only beside another
218
+ persona. Fourteen of fifteen passed their own drawing instead, so the row said something
219
+ different in every repo about the same thing.
220
+
221
+ The bolt says WHAT THE SECTION IS — the persona's one job, its live surface — and the
222
+ profile icon two places to the left already says WHO. An icon that repeats the identity
223
+ spends the row's only distinction on a thing the row has already said. */}
224
+ <a class="tb-nav" id="navKernel" href="#kernel" aria-label={kernelLabel} title={kernelLabel}>
225
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.9 3L5.7 13.35h5.4L10.2 21l8.1-10.8h-5.4l.9-7.2z"/></svg>
226
+ </a>
227
+ {posts && (
228
+ <a class="tb-nav" id="navPosts" href="#posts" aria-label={postsLabel} title={postsLabel}>
229
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.4 8.4 0 0 1-9 8.3 9.6 9.6 0 0 1-4-.9L3 21l1.1-5A8.4 8.4 0 1 1 21 11.5z"/></svg>
230
+ </a>
231
+ )}
232
+ <slot name="navExtra" />
233
+ </nav>
234
+ {files && (
235
+ // queries: files icon in the toolbar · how do I reach my files from a persona · the folder
236
+ // in the toolbar · why is files not in the section nav
237
+ //
238
+ // THE PERSONA'S FILES, ONE TAP FROM ANYWHERE IN IT.
239
+ //
240
+ // Until this, the only way into `<persona>/files` was to be asked for a file — the room
241
+ // where your things live could be entered only by a persona's invitation, which is exactly
242
+ // backwards for a room that is yours.
243
+ //
244
+ // OUTSIDE the sections nav, and deliberately: profile, kernel and posts are parts of THIS
245
+ // page and their links are fragments. `/files` is a different document — a place, not a
246
+ // section — and putting a navigation to elsewhere inside `<nav aria-label="sections">`
247
+ // would tell a screen reader it is one of them. Same reasoning the `leftExtra` slot below
248
+ // already carries, which is why this sits beside it rather than in the group above.
249
+ //
250
+ // ON BY DEFAULT, because the edge mounts `/files` on EVERY persona host: a persona that had
251
+ // to opt in would be a persona whose files exist and cannot be found. One bump here reaches
252
+ // the whole fleet, which is the only shape that survives a thousand of them.
253
+ <a class="tb-nav tb-files" id="navFiles" href="/files" aria-label={filesLabel} title={filesLabel}>
254
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7.5A1.5 1.5 0 0 1 4.5 6h4L11 8.5h8.5A1.5 1.5 0 0 1 21 10v7a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 17z"/></svg>
232
255
  </a>
233
256
  )}
234
- <slot name="navExtra" />
235
- </nav>
236
- {files && (
237
- // queries: files icon in the toolbar · how do I reach my files from a persona · the folder
238
- // in the toolbar · why is files not in the section nav
239
- //
240
- // THE PERSONA'S FILES, ONE TAP FROM ANYWHERE IN IT.
241
- //
242
- // Until this, the only way into `<persona>/files` was to be asked for a file — the room
243
- // where your things live could be entered only by a persona's invitation, which is exactly
244
- // backwards for a room that is yours.
245
- //
246
- // OUTSIDE the sections nav, and deliberately: profile, kernel and posts are parts of THIS
247
- // page and their links are fragments. `/files` is a different document — a place, not a
248
- // section — and putting a navigation to elsewhere inside `<nav aria-label="sections">`
249
- // would tell a screen reader it is one of them. Same reasoning the `leftExtra` slot below
250
- // already carries, which is why this sits beside it rather than in the group above.
251
- //
252
- // ON BY DEFAULT, because the edge mounts `/files` on EVERY persona host: a persona that had
253
- // to opt in would be a persona whose files exist and cannot be found. One bump here reaches
254
- // the whole fleet, which is the only shape that survives a thousand of them.
255
- <a class="tb-nav tb-files" id="navFiles" href="/files" aria-label={filesLabel} title={filesLabel}>
256
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7.5A1.5 1.5 0 0 1 4.5 6h4L11 8.5h8.5A1.5 1.5 0 0 1 21 10v7a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 17z"/></svg>
257
- </a>
258
- )}
259
- <!-- beside the section nav, but deliberately OUTSIDE it: a link that is not a section of this
260
- page (justai.pro carries app.zone's mark here). Keeping it out of <nav aria-label=sections>
261
- is the a11y half of the reason it is its own slot. -->
262
- <slot name="leftExtra" />
257
+ <!-- beside the section nav, but deliberately OUTSIDE it: a link that is not a section of this
258
+ page (justai.pro carries app.zone's mark here). Keeping it out of <nav aria-label=sections>
259
+ is the a11y half of the reason it is its own slot. -->
260
+ <slot name="leftExtra" />
261
+ </div>
262
+ <div class="tb-right">
263
+ <slot name="toolbarRight" />
264
+ <slot name="langPicker" />
265
+ <AuthMount />
266
+ </div>
263
267
  </div>
264
- <div class="tb-right">
265
- <slot name="toolbarRight" />
266
- <slot name="langPicker" />
267
- <AuthMount />
268
- </div>
269
- </div>
270
- <div class="tb-title" id="tbTitle"><span class="tb-title-text" id="tbTitleText"></span></div>
271
- </header>
268
+ </header>
272
269
 
273
270
  <style>
274
271
  /* ---- app toolbar — sticky to the top of the active region (kernel + posts); it never
@@ -328,54 +325,23 @@ import AuthMount from "./AuthMount.astro";
328
325
  @media (min-width: 640px) { .toolbar { margin-inline: -28px; padding-inline: 28px; } }
329
326
  /* icons row + the scroll-reactive title strip below it */
330
327
  .tb-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
331
- /* queries: --tb-strip · the title strip's height · the toolbar changes height · 26px ·
332
- * the kernel is 26px short · the game frame does not reach the fold
333
- *
334
- * ── THE ONE NUMBER THAT MAKES THIS ROW'S HEIGHT A MOVING TARGET, DECLARED SO IT CAN BE READ ──
335
- *
336
- * The strip opens and closes over 0.35s, so `.toolbar`'s height is anywhere in a 26px range at any
337
- * given moment — and anything that measures the row and feeds a LAYOUT with it is sampling an
338
- * animation. `--shell-top` did exactly that and the kernel's height came out 26px short whenever
339
- * the page happened to be measured with the strip open, which is to say whenever somebody opened
340
- * the persona at #kernel. It reads as a strip of the next section showing above the fold.
341
- *
342
- * So the number is a custom property rather than a literal: this rule uses it, and @justai/core's
343
- * `personaScroll` reads it to compute the row's EXPANDED height without waiting for or racing the
344
- * transition — `toolbar - strip` is the row, and the row plus this is what the bar will be. One
345
- * declaration, two readers, and nothing samples a moving value. */
346
- .toolbar { --tb-strip: 26px; }
347
- /* queries: the bar grows after load · why does the strip animate on arrival · data-motion ·
348
- * first paint animation · can this transition wait for the first interaction
349
- *
350
- * ── THE TRANSITION IS ALSO A DAMPER, WHICH IS WHY IT CANNOT SIMPLY WAIT ─────────────────────
351
- *
352
- * The founder asked the obvious and right question: *"şu geçiş süresi güzel — ama neden bu özellik
353
- * kullanıcının ilk interaction'ından sonra aktif edilmiyor?"* A persona lands on its kernel, so the
354
- * strip's correct state on the first frame is open; animating into it grows the bar 26px just after
355
- * the page appears, which is a glitch nobody asked for.
328
+ /* queries: where is the title strip · tb-title · the persona's name under the icons · tbTitle
356
329
  *
357
- * IT WAS TRIED, AND IT BREAKS SOMETHING ELSE. Gated behind a `data-motion` flag set on the first
358
- * pointer/key/wheel, the strip snaps open during the landing — and that 26px arrives in a SINGLE
359
- * frame, inside `#below`, while the scroll spy is deciding which cut is active. That is the
360
- * bistable oscillator `personaScroll` documents at length: the spy measures a page its own output
361
- * moved. Measured: with the gate in place, `#navProfile` no longer navigates — the page re-asserts
362
- * the kernel and stays. The 0.35s is not only easing; it is what keeps that step out of one frame.
330
+ * ── THERE IS NO SECONDARY STRIP, AND THAT IS A DECISION ──────────────────────────────────
363
331
  *
364
- * SO THE HEIGHT IS NEVER READ INSTEAD. `--shell-top` is computed as `row + --tb-strip` — the row
365
- * being the bar minus whatever the strip currently is, which is the same number at every frame of
366
- * the transition. Nothing samples the animation, so nothing depends on when it was sampled.
332
+ * A second row under the icons carried the current cut's name and opened over 0.35s. It cost more
333
+ * than it said. `position: sticky` never leaves flow, so the row's LIVE height positioned every
334
+ * section beneath it — 52 shut, 78 open — while anything that measured the shell had to freeze one
335
+ * of those two numbers and was therefore wrong in the other state. That gap is a band of the next
336
+ * section above the fold; on a game persona, whose kernel is an EXACT height, it is on the glass.
337
+ * It also coupled the scroll spy to the layout: the spy decided which cut was current, that opened
338
+ * the strip, the strip moved the page, and the spy read the page it had just moved.
367
339
  *
368
- * The real fix for the founder's question is a toolbar whose height does not change at all: reserve
369
- * the strip's space always and fade only its content. That removes the feedback at the source and
370
- * makes the gate free — and it is a fleet-wide design decision about how the bar looks at the
371
- * profile, so it is his to take rather than one to slip in. */
372
- .tb-title { display: flex; align-items: center; height: 0; overflow: hidden; opacity: 0; transition: height 0.35s var(--ease-out), opacity 0.25s var(--ease-out); }
373
- /* The fallback is not decoration: the token is declared on `.toolbar` and consumed here, which is
374
- a different selector — so the framework's own token spec reads it as ungrounded and is right to.
375
- A rule that silently collapses to `height: 0` would close the strip and say nothing. */
376
- .tb-title.show { height: 26px; height: var(--tb-strip, 26px); opacity: 1; }
377
- .tb-title-text { font-size: var(--fs-sm); font-weight: 600; letter-spacing: -0.01em; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: opacity 0.16s var(--ease-out); }
378
- .tb-title-text.fade { opacity: 0; }
340
+ * The founder's ruling, 2026-08-06: *"secondary şeridi tamamen kaldır. net karar."* So the bar is
341
+ * one row and one height, always. Nothing above the kernel changes size, and every derivation that
342
+ * existed to survive that change is gone with it — `--tb-strip`, the slot that reserved a constant
343
+ * box, the painted band that filled the reserve, and the probe that measured the strip before it
344
+ * opened. The name is on the profile, which is where a name belongs. */
379
345
  /* nav lives on the left, beside the back affordance — the middle is intentionally empty */
380
346
  .tb-left { display: flex; align-items: center; gap: 2px; min-width: 0; }
381
347
  .tb-nav-group { display: flex; align-items: center; gap: 2px; }
@@ -542,15 +508,6 @@ import AuthMount from "./AuthMount.astro";
542
508
  const ownMark = document.querySelector("#navProfile img");
543
509
  if (ownMark) adoptMark({ id: "navProfile" });
544
510
 
545
- // Both or neither — see the props above. When both are set the strip names the SECTIONS; core's
546
- // default, which names the persona and its handle, is left entirely alone otherwise. Nothing here
547
- // reproduces that default, which is the point: `.pname` and `.handle` stay core's business.
548
- const bar = document.querySelector(".toolbar") as HTMLElement | null;
549
- const kt = bar?.dataset.kernelTitle;
550
- const pt = bar?.dataset.postsTitle;
551
- personaScroll(
552
- kt && pt
553
- ? { titleFor: (id: string) => (id === "kernel" ? kt : id === "posts" ? pt : "") }
554
- : undefined,
555
- );
511
+ // No titleFor: the bar has one row and no strip to name anything in. See the note in the styles.
512
+ personaScroll();
556
513
  </script>