bearminion 1.4.0 → 1.6.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/dist/ui/mount.js CHANGED
@@ -1,12 +1,13 @@
1
- import { a as sectionFieldKey, i as isPropShown, t as defaultTheme } from "../theme-DMpt3hcT.js";
2
- import { A as isImagePosition, D as IMAGE_FITS, E as DEFAULT_IMAGE_POSITION, O as IMAGE_POSITIONS, T as DEFAULT_IMAGE_FIT, i as isSystemPage, j as withImageLayout, k as isImageFit } from "../page-ON4Jkcm-.js";
1
+ import { a as sectionFieldKey, i as isPropShown, t as defaultTheme } from "../theme-DFjHjgFO.js";
2
+ import { B as withImageLayout, F as DEFAULT_IMAGE_POSITION, I as IMAGE_FITS, L as IMAGE_POSITIONS, P as DEFAULT_IMAGE_FIT, R as isImageFit, S as upsertJsonLd, b as parseJsonLdInput, g as isPlaceholderSiteUrl, i as isSystemPage, m as generateSiteJsonLd, p as formatJsonLd, v as jsonLdWarnings, z as isImagePosition } from "../page-NOFVEqn1.js";
3
3
  import { applyTextMark, fontMarks, marksFromEmphasis, reconcileMarks, renderMarkedHtml } from "../marks.js";
4
- import { _ as consentCopy, b as jsonLdWarnings, c as hasThemeColors, d as tokenToHex, f as CONSENT_COPY, h as CONSENT_LIMITS, i as contrastChecks, n as HEX_COLOR, o as derivePalette, r as OVERRIDE_TOKENS, s as hasOverrides, t as DEFAULT_BRAND, u as themeCss, v as consentTextIssues, x as parseJsonLdInput, y as formatJsonLd } from "../theme-colors-zICpze42.js";
4
+ import { _ as consentCopy, b as parseMediaSource, c as hasThemeColors, d as tokenToHex, f as CONSENT_COPY, h as CONSENT_LIMITS, i as contrastChecks, n as HEX_COLOR, o as derivePalette, r as OVERRIDE_TOKENS, s as hasOverrides, t as DEFAULT_BRAND, u as themeCss, v as consentTextIssues } from "../theme-colors-CHROGZkI.js";
5
5
  import { _ as writeSaveNotice, a as localDraftStorage, d as removeDraft, f as savedNoticeFor, g as writeDraftRecord, h as sweepExpiredDrafts, i as isForeignSave, l as readDraftRecord, m as siteSavedKey, n as draftBannerText, o as pageDraftKey, p as siteDraftKey, r as hashText, s as pageSavedKey, t as assessStoredDraft, u as reloadDecision, x as draftImageUsages } from "../draft-store-1Y4-sn45.js";
6
6
  import { isSafeHref, markdownFromHtml, renderRichText, richLinkAt, sanitizeRichHtml, stripPlainRich, updateRichLink } from "../rich-text.js";
7
7
  import { Component, Fragment, createContext, isValidElement, options, render } from "preact";
8
8
  import { useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "preact/hooks";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "preact/jsx-runtime";
10
+ //#endregion
10
11
  //#region ../../node_modules/.pnpm/@preact+signals-core@1.14.4/node_modules/@preact/signals-core/dist/signals-core.mjs
11
12
  const i$1 = Symbol.for("preact-signals");
12
13
  function t() {
@@ -5051,7 +5052,7 @@ function wrap(tr, range, wrappers) {
5051
5052
  let start = range.start, end = range.end;
5052
5053
  tr.step(new ReplaceAroundStep(start, end, start, end, new Slice(content, 0, 0), wrappers.length, true));
5053
5054
  }
5054
- function setBlockType(tr, from, to, type, attrs) {
5055
+ function setBlockType$1(tr, from, to, type, attrs) {
5055
5056
  if (!type.isTextblock) throw new RangeError("Type given to setBlockType should be a textblock");
5056
5057
  let mapFrom = tr.steps.length;
5057
5058
  tr.doc.nodesBetween(from, to, (node, pos) => {
@@ -5861,7 +5862,7 @@ var Transform = class {
5861
5862
  the given node type with the given attributes.
5862
5863
  */
5863
5864
  setBlockType(from, to = from, type, attrs = null) {
5864
- setBlockType(this, from, to, type, attrs);
5865
+ setBlockType$1(this, from, to, type, attrs);
5865
5866
  return this;
5866
5867
  }
5867
5868
  /**
@@ -7269,6 +7270,37 @@ const selectTextblockStart = selectTextblockSide(-1);
7269
7270
  Moves the cursor to the end of current text block.
7270
7271
  */
7271
7272
  const selectTextblockEnd = selectTextblockSide(1);
7273
+ /**
7274
+ Returns a command that tries to set the selected textblocks to the
7275
+ given node type with the given attributes.
7276
+ */
7277
+ function setBlockType(nodeType, attrs = null) {
7278
+ return function(state, dispatch) {
7279
+ let applicable = false;
7280
+ for (let i = 0; i < state.selection.ranges.length && !applicable; i++) {
7281
+ let { $from: { pos: from }, $to: { pos: to } } = state.selection.ranges[i];
7282
+ state.doc.nodesBetween(from, to, (node, pos) => {
7283
+ if (applicable) return false;
7284
+ if (!node.isTextblock || node.hasMarkup(nodeType, attrs)) return;
7285
+ if (node.type == nodeType) applicable = true;
7286
+ else {
7287
+ let $pos = state.doc.resolve(pos), index = $pos.index();
7288
+ applicable = $pos.parent.canReplaceWith(index, index + 1, nodeType);
7289
+ }
7290
+ });
7291
+ }
7292
+ if (!applicable) return false;
7293
+ if (dispatch) {
7294
+ let tr = state.tr;
7295
+ for (let i = 0; i < state.selection.ranges.length; i++) {
7296
+ let { $from: { pos: from }, $to: { pos: to } } = state.selection.ranges[i];
7297
+ tr.setBlockType(from, to, nodeType, attrs);
7298
+ }
7299
+ dispatch(tr.scrollIntoView());
7300
+ }
7301
+ return true;
7302
+ };
7303
+ }
7272
7304
  function markApplies(doc, ranges, type, enterAtoms) {
7273
7305
  for (let i = 0; i < ranges.length; i++) {
7274
7306
  let { $from, $to } = ranges[i];
@@ -7941,7 +7973,7 @@ for (var i = 65; i <= 90; i++) {
7941
7973
  base[i] = String.fromCharCode(i + 32);
7942
7974
  shift[i] = String.fromCharCode(i);
7943
7975
  }
7944
- for (var code$1 in base) if (!shift.hasOwnProperty(code$1)) shift[code$1] = base[code$1];
7976
+ for (var code in base) if (!shift.hasOwnProperty(code)) shift[code] = base[code];
7945
7977
  function keyName(event) {
7946
7978
  var name = !(mac$2 && event.metaKey && event.shiftKey && !event.ctrlKey && !event.altKey || ie$1 && event.shiftKey && event.key && event.key.length == 1 || event.key == "Unidentified") && event.key || (event.shiftKey ? shift : base)[event.keyCode] || event.key || "Unidentified";
7947
7979
  if (name == "Esc") name = "Escape";
@@ -12825,115 +12857,173 @@ function checkStateComponent(plugin) {
12825
12857
  }
12826
12858
  //#endregion
12827
12859
  //#region src/ui/rich-editor.ts
12828
- /**
12829
- * The rich-text subset as a ProseMirror schema: paragraphs, line breaks, flat bulleted and numbered lists, bold,
12830
- * italic, inline code and links. Nothing else can exist in the document, so nothing else can be pasted or typed into it.
12831
- * Storage stays the markdown subset of `rich-text.ts`; this module only converts at the edges.
12832
- */
12833
- const richSchema = new Schema({
12834
- nodes: {
12835
- doc: { content: "(paragraph | bullet_list | ordered_list)+" },
12836
- paragraph: {
12837
- content: "inline*",
12838
- group: "block",
12839
- parseDOM: [{ tag: "p" }],
12840
- toDOM: () => ["p", 0]
12841
- },
12842
- bullet_list: {
12843
- content: "list_item+",
12844
- group: "block",
12845
- parseDOM: [{ tag: "ul" }],
12846
- toDOM: () => ["ul", 0]
12847
- },
12848
- ordered_list: {
12849
- content: "list_item+",
12850
- group: "block",
12851
- parseDOM: [{ tag: "ol" }],
12852
- toDOM: () => ["ol", 0]
12860
+ /** A schema type that every rich schema defines, narrowed from `| undefined`. */
12861
+ function need(value) {
12862
+ if (value === void 0) throw new Error("Missing rich-text schema type");
12863
+ return value;
12864
+ }
12865
+ /** A heading the field allows: h2 or h3. The page title is the h1, and the markdown subset stops at three. */
12866
+ const headingNode = {
12867
+ attrs: { level: { default: 2 } },
12868
+ content: "inline*",
12869
+ group: "block",
12870
+ defining: true,
12871
+ parseDOM: [
12872
+ {
12873
+ tag: "h1",
12874
+ attrs: { level: 2 }
12853
12875
  },
12854
- list_item: {
12855
- content: "paragraph",
12856
- defining: true,
12857
- parseDOM: [{ tag: "li" }],
12858
- toDOM: () => ["li", 0]
12876
+ {
12877
+ tag: "h2",
12878
+ attrs: { level: 2 }
12859
12879
  },
12860
- hard_break: {
12861
- inline: true,
12862
- group: "inline",
12863
- selectable: false,
12864
- parseDOM: [{ tag: "br" }],
12865
- toDOM: () => ["br"]
12880
+ {
12881
+ tag: "h3",
12882
+ attrs: { level: 3 }
12866
12883
  },
12867
- text: { group: "inline" }
12868
- },
12869
- marks: {
12870
- strong: {
12871
- parseDOM: [{ tag: "strong" }, { tag: "b" }],
12872
- toDOM: () => ["strong", 0]
12884
+ {
12885
+ tag: "h4",
12886
+ attrs: { level: 3 }
12873
12887
  },
12874
- em: {
12875
- parseDOM: [{ tag: "em" }, { tag: "i" }],
12876
- toDOM: () => ["em", 0]
12888
+ {
12889
+ tag: "h5",
12890
+ attrs: { level: 3 }
12877
12891
  },
12878
- code: {
12879
- excludes: "_",
12880
- inclusive: false,
12881
- parseDOM: [{ tag: "code" }],
12882
- toDOM: () => ["code", 0]
12892
+ {
12893
+ tag: "h6",
12894
+ attrs: { level: 3 }
12895
+ }
12896
+ ],
12897
+ toDOM: (node) => [`h${node.attrs.level}`, 0]
12898
+ };
12899
+ function createSchema(headings) {
12900
+ return new Schema({
12901
+ nodes: {
12902
+ doc: { content: headings ? "(paragraph | heading | bullet_list | ordered_list)+" : "(paragraph | bullet_list | ordered_list)+" },
12903
+ paragraph: {
12904
+ content: "inline*",
12905
+ group: "block",
12906
+ parseDOM: [{ tag: "p" }],
12907
+ toDOM: () => ["p", 0]
12908
+ },
12909
+ ...headings ? { heading: headingNode } : {},
12910
+ bullet_list: {
12911
+ content: "list_item+",
12912
+ group: "block",
12913
+ parseDOM: [{ tag: "ul" }],
12914
+ toDOM: () => ["ul", 0]
12915
+ },
12916
+ ordered_list: {
12917
+ content: "list_item+",
12918
+ group: "block",
12919
+ parseDOM: [{ tag: "ol" }],
12920
+ toDOM: () => ["ol", 0]
12921
+ },
12922
+ list_item: {
12923
+ content: "paragraph",
12924
+ defining: true,
12925
+ parseDOM: [{ tag: "li" }],
12926
+ toDOM: () => ["li", 0]
12927
+ },
12928
+ hard_break: {
12929
+ inline: true,
12930
+ group: "inline",
12931
+ selectable: false,
12932
+ parseDOM: [{ tag: "br" }],
12933
+ toDOM: () => ["br"]
12934
+ },
12935
+ text: { group: "inline" }
12883
12936
  },
12884
- link: {
12885
- attrs: {
12886
- href: {},
12887
- newTab: { default: null }
12937
+ marks: {
12938
+ strong: {
12939
+ parseDOM: [{ tag: "strong" }, { tag: "b" }],
12940
+ toDOM: () => ["strong", 0]
12888
12941
  },
12889
- inclusive: false,
12890
- parseDOM: [{
12891
- tag: "a[href]",
12892
- getAttrs: (dom) => {
12893
- const href = dom.getAttribute("href") ?? "";
12894
- if (!isSafeHref(href)) return false;
12895
- const tab = dom.getAttribute("data-new-tab");
12896
- return {
12897
- href,
12898
- newTab: tab === "true" ? "new" : tab === "false" ? "same" : null
12899
- };
12942
+ em: {
12943
+ parseDOM: [{ tag: "em" }, { tag: "i" }],
12944
+ toDOM: () => ["em", 0]
12945
+ },
12946
+ code: {
12947
+ excludes: "_",
12948
+ inclusive: false,
12949
+ parseDOM: [{ tag: "code" }],
12950
+ toDOM: () => ["code", 0]
12951
+ },
12952
+ link: {
12953
+ attrs: {
12954
+ href: {},
12955
+ newTab: { default: null }
12956
+ },
12957
+ inclusive: false,
12958
+ parseDOM: [{
12959
+ tag: "a[href]",
12960
+ getAttrs: (dom) => {
12961
+ const href = dom.getAttribute("href") ?? "";
12962
+ if (!isSafeHref(href)) return false;
12963
+ const tab = dom.getAttribute("data-new-tab");
12964
+ return {
12965
+ href,
12966
+ newTab: tab === "true" ? "new" : tab === "false" ? "same" : null
12967
+ };
12968
+ }
12969
+ }],
12970
+ toDOM: (mark) => {
12971
+ const tab = mark.attrs.newTab;
12972
+ const attrs = { href: String(mark.attrs.href) };
12973
+ if (tab === "new") attrs["data-new-tab"] = "true";
12974
+ else if (tab === "same") attrs["data-new-tab"] = "false";
12975
+ return [
12976
+ "a",
12977
+ attrs,
12978
+ 0
12979
+ ];
12900
12980
  }
12901
- }],
12902
- toDOM: (mark) => {
12903
- const tab = mark.attrs.newTab;
12904
- const attrs = { href: String(mark.attrs.href) };
12905
- if (tab === "new") attrs["data-new-tab"] = "true";
12906
- else if (tab === "same") attrs["data-new-tab"] = "false";
12907
- return [
12908
- "a",
12909
- attrs,
12910
- 0
12911
- ];
12912
12981
  }
12913
12982
  }
12914
- }
12915
- });
12916
- const { paragraph, bullet_list, ordered_list, list_item, hard_break } = richSchema.nodes;
12917
- const { strong, em, code, link } = richSchema.marks;
12918
- const parser = DOMParser.fromSchema(richSchema);
12919
- const serializer = DOMSerializer.fromSchema(richSchema);
12983
+ });
12984
+ }
12985
+ /**
12986
+ * The rich-text subset as a ProseMirror schema: paragraphs, line breaks, flat bulleted and numbered lists, bold,
12987
+ * italic, inline code and links. Nothing else can exist in the document, so nothing else can be pasted or typed into it.
12988
+ * Storage stays the markdown subset of `rich-text.ts`; this module only converts at the edges.
12989
+ */
12990
+ const richSchema = createSchema(false);
12991
+ /** The same, plus h2 and h3, for the fields that ask for headings (`data-rich-headings` on the field). */
12992
+ const headingRichSchema = createSchema(true);
12993
+ function kitOf(headings) {
12994
+ const schema = headings ? headingRichSchema : richSchema;
12995
+ return {
12996
+ schema,
12997
+ parser: DOMParser.fromSchema(schema),
12998
+ serializer: DOMSerializer.fromSchema(schema),
12999
+ options: { headings }
13000
+ };
13001
+ }
13002
+ const plainKit = kitOf(false);
13003
+ const headingKit = kitOf(true);
13004
+ /** The kit a document or a state belongs to. */
13005
+ function kitFor(schema) {
13006
+ return schema === headingRichSchema ? headingKit : plainKit;
13007
+ }
12920
13008
  function container(html) {
12921
13009
  const node = document.createElement("div");
12922
13010
  node.innerHTML = html;
12923
13011
  return node;
12924
13012
  }
12925
13013
  /** Markdown → document, through the same renderer the page uses, so what you edit is what the page shows. */
12926
- function docFromMarkdown(markdown) {
12927
- return parser.parse(container(renderRichText(markdown)));
13014
+ function docFromMarkdown(markdown, headings = false) {
13015
+ const kit = headings ? headingKit : plainKit;
13016
+ return kit.parser.parse(container(renderRichText(markdown, kit.options)));
12928
13017
  }
12929
13018
  /** Document → markdown, through the same serializer the draft has always used. */
12930
13019
  function markdownFromDoc(doc) {
13020
+ const kit = kitFor(doc.type.schema);
12931
13021
  const holder = document.createElement("div");
12932
- holder.append(serializer.serializeFragment(doc.content));
12933
- return markdownFromHtml(holder.innerHTML);
13022
+ holder.append(kit.serializer.serializeFragment(doc.content));
13023
+ return markdownFromHtml(holder.innerHTML, kit.options);
12934
13024
  }
12935
- function sliceFromMarkdown(markdown) {
12936
- return parser.parseSlice(container(renderRichText(markdown)));
13025
+ function sliceFromMarkdown(markdown, kit) {
13026
+ return kit.parser.parseSlice(container(renderRichText(markdown, kit.options)));
12937
13027
  }
12938
13028
  /** Document position of the `offset`-th character of the text; breaks and block edges count for nothing. */
12939
13029
  function posAtTextOffset(doc, offset) {
@@ -12954,8 +13044,10 @@ function posAtTextOffset(doc, offset) {
12954
13044
  });
12955
13045
  return found >= 0 ? found : end;
12956
13046
  }
13047
+ /** A line break. A heading is one line of markdown, so Shift-Enter does nothing there. */
12957
13048
  const insertLineBreak = (state, dispatch) => {
12958
- dispatch?.(state.tr.replaceSelectionWith(hard_break.create()).scrollIntoView());
13049
+ if (state.selection.$from.parent.type.name === "heading") return true;
13050
+ dispatch?.(state.tr.replaceSelectionWith(need(state.schema.nodes.hard_break).create()).scrollIntoView());
12959
13051
  return true;
12960
13052
  };
12961
13053
  /**
@@ -12964,6 +13056,8 @@ const insertLineBreak = (state, dispatch) => {
12964
13056
  */
12965
13057
  function wrapEachInList(kind) {
12966
13058
  return (state, dispatch) => {
13059
+ const { paragraph, list_item } = state.schema.nodes;
13060
+ if (!paragraph || !list_item) return false;
12967
13061
  const range = state.selection.$from.blockRange(state.selection.$to);
12968
13062
  if (!range) return false;
12969
13063
  const paragraphs = [];
@@ -12977,6 +13071,7 @@ function wrapEachInList(kind) {
12977
13071
  }
12978
13072
  /** The lists the selection touches (lists never nest). Works for a caret, a range and select-all alike. */
12979
13073
  function listsIn(state) {
13074
+ const { bullet_list, ordered_list } = state.schema.nodes;
12980
13075
  const { from, to } = state.selection;
12981
13076
  const found = [];
12982
13077
  state.doc.nodesBetween(from, to, (node, pos) => {
@@ -13022,8 +13117,10 @@ function unwrapSelected(lists, from, to) {
13022
13117
  };
13023
13118
  }
13024
13119
  /** Toggle a list: unwrap the same kind, convert the other kind, otherwise wrap. */
13025
- function toggleList(kind) {
13120
+ function toggleList(name) {
13026
13121
  return (state, dispatch) => {
13122
+ const kind = state.schema.nodes[name];
13123
+ if (!kind) return false;
13027
13124
  const lists = listsIn(state);
13028
13125
  if (lists.length === 0) return wrapInList(kind)(state, dispatch) || wrapEachInList(kind)(state, dispatch);
13029
13126
  if (lists.every((list) => list.node.type === kind)) return unwrapSelected(lists, state.selection.from, state.selection.to)(state, dispatch);
@@ -13039,39 +13136,62 @@ function toggleList(kind) {
13039
13136
  function setLink(href) {
13040
13137
  return (state, dispatch) => {
13041
13138
  const { from, to, empty } = state.selection;
13042
- if (empty || !isSafeHref(href)) return false;
13139
+ const link = state.schema.marks.link;
13140
+ if (empty || !link || !isSafeHref(href)) return false;
13043
13141
  dispatch?.(state.tr.addMark(from, to, link.create({ href })));
13044
13142
  return true;
13045
13143
  };
13046
13144
  }
13047
- /** The editing command behind a toolbar button. `url` is for `link`. */
13145
+ /** Make the selected block a heading of this level, or a paragraph again when it already is one. */
13146
+ function toggleHeading(level) {
13147
+ return (state, dispatch) => {
13148
+ const { heading, paragraph } = state.schema.nodes;
13149
+ if (!heading || !paragraph) return false;
13150
+ const parent = state.selection.$from.parent;
13151
+ return (parent.type === heading && parent.attrs.level === level ? setBlockType(paragraph) : setBlockType(heading, { level }))(state, dispatch);
13152
+ };
13153
+ }
13154
+ /** The editing command behind a toolbar button. `url` is for `link`. It reads the node and mark types from the state it runs on. */
13048
13155
  function commandFor(command, url = "") {
13049
13156
  switch (command) {
13050
- case "bold": return toggleMark(strong);
13051
- case "italic": return toggleMark(em);
13052
- case "code": return toggleMark(code);
13053
- case "bulletList": return toggleList(bullet_list);
13054
- case "orderedList": return toggleList(ordered_list);
13157
+ case "bold": return (state, dispatch) => toggleMark(need(state.schema.marks.strong))(state, dispatch);
13158
+ case "italic": return (state, dispatch) => toggleMark(need(state.schema.marks.em))(state, dispatch);
13159
+ case "code": return (state, dispatch) => toggleMark(need(state.schema.marks.code))(state, dispatch);
13160
+ case "bulletList": return toggleList("bullet_list");
13161
+ case "orderedList": return toggleList("ordered_list");
13055
13162
  case "link": return setLink(url);
13163
+ case "heading2": return toggleHeading(2);
13164
+ case "heading3": return toggleHeading(3);
13056
13165
  }
13057
13166
  }
13167
+ /** Enter at the end of a heading starts a paragraph, not another heading. In the middle it splits the heading. */
13168
+ const enterInHeading = (state, dispatch) => {
13169
+ const { heading, paragraph } = state.schema.nodes;
13170
+ if (!heading || !paragraph || state.selection.$from.parent.type !== heading) return false;
13171
+ return splitBlockAs((_node, atEnd) => atEnd ? { type: paragraph } : null)(state, dispatch);
13172
+ };
13058
13173
  /** Enter is a line break, a new item inside a list, and leaves the list from an empty item. */
13059
- const enterCommand = chainCommands(splitListItem(list_item), liftEmptyBlock, insertLineBreak);
13174
+ const enterCommand = (state, dispatch) => chainCommands(enterInHeading, splitListItem(need(state.schema.nodes.list_item)), liftEmptyBlock, insertLineBreak)(state, dispatch);
13060
13175
  function activeOf(state) {
13061
13176
  const { $from, from, to, empty } = state.selection;
13062
- const marked = (type) => empty ? type.isInSet(state.storedMarks ?? $from.marks()) !== void 0 : state.doc.rangeHasMark(from, to, type);
13177
+ const { strong, em, code, link } = state.schema.marks;
13178
+ const { bullet_list, ordered_list, heading } = state.schema.nodes;
13179
+ const marked = (type) => type === void 0 ? false : empty ? type.isInSet(state.storedMarks ?? $from.marks()) !== void 0 : state.doc.rangeHasMark(from, to, type);
13063
13180
  const lists = listsIn(state);
13181
+ const level = heading !== void 0 && $from.parent.type === heading ? $from.parent.attrs.level : 0;
13064
13182
  return {
13065
13183
  bold: marked(strong),
13066
13184
  italic: marked(em),
13067
13185
  code: marked(code),
13068
13186
  link: marked(link),
13069
13187
  bulletList: lists.length > 0 && lists.every((item) => item.node.type === bullet_list),
13070
- orderedList: lists.length > 0 && lists.every((item) => item.node.type === ordered_list)
13188
+ orderedList: lists.length > 0 && lists.every((item) => item.node.type === ordered_list),
13189
+ heading: level === 2 || level === 3 ? level : 0,
13190
+ headings: heading !== void 0
13071
13191
  };
13072
13192
  }
13073
13193
  function sameActive(a, b) {
13074
- return a.bold === b.bold && a.italic === b.italic && a.code === b.code && a.link === b.link && a.bulletList === b.bulletList && a.orderedList === b.orderedList;
13194
+ return a.bold === b.bold && a.italic === b.italic && a.code === b.code && a.link === b.link && a.bulletList === b.bulletList && a.orderedList === b.orderedList && a.heading === b.heading && a.headings === b.headings;
13075
13195
  }
13076
13196
  const mounted = /* @__PURE__ */ new WeakMap();
13077
13197
  /** The editor mounted on `field`, if any. */
@@ -13082,16 +13202,18 @@ function richEditorOf(field) {
13082
13202
  * Make `field` a ProseMirror editor over `markdown`. The field element itself becomes the editable surface, so the
13083
13203
  * page's own typography applies. Focus leaving the field (to anywhere but the editor's panels) ends the edit.
13084
13204
  */
13085
- function mountRichEditor(field, { markdown, selection, onChange, onActive, keepsEdit, onDestroy }) {
13205
+ function mountRichEditor(field, { markdown, headings = false, selection, onChange, onActive, keepsEdit, onDestroy }) {
13086
13206
  const existing = mounted.get(field);
13087
13207
  if (existing) return existing;
13208
+ const kit = headings ? headingKit : plainKit;
13209
+ const { strong, em } = kit.schema.marks;
13088
13210
  const stateFor = (source) => EditorState.create({
13089
- doc: docFromMarkdown(source),
13211
+ doc: docFromMarkdown(source, headings),
13090
13212
  plugins: [
13091
13213
  history(),
13092
13214
  keymap({
13093
- "Mod-b": toggleMark(strong),
13094
- "Mod-i": toggleMark(em),
13215
+ "Mod-b": toggleMark(need(strong)),
13216
+ "Mod-i": toggleMark(need(em)),
13095
13217
  "Mod-z": undo,
13096
13218
  "Mod-y": redo,
13097
13219
  "Shift-Mod-z": redo,
@@ -13120,8 +13242,8 @@ function mountRichEditor(field, { markdown, selection, onChange, onActive, keeps
13120
13242
  lastMarkdown = markdownFromDoc(next.doc);
13121
13243
  onChange(lastMarkdown);
13122
13244
  },
13123
- transformPastedHTML: (html) => sanitizeRichHtml(html),
13124
- clipboardTextParser: (text) => sliceFromMarkdown(stripPlainRich(text))
13245
+ transformPastedHTML: (html) => sanitizeRichHtml(html, kit.options),
13246
+ clipboardTextParser: (text) => sliceFromMarkdown(stripPlainRich(text, kit.options), kit)
13125
13247
  });
13126
13248
  if (selection) {
13127
13249
  const { doc } = view.state;
@@ -13156,7 +13278,7 @@ function mountRichEditor(field, { markdown, selection, onChange, onActive, keeps
13156
13278
  field.removeAttribute("contenteditable");
13157
13279
  field.removeAttribute("translate");
13158
13280
  if (!field.getAttribute("class")) field.removeAttribute("class");
13159
- field.innerHTML = renderRichText(lastMarkdown);
13281
+ field.innerHTML = renderRichText(lastMarkdown, kit.options);
13160
13282
  onDestroy?.();
13161
13283
  }
13162
13284
  };
@@ -13321,7 +13443,7 @@ function paintPage(draft) {
13321
13443
  if (isRichField(raw, node.getAttribute("data-field-kind"))) {
13322
13444
  const editing = richEditorOf(node);
13323
13445
  if (editing) editing.setMarkdown(value);
13324
- else node.innerHTML = renderRichText(value);
13446
+ else node.innerHTML = renderRichText(value, { headings: node.getAttribute("data-rich-headings") === "true" });
13325
13447
  } else if (isHeadingField(path)) node.innerHTML = renderMarkedHtml(value, marksAt(draft, path));
13326
13448
  else node.textContent = value;
13327
13449
  }
@@ -13447,10 +13569,18 @@ function isOptionalPath(content, path) {
13447
13569
  if (parts.length === 3 && arrayKey !== void 0 && key !== void 0 && /^\d+$/.test(index ?? "")) return content.items?.[arrayKey]?.includes(key) ?? false;
13448
13570
  return false;
13449
13571
  }
13450
- /** Section content keys in the order the form lists them: defaults first, then any other optional prop. */
13572
+ /**
13573
+ * Section content keys in the order the form lists them: defaults first. An optional prop the defaults leave out sits
13574
+ * right after the optional prop listed before it (`body` after `heading`), or at the end when none of those exist.
13575
+ */
13451
13576
  function orderContentKeys(present, optional, defaultKeys) {
13452
13577
  const keys = [.../* @__PURE__ */ new Set([...present, ...optional])];
13453
- const rank = [...defaultKeys, ...optional];
13578
+ const rank = [...defaultKeys];
13579
+ optional.forEach((key, position) => {
13580
+ if (rank.includes(key)) return;
13581
+ const before = optional.slice(0, position).reverse().find((name) => rank.includes(name));
13582
+ rank.splice(before === void 0 ? rank.length : rank.indexOf(before) + 1, 0, key);
13583
+ });
13454
13584
  const at = (key) => {
13455
13585
  const found = rank.indexOf(key);
13456
13586
  return found === -1 ? Number.MAX_SAFE_INTEGER : found;
@@ -13593,6 +13723,7 @@ function attachPageEditing(editor) {
13593
13723
  let stop = () => {};
13594
13724
  const handle = mountRichEditor(field, {
13595
13725
  markdown: read(),
13726
+ headings: field.getAttribute("data-rich-headings") === "true",
13596
13727
  selection,
13597
13728
  onChange: (markdown) => edits.writeField(pathOf(field), markdown),
13598
13729
  keepsEdit: isInEditor,
@@ -13867,6 +13998,24 @@ function hasAnalyticsSnippet(site) {
13867
13998
  function consentReopenOf(site) {
13868
13999
  return getAt(site, "consent.reopen") === "icon" ? "icon" : "footer";
13869
14000
  }
14001
+ /** The JSON-LD blocks every page carries, as the draft holds them. */
14002
+ function siteJsonLdOf(site) {
14003
+ const stored = getAt(site, "seo.jsonLd");
14004
+ return Array.isArray(stored) ? stored.filter(isRecord$2) : [];
14005
+ }
14006
+ /** What Generate reads from the draft. The logo counts only when it is a full https address. */
14007
+ function siteJsonLdSourceOf(site) {
14008
+ const name = getAt(site, "name");
14009
+ const url = getAt(site, "url");
14010
+ const lang = getAt(site, "lang");
14011
+ const logo = getAt(site, "brandLogo.src");
14012
+ return {
14013
+ name: typeof name === "string" ? name : "",
14014
+ url: typeof url === "string" ? url : "",
14015
+ lang: typeof lang === "string" && lang !== "" ? lang : void 0,
14016
+ logo: typeof logo === "string" && /^https:\/\//i.test(logo) ? logo : void 0
14017
+ };
14018
+ }
13870
14019
  //#endregion
13871
14020
  //#region src/ui/controllers/reactions.ts
13872
14021
  /** Signal effects that keep the page, storage and history in step with the editor state. */
@@ -14168,7 +14317,7 @@ function attachShortcuts(editor) {
14168
14317
  return;
14169
14318
  }
14170
14319
  if (ui.previewing.peek()) {
14171
- if (event.key === "Escape") {
14320
+ if (event.key === "Escape" && !document.querySelector("dialog[open]")) {
14172
14321
  event.preventDefault();
14173
14322
  chrome.exitPreview();
14174
14323
  }
@@ -14432,8 +14581,10 @@ function createChrome(ui) {
14432
14581
  for (const node of document.querySelectorAll("[data-field][contenteditable]")) node.removeAttribute("contenteditable");
14433
14582
  if (document.activeElement instanceof HTMLElement) document.activeElement.blur();
14434
14583
  document.documentElement.style.cursor = "";
14584
+ document.documentElement.setAttribute("data-bearminion-preview", "");
14435
14585
  }
14436
14586
  function exitPreview() {
14587
+ document.documentElement.removeAttribute("data-bearminion-preview");
14437
14588
  writeStorage(session, PREVIEW_KEY, null);
14438
14589
  n(() => {
14439
14590
  ui.previewing.value = false;
@@ -14550,6 +14701,15 @@ function uploadImage(file) {
14550
14701
  body
14551
14702
  });
14552
14703
  }
14704
+ const getVideos = () => request("/videos");
14705
+ function uploadVideo(file) {
14706
+ const body = new FormData();
14707
+ body.set("file", file);
14708
+ return request("/videos", {
14709
+ method: "POST",
14710
+ body
14711
+ });
14712
+ }
14553
14713
  const getGit = () => request("/git");
14554
14714
  const commit = (body) => request("/git/commit", sendJson("POST", body));
14555
14715
  /** Saved versions of the site (`scope` site) or of one page. */
@@ -16596,7 +16756,7 @@ const FOCUSABLE = "button:not(:disabled), input:not(:disabled), [tabindex=\"0\"]
16596
16756
  * Filled: thumbnail, file name, alt text, Change and Remove. The picker is a modal
16597
16757
  * with an Upload tab (drop or browse) and a Library tab (pick or delete).
16598
16758
  */
16599
- function ImageField({ label, path, value, images, withAlt = true, layout = true, hideable = false, onChange, onUploaded, onDeleted }) {
16759
+ function ImageField({ label, path, value, images, withAlt = true, layout = true, hideable = false, captionable = false, onChange, onUploaded, onDeleted }) {
16600
16760
  const [open, setOpen] = useState(false);
16601
16761
  const [error, setError] = useState("");
16602
16762
  const [over, setOver] = useState(false);
@@ -16608,18 +16768,24 @@ function ImageField({ label, path, value, images, withAlt = true, layout = true,
16608
16768
  const position = isImagePosition(value?.position) ? value.position : DEFAULT_IMAGE_POSITION;
16609
16769
  const showLayout = layout && withAlt;
16610
16770
  const hidden = hideable && value?.hidden === true;
16771
+ const caption = typeof value?.caption === "string" ? value.caption : "";
16611
16772
  const current = {
16612
16773
  src,
16613
16774
  alt,
16775
+ ...caption ? { caption } : {},
16614
16776
  fit,
16615
16777
  position,
16616
16778
  ...hidden ? { hidden } : {}
16617
16779
  };
16618
16780
  /** Emit the whole image object. A new file or alt keeps the fit and position already chosen. */
16619
- const emit = (patch) => onChange(compact({
16620
- ...current,
16621
- ...patch
16622
- }));
16781
+ const emit = (patch) => {
16782
+ const next = {
16783
+ ...current,
16784
+ ...patch
16785
+ };
16786
+ if (next.caption === "") delete next.caption;
16787
+ onChange(compact(next));
16788
+ };
16623
16789
  const empty = src === "" || src === "placeholder";
16624
16790
  const shown = previewSrc(src);
16625
16791
  const missing = useMissingFile(empty ? "" : src);
@@ -16686,15 +16852,9 @@ function ImageField({ label, path, value, images, withAlt = true, layout = true,
16686
16852
  children: [
16687
16853
  /* @__PURE__ */ jsx("span", {
16688
16854
  class: "bm-label",
16689
- children: /* @__PURE__ */ jsxs("span", {
16690
- class: "bm-label-row",
16691
- children: [/* @__PURE__ */ jsx("span", {
16692
- class: "bm-label-text",
16693
- children: label
16694
- }), withAlt && !empty && /* @__PURE__ */ jsx("span", {
16695
- class: "bm-meta-tag",
16696
- children: "alt required"
16697
- })]
16855
+ children: /* @__PURE__ */ jsx("span", {
16856
+ class: "bm-label-text",
16857
+ children: label
16698
16858
  })
16699
16859
  }),
16700
16860
  hideable && /* @__PURE__ */ jsxs("label", {
@@ -16822,12 +16982,46 @@ function ImageField({ label, path, value, images, withAlt = true, layout = true,
16822
16982
  })]
16823
16983
  })]
16824
16984
  })]
16825
- }), withAlt && /* @__PURE__ */ jsx("input", {
16826
- class: "bm-alt",
16827
- "aria-label": "Alt",
16828
- placeholder: "Alt text: describe the image",
16829
- value: alt,
16830
- onInput: (event) => emit({ alt: event.currentTarget.value })
16985
+ }), withAlt && /* @__PURE__ */ jsxs("div", {
16986
+ class: "bm-stack bm-stack-tight",
16987
+ children: [
16988
+ /* @__PURE__ */ jsxs("span", {
16989
+ class: "bm-label bm-label-row",
16990
+ "aria-hidden": "true",
16991
+ children: [/* @__PURE__ */ jsx("span", {
16992
+ class: "bm-label-text",
16993
+ children: "Alt text"
16994
+ }), /* @__PURE__ */ jsx("span", {
16995
+ class: "bm-meta-tag",
16996
+ children: "required"
16997
+ })]
16998
+ }),
16999
+ /* @__PURE__ */ jsx("input", {
17000
+ class: "bm-alt",
17001
+ "aria-label": "Alt",
17002
+ placeholder: "Describe the image",
17003
+ value: alt,
17004
+ onInput: (event) => emit({ alt: event.currentTarget.value })
17005
+ }),
17006
+ captionable && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
17007
+ class: "bm-label bm-label-row",
17008
+ "aria-hidden": "true",
17009
+ children: [/* @__PURE__ */ jsx("span", {
17010
+ class: "bm-label-text",
17011
+ children: "Caption"
17012
+ }), /* @__PURE__ */ jsx("span", {
17013
+ class: "bm-meta-tag",
17014
+ children: "optional, shown when opened large"
17015
+ })]
17016
+ }), /* @__PURE__ */ jsx("textarea", {
17017
+ class: "bm-alt",
17018
+ rows: 2,
17019
+ "aria-label": "Caption",
17020
+ placeholder: "Shown under the picture. Empty uses the alt text.",
17021
+ value: caption,
17022
+ onInput: (event) => emit({ caption: event.currentTarget.value })
17023
+ })] })
17024
+ ]
16831
17025
  })] }),
16832
17026
  missing && /* @__PURE__ */ jsxs("p", {
16833
17027
  class: "bm-error",
@@ -17261,6 +17455,126 @@ function ChoiceField({ label, value, choices, icons, path, segmented = true, onC
17261
17455
  });
17262
17456
  }
17263
17457
  //#endregion
17458
+ //#region src/ui/forms/video-source.tsx
17459
+ /** What a pasted video link is, or why it will not play. Empty for no link. */
17460
+ function describeVideoLink(value) {
17461
+ const link = value.trim();
17462
+ if (link === "") return null;
17463
+ const source = parseMediaSource(link);
17464
+ if (source?.kind === "youtube") return {
17465
+ ok: true,
17466
+ text: "YouTube video. It loads nothing until the visitor presses play."
17467
+ };
17468
+ if (source?.kind === "vimeo") return {
17469
+ ok: true,
17470
+ text: "Vimeo video. It loads nothing until the visitor presses play."
17471
+ };
17472
+ if (source?.kind === "file") return {
17473
+ ok: true,
17474
+ text: "Video file."
17475
+ };
17476
+ if (/^https?:\/\//i.test(link)) return {
17477
+ ok: false,
17478
+ text: "That is a page link, not a video. Use a YouTube or Vimeo link, or a link to a file ending in .mp4 or .webm."
17479
+ };
17480
+ return {
17481
+ ok: false,
17482
+ text: "Use a YouTube or Vimeo link, a link to a video file ending in .mp4 or .webm, or a path in public/ such as /videos/demo.webm."
17483
+ };
17484
+ }
17485
+ const megabytes = (bytes) => `${(bytes / 1048576).toFixed(bytes < 10485760 ? 1 : 0)} MB`;
17486
+ /** Under a video link field: says what the link is, uploads a video file, and picks one already uploaded. */
17487
+ function VideoSourceTools({ value, onPick }) {
17488
+ const input = useRef(null);
17489
+ const [library, setLibrary] = useState([]);
17490
+ const [busy, setBusy] = useState(false);
17491
+ const [note, setNote] = useState("");
17492
+ const [error, setError] = useState("");
17493
+ useEffect(() => {
17494
+ let live = true;
17495
+ getVideos().then((result) => {
17496
+ if (live && result.ok) setLibrary(result.value.videos);
17497
+ });
17498
+ return () => {
17499
+ live = false;
17500
+ };
17501
+ }, []);
17502
+ async function upload(file) {
17503
+ if (!file) return;
17504
+ setBusy(true);
17505
+ setError("");
17506
+ setNote("");
17507
+ const result = await uploadVideo(file);
17508
+ setBusy(false);
17509
+ if (!result.ok) {
17510
+ setError(result.status === 0 ? "Upload failed." : result.message);
17511
+ return;
17512
+ }
17513
+ setLibrary((current) => [...current.filter((item) => item.url !== result.value.url), result.value]);
17514
+ onPick(result.value.url);
17515
+ if ((result.value.bytes ?? 0) > 10485760) setNote(`${megabytes(result.value.bytes ?? 0)}: it is slow to load on every visit. YouTube or Vimeo is kinder to visitors.`);
17516
+ }
17517
+ const detected = describeVideoLink(value);
17518
+ return /* @__PURE__ */ jsxs("div", {
17519
+ class: "bm-stack bm-stack-tight",
17520
+ children: [
17521
+ detected ? /* @__PURE__ */ jsx("span", {
17522
+ class: detected.ok ? "bm-hint" : "bm-error",
17523
+ role: detected.ok ? void 0 : "alert",
17524
+ children: detected.text
17525
+ }) : /* @__PURE__ */ jsx("span", {
17526
+ class: "bm-hint",
17527
+ children: "Paste a YouTube or Vimeo link as it is, or upload a video file."
17528
+ }),
17529
+ /* @__PURE__ */ jsx("input", {
17530
+ ref: input,
17531
+ type: "file",
17532
+ accept: "video/mp4,video/webm,video/quicktime,video/ogg",
17533
+ hidden: true,
17534
+ onChange: (event) => {
17535
+ const file = event.currentTarget.files?.[0];
17536
+ event.currentTarget.value = "";
17537
+ upload(file);
17538
+ }
17539
+ }),
17540
+ /* @__PURE__ */ jsx("button", {
17541
+ type: "button",
17542
+ class: "bm-add bm-add-row",
17543
+ disabled: busy,
17544
+ onClick: () => input.current?.click(),
17545
+ children: busy ? "Uploading…" : "Upload a video file"
17546
+ }),
17547
+ library.length > 0 && /* @__PURE__ */ jsxs("label", {
17548
+ class: "bm-field",
17549
+ children: [/* @__PURE__ */ jsx("span", {
17550
+ class: "bm-label",
17551
+ children: "Uploaded videos"
17552
+ }), /* @__PURE__ */ jsxs("select", {
17553
+ value: "",
17554
+ "aria-label": "Uploaded videos",
17555
+ onChange: (event) => event.currentTarget.value && onPick(event.currentTarget.value),
17556
+ children: [/* @__PURE__ */ jsx("option", {
17557
+ value: "",
17558
+ children: "Choose one…"
17559
+ }), library.map((video) => /* @__PURE__ */ jsxs("option", {
17560
+ value: video.url,
17561
+ children: [video.filename, video.bytes ? ` (${megabytes(video.bytes)})` : ""]
17562
+ }, video.url))]
17563
+ })]
17564
+ }),
17565
+ note && /* @__PURE__ */ jsx("span", {
17566
+ class: "bm-hint",
17567
+ children: note
17568
+ }),
17569
+ error && /* @__PURE__ */ jsx("span", {
17570
+ class: "bm-error",
17571
+ role: "alert",
17572
+ children: error
17573
+ })
17574
+ ]
17575
+ });
17576
+ }
17577
+ //#endregion
17264
17578
  //#region src/ui/forms/fields.tsx
17265
17579
  /** `yearlyDiscount` and `cta_label` read as "Yearly discount" and "Cta label". Array item numbers stay numbers. */
17266
17580
  function humanize(key) {
@@ -17328,7 +17642,7 @@ function ValueEditor({ label: rawLabel, value, path, rule, variant, sample, imag
17328
17642
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === void 0) {
17329
17643
  const rich = typeof value === "string" && isRichField(path, null);
17330
17644
  const heading = isHeadingField(path);
17331
- return /* @__PURE__ */ jsx(OptionControl, {
17645
+ const control = /* @__PURE__ */ jsx(OptionControl, {
17332
17646
  option: {
17333
17647
  name: path,
17334
17648
  label,
@@ -17342,122 +17656,39 @@ function ValueEditor({ label: rawLabel, value, path, rule, variant, sample, imag
17342
17656
  value,
17343
17657
  onChange: (next) => onField(path, next)
17344
17658
  });
17659
+ if (!/(^|\.)props\.video$/.test(path)) return control;
17660
+ return /* @__PURE__ */ jsxs("div", {
17661
+ class: "bm-stack bm-stack-tight",
17662
+ children: [control, /* @__PURE__ */ jsx(VideoSourceTools, {
17663
+ value: typeof value === "string" ? value : "",
17664
+ onPick: (url) => onField(path, url)
17665
+ })]
17666
+ });
17345
17667
  }
17346
17668
  if (isImageRecord(value)) return /* @__PURE__ */ jsx(ImageField, {
17347
17669
  label,
17348
17670
  path,
17349
17671
  layout: !/(^|\.)logos\./.test(path),
17350
17672
  hideable: path.startsWith("sections.") && !/(^|\.)logos\./.test(path),
17673
+ captionable: isOptionalPath(optionalSpec, `${path}.caption`),
17351
17674
  value,
17352
17675
  images,
17353
17676
  onChange: (next) => onField(path, next),
17354
17677
  onUploaded,
17355
17678
  onDeleted
17356
17679
  });
17357
- if (Array.isArray(value)) {
17358
- const allowAdd = canAddItems(value.length, rule, variant);
17359
- const allowRemove = canRemoveItems(value.length, rule, variant);
17360
- return /* @__PURE__ */ jsxs("div", {
17361
- class: "bm-stack bm-stack-tight",
17362
- children: [/* @__PURE__ */ jsxs("span", {
17363
- class: "bm-label-row bm-label",
17364
- children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsxs("span", {
17365
- class: "bm-meta-tag",
17366
- children: [value.length, rule?.recommended !== void 0 ? `, recommended ${rule.recommended}` : ""]
17367
- })]
17368
- }), /* @__PURE__ */ jsxs("div", {
17369
- class: "bm-array",
17370
- children: [value.map((item, index) => /* @__PURE__ */ jsxs("details", {
17371
- class: "bm-array-item",
17372
- children: [/* @__PURE__ */ jsxs("summary", { children: [
17373
- /* @__PURE__ */ jsx("span", {
17374
- class: "bm-grip",
17375
- "aria-hidden": "true",
17376
- children: /* @__PURE__ */ jsx(Icon, {
17377
- name: "grip",
17378
- size: 12
17379
- })
17380
- }),
17381
- /* @__PURE__ */ jsx("span", {
17382
- class: "bm-array-summary",
17383
- children: itemSummary(item) || `${label} ${index + 1}`
17384
- }),
17385
- /* @__PURE__ */ jsx("span", {
17386
- class: "bm-chevron",
17387
- "aria-hidden": "true",
17388
- children: /* @__PURE__ */ jsx(Icon, {
17389
- name: "chevron-right",
17390
- size: 14
17391
- })
17392
- })
17393
- ] }), /* @__PURE__ */ jsxs("div", {
17394
- class: "bm-array-body",
17395
- children: [/* @__PURE__ */ jsx(ValueEditor, {
17396
- label: `${index + 1}`,
17397
- value: item,
17398
- path: `${path}.${index}`,
17399
- rule: void 0,
17400
- variant,
17401
- sample,
17402
- images,
17403
- onField,
17404
- onUploaded,
17405
- onDeleted
17406
- }), /* @__PURE__ */ jsxs("div", {
17407
- class: "bm-row bm-row-end",
17408
- children: [
17409
- /* @__PURE__ */ jsx("button", {
17410
- type: "button",
17411
- class: "bm-icon-btn",
17412
- "aria-label": "Move item up",
17413
- title: "Move up",
17414
- disabled: index === 0,
17415
- onClick: () => onField(path, reorderList(value, index, index - 1)),
17416
- children: /* @__PURE__ */ jsx(Icon, {
17417
- name: "arrow-up",
17418
- size: 14
17419
- })
17420
- }),
17421
- /* @__PURE__ */ jsx("button", {
17422
- type: "button",
17423
- class: "bm-icon-btn",
17424
- "aria-label": "Move item down",
17425
- title: "Move down",
17426
- disabled: index === value.length - 1,
17427
- onClick: () => onField(path, reorderList(value, index, index + 1)),
17428
- children: /* @__PURE__ */ jsx(Icon, {
17429
- name: "arrow-down",
17430
- size: 14
17431
- })
17432
- }),
17433
- /* @__PURE__ */ jsx("button", {
17434
- type: "button",
17435
- class: "bm-icon-btn bm-danger",
17436
- "aria-label": "Remove item",
17437
- title: "Remove",
17438
- disabled: !allowRemove,
17439
- onClick: () => onField(path, value.filter((_, itemIndex) => itemIndex !== index)),
17440
- children: /* @__PURE__ */ jsx(Icon, {
17441
- name: "trash",
17442
- size: 14
17443
- })
17444
- })
17445
- ]
17446
- })]
17447
- })]
17448
- }, `${path}.${index}`)), /* @__PURE__ */ jsx("button", {
17449
- type: "button",
17450
- class: "bm-add bm-add-row",
17451
- disabled: !allowAdd,
17452
- onClick: () => {
17453
- const next = sample === void 0 ? "New" : structuredClone(sample);
17454
- onField(path, [...value, next]);
17455
- },
17456
- children: "+ Add item"
17457
- })]
17458
- })]
17459
- });
17460
- }
17680
+ if (Array.isArray(value)) return /* @__PURE__ */ jsx(ArrayEditor, {
17681
+ label,
17682
+ value,
17683
+ path,
17684
+ rule,
17685
+ variant,
17686
+ sample,
17687
+ images,
17688
+ onField,
17689
+ onUploaded,
17690
+ onDeleted
17691
+ });
17461
17692
  if (isLinkRecord(value)) {
17462
17693
  const record = value;
17463
17694
  return /* @__PURE__ */ jsxs("div", {
@@ -17690,6 +17921,216 @@ function orderItemKeys(item, path, content) {
17690
17921
  const dropped = parts.length === 2 && /^\d+$/.test(parts[1] ?? "") ? content?.items?.[parts[0] ?? ""] ?? [] : [];
17691
17922
  return orderContentKeys(Object.keys(item), dropped, Object.keys(item));
17692
17923
  }
17924
+ let itemSeed = 0;
17925
+ /** Ids that follow each list item when it moves, so its open card, focus and inputs move with it. */
17926
+ function useItemIds(length) {
17927
+ const ids = useRef([]);
17928
+ while (ids.current.length < length) ids.current.push(`item-${++itemSeed}`);
17929
+ if (ids.current.length > length) ids.current.length = length;
17930
+ return ids;
17931
+ }
17932
+ /** Where a drop lands: the index the dragged item ends up at, or null when it would not move. */
17933
+ function dropTarget(drag) {
17934
+ const slot = drag.mode === "before" ? drag.over : drag.over + 1;
17935
+ const to = slot > drag.from ? slot - 1 : slot;
17936
+ return to === drag.from ? null : to;
17937
+ }
17938
+ /** A list of items. Each card keeps its identity when it moves, so a card you moved stays open and you can move it again. */
17939
+ function ArrayEditor({ label, value, path, rule, variant, sample, images, onField, onUploaded, onDeleted }) {
17940
+ const allowAdd = canAddItems(value.length, rule, variant);
17941
+ const allowRemove = canRemoveItems(value.length, rule, variant);
17942
+ const ids = useItemIds(value.length);
17943
+ const list = useRef(null);
17944
+ const [drag, setDrag] = useState(null);
17945
+ function move(from, to, refocus) {
17946
+ if (from === to || to < 0 || to >= value.length) return;
17947
+ const [id] = ids.current.splice(from, 1);
17948
+ if (id === void 0) return;
17949
+ ids.current.splice(to, 0, id);
17950
+ onField(path, reorderList(value, from, to));
17951
+ if (!refocus) return;
17952
+ const wanted = id;
17953
+ requestAnimationFrame(() => requestAnimationFrame(() => {
17954
+ const card = list.current?.querySelector(`[data-item-id="${wanted}"]`);
17955
+ const first = card?.querySelector(`[data-move="${refocus}"]`);
17956
+ const other = card?.querySelector(`[data-move="${refocus === "up" ? "down" : "up"}"]`);
17957
+ (first && !first.disabled ? first : other)?.focus();
17958
+ }));
17959
+ }
17960
+ return /* @__PURE__ */ jsxs("div", {
17961
+ class: "bm-stack bm-stack-tight",
17962
+ children: [/* @__PURE__ */ jsxs("span", {
17963
+ class: "bm-label-row bm-label",
17964
+ children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsxs("span", {
17965
+ class: "bm-meta-tag",
17966
+ children: [value.length, rule?.recommended !== void 0 ? `, recommended ${rule.recommended}` : ""]
17967
+ })]
17968
+ }), /* @__PURE__ */ jsxs("div", {
17969
+ class: "bm-array",
17970
+ ref: list,
17971
+ children: [value.map((item, index) => {
17972
+ const id = ids.current[index] ?? `${path}.${index}`;
17973
+ const mode = (drag !== null && drag.over === index ? dropTarget(drag) : null) === null || drag === null ? null : drag.mode;
17974
+ const rowClass = [
17975
+ "bm-array-row",
17976
+ drag?.from === index ? "bm-dragging" : "",
17977
+ mode === "before" ? "bm-drop-before" : "",
17978
+ mode === "after" ? "bm-drop-after" : ""
17979
+ ].filter(Boolean).join(" ");
17980
+ return /* @__PURE__ */ jsx("div", {
17981
+ class: rowClass,
17982
+ "data-item-id": id,
17983
+ "data-drop-hint": mode ? "Move here" : void 0,
17984
+ onDragOver: (event) => {
17985
+ if (!drag) return;
17986
+ event.preventDefault();
17987
+ event.stopPropagation();
17988
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
17989
+ const box = event.currentTarget.getBoundingClientRect();
17990
+ const next = event.clientY < box.top + box.height / 2 ? "before" : "after";
17991
+ if (drag.over !== index || drag.mode !== next) setDrag({
17992
+ ...drag,
17993
+ over: index,
17994
+ mode: next
17995
+ });
17996
+ },
17997
+ onDragLeave: (event) => {
17998
+ const next = event.relatedTarget;
17999
+ if (!drag || next instanceof Node && event.currentTarget.contains(next)) return;
18000
+ if (drag.over === index) setDrag({
18001
+ ...drag,
18002
+ over: drag.from
18003
+ });
18004
+ },
18005
+ onDrop: (event) => {
18006
+ if (!drag) return;
18007
+ event.preventDefault();
18008
+ event.stopPropagation();
18009
+ const to = dropTarget({
18010
+ ...drag,
18011
+ over: index,
18012
+ mode: drag.over === index ? drag.mode : "before"
18013
+ });
18014
+ const from = drag.from;
18015
+ setDrag(null);
18016
+ if (to !== null) move(from, to);
18017
+ },
18018
+ children: /* @__PURE__ */ jsxs("details", {
18019
+ class: "bm-array-item",
18020
+ children: [/* @__PURE__ */ jsxs("summary", { children: [
18021
+ /* @__PURE__ */ jsx("span", {
18022
+ class: "bm-grip bm-array-grip",
18023
+ draggable: true,
18024
+ title: "Drag to reorder",
18025
+ "aria-hidden": "true",
18026
+ onClick: (event) => event.preventDefault(),
18027
+ onDragStart: (event) => {
18028
+ event.stopPropagation();
18029
+ const row = event.currentTarget.closest(".bm-array-row");
18030
+ if (event.dataTransfer) {
18031
+ event.dataTransfer.effectAllowed = "move";
18032
+ event.dataTransfer.setData("text/plain", id);
18033
+ if (row) event.dataTransfer.setDragImage(row, 16, 16);
18034
+ }
18035
+ setDrag({
18036
+ from: index,
18037
+ over: index,
18038
+ mode: "before"
18039
+ });
18040
+ },
18041
+ onDragEnd: () => setDrag(null),
18042
+ children: /* @__PURE__ */ jsx(Icon, {
18043
+ name: "grip",
18044
+ size: 12
18045
+ })
18046
+ }),
18047
+ /* @__PURE__ */ jsx("span", {
18048
+ class: "bm-array-summary",
18049
+ children: itemSummary(item) || `${label} ${index + 1}`
18050
+ }),
18051
+ /* @__PURE__ */ jsx("span", {
18052
+ class: "bm-chevron",
18053
+ "aria-hidden": "true",
18054
+ children: /* @__PURE__ */ jsx(Icon, {
18055
+ name: "chevron-right",
18056
+ size: 14
18057
+ })
18058
+ })
18059
+ ] }), /* @__PURE__ */ jsxs("div", {
18060
+ class: "bm-array-body",
18061
+ children: [/* @__PURE__ */ jsx(ValueEditor, {
18062
+ label: `${index + 1}`,
18063
+ value: item,
18064
+ path: `${path}.${index}`,
18065
+ rule: void 0,
18066
+ variant,
18067
+ sample,
18068
+ images,
18069
+ onField,
18070
+ onUploaded,
18071
+ onDeleted
18072
+ }), /* @__PURE__ */ jsxs("div", {
18073
+ class: "bm-row bm-row-end",
18074
+ children: [
18075
+ /* @__PURE__ */ jsx("button", {
18076
+ type: "button",
18077
+ class: "bm-icon-btn",
18078
+ "aria-label": "Move item up",
18079
+ title: "Move up",
18080
+ "data-move": "up",
18081
+ disabled: index === 0,
18082
+ onClick: () => move(index, index - 1, "up"),
18083
+ children: /* @__PURE__ */ jsx(Icon, {
18084
+ name: "arrow-up",
18085
+ size: 14
18086
+ })
18087
+ }),
18088
+ /* @__PURE__ */ jsx("button", {
18089
+ type: "button",
18090
+ class: "bm-icon-btn",
18091
+ "aria-label": "Move item down",
18092
+ title: "Move down",
18093
+ "data-move": "down",
18094
+ disabled: index === value.length - 1,
18095
+ onClick: () => move(index, index + 1, "down"),
18096
+ children: /* @__PURE__ */ jsx(Icon, {
18097
+ name: "arrow-down",
18098
+ size: 14
18099
+ })
18100
+ }),
18101
+ /* @__PURE__ */ jsx("button", {
18102
+ type: "button",
18103
+ class: "bm-icon-btn bm-danger",
18104
+ "aria-label": "Remove item",
18105
+ title: "Remove",
18106
+ disabled: !allowRemove,
18107
+ onClick: () => {
18108
+ ids.current.splice(index, 1);
18109
+ onField(path, value.filter((_, itemIndex) => itemIndex !== index));
18110
+ },
18111
+ children: /* @__PURE__ */ jsx(Icon, {
18112
+ name: "trash",
18113
+ size: 14
18114
+ })
18115
+ })
18116
+ ]
18117
+ })]
18118
+ })]
18119
+ })
18120
+ }, id);
18121
+ }), /* @__PURE__ */ jsx("button", {
18122
+ type: "button",
18123
+ class: "bm-add bm-add-row",
18124
+ disabled: !allowAdd,
18125
+ onClick: () => {
18126
+ const next = sample === void 0 ? "New" : structuredClone(sample);
18127
+ onField(path, [...value, next]);
18128
+ },
18129
+ children: "+ Add item"
18130
+ })]
18131
+ })]
18132
+ });
18133
+ }
17693
18134
  //#endregion
17694
18135
  //#region src/ui/dialogs/consent-dialog.tsx
17695
18136
  const KEYS = [
@@ -18468,6 +18909,151 @@ function SeoDialog({ page, siteName, siteUrl, system, images, issues, onUploaded
18468
18909
  });
18469
18910
  }
18470
18911
  //#endregion
18912
+ //#region src/ui/dialogs/site-jsonld-dialog.tsx
18913
+ /**
18914
+ * The structured data every page carries: an `Organization` and a `WebSite`, or any other markup. It edits a
18915
+ * copy: Apply writes it to the site draft in one step, Cancel and Escape drop it. Nothing reaches disk until save.
18916
+ */
18917
+ function SiteJsonLdDialog({ blocks, source, onApply, onClose }) {
18918
+ const root = useRef(null);
18919
+ const [jsonText, setJsonText] = useState(() => formatJsonLd(blocks));
18920
+ const parsed = parseJsonLdInput(jsonText);
18921
+ const warnings = parsed.ok ? jsonLdWarnings(parsed.value) : [];
18922
+ const count = parsed.ok ? parsed.value.length : 0;
18923
+ const placeholder = isPlaceholderSiteUrl(source.url);
18924
+ useEffect(() => {
18925
+ root.current?.querySelector("textarea")?.focus();
18926
+ }, []);
18927
+ function generate() {
18928
+ if (!parsed.ok) return;
18929
+ setJsonText(formatJsonLd(upsertJsonLd(parsed.value, generateSiteJsonLd(source))));
18930
+ }
18931
+ return /* @__PURE__ */ jsx("div", {
18932
+ class: "bm-scrim",
18933
+ children: /* @__PURE__ */ jsxs("div", {
18934
+ class: "bm-dialog bm-seo",
18935
+ role: "dialog",
18936
+ "aria-modal": "true",
18937
+ "aria-label": "Edit site JSON-LD",
18938
+ ref: root,
18939
+ children: [
18940
+ /* @__PURE__ */ jsxs("div", {
18941
+ class: "bm-dialog-head",
18942
+ children: [/* @__PURE__ */ jsxs("div", {
18943
+ class: "bm-dialog-heading",
18944
+ children: [/* @__PURE__ */ jsx("h2", {
18945
+ class: "bm-dialog-title",
18946
+ children: "Structured data · every page"
18947
+ }), /* @__PURE__ */ jsx("p", {
18948
+ class: "bm-dialog-sub",
18949
+ children: "Applied to the site draft. Nothing is written until you save."
18950
+ })]
18951
+ }), /* @__PURE__ */ jsx(DialogClose, { onClose })]
18952
+ }),
18953
+ /* @__PURE__ */ jsxs("div", {
18954
+ class: "bm-seo-body",
18955
+ children: [/* @__PURE__ */ jsxs("div", {
18956
+ class: "bm-stack",
18957
+ children: [
18958
+ /* @__PURE__ */ jsx("p", {
18959
+ class: "bm-group",
18960
+ children: "Generate"
18961
+ }),
18962
+ /* @__PURE__ */ jsx("button", {
18963
+ type: "button",
18964
+ class: "bm-tertiary bm-seo-format",
18965
+ disabled: !parsed.ok,
18966
+ onClick: generate,
18967
+ children: "Generate Organization and WebSite"
18968
+ }),
18969
+ /* @__PURE__ */ jsxs("p", {
18970
+ class: "bm-hint",
18971
+ children: ["Filled from the site name, address and language. Blocks you already have with the same @id are replaced, the rest are kept.", source.logo ? "" : " No logo is added: paste a full https address as \"logo\" by hand, because a local image only gets its address when the site is built."]
18972
+ }),
18973
+ placeholder && /* @__PURE__ */ jsxs("span", {
18974
+ class: "bm-error",
18975
+ role: "alert",
18976
+ children: [
18977
+ "The site address is still ",
18978
+ source.url,
18979
+ ". Set the real one under Identity before you generate, or the markup names the wrong site."
18980
+ ]
18981
+ })
18982
+ ]
18983
+ }), /* @__PURE__ */ jsxs("div", {
18984
+ class: "bm-stack",
18985
+ children: [
18986
+ /* @__PURE__ */ jsx("p", {
18987
+ class: "bm-group",
18988
+ children: "JSON-LD"
18989
+ }),
18990
+ /* @__PURE__ */ jsxs("label", {
18991
+ class: "bm-label",
18992
+ children: [
18993
+ /* @__PURE__ */ jsxs("span", {
18994
+ class: "bm-label-row",
18995
+ children: [/* @__PURE__ */ jsxs("span", {
18996
+ class: "bm-label-text",
18997
+ children: ["Blocks", /* @__PURE__ */ jsx(Info, {
18998
+ label: "About site JSON-LD",
18999
+ text: "Added to every page. A page's own JSON-LD replaces only the generated page markup, and a page block with the same @id wins over the site's. Paste an object, an array of objects, or a whole script tag."
19000
+ })]
19001
+ }), /* @__PURE__ */ jsx("span", {
19002
+ class: "bm-meta-tag",
19003
+ children: parsed.ok ? `${count} ${count === 1 ? "block" : "blocks"}` : "invalid"
19004
+ })]
19005
+ }),
19006
+ /* @__PURE__ */ jsx("textarea", {
19007
+ class: "bm-mono bm-seo-json",
19008
+ rows: 14,
19009
+ spellcheck: false,
19010
+ autocomplete: "off",
19011
+ placeholder: "{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Example\"\n}",
19012
+ "aria-invalid": !parsed.ok,
19013
+ value: jsonText,
19014
+ onInput: (event) => setJsonText(event.currentTarget.value)
19015
+ }),
19016
+ !parsed.ok && /* @__PURE__ */ jsx("span", {
19017
+ class: "bm-error",
19018
+ role: "alert",
19019
+ children: parsed.error
19020
+ }),
19021
+ warnings.map((warning) => /* @__PURE__ */ jsx("span", {
19022
+ class: "bm-hint",
19023
+ children: warning
19024
+ }, warning))
19025
+ ]
19026
+ }),
19027
+ /* @__PURE__ */ jsx("button", {
19028
+ type: "button",
19029
+ class: "bm-tertiary bm-seo-format",
19030
+ disabled: !parsed.ok || parsed.value.length === 0,
19031
+ onClick: () => parsed.ok && setJsonText(formatJsonLd(parsed.value)),
19032
+ children: "Format JSON"
19033
+ })
19034
+ ]
19035
+ })]
19036
+ }),
19037
+ /* @__PURE__ */ jsxs("div", {
19038
+ class: "bm-actions",
19039
+ children: [/* @__PURE__ */ jsx("button", {
19040
+ type: "button",
19041
+ class: "bm-primary",
19042
+ disabled: !parsed.ok,
19043
+ onClick: () => parsed.ok && onApply(parsed.value),
19044
+ children: "Apply"
19045
+ }), /* @__PURE__ */ jsx("button", {
19046
+ type: "button",
19047
+ class: "bm-tertiary",
19048
+ onClick: onClose,
19049
+ children: "Cancel"
19050
+ })]
19051
+ })
19052
+ ]
19053
+ })
19054
+ });
19055
+ }
19056
+ //#endregion
18471
19057
  //#region src/ui/dialogs/editor-dialogs.tsx
18472
19058
  function parseJson(text) {
18473
19059
  if (!text) return null;
@@ -18598,6 +19184,19 @@ function SessionDialog({ editor, dialog }) {
18598
19184
  onClose: close
18599
19185
  });
18600
19186
  }
19187
+ case "siteJsonLd": {
19188
+ const site = doc.site.value;
19189
+ if (!site) return null;
19190
+ return /* @__PURE__ */ jsx(SiteJsonLdDialog, {
19191
+ blocks: siteJsonLdOf(site),
19192
+ source: siteJsonLdSourceOf(site),
19193
+ onApply: (blocks) => {
19194
+ edits.writeField("seo.jsonLd", blocks.length > 0 ? blocks : void 0);
19195
+ close();
19196
+ },
19197
+ onClose: close
19198
+ });
19199
+ }
18601
19200
  case "discard": return /* @__PURE__ */ jsx(ConfirmDialog, {
18602
19201
  label: "Discard changes",
18603
19202
  body: "Throw away every unsaved change to this page and the site, and reload both from the saved files?",
@@ -18780,6 +19379,30 @@ function RichTextBar() {
18780
19379
  class: "bm-rich",
18781
19380
  style: `top:${position.top}px;left:${position.left}px;`,
18782
19381
  children: [
19382
+ active?.headings && /* @__PURE__ */ jsxs(Fragment$1, { children: [
19383
+ /* @__PURE__ */ jsx("button", {
19384
+ type: "button",
19385
+ class: "bm-fmt-heading",
19386
+ "aria-label": "Heading",
19387
+ title: "Heading",
19388
+ "aria-pressed": active.heading === 2,
19389
+ onMouseDown: run("heading2"),
19390
+ children: "H2"
19391
+ }),
19392
+ /* @__PURE__ */ jsx("button", {
19393
+ type: "button",
19394
+ class: "bm-fmt-heading",
19395
+ "aria-label": "Subheading",
19396
+ title: "Subheading",
19397
+ "aria-pressed": active.heading === 3,
19398
+ onMouseDown: run("heading3"),
19399
+ children: "H3"
19400
+ }),
19401
+ /* @__PURE__ */ jsx("span", {
19402
+ class: "bm-sep",
19403
+ "aria-hidden": "true"
19404
+ })
19405
+ ] }),
18783
19406
  /* @__PURE__ */ jsx("button", {
18784
19407
  type: "button",
18785
19408
  class: "bm-fmt-bold",
@@ -19965,7 +20588,7 @@ function AdvancedLink({ edit }) {
19965
20588
  }
19966
20589
  //#endregion
19967
20590
  //#region src/ui/editor.css?raw
19968
- var editor_default = "/*\n * Editor styles. They live in a shadow root, so they never meet the site's Tailwind layer.\n * The editor is always light. Tokens and values follow the v4 editor design handoff.\n * The short names (--ink, --line, --accent ...) alias the --bm-* tokens so older rules read the same.\n */\n:host {\n all: initial;\n\n /* ---------- v4 tokens (editor-tokens.css) ---------- */\n --bm-font-ui: \"Bricolage Grotesque Variable\", \"Bricolage Grotesque\", ui-sans-serif, system-ui, sans-serif;\n --bm-font-mono: \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace;\n --bm-font-serif: \"Instrument Serif\", Georgia, serif;\n\n --bm-ink: oklch(0.21 0.012 255);\n --bm-label: oklch(0.3 0.01 255);\n --bm-section: oklch(0.42 0.01 255);\n --bm-help: oklch(0.47 0.01 255);\n --bm-muted: oklch(0.5 0.01 255);\n --bm-icon: oklch(0.55 0.01 255);\n --bm-info: oklch(0.6 0.01 255);\n\n --bm-fill: oklch(0.955 0.003 250);\n --bm-fill-hover: oklch(0.93 0.004 250);\n --bm-fill-soft: oklch(0.965 0.003 250);\n --bm-fill-nested: oklch(0.97 0.003 250);\n --bm-border: oklch(0.88 0.005 250);\n --bm-divider: oklch(0.93 0.004 250);\n --bm-tab-rule: oklch(0.92 0.004 250);\n\n --bm-primary: oklch(0.46 0.13 145);\n --bm-primary-hover: oklch(0.4 0.12 145);\n --bm-primary-ring: oklch(0.46 0.13 145 / 0.15);\n --bm-link: oklch(0.4 0.12 145);\n\n --bm-saved-bg: oklch(0.94 0.045 145);\n --bm-saved-fg: oklch(0.36 0.1 145);\n --bm-unsaved-bg: oklch(0.95 0.05 80);\n --bm-unsaved-fg: oklch(0.48 0.1 60);\n --bm-unsaved-dot: oklch(0.75 0.15 70);\n --bm-badge-green-bg: oklch(0.93 0.06 145);\n --bm-badge-green-fg: oklch(0.38 0.1 145);\n --bm-badge-amber-bg: oklch(0.95 0.04 75);\n --bm-badge-amber-fg: oklch(0.45 0.09 60);\n\n --bm-danger: oklch(0.55 0.19 25);\n --bm-danger-text: oklch(0.52 0.17 25);\n --bm-danger-icon: oklch(0.58 0.18 25);\n --bm-danger-soft: oklch(0.96 0.025 20);\n\n --bm-diff-del-bg: oklch(0.97 0.02 20);\n --bm-diff-del-fg: oklch(0.45 0.13 25);\n --bm-diff-add-bg: oklch(0.96 0.04 145);\n --bm-diff-add-fg: oklch(0.34 0.1 145);\n\n --bm-switch-off: oklch(0.82 0.005 250);\n\n --bm-shadow-pop: 0 0 0 1px oklch(0.9 0.005 250), 0 16px 36px -16px oklch(0.2 0.02 255 / 0.35);\n --bm-shadow-dialog: 0 0 0 1px oklch(0.9 0.005 250), 0 24px 48px -24px oklch(0.2 0.02 255 / 0.35);\n --bm-shadow-segment-on: 0 1px 2px oklch(0 0 0 / 0.08), 0 0 0 1px oklch(0.9 0.005 250);\n\n /* ---------- aliases used by the rules below ---------- */\n --ink: var(--bm-ink);\n --ink-2: var(--bm-label);\n --muted: var(--bm-muted);\n --line: var(--bm-border);\n --line-soft: var(--bm-divider);\n --fill: var(--bm-fill);\n --fill-hover: var(--bm-fill-hover);\n --fill-soft: var(--bm-fill-soft);\n --accent: var(--bm-primary);\n --accent-hover: var(--bm-primary-hover);\n --accent-tint: oklch(0.96 0.03 145);\n --accent-ring: var(--bm-primary-ring);\n --warn-tint: var(--bm-unsaved-bg);\n --warn-ink: var(--bm-unsaved-fg);\n --warn-dot: var(--bm-unsaved-dot);\n --danger-hover: oklch(0.48 0.18 25);\n --danger-tint: var(--bm-danger-soft);\n --danger-ink: var(--bm-danger-text);\n --info-dot: oklch(0.6 0.15 255);\n --sans: var(--bm-font-ui);\n --mono: var(--bm-font-mono);\n --serif: var(--bm-font-serif);\n --shadow-pop: var(--bm-shadow-pop);\n}\n* {\n box-sizing: border-box;\n}\nbutton,\ninput,\nselect,\ntextarea {\n font: inherit;\n color: inherit;\n}\nbutton {\n cursor: pointer;\n}\n:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n\n/* On-page outlines */\n.bm-outline {\n position: fixed;\n pointer-events: none;\n border-radius: 6px;\n z-index: 1;\n}\n.bm-outline-section {\n border: 2px solid var(--accent);\n}\n.bm-outline-field {\n border: 2px solid var(--accent);\n background: oklch(0.46 0.13 145 / 0.08);\n}\n.bm-image-bar {\n flex-wrap: nowrap;\n left: auto;\n white-space: nowrap;\n}\n.bm-image-bar-group {\n display: flex;\n gap: 2px;\n}\n.bm-image-bar button[aria-pressed=\"true\"] {\n background: var(--bm-saved-bg);\n color: var(--bm-saved-fg);\n}\n.bm-image-bar-grid {\n display: grid;\n grid-template-columns: repeat(3, 9px);\n grid-template-rows: repeat(3, 9px);\n gap: 2px;\n align-self: center;\n padding: 0 4px;\n}\n.bm-image-bar .bm-pos-cell {\n width: 9px;\n height: 9px;\n /* `.bm-rich button` sets a 32px minimum for the bar's text buttons; the cells stay 9px. */\n min-width: 0;\n min-height: 0;\n padding: 0;\n border-radius: 2px;\n background: var(--line);\n}\n.bm-image-bar .bm-pos-cell:hover:not(:disabled) {\n background: var(--muted);\n}\n.bm-image-bar .bm-pos-cell[aria-pressed=\"true\"] {\n background: var(--accent);\n}\n.bm-image-bar .bm-pos-cell:disabled {\n opacity: 0.3;\n cursor: default;\n}\n.bm-outline-image {\n background: oklch(0.46 0.13 145 / 0.12);\n}\n.bm-outline-image::after {\n content: \"Change image\";\n position: absolute;\n top: 8px;\n left: 8px;\n padding: 4px 9px;\n border-radius: 6px;\n background: var(--accent);\n color: #fff;\n font: 500 11px / 1.3 var(--sans, system-ui, sans-serif);\n}\n\n.bm-toolbar,\n.bm-dock,\n.bm-exit-preview,\n.bm-sidebar,\n.bm-popover,\n.bm-dialog,\n.bm-rich,\n.bm-banner,\n.bm-scrim {\n pointer-events: auto;\n font-family: var(--sans);\n font-size: 13px;\n color: var(--ink);\n -webkit-font-smoothing: antialiased;\n}\n\n/*\n * Insert between sections. Three states:\n * idle / hover a solid line and a 28px circle; hover changes nothing.\n * open the picker is open: the line stays and a \"between A and B\" chip replaces the circle.\n */\n.bm-gap {\n position: fixed;\n z-index: 2;\n height: 0;\n pointer-events: none;\n}\n.bm-gap::before {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n height: 0;\n border-top: 2px solid var(--bm-primary);\n transform: translateY(-50%);\n}\n.bm-gap-add {\n position: absolute;\n left: 50%;\n top: 0;\n transform: translate(-50%, -50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 999px;\n pointer-events: auto;\n cursor: pointer;\n white-space: nowrap;\n background: var(--bm-primary);\n color: #fff;\n box-shadow: 0 0 0 2px #fff;\n}\n.bm-gap-add .bm-icon {\n width: 14px;\n height: 14px;\n stroke-width: 2.4;\n}\n.bm-gap-add:focus-visible {\n outline: 2px solid var(--ink);\n outline-offset: 3px;\n}\n.bm-gap-chip {\n position: absolute;\n left: 50%;\n top: 0;\n transform: translate(-50%, -50%);\n padding: 4px 10px;\n border-radius: 999px;\n background: #fff;\n color: var(--bm-ink);\n box-shadow: 0 0 0 1.5px var(--bm-primary);\n white-space: nowrap;\n pointer-events: none;\n font-size: 12px;\n font-weight: 500;\n}\n\n/* Light floating bars: section toolbar, rich text bar, heading format bar */\n.bm-toolbar,\n.bm-rich {\n position: fixed;\n z-index: 3;\n display: flex;\n gap: 2px;\n padding: 4px;\n border-radius: 12px;\n background: #fff;\n color: var(--ink);\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-toolbar button,\n.bm-rich button {\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: inherit;\n min-height: 32px;\n padding: 0 10px;\n font-size: 12px;\n font-weight: 500;\n}\n.bm-toolbar button:hover:not(:disabled),\n.bm-rich button:hover {\n background: var(--fill);\n}\n.bm-rich button[aria-pressed=\"true\"] {\n background: var(--bm-saved-bg);\n box-shadow: inset 0 0 0 1px oklch(0.46 0.13 145 / 0.4);\n}\n.bm-toolbar :focus-visible,\n.bm-rich :focus-visible {\n outline-color: var(--accent);\n}\n.bm-toolbar {\n align-items: center;\n max-width: calc(100vw - 16px);\n padding: 5px;\n}\n.bm-toolbar button {\n width: 34px;\n min-height: 34px;\n height: 34px;\n padding: 0;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: oklch(0.4 0.01 255);\n}\n.bm-toolbar button:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n.bm-toolbar button:disabled {\n opacity: 0.35;\n cursor: default;\n}\n.bm-toolbar .bm-danger {\n color: var(--bm-danger-icon);\n}\n.bm-toolbar .bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-toolbar-active {\n box-shadow:\n 0 0 0 2px var(--bm-primary),\n 0 10px 24px -12px oklch(0.2 0.02 255 / 0.35);\n}\n.bm-toolbar-name {\n display: block;\n max-width: 16rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 0 12px 0 10px;\n}\n.bm-toolbar-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--bm-ink);\n}\n.bm-toolbar-anchor {\n font-family: var(--mono);\n font-size: 12px;\n font-weight: 400;\n color: var(--bm-muted);\n}\n.bm-sep {\n width: 1px;\n align-self: stretch;\n margin: 4px 2px;\n background: var(--line);\n}\n.bm-toolbar .bm-sep {\n align-self: center;\n height: 20px;\n margin: 0 4px;\n background: oklch(0.9 0.005 250);\n}\n.bm-icon {\n width: 16px;\n height: 16px;\n display: block;\n}\n.bm-rich {\n align-items: center;\n flex-wrap: wrap;\n max-width: calc(100vw - 16px);\n}\n.bm-rich button {\n min-height: 32px;\n min-width: 32px;\n}\n.bm-rich input {\n width: 168px;\n min-height: 30px;\n padding: 0 8px;\n border: 0;\n border-radius: 7px;\n background: var(--fill);\n color: var(--ink);\n font-size: 12px;\n}\n.bm-rich input:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--accent);\n}\n\n/* Heading format bar: each button shows \"Aa\" in its own weight or font over a mono caption. */\n.bm-rich.bm-format-bar {\n flex-wrap: nowrap;\n}\n.bm-rich.bm-format-bar button.bm-fmt {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2px;\n min-width: 42px;\n height: 48px;\n min-height: 48px;\n padding: 0 8px;\n border-radius: 8px;\n}\n.bm-fmt-sample {\n font-size: 15px;\n line-height: 1;\n color: var(--bm-ink);\n}\n.bm-fmt-caption {\n font-family: var(--mono);\n font-size: 9px;\n letter-spacing: 0.02em;\n color: var(--bm-muted);\n}\n.bm-rich.bm-format-bar button.bm-fmt[aria-pressed=\"true\"] {\n background: var(--bm-saved-bg);\n box-shadow: inset 0 0 0 1px oklch(0.46 0.13 145 / 0.4);\n}\n.bm-format-bar .bm-sep {\n align-self: stretch;\n margin: 6px 4px;\n}\n\n/* Light popovers: add menu, section picker, edit link */\n.bm-popover {\n position: fixed;\n z-index: 3;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 180px;\n max-height: min(420px, calc(100vh - 16px));\n overflow: auto;\n padding: 6px;\n border-radius: 12px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-popover > button {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 34px;\n padding: 0 10px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n text-align: left;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-popover > button:hover {\n background: var(--fill);\n}\n\n/* Add section picker: wireframe cards */\n.bm-popover[aria-label=\"Add section\"][role=\"listbox\"] {\n gap: 14px;\n width: 640px;\n max-width: calc(100vw - 16px);\n max-height: calc(100vh - 16px);\n padding: 16px;\n border-radius: 14px;\n overflow: visible;\n box-shadow: var(--bm-shadow-dialog);\n}\n.bm-picker-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.bm-picker-title {\n font-size: 17px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n.bm-picker-where {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n color: var(--bm-muted);\n}\n.bm-picker-grid {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 10px;\n max-height: 26rem;\n overflow-y: auto;\n padding: 2px 6px 2px 2px;\n margin-right: -6px;\n scrollbar-gutter: stable;\n}\n.bm-popover .bm-picker-grid > button {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: flex-start;\n gap: 6px;\n min-height: 0;\n padding: 8px 8px 10px;\n border: 1px solid oklch(0.9 0.005 250);\n border-radius: 10px;\n background: #fff;\n text-align: left;\n font-weight: 400;\n}\n.bm-popover .bm-picker-grid > button:hover {\n background: #fff;\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px oklch(0.46 0.13 145 / 0.12);\n}\n.bm-wire {\n position: relative;\n display: block;\n width: 100%;\n height: 76px;\n border-radius: 7px;\n background: oklch(0.97 0 0);\n overflow: hidden;\n}\n.bm-wire > span {\n position: absolute;\n display: block;\n}\n.bm-type-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 0 2px;\n}\n.bm-type-name {\n font-size: 14px;\n font-weight: 600;\n line-height: 1.25;\n color: var(--bm-ink);\n}\n.bm-type-variants {\n font-family: var(--mono);\n font-size: 10px;\n font-weight: 400;\n line-height: 1.35;\n white-space: nowrap;\n color: var(--muted);\n}\n.bm-type-desc {\n padding: 0 2px;\n font-size: 12px;\n line-height: 1.4;\n color: var(--bm-help);\n}\n.bm-picker-note {\n margin: 0;\n font-size: 12px;\n color: var(--bm-muted);\n}\n\n.bm-popover[aria-label=\"Edit link\"] {\n gap: 14px;\n padding: 16px;\n max-height: calc(100vh - 16px);\n}\n\n/* Dialogs and banners */\n.bm-dialog {\n position: fixed;\n z-index: 6;\n display: flex;\n flex-direction: column;\n gap: 16px;\n width: min(400px, calc(100vw - 32px));\n padding: 20px;\n border-radius: 14px;\n background: #fff;\n box-shadow: var(--bm-shadow-dialog);\n}\n.bm-dialog-head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n}\n.bm-dialog-heading {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.bm-dialog-sub {\n margin: 0;\n font-size: 13px;\n line-height: 1.4;\n color: var(--bm-help);\n}\n.bm-dialog .bm-dialog-x,\n.bm-popover .bm-dialog-x,\n.bm-modal .bm-dialog-x {\n flex: none;\n width: 32px;\n height: 32px;\n margin: -6px -8px -6px 0;\n background: transparent;\n color: var(--bm-icon);\n}\n.bm-dialog-title {\n margin: 0;\n font-size: 17px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--bm-ink);\n}\n.bm-popover .bm-dialog-title {\n font-size: 16px;\n}\n.bm-dialog .bm-note {\n color: var(--bm-label);\n font-size: 14px;\n line-height: 1.5;\n}\n.bm-dialog button,\n.bm-popover .bm-actions button,\n.bm-banner button {\n min-height: 38px;\n padding: 0 16px;\n border: 0;\n border-radius: 8px;\n background: var(--fill);\n font-size: 14px;\n font-weight: 400;\n}\n.bm-dialog button:hover:not(:disabled),\n.bm-popover .bm-actions button:hover:not(:disabled) {\n background: var(--fill-hover);\n}\n/* The primary action comes first in the DOM (focus lands on it); row-reverse shows it last, on the right. */\n.bm-actions {\n display: flex;\n flex-direction: row-reverse;\n justify-content: flex-start;\n align-items: center;\n gap: 8px;\n}\n.bm-dialog > .bm-actions,\n.bm-popover[aria-label=\"Edit link\"] > .bm-actions {\n padding-top: 12px;\n border-top: 1px solid var(--bm-divider);\n}\n.bm-dialog-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-top: 12px;\n border-top: 1px solid var(--bm-divider);\n}\n.bm-dialog-foot > .bm-hint {\n flex: 1;\n min-width: 0;\n margin: 0;\n}\n.bm-dialog-foot .bm-actions {\n flex: none;\n}\n\n/* Alert dialogs: [icon tile] [title / body / note] [x] */\n.bm-alert-main {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n.bm-alert-copy {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.bm-alert-body {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n color: var(--bm-label);\n overflow-wrap: anywhere;\n}\n.bm-alert-body strong {\n font-weight: 600;\n color: var(--bm-ink);\n}\n.bm-alert-note {\n margin: 0;\n font-size: 12px;\n line-height: 1.45;\n color: var(--bm-muted);\n}\n.bm-tile {\n flex: none;\n display: grid;\n place-items: center;\n width: 36px;\n height: 36px;\n border-radius: 9px;\n}\n.bm-tile .bm-icon {\n width: 18px;\n height: 18px;\n}\n.bm-tile-warn {\n background: var(--bm-unsaved-bg);\n color: var(--bm-unsaved-fg);\n}\n.bm-tile-danger {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-tile-neutral {\n background: var(--bm-fill);\n color: var(--bm-label);\n}\n\n.bm-banner {\n position: fixed;\n z-index: 6;\n display: flex;\n align-items: center;\n gap: 12px;\n width: min(440px, calc(100vw - 32px));\n padding: 12px 14px;\n border-radius: 12px;\n box-shadow: 0 14px 34px -10px oklch(0.2 0.02 255 / 0.4);\n}\n.bm-banner button {\n min-height: 34px;\n padding: 0 14px;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-banner-ink {\n background: var(--ink);\n color: #fff;\n}\n.bm-banner-light {\n background: #fff;\n box-shadow: var(--shadow-pop);\n}\n.bm-banner-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n.bm-banner-title {\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.35;\n}\n.bm-banner-sub {\n margin: 0;\n font-size: 12px;\n line-height: 1.4;\n opacity: 0.7;\n}\n.bm-banner .bm-actions {\n flex: none;\n gap: 6px;\n}\n.bm-banner-ink button {\n min-height: 30px;\n padding: 0 12px;\n font-size: 12px;\n background: oklch(1 0 0 / 0.12);\n color: #fff;\n}\n.bm-banner-ink button:hover {\n background: oklch(1 0 0 / 0.2);\n}\n.bm-banner-ink .bm-primary {\n background: #fff;\n color: var(--ink);\n}\n.bm-banner-ink .bm-primary:hover {\n background: oklch(0.94 0.003 250);\n}\n.bm-banner-ink :focus-visible {\n outline-color: oklch(0.82 0.14 145);\n}\n.bm-dot-stale {\n background: oklch(0.7 0.18 25) !important;\n}\n.bm-dot-info {\n background: var(--info-dot) !important;\n}\n\n/* Closed editor. The dock sits where the sidebar header's controls sit: header padding (top 14, right 14) minus the dock's 7px padding. */\n.bm-dock {\n position: fixed;\n z-index: 5;\n top: 7px;\n right: 7px;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 7px 7px 7px 10px;\n border-radius: 14px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-dot {\n flex: none;\n width: 8px;\n height: 8px;\n border-radius: 99px;\n background: oklch(0.72 0.17 145);\n}\n.bm-dot-dirty {\n background: var(--warn-dot);\n}\n\n/* Sidebar shell */\n.bm-sidebar {\n position: fixed;\n z-index: 4;\n top: 0;\n right: 0;\n bottom: 0;\n width: min(440px, 100vw);\n display: flex;\n flex-direction: column;\n background: #fff;\n box-shadow:\n 0 0 0 1px var(--line),\n -24px 0 48px -24px oklch(0.2 0.02 255 / 0.25);\n}\n.bm-resize {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n touch-action: none;\n z-index: 2;\n}\n.bm-resize:hover,\n.bm-resize:focus-visible {\n background: oklch(0.46 0.13 145 / 0.25);\n}\n.bm-resize:focus-visible {\n outline-offset: -2px;\n}\n\n.bm-head {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 14px 14px 16px;\n border-bottom: 1px solid var(--line-soft);\n}\n.bm-mark {\n flex: none;\n display: block;\n width: 28px;\n height: auto;\n aspect-ratio: 21 / 19;\n image-rendering: pixelated;\n user-select: none;\n}\n/* Bear, name and slogan. Takes the space the controls leave; the text fades out when it no longer fits. */\n.bm-brand {\n position: relative;\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.bm-head-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n transition: opacity 160ms ease;\n}\n.bm-brand-compact .bm-head-text {\n opacity: 0;\n}\n/* The same two lines, in a card left of the sidebar (over the page), level with the header, while the pointer is on\n the brand. 16px is the header's left padding: the card clears the sidebar edge by 10px. */\n.bm-brand-tip {\n position: absolute;\n z-index: 5;\n top: 50%;\n right: calc(100% + 16px + 10px);\n display: flex;\n flex-direction: column;\n padding: 8px 12px;\n border-radius: 10px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n white-space: nowrap;\n opacity: 0;\n transform: translate(4px, -50%);\n pointer-events: none;\n transition:\n opacity 120ms ease,\n transform 120ms ease;\n}\n.bm-brand-compact:hover .bm-brand-tip {\n opacity: 1;\n transform: translate(0, -50%);\n transition-delay: 120ms;\n}\n@media (prefers-reduced-motion: reduce) {\n .bm-head-text,\n .bm-brand-tip {\n transition: none;\n }\n}\n/* A ring with one open quarter that turns while a save is written and the page reloads. */\n.bm-spin {\n flex: none;\n width: 14px;\n height: 14px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: bm-spin 0.8s linear infinite;\n}\n@keyframes bm-spin {\n to {\n transform: rotate(360deg);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .bm-spin {\n animation: none;\n }\n}\n.bm-faces {\n display: grid;\n}\n.bm-face {\n grid-area: 1 / 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n white-space: nowrap;\n}\n.bm-face[hidden-face] {\n visibility: hidden;\n}\n.bm-save:disabled {\n opacity: 0.85;\n cursor: progress;\n}\n.bm-head-title {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.015em;\n /* The controls beside it never shrink, so a narrow sidebar cuts the name, not the buttons. */\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-head-sub {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-pill {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 24px;\n padding: 0 10px;\n border-radius: 999px;\n background: var(--bm-saved-bg);\n color: var(--bm-saved-fg);\n font-size: 12px;\n font-weight: 500;\n}\n.bm-pill .bm-dot {\n width: 6px;\n height: 6px;\n background: var(--accent);\n}\n.bm-pill-dirty {\n background: var(--warn-tint);\n color: var(--warn-ink);\n}\n.bm-pill-dirty .bm-dot {\n background: var(--warn-dot);\n}\nbutton.bm-pill-btn {\n min-height: 0;\n padding: 0 10px;\n border: 0;\n border-radius: 999px;\n background: var(--warn-tint);\n color: var(--warn-ink);\n font-family: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n}\n:is(.bm-sidebar, .bm-dock) button.bm-pill-btn:hover:not(:disabled) {\n background: oklch(0.93 0.06 75);\n color: var(--warn-ink);\n}\nbutton.bm-pill-btn:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n.bm-dialog-wide {\n width: min(400px, calc(100vw - 32px));\n}\n.bm-dialog .bm-actions {\n flex-wrap: nowrap;\n}\n.bm-dialog .bm-actions button {\n flex: none;\n white-space: nowrap;\n}\n.bm-changes {\n width: min(540px, calc(100vw - 32px));\n}\n.bm-commit-files {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n max-height: min(34vh, 280px);\n overflow-y: auto;\n}\n.bm-commit-files label {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n cursor: pointer;\n}\n.bm-commit-mark {\n font:\n 600 11px / 1 ui-monospace,\n monospace;\n width: 18px;\n text-align: center;\n opacity: 0.7;\n}\n.bm-commit-msg {\n width: 100%;\n box-sizing: border-box;\n resize: vertical;\n font: inherit;\n font-size: 14px;\n padding: 8px 12px;\n border: 1px solid var(--line);\n border-radius: 8px;\n background: transparent;\n color: inherit;\n}\n\n/* Unsaved changes review and version history: groups, rows, diff lines */\n.bm-changes-list {\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-height: 22rem;\n overflow-y: auto;\n margin: 0 -4px;\n padding: 0 4px;\n}\n.bm-changes-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-changes-area {\n margin: 0;\n display: flex;\n align-items: baseline;\n gap: 8px;\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bm-section);\n}\n.bm-changes-file {\n font-weight: 400;\n letter-spacing: 0;\n text-transform: none;\n color: oklch(0.55 0.01 255);\n}\n.bm-changes-count {\n margin-left: auto;\n font-weight: 400;\n letter-spacing: 0;\n color: var(--bm-muted);\n}\n.bm-changes ul {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n overflow: hidden;\n}\n.bm-change {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px;\n font-size: 14px;\n line-height: 1.4;\n}\n.bm-change + .bm-change {\n border-top: 1px solid var(--bm-divider);\n}\n.bm-change-mark {\n flex: none;\n display: grid;\n place-items: center;\n width: 22px;\n height: 22px;\n border-radius: 6px;\n font-family: var(--mono);\n font-size: 13px;\n font-weight: 600;\n background: var(--bm-unsaved-bg);\n color: var(--bm-unsaved-fg);\n}\n.bm-change-added .bm-change-mark {\n background: var(--bm-badge-green-bg);\n color: var(--bm-badge-green-fg);\n}\n.bm-change-removed .bm-change-mark {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-text);\n}\n.bm-change-body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.bm-change-field {\n font-weight: 500;\n color: var(--bm-ink);\n overflow-wrap: anywhere;\n}\n.bm-change-values {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n}\n.bm-change-values del,\n.bm-change-values ins {\n display: flex;\n gap: 6px;\n min-width: 0;\n padding: 3px 7px;\n border-radius: 5px;\n text-decoration: none;\n font-size: 13px;\n}\n.bm-change-values del {\n background: var(--bm-diff-del-bg);\n color: var(--bm-diff-del-fg);\n}\n.bm-change-values ins {\n background: var(--bm-diff-add-bg);\n color: var(--bm-diff-add-fg);\n}\n.bm-change-values del::before {\n content: \"\\2212\";\n flex: none;\n font-family: var(--mono);\n}\n.bm-change-values ins::before {\n content: \"+\";\n flex: none;\n font-family: var(--mono);\n}\n.bm-change-values del > span,\n.bm-change-values ins > span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-change-values del > span {\n text-decoration: line-through;\n text-decoration-color: oklch(0.45 0.13 25 / 0.5);\n}\n.bm-changes-empty {\n margin: 0;\n padding: 24px 0;\n text-align: center;\n font-size: 14px;\n color: var(--bm-muted);\n}\n\n.bm-changes ul.bm-versions {\n gap: 0;\n}\n.bm-version {\n padding: 0;\n}\n.bm-version + .bm-version {\n border-top: 1px solid var(--bm-divider);\n}\n.bm-version-when strong {\n font-weight: 600;\n}\n.bm-tipped {\n position: relative;\n}\n.bm-tipped::after {\n content: attr(data-tip);\n position: absolute;\n right: calc(100% + 6px);\n top: 50%;\n transform: translateY(-50%);\n padding: 4px 8px;\n border-radius: 6px;\n background: var(--ink);\n color: #fff;\n font-size: 12px;\n font-weight: 500;\n line-height: 1.3;\n white-space: nowrap;\n pointer-events: none;\n visibility: hidden;\n z-index: 5;\n}\n.bm-version-row > .bm-tipped:first-child::after {\n right: auto;\n left: calc(100% + 6px);\n}\n.bm-tipped:hover::after,\n.bm-tipped:focus-visible::after {\n visibility: visible;\n}\n.bm-version-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 8px 8px 10px;\n}\n.bm-version-when {\n flex: 1;\n min-width: 0;\n margin-right: auto;\n padding: 0 !important;\n min-height: 32px !important;\n font-weight: 500;\n display: flex !important;\n flex-direction: column;\n align-items: flex-start !important;\n justify-content: center;\n gap: 2px;\n text-align: left;\n}\n.bm-version-line {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n.bm-version-sum {\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n font-weight: 400;\n color: var(--bm-help);\n}\n.bm-version-row .bm-restore {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n min-height: 32px;\n padding: 0 10px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-version-rel {\n font-size: 14px;\n font-weight: 500;\n color: var(--bm-ink);\n}\n.bm-version-abs {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--bm-muted);\n}\n.bm-version-diff {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 4px 10px 12px 10px;\n border-top: 1px solid var(--bm-divider);\n margin-top: 0;\n}\n.bm-version-diff ul {\n margin: 0;\n}\n.bm-day {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.bm-restored {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 8px 8px 12px;\n border-radius: 9px;\n background: var(--bm-diff-add-bg);\n color: var(--bm-saved-fg);\n font-size: 13px;\n}\n.bm-restored > span {\n flex: 1;\n min-width: 0;\n}\n\n.bm-tabs {\n display: flex;\n gap: 0;\n padding: 0 12px;\n overflow-x: auto;\n border-bottom: 1px solid var(--bm-tab-rule);\n}\n.bm-tabs button {\n flex: 1 1 auto;\n height: 46px;\n padding: 0 6px;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: oklch(0.48 0.01 255);\n font-size: 13px;\n font-weight: 400;\n}\n.bm-tabs button:hover {\n color: var(--ink);\n background: var(--fill-soft);\n}\n.bm-tabs button[aria-selected=\"true\"] {\n color: var(--ink);\n background: transparent;\n font-weight: 600;\n box-shadow: inset 0 -2px 0 var(--accent);\n}\n.bm-tabs button:focus-visible {\n outline-offset: -2px;\n}\n\n.bm-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 24px 24px 32px;\n display: flex;\n flex-direction: column;\n gap: 18px;\n}\n.bm-foot {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n border-top: 1px solid var(--line-soft);\n font-family: var(--mono);\n font-size: 10px;\n color: var(--muted);\n}\n.bm-foot span:first-child {\n flex: none;\n white-space: nowrap;\n}\n.bm-foot span:last-child {\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n/* Group header: mono 11/500, then a 1px rule. With a right-hand item the rule sits on the flex wrapper. */\n.bm-group {\n margin: 18px 0 0;\n padding-bottom: 10px;\n border-bottom: 1px solid var(--bm-divider);\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bm-section);\n}\n.bm-group:first-child {\n margin-top: 0;\n}\n.bm-stack-tight > .bm-group {\n margin-bottom: 10px;\n}\n.bm-meta {\n margin: 0;\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n}\n\n/* Fields */\n.bm-label {\n display: flex;\n flex-direction: column;\n gap: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n}\n.bm-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-hint {\n font-size: 12px;\n line-height: 1.45;\n font-weight: 400;\n color: var(--muted);\n}\n.bm-label-text {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n}\n.bm-info {\n position: relative;\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n margin-left: 4px;\n}\n.bm-info-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n margin: -3px 0;\n border-radius: 999px;\n color: var(--bm-info);\n cursor: help;\n text-transform: none;\n letter-spacing: 0;\n}\n.bm-info-btn:hover,\n.bm-info-btn[aria-expanded=\"true\"] {\n color: var(--ink);\n}\n.bm-info-btn:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 1px;\n}\n.bm-tip {\n position: fixed;\n z-index: 2147483647;\n visibility: hidden;\n pointer-events: none;\n padding: 8px 10px;\n border-radius: 8px;\n box-sizing: border-box;\n background: var(--ink);\n color: oklch(0.98 0.003 250);\n font-family: var(--sans, inherit);\n font-size: 12px;\n line-height: 1.45;\n font-weight: 400;\n text-transform: none;\n letter-spacing: 0;\n text-align: left;\n white-space: normal;\n box-shadow: 0 6px 20px rgb(0 0 0 / 0.25);\n}\n.bm-tip-open {\n visibility: visible;\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) :where(input:not([type=\"checkbox\"]):not([type=\"file\"]), select, textarea) {\n width: 100%;\n min-height: 40px;\n padding: 0 12px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n color: var(--ink);\n font-size: 14px;\n font-weight: 400;\n outline: none;\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) textarea {\n padding: 8px 12px;\n min-height: 72px;\n line-height: 1.5;\n resize: vertical;\n}\n:is(.bm-sidebar, .bm-popover) select:not([size]) {\n appearance: none;\n padding-right: 32px;\n /* A caret made of gradients, not a `data:` image: a site's Content-Security-Policy can block those. */\n background-image: linear-gradient(45deg, transparent 50%, #777 50%), linear-gradient(135deg, #777 50%, transparent 50%);\n background-size: 6px 6px;\n background-repeat: no-repeat;\n background-position:\n right 17px center,\n right 12px center;\n}\n.bm-sidebar select[size],\n.bm-popover select[size] {\n padding: 4px;\n font-size: 12px;\n}\n.bm-sidebar select[size] option,\n.bm-sidebar select[size] optgroup,\n.bm-popover select[size] option,\n.bm-popover select[size] optgroup {\n padding: 3px 6px;\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) :where(input:not([type=\"checkbox\"]):not([type=\"file\"]), select, textarea):focus {\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px var(--bm-primary-ring);\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) :where(input[aria-label=\"Link URL\"], .bm-mono) {\n font-family: var(--mono);\n font-size: 13px;\n}\n.bm-prefix-wrap {\n display: flex;\n align-items: center;\n min-height: 40px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n}\n.bm-prefix-wrap:focus-within {\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px var(--bm-primary-ring);\n}\n.bm-prefix {\n padding: 0 2px 0 12px;\n font-family: var(--mono);\n font-size: 13px;\n color: var(--muted);\n}\n.bm-prefix-wrap input {\n border: 0;\n box-shadow: none !important;\n min-height: 38px;\n padding-left: 2px;\n font-family: var(--mono);\n font-size: 13px;\n}\n.bm-stack {\n display: flex;\n flex-direction: column;\n gap: 18px;\n}\n.bm-stack-tight {\n gap: 8px;\n}\n.bm-groups {\n gap: 36px;\n}\n.bm-list {\n display: flex;\n flex-direction: column;\n border-radius: 10px;\n box-shadow: 0 0 0 1px var(--bm-border);\n overflow: hidden;\n}\n.bm-list-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px 8px 12px;\n border-bottom: 1px solid var(--line-soft);\n}\n.bm-list-row:last-child {\n border-bottom: 0;\n}\n.bm-list-row-on {\n background: var(--accent-tint);\n}\n.bm-list-row a {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n color: var(--ink);\n text-decoration: none;\n}\n.bm-list-row a:hover .bm-list-title {\n text-decoration: underline;\n}\n.bm-list-title {\n font-size: 14px;\n font-weight: 500;\n}\n.bm-list-path {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n}\n.bm-badge-home {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: var(--bm-badge-green-bg);\n color: var(--bm-badge-green-fg);\n}\n.bm-badge {\n font-family: var(--mono);\n font-size: 11px;\n padding: 3px 7px;\n border-radius: 5px;\n background: var(--bm-badge-amber-bg);\n color: var(--bm-badge-amber-fg);\n}\n.bm-badge-system {\n background: var(--fill);\n color: var(--ink-2);\n}\n.bm-badge-on {\n background: var(--bm-badge-green-bg);\n color: var(--bm-badge-green-fg);\n}\n.bm-row {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-wrap: wrap;\n}\n.bm-row-split {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 10px;\n}\n.bm-error {\n color: var(--danger-ink);\n font-size: 12px;\n font-weight: 400;\n margin: 0;\n}\n.bm-warn {\n color: var(--warn-ink);\n font-size: 12px;\n margin: 0;\n}\n.bm-note {\n margin: 0;\n color: var(--bm-help);\n font-size: 13px;\n line-height: 1.55;\n font-weight: 400;\n}\n.bm-group + .bm-note,\n.bm-group-split + .bm-note {\n margin-top: -4px;\n}\n\n/* Switch: 36 x 20, knob 16 inset 2 */\n.bm-check {\n flex-direction: row;\n align-items: center;\n gap: 10px;\n font-weight: 500;\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"] {\n appearance: none;\n position: relative;\n flex: none;\n width: 36px;\n height: 20px;\n margin: 0;\n border-radius: 999px;\n background: var(--bm-switch-off);\n cursor: pointer;\n transition: background 0.15s;\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"]::before {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #fff;\n box-shadow: 0 1px 2px oklch(0 0 0 / 0.2);\n transition: transform 0.15s;\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"]:checked {\n background: var(--bm-primary);\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"]:checked::before {\n transform: translateX(16px);\n}\n.bm-popover .bm-check {\n color: var(--bm-label);\n font-size: 14px;\n}\n\n/* Buttons inside the sidebar */\n.bm-sidebar :where(button:not([role=\"tab\"]):not([role=\"radio\"]):not(.bm-resize)) {\n min-height: 32px;\n padding: 0 12px;\n border: 0;\n border-radius: 8px;\n background: var(--fill);\n color: var(--ink);\n font-size: 13px;\n font-weight: 500;\n}\n.bm-sidebar :where(button:not([role=\"tab\"]):not([role=\"radio\"]):not(.bm-resize)):hover:not(:disabled) {\n background: var(--fill-hover);\n}\n.bm-sidebar button:disabled {\n opacity: 0.45;\n cursor: default;\n}\n/* Dashed \"Add ...\" buttons: Add link, Add button, Add column, Add item */\n.bm-sidebar .bm-add {\n min-height: 44px;\n background: oklch(0.985 0.002 250);\n color: var(--bm-link);\n border: 1px dashed oklch(0.85 0.005 250);\n border-radius: 8px;\n}\n.bm-sidebar .bm-add:hover:not(:disabled) {\n background: var(--accent-tint);\n}\n\n/* Cards, lists, images */\n.bm-card {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 12px;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n}\n.bm-card .bm-card {\n background: var(--bm-fill-nested);\n border-color: var(--line-soft);\n}\n.bm-card > .bm-label:first-child:not(:only-child) {\n font-family: var(--mono);\n font-size: 11px;\n letter-spacing: 0.04em;\n font-weight: 500;\n color: var(--muted);\n}\n.bm-card[draggable=\"true\"] {\n cursor: grab;\n}\n/* Drag and drop: the target shows what a drop would do. */\n.bm-dragging {\n opacity: 0.4;\n}\n.bm-drop-before,\n.bm-drop-after,\n.bm-drop-child {\n --drop: var(--accent);\n}\n.bm-drop-before::before,\n.bm-drop-after::before {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n height: 3px;\n border-radius: 3px;\n background: var(--drop);\n box-shadow: 0 0 0 2px var(--accent-ring);\n pointer-events: none;\n z-index: 2;\n}\n.bm-drop-before::before {\n top: -6px;\n}\n.bm-drop-after::before {\n bottom: -6px;\n}\n.bm-drop-child {\n box-shadow: inset 0 0 0 2px var(--drop);\n background: var(--accent-tint);\n}\n.bm-drop-before::after,\n.bm-drop-after::after,\n.bm-drop-child::after,\n.bm-drop-files::after {\n content: attr(data-drop-hint);\n position: absolute;\n right: 8px;\n padding: 3px 8px;\n border-radius: 6px;\n background: var(--ink);\n color: #fff;\n font-size: 11px;\n font-weight: 500;\n line-height: 1.3;\n white-space: nowrap;\n pointer-events: none;\n z-index: 3;\n}\n.bm-drop-before::after {\n top: -22px;\n}\n.bm-drop-after::after {\n bottom: -22px;\n}\n.bm-drop-child::after {\n top: -11px;\n right: 12px;\n}\n.bm-drop-files {\n box-shadow: inset 0 0 0 2px var(--accent);\n background: var(--accent-tint);\n}\n.bm-drop-files::after {\n top: -11px;\n right: 12px;\n}\n.bm-thumb {\n width: 100%;\n height: 96px;\n object-fit: cover;\n border-radius: 7px;\n background: var(--fill);\n}\n.bm-drop {\n display: flex;\n flex-direction: column;\n gap: 8px;\n border: 1px dashed var(--line);\n border-radius: 10px;\n padding: 10px;\n background: var(--fill-soft);\n}\n.bm-drop input[type=\"file\"] {\n width: 100%;\n font-size: 12px;\n color: var(--muted);\n}\n.bm-drop input[type=\"file\"]::file-selector-button {\n height: 32px;\n margin-right: 10px;\n padding: 0 12px;\n border: 0;\n border-radius: 7px;\n background: var(--ink);\n color: #fff;\n font: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n}\n.bm-alert {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 14px;\n border-radius: 12px;\n background: var(--danger-tint);\n box-shadow: 0 0 0 1px oklch(0.55 0.18 25 / 0.35);\n}\n.bm-alert-title {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--danger-ink);\n}\n.bm-alert .bm-error {\n font-family: var(--mono);\n font-size: 11px;\n}\n.bm-alert-notice {\n background: var(--warn-tint);\n box-shadow: 0 0 0 1px oklch(0.45 0.09 65 / 0.2);\n}\n.bm-alert-notice .bm-note {\n color: var(--warn-ink);\n font-size: 12px;\n}\n\n/* Header actions */\n.bm-save {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 34px;\n padding: 0 12px;\n border: 0;\n border-radius: 8px;\n background: var(--accent);\n color: #fff;\n font-size: 13px;\n font-weight: 600;\n}\n.bm-dialog .bm-primary kbd {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n margin-left: 8px;\n opacity: 0.8;\n}\n.bm-save kbd {\n font-family: var(--mono);\n font-size: 10px;\n font-weight: 400;\n opacity: 0.75;\n}\n/* Icon buttons: 32 x 32, transparent, grey icon, grey fill on hover. */\n.bm-icon-btn {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: 32px;\n height: 32px;\n min-height: 0 !important;\n padding: 0 !important;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--bm-icon);\n}\n.bm-icon-btn:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n.bm-icon-btn:disabled {\n opacity: 0.35;\n}\n.bm-close {\n width: 32px;\n height: 32px;\n background: transparent;\n color: var(--bm-icon);\n border-radius: 7px;\n}\n.bm-close:hover:not(:disabled) {\n background: var(--fill) !important;\n color: var(--ink);\n}\n.bm-dock .bm-save {\n font-family: var(--sans);\n}\n.bm-split {\n position: relative;\n display: inline-flex;\n flex: none;\n}\n.bm-split .bm-split-main {\n border-radius: 8px 0 0 8px;\n}\n.bm-split .bm-split-toggle {\n width: 28px;\n padding: 0;\n justify-content: center;\n border-radius: 0 8px 8px 0;\n box-shadow: inset 1px 0 0 oklch(1 0 0 / 0.35);\n}\n.bm-split .bm-split-toggle:focus-visible,\n.bm-split .bm-split-main:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n.bm-split-menu {\n position: absolute;\n z-index: 8;\n top: calc(100% + 6px);\n right: 0;\n min-width: 200px;\n display: flex;\n flex-direction: column;\n padding: 4px;\n border-radius: 10px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-split-menu button.bm-split-item {\n display: flex;\n align-items: center;\n width: 100%;\n min-height: 34px;\n padding: 0 10px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--ink);\n font-family: var(--sans);\n font-size: 13px;\n font-weight: 500;\n text-align: left;\n}\n.bm-split-menu button.bm-split-item:hover:not(:disabled),\n.bm-split-menu button.bm-split-item:focus-visible {\n background: var(--fill);\n outline: none;\n}\n.bm-split-menu button.bm-split-danger {\n color: var(--danger-ink);\n}\n.bm-split-menu button.bm-split-item {\n justify-content: space-between;\n gap: 16px;\n}\n.bm-split-menu button.bm-split-item kbd {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--muted);\n}\n.bm-split-menu button.bm-split-sep {\n margin-top: 5px;\n position: relative;\n}\n.bm-split-menu button.bm-split-sep::before {\n content: \"\";\n position: absolute;\n left: 6px;\n right: 6px;\n top: -3px;\n height: 1px;\n background: var(--line);\n}\n.bm-split-menu button.bm-split-danger:hover:not(:disabled),\n.bm-split-menu button.bm-split-danger:focus-visible {\n background: var(--danger-tint);\n}\n.bm-split-menu button.bm-split-item:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.bm-sidebar .bm-icon-btn.bm-danger {\n color: var(--bm-danger-icon);\n}\n.bm-sidebar .bm-icon-btn.bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-small {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n min-height: 28px !important;\n padding: 0 10px !important;\n font-family: var(--sans);\n font-size: 12px !important;\n letter-spacing: 0;\n text-transform: none;\n align-self: flex-start;\n}\n.bm-group-split {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-top: 18px;\n margin-bottom: 0;\n padding-bottom: 10px;\n border-bottom: 1px solid var(--bm-divider);\n}\n.bm-group-split:first-child {\n margin-top: 0;\n}\n.bm-group-split > .bm-group {\n margin: 0;\n padding: 0;\n border: 0;\n}\n.bm-group-split .bm-small {\n text-transform: none;\n letter-spacing: 0;\n}\n.bm-group-split span.bm-small {\n font-family: var(--mono);\n font-size: 11px !important;\n font-weight: 400;\n color: var(--bm-muted);\n padding: 0 !important;\n min-height: 0 !important;\n}\n.bm-stack-tight > .bm-group-split {\n margin-bottom: 10px;\n}\n\n/* Labels with a right-hand tag */\n.bm-label.bm-label-row,\n.bm-label-row {\n flex-direction: row;\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n}\n.bm-meta-tag {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n letter-spacing: 0;\n color: var(--bm-muted);\n}\n\n/* Switch rows */\n.bm-switch-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n cursor: pointer;\n}\n.bm-switch-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n.bm-switch-title {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n font-weight: 500;\n color: var(--bm-label);\n}\n\n/* Tone cards and segmented controls */\n.bm-tones {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 6px;\n}\n:is(.bm-sidebar, .bm-popover) .bm-tone {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: 6px;\n min-height: 0;\n padding: 5px 5px 6px;\n border-radius: 9px;\n background: #fff;\n border: 0;\n box-shadow: inset 0 0 0 1px var(--bm-border);\n font-size: 12px;\n font-weight: 500;\n text-align: center;\n}\n:is(.bm-sidebar, .bm-popover) .bm-tone:hover {\n background: var(--fill-soft);\n}\n:is(.bm-sidebar, .bm-popover) .bm-tone[aria-checked=\"true\"] {\n box-shadow: inset 0 0 0 2px var(--accent);\n background: #fff;\n}\n.bm-tones-2 {\n grid-template-columns: repeat(2, 1fr);\n}\n.bm-tones-3 {\n grid-template-columns: repeat(3, 1fr);\n}\n/* A miniature of each button look, drawn with the editor's colours so it does not depend on the site theme. */\n.bm-btnsample {\n display: grid;\n place-items: center;\n height: 26px;\n border-radius: 6px;\n background: var(--fill-soft);\n}\n.bm-btnsample > span {\n display: block;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n}\n.bm-btnsample-default > span {\n color: var(--ink-2);\n}\n.bm-btnsample-primary > span {\n padding: 5px 12px;\n border-radius: 999px;\n background: var(--accent);\n color: #fff;\n}\n.bm-btnsample-secondary > span {\n padding: 5px 12px;\n border-radius: 999px;\n color: var(--ink);\n box-shadow: inset 0 0 0 1px var(--ink-2);\n}\n.bm-btnsample-tertiary > span {\n color: var(--accent);\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n.bm-swatch {\n display: inline-block;\n flex: none;\n width: 10px;\n height: 10px;\n border-radius: 3px;\n box-shadow: inset 0 0 0 1px oklch(0.2 0.02 255 / 0.15);\n}\n.bm-swatch-lg {\n display: block;\n width: auto;\n height: 22px;\n border-radius: 6px;\n}\n.bm-swatch-base {\n background: #fff;\n}\n.bm-swatch-subtle {\n background: oklch(0.96 0.005 250);\n}\n.bm-swatch-inverse {\n background: var(--ink);\n}\n.bm-swatch-brand {\n background: var(--accent);\n}\n.bm-segmented {\n display: flex;\n padding: 3px;\n border-radius: 9px;\n background: var(--bm-fill);\n}\n.bm-sidebar .bm-segmented button,\n.bm-dialog .bm-segmented button {\n flex: 1;\n min-height: 36px;\n height: 36px;\n padding: 0 8px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: oklch(0.45 0.01 255);\n font-size: 13px;\n font-weight: 400;\n}\n.bm-sidebar .bm-segmented button:hover:not(:disabled),\n.bm-dialog .bm-segmented button:hover:not(:disabled) {\n background: oklch(1 0 0 / 0.5);\n}\n.bm-sidebar .bm-segmented button[aria-checked=\"true\"],\n.bm-dialog .bm-segmented button[aria-checked=\"true\"] {\n background: #fff;\n color: var(--ink);\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-icon-picker {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));\n gap: 4px;\n padding: 3px;\n border-radius: 9px;\n background: var(--bm-fill);\n}\n.bm-sidebar .bm-icon-picker button {\n display: grid;\n place-items: center;\n min-height: 40px;\n height: 40px;\n padding: 0;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: oklch(0.45 0.01 255);\n}\n.bm-sidebar .bm-icon-picker button:hover {\n background: oklch(1 0 0 / 0.5);\n color: var(--ink);\n}\n.bm-sidebar .bm-icon-picker button[aria-checked=\"true\"] {\n background: #fff;\n color: var(--accent);\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-icon-picker svg {\n width: 20px;\n height: 20px;\n}\n.bm-actions-split {\n display: flex;\n gap: 8px;\n padding-top: 4px;\n}\n.bm-actions-split button {\n flex: 1;\n min-height: 40px !important;\n font-size: 14px !important;\n}\n.bm-sidebar .bm-actions-split .bm-danger {\n background: var(--bm-danger-soft);\n}\n\n/* Arrays, links, images */\n.bm-array {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-array-item {\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n overflow: hidden;\n}\n.bm-array-item summary {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 44px;\n padding: 0 8px 0 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--ink);\n cursor: pointer;\n list-style: none;\n}\n.bm-array-item summary::-webkit-details-marker {\n display: none;\n}\n.bm-array-item summary:hover {\n background: var(--fill-soft);\n}\n.bm-array-summary {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-grip,\n.bm-chevron {\n display: inline-grid;\n place-items: center;\n color: oklch(0.65 0.01 255);\n}\n.bm-chevron {\n transition: transform 0.12s;\n}\ndetails[open] > summary .bm-chevron {\n transform: rotate(90deg);\n}\n.bm-array-body {\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 12px;\n background: var(--bm-fill-nested);\n border-top: 1px solid var(--line-soft);\n}\n.bm-row-end {\n justify-content: flex-end;\n}\n.bm-sidebar .bm-add-row {\n width: 100%;\n}\n.bm-link-btn {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n min-height: 40px;\n padding: 0 12px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n text-align: left;\n color: var(--ink-2);\n}\n.bm-sidebar .bm-link-btn {\n background: #fff;\n border: 1px solid var(--bm-border);\n font-size: 14px;\n padding: 0 12px;\n}\n.bm-sidebar .bm-link-btn:hover:not(:disabled) {\n background: #fff;\n border-color: oklch(0.8 0.005 250);\n}\n.bm-link-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--ink);\n font-weight: 500;\n}\n.bm-link-href {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n max-width: 45%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-stripes {\n background: repeating-linear-gradient(135deg, oklch(0.93 0.004 250) 0 6px, oklch(0.965 0.003 250) 6px 12px);\n}\n\n/* Image field: label above, compact 56px row, alt text under it */\n.bm-imagefield {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-image-row {\n display: flex;\n gap: 10px;\n align-items: center;\n}\n.bm-image-row .bm-thumb {\n flex: none;\n width: 56px;\n height: 56px;\n border-radius: 6px;\n}\n.bm-image-meta {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n justify-content: center;\n}\n.bm-image-path {\n font-family: var(--mono);\n font-size: 12px;\n color: var(--bm-label);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-sidebar .bm-alt {\n min-height: 40px;\n font-size: 14px;\n}\n.bm-image-actions {\n flex-wrap: nowrap;\n gap: 6px;\n}\n.bm-image-actions > button:not(.bm-icon-btn) {\n flex: 1;\n min-height: 36px;\n font-size: 13px;\n}\n.bm-layout {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding-top: 2px;\n}\n.bm-layout-row {\n display: grid;\n grid-template-columns: 56px 1fr;\n align-items: center;\n column-gap: 10px;\n row-gap: 4px;\n}\n.bm-layout-row .bm-label {\n margin: 0;\n}\n.bm-layout-row .bm-layout-hint {\n grid-column: 2;\n}\n.bm-position {\n display: grid;\n grid-template-columns: repeat(3, 20px);\n grid-template-rows: repeat(3, 20px);\n gap: 3px;\n padding: 4px;\n width: max-content;\n border-radius: 8px;\n background: var(--fill);\n}\n.bm-sidebar .bm-position-cell {\n width: 20px;\n height: 20px;\n min-height: 0;\n padding: 0;\n border: 0;\n border-radius: 5px;\n background: #fff;\n box-shadow: inset 0 0 0 1px var(--line);\n}\n.bm-sidebar .bm-position-cell:hover:not(:disabled) {\n background: var(--accent-tint);\n}\n.bm-sidebar .bm-position-cell[aria-checked=\"true\"],\n.bm-sidebar .bm-position-cell[aria-checked=\"true\"]:hover:not(:disabled) {\n background: var(--accent);\n box-shadow: none;\n}\n.bm-sidebar .bm-position-cell:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.bm-slot,\n.bm-dropzone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 4px;\n width: 100%;\n min-height: 96px;\n padding: 14px;\n border: 1.5px dashed oklch(0.82 0.006 250);\n border-radius: 10px;\n background: var(--fill-soft);\n color: var(--ink-2);\n text-align: center;\n cursor: pointer;\n}\n.bm-sidebar .bm-slot:hover:not(:disabled),\n.bm-dropzone:hover {\n border-color: var(--accent);\n background: var(--accent-tint);\n}\n.bm-dropzone {\n min-height: 180px;\n position: relative;\n}\n.bm-dropzone:focus-within {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n.bm-dropzone-over {\n border-color: var(--accent);\n background: var(--accent-tint);\n}\n.bm-slot-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--ink);\n}\n.bm-slot-hint {\n font-size: 11px;\n color: var(--muted);\n}\n.bm-scrim {\n position: fixed;\n inset: 0;\n z-index: 7;\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding: 10vh 16px 16px;\n background: oklch(0.2 0.01 255 / 0.4);\n}\n.bm-modal {\n display: flex;\n flex-direction: column;\n width: min(480px, 100%);\n max-height: min(560px, 80vh);\n overflow: hidden;\n padding: 20px 0 0;\n border-radius: 14px;\n background: #fff;\n box-shadow: var(--bm-shadow-dialog);\n}\n.bm-modal-head {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 0 20px 12px;\n}\n.bm-modal-head .bm-dialog-title {\n flex: none;\n}\n.bm-modal-head .bm-meta-tag {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-modal-head .bm-icon-btn {\n margin: -6px -8px -6px 0;\n}\n.bm-modal .bm-tabs {\n margin: 0 20px;\n padding: 3px;\n gap: 0;\n border: 0;\n border-radius: 9px;\n background: var(--bm-fill);\n overflow: visible;\n}\n.bm-modal .bm-tabs button {\n flex: 1;\n height: 36px;\n min-height: 36px;\n padding: 0 8px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 400;\n}\n.bm-modal .bm-tabs button:hover {\n background: oklch(1 0 0 / 0.5);\n}\n.bm-modal .bm-tabs button[aria-selected=\"true\"] {\n background: #fff;\n color: var(--ink);\n font-weight: 500;\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-modal-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 16px 20px 20px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.bm-library {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 10px;\n}\n.bm-library-item {\n position: relative;\n}\n.bm-library-pick {\n display: flex;\n flex-direction: column;\n gap: 4px;\n width: 100%;\n min-height: 0;\n padding: 4px;\n border: 0;\n border-radius: 9px;\n background: var(--fill-soft);\n text-align: left;\n font-family: var(--mono);\n font-size: 9px;\n font-weight: 400;\n color: var(--muted);\n word-break: break-all;\n cursor: pointer;\n}\n.bm-library-pick:hover {\n background: var(--fill-hover);\n}\n.bm-library-pick img {\n width: 100%;\n aspect-ratio: 1 / 1;\n object-fit: cover;\n border-radius: 6px;\n background: var(--fill);\n}\n.bm-library-pick[aria-pressed=\"true\"] {\n box-shadow: 0 0 0 2px var(--accent);\n background: var(--accent-tint);\n}\n.bm-library-delete {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 24px;\n height: 24px;\n min-height: 0;\n background: #fff;\n box-shadow: 0 1px 3px oklch(0.2 0.01 255 / 0.25);\n opacity: 0;\n}\n.bm-library-item:hover .bm-library-delete,\n.bm-library-delete:focus-visible {\n opacity: 1;\n}\n.bm-library-empty {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n}\n.bm-modal-confirm {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px 20px 16px;\n border-top: 1px solid var(--line-soft);\n background: var(--danger-tint);\n}\n.bm-modal-confirm .bm-note {\n color: var(--danger-ink);\n font-size: 13px;\n line-height: 1.5;\n}\n.bm-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n border: 0;\n white-space: nowrap;\n}\n.bm-popover-title {\n grid-column: 1 / -1;\n padding: 0;\n font-size: 16px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--bm-ink);\n}\n.bm-popover-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0;\n}\n.bm-popover-head-wide {\n grid-column: 1 / -1;\n}\n.bm-popover[aria-label=\"Edit link\"],\n.bm-popover[aria-label=\"Add section\"][role=\"listbox\"] {\n z-index: 5;\n}\n.bm-popover :is(.bm-fmt-bold) {\n font-weight: 700;\n}\n.bm-fmt-bold {\n font-weight: 700;\n font-size: 13px;\n}\n.bm-fmt-italic {\n font-family: var(--serif);\n font-style: italic;\n font-size: 15px;\n}\n\n/* Edit link: Advanced row */\n.bm-advanced {\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n.bm-popover button.bm-advanced-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-height: 32px;\n padding: 0 2px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--bm-label);\n font-size: 13px;\n font-weight: 500;\n text-align: left;\n}\n.bm-popover button.bm-advanced-toggle:hover {\n background: transparent;\n color: var(--bm-ink);\n}\n.bm-advanced-toggle .bm-chevron {\n transition: transform 0.12s;\n}\n.bm-advanced-toggle[aria-expanded=\"true\"] .bm-chevron {\n transform: rotate(90deg);\n}\n.bm-advanced-summary {\n margin-left: auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--bm-muted);\n}\n\n/* SEO card and dialog */\n.bm-seo-card {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.bm-seo-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.bm-seo-badge {\n padding: 2px 8px;\n border-radius: 999px;\n background: var(--fill-soft);\n color: var(--bm-label);\n font-family: var(--mono);\n font-size: 11px;\n}\n.bm-seo-edit,\n.bm-consent-edit {\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n.bm-dialog.bm-seo {\n position: relative;\n width: min(560px, 100%);\n max-height: calc(100vh - 10vh - 32px);\n min-height: 0;\n}\n.bm-seo-body {\n display: flex;\n flex-direction: column;\n gap: 20px;\n min-height: 0;\n overflow-y: auto;\n padding: 2px 4px 2px 2px;\n}\n.bm-seo-json {\n min-height: 220px;\n white-space: pre;\n overflow: auto;\n tab-size: 2;\n}\n.bm-seo-json[aria-invalid=\"true\"] {\n border-color: var(--bm-danger);\n}\n.bm-seo-format {\n align-self: flex-start;\n}\n\n/* Cookie banner dialog */\n.bm-dialog.bm-consent {\n position: relative;\n width: min(520px, 100%);\n max-height: calc(100vh - 10vh - 32px);\n min-height: 0;\n}\n.bm-consent-body {\n display: flex;\n flex-direction: column;\n gap: 20px;\n min-height: 0;\n overflow-y: auto;\n padding: 2px 4px 2px 2px;\n}\n.bm-consent-preview {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--fill-soft);\n}\n.bm-consent-preview-title {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--bm-label);\n}\n.bm-consent-preview-text {\n margin: 0;\n font-size: 13px;\n line-height: 1.45;\n color: var(--bm-muted);\n overflow-wrap: anywhere;\n}\n.bm-consent-preview-link {\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n.bm-consent-preview-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n.bm-consent-preview-buttons > span {\n padding: 5px 14px;\n border-radius: 999px;\n box-shadow: inset 0 0 0 1px var(--bm-border);\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n}\n\n/* SEO preview, OG row, outline */\n.bm-serp {\n display: flex;\n flex-direction: column;\n gap: 3px;\n padding: 12px 14px;\n border-radius: 10px;\n background: var(--fill-soft);\n}\n.bm-serp-image {\n flex-direction: row;\n align-items: flex-start;\n gap: 12px;\n}\n.bm-serp-text {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n}\n.bm-serp-thumb {\n flex: none;\n width: 64px;\n height: 64px;\n border-radius: 8px;\n object-fit: cover;\n background: var(--fill);\n}\n.bm-serp-title {\n font-size: 15px;\n font-weight: 500;\n color: oklch(0.42 0.12 260);\n}\n.bm-serp-url {\n font-family: var(--mono);\n font-size: 11px;\n color: oklch(0.45 0.08 145);\n}\n.bm-serp-desc {\n font-size: 12px;\n line-height: 1.45;\n color: oklch(0.45 0.01 255);\n}\n.bm-outline-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.bm-sidebar .bm-outline-row {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n min-height: 40px;\n padding: 0 10px;\n border-radius: 8px;\n background: transparent;\n text-align: left;\n font-size: 14px;\n}\n.bm-sidebar .bm-outline-row:hover:not(:disabled) {\n background: var(--fill-soft);\n}\n\n/* Section rows (Pages tab): grip, tone swatch, name over #anchor and variant, then actions. */\n.bm-srow {\n position: relative;\n display: flex;\n align-items: center;\n gap: 4px;\n min-height: 52px;\n padding: 6px 6px 6px 8px;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n}\n.bm-srow:hover {\n border-color: oklch(0.8 0.008 250);\n}\n.bm-srow-grip {\n flex: none;\n width: 16px;\n height: 32px;\n display: inline-grid;\n place-items: center;\n cursor: grab;\n touch-action: none;\n}\n.bm-srow-grip:active {\n cursor: grabbing;\n}\n.bm-srow .bm-outline-row {\n flex: 1;\n min-width: 0;\n width: auto;\n padding: 0 8px 0 4px;\n gap: 10px;\n}\n.bm-srow .bm-swatch {\n width: 10px;\n height: 10px;\n border-radius: 2px;\n}\n.bm-srow-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.bm-srow-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--bm-ink);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-srow-meta {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--bm-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-srow .bm-outline-meta {\n flex: none;\n max-width: 40%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-srow-btn {\n width: 32px;\n height: 32px;\n background: transparent;\n color: var(--bm-icon);\n border-radius: 7px;\n}\n.bm-srow-btn:disabled {\n opacity: 0.35;\n}\n.bm-sidebar .bm-srow-btn:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n.bm-sidebar .bm-srow-btn.bm-danger {\n color: var(--bm-danger-icon);\n}\n.bm-sidebar .bm-srow-btn.bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n}\n.bm-srow-sep {\n flex: none;\n width: 1px;\n height: 20px;\n margin: 0 2px;\n background: var(--bm-divider);\n}\n.bm-outline-n {\n width: 18px;\n font-family: var(--mono);\n font-size: 11px;\n color: oklch(0.55 0.01 255);\n}\n.bm-outline-label {\n flex: 1;\n min-width: 0;\n font-weight: 500;\n}\n.bm-outline-meta {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--muted);\n}\n\n/* Navigation and footer link cards */\n.bm-nav-card {\n padding: 12px 12px 14px;\n gap: 10px;\n}\n.bm-nested {\n margin: 6px 0 0 16px;\n}\n.bm-nav-children {\n margin-top: -4px;\n}\n.bm-nav-head {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.bm-nav-head .bm-icon-btn,\n.bm-column-head .bm-icon-btn {\n background: var(--bm-fill);\n color: oklch(0.45 0.01 255);\n}\n.bm-nav-head .bm-icon-btn:hover:not(:disabled),\n.bm-column-head .bm-icon-btn:hover:not(:disabled) {\n background: var(--bm-fill-hover);\n color: var(--bm-ink);\n}\n.bm-sidebar .bm-nav-head .bm-icon-btn.bm-danger,\n.bm-sidebar .bm-column-head .bm-icon-btn.bm-danger {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-sidebar .bm-nav-label {\n flex: 1;\n min-width: 0;\n min-height: 32px;\n padding: 0 8px;\n border-color: transparent;\n font-weight: 500;\n}\n.bm-sidebar .bm-nav-label:hover {\n border-color: var(--line);\n}\n.bm-column {\n padding: 0;\n gap: 0;\n}\n.bm-column-head {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px;\n cursor: grab;\n}\n.bm-column-links > summary {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 40px;\n padding: 0 12px;\n border-top: 1px solid var(--line-soft);\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n cursor: pointer;\n list-style: none;\n}\n.bm-column-links > summary::-webkit-details-marker {\n display: none;\n}\n.bm-column-links > :not(summary) {\n margin: 10px 12px 0;\n}\n.bm-column-links > :last-child {\n margin-bottom: 12px;\n}\n\n/* Wordmark preview */\n.bm-card-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.bm-card-head .bm-label {\n flex: none;\n}\n.bm-combo {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n:is(.bm-sidebar, .bm-popover) .bm-combo-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n width: auto;\n max-width: 140px;\n min-height: 38px;\n padding: 0 10px 0 12px;\n border: 0;\n border-left: 1px solid var(--bm-border);\n border-radius: 0;\n background: var(--fill-soft);\n color: var(--ink-2);\n font-family: var(--mono);\n font-size: 12px;\n font-weight: 400;\n text-align: left;\n}\n:is(.bm-sidebar, .bm-popover) .bm-combo-trigger:hover:not(:disabled) {\n background: var(--fill-hover);\n}\n:is(.bm-sidebar, .bm-popover) .bm-combo-trigger[aria-expanded=\"true\"] {\n background: var(--accent-tint);\n color: var(--accent-hover);\n}\n/* One URL field: the text input and the page picker share a single border. */\n.bm-linkfield {\n display: flex;\n align-items: stretch;\n min-height: 40px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n}\n.bm-linkfield:focus-within {\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px var(--bm-primary-ring);\n}\n.bm-linkfield > input {\n flex: 1;\n min-width: 0;\n border: 0 !important;\n box-shadow: none !important;\n border-radius: 0;\n min-height: 38px;\n background: transparent;\n}\n.bm-linkfield .bm-combo {\n flex: none;\n max-width: 45%;\n}\n.bm-linkfield .bm-combo-trigger {\n height: 100%;\n}\n.bm-linkfield .bm-combo-trigger:focus-visible {\n outline-offset: -2px;\n}\n.bm-combo-trigger > span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-combo-trigger .bm-combo-custom {\n color: var(--muted);\n}\n.bm-combo-panel {\n position: fixed;\n z-index: 6;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 6px;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n box-shadow: 0 6px 18px oklch(0.2 0.02 255 / 0.1);\n}\n.bm-combo-list {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n}\n.bm-combo-group {\n margin: 6px 6px 2px;\n font-family: var(--mono);\n font-size: 10px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--muted);\n}\n.bm-combo-option {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 10px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--ink);\n cursor: pointer;\n}\n.bm-combo-option[aria-selected=\"true\"] {\n font-weight: 600;\n color: var(--accent-hover);\n}\n.bm-combo-active {\n background: var(--fill);\n}\n.bm-combo-value {\n flex: none;\n max-width: 50%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n}\n.bm-combo-empty {\n margin: 0;\n padding: 8px;\n font-size: 12px;\n color: var(--muted);\n}\n.bm-format {\n margin-top: -4px;\n}\n.bm-sidebar .bm-format button[aria-pressed=\"true\"] {\n background: #fff;\n color: var(--ink);\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-wordmark {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 14px;\n border-radius: 10px;\n background: var(--bm-fill-soft);\n}\n.bm-wordmark-name {\n font-size: 24px;\n font-weight: 600;\n letter-spacing: -0.03em;\n}\n.bm-alert-notice {\n flex-direction: row;\n align-items: flex-start;\n gap: 8px;\n color: var(--warn-ink);\n}\n.bm-alert-notice .bm-icon {\n margin-top: 2px;\n flex: none;\n}\n\n/*\n * Button system. Three variants, one danger modifier, one rule set.\n * secondary (default): neutral fill, ink text.\n * .bm-primary: the one main action of a surface. Solid accent, white text (AA).\n * .bm-tertiary: low emphasis text button (Cancel, Reset). No fill, no underline, grey fill on hover.\n * .bm-danger: modifier. primary = solid red, secondary = red text, tertiary = red text.\n * The scope list gives every rule enough specificity to beat the per-surface defaults above,\n * so the hover state of one variant can never fall back to the secondary fill.\n */\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button:where(.bm-primary, .bm-tertiary, .bm-danger):not(.bm-icon-btn, .bm-save) {\n transition:\n background-color 0.12s,\n color 0.12s;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary {\n background: var(--bm-primary);\n color: #fff;\n box-shadow: none;\n font-weight: 600;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary:hover:not(:disabled) {\n background: var(--bm-primary-hover);\n color: #fff;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary.bm-danger {\n background: var(--bm-danger);\n color: #fff;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary.bm-danger:hover:not(:disabled) {\n background: var(--danger-hover);\n color: #fff;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-danger:not(.bm-primary, .bm-tertiary, .bm-icon-btn) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-danger:not(.bm-primary, .bm-tertiary, .bm-icon-btn):hover:not(:disabled) {\n background: oklch(0.93 0.04 25);\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary {\n min-height: 32px;\n padding: 0 10px;\n border-radius: 8px;\n background: transparent;\n color: var(--bm-label);\n font-weight: 400;\n box-shadow: none;\n text-decoration: none;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal) button.bm-tertiary {\n min-height: 38px;\n font-size: 14px;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary.bm-danger {\n background: transparent;\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary.bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.bm-save:hover:not(:disabled) {\n background: var(--accent-hover);\n color: #fff;\n}\n.bm-sidebar .bm-save:hover:not(:disabled) {\n background: var(--accent-hover);\n color: #fff;\n}\n.bm-popover .bm-actions-remove,\n.bm-dialog .bm-actions-remove {\n margin-right: auto;\n}\n.bm-modal :where(button:not([role=\"tab\"], .bm-library-pick, .bm-icon-btn, .bm-tertiary)) {\n min-height: 38px;\n padding: 0 16px;\n border: 0;\n border-radius: 8px;\n background: var(--fill);\n color: var(--ink);\n font-size: 14px;\n font-weight: 400;\n}\n.bm-modal :where(button:not([role=\"tab\"], .bm-library-pick, .bm-icon-btn, .bm-tertiary)):hover:not(:disabled) {\n background: var(--fill-hover);\n}\n.bm-modal .bm-dropzone {\n font-family: var(--sans);\n}\n\n/* Design tab */\n.bm-colorrow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.bm-colorpick {\n flex: none;\n width: 40px !important;\n height: 40px;\n min-height: 40px !important;\n padding: 2px !important;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n cursor: pointer;\n}\n.bm-colorhex {\n flex: 1;\n min-width: 0;\n font-family: var(--mono);\n font-size: 13px;\n text-transform: lowercase;\n}\n.bm-colorhex[aria-invalid=\"true\"] {\n border-color: var(--bm-danger);\n}\n.bm-overrides {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n overflow: hidden;\n}\n.bm-override-row {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 10px 8px 12px;\n}\n.bm-override-row + .bm-override-row {\n border-top: 1px solid var(--bm-divider);\n}\n.bm-override-label {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n}\n.bm-override-label .bm-meta-tag {\n font-size: 10px;\n}\n.bm-override-row .bm-colorpick {\n width: 32px !important;\n height: 32px;\n min-height: 32px !important;\n padding: 1px !important;\n border-radius: 7px;\n}\n.bm-override-row .bm-colorhex {\n flex: none;\n width: 104px;\n min-height: 36px;\n padding: 0 10px;\n}\n.bm-tone-matrix {\n display: grid;\n grid-template-columns: 60px minmax(0, 1fr) minmax(0, 1fr);\n gap: 8px;\n align-items: stretch;\n}\n.bm-tone-pick {\n border: 0;\n text-align: left;\n font: inherit;\n cursor: pointer;\n}\n.bm-tone-cell[aria-pressed=\"true\"] {\n outline: 2px solid var(--bm-primary);\n outline-offset: 0;\n}\n.bm-tone-head {\n font-family: var(--mono);\n font-size: 10px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--muted);\n}\n.bm-tone-name {\n align-self: center;\n font-size: 12px;\n font-weight: 500;\n color: var(--ink-2);\n}\n.bm-tone-cell {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n min-width: 0;\n min-height: 46px;\n padding: 0 10px;\n border-radius: 8px;\n overflow: hidden;\n white-space: nowrap;\n}\n.bm-tone-aa {\n flex: none;\n font-size: 16px;\n font-weight: 600;\n}\n.bm-tone-muted {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 11px;\n}\n.bm-tone-chip {\n flex: none;\n padding: 2px 6px;\n border-radius: 5px;\n font-size: 10px;\n font-weight: 600;\n}\n.bm-tone-link {\n flex: none;\n font-size: 11px;\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.bm-contrast-list {\n margin: 6px 0 0;\n padding-left: 16px;\n font-family: var(--mono);\n font-size: 11px;\n color: var(--warn-ink);\n}\n.bm-range {\n flex: 1;\n min-width: 0;\n min-height: 28px;\n accent-color: var(--accent);\n cursor: pointer;\n}\n/* Preview: the only editor UI left on screen. */\n.bm-exit-preview {\n position: fixed;\n z-index: 7;\n right: 16px;\n bottom: 16px;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 40px;\n padding: 0 16px;\n border: 0;\n border-radius: 999px;\n background: var(--ink);\n color: #fff;\n font-size: 13px;\n font-weight: 500;\n box-shadow: 0 10px 30px oklch(0.2 0.02 255 / 0.3);\n}\n.bm-exit-preview:hover {\n background: oklch(0.28 0.012 255);\n}\n.bm-exit-preview:focus-visible {\n outline-color: oklch(0.82 0.14 145);\n outline-offset: 3px;\n}\n.bm-srow-add {\n display: flex;\n justify-content: flex-end;\n padding-top: 6px;\n}\n.bm-sidebar .bm-add-section {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-height: 32px;\n padding: 0 12px;\n border: 0;\n border-radius: 8px;\n background: var(--bm-primary);\n color: #fff;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-sidebar .bm-add-section:hover {\n background: var(--bm-primary-hover);\n}\n";
20591
+ var editor_default = "/*\n * Editor styles. They live in a shadow root, so they never meet the site's Tailwind layer.\n * The editor is always light. Tokens and values follow the v4 editor design handoff.\n * The short names (--ink, --line, --accent ...) alias the --bm-* tokens so older rules read the same.\n */\n:host {\n all: initial;\n\n /* ---------- v4 tokens (editor-tokens.css) ---------- */\n --bm-font-ui: \"Bricolage Grotesque Variable\", \"Bricolage Grotesque\", ui-sans-serif, system-ui, sans-serif;\n --bm-font-mono: \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace;\n --bm-font-serif: \"Instrument Serif\", Georgia, serif;\n\n --bm-ink: oklch(0.21 0.012 255);\n --bm-label: oklch(0.3 0.01 255);\n --bm-section: oklch(0.42 0.01 255);\n --bm-help: oklch(0.47 0.01 255);\n --bm-muted: oklch(0.5 0.01 255);\n --bm-icon: oklch(0.55 0.01 255);\n --bm-info: oklch(0.6 0.01 255);\n\n --bm-fill: oklch(0.955 0.003 250);\n --bm-fill-hover: oklch(0.93 0.004 250);\n --bm-fill-soft: oklch(0.965 0.003 250);\n --bm-fill-nested: oklch(0.97 0.003 250);\n --bm-border: oklch(0.88 0.005 250);\n --bm-divider: oklch(0.93 0.004 250);\n --bm-tab-rule: oklch(0.92 0.004 250);\n\n --bm-primary: oklch(0.46 0.13 145);\n --bm-primary-hover: oklch(0.4 0.12 145);\n --bm-primary-ring: oklch(0.46 0.13 145 / 0.15);\n --bm-link: oklch(0.4 0.12 145);\n\n --bm-saved-bg: oklch(0.94 0.045 145);\n --bm-saved-fg: oklch(0.36 0.1 145);\n --bm-unsaved-bg: oklch(0.95 0.05 80);\n --bm-unsaved-fg: oklch(0.48 0.1 60);\n --bm-unsaved-dot: oklch(0.75 0.15 70);\n --bm-badge-green-bg: oklch(0.93 0.06 145);\n --bm-badge-green-fg: oklch(0.38 0.1 145);\n --bm-badge-amber-bg: oklch(0.95 0.04 75);\n --bm-badge-amber-fg: oklch(0.45 0.09 60);\n\n --bm-danger: oklch(0.55 0.19 25);\n --bm-danger-text: oklch(0.52 0.17 25);\n --bm-danger-icon: oklch(0.58 0.18 25);\n --bm-danger-soft: oklch(0.96 0.025 20);\n\n --bm-diff-del-bg: oklch(0.97 0.02 20);\n --bm-diff-del-fg: oklch(0.45 0.13 25);\n --bm-diff-add-bg: oklch(0.96 0.04 145);\n --bm-diff-add-fg: oklch(0.34 0.1 145);\n\n --bm-switch-off: oklch(0.82 0.005 250);\n\n --bm-shadow-pop: 0 0 0 1px oklch(0.9 0.005 250), 0 16px 36px -16px oklch(0.2 0.02 255 / 0.35);\n --bm-shadow-dialog: 0 0 0 1px oklch(0.9 0.005 250), 0 24px 48px -24px oklch(0.2 0.02 255 / 0.35);\n --bm-shadow-segment-on: 0 1px 2px oklch(0 0 0 / 0.08), 0 0 0 1px oklch(0.9 0.005 250);\n\n /* ---------- aliases used by the rules below ---------- */\n --ink: var(--bm-ink);\n --ink-2: var(--bm-label);\n --muted: var(--bm-muted);\n --line: var(--bm-border);\n --line-soft: var(--bm-divider);\n --fill: var(--bm-fill);\n --fill-hover: var(--bm-fill-hover);\n --fill-soft: var(--bm-fill-soft);\n --accent: var(--bm-primary);\n --accent-hover: var(--bm-primary-hover);\n --accent-tint: oklch(0.96 0.03 145);\n --accent-ring: var(--bm-primary-ring);\n --warn-tint: var(--bm-unsaved-bg);\n --warn-ink: var(--bm-unsaved-fg);\n --warn-dot: var(--bm-unsaved-dot);\n --danger-hover: oklch(0.48 0.18 25);\n --danger-tint: var(--bm-danger-soft);\n --danger-ink: var(--bm-danger-text);\n --info-dot: oklch(0.6 0.15 255);\n --sans: var(--bm-font-ui);\n --mono: var(--bm-font-mono);\n --serif: var(--bm-font-serif);\n --shadow-pop: var(--bm-shadow-pop);\n}\n* {\n box-sizing: border-box;\n}\nbutton,\ninput,\nselect,\ntextarea {\n font: inherit;\n color: inherit;\n}\nbutton {\n cursor: pointer;\n}\n:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n\n/* On-page outlines */\n.bm-outline {\n position: fixed;\n pointer-events: none;\n border-radius: 6px;\n z-index: 1;\n}\n.bm-outline-section {\n border: 2px solid var(--accent);\n}\n.bm-outline-field {\n border: 2px solid var(--accent);\n background: oklch(0.46 0.13 145 / 0.08);\n}\n.bm-image-bar {\n flex-wrap: nowrap;\n left: auto;\n white-space: nowrap;\n}\n.bm-image-bar-group {\n display: flex;\n gap: 2px;\n}\n.bm-image-bar button[aria-pressed=\"true\"] {\n background: var(--bm-saved-bg);\n color: var(--bm-saved-fg);\n}\n.bm-image-bar-grid {\n display: grid;\n grid-template-columns: repeat(3, 9px);\n grid-template-rows: repeat(3, 9px);\n gap: 2px;\n align-self: center;\n padding: 0 4px;\n}\n.bm-image-bar .bm-pos-cell {\n width: 9px;\n height: 9px;\n /* `.bm-rich button` sets a 32px minimum for the bar's text buttons; the cells stay 9px. */\n min-width: 0;\n min-height: 0;\n padding: 0;\n border-radius: 2px;\n background: var(--line);\n}\n.bm-image-bar .bm-pos-cell:hover:not(:disabled) {\n background: var(--muted);\n}\n.bm-image-bar .bm-pos-cell[aria-pressed=\"true\"] {\n background: var(--accent);\n}\n.bm-image-bar .bm-pos-cell:disabled {\n opacity: 0.3;\n cursor: default;\n}\n.bm-outline-image {\n background: oklch(0.46 0.13 145 / 0.12);\n}\n.bm-outline-image::after {\n content: \"Change image\";\n position: absolute;\n top: 8px;\n left: 8px;\n padding: 4px 9px;\n border-radius: 6px;\n background: var(--accent);\n color: #fff;\n font: 500 11px / 1.3 var(--sans, system-ui, sans-serif);\n}\n\n.bm-toolbar,\n.bm-dock,\n.bm-exit-preview,\n.bm-sidebar,\n.bm-popover,\n.bm-dialog,\n.bm-rich,\n.bm-banner,\n.bm-scrim {\n pointer-events: auto;\n font-family: var(--sans);\n font-size: 13px;\n color: var(--ink);\n -webkit-font-smoothing: antialiased;\n}\n\n/*\n * Insert between sections. Three states:\n * idle / hover a solid line and a 28px circle; hover changes nothing.\n * open the picker is open: the line stays and a \"between A and B\" chip replaces the circle.\n */\n.bm-gap {\n position: fixed;\n z-index: 2;\n height: 0;\n pointer-events: none;\n}\n.bm-gap::before {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n height: 0;\n border-top: 2px solid var(--bm-primary);\n transform: translateY(-50%);\n}\n.bm-gap-add {\n position: absolute;\n left: 50%;\n top: 0;\n transform: translate(-50%, -50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 999px;\n pointer-events: auto;\n cursor: pointer;\n white-space: nowrap;\n background: var(--bm-primary);\n color: #fff;\n box-shadow: 0 0 0 2px #fff;\n}\n.bm-gap-add .bm-icon {\n width: 14px;\n height: 14px;\n stroke-width: 2.4;\n}\n.bm-gap-add:focus-visible {\n outline: 2px solid var(--ink);\n outline-offset: 3px;\n}\n.bm-gap-chip {\n position: absolute;\n left: 50%;\n top: 0;\n transform: translate(-50%, -50%);\n padding: 4px 10px;\n border-radius: 999px;\n background: #fff;\n color: var(--bm-ink);\n box-shadow: 0 0 0 1.5px var(--bm-primary);\n white-space: nowrap;\n pointer-events: none;\n font-size: 12px;\n font-weight: 500;\n}\n\n/* Light floating bars: section toolbar, rich text bar, heading format bar */\n.bm-toolbar,\n.bm-rich {\n position: fixed;\n z-index: 3;\n display: flex;\n gap: 2px;\n padding: 4px;\n border-radius: 12px;\n background: #fff;\n color: var(--ink);\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-toolbar button,\n.bm-rich button {\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: inherit;\n min-height: 32px;\n padding: 0 10px;\n font-size: 12px;\n font-weight: 500;\n}\n.bm-toolbar button:hover:not(:disabled),\n.bm-rich button:hover {\n background: var(--fill);\n}\n.bm-rich button[aria-pressed=\"true\"] {\n background: var(--bm-saved-bg);\n box-shadow: inset 0 0 0 1px oklch(0.46 0.13 145 / 0.4);\n}\n.bm-toolbar :focus-visible,\n.bm-rich :focus-visible {\n outline-color: var(--accent);\n}\n.bm-toolbar {\n align-items: center;\n max-width: calc(100vw - 16px);\n padding: 5px;\n}\n.bm-toolbar button {\n width: 34px;\n min-height: 34px;\n height: 34px;\n padding: 0;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: oklch(0.4 0.01 255);\n}\n.bm-toolbar button:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n.bm-toolbar button:disabled {\n opacity: 0.35;\n cursor: default;\n}\n.bm-toolbar .bm-danger {\n color: var(--bm-danger-icon);\n}\n.bm-toolbar .bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-toolbar-active {\n box-shadow:\n 0 0 0 2px var(--bm-primary),\n 0 10px 24px -12px oklch(0.2 0.02 255 / 0.35);\n}\n.bm-toolbar-name {\n display: block;\n max-width: 16rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 0 12px 0 10px;\n}\n.bm-toolbar-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--bm-ink);\n}\n.bm-toolbar-anchor {\n font-family: var(--mono);\n font-size: 12px;\n font-weight: 400;\n color: var(--bm-muted);\n}\n.bm-sep {\n width: 1px;\n align-self: stretch;\n margin: 4px 2px;\n background: var(--line);\n}\n.bm-toolbar .bm-sep {\n align-self: center;\n height: 20px;\n margin: 0 4px;\n background: oklch(0.9 0.005 250);\n}\n.bm-icon {\n width: 16px;\n height: 16px;\n display: block;\n}\n.bm-rich {\n align-items: center;\n flex-wrap: wrap;\n max-width: calc(100vw - 16px);\n}\n.bm-rich button {\n min-height: 32px;\n min-width: 32px;\n}\n.bm-rich input {\n width: 168px;\n min-height: 30px;\n padding: 0 8px;\n border: 0;\n border-radius: 7px;\n background: var(--fill);\n color: var(--ink);\n font-size: 12px;\n}\n.bm-rich input:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--accent);\n}\n\n/* Heading format bar: each button shows \"Aa\" in its own weight or font over a mono caption. */\n.bm-rich.bm-format-bar {\n flex-wrap: nowrap;\n}\n.bm-rich.bm-format-bar button.bm-fmt {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2px;\n min-width: 42px;\n height: 48px;\n min-height: 48px;\n padding: 0 8px;\n border-radius: 8px;\n}\n.bm-fmt-sample {\n font-size: 15px;\n line-height: 1;\n color: var(--bm-ink);\n}\n.bm-fmt-caption {\n font-family: var(--mono);\n font-size: 9px;\n letter-spacing: 0.02em;\n color: var(--bm-muted);\n}\n.bm-rich.bm-format-bar button.bm-fmt[aria-pressed=\"true\"] {\n background: var(--bm-saved-bg);\n box-shadow: inset 0 0 0 1px oklch(0.46 0.13 145 / 0.4);\n}\n.bm-format-bar .bm-sep {\n align-self: stretch;\n margin: 6px 4px;\n}\n\n/* Light popovers: add menu, section picker, edit link */\n.bm-popover {\n position: fixed;\n z-index: 3;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 180px;\n max-height: min(420px, calc(100vh - 16px));\n overflow: auto;\n padding: 6px;\n border-radius: 12px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-popover > button {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 34px;\n padding: 0 10px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n text-align: left;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-popover > button:hover {\n background: var(--fill);\n}\n\n/* Add section picker: wireframe cards */\n.bm-popover[aria-label=\"Add section\"][role=\"listbox\"] {\n gap: 14px;\n width: 640px;\n max-width: calc(100vw - 16px);\n max-height: calc(100vh - 16px);\n padding: 16px;\n border-radius: 14px;\n overflow: visible;\n box-shadow: var(--bm-shadow-dialog);\n}\n.bm-picker-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.bm-picker-title {\n font-size: 17px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n.bm-picker-where {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n color: var(--bm-muted);\n}\n.bm-picker-grid {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 10px;\n max-height: 26rem;\n overflow-y: auto;\n padding: 2px 6px 2px 2px;\n margin-right: -6px;\n scrollbar-gutter: stable;\n}\n.bm-popover .bm-picker-grid > button {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: flex-start;\n gap: 6px;\n min-height: 0;\n padding: 8px 8px 10px;\n border: 1px solid oklch(0.9 0.005 250);\n border-radius: 10px;\n background: #fff;\n text-align: left;\n font-weight: 400;\n}\n.bm-popover .bm-picker-grid > button:hover {\n background: #fff;\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px oklch(0.46 0.13 145 / 0.12);\n}\n.bm-wire {\n position: relative;\n display: block;\n width: 100%;\n height: 76px;\n border-radius: 7px;\n background: oklch(0.97 0 0);\n overflow: hidden;\n}\n.bm-wire > span {\n position: absolute;\n display: block;\n}\n.bm-type-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 0 2px;\n}\n.bm-type-name {\n font-size: 14px;\n font-weight: 600;\n line-height: 1.25;\n color: var(--bm-ink);\n}\n.bm-type-variants {\n font-family: var(--mono);\n font-size: 10px;\n font-weight: 400;\n line-height: 1.35;\n white-space: nowrap;\n color: var(--muted);\n}\n.bm-type-desc {\n padding: 0 2px;\n font-size: 12px;\n line-height: 1.4;\n color: var(--bm-help);\n}\n.bm-picker-note {\n margin: 0;\n font-size: 12px;\n color: var(--bm-muted);\n}\n\n.bm-popover[aria-label=\"Edit link\"] {\n gap: 14px;\n padding: 16px;\n max-height: calc(100vh - 16px);\n}\n\n/* Dialogs and banners */\n.bm-dialog {\n position: fixed;\n z-index: 6;\n display: flex;\n flex-direction: column;\n gap: 16px;\n width: min(400px, calc(100vw - 32px));\n padding: 20px;\n border-radius: 14px;\n background: #fff;\n box-shadow: var(--bm-shadow-dialog);\n}\n.bm-dialog-head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n}\n.bm-dialog-heading {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.bm-dialog-sub {\n margin: 0;\n font-size: 13px;\n line-height: 1.4;\n color: var(--bm-help);\n}\n.bm-dialog .bm-dialog-x,\n.bm-popover .bm-dialog-x,\n.bm-modal .bm-dialog-x {\n flex: none;\n width: 32px;\n height: 32px;\n margin: -6px -8px -6px 0;\n background: transparent;\n color: var(--bm-icon);\n}\n.bm-dialog-title {\n margin: 0;\n font-size: 17px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--bm-ink);\n}\n.bm-popover .bm-dialog-title {\n font-size: 16px;\n}\n.bm-dialog .bm-note {\n color: var(--bm-label);\n font-size: 14px;\n line-height: 1.5;\n}\n.bm-dialog button,\n.bm-popover .bm-actions button,\n.bm-banner button {\n min-height: 38px;\n padding: 0 16px;\n border: 0;\n border-radius: 8px;\n background: var(--fill);\n font-size: 14px;\n font-weight: 400;\n}\n.bm-dialog button:hover:not(:disabled),\n.bm-popover .bm-actions button:hover:not(:disabled) {\n background: var(--fill-hover);\n}\n/* The primary action comes first in the DOM (focus lands on it); row-reverse shows it last, on the right. */\n.bm-actions {\n display: flex;\n flex-direction: row-reverse;\n justify-content: flex-start;\n align-items: center;\n gap: 8px;\n}\n.bm-dialog > .bm-actions,\n.bm-popover[aria-label=\"Edit link\"] > .bm-actions {\n padding-top: 12px;\n border-top: 1px solid var(--bm-divider);\n}\n.bm-dialog-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-top: 12px;\n border-top: 1px solid var(--bm-divider);\n}\n.bm-dialog-foot > .bm-hint {\n flex: 1;\n min-width: 0;\n margin: 0;\n}\n.bm-dialog-foot .bm-actions {\n flex: none;\n}\n\n/* Alert dialogs: [icon tile] [title / body / note] [x] */\n.bm-alert-main {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n.bm-alert-copy {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.bm-alert-body {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n color: var(--bm-label);\n overflow-wrap: anywhere;\n}\n.bm-alert-body strong {\n font-weight: 600;\n color: var(--bm-ink);\n}\n.bm-alert-note {\n margin: 0;\n font-size: 12px;\n line-height: 1.45;\n color: var(--bm-muted);\n}\n.bm-tile {\n flex: none;\n display: grid;\n place-items: center;\n width: 36px;\n height: 36px;\n border-radius: 9px;\n}\n.bm-tile .bm-icon {\n width: 18px;\n height: 18px;\n}\n.bm-tile-warn {\n background: var(--bm-unsaved-bg);\n color: var(--bm-unsaved-fg);\n}\n.bm-tile-danger {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-tile-neutral {\n background: var(--bm-fill);\n color: var(--bm-label);\n}\n\n.bm-banner {\n position: fixed;\n z-index: 6;\n display: flex;\n align-items: center;\n gap: 12px;\n width: min(440px, calc(100vw - 32px));\n padding: 12px 14px;\n border-radius: 12px;\n box-shadow: 0 14px 34px -10px oklch(0.2 0.02 255 / 0.4);\n}\n.bm-banner button {\n min-height: 34px;\n padding: 0 14px;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-banner-ink {\n background: var(--ink);\n color: #fff;\n}\n.bm-banner-light {\n background: #fff;\n box-shadow: var(--shadow-pop);\n}\n.bm-banner-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n.bm-banner-title {\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.35;\n}\n.bm-banner-sub {\n margin: 0;\n font-size: 12px;\n line-height: 1.4;\n opacity: 0.7;\n}\n.bm-banner .bm-actions {\n flex: none;\n gap: 6px;\n}\n.bm-banner-ink button {\n min-height: 30px;\n padding: 0 12px;\n font-size: 12px;\n background: oklch(1 0 0 / 0.12);\n color: #fff;\n}\n.bm-banner-ink button:hover {\n background: oklch(1 0 0 / 0.2);\n}\n.bm-banner-ink .bm-primary {\n background: #fff;\n color: var(--ink);\n}\n.bm-banner-ink .bm-primary:hover {\n background: oklch(0.94 0.003 250);\n}\n.bm-banner-ink :focus-visible {\n outline-color: oklch(0.82 0.14 145);\n}\n.bm-dot-stale {\n background: oklch(0.7 0.18 25) !important;\n}\n.bm-dot-info {\n background: var(--info-dot) !important;\n}\n\n/* Closed editor. The dock sits where the sidebar header's controls sit: header padding (top 14, right 14) minus the dock's 7px padding. */\n.bm-dock {\n position: fixed;\n z-index: 5;\n top: 7px;\n right: 7px;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 7px 7px 7px 10px;\n border-radius: 14px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-dot {\n flex: none;\n width: 8px;\n height: 8px;\n border-radius: 99px;\n background: oklch(0.72 0.17 145);\n}\n.bm-dot-dirty {\n background: var(--warn-dot);\n}\n\n/* Sidebar shell */\n.bm-sidebar {\n position: fixed;\n z-index: 4;\n top: 0;\n right: 0;\n bottom: 0;\n width: min(440px, 100vw);\n display: flex;\n flex-direction: column;\n background: #fff;\n box-shadow:\n 0 0 0 1px var(--line),\n -24px 0 48px -24px oklch(0.2 0.02 255 / 0.25);\n}\n.bm-resize {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n touch-action: none;\n z-index: 2;\n}\n.bm-resize:hover,\n.bm-resize:focus-visible {\n background: oklch(0.46 0.13 145 / 0.25);\n}\n.bm-resize:focus-visible {\n outline-offset: -2px;\n}\n\n.bm-head {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 14px 14px 16px;\n border-bottom: 1px solid var(--line-soft);\n}\n.bm-mark {\n flex: none;\n display: block;\n width: 28px;\n height: auto;\n aspect-ratio: 21 / 19;\n image-rendering: pixelated;\n user-select: none;\n}\n/* Bear, name and slogan. Takes the space the controls leave; the text fades out when it no longer fits. */\n.bm-brand {\n position: relative;\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.bm-head-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n transition: opacity 160ms ease;\n}\n.bm-brand-compact .bm-head-text {\n opacity: 0;\n}\n/* The same two lines, in a card left of the sidebar (over the page), level with the header, while the pointer is on\n the brand. 16px is the header's left padding: the card clears the sidebar edge by 10px. */\n.bm-brand-tip {\n position: absolute;\n z-index: 5;\n top: 50%;\n right: calc(100% + 16px + 10px);\n display: flex;\n flex-direction: column;\n padding: 8px 12px;\n border-radius: 10px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n white-space: nowrap;\n opacity: 0;\n transform: translate(4px, -50%);\n pointer-events: none;\n transition:\n opacity 120ms ease,\n transform 120ms ease;\n}\n.bm-brand-compact:hover .bm-brand-tip {\n opacity: 1;\n transform: translate(0, -50%);\n transition-delay: 120ms;\n}\n@media (prefers-reduced-motion: reduce) {\n .bm-head-text,\n .bm-brand-tip {\n transition: none;\n }\n}\n/* A ring with one open quarter that turns while a save is written and the page reloads. */\n.bm-spin {\n flex: none;\n width: 14px;\n height: 14px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: bm-spin 0.8s linear infinite;\n}\n@keyframes bm-spin {\n to {\n transform: rotate(360deg);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .bm-spin {\n animation: none;\n }\n}\n.bm-faces {\n display: grid;\n}\n.bm-face {\n grid-area: 1 / 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n white-space: nowrap;\n}\n.bm-face[hidden-face] {\n visibility: hidden;\n}\n.bm-save:disabled {\n opacity: 0.85;\n cursor: progress;\n}\n.bm-head-title {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.015em;\n /* The controls beside it never shrink, so a narrow sidebar cuts the name, not the buttons. */\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-head-sub {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-pill {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 24px;\n padding: 0 10px;\n border-radius: 999px;\n background: var(--bm-saved-bg);\n color: var(--bm-saved-fg);\n font-size: 12px;\n font-weight: 500;\n}\n.bm-pill .bm-dot {\n width: 6px;\n height: 6px;\n background: var(--accent);\n}\n.bm-pill-dirty {\n background: var(--warn-tint);\n color: var(--warn-ink);\n}\n.bm-pill-dirty .bm-dot {\n background: var(--warn-dot);\n}\nbutton.bm-pill-btn {\n min-height: 0;\n padding: 0 10px;\n border: 0;\n border-radius: 999px;\n background: var(--warn-tint);\n color: var(--warn-ink);\n font-family: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n}\n:is(.bm-sidebar, .bm-dock) button.bm-pill-btn:hover:not(:disabled) {\n background: oklch(0.93 0.06 75);\n color: var(--warn-ink);\n}\nbutton.bm-pill-btn:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n.bm-dialog-wide {\n width: min(400px, calc(100vw - 32px));\n}\n.bm-dialog .bm-actions {\n flex-wrap: nowrap;\n}\n.bm-dialog .bm-actions button {\n flex: none;\n white-space: nowrap;\n}\n.bm-changes {\n width: min(540px, calc(100vw - 32px));\n}\n.bm-commit-files {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n max-height: min(34vh, 280px);\n overflow-y: auto;\n}\n.bm-commit-files label {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n cursor: pointer;\n}\n.bm-commit-mark {\n font:\n 600 11px / 1 ui-monospace,\n monospace;\n width: 18px;\n text-align: center;\n opacity: 0.7;\n}\n.bm-commit-msg {\n width: 100%;\n box-sizing: border-box;\n resize: vertical;\n font: inherit;\n font-size: 14px;\n padding: 8px 12px;\n border: 1px solid var(--line);\n border-radius: 8px;\n background: transparent;\n color: inherit;\n}\n\n/* Unsaved changes review and version history: groups, rows, diff lines */\n.bm-changes-list {\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-height: 22rem;\n overflow-y: auto;\n margin: 0 -4px;\n padding: 0 4px;\n}\n.bm-changes-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-changes-area {\n margin: 0;\n display: flex;\n align-items: baseline;\n gap: 8px;\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bm-section);\n}\n.bm-changes-file {\n font-weight: 400;\n letter-spacing: 0;\n text-transform: none;\n color: oklch(0.55 0.01 255);\n}\n.bm-changes-count {\n margin-left: auto;\n font-weight: 400;\n letter-spacing: 0;\n color: var(--bm-muted);\n}\n.bm-changes ul {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n overflow: hidden;\n}\n.bm-change {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px;\n font-size: 14px;\n line-height: 1.4;\n}\n.bm-change + .bm-change {\n border-top: 1px solid var(--bm-divider);\n}\n.bm-change-mark {\n flex: none;\n display: grid;\n place-items: center;\n width: 22px;\n height: 22px;\n border-radius: 6px;\n font-family: var(--mono);\n font-size: 13px;\n font-weight: 600;\n background: var(--bm-unsaved-bg);\n color: var(--bm-unsaved-fg);\n}\n.bm-change-added .bm-change-mark {\n background: var(--bm-badge-green-bg);\n color: var(--bm-badge-green-fg);\n}\n.bm-change-removed .bm-change-mark {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-text);\n}\n.bm-change-body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.bm-change-field {\n font-weight: 500;\n color: var(--bm-ink);\n overflow-wrap: anywhere;\n}\n.bm-change-values {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n}\n.bm-change-values del,\n.bm-change-values ins {\n display: flex;\n gap: 6px;\n min-width: 0;\n padding: 3px 7px;\n border-radius: 5px;\n text-decoration: none;\n font-size: 13px;\n}\n.bm-change-values del {\n background: var(--bm-diff-del-bg);\n color: var(--bm-diff-del-fg);\n}\n.bm-change-values ins {\n background: var(--bm-diff-add-bg);\n color: var(--bm-diff-add-fg);\n}\n.bm-change-values del::before {\n content: \"\\2212\";\n flex: none;\n font-family: var(--mono);\n}\n.bm-change-values ins::before {\n content: \"+\";\n flex: none;\n font-family: var(--mono);\n}\n.bm-change-values del > span,\n.bm-change-values ins > span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-change-values del > span {\n text-decoration: line-through;\n text-decoration-color: oklch(0.45 0.13 25 / 0.5);\n}\n.bm-changes-empty {\n margin: 0;\n padding: 24px 0;\n text-align: center;\n font-size: 14px;\n color: var(--bm-muted);\n}\n\n.bm-changes ul.bm-versions {\n gap: 0;\n}\n.bm-version {\n padding: 0;\n}\n.bm-version + .bm-version {\n border-top: 1px solid var(--bm-divider);\n}\n.bm-version-when strong {\n font-weight: 600;\n}\n.bm-tipped {\n position: relative;\n}\n.bm-tipped::after {\n content: attr(data-tip);\n position: absolute;\n right: calc(100% + 6px);\n top: 50%;\n transform: translateY(-50%);\n padding: 4px 8px;\n border-radius: 6px;\n background: var(--ink);\n color: #fff;\n font-size: 12px;\n font-weight: 500;\n line-height: 1.3;\n white-space: nowrap;\n pointer-events: none;\n visibility: hidden;\n z-index: 5;\n}\n.bm-version-row > .bm-tipped:first-child::after {\n right: auto;\n left: calc(100% + 6px);\n}\n.bm-tipped:hover::after,\n.bm-tipped:focus-visible::after {\n visibility: visible;\n}\n.bm-version-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 8px 8px 10px;\n}\n.bm-version-when {\n flex: 1;\n min-width: 0;\n margin-right: auto;\n padding: 0 !important;\n min-height: 32px !important;\n font-weight: 500;\n display: flex !important;\n flex-direction: column;\n align-items: flex-start !important;\n justify-content: center;\n gap: 2px;\n text-align: left;\n}\n.bm-version-line {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n.bm-version-sum {\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n font-weight: 400;\n color: var(--bm-help);\n}\n.bm-version-row .bm-restore {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n min-height: 32px;\n padding: 0 10px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-version-rel {\n font-size: 14px;\n font-weight: 500;\n color: var(--bm-ink);\n}\n.bm-version-abs {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--bm-muted);\n}\n.bm-version-diff {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 4px 10px 12px 10px;\n border-top: 1px solid var(--bm-divider);\n margin-top: 0;\n}\n.bm-version-diff ul {\n margin: 0;\n}\n.bm-day {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.bm-restored {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 8px 8px 12px;\n border-radius: 9px;\n background: var(--bm-diff-add-bg);\n color: var(--bm-saved-fg);\n font-size: 13px;\n}\n.bm-restored > span {\n flex: 1;\n min-width: 0;\n}\n\n.bm-tabs {\n display: flex;\n gap: 0;\n padding: 0 12px;\n overflow-x: auto;\n border-bottom: 1px solid var(--bm-tab-rule);\n}\n.bm-tabs button {\n flex: 1 1 auto;\n height: 46px;\n padding: 0 6px;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: oklch(0.48 0.01 255);\n font-size: 13px;\n font-weight: 400;\n}\n.bm-tabs button:hover {\n color: var(--ink);\n background: var(--fill-soft);\n}\n.bm-tabs button[aria-selected=\"true\"] {\n color: var(--ink);\n background: transparent;\n font-weight: 600;\n box-shadow: inset 0 -2px 0 var(--accent);\n}\n.bm-tabs button:focus-visible {\n outline-offset: -2px;\n}\n\n.bm-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 24px 24px 32px;\n display: flex;\n flex-direction: column;\n gap: 18px;\n}\n.bm-foot {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n border-top: 1px solid var(--line-soft);\n font-family: var(--mono);\n font-size: 10px;\n color: var(--muted);\n}\n.bm-foot span:first-child {\n flex: none;\n white-space: nowrap;\n}\n.bm-foot span:last-child {\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n/* Group header: mono 11/500, then a 1px rule. With a right-hand item the rule sits on the flex wrapper. */\n.bm-group {\n margin: 18px 0 0;\n padding-bottom: 10px;\n border-bottom: 1px solid var(--bm-divider);\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bm-section);\n}\n.bm-group:first-child {\n margin-top: 0;\n}\n.bm-stack-tight > .bm-group {\n margin-bottom: 10px;\n}\n.bm-meta {\n margin: 0;\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n}\n\n/* Fields */\n.bm-label {\n display: flex;\n flex-direction: column;\n gap: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n}\n.bm-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-hint {\n font-size: 12px;\n line-height: 1.45;\n font-weight: 400;\n color: var(--muted);\n}\n.bm-label-text {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n}\n.bm-info {\n position: relative;\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n margin-left: 4px;\n}\n.bm-info-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n margin: -3px 0;\n border-radius: 999px;\n color: var(--bm-info);\n cursor: help;\n text-transform: none;\n letter-spacing: 0;\n}\n.bm-info-btn:hover,\n.bm-info-btn[aria-expanded=\"true\"] {\n color: var(--ink);\n}\n.bm-info-btn:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 1px;\n}\n.bm-tip {\n position: fixed;\n z-index: 2147483647;\n visibility: hidden;\n pointer-events: none;\n padding: 8px 10px;\n border-radius: 8px;\n box-sizing: border-box;\n background: var(--ink);\n color: oklch(0.98 0.003 250);\n font-family: var(--sans, inherit);\n font-size: 12px;\n line-height: 1.45;\n font-weight: 400;\n text-transform: none;\n letter-spacing: 0;\n text-align: left;\n white-space: normal;\n box-shadow: 0 6px 20px rgb(0 0 0 / 0.25);\n}\n.bm-tip-open {\n visibility: visible;\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) :where(input:not([type=\"checkbox\"]):not([type=\"file\"]), select, textarea) {\n width: 100%;\n min-height: 40px;\n padding: 0 12px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n color: var(--ink);\n font-size: 14px;\n font-weight: 400;\n outline: none;\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) textarea {\n padding: 8px 12px;\n min-height: 72px;\n line-height: 1.5;\n resize: vertical;\n}\n:is(.bm-sidebar, .bm-popover) select:not([size]) {\n appearance: none;\n padding-right: 32px;\n /* A caret made of gradients, not a `data:` image: a site's Content-Security-Policy can block those. */\n background-image: linear-gradient(45deg, transparent 50%, #777 50%), linear-gradient(135deg, #777 50%, transparent 50%);\n background-size: 6px 6px;\n background-repeat: no-repeat;\n background-position:\n right 17px center,\n right 12px center;\n}\n.bm-sidebar select[size],\n.bm-popover select[size] {\n padding: 4px;\n font-size: 12px;\n}\n.bm-sidebar select[size] option,\n.bm-sidebar select[size] optgroup,\n.bm-popover select[size] option,\n.bm-popover select[size] optgroup {\n padding: 3px 6px;\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) :where(input:not([type=\"checkbox\"]):not([type=\"file\"]), select, textarea):focus {\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px var(--bm-primary-ring);\n}\n:is(.bm-sidebar, .bm-popover, .bm-seo, .bm-consent) :where(input[aria-label=\"Link URL\"], .bm-mono) {\n font-family: var(--mono);\n font-size: 13px;\n}\n.bm-prefix-wrap {\n display: flex;\n align-items: center;\n min-height: 40px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n}\n.bm-prefix-wrap:focus-within {\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px var(--bm-primary-ring);\n}\n.bm-prefix {\n padding: 0 2px 0 12px;\n font-family: var(--mono);\n font-size: 13px;\n color: var(--muted);\n}\n.bm-prefix-wrap input {\n border: 0;\n box-shadow: none !important;\n min-height: 38px;\n padding-left: 2px;\n font-family: var(--mono);\n font-size: 13px;\n}\n.bm-stack {\n display: flex;\n flex-direction: column;\n gap: 18px;\n}\n.bm-stack-tight {\n gap: 8px;\n}\n.bm-groups {\n gap: 36px;\n}\n.bm-list {\n display: flex;\n flex-direction: column;\n border-radius: 10px;\n box-shadow: 0 0 0 1px var(--bm-border);\n overflow: hidden;\n}\n.bm-list-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px 8px 12px;\n border-bottom: 1px solid var(--line-soft);\n}\n.bm-list-row:last-child {\n border-bottom: 0;\n}\n.bm-list-row-on {\n background: var(--accent-tint);\n}\n.bm-list-row a {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n color: var(--ink);\n text-decoration: none;\n}\n.bm-list-row a:hover .bm-list-title {\n text-decoration: underline;\n}\n.bm-list-title {\n font-size: 14px;\n font-weight: 500;\n}\n.bm-list-path {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n}\n.bm-badge-home {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: var(--bm-badge-green-bg);\n color: var(--bm-badge-green-fg);\n}\n.bm-badge {\n font-family: var(--mono);\n font-size: 11px;\n padding: 3px 7px;\n border-radius: 5px;\n background: var(--bm-badge-amber-bg);\n color: var(--bm-badge-amber-fg);\n}\n.bm-badge-system {\n background: var(--fill);\n color: var(--ink-2);\n}\n.bm-badge-on {\n background: var(--bm-badge-green-bg);\n color: var(--bm-badge-green-fg);\n}\n.bm-row {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-wrap: wrap;\n}\n.bm-row-split {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 10px;\n}\n.bm-error {\n color: var(--danger-ink);\n font-size: 12px;\n font-weight: 400;\n margin: 0;\n}\n.bm-warn {\n color: var(--warn-ink);\n font-size: 12px;\n margin: 0;\n}\n.bm-note {\n margin: 0;\n color: var(--bm-help);\n font-size: 13px;\n line-height: 1.55;\n font-weight: 400;\n}\n.bm-group + .bm-note,\n.bm-group-split + .bm-note {\n margin-top: -4px;\n}\n\n/* Switch: 36 x 20, knob 16 inset 2 */\n.bm-check {\n flex-direction: row;\n align-items: center;\n gap: 10px;\n font-weight: 500;\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"] {\n appearance: none;\n position: relative;\n flex: none;\n width: 36px;\n height: 20px;\n margin: 0;\n border-radius: 999px;\n background: var(--bm-switch-off);\n cursor: pointer;\n transition: background 0.15s;\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"]::before {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #fff;\n box-shadow: 0 1px 2px oklch(0 0 0 / 0.2);\n transition: transform 0.15s;\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"]:checked {\n background: var(--bm-primary);\n}\n:is(.bm-check, .bm-switch-row) input[type=\"checkbox\"]:checked::before {\n transform: translateX(16px);\n}\n.bm-popover .bm-check {\n color: var(--bm-label);\n font-size: 14px;\n}\n\n/* Buttons inside the sidebar */\n.bm-sidebar :where(button:not([role=\"tab\"]):not([role=\"radio\"]):not(.bm-resize)) {\n min-height: 32px;\n padding: 0 12px;\n border: 0;\n border-radius: 8px;\n background: var(--fill);\n color: var(--ink);\n font-size: 13px;\n font-weight: 500;\n}\n.bm-sidebar :where(button:not([role=\"tab\"]):not([role=\"radio\"]):not(.bm-resize)):hover:not(:disabled) {\n background: var(--fill-hover);\n}\n.bm-sidebar button:disabled {\n opacity: 0.45;\n cursor: default;\n}\n/* Dashed \"Add ...\" buttons: Add link, Add button, Add column, Add item */\n.bm-sidebar .bm-add {\n min-height: 44px;\n background: oklch(0.985 0.002 250);\n color: var(--bm-link);\n border: 1px dashed oklch(0.85 0.005 250);\n border-radius: 8px;\n}\n.bm-sidebar .bm-add:hover:not(:disabled) {\n background: var(--accent-tint);\n}\n\n/* Cards, lists, images */\n.bm-card {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 12px;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n}\n.bm-card .bm-card {\n background: var(--bm-fill-nested);\n border-color: var(--line-soft);\n}\n.bm-card > .bm-label:first-child:not(:only-child) {\n font-family: var(--mono);\n font-size: 11px;\n letter-spacing: 0.04em;\n font-weight: 500;\n color: var(--muted);\n}\n.bm-card[draggable=\"true\"] {\n cursor: grab;\n}\n/* Drag and drop: the target shows what a drop would do. */\n.bm-dragging {\n opacity: 0.4;\n}\n.bm-drop-before,\n.bm-drop-after,\n.bm-drop-child {\n --drop: var(--accent);\n}\n.bm-drop-before::before,\n.bm-drop-after::before {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n height: 3px;\n border-radius: 3px;\n background: var(--drop);\n box-shadow: 0 0 0 2px var(--accent-ring);\n pointer-events: none;\n z-index: 2;\n}\n.bm-drop-before::before {\n top: -6px;\n}\n.bm-drop-after::before {\n bottom: -6px;\n}\n.bm-drop-child {\n box-shadow: inset 0 0 0 2px var(--drop);\n background: var(--accent-tint);\n}\n.bm-drop-before::after,\n.bm-drop-after::after,\n.bm-drop-child::after,\n.bm-drop-files::after {\n content: attr(data-drop-hint);\n position: absolute;\n right: 8px;\n padding: 3px 8px;\n border-radius: 6px;\n background: var(--ink);\n color: #fff;\n font-size: 11px;\n font-weight: 500;\n line-height: 1.3;\n white-space: nowrap;\n pointer-events: none;\n z-index: 3;\n}\n.bm-drop-before::after {\n top: -22px;\n}\n.bm-drop-after::after {\n bottom: -22px;\n}\n.bm-drop-child::after {\n top: -11px;\n right: 12px;\n}\n.bm-drop-files {\n box-shadow: inset 0 0 0 2px var(--accent);\n background: var(--accent-tint);\n}\n.bm-drop-files::after {\n top: -11px;\n right: 12px;\n}\n.bm-thumb {\n width: 100%;\n height: 96px;\n object-fit: cover;\n border-radius: 7px;\n background: var(--fill);\n}\n.bm-drop {\n display: flex;\n flex-direction: column;\n gap: 8px;\n border: 1px dashed var(--line);\n border-radius: 10px;\n padding: 10px;\n background: var(--fill-soft);\n}\n.bm-drop input[type=\"file\"] {\n width: 100%;\n font-size: 12px;\n color: var(--muted);\n}\n.bm-drop input[type=\"file\"]::file-selector-button {\n height: 32px;\n margin-right: 10px;\n padding: 0 12px;\n border: 0;\n border-radius: 7px;\n background: var(--ink);\n color: #fff;\n font: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n}\n.bm-alert {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 14px;\n border-radius: 12px;\n background: var(--danger-tint);\n box-shadow: 0 0 0 1px oklch(0.55 0.18 25 / 0.35);\n}\n.bm-alert-title {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--danger-ink);\n}\n.bm-alert .bm-error {\n font-family: var(--mono);\n font-size: 11px;\n}\n.bm-alert-notice {\n background: var(--warn-tint);\n box-shadow: 0 0 0 1px oklch(0.45 0.09 65 / 0.2);\n}\n.bm-alert-notice .bm-note {\n color: var(--warn-ink);\n font-size: 12px;\n}\n\n/* Header actions */\n.bm-save {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 34px;\n padding: 0 12px;\n border: 0;\n border-radius: 8px;\n background: var(--accent);\n color: #fff;\n font-size: 13px;\n font-weight: 600;\n}\n.bm-dialog .bm-primary kbd {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n margin-left: 8px;\n opacity: 0.8;\n}\n.bm-save kbd {\n font-family: var(--mono);\n font-size: 10px;\n font-weight: 400;\n opacity: 0.75;\n}\n/* Icon buttons: 32 x 32, transparent, grey icon, grey fill on hover. */\n.bm-icon-btn {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: 32px;\n height: 32px;\n min-height: 0 !important;\n padding: 0 !important;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--bm-icon);\n}\n.bm-icon-btn:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n.bm-icon-btn:disabled {\n opacity: 0.35;\n}\n.bm-close {\n width: 32px;\n height: 32px;\n background: transparent;\n color: var(--bm-icon);\n border-radius: 7px;\n}\n.bm-close:hover:not(:disabled) {\n background: var(--fill) !important;\n color: var(--ink);\n}\n.bm-dock .bm-save {\n font-family: var(--sans);\n}\n.bm-split {\n position: relative;\n display: inline-flex;\n flex: none;\n}\n.bm-split .bm-split-main {\n border-radius: 8px 0 0 8px;\n}\n.bm-split .bm-split-toggle {\n width: 28px;\n padding: 0;\n justify-content: center;\n border-radius: 0 8px 8px 0;\n box-shadow: inset 1px 0 0 oklch(1 0 0 / 0.35);\n}\n.bm-split .bm-split-toggle:focus-visible,\n.bm-split .bm-split-main:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n.bm-split-menu {\n position: absolute;\n z-index: 8;\n top: calc(100% + 6px);\n right: 0;\n min-width: 200px;\n display: flex;\n flex-direction: column;\n padding: 4px;\n border-radius: 10px;\n background: #fff;\n box-shadow: var(--bm-shadow-pop);\n}\n.bm-split-menu button.bm-split-item {\n display: flex;\n align-items: center;\n width: 100%;\n min-height: 34px;\n padding: 0 10px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--ink);\n font-family: var(--sans);\n font-size: 13px;\n font-weight: 500;\n text-align: left;\n}\n.bm-split-menu button.bm-split-item:hover:not(:disabled),\n.bm-split-menu button.bm-split-item:focus-visible {\n background: var(--fill);\n outline: none;\n}\n.bm-split-menu button.bm-split-danger {\n color: var(--danger-ink);\n}\n.bm-split-menu button.bm-split-item {\n justify-content: space-between;\n gap: 16px;\n}\n.bm-split-menu button.bm-split-item kbd {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--muted);\n}\n.bm-split-menu button.bm-split-sep {\n margin-top: 5px;\n position: relative;\n}\n.bm-split-menu button.bm-split-sep::before {\n content: \"\";\n position: absolute;\n left: 6px;\n right: 6px;\n top: -3px;\n height: 1px;\n background: var(--line);\n}\n.bm-split-menu button.bm-split-danger:hover:not(:disabled),\n.bm-split-menu button.bm-split-danger:focus-visible {\n background: var(--danger-tint);\n}\n.bm-split-menu button.bm-split-item:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.bm-sidebar .bm-icon-btn.bm-danger {\n color: var(--bm-danger-icon);\n}\n.bm-sidebar .bm-icon-btn.bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-small {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n min-height: 28px !important;\n padding: 0 10px !important;\n font-family: var(--sans);\n font-size: 12px !important;\n letter-spacing: 0;\n text-transform: none;\n align-self: flex-start;\n}\n.bm-group-split {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-top: 18px;\n margin-bottom: 0;\n padding-bottom: 10px;\n border-bottom: 1px solid var(--bm-divider);\n}\n.bm-group-split:first-child {\n margin-top: 0;\n}\n.bm-group-split > .bm-group {\n margin: 0;\n padding: 0;\n border: 0;\n}\n.bm-group-split .bm-small {\n text-transform: none;\n letter-spacing: 0;\n}\n.bm-group-split span.bm-small {\n font-family: var(--mono);\n font-size: 11px !important;\n font-weight: 400;\n color: var(--bm-muted);\n padding: 0 !important;\n min-height: 0 !important;\n}\n.bm-stack-tight > .bm-group-split {\n margin-bottom: 10px;\n}\n\n/* Labels with a right-hand tag */\n.bm-label.bm-label-row,\n.bm-label-row {\n flex-direction: row;\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n}\n.bm-meta-tag {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n letter-spacing: 0;\n color: var(--bm-muted);\n}\n\n/* Switch rows */\n.bm-switch-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n cursor: pointer;\n}\n.bm-switch-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n.bm-switch-title {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n font-weight: 500;\n color: var(--bm-label);\n}\n\n/* Tone cards and segmented controls */\n.bm-tones {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 6px;\n}\n:is(.bm-sidebar, .bm-popover) .bm-tone {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: 6px;\n min-height: 0;\n padding: 5px 5px 6px;\n border-radius: 9px;\n background: #fff;\n border: 0;\n box-shadow: inset 0 0 0 1px var(--bm-border);\n font-size: 12px;\n font-weight: 500;\n text-align: center;\n}\n:is(.bm-sidebar, .bm-popover) .bm-tone:hover {\n background: var(--fill-soft);\n}\n:is(.bm-sidebar, .bm-popover) .bm-tone[aria-checked=\"true\"] {\n box-shadow: inset 0 0 0 2px var(--accent);\n background: #fff;\n}\n.bm-tones-2 {\n grid-template-columns: repeat(2, 1fr);\n}\n.bm-tones-3 {\n grid-template-columns: repeat(3, 1fr);\n}\n/* A miniature of each button look, drawn with the editor's colours so it does not depend on the site theme. */\n.bm-btnsample {\n display: grid;\n place-items: center;\n height: 26px;\n border-radius: 6px;\n background: var(--fill-soft);\n}\n.bm-btnsample > span {\n display: block;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n}\n.bm-btnsample-default > span {\n color: var(--ink-2);\n}\n.bm-btnsample-primary > span {\n padding: 5px 12px;\n border-radius: 999px;\n background: var(--accent);\n color: #fff;\n}\n.bm-btnsample-secondary > span {\n padding: 5px 12px;\n border-radius: 999px;\n color: var(--ink);\n box-shadow: inset 0 0 0 1px var(--ink-2);\n}\n.bm-btnsample-tertiary > span {\n color: var(--accent);\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n.bm-swatch {\n display: inline-block;\n flex: none;\n width: 10px;\n height: 10px;\n border-radius: 3px;\n box-shadow: inset 0 0 0 1px oklch(0.2 0.02 255 / 0.15);\n}\n.bm-swatch-lg {\n display: block;\n width: auto;\n height: 22px;\n border-radius: 6px;\n}\n.bm-swatch-base {\n background: #fff;\n}\n.bm-swatch-subtle {\n background: oklch(0.96 0.005 250);\n}\n.bm-swatch-inverse {\n background: var(--ink);\n}\n.bm-swatch-brand {\n background: var(--accent);\n}\n.bm-segmented {\n display: flex;\n padding: 3px;\n border-radius: 9px;\n background: var(--bm-fill);\n}\n.bm-sidebar .bm-segmented button,\n.bm-dialog .bm-segmented button {\n flex: 1;\n min-height: 36px;\n height: 36px;\n padding: 0 8px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: oklch(0.45 0.01 255);\n font-size: 13px;\n font-weight: 400;\n}\n.bm-sidebar .bm-segmented button:hover:not(:disabled),\n.bm-dialog .bm-segmented button:hover:not(:disabled) {\n background: oklch(1 0 0 / 0.5);\n}\n.bm-sidebar .bm-segmented button[aria-checked=\"true\"],\n.bm-dialog .bm-segmented button[aria-checked=\"true\"] {\n background: #fff;\n color: var(--ink);\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-icon-picker {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));\n gap: 4px;\n padding: 3px;\n border-radius: 9px;\n background: var(--bm-fill);\n}\n.bm-sidebar .bm-icon-picker button {\n display: grid;\n place-items: center;\n min-height: 40px;\n height: 40px;\n padding: 0;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: oklch(0.45 0.01 255);\n}\n.bm-sidebar .bm-icon-picker button:hover {\n background: oklch(1 0 0 / 0.5);\n color: var(--ink);\n}\n.bm-sidebar .bm-icon-picker button[aria-checked=\"true\"] {\n background: #fff;\n color: var(--accent);\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-icon-picker svg {\n width: 20px;\n height: 20px;\n}\n.bm-actions-split {\n display: flex;\n gap: 8px;\n padding-top: 4px;\n}\n.bm-actions-split button {\n flex: 1;\n min-height: 40px !important;\n font-size: 14px !important;\n}\n.bm-sidebar .bm-actions-split .bm-danger {\n background: var(--bm-danger-soft);\n}\n\n/* Arrays, links, images */\n.bm-array {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-array-row {\n position: relative;\n}\n.bm-array-grip {\n cursor: grab;\n}\n.bm-array-item {\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n overflow: hidden;\n}\n.bm-array-item summary {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 44px;\n padding: 0 8px 0 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--ink);\n cursor: pointer;\n list-style: none;\n}\n.bm-array-item summary::-webkit-details-marker {\n display: none;\n}\n.bm-array-item summary:hover {\n background: var(--fill-soft);\n}\n.bm-array-summary {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-grip,\n.bm-chevron {\n display: inline-grid;\n place-items: center;\n color: oklch(0.65 0.01 255);\n}\n.bm-chevron {\n transition: transform 0.12s;\n}\ndetails[open] > summary .bm-chevron {\n transform: rotate(90deg);\n}\n.bm-array-body {\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 12px;\n background: var(--bm-fill-nested);\n border-top: 1px solid var(--line-soft);\n}\n.bm-row-end {\n justify-content: flex-end;\n}\n.bm-sidebar .bm-add-row {\n width: 100%;\n}\n.bm-link-btn {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n min-height: 40px;\n padding: 0 12px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n text-align: left;\n color: var(--ink-2);\n}\n.bm-sidebar .bm-link-btn {\n background: #fff;\n border: 1px solid var(--bm-border);\n font-size: 14px;\n padding: 0 12px;\n}\n.bm-sidebar .bm-link-btn:hover:not(:disabled) {\n background: #fff;\n border-color: oklch(0.8 0.005 250);\n}\n.bm-link-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--ink);\n font-weight: 500;\n}\n.bm-link-href {\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n max-width: 45%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-stripes {\n background: repeating-linear-gradient(135deg, oklch(0.93 0.004 250) 0 6px, oklch(0.965 0.003 250) 6px 12px);\n}\n\n/* Image field: label above, compact 56px row, alt text under it */\n.bm-imagefield {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.bm-image-row {\n display: flex;\n gap: 10px;\n align-items: center;\n}\n.bm-image-row .bm-thumb {\n flex: none;\n width: 56px;\n height: 56px;\n border-radius: 6px;\n}\n.bm-image-meta {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n justify-content: center;\n}\n.bm-image-path {\n font-family: var(--mono);\n font-size: 12px;\n color: var(--bm-label);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-sidebar .bm-alt {\n min-height: 40px;\n font-size: 14px;\n}\n.bm-image-actions {\n flex-wrap: nowrap;\n gap: 6px;\n}\n.bm-image-actions > button:not(.bm-icon-btn) {\n flex: 1;\n min-height: 36px;\n font-size: 13px;\n}\n.bm-layout {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding-top: 2px;\n}\n.bm-layout-row {\n display: grid;\n grid-template-columns: 56px 1fr;\n align-items: center;\n column-gap: 10px;\n row-gap: 4px;\n}\n.bm-layout-row .bm-label {\n margin: 0;\n}\n.bm-layout-row .bm-layout-hint {\n grid-column: 2;\n}\n.bm-position {\n display: grid;\n grid-template-columns: repeat(3, 20px);\n grid-template-rows: repeat(3, 20px);\n gap: 3px;\n padding: 4px;\n width: max-content;\n border-radius: 8px;\n background: var(--fill);\n}\n.bm-sidebar .bm-position-cell {\n width: 20px;\n height: 20px;\n min-height: 0;\n padding: 0;\n border: 0;\n border-radius: 5px;\n background: #fff;\n box-shadow: inset 0 0 0 1px var(--line);\n}\n.bm-sidebar .bm-position-cell:hover:not(:disabled) {\n background: var(--accent-tint);\n}\n.bm-sidebar .bm-position-cell[aria-checked=\"true\"],\n.bm-sidebar .bm-position-cell[aria-checked=\"true\"]:hover:not(:disabled) {\n background: var(--accent);\n box-shadow: none;\n}\n.bm-sidebar .bm-position-cell:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.bm-slot,\n.bm-dropzone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 4px;\n width: 100%;\n min-height: 96px;\n padding: 14px;\n border: 1.5px dashed oklch(0.82 0.006 250);\n border-radius: 10px;\n background: var(--fill-soft);\n color: var(--ink-2);\n text-align: center;\n cursor: pointer;\n}\n.bm-sidebar .bm-slot:hover:not(:disabled),\n.bm-dropzone:hover {\n border-color: var(--accent);\n background: var(--accent-tint);\n}\n.bm-dropzone {\n min-height: 180px;\n position: relative;\n}\n.bm-dropzone:focus-within {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n}\n.bm-dropzone-over {\n border-color: var(--accent);\n background: var(--accent-tint);\n}\n.bm-slot-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--ink);\n}\n.bm-slot-hint {\n font-size: 11px;\n color: var(--muted);\n}\n.bm-scrim {\n position: fixed;\n inset: 0;\n z-index: 7;\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding: 10vh 16px 16px;\n background: oklch(0.2 0.01 255 / 0.4);\n}\n.bm-modal {\n display: flex;\n flex-direction: column;\n width: min(480px, 100%);\n max-height: min(560px, 80vh);\n overflow: hidden;\n padding: 20px 0 0;\n border-radius: 14px;\n background: #fff;\n box-shadow: var(--bm-shadow-dialog);\n}\n.bm-modal-head {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 0 20px 12px;\n}\n.bm-modal-head .bm-dialog-title {\n flex: none;\n}\n.bm-modal-head .bm-meta-tag {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-modal-head .bm-icon-btn {\n margin: -6px -8px -6px 0;\n}\n.bm-modal .bm-tabs {\n margin: 0 20px;\n padding: 3px;\n gap: 0;\n border: 0;\n border-radius: 9px;\n background: var(--bm-fill);\n overflow: visible;\n}\n.bm-modal .bm-tabs button {\n flex: 1;\n height: 36px;\n min-height: 36px;\n padding: 0 8px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 400;\n}\n.bm-modal .bm-tabs button:hover {\n background: oklch(1 0 0 / 0.5);\n}\n.bm-modal .bm-tabs button[aria-selected=\"true\"] {\n background: #fff;\n color: var(--ink);\n font-weight: 500;\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-modal-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: 16px 20px 20px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.bm-library {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 10px;\n}\n.bm-library-item {\n position: relative;\n}\n.bm-library-pick {\n display: flex;\n flex-direction: column;\n gap: 4px;\n width: 100%;\n min-height: 0;\n padding: 4px;\n border: 0;\n border-radius: 9px;\n background: var(--fill-soft);\n text-align: left;\n font-family: var(--mono);\n font-size: 9px;\n font-weight: 400;\n color: var(--muted);\n word-break: break-all;\n cursor: pointer;\n}\n.bm-library-pick:hover {\n background: var(--fill-hover);\n}\n.bm-library-pick img {\n width: 100%;\n aspect-ratio: 1 / 1;\n object-fit: cover;\n border-radius: 6px;\n background: var(--fill);\n}\n.bm-library-pick[aria-pressed=\"true\"] {\n box-shadow: 0 0 0 2px var(--accent);\n background: var(--accent-tint);\n}\n.bm-library-delete {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 24px;\n height: 24px;\n min-height: 0;\n background: #fff;\n box-shadow: 0 1px 3px oklch(0.2 0.01 255 / 0.25);\n opacity: 0;\n}\n.bm-library-item:hover .bm-library-delete,\n.bm-library-delete:focus-visible {\n opacity: 1;\n}\n.bm-library-empty {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n}\n.bm-modal-confirm {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px 20px 16px;\n border-top: 1px solid var(--line-soft);\n background: var(--danger-tint);\n}\n.bm-modal-confirm .bm-note {\n color: var(--danger-ink);\n font-size: 13px;\n line-height: 1.5;\n}\n.bm-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n border: 0;\n white-space: nowrap;\n}\n.bm-popover-title {\n grid-column: 1 / -1;\n padding: 0;\n font-size: 16px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--bm-ink);\n}\n.bm-popover-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0;\n}\n.bm-popover-head-wide {\n grid-column: 1 / -1;\n}\n.bm-popover[aria-label=\"Edit link\"],\n.bm-popover[aria-label=\"Add section\"][role=\"listbox\"] {\n z-index: 5;\n}\n.bm-popover :is(.bm-fmt-bold) {\n font-weight: 700;\n}\n.bm-fmt-bold {\n font-weight: 700;\n font-size: 13px;\n}\n.bm-fmt-heading {\n font-weight: 700;\n font-size: 12px;\n letter-spacing: -0.02em;\n}\n.bm-fmt-italic {\n font-family: var(--serif);\n font-style: italic;\n font-size: 15px;\n}\n\n/* Edit link: Advanced row */\n.bm-advanced {\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n.bm-popover button.bm-advanced-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-height: 32px;\n padding: 0 2px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--bm-label);\n font-size: 13px;\n font-weight: 500;\n text-align: left;\n}\n.bm-popover button.bm-advanced-toggle:hover {\n background: transparent;\n color: var(--bm-ink);\n}\n.bm-advanced-toggle .bm-chevron {\n transition: transform 0.12s;\n}\n.bm-advanced-toggle[aria-expanded=\"true\"] .bm-chevron {\n transform: rotate(90deg);\n}\n.bm-advanced-summary {\n margin-left: auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--bm-muted);\n}\n\n/* SEO card and dialog */\n.bm-seo-card {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.bm-seo-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.bm-seo-badge {\n padding: 2px 8px;\n border-radius: 999px;\n background: var(--fill-soft);\n color: var(--bm-label);\n font-family: var(--mono);\n font-size: 11px;\n}\n.bm-seo-edit,\n.bm-consent-edit {\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n.bm-dialog.bm-seo {\n position: relative;\n width: min(560px, 100%);\n max-height: calc(100vh - 10vh - 32px);\n min-height: 0;\n}\n.bm-seo-body {\n display: flex;\n flex-direction: column;\n gap: 20px;\n min-height: 0;\n overflow-y: auto;\n padding: 2px 4px 2px 2px;\n}\n.bm-seo-json {\n min-height: 220px;\n white-space: pre;\n overflow: auto;\n tab-size: 2;\n}\n.bm-seo-json[aria-invalid=\"true\"] {\n border-color: var(--bm-danger);\n}\n.bm-seo-format {\n align-self: flex-start;\n}\n\n/* Cookie banner dialog */\n.bm-dialog.bm-consent {\n position: relative;\n width: min(520px, 100%);\n max-height: calc(100vh - 10vh - 32px);\n min-height: 0;\n}\n.bm-consent-body {\n display: flex;\n flex-direction: column;\n gap: 20px;\n min-height: 0;\n overflow-y: auto;\n padding: 2px 4px 2px 2px;\n}\n.bm-consent-preview {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--fill-soft);\n}\n.bm-consent-preview-title {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--bm-label);\n}\n.bm-consent-preview-text {\n margin: 0;\n font-size: 13px;\n line-height: 1.45;\n color: var(--bm-muted);\n overflow-wrap: anywhere;\n}\n.bm-consent-preview-link {\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n.bm-consent-preview-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n.bm-consent-preview-buttons > span {\n padding: 5px 14px;\n border-radius: 999px;\n box-shadow: inset 0 0 0 1px var(--bm-border);\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n}\n\n/* SEO preview, OG row, outline */\n.bm-serp {\n display: flex;\n flex-direction: column;\n gap: 3px;\n padding: 12px 14px;\n border-radius: 10px;\n background: var(--fill-soft);\n}\n.bm-serp-image {\n flex-direction: row;\n align-items: flex-start;\n gap: 12px;\n}\n.bm-serp-text {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n}\n.bm-serp-thumb {\n flex: none;\n width: 64px;\n height: 64px;\n border-radius: 8px;\n object-fit: cover;\n background: var(--fill);\n}\n.bm-serp-title {\n font-size: 15px;\n font-weight: 500;\n color: oklch(0.42 0.12 260);\n}\n.bm-serp-url {\n font-family: var(--mono);\n font-size: 11px;\n color: oklch(0.45 0.08 145);\n}\n.bm-serp-desc {\n font-size: 12px;\n line-height: 1.45;\n color: oklch(0.45 0.01 255);\n}\n.bm-outline-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.bm-sidebar .bm-outline-row {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n min-height: 40px;\n padding: 0 10px;\n border-radius: 8px;\n background: transparent;\n text-align: left;\n font-size: 14px;\n}\n.bm-sidebar .bm-outline-row:hover:not(:disabled) {\n background: var(--fill-soft);\n}\n\n/* Section rows (Pages tab): grip, tone swatch, name over #anchor and variant, then actions. */\n.bm-srow {\n position: relative;\n display: flex;\n align-items: center;\n gap: 4px;\n min-height: 52px;\n padding: 6px 6px 6px 8px;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n}\n.bm-srow:hover {\n border-color: oklch(0.8 0.008 250);\n}\n.bm-srow-grip {\n flex: none;\n width: 16px;\n height: 32px;\n display: inline-grid;\n place-items: center;\n cursor: grab;\n touch-action: none;\n}\n.bm-srow-grip:active {\n cursor: grabbing;\n}\n.bm-srow .bm-outline-row {\n flex: 1;\n min-width: 0;\n width: auto;\n padding: 0 8px 0 4px;\n gap: 10px;\n}\n.bm-srow .bm-swatch {\n width: 10px;\n height: 10px;\n border-radius: 2px;\n}\n.bm-srow-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.bm-srow-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--bm-ink);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-srow-meta {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--bm-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-srow .bm-outline-meta {\n flex: none;\n max-width: 40%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-srow-btn {\n width: 32px;\n height: 32px;\n background: transparent;\n color: var(--bm-icon);\n border-radius: 7px;\n}\n.bm-srow-btn:disabled {\n opacity: 0.35;\n}\n.bm-sidebar .bm-srow-btn:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n.bm-sidebar .bm-srow-btn.bm-danger {\n color: var(--bm-danger-icon);\n}\n.bm-sidebar .bm-srow-btn.bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n}\n.bm-srow-sep {\n flex: none;\n width: 1px;\n height: 20px;\n margin: 0 2px;\n background: var(--bm-divider);\n}\n.bm-outline-n {\n width: 18px;\n font-family: var(--mono);\n font-size: 11px;\n color: oklch(0.55 0.01 255);\n}\n.bm-outline-label {\n flex: 1;\n min-width: 0;\n font-weight: 500;\n}\n.bm-outline-meta {\n font-family: var(--mono);\n font-size: 11px;\n font-weight: 400;\n color: var(--muted);\n}\n\n/* Navigation and footer link cards */\n.bm-nav-card {\n padding: 12px 12px 14px;\n gap: 10px;\n}\n.bm-nested {\n margin: 6px 0 0 16px;\n}\n.bm-nav-children {\n margin-top: -4px;\n}\n.bm-nav-head {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.bm-nav-head .bm-icon-btn,\n.bm-column-head .bm-icon-btn {\n background: var(--bm-fill);\n color: oklch(0.45 0.01 255);\n}\n.bm-nav-head .bm-icon-btn:hover:not(:disabled),\n.bm-column-head .bm-icon-btn:hover:not(:disabled) {\n background: var(--bm-fill-hover);\n color: var(--bm-ink);\n}\n.bm-sidebar .bm-nav-head .bm-icon-btn.bm-danger,\n.bm-sidebar .bm-column-head .bm-icon-btn.bm-danger {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-icon);\n}\n.bm-sidebar .bm-nav-label {\n flex: 1;\n min-width: 0;\n min-height: 32px;\n padding: 0 8px;\n border-color: transparent;\n font-weight: 500;\n}\n.bm-sidebar .bm-nav-label:hover {\n border-color: var(--line);\n}\n.bm-column {\n padding: 0;\n gap: 0;\n}\n.bm-column-head {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px;\n cursor: grab;\n}\n.bm-column-links > summary {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 40px;\n padding: 0 12px;\n border-top: 1px solid var(--line-soft);\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n cursor: pointer;\n list-style: none;\n}\n.bm-column-links > summary::-webkit-details-marker {\n display: none;\n}\n.bm-column-links > :not(summary) {\n margin: 10px 12px 0;\n}\n.bm-column-links > :last-child {\n margin-bottom: 12px;\n}\n\n/* Wordmark preview */\n.bm-card-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.bm-card-head .bm-label {\n flex: none;\n}\n.bm-combo {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n:is(.bm-sidebar, .bm-popover) .bm-combo-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n width: auto;\n max-width: 140px;\n min-height: 38px;\n padding: 0 10px 0 12px;\n border: 0;\n border-left: 1px solid var(--bm-border);\n border-radius: 0;\n background: var(--fill-soft);\n color: var(--ink-2);\n font-family: var(--mono);\n font-size: 12px;\n font-weight: 400;\n text-align: left;\n}\n:is(.bm-sidebar, .bm-popover) .bm-combo-trigger:hover:not(:disabled) {\n background: var(--fill-hover);\n}\n:is(.bm-sidebar, .bm-popover) .bm-combo-trigger[aria-expanded=\"true\"] {\n background: var(--accent-tint);\n color: var(--accent-hover);\n}\n/* One URL field: the text input and the page picker share a single border. */\n.bm-linkfield {\n display: flex;\n align-items: stretch;\n min-height: 40px;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n}\n.bm-linkfield:focus-within {\n border-color: var(--bm-primary);\n box-shadow: 0 0 0 3px var(--bm-primary-ring);\n}\n.bm-linkfield > input {\n flex: 1;\n min-width: 0;\n border: 0 !important;\n box-shadow: none !important;\n border-radius: 0;\n min-height: 38px;\n background: transparent;\n}\n.bm-linkfield .bm-combo {\n flex: none;\n max-width: 45%;\n}\n.bm-linkfield .bm-combo-trigger {\n height: 100%;\n}\n.bm-linkfield .bm-combo-trigger:focus-visible {\n outline-offset: -2px;\n}\n.bm-combo-trigger > span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bm-combo-trigger .bm-combo-custom {\n color: var(--muted);\n}\n.bm-combo-panel {\n position: fixed;\n z-index: 6;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 6px;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n background: #fff;\n box-shadow: 0 6px 18px oklch(0.2 0.02 255 / 0.1);\n}\n.bm-combo-list {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n}\n.bm-combo-group {\n margin: 6px 6px 2px;\n font-family: var(--mono);\n font-size: 10px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--muted);\n}\n.bm-combo-option {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 10px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--ink);\n cursor: pointer;\n}\n.bm-combo-option[aria-selected=\"true\"] {\n font-weight: 600;\n color: var(--accent-hover);\n}\n.bm-combo-active {\n background: var(--fill);\n}\n.bm-combo-value {\n flex: none;\n max-width: 50%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--mono);\n font-size: 11px;\n color: var(--muted);\n}\n.bm-combo-empty {\n margin: 0;\n padding: 8px;\n font-size: 12px;\n color: var(--muted);\n}\n.bm-format {\n margin-top: -4px;\n}\n.bm-sidebar .bm-format button[aria-pressed=\"true\"] {\n background: #fff;\n color: var(--ink);\n box-shadow: var(--bm-shadow-segment-on);\n}\n.bm-wordmark {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 14px;\n border-radius: 10px;\n background: var(--bm-fill-soft);\n}\n.bm-wordmark-name {\n font-size: 24px;\n font-weight: 600;\n letter-spacing: -0.03em;\n}\n.bm-alert-notice {\n flex-direction: row;\n align-items: flex-start;\n gap: 8px;\n color: var(--warn-ink);\n}\n.bm-alert-notice .bm-icon {\n margin-top: 2px;\n flex: none;\n}\n\n/*\n * Button system. Three variants, one danger modifier, one rule set.\n * secondary (default): neutral fill, ink text.\n * .bm-primary: the one main action of a surface. Solid accent, white text (AA).\n * .bm-tertiary: low emphasis text button (Cancel, Reset). No fill, no underline, grey fill on hover.\n * .bm-danger: modifier. primary = solid red, secondary = red text, tertiary = red text.\n * The scope list gives every rule enough specificity to beat the per-surface defaults above,\n * so the hover state of one variant can never fall back to the secondary fill.\n */\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button:where(.bm-primary, .bm-tertiary, .bm-danger):not(.bm-icon-btn, .bm-save) {\n transition:\n background-color 0.12s,\n color 0.12s;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary {\n background: var(--bm-primary);\n color: #fff;\n box-shadow: none;\n font-weight: 600;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary:hover:not(:disabled) {\n background: var(--bm-primary-hover);\n color: #fff;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary.bm-danger {\n background: var(--bm-danger);\n color: #fff;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-primary.bm-danger:hover:not(:disabled) {\n background: var(--danger-hover);\n color: #fff;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-danger:not(.bm-primary, .bm-tertiary, .bm-icon-btn) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-danger:not(.bm-primary, .bm-tertiary, .bm-icon-btn):hover:not(:disabled) {\n background: oklch(0.93 0.04 25);\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary {\n min-height: 32px;\n padding: 0 10px;\n border-radius: 8px;\n background: transparent;\n color: var(--bm-label);\n font-weight: 400;\n box-shadow: none;\n text-decoration: none;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal) button.bm-tertiary {\n min-height: 38px;\n font-size: 14px;\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary:hover:not(:disabled) {\n background: var(--bm-fill);\n color: var(--bm-ink);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary.bm-danger {\n background: transparent;\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button.bm-tertiary.bm-danger:hover:not(:disabled) {\n background: var(--bm-danger-soft);\n color: var(--bm-danger-text);\n}\n:is(.bm-dialog, .bm-popover, .bm-modal, .bm-sidebar) button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.bm-save:hover:not(:disabled) {\n background: var(--accent-hover);\n color: #fff;\n}\n.bm-sidebar .bm-save:hover:not(:disabled) {\n background: var(--accent-hover);\n color: #fff;\n}\n.bm-popover .bm-actions-remove,\n.bm-dialog .bm-actions-remove {\n margin-right: auto;\n}\n.bm-modal :where(button:not([role=\"tab\"], .bm-library-pick, .bm-icon-btn, .bm-tertiary)) {\n min-height: 38px;\n padding: 0 16px;\n border: 0;\n border-radius: 8px;\n background: var(--fill);\n color: var(--ink);\n font-size: 14px;\n font-weight: 400;\n}\n.bm-modal :where(button:not([role=\"tab\"], .bm-library-pick, .bm-icon-btn, .bm-tertiary)):hover:not(:disabled) {\n background: var(--fill-hover);\n}\n.bm-modal .bm-dropzone {\n font-family: var(--sans);\n}\n\n/* Design tab */\n.bm-colorrow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.bm-colorpick {\n flex: none;\n width: 40px !important;\n height: 40px;\n min-height: 40px !important;\n padding: 2px !important;\n border: 1px solid var(--bm-border);\n border-radius: 8px;\n background: #fff;\n cursor: pointer;\n}\n.bm-colorhex {\n flex: 1;\n min-width: 0;\n font-family: var(--mono);\n font-size: 13px;\n text-transform: lowercase;\n}\n.bm-colorhex[aria-invalid=\"true\"] {\n border-color: var(--bm-danger);\n}\n.bm-overrides {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--bm-border);\n border-radius: 10px;\n overflow: hidden;\n}\n.bm-override-row {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 10px 8px 12px;\n}\n.bm-override-row + .bm-override-row {\n border-top: 1px solid var(--bm-divider);\n}\n.bm-override-label {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n font-weight: 500;\n color: var(--bm-label);\n}\n.bm-override-label .bm-meta-tag {\n font-size: 10px;\n}\n.bm-override-row .bm-colorpick {\n width: 32px !important;\n height: 32px;\n min-height: 32px !important;\n padding: 1px !important;\n border-radius: 7px;\n}\n.bm-override-row .bm-colorhex {\n flex: none;\n width: 104px;\n min-height: 36px;\n padding: 0 10px;\n}\n.bm-tone-matrix {\n display: grid;\n grid-template-columns: 60px minmax(0, 1fr) minmax(0, 1fr);\n gap: 8px;\n align-items: stretch;\n}\n.bm-tone-pick {\n border: 0;\n text-align: left;\n font: inherit;\n cursor: pointer;\n}\n.bm-tone-cell[aria-pressed=\"true\"] {\n outline: 2px solid var(--bm-primary);\n outline-offset: 0;\n}\n.bm-tone-head {\n font-family: var(--mono);\n font-size: 10px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--muted);\n}\n.bm-tone-name {\n align-self: center;\n font-size: 12px;\n font-weight: 500;\n color: var(--ink-2);\n}\n.bm-tone-cell {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n min-width: 0;\n min-height: 46px;\n padding: 0 10px;\n border-radius: 8px;\n overflow: hidden;\n white-space: nowrap;\n}\n.bm-tone-aa {\n flex: none;\n font-size: 16px;\n font-weight: 600;\n}\n.bm-tone-muted {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 11px;\n}\n.bm-tone-chip {\n flex: none;\n padding: 2px 6px;\n border-radius: 5px;\n font-size: 10px;\n font-weight: 600;\n}\n.bm-tone-link {\n flex: none;\n font-size: 11px;\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.bm-contrast-list {\n margin: 6px 0 0;\n padding-left: 16px;\n font-family: var(--mono);\n font-size: 11px;\n color: var(--warn-ink);\n}\n.bm-range {\n flex: 1;\n min-width: 0;\n min-height: 28px;\n accent-color: var(--accent);\n cursor: pointer;\n}\n/* Preview: the only editor UI left on screen. */\n.bm-exit-preview {\n position: fixed;\n z-index: 7;\n right: 16px;\n bottom: 16px;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 40px;\n padding: 0 16px;\n border: 0;\n border-radius: 999px;\n background: var(--ink);\n color: #fff;\n font-size: 13px;\n font-weight: 500;\n box-shadow: 0 10px 30px oklch(0.2 0.02 255 / 0.3);\n}\n.bm-exit-preview:hover {\n background: oklch(0.28 0.012 255);\n}\n.bm-exit-preview:focus-visible {\n outline-color: oklch(0.82 0.14 145);\n outline-offset: 3px;\n}\n.bm-srow-add {\n display: flex;\n justify-content: flex-end;\n padding-top: 6px;\n}\n.bm-sidebar .bm-add-section {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-height: 32px;\n padding: 0 12px;\n border: 0;\n border-radius: 8px;\n background: var(--bm-primary);\n color: #fff;\n font-size: 13px;\n font-weight: 500;\n}\n.bm-sidebar .bm-add-section:hover {\n background: var(--bm-primary-hover);\n}\n";
19969
20592
  //#endregion
19970
20593
  //#region src/ui/styles.ts
19971
20594
  function boxStyle(rect, offset = 0) {
@@ -21312,7 +21935,7 @@ function siteOptionControl(site, option, onField) {
21312
21935
  onChange: (value) => onField(option.name, value)
21313
21936
  }, option.name);
21314
21937
  }
21315
- function SiteForm({ site, options, images, onField, onOptional, onConsentEnabled, onEditConsent, onMarks, onUploaded, onDeleted }) {
21938
+ function SiteForm({ site, options, images, onField, onOptional, onConsentEnabled, onEditConsent, onEditJsonLd, onMarks, onUploaded, onDeleted }) {
21316
21939
  const logo = getAt(site, "favicon") ?? getAt(site, "logo");
21317
21940
  const groupOf = (option) => SITE_GROUPS.find((group) => option.name.startsWith(group.prefix));
21318
21941
  const shown = options.filter((option) => !option.name.startsWith("footer.") && !option.name.startsWith("header.") && option.name !== "theme.mode");
@@ -21392,6 +22015,10 @@ function SiteForm({ site, options, images, onField, onOptional, onConsentEnabled
21392
22015
  })
21393
22016
  ]
21394
22017
  }),
22018
+ /* @__PURE__ */ jsx(JsonLdGroup, {
22019
+ site,
22020
+ onEdit: onEditJsonLd
22021
+ }),
21395
22022
  /* @__PURE__ */ jsxs("div", {
21396
22023
  class: "bm-stack",
21397
22024
  children: [
@@ -21512,6 +22139,33 @@ function ConsentGroup({ enabled, snippets, onEnabled, onEdit }) {
21512
22139
  ]
21513
22140
  });
21514
22141
  }
22142
+ /** Structured data on every page: a summary here, the blocks in a dialog. */
22143
+ function JsonLdGroup({ site, onEdit }) {
22144
+ const blocks = siteJsonLdOf(site);
22145
+ const types = blocks.map((block) => typeof block["@type"] === "string" ? block["@type"] : "block");
22146
+ return /* @__PURE__ */ jsxs("div", {
22147
+ class: "bm-stack",
22148
+ children: [
22149
+ /* @__PURE__ */ jsx("p", {
22150
+ class: "bm-group",
22151
+ children: "Structured data"
22152
+ }),
22153
+ /* @__PURE__ */ jsx("p", {
22154
+ class: "bm-hint",
22155
+ children: blocks.length === 0 ? "None. Add an Organization and a WebSite so search engines know who runs the site." : `On every page: ${types.join(", ")}.`
22156
+ }),
22157
+ /* @__PURE__ */ jsxs("button", {
22158
+ type: "button",
22159
+ class: "bm-tertiary bm-consent-edit",
22160
+ onClick: onEdit,
22161
+ children: [/* @__PURE__ */ jsx(Icon, {
22162
+ name: "settings",
22163
+ size: 14
22164
+ }), "Edit JSON-LD"]
22165
+ })
22166
+ ]
22167
+ });
22168
+ }
21515
22169
  //#endregion
21516
22170
  //#region src/ui/forms/footer-form.tsx
21517
22171
  /** Footer tab: layout, text, and the columns with their links. */
@@ -22430,6 +23084,9 @@ function SitePanel({ site, catalog }) {
22430
23084
  onEditConsent: () => {
22431
23085
  ui.dialog.value = { kind: "consent" };
22432
23086
  },
23087
+ onEditJsonLd: () => {
23088
+ ui.dialog.value = { kind: "siteJsonLd" };
23089
+ },
22433
23090
  onMarks: edits.applyMarksAt,
22434
23091
  onUploaded: doc.addImage,
22435
23092
  onDeleted: doc.dropImage