beatrina 0.9.43 → 1.0.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/app/Beatrina.app/Contents/Info.plist +86 -0
- package/app/Beatrina.app/Contents/MacOS/beatrina +0 -0
- package/app/Beatrina.app/Contents/Resources/icon.icns +0 -0
- package/app/beatrina.png +0 -0
- package/app/linux-arm64/beatrina +0 -0
- package/app/win-x64/Beatrina-setup.exe +0 -0
- package/beatrina_V1.0.0.html +1906 -0
- package/beatrina_V1.0.0.html.inputs.json +1 -0
- package/bin/beatrina.mjs +200 -12
- package/bin/cli.mjs +8 -3
- package/bin/finder.mjs +1 -1
- package/bin/shortcut.mjs +15 -15
- package/build-info.json +1 -1
- package/host/engine-node-job.mjs +35 -0
- package/host/engine-pool.mjs +153 -26
- package/host/engine-r.mjs +8 -1
- package/host/jobs/document-child.mjs +271 -0
- package/host/journal-store.mjs +19 -3
- package/host/latex-compile.mjs +673 -0
- package/host/main.mjs +58 -18
- package/host/planes/analyze.mjs +18 -2
- package/host/planes/choose.mjs +13 -2
- package/host/planes/expect-term.mjs +102 -0
- package/host/planes/jobs.mjs +38 -5
- package/host/planes/sessions.mjs +5 -1
- package/host/planes/terminal.mjs +23 -9
- package/host/pwa/icon-192.png +0 -0
- package/host/pwa/icon-512.png +0 -0
- package/host/quarto.mjs +118 -0
- package/host/server.mjs +83 -2
- package/host/worker-plane.mjs +7 -1
- package/kernel/check/acceptance.mjs +43 -12
- package/kernel/check/knit-file.mjs +300 -52
- package/kernel/check/session.mjs +19 -4
- package/kernel/kernel-version +1 -1
- package/kernel/knitr-run.R +8 -1
- package/kernel/mcp/beatrina-mcp.mjs +6 -5
- package/kernel/worker.R +21 -1
- package/lib/engine-labels.js +7 -1
- package/menu/Beatrina Menu.app/Contents/Info.plist +2 -2
- package/menu/Beatrina Menu.app/Contents/MacOS/Beatrina Menu +0 -0
- package/package.json +4 -3
- package/beatrina_V0.9.43.html +0 -1885
- package/beatrina_V0.9.43.html.inputs.json +0 -1
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
+
var __esm = (fn, res, err) => function __init() {
|
|
3
|
+
if (err) throw err[0];
|
|
4
|
+
try {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
} catch (e) {
|
|
7
|
+
throw err = [e], e;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// lib/engine-labels.js
|
|
12
|
+
var KNOWN_ENGINES, BY_KEY, AUTHORING_ENGINES;
|
|
13
|
+
var init_engine_labels = __esm({
|
|
14
|
+
"lib/engine-labels.js"() {
|
|
15
|
+
KNOWN_ENGINES = Object.freeze([
|
|
16
|
+
Object.freeze({ key: "r", label: "R" }),
|
|
17
|
+
Object.freeze({ key: "python", label: "Python" }),
|
|
18
|
+
Object.freeze({ key: "js", label: "JavaScript" }),
|
|
19
|
+
Object.freeze({ key: "bash", label: "Bash" }),
|
|
20
|
+
Object.freeze({ key: "sql", label: "SQL" })
|
|
21
|
+
]);
|
|
22
|
+
BY_KEY = new Map(KNOWN_ENGINES.map((e) => [e.key, e.label]));
|
|
23
|
+
AUTHORING_ENGINES = Object.freeze(KNOWN_ENGINES.map((e) => e.key));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
1
27
|
// tools/beatrina/knit-file.mjs
|
|
2
28
|
import fs from "node:fs";
|
|
3
29
|
import path from "node:path";
|
|
@@ -1629,10 +1655,18 @@ var BEATRINA_CSS = `
|
|
|
1629
1655
|
.cn-root .beatrina-ai-capability{
|
|
1630
1656
|
border:1px solid transparent;padding:3px 9px;
|
|
1631
1657
|
}
|
|
1632
|
-
/*
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
.cn-root .beatrina-ai-capability
|
|
1658
|
+
/* ONE entrance in every layout (2026-09-22): "Code \u25BE" \u2014 the word acts, the
|
|
1659
|
+
arrow holds Chat and Plan. The three capability buttons stay in the DOM,
|
|
1660
|
+
hidden; the destination toggle is still the sheet layout's alone. */
|
|
1661
|
+
.cn-root .beatrina-ai-capability{display:none;}
|
|
1662
|
+
.cn-root .beatrina-ai-destination-toggle{display:none;}
|
|
1663
|
+
.cn-root .beatrina-ai-capability-one,.cn-root .beatrina-ai-capability-more{
|
|
1664
|
+
display:inline-flex;align-items:center;color:#fff;background:var(--cn-accent,#4e79a7);border:1px solid transparent;
|
|
1665
|
+
}
|
|
1666
|
+
.cn-root .beatrina-ai-capability-one{font-weight:750;padding:3px 8px 3px 9px;border-radius:6px 0 0 6px;margin-right:0;}
|
|
1667
|
+
.cn-root .beatrina-ai-capability-more{padding:3px 6px;border-radius:0 6px 6px 0;margin-left:-1px;border-left:1px solid rgba(255,255,255,.35);}
|
|
1668
|
+
.cn-root .beatrina-ai-capability-one:hover:not(:disabled),.cn-root .beatrina-ai-capability-more:hover:not(:disabled){color:#fff;background:var(--cn-accent-deep,#3a6a9f);}
|
|
1669
|
+
.cn-root .beatrina-ai-capability-more .beatrina-ai-quickwrite-caret{font-size:10px;opacity:.9;pointer-events:none;}
|
|
1636
1670
|
.cn-root .beatrina-ai-capability[data-intent="ask"]{
|
|
1637
1671
|
color:var(--cn-accent-deep,#3a6a9f);background:transparent;
|
|
1638
1672
|
}
|
|
@@ -2327,6 +2361,12 @@ var BEATRINA_CSS = `
|
|
|
2327
2361
|
background:var(--cn-control-bg);color:var(--cn-text);
|
|
2328
2362
|
}
|
|
2329
2363
|
.cn-root .beatrina-prompt-input:focus{outline:none;border-color:var(--cn-accent);box-shadow:var(--cn-focus-ring);}
|
|
2364
|
+
/* The multi-line form (Writing mode's Edit source): Markdown, so the mono
|
|
2365
|
+
face and the size a source is read at; resizable downward only. */
|
|
2366
|
+
.cn-root textarea.beatrina-prompt-input{
|
|
2367
|
+
font-family:var(--cn-mono);font-size:var(--cn-fs);line-height:1.5;
|
|
2368
|
+
min-width:min(560px, 80vw);resize:vertical;
|
|
2369
|
+
}
|
|
2330
2370
|
|
|
2331
2371
|
/* \u2500\u2500 the prompt editor \u2014 the words, and the right to change them \u2500\u2500 */
|
|
2332
2372
|
.cn-root .beatrina-modal-panel.is-prompts{width:min(860px,95vw);}
|
|
@@ -3370,6 +3410,11 @@ var BEATRINA_CSS = `
|
|
|
3370
3410
|
color:rgba(255,255,255,.72);font:12px var(--cn-font);pointer-events:none;
|
|
3371
3411
|
animation:beatrina-focus-in .26s ease;
|
|
3372
3412
|
}
|
|
3413
|
+
/* A Text cell on its own: a LIGHT, quiet page around the prose (owner,
|
|
3414
|
+
2026-09-22: "it is all dark"). The code chunk keeps the dark haze. */
|
|
3415
|
+
.cn-root.beatrina-focus-prose .beatrina-focus-haze{background:color-mix(in srgb, var(--cn-bg,#fff) 94%, transparent);}
|
|
3416
|
+
.cn-root.beatrina-focus-prose .beatrina-focus-note{color:var(--cn-text-dim,#666);}
|
|
3417
|
+
.cn-root.beatrina-focus-prose .cell.beatrina-focus-cell{box-shadow:0 1px 0 var(--cn-border,#e3e7ef),0 12px 40px rgba(0,0,0,.08);}
|
|
3373
3418
|
/* Narrower than the notebook, and a WORKING surface rather than a card.
|
|
3374
3419
|
660px with the chunk's own height left a three-line chunk as a small box
|
|
3375
3420
|
adrift in a large dark screen (owner, 2026-09-11: "This is so small"). The
|
|
@@ -3721,6 +3766,65 @@ var BEATRINA_CSS = `
|
|
|
3721
3766
|
}
|
|
3722
3767
|
.cn-root .beatrina-source-view .beatrina-highlight .mdh-yaml{color:var(--cn-text);}
|
|
3723
3768
|
|
|
3769
|
+
/* \u2500\u2500 Source mode reads like a README on GitHub (owner, 2026-09-22: "the
|
|
3770
|
+
source mode is ugly and horrible, even reading a readme on github is
|
|
3771
|
+
better") \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3772
|
+
Everything below is DECORATION of the same bytes: no glyph changes and no
|
|
3773
|
+
line moves, so the transparent textarea stays exactly over its colour.
|
|
3774
|
+
|
|
3775
|
+
A reading width. At Full page width a prose line ran 1,400 px; a README is
|
|
3776
|
+
read at about a thousand. Centred in whatever the page gives it. */
|
|
3777
|
+
.cn-root .beatrina-source-view{max-width:min(100%, 1080px);margin:0 auto;}
|
|
3778
|
+
/* Prose always wraps here, whatever the code-chunk wrap setting says
|
|
3779
|
+
(lib/source-view.js passes softWrap: "always" to the surface, which makes
|
|
3780
|
+
the gutter follow the wrapped rows). */
|
|
3781
|
+
.cn-root .beatrina-source-view textarea.beatrina-code,
|
|
3782
|
+
.cn-root .beatrina-source-view .beatrina-highlight{white-space:pre-wrap;overflow-wrap:break-word;}
|
|
3783
|
+
.cn-root .beatrina-source-view textarea.beatrina-code{overflow-x:hidden;}
|
|
3784
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span{display:block;}
|
|
3785
|
+
.cn-root .beatrina-source-view .beatrina-code-wrap::after,
|
|
3786
|
+
.cn-root .beatrina-source-view .beatrina-code-wrap::before{content:none;}
|
|
3787
|
+
/* Code blocks and the front matter on a band (lib/qmd-language.js names
|
|
3788
|
+
each line's region). Widened by a negative margin and an equal padding, so
|
|
3789
|
+
the band reaches past the text while the text itself stays exactly where
|
|
3790
|
+
the textarea puts it and wraps at the same width. */
|
|
3791
|
+
.cn-root .beatrina-source-view{
|
|
3792
|
+
--src-code-bg:color-mix(in srgb, var(--cn-text) 5%, var(--ed-bg, var(--cn-surface)));
|
|
3793
|
+
--src-yaml-bg:color-mix(in srgb, var(--cn-text) 3%, var(--ed-bg, var(--cn-surface)));
|
|
3794
|
+
}
|
|
3795
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span:is(.qmd-open, .qmd-code, .qmd-close),
|
|
3796
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span.qmd-yaml{
|
|
3797
|
+
margin:0 -10px;padding:0 10px;background:var(--src-code-bg);
|
|
3798
|
+
}
|
|
3799
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span.qmd-yaml{background:var(--src-yaml-bg);}
|
|
3800
|
+
/* A line is 13 \xD7 1.62 = 21.06 px tall, so neighbouring bands meet on a
|
|
3801
|
+
fraction of a pixel and the page shows through as a hairline seam. Each
|
|
3802
|
+
band line casts its own colour one pixel down to close it (not the last). */
|
|
3803
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span:is(.qmd-open, .qmd-code){box-shadow:0 1px 0 var(--src-code-bg);}
|
|
3804
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span.qmd-yaml:has(+ span.qmd-yaml){box-shadow:0 1px 0 var(--src-yaml-bg);}
|
|
3805
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span.qmd-open{border-radius:6px 6px 0 0;}
|
|
3806
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span.qmd-close{border-radius:0 0 6px 6px;}
|
|
3807
|
+
.cn-root .beatrina-source-view .beatrina-highlight > span.qmd-open + span.qmd-close{border-radius:6px;}
|
|
3808
|
+
/* Headings in the editor theme's function colour, so they lead in every
|
|
3809
|
+
theme \u2014 in Plain the accent is graphite and a heading read as bold text. */
|
|
3810
|
+
.cn-root .beatrina-source-view .beatrina-highlight .mdh-h{color:var(--rtok-fn, var(--cn-accent-deep));}
|
|
3811
|
+
/* Copy all above the text; Copy beside each block's opening fence
|
|
3812
|
+
(lib/source-copy.js). Quiet until pointed at; a done copy says so in words
|
|
3813
|
+
and in the Okabe-Ito green \u2014 never by colour alone. */
|
|
3814
|
+
.cn-root .beatrina-src-actions{display:flex;justify-content:flex-end;margin:0 0 6px;}
|
|
3815
|
+
.cn-root .beatrina-src-copies{position:absolute;inset:0;pointer-events:none;z-index:3;}
|
|
3816
|
+
.cn-root .beatrina-src-copy{
|
|
3817
|
+
display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 8px;
|
|
3818
|
+
font:500 var(--cn-fs-xs,11px)/1 var(--cn-font);color:var(--cn-text-muted);
|
|
3819
|
+
background:var(--cn-surface);border:1px solid var(--cn-border);border-radius:6px;cursor:pointer;
|
|
3820
|
+
}
|
|
3821
|
+
.cn-root .beatrina-src-copies .beatrina-src-copy{position:absolute;right:4px;margin-top:-1px;pointer-events:auto;opacity:.62;}
|
|
3822
|
+
.cn-root .beatrina-src-copy svg{width:13px;height:13px;flex:none;}
|
|
3823
|
+
.cn-root .beatrina-src-copy:hover,.cn-root .beatrina-src-copy:focus-visible{opacity:1;color:var(--cn-accent-deep);border-color:var(--cn-control-border);}
|
|
3824
|
+
.cn-root .beatrina-src-copy:focus-visible{outline:2px solid var(--cn-accent);outline-offset:1px;}
|
|
3825
|
+
.cn-root .beatrina-src-copy.is-done{opacity:1;color:#009E73;border-color:#009E73;}
|
|
3826
|
+
@media print{.cn-root .beatrina-src-actions,.cn-root .beatrina-src-copies{display:none!important;}}
|
|
3827
|
+
|
|
3724
3828
|
/* \u2500\u2500 result bar: fold / clear \u2500\u2500 */
|
|
3725
3829
|
.cn-root .beatrina-output-bar{
|
|
3726
3830
|
display:flex;align-items:center;gap:5px;margin:3px 0 0;
|
|
@@ -4389,7 +4493,10 @@ var BEATRINA_CSS = `
|
|
|
4389
4493
|
.cn-root .beatrina-md-tool:focus-visible{outline:0;box-shadow:var(--cn-focus-ring);}
|
|
4390
4494
|
.cn-root .beatrina-md-tool.is-cite{color:var(--cn-accent);}
|
|
4391
4495
|
.cn-root .beatrina-md-tool-label{font:600 var(--cn-fs-sm) var(--cn-font);}
|
|
4392
|
-
|
|
4496
|
+
/* width as well as flex-basis: WebKit leaves a basis-only item out of the bar's max-content
|
|
4497
|
+
width, so the bar came out 4 px short at every fold level and folded everything behind \u22EE
|
|
4498
|
+
(Beatrina's window, 2026-09-23). */
|
|
4499
|
+
.cn-root .beatrina-md-bar-sp{flex:0 0 4px;width:4px;}
|
|
4393
4500
|
.cn-root .beatrina-md-count{
|
|
4394
4501
|
font-size:var(--cn-fs-sm);opacity:.55;font-variant-numeric:tabular-nums;margin-right:2px;
|
|
4395
4502
|
}
|
|
@@ -4471,10 +4578,10 @@ var BEATRINA_CSS = `
|
|
|
4471
4578
|
/* The row's fixed groups leave the bar roughly (viewport \u2212 1000) px. It
|
|
4472
4579
|
gives up its least essential pixels first, and every group it drops is
|
|
4473
4580
|
still on the \u22EE shelf, labelled, with its key \u2014 a narrow window costs a
|
|
4474
|
-
click, never a command. Order of surrender: the
|
|
4475
|
-
|
|
4581
|
+
click, never a command. Order of surrender: the count, breathing room,
|
|
4582
|
+
the insert group, the blocks group. (Cite is a word with no glyph now, so
|
|
4583
|
+
it is never shrunk to one.) */
|
|
4476
4584
|
@media (max-width:1640px){
|
|
4477
|
-
.cn-root header .beatrina-md-bar .is-cite .beatrina-md-tool-label{display:none;}
|
|
4478
4585
|
.cn-root header .beatrina-md-bar .beatrina-md-count{display:none;}
|
|
4479
4586
|
}
|
|
4480
4587
|
@media (max-width:1560px){
|
|
@@ -4493,7 +4600,7 @@ var BEATRINA_CSS = `
|
|
|
4493
4600
|
.cn-root header .beatrina-md-bar[data-fold="3"] .beatrina-md-group.is-insert,
|
|
4494
4601
|
.cn-root header .beatrina-md-bar[data-fold="3"] .beatrina-md-group.is-blocks,
|
|
4495
4602
|
.cn-root header .beatrina-md-bar[data-fold="3"] .beatrina-md-group.is-history{display:none;}
|
|
4496
|
-
.cn-root header .beatrina-md-bar[data-fold="4"] .beatrina-md-group:not(.is-text),
|
|
4603
|
+
.cn-root header .beatrina-md-bar[data-fold="4"] .beatrina-md-group:not(.is-text):not(.is-cite-lead),
|
|
4497
4604
|
.cn-root header .beatrina-md-bar[data-fold="4"] .is-text .beatrina-md-tool:not([data-command="prose.bold"]):not([data-command="prose.italic"]),
|
|
4498
4605
|
.cn-root header .beatrina-md-bar[data-fold="5"] .beatrina-md-group{display:none;}
|
|
4499
4606
|
/* At the last fold what is left (the \u22EE shelf and Done) is the bar's minimum:
|
|
@@ -4545,7 +4652,7 @@ var BEATRINA_CSS = `
|
|
|
4545
4652
|
.cn-root .beatrina-md-morebar{
|
|
4546
4653
|
display:block; /* .beatrina-pop is a column flexbox, and a flexbox has no CSS columns */
|
|
4547
4654
|
columns:var(--beatrina-menu-cols,2);column-gap:14px;column-rule:1px solid var(--cn-border-soft);
|
|
4548
|
-
width:min(calc(var(--beatrina-menu-cols,2) *
|
|
4655
|
+
width:min(calc(var(--beatrina-menu-cols,2) * var(--beatrina-menu-colw) + 30px), calc(100vw - 24px));
|
|
4549
4656
|
max-height:calc(100vh - 100px);overflow-y:auto;padding:6px 8px 2px;
|
|
4550
4657
|
}
|
|
4551
4658
|
.cn-root .beatrina-md-pop-group{break-inside:avoid;-webkit-column-break-inside:avoid;margin:0 0 8px;}
|
|
@@ -4851,18 +4958,22 @@ var BEATRINA_CSS = `
|
|
|
4851
4958
|
.cn-root .cell.beatrina-md-cell:focus-within .beatrina-cell-rail{
|
|
4852
4959
|
pointer-events:auto;
|
|
4853
4960
|
}
|
|
4961
|
+
/* A bit larger (owner, 2026-09-22): 24px buttons, 15px glyphs \u2014 the most the 32px gutter band holds. */
|
|
4854
4962
|
.cn-root .beatrina-cell-rail-btn{
|
|
4855
4963
|
position:relative;
|
|
4856
4964
|
display:flex;align-items:center;justify-content:center;
|
|
4857
|
-
width:
|
|
4965
|
+
width:24px;height:24px;padding:0;border:0;border-radius:7px;
|
|
4858
4966
|
background:transparent;cursor:pointer;
|
|
4859
|
-
color:color-mix(in srgb, var(--cn-text)
|
|
4967
|
+
color:color-mix(in srgb, var(--cn-text) 55%, transparent);
|
|
4860
4968
|
transition:color var(--cn-dur-1),background var(--cn-dur-1);
|
|
4861
4969
|
}
|
|
4862
4970
|
.cn-root .beatrina-cell-rail-btn svg{
|
|
4863
|
-
width:
|
|
4971
|
+
width:15px;height:15px;
|
|
4864
4972
|
transition:transform var(--cn-dur-1);
|
|
4865
4973
|
}
|
|
4974
|
+
/* The lock, once on, stays visible: a locked cell says so without a hover. */
|
|
4975
|
+
.cn-root .cell.locked .beatrina-cell-rail{pointer-events:auto;}
|
|
4976
|
+
.cn-root .cell.locked .beatrina-cell-rail-btn[data-command="text.lock"]{color:var(--cn-accent-deep);opacity:1;}
|
|
4866
4977
|
.cn-root .beatrina-cell-rail-btn:hover{
|
|
4867
4978
|
background:color-mix(in srgb, var(--cn-accent) 13%, transparent);
|
|
4868
4979
|
color:var(--cn-accent-deep);
|
|
@@ -5117,6 +5228,8 @@ var BEATRINA_CSS = `
|
|
|
5117
5228
|
font:700 var(--cn-fs-sm,12.5px) var(--cn-font);border:1px solid #E69F00;background:#E69F00;color:#1a1300;}
|
|
5118
5229
|
.cn-root .beatrina-tolatex:hover{filter:brightness(1.06);}
|
|
5119
5230
|
.cn-root .beatrina-tolatex:focus-visible{outline:2px solid var(--beatrina-hdr-focus,#fff);outline-offset:2px;}
|
|
5231
|
+
/* "Open <stem>.tex": a file name can be long; the button keeps its row. */
|
|
5232
|
+
.cn-root .beatrina-tolatex.is-open{max-width:220px;overflow:hidden;text-overflow:ellipsis;}
|
|
5120
5233
|
/* In LaTeX the same place SAYS where you are \u2014 green, a dot as well as the
|
|
5121
5234
|
colour, and not a button any more. */
|
|
5122
5235
|
.cn-root .beatrina-tolatex.is-latex{background:#009E73;border-color:#009E73;color:#fff;cursor:default;}
|
|
@@ -5168,10 +5281,13 @@ var BEATRINA_CSS = `
|
|
|
5168
5281
|
Import Data \xB7 Save drop their words) makes the room \u2014 the document's
|
|
5169
5282
|
name outranks three verbs that keep their icons. */
|
|
5170
5283
|
.cn-root .hdr-row-id .beatrina-docsw{order:7;flex:0 1 auto;min-width:120px;position:relative;}
|
|
5284
|
+
/* A BUTTON you can see (owner, 2026-09-22: "it should be open documents and
|
|
5285
|
+
should be clearer"): the header's own button face, the words on it, not a
|
|
5286
|
+
faint pill with a glyph. */
|
|
5171
5287
|
.cn-root .hdr-row-id .beatrina-docsw-btn{
|
|
5172
|
-
display:inline-flex;align-items:center;gap:
|
|
5173
|
-
border-radius:
|
|
5174
|
-
color:var(--beatrina-hdr-fg);font:
|
|
5288
|
+
display:inline-flex;align-items:center;gap:8px;height:30px;max-width:min(360px,100%);min-width:0;padding:0 12px 0 10px;
|
|
5289
|
+
border-radius:8px;border:1px solid var(--beatrina-hdr-line);background:var(--beatrina-hdr-wash);box-shadow:none;
|
|
5290
|
+
color:var(--beatrina-hdr-fg);font:600 var(--cn-fs-sm,12.5px) var(--cn-font);cursor:pointer;
|
|
5175
5291
|
}
|
|
5176
5292
|
.cn-root .hdr-row-id .beatrina-docsw-btn:hover{background:var(--beatrina-hdr-wash);}
|
|
5177
5293
|
.cn-root .hdr-row-id .beatrina-docsw-btn[aria-expanded="true"]{background:var(--beatrina-hdr-wash-2);}
|
|
@@ -5181,38 +5297,102 @@ var BEATRINA_CSS = `
|
|
|
5181
5297
|
}
|
|
5182
5298
|
.cn-root .beatrina-docsw-kind.is-notebook{border-color:transparent;background:var(--beatrina-hdr-wash-2);color:var(--beatrina-hdr-fg);}
|
|
5183
5299
|
.cn-root .beatrina-docsw-name{font:600 11px var(--cn-mono);color:var(--beatrina-hdr-fg);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
5300
|
+
.cn-root .beatrina-docsw-word{font:600 var(--cn-fs-sm,12.5px) var(--cn-font);color:var(--beatrina-hdr-fg);white-space:nowrap;}
|
|
5184
5301
|
.cn-root .beatrina-docsw-count{font:500 var(--cn-fs-xs) var(--cn-font);color:var(--beatrina-hdr-fg-faint);white-space:nowrap;}
|
|
5185
5302
|
.cn-root .beatrina-docsw-count:empty{display:none;}
|
|
5186
5303
|
.cn-root .beatrina-docsw-caret{font-size:9px;color:var(--beatrina-hdr-fg-faint);}
|
|
5187
|
-
.cn-root .beatrina-docsw .hdr-export-drop{left:auto;right:0;width:
|
|
5188
|
-
.cn-root .beatrina-docsw-drop .beatrina-docsw-badge{border-color:var(--cn-border);color:var(--cn-text-dim);background:var(--cn-surface);}
|
|
5304
|
+
.cn-root .beatrina-docsw .hdr-export-drop{left:auto;right:0;width:540px;max-width:calc(100vw - 24px);}
|
|
5305
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-badge{border-color:var(--cn-border);color:var(--cn-text-dim);background:var(--cn-surface);min-width:26px;height:20px;font-size:10px;}
|
|
5306
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-head{display:flex;align-items:center;justify-content:space-between;gap:8px;white-space:nowrap;}
|
|
5307
|
+
.cn-root .beatrina-docsw-head-note{font:500 10.5px var(--cn-font);color:var(--cn-text-dim);text-transform:none;letter-spacing:0;}
|
|
5308
|
+
.cn-root .beatrina-docsw-list{display:flex;flex-direction:column;gap:0;padding:2px 0;}
|
|
5309
|
+
.cn-root .beatrina-docsw-list > * + *{border-top:1px solid var(--cn-border-soft,#eef1f5);}
|
|
5310
|
+
/* A drawn icon per kind, the kind's badge under it. */
|
|
5311
|
+
.cn-root .beatrina-docsw-icon{display:inline-flex;flex-direction:column;align-items:center;gap:2px;width:36px;flex:0 0 36px;color:var(--cn-text-dim);}
|
|
5312
|
+
.cn-root .beatrina-docsw-icon svg{width:18px;height:18px;}
|
|
5313
|
+
.cn-root .beatrina-docsw-icon .beatrina-docsw-badge{min-width:0;height:14px;padding:0 4px;font-size:8.5px;}
|
|
5189
5314
|
.cn-root .beatrina-docsw-drop .beatrina-docsw-row{
|
|
5190
|
-
display:grid;grid-template-columns:
|
|
5191
|
-
align-items:center;column-gap:
|
|
5192
|
-
border:0;border-radius:
|
|
5315
|
+
display:grid;grid-template-columns:36px minmax(0,1fr) auto 30px;grid-template-rows:auto auto;
|
|
5316
|
+
align-items:center;column-gap:10px;row-gap:2px;text-align:left;width:100%;padding:8px 10px;margin:0;
|
|
5317
|
+
border:0;border-radius:8px;background:transparent;color:var(--cn-text);cursor:pointer;font:var(--cn-fs-sm) var(--cn-font);
|
|
5193
5318
|
}
|
|
5194
5319
|
.cn-root .beatrina-docsw-drop .beatrina-docsw-row:hover{background:var(--cn-control-bg);}
|
|
5195
5320
|
.cn-root .beatrina-docsw-drop .beatrina-docsw-row:focus-visible{outline:2px solid var(--cn-accent);outline-offset:-2px;}
|
|
5196
|
-
|
|
5321
|
+
/* The one on screen: a wash, a bar at its edge, and the words "on screen" \u2014 never colour alone. */
|
|
5322
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-row[aria-current="true"]{background:var(--cn-accent-soft,#eef3f8);box-shadow:inset 3px 0 0 var(--cn-accent);}
|
|
5323
|
+
/* Every cell PLACED, not auto-flowed: the path in row 2 of column 2 sat under
|
|
5324
|
+
the chip's would-be column, so auto-placement pushed the chip one column
|
|
5325
|
+
right and the \xD7 into an implicit fifth \u2014 measured 36px 374px 0 30px 28px. */
|
|
5326
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-row > .beatrina-docsw-icon{grid-column:1;grid-row:1 / span 2;}
|
|
5327
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-row > .beatrina-docsw-mode{grid-column:3;grid-row:1 / span 2;}
|
|
5328
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-row > .beatrina-docsw-x{grid-column:4;grid-row:1 / span 2;}
|
|
5329
|
+
.cn-root .beatrina-docsw-main{grid-column:2;grid-row:1;display:inline-flex;align-items:center;gap:7px;min-width:0;}
|
|
5330
|
+
.cn-root .beatrina-docsw-here{font:500 10.5px var(--cn-font);color:var(--cn-accent);white-space:nowrap;}
|
|
5197
5331
|
.cn-root .beatrina-docsw-dot{width:7px;height:7px;border-radius:50%;border:1px solid var(--cn-border);background:transparent;}
|
|
5198
5332
|
.cn-root .beatrina-docsw-dot.is-dirty{background:#E69F00;border-color:#E69F00;}
|
|
5199
5333
|
.cn-root .beatrina-docsw-dot.is-running{background:#56B4E9;border-color:#56B4E9;}
|
|
5200
|
-
.cn-root .beatrina-docsw-drop .beatrina-docsw-label{font:600
|
|
5334
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-label{font:600 12.5px var(--cn-font);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
5201
5335
|
.cn-root .beatrina-docsw-mode{
|
|
5202
5336
|
font:600 9.5px var(--cn-font);letter-spacing:.06em;text-transform:uppercase;color:var(--cn-text-dim);
|
|
5203
5337
|
border:1px solid var(--cn-border);border-radius:4px;padding:1px 4px;line-height:1.2;white-space:nowrap;
|
|
5204
5338
|
}
|
|
5205
5339
|
.cn-root .beatrina-docsw-mode:empty{visibility:hidden;}
|
|
5206
5340
|
.cn-root .beatrina-docsw-mode.is-writing{color:#8e5b00;border-color:#e6c47a;}
|
|
5207
|
-
.cn-root .beatrina-docsw-
|
|
5208
|
-
.
|
|
5209
|
-
.cn-root .beatrina-docsw-
|
|
5341
|
+
.cn-root .beatrina-docsw-mode.is-on{color:var(--cn-accent);border-color:var(--cn-accent);}
|
|
5342
|
+
/* A Close you can see: a bordered square on every row. */
|
|
5343
|
+
.cn-root .beatrina-docsw-x{
|
|
5344
|
+
width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;
|
|
5345
|
+
border:1px solid var(--cn-border);border-radius:7px;background:var(--cn-surface);
|
|
5346
|
+
color:var(--cn-text-dim);font-size:16px;line-height:1;text-align:center;
|
|
5347
|
+
}
|
|
5348
|
+
.cn-root .beatrina-docsw-x:hover{color:#c5221f;border-color:#c5221f;background:#fce8e6;}
|
|
5349
|
+
.cn-root .beatrina-docsw-x.is-off,.cn-root .beatrina-docsw-x.is-off:hover{opacity:.35;cursor:default;color:var(--cn-text-dim);border-color:var(--cn-border);background:var(--cn-surface);}
|
|
5350
|
+
.cn-root .beatrina-docsw-sub{grid-column:2;grid-row:2;display:flex;align-items:baseline;gap:5px;min-width:0;}
|
|
5351
|
+
.cn-root .beatrina-docsw-path{flex:0 1 auto;min-width:0;font:10.5px var(--cn-font);color:var(--cn-text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
5352
|
+
/* The footer: ONE row \u2014 New \u25BE \xB7 Open\u2026 on the left, Close apart on the right; an icon and a word each. */
|
|
5353
|
+
.cn-root .beatrina-docsw-foot{display:flex;flex-wrap:nowrap;gap:8px;align-items:center;padding:10px 8px 6px;margin-top:6px;border-top:1px solid var(--cn-border);}
|
|
5354
|
+
.cn-root .beatrina-docsw-new{position:relative;display:inline-flex;}
|
|
5355
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-fbtn{
|
|
5356
|
+
width:auto;flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;height:28px;min-height:28px;padding:0 11px 0 9px;
|
|
5357
|
+
border:1px solid var(--cn-border);border-radius:7px;background:var(--cn-surface);color:var(--cn-text);
|
|
5358
|
+
font:600 12px var(--cn-font);cursor:pointer;
|
|
5359
|
+
}
|
|
5360
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-fbtn svg{width:14px;height:14px;flex:0 0 auto;color:var(--cn-text-dim);}
|
|
5361
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-fbtn:not(:disabled):hover{background:var(--cn-control-bg);}
|
|
5362
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-fbtn:disabled{opacity:.45;cursor:default;}
|
|
5363
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-fbtn .beatrina-menu-label{overflow:visible;}
|
|
5364
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-fbtn .beatrina-docsw-caret{font-size:9px;color:var(--cn-text-dim);}
|
|
5365
|
+
.cn-root .beatrina-docsw-newmenu{
|
|
5366
|
+
position:absolute;left:0;bottom:calc(100% + 6px);display:flex;flex-direction:column;gap:2px;min-width:200px;padding:6px;
|
|
5367
|
+
background:var(--cn-bg,#fff);border:1px solid var(--cn-border);border-radius:9px;box-shadow:0 8px 24px rgba(0,0,0,.14);z-index:3;
|
|
5368
|
+
}
|
|
5369
|
+
.cn-root .beatrina-docsw-newmenu[hidden]{display:none;}
|
|
5370
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-newmenu button.beatrina-docsw-fbtn{border-color:transparent;background:transparent;width:100%;justify-content:flex-start;font-weight:500;}
|
|
5371
|
+
.cn-root .beatrina-docsw-drop .beatrina-docsw-newmenu button.beatrina-docsw-fbtn:not(:disabled):hover{background:var(--cn-control-bg);}
|
|
5372
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-fbtn.is-close{margin-left:auto;color:#c5221f;border-color:#e5b4b0;}
|
|
5373
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-fbtn.is-close .beatrina-docsw-x-glyph{font-size:16px;line-height:1;}
|
|
5374
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-fbtn.is-close:not(:disabled):hover{background:#fce8e6;}
|
|
5210
5375
|
.cn-root .beatrina-docsw-recent{display:flex !important;align-items:center;gap:8px;color:var(--cn-text-dim);}
|
|
5376
|
+
.cn-root .beatrina-docsw-facts{flex:0 0 auto;font:10.5px var(--cn-font);color:var(--cn-text);white-space:nowrap;}
|
|
5377
|
+
/* Specific enough to beat the drop's generic button rule (which stretched it to 434px, measured). */
|
|
5378
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-clear{
|
|
5379
|
+
margin-left:auto;width:auto;flex:0 0 auto;display:inline-flex;align-items:center;height:22px;min-height:22px;padding:0 9px;
|
|
5380
|
+
border:1px solid var(--cn-border);border-radius:6px;background:var(--cn-surface);
|
|
5381
|
+
color:var(--cn-text-dim);font:600 10.5px var(--cn-font);letter-spacing:0;text-transform:none;cursor:pointer;
|
|
5382
|
+
}
|
|
5383
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-clear:not(:disabled):hover{color:#c5221f;border-color:#c5221f;background:#fce8e6;}
|
|
5384
|
+
.cn-root .beatrina-docsw-drop button.beatrina-docsw-clear:disabled{opacity:.4;cursor:default;}
|
|
5385
|
+
.cn-root .beatrina-docsw-forget{
|
|
5386
|
+
flex:0 0 auto;width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;
|
|
5387
|
+
border:1px solid transparent;border-radius:6px;color:var(--cn-text-dim);font-size:14px;line-height:1;
|
|
5388
|
+
}
|
|
5389
|
+
.cn-root .beatrina-docsw-recent:hover .beatrina-docsw-forget{border-color:var(--cn-border);}
|
|
5390
|
+
.cn-root .beatrina-docsw-forget:hover{color:#c5221f;border-color:#c5221f !important;background:#fce8e6;}
|
|
5211
5391
|
.cn-root .beatrina-docsw-recent .beatrina-docsw-label{font:500 11.5px var(--cn-mono);}
|
|
5212
5392
|
/* A recent row: the name over its path, when it was at the right. */
|
|
5213
5393
|
.cn-root .beatrina-docsw-recent-text{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1 1 auto;}
|
|
5214
5394
|
.cn-root .beatrina-docsw-recent .beatrina-docsw-path{grid-column:auto;grid-row:auto;}
|
|
5215
|
-
.cn-root .beatrina-docsw-when{flex:0 0 auto;font:10.5px var(--cn-font);color:var(--cn-text
|
|
5395
|
+
.cn-root .beatrina-docsw-when{flex:0 0 auto;font:10.5px var(--cn-font);color:var(--cn-text);white-space:nowrap;}
|
|
5216
5396
|
.cn-root .beatrina-docsw-note{font:10.5px var(--cn-font);color:var(--cn-text-dim);padding:8px 8px 2px;}
|
|
5217
5397
|
|
|
5218
5398
|
.cn-root .hdr-row-id .beatrina-kernel{order:8;}
|
|
@@ -5485,11 +5665,18 @@ var BEATRINA_CSS = `
|
|
|
5485
5665
|
The Code menu read this way since 7.5 and the strips beside it did not;
|
|
5486
5666
|
the owner called that out (2026-09-03), so now File \u25BE through Help \u25BE all
|
|
5487
5667
|
do. Width is derived from the column count so every panel shares one
|
|
5488
|
-
recipe.
|
|
5668
|
+
recipe.
|
|
5669
|
+
|
|
5670
|
+
ONE column width for every panel, wide enough for the longest row a menu
|
|
5671
|
+
carries \u2014 icon, a sentence of a label, a shortcut. At 226 px, "Send
|
|
5672
|
+
Selection or Line to C\u2026", "Restart R and Run All Chunk\u2026", "Convert again
|
|
5673
|
+
from Markdo\u2026" were all cut with room to spare in the window (FINDINGS
|
|
5674
|
+
2026-09-22 B11); 272 px holds the longest with its key, measured. */
|
|
5675
|
+
.cn-root{--beatrina-menu-colw:272px;}
|
|
5489
5676
|
.cn-root .beatrina-menu-drop.beatrina-menu-cols{
|
|
5490
5677
|
columns:var(--beatrina-menu-cols,3);column-gap:16px;
|
|
5491
5678
|
column-rule:1px solid var(--cn-border-soft);
|
|
5492
|
-
width:min(calc(var(--beatrina-menu-cols,3) *
|
|
5679
|
+
width:min(calc(var(--beatrina-menu-cols,3) * var(--beatrina-menu-colw) + 40px), calc(100vw - 24px));
|
|
5493
5680
|
padding:10px 12px 6px;
|
|
5494
5681
|
}
|
|
5495
5682
|
.cn-root .beatrina-menu-cols .beatrina-menu-group{
|
|
@@ -5705,6 +5892,17 @@ var BEATRINA_CSS = `
|
|
|
5705
5892
|
.cn-root[data-app-theme="plain"] .beatrina-ai-capability[data-intent="plan"]{
|
|
5706
5893
|
background:var(--cn-accent-soft);color:var(--cn-text);
|
|
5707
5894
|
}
|
|
5895
|
+
/* Code \u25BE is an OUTLINED pill here, like Quick write and Pin beside it: a
|
|
5896
|
+
graphite fill read as a black block (owner, 2026-09-22: "overly 3d"). */
|
|
5897
|
+
.cn-root:is([data-app-theme="flat"],[data-app-theme="plain"]) .beatrina-ai-capability-one,
|
|
5898
|
+
.cn-root:is([data-app-theme="flat"],[data-app-theme="plain"]) .beatrina-ai-capability-more{
|
|
5899
|
+
background:transparent;color:var(--cn-text);border-color:var(--cn-border-strong,#c9ced6);box-shadow:none;font-weight:600;
|
|
5900
|
+
}
|
|
5901
|
+
.cn-root:is([data-app-theme="flat"],[data-app-theme="plain"]) .beatrina-ai-capability-more{border-left-color:var(--cn-border-strong,#c9ced6);}
|
|
5902
|
+
.cn-root:is([data-app-theme="flat"],[data-app-theme="plain"]) .beatrina-ai-capability-one:hover:not(:disabled),
|
|
5903
|
+
.cn-root:is([data-app-theme="flat"],[data-app-theme="plain"]) .beatrina-ai-capability-more:hover:not(:disabled){
|
|
5904
|
+
background:var(--cn-control-bg);color:var(--cn-text);
|
|
5905
|
+
}
|
|
5708
5906
|
.cn-root[data-app-theme="plain"] .beatrina-chunk-name-input{border-color:var(--cn-border-strong);}
|
|
5709
5907
|
/* Save is an ACTION, and its blue is a literal that predates the accent
|
|
5710
5908
|
token \u2014 in a monochrome theme it follows the accent like every other
|
|
@@ -5946,7 +6144,8 @@ var BEATRINA_CSS = `
|
|
|
5946
6144
|
destination is one toggle. All three controls exist in the DOM under every
|
|
5947
6145
|
layout (lib/ai-code-button.js) \u2014 this is where the layout chooses. */
|
|
5948
6146
|
.cn-root[data-chunk-layout="sheet"] .beatrina-ai-capability{display:none;}
|
|
5949
|
-
.cn-root[data-chunk-layout="sheet"] .beatrina-ai-capability-one
|
|
6147
|
+
.cn-root[data-chunk-layout="sheet"] .beatrina-ai-capability-one,.cn-root[data-chunk-layout="sheet"] .beatrina-ai-capability-more,
|
|
6148
|
+
.cn-root[data-chunk-layout="sheet"] .beatrina-ai-capability-one:hover:not(:disabled),.cn-root[data-chunk-layout="sheet"] .beatrina-ai-capability-more:hover:not(:disabled){display:inline-flex;align-items:center;color:var(--cn-text-muted);background:transparent;font-weight:500;border-color:transparent;}
|
|
5950
6149
|
.cn-root[data-chunk-layout="sheet"] .beatrina-ai-context-group{display:none;}
|
|
5951
6150
|
.cn-root[data-chunk-layout="sheet"] .beatrina-ai-destination-button{display:none;}
|
|
5952
6151
|
.cn-root[data-chunk-layout="sheet"] .beatrina-ai-destination-toggle{display:inline-flex;cursor:pointer;white-space:nowrap;font:500 var(--cn-fs-xs) var(--cn-font);}
|
|
@@ -7488,15 +7687,32 @@ var BEATRINA_CSS = `
|
|
|
7488
7687
|
position:sticky;top:0;z-index:1;background:var(--cn-surface);
|
|
7489
7688
|
border-bottom:1px solid var(--cn-border);padding:0;text-align:left;
|
|
7490
7689
|
}
|
|
7690
|
+
/* The header's first line is TWO sibling buttons in one band: the name
|
|
7691
|
+
(select the column) and the arrow (sort). Siblings, not nested \u2014 a button
|
|
7692
|
+
inside a button is invalid and the inner one had no keyboard path (N13).
|
|
7693
|
+
The band carries the hover and selected paint so the pair reads as one
|
|
7694
|
+
header; the 10 px outer padding is split across the two so the name still
|
|
7695
|
+
starts on the same vertical as the distribution line below it. */
|
|
7696
|
+
.cn-root .beatrina-grid-head{display:flex;align-items:stretch;}
|
|
7491
7697
|
.cn-root .beatrina-grid-sort{
|
|
7492
|
-
display:flex;align-items:center;gap:4px;width:
|
|
7698
|
+
display:flex;align-items:center;gap:4px;flex:1 1 auto;min-width:0;padding:5px 4px 5px 10px;
|
|
7493
7699
|
font:600 11px var(--cn-font);color:var(--cn-text-muted);cursor:pointer;
|
|
7494
7700
|
background:transparent;border:0;white-space:nowrap;
|
|
7495
7701
|
}
|
|
7496
7702
|
.cn-root .beatrina-grid th.is-num .beatrina-grid-sort{justify-content:flex-end;}
|
|
7497
|
-
.cn-root .beatrina-grid-
|
|
7498
|
-
.cn-root .beatrina-grid
|
|
7499
|
-
.cn-root .beatrina-grid-arrow{
|
|
7703
|
+
.cn-root .beatrina-grid-head:hover{background:var(--cn-accent-soft);}
|
|
7704
|
+
.cn-root .beatrina-grid-head:hover .beatrina-grid-sort,
|
|
7705
|
+
.cn-root .beatrina-grid-head:hover .beatrina-grid-arrow{color:var(--cn-accent-deep);}
|
|
7706
|
+
.cn-root .beatrina-grid th.is-sorted .beatrina-grid-sort,
|
|
7707
|
+
.cn-root .beatrina-grid th.is-sorted .beatrina-grid-arrow{color:var(--cn-accent-deep);}
|
|
7708
|
+
.cn-root .beatrina-grid-arrow{
|
|
7709
|
+
flex:0 0 auto;padding:5px 10px 5px 4px;border:0;background:transparent;cursor:pointer;
|
|
7710
|
+
font:600 9px var(--cn-font);line-height:1;color:var(--cn-text-muted);
|
|
7711
|
+
}
|
|
7712
|
+
.cn-root .beatrina-grid-sort:focus-visible,
|
|
7713
|
+
.cn-root .beatrina-grid-arrow:focus-visible{
|
|
7714
|
+
outline:2px solid var(--cn-accent-deep);outline-offset:-2px;
|
|
7715
|
+
}
|
|
7500
7716
|
.cn-root .beatrina-grid td{
|
|
7501
7717
|
padding:3px 10px;border-bottom:1px solid var(--cn-border-soft);
|
|
7502
7718
|
white-space:nowrap;max-width:28ch;overflow:hidden;text-overflow:ellipsis;
|
|
@@ -7527,12 +7743,15 @@ var BEATRINA_CSS = `
|
|
|
7527
7743
|
.cn-root .beatrina-grid td.is-sel-bottom{--sel-b:var(--cn-accent-deep,#31537a);}
|
|
7528
7744
|
.cn-root .beatrina-grid td.is-sel-left{--sel-l:var(--cn-accent-deep,#31537a);}
|
|
7529
7745
|
.cn-root .beatrina-grid td.is-sel-right{--sel-r:var(--cn-accent-deep,#31537a);}
|
|
7530
|
-
.cn-root .beatrina-grid th.is-selected .beatrina-grid-sort
|
|
7531
|
-
|
|
7746
|
+
.cn-root .beatrina-grid th.is-selected .beatrina-grid-sort,
|
|
7747
|
+
.cn-root .beatrina-grid th.is-selected .beatrina-grid-arrow{color:var(--cn-accent-deep);}
|
|
7748
|
+
.cn-root .beatrina-grid th.is-selected .beatrina-grid-head{
|
|
7749
|
+
background:var(--cn-accent-soft);
|
|
7532
7750
|
box-shadow:inset 0 -2px 0 var(--cn-accent-deep,#31537a);
|
|
7533
7751
|
}
|
|
7534
7752
|
.cn-root .beatrina-grid-arrow.is-idle{opacity:.45;}
|
|
7535
|
-
.cn-root .beatrina-grid-
|
|
7753
|
+
.cn-root .beatrina-grid-head:hover .beatrina-grid-arrow.is-idle,
|
|
7754
|
+
.cn-root .beatrina-grid-arrow.is-idle:focus-visible{opacity:.9;}
|
|
7536
7755
|
.cn-root .beatrina-grid .beatrina-grid-idx{
|
|
7537
7756
|
position:sticky;left:0;background:var(--cn-surface);color:var(--cn-text-dim);
|
|
7538
7757
|
font-family:var(--cn-mono);font-size:10px;text-align:right;padding:3px 8px;
|
|
@@ -8806,6 +9025,22 @@ var BEATRINA_CSS = `
|
|
|
8806
9025
|
color:var(--cn-text-dim);font:500 var(--cn-fs-sm,11px) var(--cn-mono);white-space:nowrap;background:transparent;border:0;box-shadow:none;padding:0;
|
|
8807
9026
|
}
|
|
8808
9027
|
.cn-root .beatrina-context-separator{height:1px;margin:4px 8px;background:var(--cn-border-soft);}
|
|
9028
|
+
/* An icon row (the writing page's B \xB7 I \xB7 U \xB7 <>): the formats as one line of
|
|
9029
|
+
square buttons at the head of the menu, the way a word processor's
|
|
9030
|
+
right-click leads with them. Lit = the selection already carries it. */
|
|
9031
|
+
.cn-root .beatrina-context-iconrow{display:flex;gap:2px;padding:2px 6px;}
|
|
9032
|
+
.cn-root .beatrina-context-iconbtn{
|
|
9033
|
+
display:inline-flex;align-items:center;justify-content:center;width:32px;height:30px;padding:0;
|
|
9034
|
+
border:0;border-radius:var(--cn-radius-sm,6px);background:transparent;color:var(--cn-text-muted);cursor:pointer;
|
|
9035
|
+
}
|
|
9036
|
+
.cn-root .beatrina-context-iconbtn svg{display:block;width:16px;height:16px;}
|
|
9037
|
+
.cn-root .beatrina-context-iconbtn.is-word{width:auto;padding:0 9px;font:600 var(--cn-fs,13px)/1 var(--cn-font);}
|
|
9038
|
+
.cn-root .beatrina-context-iconbtn:hover,.cn-root .beatrina-context-iconbtn:focus{
|
|
9039
|
+
outline:0;background:color-mix(in srgb,var(--cn-accent) 10%,var(--cn-surface));color:var(--cn-accent-deep);
|
|
9040
|
+
}
|
|
9041
|
+
.cn-root .beatrina-context-iconbtn:focus-visible{outline:2px solid var(--cn-accent);outline-offset:-2px;}
|
|
9042
|
+
.cn-root .beatrina-context-iconbtn.is-on{background:color-mix(in srgb,var(--cn-accent) 16%,var(--cn-surface));color:var(--cn-accent-deep);}
|
|
9043
|
+
.cn-root .beatrina-context-iconbtn:disabled{opacity:.38;cursor:default;background:transparent;}
|
|
8809
9044
|
/* A group row opens a fly-out beside the menu (Beatrina AI on the selection). The
|
|
8810
9045
|
caret is the only sign; the row itself reads like every other item. */
|
|
8811
9046
|
.cn-root .beatrina-context-item.is-submenu.is-open{
|
|
@@ -10431,6 +10666,14 @@ var BEATRINA_CSS = `
|
|
|
10431
10666
|
@media(max-width:760px){
|
|
10432
10667
|
.cn-root.has-ai-left{padding-left:0;}
|
|
10433
10668
|
.cn-root.has-ai-right{padding-right:0;}
|
|
10669
|
+
/* \u2026and so a docked pane is a SHEET over the whole window, not a 400 px
|
|
10670
|
+
slab over the right half of the words. Reserving its width at this size
|
|
10671
|
+
would leave a column of ~260 px; overlaying half the text left every line
|
|
10672
|
+
cut off under it (journey windows, 720 px, 2026-09-24). One or the other
|
|
10673
|
+
is on screen; \xD7 gives the document back. !important beats the inline
|
|
10674
|
+
left/right/width ai-shell.js writes for the wide layout. */
|
|
10675
|
+
.cn-root .beatrina-ai-panel.is-side{left:0 !important;right:0 !important;width:auto !important;}
|
|
10676
|
+
.cn-root .beatrina-ai-panel.is-side .beatrina-ai-sedge{display:none;}
|
|
10434
10677
|
}
|
|
10435
10678
|
|
|
10436
10679
|
.cn-root .beatrina-aiw-convbtn{flex:0 0 auto;width:24px;height:24px;
|
|
@@ -11167,13 +11410,16 @@ body:has(.cn-root[data-beatrina-mode="writing"] > .beatrina-writing-bar){--beatr
|
|
|
11167
11410
|
.cn-root[data-beatrina-mode="latex"] main > .beatrina-mtab-page{margin-bottom:0;}
|
|
11168
11411
|
.cn-root[data-beatrina-mode="latex"] > .cn-footer{display:none;}
|
|
11169
11412
|
|
|
11170
|
-
/* What goes away. The tab strip goes because the workbench IS the tab
|
|
11413
|
+
/* What goes away. The tab strip goes because the workbench IS the tab \u2014 while
|
|
11414
|
+
a .tex is in front; with Jobs, a data view or the console in front
|
|
11415
|
+
(data-latex-front="other", stamped by src/notebook-entry.js) it stays, or
|
|
11416
|
+
there is no visible way back (owner, 2026-09-22). The
|
|
11171
11417
|
status line and the working-directory row go because the rail says where
|
|
11172
11418
|
you are; the notebook's own add-strip and width control are answering
|
|
11173
11419
|
questions this mode does not ask. The kernel badge and the session plug
|
|
11174
11420
|
STAY \u2014 unlike Writing mode, R is live here and a reader has to be able to
|
|
11175
11421
|
see that it is, because Compile is about to need it. */
|
|
11176
|
-
.cn-root[data-beatrina-mode="latex"] .beatrina-mtabs,
|
|
11422
|
+
.cn-root[data-beatrina-mode="latex"]:not([data-latex-front="other"]) .beatrina-mtabs,
|
|
11177
11423
|
.cn-root[data-beatrina-mode="latex"] .beatrina-status,
|
|
11178
11424
|
.cn-root[data-beatrina-mode="latex"] .beatrina-wd,
|
|
11179
11425
|
.cn-root[data-beatrina-mode="latex"] .beatrina-addstrip,
|
|
@@ -11368,6 +11614,10 @@ body:has(.cn-root[data-beatrina-mode="writing"] > .beatrina-writing-bar){--beatr
|
|
|
11368
11614
|
.cn-root .beatrina-latex-rail-problems{flex:1 1 auto;min-height:0;overflow:auto;}
|
|
11369
11615
|
.cn-root .beatrina-latex-rail-problems .beatrina-problems{padding:4px 0;}
|
|
11370
11616
|
.cn-root .beatrina-latex-rail-problems .beatrina-problem{padding:7px 10px;}
|
|
11617
|
+
/* The Log view: the compiler's lines, as the console draws them. */
|
|
11618
|
+
.cn-root .beatrina-latex-rail-log{flex:1 1 auto;min-height:0;overflow:auto;font-size:var(--cn-fs-xs,11px);}
|
|
11619
|
+
.cn-root .beatrina-latex-rail-log-head{padding:6px 10px;color:var(--cn-muted,#666);}
|
|
11620
|
+
.cn-root .beatrina-latex-rail-log .beatrina-latex-rail-pre{margin:0;padding:4px 10px;white-space:pre-wrap;word-break:break-word;}
|
|
11371
11621
|
|
|
11372
11622
|
/* \u2500\u2500 the start panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
11373
11623
|
What the workbench shows before there is a .tex in it: the notebook you
|
|
@@ -11564,7 +11814,7 @@ body:has(.cn-root[data-beatrina-mode="writing"] > .beatrina-writing-bar){--beatr
|
|
|
11564
11814
|
box-shadow:0 -1px 0 var(--cn-border,#e3e3e3);
|
|
11565
11815
|
}
|
|
11566
11816
|
.beatrina-dock[hidden]{display:none;}
|
|
11567
|
-
.beatrina-dock[data-mode="bottom"]{left:
|
|
11817
|
+
.beatrina-dock[data-mode="bottom"]{left:var(--beatrina-ai-edge-left,0px);right:var(--beatrina-ai-edge-right,0px);bottom:0;flex-direction:column;}
|
|
11568
11818
|
.beatrina-dock[data-mode="right"]{
|
|
11569
11819
|
top:0;right:0;bottom:0;flex-direction:row;
|
|
11570
11820
|
box-shadow:-1px 0 0 var(--cn-border,#e3e3e3);
|
|
@@ -14692,7 +14942,8 @@ ${out}</div>
|
|
|
14692
14942
|
if (!ctx.rawUrls && !safeImageSrc(url)) {
|
|
14693
14943
|
return `<span class="beatrina-md-badsrc">[image: ${alt || "unsupported source"}]</span>`;
|
|
14694
14944
|
}
|
|
14695
|
-
|
|
14945
|
+
const local = ctx.localImages && /^(?![a-z][a-z0-9+.-]*:|\/\/|#)/i.test(url.trim());
|
|
14946
|
+
let out = local ? `<img data-local-src="${attrValue(url)}" alt="${alt}"` : `<img src="${attrValue(encodeHref(url))}" alt="${alt}"`;
|
|
14696
14947
|
if (node2.title) out += ` title="${attrValue(node2.title)}"`;
|
|
14697
14948
|
if (!ctx.spec) out += ' class="beatrina-md-img" loading="lazy"';
|
|
14698
14949
|
return ctx.spec ? `${out} />` : `${out}>`;
|
|
@@ -14781,6 +15032,7 @@ function toHtml(tree, opts = {}) {
|
|
|
14781
15032
|
// survived a JSON round-trip or a parsed query, does not open it.
|
|
14782
15033
|
rawHtml: opts.allowDangerousHtml === true,
|
|
14783
15034
|
rawUrls: opts.allowDangerousProtocol === true,
|
|
15035
|
+
localImages: opts.localImages === true,
|
|
14784
15036
|
gfm: opts.gfm !== false,
|
|
14785
15037
|
softBreak: typeof opts.softBreak === "string" ? opts.softBreak : "\n",
|
|
14786
15038
|
state: opts.state || {},
|
|
@@ -18484,17 +18736,6 @@ function citeStyleOf(notebook) {
|
|
|
18484
18736
|
};
|
|
18485
18737
|
}
|
|
18486
18738
|
|
|
18487
|
-
// lib/engine-labels.js
|
|
18488
|
-
var KNOWN_ENGINES = Object.freeze([
|
|
18489
|
-
Object.freeze({ key: "r", label: "R" }),
|
|
18490
|
-
Object.freeze({ key: "python", label: "Python" }),
|
|
18491
|
-
Object.freeze({ key: "js", label: "JavaScript" }),
|
|
18492
|
-
Object.freeze({ key: "bash", label: "Bash" }),
|
|
18493
|
-
Object.freeze({ key: "sql", label: "SQL" })
|
|
18494
|
-
]);
|
|
18495
|
-
var BY_KEY = new Map(KNOWN_ENGINES.map((e) => [e.key, e.label]));
|
|
18496
|
-
var AUTHORING_ENGINES = Object.freeze(KNOWN_ENGINES.map((e) => e.key));
|
|
18497
|
-
|
|
18498
18739
|
// lib/doc-mode.js
|
|
18499
18740
|
var MODES = Object.freeze(["development", "writing", "latex"]);
|
|
18500
18741
|
var MODE_KEY = "beatrina-mode";
|
|
@@ -19458,6 +19699,10 @@ ${references}
|
|
|
19458
19699
|
`;
|
|
19459
19700
|
}
|
|
19460
19701
|
|
|
19702
|
+
// lib/chunk-meta.js
|
|
19703
|
+
init_engine_labels();
|
|
19704
|
+
init_engine_labels();
|
|
19705
|
+
|
|
19461
19706
|
// src/r-kernel.js
|
|
19462
19707
|
function normalizeTable(frame) {
|
|
19463
19708
|
const rows = Array.isArray(frame.rows) ? frame.rows : frame.rows ? [frame.rows] : [];
|
|
@@ -19470,6 +19715,9 @@ function normalizeTable(frame) {
|
|
|
19470
19715
|
rows,
|
|
19471
19716
|
nrow: frame.nrow,
|
|
19472
19717
|
ncol: frame.ncol,
|
|
19718
|
+
// The frame's own width, row names not counted (worker.R; FINDINGS
|
|
19719
|
+
// 2026-09-22 B10). Absent from an older kernel, and then the page says ncol.
|
|
19720
|
+
...Number.isFinite(frame.dataCols) ? { dataCols: frame.dataCols } : {},
|
|
19473
19721
|
truncated: Boolean(frame.truncated),
|
|
19474
19722
|
shown: rows.length,
|
|
19475
19723
|
// The name the frame was printed under, when the printed expression was a
|
package/kernel/check/session.mjs
CHANGED
|
@@ -143,8 +143,14 @@ export function freePort() {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
/**
|
|
146
|
-
* Start a supervisor on `port`, open a page socket, and wait for
|
|
147
|
-
*
|
|
146
|
+
* Start a supervisor on `port`, open a page socket, and wait for it to be ready.
|
|
147
|
+
*
|
|
148
|
+
* A host that speaks the handshake sends `host-ready` first (plans/
|
|
149
|
+
* getting_rid_of_R.md K2). When its R row says R is NOT coming — absent, or
|
|
150
|
+
* failed to start — there is no R `ready` to wait for, and the session is the
|
|
151
|
+
* HOST: `ready` stays null, `hostReady` is the frame, `noR` says why. An older
|
|
152
|
+
* host sends no host-ready and is waited on for R's ready, as before.
|
|
153
|
+
* @returns {Promise<object>} the session: frames, until, text, run, ask, ready, hostReady, noR, startupMs, log, shutdown
|
|
148
154
|
*/
|
|
149
155
|
export async function startSession({ command, port, cwd, env = {}, readyMs = 90000, logFile = "" }) {
|
|
150
156
|
const t0 = Date.now();
|
|
@@ -214,7 +220,7 @@ export async function startSession({ command, port, cwd, env = {}, readyMs = 900
|
|
|
214
220
|
else { try { process.kill(child.pid, "SIGKILL"); } catch { /* gone */ } }
|
|
215
221
|
}
|
|
216
222
|
};
|
|
217
|
-
const session = { child, port, announced, page: null, frames: [], ready: null, startupMs: null, log: () => hostLog, shutdown };
|
|
223
|
+
const session = { child, port, announced, page: null, frames: [], ready: null, hostReady: null, noR: "", startupMs: null, log: () => hostLog, shutdown };
|
|
218
224
|
if (!announced) return session;
|
|
219
225
|
|
|
220
226
|
const page = await openSocket(port, `http://127.0.0.1:${port}`);
|
|
@@ -250,7 +256,16 @@ export async function startSession({ command, port, cwd, env = {}, readyMs = 900
|
|
|
250
256
|
const reply = await session.until((f) => f.id === id && f.type !== "stdout" && f.type !== "stderr", ms, from);
|
|
251
257
|
return { reply, ms: Date.now() - t };
|
|
252
258
|
};
|
|
253
|
-
|
|
259
|
+
// host-ready is the first frame on open, or never (an older host): a short wait decides.
|
|
260
|
+
session.hostReady = await session.until((f) => f.type === "host-ready" || f.type === "ready", 15000);
|
|
261
|
+
if (session.hostReady && session.hostReady.type === "ready") { session.ready = session.hostReady; session.hostReady = null; }
|
|
262
|
+
const rRow = session.hostReady && Array.isArray(session.hostReady.engine_status)
|
|
263
|
+
? session.hostReady.engine_status.find((e) => e.engine === "r") : null;
|
|
264
|
+
if (session.hostReady && (!rRow || !rRow.available || rRow.error)) {
|
|
265
|
+
session.noR = (rRow && (rRow.error || rRow.detail)) || "this host has no R engine";
|
|
266
|
+
} else if (!session.ready) {
|
|
267
|
+
session.ready = await session.until((f) => f.type === "ready", readyMs);
|
|
268
|
+
}
|
|
254
269
|
session.startupMs = Date.now() - t0;
|
|
255
270
|
return session;
|
|
256
271
|
}
|
package/kernel/kernel-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
1.0.0
|