:root {
  --bg: #f2f3f5;
  --canvas: #e0e3e7;
  --panel: #fff;
  --border: #d4d7dc;
  --text: #1c1e21;
  --dim: #6a7075;
  --accent: #2f6fed;
  --accent-soft: #2f6fed33;
  --paper: #fff;
  --paper-shadow: rgba(0, 0, 0, 0.18);
  --mark: #ffd54f66;
  --mark-strong: #ffb300aa;
  --ink: #111;
  --field: #fff;
  --code-size: 14px;
  --popup-font: 19px;
  --tok-bracket: #495057;
  --tok-fret: #0b7285;
  --tok-note: #7048e8;
  --tok-cmd: #e8590c;
  --tok-num: #c2255c;
  --tok-bar: #c92a2a;
  --tok-punct: #868e96;
  --fb-green: #1f9d55;
  --fb-green-hover: #1b8a4b;
  --fb-green-text: #ffffff;
  --fb-green-soft: #e6f6ec;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1b1c1f;
    --canvas: #101114;
    --panel: #242629;
    --border: #3a3d42;
    --text: #e6e6e6;
    --dim: #969aa0;
    --accent: #5b93ff;
    --accent-soft: #5b93ff40;
    --paper: #26282c;
    --paper-shadow: rgba(0, 0, 0, 0.6);
    --mark: #8a6d0066;
    --mark-strong: #c9a200aa;
    --ink: #c2c5c9;
    --field: #35383d;
    --tok-bracket: #ced4da;
    --tok-fret: #66d9e8;
    --tok-note: #b197fc;
    --tok-cmd: #ffa94d;
    --tok-num: #f783ac;
    --tok-bar: #ff8787;
    --tok-punct: #9099a2;
    --fb-green: #2fb768;
    --fb-green-hover: #29a25c;
    --fb-green-text: #ffffff;
    --fb-green-soft: #123822;
  }
  body:not([data-theme]) {
    color-scheme: dark;
  }
}
/* explicit in-app toggle always wins over the OS preference above, in
     both directions — see themeBtn */
body[data-theme="light"] {
  color-scheme: light;
  --bg: #f2f3f5;
  --canvas: #e0e3e7;
  --panel: #fff;
  --border: #d4d7dc;
  --text: #1c1e21;
  --dim: #6a7075;
  --accent: #2f6fed;
  --accent-soft: #2f6fed33;
  --paper: #fff;
  --paper-shadow: rgba(0, 0, 0, 0.18);
  --mark: #ffd54f66;
  --mark-strong: #ffb300aa;
  --ink: #111;
  --field: #fff;
  --tok-bracket: #495057;
  --tok-fret: #0b7285;
  --tok-note: #7048e8;
  --tok-cmd: #e8590c;
  --tok-num: #c2255c;
  --tok-bar: #c92a2a;
  --tok-punct: #868e96;
  --fb-green: #1f9d55;
  --fb-green-hover: #1b8a4b;
  --fb-green-text: #ffffff;
  --fb-green-soft: #e6f6ec;
}
body[data-theme="dark"] {
  color-scheme: dark;
  --bg: #1b1c1f;
  --canvas: #141518;
  --panel: #242629;
  --border: #3a3d42;
  --text: #e6e6e6;
  --dim: #969aa0;
  --accent: #5b93ff;
  --accent-soft: #5b93ff40;
  --paper: #26282c;
  --paper-shadow: rgba(0, 0, 0, 0.6);
  --field: #35383d;
  --mark: #8a6d0066;
  --mark-strong: #c9a200aa;
  --ink: #c2c5c9;
  --tok-bracket: #ced4da;
  --tok-fret: #66d9e8;
  --tok-note: #b197fc;
  --tok-cmd: #ffa94d;
  --tok-num: #f783ac;
  --tok-bar: #ff8787;
  --tok-punct: #9099a2;
  --fb-green: #2fb768;
  --fb-green-hover: #29a25c;
  --fb-green-text: #ffffff;
  --fb-green-soft: #123822;
}
* {
  box-sizing: border-box;
}
html,
body {
  height: 100%;
}
body {
  margin: 0;
  font:
    13px/1.45 -apple-system,
    system-ui,
    sans-serif;
  background: var(--bg);
  color: var(--text);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ---------- top navbar: logo / search / account icons ---------- */
#navbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 14px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
#navLogo {
  font-weight: 700;
  font-size: 15px;
  color: var(--text);
  flex: none;
  white-space: nowrap;
}
#navSearchWrap {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
#appSwitcher {
  grid-column: 1;
  justify-self: end;
  margin-right: 10px;
  border-radius: 999px;
  padding: 6px 14px;
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 600;
}
#appSwitcher:hover {
  filter: brightness(1.1);
}
#navSearchBox {
  grid-column: 2;
  position: relative;
  display: flex;
  justify-content: center;
}
#navSearch {
  width: min(420px, 100%);
  border-radius: 999px;
  padding: 6px 14px;
}
#navIcons {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}

/* ---------- toolbar + menu bar: mode-scoped (Score/Font/Presets/Initials) --- */
/* Only the current mode's own menu bar / toolbar is shown -- same
   body.fontMode/body.presetsMode/body.initialsMode gating the old ribbon used.
   Initials has no menu bar/toolbar of its own (deliberately kept simple --
   see #initialsTopbar, a plain child of #initialsMain like #presetsTopbar),
   so it only ever needs to hide the OTHER modes' bars, never show its own. */
body.fontMode #scoreMenuBar, body.fontMode #scoreToolbar, body.fontMode #textFormatBar,
body.presetsMode #scoreMenuBar, body.presetsMode #scoreToolbar, body.presetsMode #textFormatBar,
body.initialsMode #scoreMenuBar, body.initialsMode #scoreToolbar, body.initialsMode #textFormatBar {
  display: none !important;
}
body:not(.fontMode) #fontMenuBar, body:not(.fontMode) #fontToolbar,
body.presetsMode #fontMenuBar, body.presetsMode #fontToolbar,
body.initialsMode #fontMenuBar, body.initialsMode #fontToolbar {
  display: none !important;
}
body:not(.presetsMode) #presetsMenuBar, body:not(.presetsMode) #presetsToolbar {
  display: none !important;
}
.menuBar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 14px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.menuBarBtn {
  position: relative;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px 6px 0 0;
  padding: 5px 12px;
  color: var(--dim);
  font-weight: 500;
}
.menuBarBtn:hover, .menuBarBtn.open {
  color: var(--text);
  background: var(--bg);
  border-color: var(--border) var(--border) transparent;
}
.menuDropdown {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 90;
  min-width: 15em;
  margin-top: 1px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 0 8px 8px 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
  padding: 4px;
  flex-direction: column;
  gap: 1px;
}
.menuDropdown.open {
  display: flex;
}
.menuBarBtn + .menuDropdown {
  /* dropdown is the trigger's next sibling, but positioned relative to a
     positioned ancestor -- .menuBar itself, so it hangs directly under
     its own trigger button regardless of DOM/flow position */
  position: absolute;
}
.menuBar {
  position: relative;
}
.menuItem {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: transparent;
  text-align: left;
  border-radius: 5px;
  padding: 6px 9px;
  white-space: nowrap;
  width: 100%;
}
.menuItem:hover:not([disabled]) {
  background: var(--accent-soft);
  border-color: transparent;
}
.menuItem[disabled] {
  opacity: 0.4;
  cursor: default;
}
.menuItemRow {
  justify-content: space-between;
  cursor: default;
}
.menuSep {
  height: 1px;
  background: var(--border);
  margin: 4px 2px;
}
.toolbar {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 14px;
  background: var(--bg);
  flex-wrap: nowrap;
  /* No overflow:hidden here -- the reflow engine (see toolbar.js) keeps
     this row's content within its own width by moving items into the
     overflow dropdown, so this box itself never needs to clip. Clipping
     here would also cut off the dropdown itself, since it's an absolutely
     positioned descendant of this row. */
  min-width: 0;
}
.toolbar.tbCollapsed {
  display: none;
}
.tbItem {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: none;
}
.tbSpacer {
  flex: 1 1 auto;
  min-width: 0;
}
.tbSep {
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 0 2px;
}
.tbIcon {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}
.tbCheckIcon {
  width: 14px;
  height: 14px;
  color: var(--dim);
}
.tbIconBtn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text);
}
.tbIconBtn:hover {
  border-color: transparent;
  background: var(--accent-soft);
}
.tbIconBtn.primary {
  background: var(--accent);
  color: #fff;
}
.tbIconBtn.active {
  background: var(--accent);
  border-color: transparent;
  color: #fff;
}
.tbTextBtn {
  padding: 3px 8px;
}
.tbSearchGroup {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 3px 1px 1px;
  background: var(--panel);
}
.tbSearchGroup input {
  border: 0;
  background: transparent;
  padding: 2px 4px;
  font-size: 0.92em;
}
.tbMoreWrap, .tbCollapseWrap {
  position: relative;
  flex: none;
}
.menuBarCollapseWrap {
  margin-left: auto;
  align-self: center;
}
/* Smaller controls throughout the toolbar/menu-bar rows -- the file-name
   display is exempt on purpose (kept at its normal reading size). */
.toolbar select,
.toolbar button:not(.tbIconBtn):not(.tbTextBtn),
.menuBar select {
  padding: 3px 7px;
  font-size: 0.92em;
}
.toolbar input[type="number"] {
  padding: 3px 5px;
  font-size: 0.92em;
}
/* Menu bar (File/Edit/Layer/View/Tools) deactivated for now on all 3 pages
   -- not needed yet. Markup/JS untouched; delete this rule to bring it
   back. The collapse chevron stays working since it isn't a .menuBarBtn. */
.menuBarBtn, .menuDropdown {
  display: none !important;
}
.tbOverflowMenu {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 90;
  min-width: 14em;
  max-width: 26em;
  margin-top: 4px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
  padding: 6px;
  flex-flow: row wrap;
  gap: 6px;
  max-height: 70vh;
  overflow-y: auto;
}
.tbOverflowMenu.open {
  display: flex;
}
#themeBtn {
  border-radius: 50%;
  width: 27px;
  height: 27px;
  padding: 0;
  font-size: 14px;
  flex: none;
}
#docsBtn {
  font-weight: 700;
  border-radius: 50%;
  width: 27px;
  height: 27px;
  padding: 0;
  flex: none;
}
#avatarWrap {
  position: relative;
  flex: none;
}
#avatarBtn {
  border-radius: 50%;
  width: 27px;
  height: 27px;
  padding: 0;
  font-size: 12px;
  font-weight: 700;
  flex: none;
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  overflow: hidden;
}
#avatarBtn:hover {
  opacity: 0.88;
  border-color: var(--accent);
}
#avatarBtn img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
#avatarMenu {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 80;
  min-width: 9em;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
  padding: 4px;
  flex-direction: column;
  gap: 2px;
}
#avatarMenu.open {
  display: flex;
}
#avatarMenu button {
  border: 0;
  background: transparent;
  text-align: left;
  border-radius: 5px;
  padding: 6px 8px;
}
#avatarMenu button:hover {
  background: var(--accent-soft);
  border-color: transparent;
}
#avatarUserLabel {
  padding: 6px 8px 8px;
  font-size: 0.85em;
  font-weight: 600;
  color: var(--dim);
  border-bottom: 1px solid var(--border);
  margin-bottom: 2px;
  white-space: nowrap;
}
.zoomGroup {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--dim);
}
.zoomGroup button {
  padding: 3px 10px;
}
.zoomGroup span.val {
  min-width: 2.8em;
  text-align: center;
  color: var(--text);
}
button,
select,
input {
  font: inherit;
  color: var(--text);
  background: var(--field);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 9px;
}
button {
  cursor: pointer;
}
button:hover {
  border-color: var(--accent);
}
button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
button:disabled {
  opacity: 0.4;
  cursor: default;
}
input[type="number"] {
  width: 4.2em;
}
#histLabel {
  color: var(--dim);
  min-width: 3.2em;
  text-align: center;
}
.mini {
  font-size: 11px;
  color: var(--dim);
}
.fieldGroup {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.fieldLabel {
  font-size: 11px;
  color: var(--dim);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
/* Reusable −/value/+ stepper (no slider) -- e.g. the Presets page's image
   size setting. */
.stepperCtl {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.stepperCtl button {
  padding: 2px 9px;
  line-height: 1.4;
}
.stepperCtl span {
  min-width: 3.4em;
  text-align: center;
  font-size: 11px;
  color: var(--dim);
}
.segmented {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.segmented .segBtn {
  border: 0;
  border-radius: 0;
  padding: 4px 11px;
}
.segmented .segBtn + .segBtn {
  border-left: 1px solid var(--border);
}
.segmented .segBtn.active {
  background: var(--accent);
  color: #fff;
}
.checkField {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 8px;
  cursor: pointer;
}
.checkField input {
  width: auto;
  padding: 0;
  cursor: pointer;
}
#scoreNameDisplay {
  padding: 4px 9px;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: text;
  font-weight: 600;
  white-space: nowrap;
}
#scoreNameDisplay:hover {
  border-color: var(--border);
}
#scoreName {
  width: 14em;
}
#findInput {
  width: 9em;
}

/* ---------- main split ---------- */
#main {
  flex: 1;
  display: grid;
  min-height: 0;
}
body[data-layout="right"] #main {
  grid-template-columns: 1fr 6px minmax(280px, var(--editor-size, 34%));
}
body[data-layout="bottom"] #main {
  grid-template-rows: 1fr 6px minmax(140px, var(--editor-size, 30%));
}
body.codeHidden #main {
  grid-template-columns: 1fr !important;
  grid-template-rows: 1fr !important;
}
body.codeHidden #editorPane,
body.codeHidden #splitHandle {
  display: none !important;
}
#splitHandle {
  background: transparent;
  position: relative;
  z-index: 3;
}
#splitHandle::after {
  content: "";
  position: absolute;
  background: var(--border);
}
body[data-layout="right"] #splitHandle {
  cursor: col-resize;
}
body[data-layout="right"] #splitHandle::after {
  left: 2px;
  top: 0;
  width: 2px;
  height: 100%;
}
body[data-layout="bottom"] #splitHandle {
  cursor: row-resize;
}
body[data-layout="bottom"] #splitHandle::after {
  top: 2px;
  left: 0;
  height: 2px;
  width: 100%;
}
#splitHandle:hover::after,
#splitHandle.dragging::after {
  background: var(--accent);
}
@media (max-width: 760px) {
  body:not(.codeHidden) #main {
    display: grid;
    grid-template-columns: none !important;
    grid-template-rows: 1fr 6px minmax(160px, var(--editor-size, 40%)) !important;
  }
  body[data-layout] #splitHandle {
    cursor: row-resize;
  }
  body[data-layout] #splitHandle::after {
    top: 2px;
    left: 0;
    height: 2px;
    width: 100%;
  }
}

/* ---------- preview ---------- */
#previewPane {
  position: relative;
  overflow: hidden;
  /* deliberately its own shade, not --bg -- the ribbon/menus above use --bg,
     so the canvas needs a visibly different backdrop or the chrome and the
     work area read as one undifferentiated gray block */
  background: var(--canvas);
}
#previewCanvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
#previewSvg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;
  cursor: grab;
  background: transparent;
}
#previewSvg.panning {
  cursor: grabbing;
}
.page {
  fill: var(--paper);
}
.glyph {
  fill: var(--ink);
}
body .glyph.hl {
  fill: var(--accent);
}
body .glyph.flash {
  fill: var(--accent);
}
body .glyph.sel {
  fill: var(--accent);
}
.hit {
  fill: transparent;
  cursor: pointer;
}
/* Selection box: a persistent outline behind the selected glyph, distinct
     from the transient .hl (hover) / .flash (jump) recolors above — those
     disappear in a moment, so the selection needs its own, un-missable
     marker. vector-effect keeps the stroke a constant on-screen width
     regardless of canvas zoom. */
#selBox {
  fill: var(--accent-soft);
  stroke: var(--accent);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
  visibility: hidden;
}
/* Placeholder mark for a hovered/selected "-" (course-skip): it draws no
   ink of its own by design, so without this there's nothing to see at
   all. Same orange as the rest of the app's highlight accents. */
#dashMarker {
  fill: var(--tok-cmd);
  pointer-events: none;
}
.wrapmark {
  fill: #e33;
}
/* Hover locator: a small fixed-size arrow pointing down at whatever glyph
     is currently hovered, on canvas OR in the code editor — unlike the .hl
     recolor (which scales/blends with the glyph and gets lost in dense
     tablature), this stays a constant screen size and sits clear of the
     ink, so the hovered element is easy to spot at a glance. Positioned in
     JS (updateHoverArrow) from the hovered glyph's getBoundingClientRect. */
#hoverArrow {
  position: fixed;
  width: 0;
  height: 0;
  z-index: 6;
  pointer-events: none;
  border-left: 11px solid transparent;
  border-right: 11px solid transparent;
  border-top: 18px solid var(--tok-cmd);
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.4));
  opacity: 0;
  transform: translateY(-16px);
  transition:
    opacity 0.25s ease,
    transform 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
}
#hoverArrow.reset {
  transition: none;
}
#hoverArrow.show {
  opacity: 1;
  transform: translateY(0);
}
/* Per-line "edit mode" Save/Discard controls -- plain fixed-position HTML
   (not SVG content), same reasoning as #hoverArrow: a constant on-screen
   size regardless of the current page zoom. One pill sits at the top-right
   corner of whichever line's editLineBorder frame is currently open;
   Save keeps that line's edits, Discard reverts them -- either way the
   line drops back to the cheap read-only canvas painting. */
#lineEditControls {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.lineEditActions {
  position: fixed;
  transform: translate(-100%, 6px);
  display: flex;
  gap: 4px;
  padding: 3px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 7px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  pointer-events: auto;
  z-index: 6;
}
.lineEditActions button {
  padding: 2px 8px;
  font-size: 11px;
  line-height: 1.4;
}
.lineEditSave {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
/* Appears in the canvas's own top-right corner whenever at least one line
   is open for editing -- batch equivalents of the per-line controls above. */
#canvasEditControls {
  position: absolute;
  top: 8px;
  right: 10px;
  display: none;
  gap: 4px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 4px 6px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  z-index: 5;
}
#canvasEditControls button {
  padding: 2px 10px;
  line-height: 1.4;
}
#saveAllLinesBtn {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
/* Non-interactive outline around whichever line is currently in edit mode
   -- an SVG overlay, not a real CSS border/outline, so it can never add or
   remove layout pixels; it just draws on top of the existing content. */
.editLineBorder {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
/* Per-line manual arrange pills (see score/line-arrange.js) -- same fixed-
   on-screen-size host idiom as #lineEditControls, anchored at the page's
   left edge and pulled fully outside it via the transform below so it
   never overlaps the notation itself, regardless of a line's own dx. */
#lineArrangeControls {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.lineArrangePill {
  position: fixed;
  transform: translate(calc(-100% - 8px), -50%);
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 5px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 7px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  pointer-events: auto;
  z-index: 6;
}
.laRow {
  display: flex;
  align-items: center;
  gap: 3px;
}
.laBtn {
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid transparent;
  background: transparent;
  color: var(--dim);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
}
.laBtn:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.laLabel {
  font-size: 10px;
  color: var(--dim);
  width: 34px;
  flex: none;
}
.lineArrangePill .stepperCtl span {
  min-width: 30px;
  text-align: center;
  font-size: 10px;
}
.laReset {
  font-size: 10px;
  padding: 3px 0;
  color: var(--dim);
  border: 1px dashed var(--border);
  border-radius: 5px;
  background: transparent;
}
.laReset:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* ---------- text boxes (see score/textboxes.js) ---------- */
/* A second SVG stacked exactly over #previewSvg, kept in the same viewBox
   (see applyView) -- separate from #previewSvg on purpose, since that one's
   innerHTML gets wiped and rebuilt on every shape/render pass (every
   keystroke in the code editor); doing that to a live contenteditable box
   would drop focus/cursor/selection mid-type. pointer-events:none at the
   layer level so empty canvas area still passes clicks through to
   pan/zoom underneath -- only the boxes themselves (and the fixed-size
   chrome overlay below) opt back in. */
#textboxSvg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
#textboxSvg foreignObject {
  pointer-events: auto;
  overflow: visible;
}
.tbBox {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  overflow: visible;
  outline: none;
  cursor: text;
  white-space: pre-wrap;
  word-wrap: break-word;
  /* "dlig" (discretionary ligatures) is off by default in every rendering
     engine unless a font/app opts in -- turning it on here is what makes a
     user-authored ligature (sources/text_ligatures.py, built into the
     compiled font's "dlig" GSUB feature by tools/text_build.py) actually
     fire when its trigger sequence is typed. Harmless for any font that
     defines no "dlig" rules at all. */
  font-feature-settings: "dlig" 1;
}
/* Dark-mode override for live text boxes (never applied to print.js's own
   throwaway divs -- see textboxes.js's tbApplyStyle). A box's colors are
   literal hex picked against a white printed page, so on-screen in dark
   mode they're replaced with the same theme-aware tones the note glyphs
   use, regardless of what's actually stored. The "*" arm is required
   because per-selection color changes land as inline <span style="color">
   inside the box's own html -- a descendant's inline style otherwise beats
   any color set on this container, dark override or not. */
.tbDarkOverride,
.tbDarkOverride * {
  color: var(--ink) !important;
}
.tbDarkOverride {
  background: transparent !important;
  border-color: var(--border) !important;
}
/* Active-box outline (plain black) and the boundary helper for borderless
   boxes (faint, toggled by #tbBoundsToggleBtn) are both set as an inline
   box-shadow instead of living here -- see textboxes.js's tbIndicatorStyle.
   A flat CSS "1px" would scale with the page like everything else inside
   the foreignObject (same mechanism the real font-size fix relies on), so
   it needs to be divided by the current zoom in JS to stay a true constant
   screen px instead of turning into a thick smear once zoomed in. */
/* Fixed-px chrome (drag handle / resize / delete) -- plain HTML, same
   reasoning as #lineEditControls/#hoverArrow: constant on-screen size
   regardless of page zoom. Positioned in JS (renderTextboxChrome) from the
   active box's own getBoundingClientRect, so it tracks pan/zoom/scroll
   without needing its own mm math. Styled like the app's other floating
   chrome (.lineEditActions/.cornerZoom) rather than a solid color block,
   for the same "quiet until you need it" feel. */
#textboxChrome {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.tbHandleBar {
  position: fixed;
  display: flex;
  align-items: center;
  gap: 1px;
  height: 20px;
  padding: 0 2px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  transform: translate(-2px, calc(-100% - 5px));
  cursor: move;
  pointer-events: auto;
  z-index: 6;
}
.tbHandleBar::before {
  content: "";
  width: 10px;
  height: 10px;
  margin: 0 1px 0 2px;
  flex: none;
  background: var(--dim);
  opacity: 0.55;
  -webkit-mask: radial-gradient(circle, currentColor 1.1px, transparent 1.3px) 0 0/5px 5px;
  mask: radial-gradient(circle, currentColor 1.1px, transparent 1.3px) 0 0/5px 5px;
}
.tbHandleBar button {
  width: 17px;
  height: 17px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--dim);
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  font-size: 11px;
  border-radius: 4px;
}
.tbHandleBar button:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.tbResizeHandle {
  position: fixed;
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  background: var(--panel);
  border: 1.5px solid var(--accent);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  cursor: nwse-resize;
  pointer-events: auto;
  z-index: 6;
}
/* Custom text caret (see textboxes.js's renderTbCaret) -- the native one is
   hidden (caret-color:transparent on .tbBox) since its device-pixel width
   doesn't scale with font-size inside a zoomed foreignObject and ends up
   looking like a thick, oversized bar next to whatever size text is
   actually set. This one is sized directly from the selection's own real
   getClientRects() height, so it's always exactly line-height tall and a
   true 1 screen px wide regardless of zoom. */
.tbCaret {
  position: fixed;
  width: 1px;
  pointer-events: none;
  z-index: 6;
  animation: tbCaretBlink 1s step-end infinite;
}
@keyframes tbCaretBlink {
  50% { opacity: 0; }
}
/* Image boxes (initials, or any placed picture) -- same foreignObject shell
   as a text box, an <img> instead of a contenteditable div inside. Dragging
   happens via the box itself, so the native img drag-ghost is turned off. */
.tbImgBox {
  display: flex;
  cursor: move;
}
.tbImg {
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}
/* Music boxes (see musicbox.js) -- inner <svg> of shaped glyph paths,
   theme-aware fill like the main score's own notation (compare
   tbApplyStyle's forPrint override, which is why print.js's own rebuild
   sets a literal fill="#111" on the svg root instead of using this class). */
.tbMusicBox {
  cursor: move;
}
.tbMusicSvg {
  width: 100%;
  height: 100%;
  display: block;
  fill: var(--ink);
}
/* "Edit notation" popup (see musicbox.js's renderMbEditPopup) -- a plain
   textarea bound to the box's own text, independent of the main code
   editor/gutter/mirror. */
.mbEditPopup {
  position: fixed;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 8px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
  pointer-events: auto;
  z-index: 8;
  width: 220px;
}
.mbEditHint {
  font-size: 10px;
  color: var(--dim);
  line-height: 1.4;
}
.mbEditPopup textarea {
  width: 100%;
  height: 100px;
  resize: vertical;
  font: 12px/1.4 ui-monospace, monospace;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 5px 6px;
  box-sizing: border-box;
}
/* Rotate handle -- same fixed-screen-size chrome idiom as .tbResizeHandle,
   just circular-outline instead of solid so it doesn't get mistaken for it. */
.tbRotateHandle {
  position: fixed;
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  background: var(--panel);
  border: 1.5px solid var(--accent);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  cursor: grab;
  pointer-events: auto;
  z-index: 6;
}
.tbRotateHandle:active {
  cursor: grabbing;
}
/* Smart alignment guides (see textboxes.js's renderTbGuides) -- a thin
   accent-colored line spanning the whole preview pane at the matched
   edge/center, same visual language Figma/Keynote/PowerPoint use. */
.tbGuideLine {
  position: fixed;
  background: var(--accent);
  pointer-events: none;
  z-index: 7;
}
.tbGuideLineV { width: 1px; }
.tbGuideLineH { height: 1px; }
/* Position & size popup (see textboxes.js's renderTbPosPopup) -- opened via
   the ⌖ button in .tbHandleBar, one numeric field per box property. */
.tbPosPopup {
  position: fixed;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 7px 9px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
  pointer-events: auto;
  z-index: 8;
  font-size: 11px;
}
.tbPosPopup label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  color: var(--dim);
  white-space: nowrap;
}
.tbPosPopup input {
  width: 56px;
}
/* Image boxes have no typographic properties -- the format bar's font/size/
   spacing/line-height/text-color/bold/italic/underline groups only make
   sense for a text box, so they're hidden while the active box is an image
   (see textboxes.js's setActiveTextbox). Background/border stay visible --
   still meaningful as a frame around a picture. */
#textFormatBar.tbImgMode .tbTextOnly {
  display: none;
}

/* Add-image picker (see textboxes.js's tbOpenImagePicker) -- library tab
   (folders + resizable thumbnail grid, same idea as Initials mode's own
   gallery but fetched independently), upload tab, URL tab. */
#tbImagePickerPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  width: 640px;
  max-width: 92vw;
  height: 520px;
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
#tbImagePickerTabs {
  display: flex;
  gap: 4px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
.tbPickerTabBtn {
  padding: 7px 12px;
  border: 0;
  background: transparent;
  color: var(--dim);
  border-bottom: 2px solid transparent;
  font: inherit;
  cursor: pointer;
}
.tbPickerTabBtn:hover {
  color: var(--fg);
}
.tbPickerTabBtn.active {
  color: var(--fg);
  border-bottom-color: var(--accent);
}
.tbPickerPane {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.tbPickerPane[hidden] {
  display: none;
}
#tbPickerLibraryBody {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: 12px;
}
#tbPickerFolderList {
  width: 150px;
  flex: none;
  overflow-y: auto;
  border-right: 1px solid var(--border);
  padding-right: 10px;
}
.tbPickerFolderRow {
  padding: 5px 7px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.9em;
  color: var(--dim);
}
.tbPickerFolderRow:hover {
  background: var(--accent-soft);
}
.tbPickerFolderRow.active {
  background: var(--accent-soft);
  color: var(--accent);
}
#tbPickerGalleryCol {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
#tbPickerGalleryHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 8px;
  color: var(--dim);
  font-size: 0.9em;
}
#tbPickerGalleryGrid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tbPickerThumbPx, 88px), 1fr));
  gap: 8px;
  align-content: start;
}
.tbPickerThumb {
  position: relative;
  aspect-ratio: 1;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
  background: var(--bg);
}
.tbPickerThumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.tbPickerThumb:hover {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.tbPickerHint {
  color: var(--dim);
  font-size: 0.9em;
}
#tbPickerPaneUpload,
#tbPickerPaneUrl {
  gap: 10px;
  padding-top: 6px;
}
#tbPickerUrlBtnRow {
  margin-top: 4px;
}
#textFormatBar select,
#textFormatBar input[type="number"] {
  width: auto;
}
#textFormatBar input[type="color"] {
  width: 22px;
  height: 22px;
  padding: 1px;
  vertical-align: middle;
  border-radius: 5px;
}
#textFormatBar label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--dim);
}
#previewHint {
  position: absolute;
  left: 10px;
  bottom: 8px;
  font-size: 11px;
  color: var(--dim);
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 3px 8px;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0.9;
  max-width: min(70%, 32em);
}
#shapeErr {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  background: #c0392b;
  color: #fff;
  padding: 4px 12px;
  border-radius: 6px;
  display: none;
}
.cornerZoom {
  position: absolute;
  right: 10px;
  bottom: 8px;
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 3px 6px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  z-index: 5;
}
.cornerZoom button {
  padding: 2px 10px;
  line-height: 1.4;
}
#cornerCodeToggleBtn {
  width: 24px;
  height: 24px;
  padding: 0;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}
#cornerCodeToggleBtn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.cornerZoom span {
  min-width: 3em;
  text-align: center;
  font-size: 11px;
  color: var(--dim);
}

/* ---------- preset quick-insert toolbar ---------- */
/* Author's own `display: grid` below beats the UA [hidden] rule on
   specificity (both are single-selector -- ID vs attribute -- so without
   this the toolbar stayed visible as an empty bordered box whenever
   box.hidden was set). */
#presetToolbar[hidden] {
  display: none;
}
#presetToolbar {
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 9px;
  /* extra top padding -- a bit of breathing room above the switcher/first
     tool, so content doesn't start flush against the toolbar's own border */
  padding: 10px 6px 6px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  max-height: calc(100% - 20px);
  overflow-y: auto;
  /* hidden scrollbar -- still scrollable, just not shown (Firefox + WebKit) */
  scrollbar-width: none;
}
#presetToolbar::-webkit-scrollbar {
  display: none;
}
.ptToolbarCta {
  white-space: nowrap;
  font-size: 12px;
  padding: 6px 10px;
}
.ptIconGrid {
  display: grid;
  grid-template-columns: repeat(var(--pt-cols, 1), var(--pt-btn-size, 36px));
  grid-auto-flow: row;
  gap: 6px;
}
/* ‹ N/total › package switcher -- lets a font with several independent
   preset packages (see preset-toolbar.js's own state comment) page between
   them; always shown once at least one exists, even just one. */
.ptPkgSwitcher {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2px;
}
.ptPkgSwitcher button {
  flex: none;
  border: 0;
  background: transparent;
  color: var(--dim);
  font-weight: 700;
  font-size: 15px;
  line-height: 1;
  padding: 3px 4px;
  border-radius: 5px;
}
.ptPkgSwitcher button:hover {
  background: var(--accent-soft);
  color: var(--text);
}
.ptPkgLabel {
  flex: 1;
  min-width: 0;
  text-align: center;
  font-size: 10px;
  color: var(--dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Icons under 50px: label no longer fits without forcing the toolbar
   wider than the icon grid -- keep just the prev/next arrows. */
.ptCompactSwitcher .ptPkgLabel {
  display: none;
}
.ptCompactSwitcher .ptPkgSwitcher {
  justify-content: center;
  gap: 6px;
}
.ptToolBtn {
  flex: none;
  box-sizing: border-box;
  width: var(--pt-btn-size, 36px);
  height: var(--pt-btn-size, 36px);
  /* Scales with the button instead of a fixed px -- a full-bleed glyph
     against the border reads fine at 64px but looks broken (strokes
     touching the edge) once the slider shrinks the button toward 24px, so
     the margin has to shrink proportionally with it, not stay at 0. */
  padding: max(2px, calc(var(--pt-btn-size, 36px) * 0.14));
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #f2f3f5;
}
body[data-theme="dark"] .ptToolBtn {
  background: #333538;
}
.ptToolBtn svg.ptThumb,
.ptCell svg.ptThumb {
  width: 100%;
  height: 100%;
}
.ptToolBtn svg.ptThumb *,
.ptCell svg.ptThumb * {
  fill: #1a1a1a;
}
body[data-theme="dark"] .ptToolBtn svg.ptThumb *,
body[data-theme="dark"] .ptCell svg.ptThumb * {
  fill: #c9cdd2;
}
.ptToolBtn img.ptIconImg {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

#presetPopupLayer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 20;
}
.ptPopup {
  position: fixed;
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  width: 250px;
  height: 400px;
  min-width: 200px;
  min-height: 220px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 9px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);
  overflow: hidden;
}
.ptPopup.pinned {
  resize: both;
}
.ptPopupHead {
  flex: none;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 6px 6px 10px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  font-size: 13px;
}
.ptPopup.pinned .ptPopupHead {
  cursor: move;
}
.ptPopupTitle {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ptPopupHead button {
  flex: none;
  border: 0;
  background: transparent;
  padding: 2px 6px;
}
.ptPopupPinBtn.active {
  background: var(--accent-soft);
  border-radius: 5px;
}
/* Pinned: close btn gone (must unpin to close), pin btn moves out of the
   head flow into the popup's own corner as a small overlay badge. */
.ptPopup.pinned .ptPopupCloseBtn {
  display: none;
}
.ptPopup.pinned .ptPopupPinBtn {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 1;
}
.ptPopupCrumbs {
  flex: none;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  font-size: 11.5px;
}
.ptCrumbSep {
  color: var(--dim);
}
.ptCrumbBtn {
  border: 0;
  background: transparent;
  color: var(--dim);
  padding: 1px 3px;
  border-radius: 4px;
}
.ptCrumbBtn:not(:disabled):hover {
  color: var(--text);
  background: var(--accent-soft);
}
.ptCrumbBtn:disabled {
  color: var(--text);
  font-weight: 600;
}
.ptPopupGridWrap {
  flex: 1;
  min-height: 0;
  position: relative;
  overflow: hidden;
}
.ptPopupGrid {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 6px;
  padding: 8px;
}
.ptCell {
  flex: none;
  box-sizing: border-box;
  width: var(--pt-thumb, 50px);
  height: var(--pt-thumb, 50px);
  /* Same proportional-margin reasoning as .ptToolBtn above -- these cells
     zoom from 30px to 110px, so a fixed padding would be too tight at one
     end or too wasteful at the other. */
  padding: max(2px, calc(var(--pt-thumb, 50px) * 0.14));
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #f2f3f5;
}
body[data-theme="dark"] .ptCell {
  background: #333538;
}
.ptCellDisabled {
  opacity: 0.35;
  cursor: default;
}
.ptEmptyHint {
  color: var(--dim);
  font-size: 12px;
}
.ptPopupFoot {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 6px 8px;
  border-top: 1px solid var(--border);
}
.ptSizeCtl {
  flex: none;
  display: flex;
  align-items: center;
  gap: 4px;
}
.ptSizeCtl button {
  padding: 2px 9px;
  line-height: 1.4;
}
.ptPopupSizeLabel {
  min-width: 3.4em;
  text-align: center;
  font-size: 11px;
  color: var(--dim);
}

/* ---------- editor ---------- */
#editorPane {
  position: relative;
  border-left: 1px solid var(--border);
  border-top: 1px solid var(--border);
  background: var(--panel);
  min-height: 0;
}
#gutter,
#gutterInner,
#mirror,
#input {
  font-size: var(--code-size);
  line-height: 1.9;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-ligatures: none;
}
#gutter {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--gutter-w, 2.6em);
  overflow: hidden;
  background: var(--panel);
  border-right: 1px solid var(--border);
  z-index: 0;
  pointer-events: none;
  user-select: none;
}
#gutterInner {
  position: relative;
  height: 100%;
  padding: 12px 6px 12px 0;
  text-align: right;
  color: var(--dim);
  white-space: pre;
}
#gutterInner .gline {
  display: block;
}
#gutterInner .gline.abs {
  position: absolute;
  left: 0;
  right: 6px;
  display: block;
  text-align: right;
}
/* Light full-width background behind whichever code line is in edit mode
   -- wraps the whole line's text as a block span (see renderLineHtml), so
   it stretches to the mirror's own box width regardless of line length. */
#mirror .lineEditingBg {
  display: block;
  min-height: 1em;
  background: rgba(140, 140, 140, 0.18);
}
#mirror,
#input {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: var(--gutter-w, 2.6em);
  margin: 0;
  padding: 12px 14px;
  border: 0;
  white-space: pre;
  overflow: auto;
}
#mirror {
  pointer-events: none;
  z-index: 0;
  color: var(--text);
}
#mirror .lineMark,
#lp_mirror .lineMark {
  background: var(--mark);
  border-radius: 2px;
}
#mirror .charMark,
#lp_mirror .charMark {
  background: var(--mark-strong);
  border-radius: 3px;
}
#mirror .tok-bracket,
#lp_mirror .tok-bracket,
.fb-sandbox-code .tok-bracket,
#fbBig_mirror .tok-bracket {
  color: var(--tok-bracket);
  font-weight: 700;
}
#mirror .tok-fret,
#lp_mirror .tok-fret,
.fb-sandbox-code .tok-fret,
#fbBig_mirror .tok-fret {
  color: var(--tok-fret);
}
#mirror .tok-note,
#lp_mirror .tok-note,
.fb-sandbox-code .tok-note,
#fbBig_mirror .tok-note {
  color: var(--tok-note);
}
#mirror .tok-cmd,
#lp_mirror .tok-cmd,
.fb-sandbox-code .tok-cmd,
#fbBig_mirror .tok-cmd {
  color: var(--tok-cmd);
}
#mirror .tok-num,
#lp_mirror .tok-num,
.fb-sandbox-code .tok-num,
#fbBig_mirror .tok-num {
  color: var(--tok-num);
}
#mirror .tok-bar,
#lp_mirror .tok-bar,
.fb-sandbox-code .tok-bar,
#fbBig_mirror .tok-bar {
  color: var(--tok-bar);
  font-weight: 700;
}
#mirror .tok-punct,
#lp_mirror .tok-punct,
.fb-sandbox-code .tok-punct,
#fbBig_mirror .tok-punct {
  color: var(--tok-punct);
}
#input {
  background: transparent;
  color: transparent;
  caret-color: var(--text);
  resize: none;
  z-index: 1;
  outline: none;
}
#input::selection {
  background: var(--accent-soft);
}
body[data-wrap="on"] #input,
body[data-wrap="on"] #mirror {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow-x: hidden;
}

/* ---------- snippet popup ---------- */
#snippetPopup {
  position: fixed;
  z-index: 60;
  display: none;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
}
#snippetPopup.open {
  display: block;
}
#popupArrow {
  position: absolute;
  width: 12px;
  height: 12px;
  left: 20px;
  background: var(--panel);
  border: 1px solid var(--border);
  transform: rotate(45deg);
}
#popupArrow.arrow-up {
  top: -7px;
  border-right: none;
  border-bottom: none;
}
#popupArrow.arrow-down {
  bottom: -7px;
  border-left: none;
  border-top: none;
}
#popupModeLabel {
  position: absolute;
  top: 2px;
  left: 4px;
  font-size: 9px;
  line-height: 1;
  color: var(--dim);
  text-transform: lowercase;
  pointer-events: none;
  user-select: none;
}
#popupRow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
}
#popupChips {
  display: flex;
  align-items: baseline;
  gap: 3px;
  font:
    var(--popup-font) ui-monospace,
    SFMono-Regular,
    Menlo,
    monospace;
  white-space: pre;
  transition:
    transform 140ms ease,
    opacity 140ms ease;
}
/* Ligature <-> char layer switch (Ctrl/Cmd+ArrowDown/Up): the outgoing
   chips roll away, then the freshly rebuilt layer rolls in from the
   opposite side — see animateChipsSwap() in snippet-popup.js. */
#popupChips.chipsRollOutUp {
  transform: translateY(-10px);
  opacity: 0;
}
#popupChips.chipsRollOutDown {
  transform: translateY(10px);
  opacity: 0;
}
#popupChips.chipsRollInBottom {
  transition: none;
  transform: translateY(10px);
  opacity: 0;
}
#popupChips.chipsRollInTop {
  transition: none;
  transform: translateY(-10px);
  opacity: 0;
}
#popupChips .chip {
  color: var(--dim);
  cursor: pointer;
  padding: 2px 3px;
  border-radius: 4px;
}
#popupChips .chip:hover {
  background: var(--accent-soft);
}
#popupChips .chipSep {
  color: var(--dim);
  opacity: 0.5;
  padding: 0 3px;
}
#popupChips .breakWrap {
  position: relative;
  display: inline-block;
  padding-top: 6px;
}
#popupChips .chipSepBreak {
  cursor: pointer;
  opacity: 0.8;
  border-radius: 4px;
  padding: 2px 3px;
}
#popupChips .chipSepBreak:hover {
  opacity: 1;
  background: #d3332233;
  color: #d33;
}
#popupChips .breakX {
  position: absolute;
  top: -2px;
  right: -4px;
  width: 12px;
  height: 12px;
  line-height: 11px;
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  background: #d33;
  border-radius: 50%;
  cursor: pointer;
  z-index: 1;
  font-family: sans-serif;
}
#popupChips .breakX:hover {
  background: #ff4444;
  transform: scale(1.15);
}
#popupInput,
#popupBreakInput {
  font:
    var(--popup-font) ui-monospace,
    SFMono-Regular,
    Menlo,
    monospace;
  border: 1px solid var(--accent);
  border-radius: 5px;
  padding: 2px 6px;
  color: var(--text);
  background: var(--panel);
  min-width: 1.6em;
}
#popupBreakInput {
  color: var(--dim);
  text-align: center;
  cursor: default;
}
/* ---------- confirm-discard popup ---------- */
#confirmPopup {
  position: fixed;
  z-index: 70;
  display: none;
  background: var(--panel);
  border: 2px solid #d33;
  border-radius: 10px;
  padding: 10px 14px;
  max-width: 230px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
}
#confirmPopup.open {
  display: block;
}
#confirmArrow {
  position: absolute;
  width: 12px;
  height: 12px;
  background: var(--panel);
  transform: rotate(45deg);
}
#confirmArrow.arrow-side {
  left: -7px;
  top: 16px;
  border-left: 2px solid #d33;
  border-bottom: 2px solid #d33;
}
#confirmArrow.arrow-top {
  top: -7px;
  border-top: 2px solid #d33;
  border-left: 2px solid #d33;
}
#confirmArrow.arrow-bottom {
  bottom: -7px;
  border-bottom: 2px solid #d33;
  border-right: 2px solid #d33;
}
.confirmMsg {
  font-weight: 700;
  margin-bottom: 8px;
}
.confirmBtns {
  display: flex;
  gap: 6px;
}
.confirmHint {
  font-size: 11px;
  color: var(--dim);
  margin-top: 8px;
  line-height: 1.4;
}

/* ---------- Tools > Popup size demo preview ---------- */
#popupDemo {
  position: fixed;
  z-index: 65;
  display: none;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
  pointer-events: none;
}
#popupDemo.show {
  display: block;
}
#popupDemo .demoArrow {
  position: absolute;
  width: 12px;
  height: 12px;
  left: 20px;
  top: -7px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-right: none;
  border-bottom: none;
  transform: rotate(45deg);
}
#popupDemo .demoChips {
  display: flex;
  align-items: baseline;
  gap: 3px;
  font:
    var(--popup-font) ui-monospace,
    SFMono-Regular,
    Menlo,
    monospace;
  white-space: pre;
}
#popupDemo .demoChips .chip {
  color: var(--dim);
  padding: 2px 3px;
  border-radius: 4px;
}
#popupDemo .demoChips .chip.sel {
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 5px;
  padding: 2px 6px;
}
#popupDemo .demoHint {
  font-size: 10px;
  color: var(--dim);
  text-align: center;
  margin-top: 6px;
}

/* ---------- Font Editor tab: glyph catalog editor ---------- */
#fontMain {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
body.fontMode #main,
body.presetsMode #main,
body.initialsMode #main {
  display: none;
}
body.fontMode #fontMain {
  display: flex;
}
/* Live preview is a Font Editor tool -- never show it (or its minimized
   pill) while the Score Editor tab is active, regardless of lpMode. */
body:not(.fontMode) #lpPanel,
body:not(.fontMode) #lpMinIcon {
  display: none;
}

.feToolbarRow {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  overflow-x: auto;
  padding: 7px 10px;
}
.feToolbarRow + .feToolbarRow {
  border-top: 1px solid var(--border);
}
.feToolbarRow button {
  padding: 4px 9px;
  font-size: 12px;
  flex: none;
}
.feToolbarRow .sep {
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 0 4px;
  flex: none;
}
.feToolbarRow .checkField {
  padding: 2px 4px;
  font-size: 12px;
  flex: none;
  white-space: nowrap;
}
.feInlineCtl {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--dim);
  flex: none;
}
.feInlineCtl input[type="range"] {
  width: 90px;
}

#fontBody {
  flex: 1;
  display: grid;
  min-height: 0;
  grid-template-columns: 260px 1fr 6px minmax(220px, var(--font-code-size, 30%));
}
body.fontMode.fontCodeHidden #fontBody {
  grid-template-columns: 260px 1fr;
}
body.fontMode.fontCodeHidden #fontCodePane,
body.fontMode.fontCodeHidden #fontSplitHandle {
  display: none;
}

#fontSidebar {
  background: var(--panel);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
  color: var(--text);
}
/* Sticky header: only #fontCatalogList itself scrolls (flex:1 + its own
   overflow-y:auto below), so the search bar never scrolls away. */
#feSidebarTools {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px;
  border-bottom: 1px solid var(--border);
  flex: none;
  position: relative;
}
#fe_sidebarSearch {
  flex: 1;
  min-width: 0;
  border-radius: 999px;
  padding: 5px 12px;
}
#feVisibilityWrap {
  position: relative;
  flex: none;
}
#fe_searchModeBtn,
#fe_toggleAllBtn {
  padding: 4px 9px;
  font-weight: 700;
  line-height: 1;
  flex: none;
}
#fe_searchModeBtn.active {
  background: var(--accent);
  border-color: var(--accent);
}
.feVisAllBtn {
  display: block;
  width: 100%;
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  padding: 5px 8px;
  margin-bottom: 4px;
  border-radius: 6px;
}
#fe_visibilityBtn {
  padding: 4px 9px;
  font-weight: 700;
  line-height: 1;
}
#feVisibilityMenu {
  display: none;
  position: absolute;
  right: 0;
  top: 100%;
  margin-top: 4px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
  z-index: 20;
  min-width: 230px;
  max-height: 60vh;
  overflow-y: auto;
}
#feVisibilityMenu.open {
  display: block;
}
.feVisRow {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px;
  font-size: 12px;
  cursor: pointer;
  border-radius: 5px;
}
.feVisRow:hover {
  background: var(--accent-soft);
}
.feVisRowFont {
  font-weight: 700;
  margin-top: 6px;
}
.feVisRowFont:first-child {
  margin-top: 0;
}
.feVisRowCat {
  padding-left: 22px;
  color: var(--dim);
}
.feVisRow input {
  width: auto;
  padding: 0;
  cursor: pointer;
}
/* Dark mode: readable but not glaring -- a softer light gray instead of
     the near-white body text color, against a dark (not black) panel
     (applyTheme() always sets data-theme, so this is the only rule needed). */
body[data-theme="dark"] #fontSidebar {
  background: #2a2c30;
  color: #b8bcc2;
}
#fontCatalogList {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  padding: 8px;
}
.fontGroup {
  display: block;
}
.fontGroup > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  margin: 0;
  padding: 4px 2px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.fontGroup > summary::-webkit-details-marker {
  display: none;
}
.fontGroup > summary::before {
  content: "▾";
  display: inline-block;
  font-size: 11px;
  transition: transform 0.18s ease;
}
.fontGroup:not([open]) > summary::before {
  transform: rotate(-90deg);
}
.fontGroupBody {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 2px;
  padding-left: 6px;
  border-left: 2px solid var(--border);
}
.fontCategory {
  display: block;
}
.fontCategory > summary {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--dim);
  margin: 0;
  padding: 4px 2px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.fontCategory > summary::-webkit-details-marker {
  display: none;
}
.fontCategory > summary::before {
  content: "▸";
  display: inline-block;
  font-size: 9px;
  transition: transform 0.18s ease;
}
.fontCategory[open] > summary::before {
  transform: rotate(90deg);
}
.fontCategory > .fontItems {
  margin-top: 3px;
}
.fontItems {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}
.fontItems button {
  position: relative;
  padding: 0;
  aspect-ratio: 1;
  overflow: hidden;
}
.fontItems button.active {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent) inset;
}
.fontItems button .name {
  position: absolute;
  top: 3px;
  right: 4px;
  font-size: 10px;
  color: var(--text);
  background: var(--panel);
  padding: 1px 4px;
  border-radius: 4px;
  line-height: 1.4;
  pointer-events: none;
}
.fontItems button.dirty .name::after {
  content: " •";
  color: #e8590c;
}
/* Light theme: ink-on-paper look, soft off-white (not stark #fff).
     Dark theme: matches the app instead of a bright paper cutout -- dark
     gray background, light gray ink. */
.fontItems svg.thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  background: #f2f3f5;
}
.fontItems svg.thumb * {
  fill: #1a1a1a;
}
body[data-theme="dark"] .fontItems svg.thumb {
  background: #333538;
}
body[data-theme="dark"] .fontItems svg.thumb * {
  fill: #c9cdd2;
}
#fe_status {
  font-size: 11px;
  color: var(--dim);
  white-space: pre-wrap;
  padding: 4px 10px;
}

#fontStage {
  position: relative;
  overflow: hidden;
  background: conic-gradient(
      var(--panel) 90deg,
      var(--bg) 90deg 180deg,
      var(--panel) 180deg 270deg,
      var(--bg) 270deg
    )
    0 0/24px 24px;
}
#fe_svgRoot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;
  cursor: default;
}
#fe_svgRoot.panning {
  cursor: grabbing;
}
#fontWelcome {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--dim);
  pointer-events: none;
  text-align: center;
  padding: 0 20px;
}
#fe_canvasSaveBtn {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 6;
  display: none;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
}
#fe_canvasSaveBtn.show {
  display: inline-block;
}
#fontHint {
  position: absolute;
  left: 10px;
  bottom: 8px;
  font-size: 11px;
  color: var(--dim);
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 3px 8px;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0.9;
}
#fe_handleLayer .anchorPt {
  fill: var(--panel);
  stroke: #e8590c;
  cursor: move;
}
#fe_handleLayer .anchorPt.sel {
  fill: #e8590c;
}
#fe_handleLayer .ctlPt {
  fill: var(--panel);
  stroke: var(--accent);
  cursor: move;
}
#fe_handleLayer .ctlLine {
  stroke: var(--accent);
  stroke-opacity: 0.6;
  fill: none;
}
#fe_glyphHolder path {
  cursor: crosshair;
  fill: var(--ink);
}
#fe_rulerLayer {
  pointer-events: none;
}
.fe-ruler-rect {
  fill: none;
  stroke: #1098ad;
  stroke-width: 1.2;
  stroke-dasharray: 4 3;
  vector-effect: non-scaling-stroke;
  opacity: 0.85;
}
.fe-canvas-border {
  stroke: #2f9e44;
  stroke-width: 1.5;
  stroke-dasharray: 5 3;
  pointer-events: none;
}
.fe-ref-movebox {
  fill: transparent;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-dasharray: 3 3;
  cursor: move;
}
.fe-ref-handle {
  fill: var(--accent);
  stroke: #fff;
  stroke-width: 1;
  cursor: nwse-resize;
}
.fe-marquee {
  fill: rgba(156, 54, 181, 0.12);
  stroke: #9c36b5;
  stroke-width: 1.2;
  stroke-dasharray: 4 3;
  pointer-events: none;
}
.fe-box-movebox {
  fill: transparent;
  stroke: #9c36b5;
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  pointer-events: none;
}
.fe-box-handle {
  fill: #9c36b5;
  stroke: #fff;
  stroke-width: 1;
  cursor: nwse-resize;
}

#fontSplitHandle {
  background: transparent;
  position: relative;
  z-index: 3;
  cursor: col-resize;
  grid-column: 3;
}
#fontSplitHandle::after {
  content: "";
  position: absolute;
  background: var(--border);
  left: 2px;
  top: 0;
  width: 2px;
  height: 100%;
}
#fontSplitHandle:hover::after,
#fontSplitHandle.dragging::after {
  background: var(--accent);
}

#fontCodePane {
  position: relative;
  border-left: 1px solid var(--border);
  background: var(--panel);
  min-height: 0;
  grid-column: 4;
}
#fe_gutter,
#fe_gutterInner,
#fe_mirror,
#fe_codeInput {
  font-size: var(--font-code-size-px, 14px);
  line-height: 1.6;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-ligatures: none;
}
#fe_gutter {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 2.6em;
  overflow: hidden;
  background: var(--panel);
  border-right: 1px solid var(--border);
  z-index: 0;
  pointer-events: none;
  user-select: none;
}
#fe_gutterInner {
  padding: 12px 6px 12px 0;
  text-align: right;
  color: var(--dim);
  white-space: pre;
}
#fe_gutterInner {
  position: relative;
  height: 100%;
}
#fe_gutterInner .gline {
  display: block;
}
#fe_gutterInner .gline.abs {
  position: absolute;
  left: 0;
  right: 6px;
  display: block;
  text-align: right;
}
#fe_mirror,
#fe_codeInput {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 2.6em;
  margin: 0;
  padding: 12px 14px;
  border: 0;
  white-space: pre;
  overflow: auto;
}
#fe_mirror {
  pointer-events: none;
  z-index: 0;
  color: var(--text);
}
#fe_mirror .tok-tag {
  color: var(--tok-cmd);
  font-weight: 700;
}
#fe_mirror .tok-attr {
  color: var(--tok-fret);
}
#fe_mirror .tok-string {
  color: var(--tok-note);
}
#fe_mirror .tok-num {
  color: var(--tok-num);
}
#fe_mirror .tok-punct {
  color: var(--tok-punct);
}
#fe_codeInput {
  background: transparent;
  color: transparent;
  caret-color: var(--text);
  resize: none;
  z-index: 1;
  outline: none;
}
#fe_codeInput::selection {
  background: var(--accent-soft);
}
#fe_codeError {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  background: #c0392b;
  color: #fff;
  padding: 3px 10px;
  border-radius: 6px;
  font-size: 11px;
  display: none;
  z-index: 2;
}
body.fontWrapOn #fe_codeInput,
body.fontWrapOn #fe_mirror {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow-x: hidden;
}

.feInlineCtl input[type="number"] {
  background: var(--field);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 5px;
  padding: 3px 6px;
  width: 5.5em;
}

/* ---------- Font Editor: live preview panel ---------- */
#lpPanel {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);
  color: var(--text);
}
#lpPanel.lp-hidden {
  display: none;
}
#lpPanel.lp-float {
  position: fixed;
  z-index: 55;
  border-radius: 8px;
  resize: both;
  overflow: hidden;
  min-width: 300px;
  min-height: 220px;
}
#lpPanel.lp-dock {
  position: static;
  flex: none;
  width: auto;
  height: var(--lp-dock-h, 220px);
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
}
#lpTitlebar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px 8px;
  font-size: 12px;
  font-weight: 600;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  cursor: move;
  user-select: none;
  flex: none;
}
#lpTitlebar button {
  margin-left: auto;
  border: 0;
  background: transparent;
  padding: 2px 6px;
  font-size: 12px;
  cursor: pointer;
  color: var(--dim);
}
#lpTitlebar button + button {
  margin-left: 2px;
}
#lpTitlebar button:hover {
  color: var(--text);
}
#lp_codeToggleBtn.active {
  color: var(--accent);
}
#lpZoomBar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  flex: none;
}
#lpDockHandle {
  display: none;
  position: relative;
  height: 6px;
  flex: none;
  cursor: row-resize;
  background: transparent;
}
#lpPanel.lp-dock #lpDockHandle {
  display: block;
}
#lpDockHandle::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 2px;
  height: 2px;
  background: var(--border);
}
#lpDockHandle:hover::after,
#lpDockHandle.dragging::after {
  background: var(--accent);
}
#lpBody {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
#lpPreviewWrap {
  border-bottom: 1px solid var(--border);
}
#lpInputWrap {
  position: relative;
  flex: none;
  height: 5.5em;
}
#lpSplitHandle {
  display: none;
}
#lpPanel.lp-codeHidden #lpInputWrap,
#lpPanel.lp-codeHidden #lp_codeZoomGroup,
#lpPanel.lp-codeHidden #lpSplitHandle {
  display: none;
}
#lpPanel.lp-codeHidden #lpPreviewWrap {
  border-bottom: 0;
}
#lpCodeToggleCorner {
  z-index: 6;
}
/* Above ~600px of panel width, lay preview and code side by side
   (preview left, code right) instead of stacked -- the docked strip
   is almost always this wide, floating panels only once resized up. */
#lpPanel {
  container-type: inline-size;
  container-name: lp;
}
@container lp (min-width: 600px) {
  #lpBody {
    flex-direction: row;
  }
  #lpPreviewWrap {
    border-bottom: 0;
  }
  #lpInputWrap {
    height: auto;
    width: var(--lp-code-w, 320px);
  }
  #lpPanel:not(.lp-codeHidden) #lpSplitHandle {
    display: block;
    flex: none;
    width: 6px;
    cursor: col-resize;
    background: transparent;
    position: relative;
  }
  #lpSplitHandle::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 2px;
    width: 2px;
    background: var(--border);
  }
  #lpSplitHandle:hover::after,
  #lpSplitHandle.dragging::after {
    background: var(--accent);
  }
}
#lp_gutter,
#lp_gutterInner,
#lp_mirror,
#lp_input {
  font-size: var(--lp-code-size, 12.5px);
  line-height: 1.5;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-ligatures: none;
}
#lp_gutter {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--lp-gutter-w, 2.2em);
  overflow: hidden;
  background: var(--panel);
  border-right: 1px solid var(--border);
  pointer-events: none;
  user-select: none;
}
#lp_gutterInner {
  padding: 8px 5px 8px 0;
  text-align: right;
  color: var(--dim);
  white-space: pre;
}
#lp_gutterInner .gline {
  display: block;
}
#lp_mirror,
#lp_input {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: var(--lp-gutter-w, 2.2em);
  margin: 0;
  padding: 8px 10px;
  border: 0;
  white-space: pre;
  overflow: auto;
}
#lp_mirror {
  pointer-events: none;
  z-index: 0;
  color: var(--text);
}
#lp_input {
  background: transparent;
  color: transparent;
  caret-color: var(--text);
  resize: none;
  z-index: 1;
  outline: none;
}
#lpPreviewWrap {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: auto;
  background: var(--paper);
}
#lpSvg {
  display: block;
}
#lpSvg .glyph {
  cursor: default;
}
#lp_error {
  position: absolute;
  bottom: 6px;
  left: 50%;
  transform: translateX(-50%);
  background: #c0392b;
  color: #fff;
  padding: 3px 10px;
  border-radius: 6px;
  font-size: 11px;
  display: none;
  z-index: 2;
}
#lpMinIcon {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 55;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  padding: 7px 14px;
  font-size: 12px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
  cursor: pointer;
}

.feOverlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 90;
}
.feOverlay.open {
  display: flex;
}
#feRefPopup,
#feNewFontPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  min-width: 300px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
.fePopupHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 600;
  margin-bottom: 10px;
}
.fePopupHead button {
  border: 0;
  background: transparent;
  padding: 2px 6px;
}
#fe_refDropZone {
  border: 2px dashed var(--border);
  border-radius: 8px;
  padding: 28px 20px;
  text-align: center;
  color: var(--dim);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition:
    border-color 0.15s,
    background 0.15s;
}
#fe_refDropZone.dragover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

#feNewFontForm {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 320px;
}
.feNewFontField {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.9em;
  color: var(--dim);
}
.feNewFontField input[type="text"],
.feNewFontField select {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
}
#feNewFontForm .checkField {
  align-items: flex-start;
  font-size: 0.9em;
}

/* ---------- Font Library (Manage Fonts popup) ---------- */
.flPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  min-width: 360px;
  max-width: 480px;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
.flFontList {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 50vh;
  overflow-y: auto;
  margin-bottom: 12px;
}
.flFontRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}
.flFontRow:hover {
  background: var(--accent-soft);
}
.flFontName {
  font-weight: 600;
}
.flFontMeta {
  font-size: 0.85em;
  color: var(--dim);
}
.flRowChevron {
  color: var(--dim);
  font-size: 1.2em;
  flex-shrink: 0;
}
.flEmpty {
  color: var(--dim);
  font-size: 0.9em;
  padding: 8px 10px;
}
.flTierDot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  flex-shrink: 0;
}
.flTierGreen { background: #22c55e; }
.flTierOrange { background: #f97316; }
.flTierRed { background: #ef4444; }
.flTierUnknown { background: var(--dim); }
.flTierText {
  font-weight: 600;
  font-size: 0.9em;
}
.flTierText.flTierGreen { color: #16a34a; background: none; }
.flTierText.flTierOrange { color: #ea580c; background: none; }
.flTierText.flTierRed { color: #dc2626; background: none; }
.flDetailForm {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 320px;
}
.flStaticField {
  color: var(--fg);
  font-size: 0.95em;
}
.flHelpText {
  font-size: 0.85em;
  color: var(--dim);
  margin: 0;
}
.flTierPickerBtns {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.flTierPickerBtns button {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  padding: 4px 8px;
  font-size: 0.85em;
  cursor: pointer;
}
.flTierPickerBtns button.active {
  border-color: var(--accent);
  background: var(--accent-soft);
  font-weight: 600;
}
.flFormActions {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
}
#fe_newFontCreateBtn {
  align-self: flex-end;
  margin-top: 4px;
}
.fePopupSmall {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  min-width: 320px;
  max-width: 420px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
.feLigAddRow {
  display: flex;
  gap: 6px;
  margin: 10px 0;
}
.feLigAddRow input[type="text"] {
  flex: 1 1 auto;
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  min-width: 0;
}
.feLigAddRow select {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  max-width: 40%;
}
.feLigError {
  color: #dc2626 !important;
}
.feLigList {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 22vh;
  overflow-y: auto;
  margin-bottom: 10px;
}
.feLigRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.9em;
}
.feLigRow .feLigTrigger {
  font-family: ui-monospace, Menlo, monospace;
  font-weight: 600;
}
.feLigRow .feLigArrow {
  color: var(--dim);
}
.feLigRow button {
  border: 0;
  background: transparent;
  color: var(--dim);
  cursor: pointer;
  padding: 2px 6px;
}
.feLigRow button:hover {
  color: #dc2626;
}

#feProgressPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 24px 30px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  min-width: 220px;
}
.fe-spinner {
  width: 30px;
  height: 30px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: fe-spin 0.8s linear infinite;
}
@keyframes fe-spin {
  to {
    transform: rotate(360deg);
  }
}
#fe_progressMsg {
  font-size: 13px;
  color: var(--text);
  text-align: center;
}

#feErasePopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
  max-width: min(90vw, 900px);
}
#fe_eraseCanvasWrap {
  position: relative;
  max-width: 100%;
  max-height: 65vh;
  overflow: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: none;
  background: repeating-conic-gradient(var(--bg) 0% 25%, var(--panel) 0% 50%) 0
    0/16px 16px;
}
/* generous pasteboard margin around the canvas so any corner/edge of the
   image can be scrolled to the center of the visible area -- otherwise the
   image's own edges are also the scroll limits and can hide under the
   popup header/toolbar at high zoom */
#fe_eraseCanvasPad {
  position: relative;
  display: inline-block;
  padding: 45vh 45vw;
}
#fe_eraseCanvas {
  display: block;
  cursor: none;
  touch-action: none;
}
#fe_eraseBrushCursor {
  position: absolute;
  left: 0;
  top: 0;
  border-radius: 50%;
  pointer-events: none;
  display: none;
  background: repeating-conic-gradient(#000 0deg 12deg, #fff 12deg 24deg);
  -webkit-mask-image: radial-gradient(
    closest-side,
    transparent calc(100% - 1.5px),
    #000 calc(100% - 1.5px)
  );
  mask-image: radial-gradient(
    closest-side,
    transparent calc(100% - 1.5px),
    #000 calc(100% - 1.5px)
  );
  mix-blend-mode: difference;
  opacity: 0.9;
}
#feErasePopup .feToolbarRow {
  border: 0;
  padding: 10px 0 0;
  flex-wrap: wrap;
}
#fe_eraseZoomLabel {
  font-size: 12px;
  color: var(--text-dim, var(--text));
  min-width: 3.5em;
  text-align: center;
}

/* ---------- docs dialog ---------- */
dialog {
  max-width: min(860px, 92vw);
  max-height: 86vh;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--panel);
  color: var(--text);
  padding: 0;
}
dialog::backdrop {
  background: rgba(0, 0, 0, 0.45);
}
#docsHead {
  display: flex;
  gap: 6px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--panel);
  z-index: 2;
}
#docsHead button.tabbtn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
#docsHead #docsClose {
  margin-left: auto;
}
#docsBody {
  padding: 14px 18px;
  overflow: auto;
  max-height: calc(86vh - 52px);
}
#docsBody h3 {
  margin: 1.2em 0 0.4em;
}
#docsBody table {
  border-collapse: collapse;
  width: 100%;
}
#docsBody td,
#docsBody th {
  border: 1px solid var(--border);
  padding: 4px 8px;
  text-align: left;
  vertical-align: middle;
}
#docsBody code,
#docsBody kbd {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0 5px;
  font-family: ui-monospace, Menlo, monospace;
}
.serfont {
  font-family: "EMS Sheet plus Tabs";
  font-feature-settings:
    "calt" 1,
    "liga" 1,
    "ccmp" 1;
  font-size: 34px;
  line-height: 2.4;
  white-space: pre;
}
.combo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 6px;
}
.combo {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px 6px;
  text-align: center;
}
.combo kbd {
  display: block;
  margin-bottom: 0;
  border: 0;
  background: none;
  color: var(--dim);
}
.combo .serfont {
  font-size: 26px;
  line-height: 2.2;
  display: block;
}
@font-face {
  font-family: "EMS Sheet plus Tabs";
  src: url(/build/EMS_Serenissima_Sheet_plus_Tabs.otf) format("opentype");
}

/* ---------- text-box webfonts (see font/font-licenses.js's BUNDLED_FONTS,
   and score/textboxes.js's tbPopulateFontSelect) ----------
   Self-hosted subset (latin + latin-ext only -- these are early-music/
   scholarly typefaces, no need for greek/cyrillic/vietnamese/etc coverage),
   downloaded from Google Fonts (all but Junicode, which isn't on Google
   Fonts -- pulled from its own GitHub release, psb1558/Junicode-font)
   and converted to woff2. Files live in /fonts/ (top-level, see
   backend/app.py's editor_fonts_static / editor/serve.py's blanket static).
   These 5 fixed @font-face rules are left exactly as-is (never touched by
   the Font Library feature) so existing saved scores' text boxes, which
   store one of these literal family names as their fontFamily, keep
   rendering correctly forever. User-uploaded fonts instead get their
   @font-face rules generated at runtime into #dynamicFontFaces -- see
   font/font-library.js's flInjectFontFaces(). */

/* Cardo */
@font-face {
  font-family: "Cardo";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Cardo-400-italic-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Cardo";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Cardo-400-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Cardo";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Cardo-400-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Cardo";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Cardo-400-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Cardo";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/Cardo-700-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Cardo";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/Cardo-700-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* EB Garamond */
@font-face {
  font-family: "EB Garamond";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/EBGaramond-400-italic-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "EB Garamond";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/EBGaramond-400-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "EB Garamond";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/EBGaramond-700-italic-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "EB Garamond";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/EBGaramond-700-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "EB Garamond";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/EBGaramond-400-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "EB Garamond";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/EBGaramond-400-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "EB Garamond";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/EBGaramond-700-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "EB Garamond";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/EBGaramond-700-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* IM Fell English */
@font-face {
  font-family: "IM Fell English";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/IMFellEnglish-400-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IM Fell English";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/IMFellEnglish-400-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Old Standard TT */
@font-face {
  font-family: "Old Standard TT";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/OldStandardTT-400-italic-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Old Standard TT";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/OldStandardTT-400-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Old Standard TT";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/OldStandardTT-400-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Old Standard TT";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/OldStandardTT-400-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Old Standard TT";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/OldStandardTT-700-normal-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Old Standard TT";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/OldStandardTT-700-normal-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Junicode -- static weights (not the variable-font build), no per-subset
   split (its own release doesn't offer one). */
@font-face {
  font-family: "Junicode";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Junicode-Regular.woff2) format("woff2");
}
@font-face {
  font-family: "Junicode";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/Junicode-Bold.woff2) format("woff2");
}
@font-face {
  font-family: "Junicode";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/Junicode-Italic.woff2) format("woff2");
}
@font-face {
  font-family: "Junicode";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/Junicode-BoldItalic.woff2) format("woff2");
}

/* ---------- small screens ---------- */
@media (max-width: 600px) {
  .toolbar {
    padding: 8px 14px;
    gap: 8px;
  }
  .menuBar {
    padding: 6px 14px;
  }
  button,
  select,
  input {
    padding: 7px 11px;
  }
  .menuBarBtn {
    padding: 8px 12px;
  }
  #scoreName {
    width: 10em;
  }
  #findInput {
    width: 8em;
  }
}

/* ---------- print (Score mode only -- prints the current preview view) ---------- */
/* Printing (see score/print.js): a dedicated, all-vector rebuild of every
   page swapped in just for the print media, since the live view's canvas
   layer (raster, screen-resolution, current pan/zoom) isn't fit to print
   and its SVG layer only has real paths for the line mid-edit. Hidden the
   rest of the time -- #printPages only appears under @media print below. */
#printPages {
  display: none;
}
@media print {
  @page {
    margin: 0;
  }
  body > *:not(#printPages) {
    display: none !important;
  }
  #printPages {
    display: block !important;
  }
  .printPage {
    width: 100%;
  }
  .printPage svg {
    display: block;
    width: 100%;
    height: auto;
  }
  .printPage + .printPage {
    break-before: page;
  }
}

/* ---------- documentation search & popup ---------- */
#navSearchWrap {
  position: relative;
}
.search-results-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  width: min(420px, 100vw - 20px);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
  z-index: 1000;
  max-height: 320px;
  overflow-y: auto;
  display: none;
}
.search-result-item {
  padding: 10px 14px;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-align: left;
  transition: background 0.15s ease;
}
.search-result-item:last-child {
  border-bottom: none;
}
.search-result-item:hover {
  background: var(--bg);
}
.search-result-title {
  font-weight: 600;
  color: var(--text);
  font-size: 13px;
}
.search-result-chapter {
  font-size: 10px;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.search-result-snippet {
  font-size: 11px;
  color: var(--dim);
  font-style: italic;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.search-result-highlight {
  background: var(--mark);
  border-radius: 2px;
  padding: 0 2px;
}
.search-no-results {
  padding: 14px;
  color: var(--dim);
  font-size: 13px;
  text-align: center;
}

/* ---------- doc popup dialog ---------- */
#docPopup {
  width: min(860px, 92vw);
  max-height: 86vh;
}
#docPopupHead {
  display: flex;
  align-items: center;
  padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--panel);
  z-index: 2;
}
#docPopupClose {
  margin-left: auto;
  background: transparent;
  border: none;
  font-size: 18px;
  color: var(--dim);
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s;
}
#docPopupClose:hover {
  background: var(--bg);
  color: var(--text);
}
#docPopupBody {
  padding: 20px 24px;
  overflow-y: auto;
  max-height: calc(86vh - 54px);
  text-align: left;
}
#docPopupBody h1 {
  font-size: 24px;
  margin: 0 0 16px;
  border-bottom: 2px solid var(--border);
  padding-bottom: 8px;
}
#docPopupBody h2 {
  font-size: 18px;
  margin: 24px 0 12px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 6px;
}
#docPopupBody h3 {
  font-size: 15px;
  margin: 18px 0 10px;
}
#docPopupBody p {
  margin: 0 0 12px;
  line-height: 1.5;
}
#docPopupBody code {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 0.9em;
}
#docPopupBody pre {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 12px;
  overflow-x: auto;
  margin: 12px 0;
}
#docPopupBody pre code {
  background: transparent;
  border: none;
  padding: 0;
  font-size: 13px;
  line-height: 1.4;
}
#docPopupBody kbd {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  font-family: ui-monospace, Menlo, monospace;
  font-weight: bold;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
}
#docPopupBody table {
  border-collapse: collapse;
  width: 100%;
  margin: 16px 0;
}
#docPopupBody td,
#docPopupBody th {
  border: 1px solid var(--border);
  padding: 6px 10px;
  text-align: left;
  font-size: 13px;
}
#docPopupBody th {
  background: var(--bg);
  font-weight: 600;
}
#docPopupBody ul,
#docPopupBody ol {
  margin: 0 0 14px;
  padding-left: 20px;
}
#docPopupBody li {
  margin-bottom: 6px;
  line-height: 1.4;
}

/* Alert blocks in docs */
.alert-block {
  padding: 12px 16px;
  margin: 16px 0;
  border-radius: 6px;
  border-left: 4px solid var(--border);
  font-size: 13px;
}
.alert-note {
  background: var(--bg);
  border-left-color: var(--dim);
}
.alert-tip {
  background: var(--bg);
  border-left-color: var(--accent);
}
.alert-important {
  background: var(--bg);
  border-left-color: var(--tok-bar);
}
.alert-warning {
  background: var(--bg);
  border-left-color: var(--tok-cmd);
}
.alert-caution {
  background: var(--bg);
  border-left-color: var(--tok-num);
}

/* ---------- Presets page: 3-column preset builder ---------- */
#presetsMain {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
body.presetsMode #presetsMain {
  display: flex;
}
#presetsTopbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
#presetsBody {
  display: flex;
  flex: 1;
  min-height: 0;
}
#presetsColCats,
#presetsColTree,
#presetsColAll {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--border);
  /* White canvas for the 3 working columns -- the ribbon/settings bars
     above stay on the page's usual --bg gray, so the columns read as a
     distinct "workspace" the rows (below) sit on top of as cards. */
  background: var(--panel);
}
#presetsColCats {
  flex: 0 0 var(--pr-col-cats, 230px);
}
#presetsColTree {
  flex: 1 1 auto;
  min-width: 0;
}
#presetsColAll {
  flex: 0 0 var(--pr-col-all, 320px);
  border-right: none;
}
.prColResizeHandle {
  flex: none;
  width: 6px;
  position: relative;
  cursor: col-resize;
  background: transparent;
}
.prColResizeHandle::after {
  content: "";
  position: absolute;
  left: 2px;
  top: 0;
  width: 2px;
  height: 100%;
  background: var(--border);
}
.prColResizeHandle:hover::after,
.prColResizeHandle.dragging::after {
  background: var(--accent);
}
#presetsMain .prCategory > summary,
#presetsMain .prGroup > summary {
  padding-left: 8px;
}
#presetsMain .prCategory {
  background: #e3e5e9;
  border-radius: 8px;
  margin-bottom: 6px;
  padding: 2px 4px;
}
body[data-theme="dark"] #presetsMain .prCategory {
  background: #2c2e31;
}
#presetsMain .prCategory > .fontItems {
  padding: 4px 4px 6px;
}
.prCatTitle {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.prCatAddBtn {
  flex: none;
  margin-left: auto;
  border: 0;
  background: transparent;
  color: var(--dim);
  font-weight: 700;
  padding: 2px 6px;
  border-radius: 4px;
  line-height: 1;
}
.prCatAddBtn:hover {
  color: var(--text);
  background: var(--accent-soft);
}
.prCatAddBtn:disabled {
  opacity: 0.4;
  cursor: default;
}
.prCatAddBtn:disabled:hover {
  background: transparent;
}
.presetsColHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  font-size: 13px;
  flex: none;
}
.prHeadBtnGroup {
  display: flex;
  gap: 6px;
}
.presetsColHead input[type="search"] {
  flex: 1;
  min-width: 0;
  max-width: 160px;
  border-radius: 999px;
  padding: 4px 10px;
  font-weight: 400;
}
#presetsCatList,
#presetsTreeList {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.prCatRow {
  cursor: pointer;
  user-select: none;
}
.prCatRow.active {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.prRootDrop {
  flex: none;
  padding: 6px 10px;
  margin-bottom: 2px;
  border: 1px dashed var(--border);
  border-radius: 6px;
  color: var(--dim);
  font-size: 11.5px;
  text-align: center;
}
.prRootDrop.dragover {
  border-color: var(--accent);
  color: var(--text);
  background: var(--accent-soft);
}
.prNode {
  display: block;
}
.prNodeRow {
  list-style: none;
  user-select: none;
}
.prNodeRow::-webkit-details-marker {
  display: none;
}
.prFolderRow::before {
  content: "▸";
  display: inline-block;
  flex: none;
  width: 16px;
  text-align: center;
  font-size: 15px;
  color: var(--dim);
  transition:
    transform 0.18s ease,
    color 0.18s ease;
}
.prFolder[open] > .prFolderRow::before {
  transform: rotate(90deg);
  color: var(--accent);
}
.prLeafRow::before {
  content: "";
  flex: none;
  width: 16px;
}
/* The tree column (column 2) needs that 16px reserved so folder-arrow rows
   and arrow-less leaf rows still line up at nested depth -- Categories
   (column 1) is always a flat top-level list, so the same spacer here was
   just a dead gap in front of the order number/icon. Match the flush-left
   look of the numbered leaf-body list (.prContentRow) instead. */
.prCatRow.prFolderRow::before,
.prCatRow.prLeafRow::before {
  content: none;
  width: 0;
}
.prFolderCount {
  flex: none;
  color: var(--dim);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.prFolderChildren {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 3px 0 3px 12px;
  padding-left: 16px;
}
/* real tree branch lines: each direct child gets a ├─ tick; the last
   child's vertical stub stops halfway (└─) instead of running full-height */
.prFolderChildren > .prNode {
  position: relative;
}
.prFolderChildren > .prNode::before,
.prFolderChildren > .prNode::after {
  content: "";
  position: absolute;
  left: -16px;
  background: var(--border);
}
.prFolderChildren > .prNode::before {
  top: 0;
  bottom: 0;
  width: 1px;
}
.prFolderChildren > .prNode:last-child::before {
  bottom: auto;
  height: 25px;
}
.prFolderChildren > .prNode::after {
  top: 25px;
  width: 16px;
  height: 1px;
}
.prNodeRow.dragover-before {
  box-shadow: inset 0 2px 0 var(--accent);
}
.prNodeRow.dragover-after {
  box-shadow: inset 0 -2px 0 var(--accent);
}
.prNodeRow.dragover-into {
  outline: 2px dashed var(--accent);
  outline-offset: -2px;
  background: var(--accent-soft);
}
.prLeafBody {
  margin: 2px 0 4px 20px;
  padding: 6px 8px;
  border-radius: 8px;
  background: #e3e5e9;
}
body[data-theme="dark"] .prLeafBody {
  background: #2c2e31;
}
.prLeafBodyRoot {
  margin: 6px;
}
.prLeafBodyHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  color: var(--dim);
  padding: 2px 2px 6px;
}
.prLeafRemoveAllBtn {
  border: 0;
  background: transparent;
  color: var(--dim);
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 4px;
}
.prLeafRemoveAllBtn:hover:not(:disabled) {
  color: var(--text);
  background: var(--accent-soft);
}
.prLeafRemoveAllBtn:disabled {
  opacity: 0.4;
}
.prLeafItemsList {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
#presetsAllList {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 6px 6px 2px;
}
.prItemsList {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.prEmptyHint {
  color: var(--dim);
  font-size: 12.5px;
  padding: 10px 6px;
  font-style: italic;
}
.prRow {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-radius: 6px;
  cursor: default;
  border: 1px solid transparent;
  /* Idle card look, not table rows -- every draggable row (category, tree
     node, All-chars entry) gets its own visible background at rest, so it
     reads as a separate, pick-up-able chip even before you hover it.
     Lighter than plain --bg on purpose: .prIcon's swatch is --bg (or close
     to it), so a row using the same tone left the icon square invisible
     against its own row -- splitting the difference between --bg and
     --panel keeps the row visible against the white column canvas while
     still giving the icon swatch something to contrast against. */
  background: color-mix(in srgb, var(--bg) 45%, var(--panel));
}
.prNodeRow {
  cursor: pointer;
}
.prNodeRow:hover,
.prContentRow:hover,
.prAllRow:hover {
  background: var(--accent-soft);
}
/* Only the actually-selected leaf gets the accent highlight -- an open
   folder can just be an ancestor on the path to it (see prBuildFolder's
   ancestorsOfCurrent), so it must not look "selected" too. Open/closed
   folder state is instead carried by the (now much bigger) arrow alone. */
.prLeaf[open] > .prLeafRow {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.prContentRow,
.prAllRow {
  /* Their containers -- .prLeafBody here, .prCategory for .prAllRow --
     are already this same gray, so white keeps each item a distinct card
     against that shelf instead of the two flattening into one
     undifferentiated block. Same pattern in both columns on purpose --
     .prAllRow is just the All-chars column's version of a .prContentRow. */
  background: var(--panel);
  padding: 6px;
}
.prContentRow:hover {
  background: var(--accent-soft);
}
.prOrderNum {
  flex: none;
  width: 1.6em;
  text-align: right;
  color: var(--dim);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.prIcon {
  flex: none;
  width: var(--pr-icon-size, 40px);
  height: var(--pr-icon-size, 40px);
  border-radius: 4px;
  overflow: hidden;
  background: #f2f3f5;
  display: flex;
  align-items: center;
  justify-content: center;
}
body[data-theme="dark"] .prIcon {
  background: #333538;
}
.prIcon svg.thumb {
  width: 100%;
  height: 100%;
}
.prIcon svg.thumb * {
  fill: #1a1a1a;
}
body[data-theme="dark"] .prIcon svg.thumb * {
  fill: #c9cdd2;
}
.prIcon img.prIconImg {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.prName {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
}
.prEditBtn,
.prDragHandle,
.prArrowBtn {
  flex: none;
  border: 0;
  background: transparent;
  padding: 2px 5px;
  color: var(--dim);
  line-height: 1;
}
.prEditBtn:hover,
.prArrowBtn:hover {
  color: var(--text);
}
.prDragHandle {
  cursor: grab;
  letter-spacing: -1px;
}
.prVisBtn.prVisOff {
  opacity: 0.35;
}
.prArrowBtn {
  opacity: 0;
  pointer-events: none;
  font-weight: 700;
  transition: opacity 0.12s;
}
.prRow:hover .prArrowBtn {
  opacity: 1;
  pointer-events: auto;
}
.prAllRow.already-added .prArrowLeft {
  display: none;
}
.prAllRow.already-added {
  opacity: 0.5;
}

/* ---------- Initials tab: AI-generated illuminated-initial studio ---------- */
#initialsMain {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
body.initialsMode #initialsMain {
  display: flex;
}
#initialsTopbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
#initials_apiKeyInput {
  width: 220px;
}
.inKeyStatus {
  font-size: 11.5px;
  color: var(--dim);
}
.inKeyStatus.ok {
  color: var(--accent);
}
#initialsUsageStats {
  margin-left: auto;
  font-size: 11.5px;
  color: var(--dim);
  white-space: nowrap;
}
#initialsBody {
  display: flex;
  flex: 1;
  min-height: 0;
}
#initialsColFolders,
#initialsColGallery {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--border);
  background: var(--panel);
}
#initialsColFolders {
  flex: 0 0 200px;
}
#initialsColGallery {
  flex: 1 1 auto;
  min-width: 0;
}
#initialsColGenerate {
  flex: 0 0 480px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--panel);
}
#initialsFolderList {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.inFolderRow {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
  user-select: none;
}
.inFolderRow:hover {
  background: var(--accent-soft);
}
.inFolderRow.active {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.inFolderRow .inFolderName {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inFolderRow .inFolderDeleteBtn {
  opacity: 0;
  border: 0;
  background: transparent;
  color: var(--dim);
  flex: none;
}
.inFolderRow:hover .inFolderDeleteBtn {
  opacity: 1;
}
/* Drag-and-drop target: any folder row (incl. "Unfiled") while an image
   thumbnail is being dragged over it -- see inThumb dragstart/dragover. */
.inFolderRow.dragover {
  outline: 2px dashed var(--accent);
  outline-offset: -2px;
  background: var(--accent-soft);
}
#initials_fileInput {
  display: none;
}
#initials_ratingFilterSel {
  font-size: 12px;
  padding: 3px 6px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--fg);
}
#initialsGalleryGrid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 10px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 10px;
  align-content: start;
}
#initialsGalleryGrid.dragover {
  outline: 2px dashed var(--accent);
  outline-offset: -6px;
}
.inThumb {
  position: relative;
  aspect-ratio: 1;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  background: var(--bg);
}
.inThumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.inThumb.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.inThumb.dragging {
  opacity: 0.4;
}
.inThumbDeleteBtn {
  position: absolute;
  top: 3px;
  right: 3px;
  opacity: 0;
  border: 0;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  padding: 3px 5px;
  z-index: 2;
}
.inThumb:hover .inThumbDeleteBtn {
  opacity: 1;
}
.inThumbRefBtn {
  position: absolute;
  top: 3px;
  left: 3px;
  opacity: 0;
  border: 0;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  padding: 3px 5px;
  z-index: 2;
}
.inThumb:hover .inThumbRefBtn,
.inThumb.selected .inThumbRefBtn {
  opacity: 1;
}
.inThumb.selected .inThumbRefBtn {
  background: var(--accent);
}
.inThumbPlaceBtn {
  position: absolute;
  bottom: 3px;
  right: 3px;
  opacity: 0;
  border: 0;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  padding: 3px 5px;
  z-index: 2;
}
.inThumb:hover .inThumbPlaceBtn {
  opacity: 1;
}
.inThumbRatingBadge {
  position: absolute;
  bottom: 3px;
  left: 3px;
  background: rgba(0, 0, 0, 0.55);
  color: #ffcc4d;
  font-size: 10px;
  line-height: 1;
  padding: 2px 5px;
  border-radius: 4px;
  z-index: 2;
}
#initialsGenerateBody {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.inField {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 0.9em;
  color: var(--dim);
}
.inField textarea {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  resize: vertical;
  min-height: 56px;
}
.inField select {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
}
/* System prompt / Instruction: the two fields users actually write longer
   text into -- given real vertical room (flex:1 shares whatever's left
   after the compact top row + action row + result/history), not the old
   fixed 56px box. */
.inFieldGrow {
  flex: 1 1 auto;
  min-height: 140px;
}
.inFieldGrow textarea {
  flex: 1;
  min-height: 140px;
  line-height: 1.4;
}
#initialsGenerateTopRow {
  display: flex;
  gap: 12px;
  flex: none;
}
.inFieldCompact {
  flex: 1;
  min-width: 0;
}
.inStylePresetRow {
  display: flex;
  gap: 6px;
}
.inStylePresetRow select {
  flex: 1;
  min-width: 0;
}
#initialsGenerateActionRow {
  display: flex;
  gap: 8px;
  flex: none;
}
#initials_generateBtn {
  flex: 1;
}
#initialsRefChips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 28px;
}
.inRefChip {
  position: relative;
  width: 44px;
  height: 44px;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.inRefChip img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.inRefChipRemoveBtn {
  position: absolute;
  top: 0;
  right: 0;
  border: 0;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 10px;
  line-height: 1;
  padding: 2px 4px;
}
#initialsResultView {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-top: 1px solid var(--border);
  padding-top: 12px;
}
#initialsResultView[hidden] {
  display: none;
}
#initialsResultImg {
  width: 100%;
  max-height: 260px;
  object-fit: contain;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  cursor: pointer;
}
#initialsResultActions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
#initialsHistoryStrip {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}
#initialsHistoryStrip .inThumb {
  flex: none;
  width: 56px;
  height: 56px;
}
#initialsPromptPopup,
#initialsChooseFolderPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  min-width: 300px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
/* .feNewFontField's own display:flex (an author rule) otherwise beats the
   UA stylesheet's [hidden] -- same fix as #initialsResultView[hidden]
   above, needed here since this field is conditionally shown/hidden by
   inShowPrompt() depending on what's being named (folder vs style preset). */
#initialsPromptSystemPromptField[hidden] {
  display: none;
}
#initialsPromptSystemPrompt {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  min-height: 70px;
  resize: vertical;
}
#initialsPromptBtnRow {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}
#initialsChooseFolderList {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 260px;
  overflow-y: auto;
}
#initialsChooseFolderList button {
  text-align: left;
}

.danger {
  color: #c0392b;
  border-color: #c0392b;
  background: transparent;
}
.danger:hover {
  background: rgba(192, 57, 43, 0.12);
}

#initialsConfirmPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  min-width: 280px;
  max-width: 360px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
#initialsConfirmMessage {
  margin-bottom: 14px;
  line-height: 1.4;
}
#initialsConfirmBtnRow {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Star rating widget -- reused both as the small interactive control in the
   profile popup and (read-only render) for the per-thumbnail badge above. */
.inStars {
  display: inline-flex;
  gap: 2px;
}
.inStars button {
  border: 0;
  background: transparent;
  padding: 0 1px;
  font-size: 20px;
  line-height: 1;
  color: var(--border);
  cursor: pointer;
}
.inStars button.filled {
  color: #ffcc4d;
}
.inStars button:hover {
  color: #ffcc4d;
  opacity: 0.7;
}

/* ---------- Initials: image profile / portfolio popup ---------- */
#initialsProfilePopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
  width: min(1000px, 92vw);
  max-height: 88vh;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.inProfileCloseBtn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 3;
  border: 0;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  border-radius: 6px;
  width: 28px;
  height: 28px;
  font-size: 14px;
}
#initialsProfileBody {
  display: flex;
  min-height: 0;
  overflow: hidden;
}
#initialsProfileImageCol {
  flex: 1 1 55%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 20px;
  background: var(--bg);
  border-right: 1px solid var(--border);
  overflow-y: auto;
}
#initialsProfileImg {
  width: 100%;
  max-height: 60vh;
  object-fit: contain;
  border-radius: 8px;
  background: var(--panel);
  border: 1px solid var(--border);
}
#initialsProfileActions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
#initialsProfileDetailsCol {
  flex: 1 1 45%;
  min-width: 0;
  padding: 20px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
#initialsProfileMeta {
  font-size: 12.5px;
  color: var(--dim);
}
.inProfileField {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 0.9em;
  color: var(--dim);
}
.inProfileTextBlock {
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  white-space: pre-wrap;
  font-size: 13px;
  line-height: 1.45;
  max-height: 180px;
  overflow-y: auto;
}
#initialsProfileRefs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
#initialsProfileRefs .inThumb {
  width: 64px;
  height: 64px;
  flex: none;
}
#initialsProfileUsage {
  font-size: 12.5px;
  color: var(--fg);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* ---------- Initials: prompt-generator popup ---------- */
#initialsPromptGenPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  width: min(560px, 92vw);
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
#initialsPromptGenBody {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 10px;
}
#initialsPromptGenRefGrid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
#initialsPromptGenRefGrid .inThumb {
  width: 56px;
  height: 56px;
  flex: none;
}
#initials_promptGenIdea {
  min-height: 70px;
}
#initialsPromptGenResult textarea {
  min-height: 90px;
}

/* Bigger hover-zoom preview specifically for Initials thumbnails (the
   generic #hoverZoomPreview img rule elsewhere is tuned for small glyph
   icons) -- see editor/js/initials.js's HoverZoom.watch call. */
#hoverZoomPreview img.inHoverImg {
  width: 340px;
  height: 340px;
}

/* ---------- Presets: new/manage package popups ---------- */
#prNewPackagePopup,
#prManagePackagesPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  min-width: 320px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
#prNewPackageForm {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 280px;
}
#prNewPackageForm input[type="text"] {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
}
#prNewPackageBtnRow {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}
#prManagePackagesPopup {
  min-width: 380px;
  max-width: 90vw;
}
#prManagePackagesHint {
  font-size: 12px;
  color: var(--dim);
  margin-bottom: 10px;
}
#prManagePackagesList {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 50vh;
  overflow-y: auto;
}
.pkgRow {
  background: #e3e5e9;
}
body[data-theme="dark"] .pkgRow {
  background: #333538;
}
.pkgRow.dragover-before {
  box-shadow: inset 0 2px 0 var(--accent);
}
.pkgRow.dragover-after {
  box-shadow: inset 0 -2px 0 var(--accent);
}
.pkgNameInput {
  flex: 1;
  min-width: 0;
  font: inherit;
  color: var(--fg);
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 2px 6px;
}

/* ---------- Presets: edit popup (name + icon) ---------- */
#prEditPopup,
#prIconPopup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  min-width: 320px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
#prEditForm {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 300px;
}
#prEditForm input[type="text"] {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
}
#pr_iconPickBtn {
  width: 48px;
  height: 48px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  background: var(--bg);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  color: var(--dim);
  cursor: pointer;
}
#pr_iconPickBtn svg.thumb {
  width: 100%;
  height: 100%;
  background: #f2f3f5;
}
#pr_iconPickBtn svg.thumb * {
  fill: #1a1a1a;
}
body[data-theme="dark"] #pr_iconPickBtn svg.thumb {
  background: #333538;
}
body[data-theme="dark"] #pr_iconPickBtn svg.thumb * {
  fill: #c9cdd2;
}
#pr_iconPickBtn img.prIconImg {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
#prEditBtnRow {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 4px;
}
#pr_deleteBtn {
  color: #c0392b;
  border-color: #c0392b;
  background: transparent;
}
#pr_deleteBtn:hover {
  background: rgba(192, 57, 43, 0.12);
}

/* ---------- Presets: icon picker popup ---------- */
#prIconPopup {
  min-width: 420px;
  max-width: 90vw;
}
#prIconTabs {
  display: flex;
  gap: 6px;
  margin-bottom: 10px;
}
.prIconTabBtn {
  flex: 1;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--dim);
}
.prIconTabBtn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
#pr_iconSearch {
  width: 100%;
  border-radius: 999px;
  padding: 5px 12px;
  margin-bottom: 8px;
}
#prIconGlyphGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
}
.prIconGridBtn {
  position: relative;
  padding: 0;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 6px;
}
.prIconGridBtn svg.thumb {
  width: 100%;
  height: 100%;
  background: #f2f3f5;
}
.prIconGridBtn svg.thumb * {
  fill: #1a1a1a;
}
body[data-theme="dark"] .prIconGridBtn svg.thumb {
  background: #333538;
}
body[data-theme="dark"] .prIconGridBtn svg.thumb * {
  fill: #c9cdd2;
}
#prIconUploadPane #pr_iconDropZone {
  border: 2px dashed var(--border);
  border-radius: 8px;
  padding: 28px 20px;
  text-align: center;
  color: var(--dim);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition:
    border-color 0.15s,
    background 0.15s;
}
#prIconUploadPane #pr_iconDropZone.dragover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* ==================== Feedback chat ==================== */
#feedbackBtn {
  grid-column: 3;
  justify-self: start;
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 0;
  border-radius: 999px;
  padding: 6px 14px 6px 12px;
  font-size: 13px;
  font-weight: 600;
  background: var(--fb-green);
  color: var(--fb-green-text);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
#feedbackBtn:hover {
  background: var(--fb-green-hover);
}
#feedbackBtnIcon {
  font-size: 15px;
  line-height: 1;
}
#feedbackBadge[hidden] {
  display: none;
}
#feedbackBadge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: #e0322c;
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--bg);
  font-variant-numeric: tabular-nums;
}

/* Floating panel, not a modal -- position/size persisted (see
   feedback-chat.js's fbPanelStore), draggable via its own head, natively
   resizable (CSS resize:both, like the Font Editor's Live Preview panel),
   and can be pinned so an outside click doesn't dismiss it. */
#feedbackPopup {
  position: fixed;
  z-index: 95;
  width: 400px;
  height: 560px;
  min-width: 300px;
  min-height: 320px;
  max-width: calc(100vw - 20px);
  max-height: calc(100vh - 20px);
  background: var(--panel);
  border-radius: 16px;
  box-shadow: 0 16px 50px rgba(0, 0, 0, 0.4);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  resize: both;
  transform-origin: center center;
}
#feedbackPopup.fb-hidden {
  display: none;
}
#feedbackPopup.fb-full {
  resize: none;
  border-radius: 8px;
}
/* Only present while JS is tweening a size/position change it made itself
   (full-screen toggle) -- never during a live native corner-drag resize,
   which would otherwise fight the browser's own 1:1 pointer tracking. */
#feedbackPopup.fb-animating {
  transition:
    left 0.38s cubic-bezier(0.22, 0.9, 0.3, 1),
    top 0.38s cubic-bezier(0.22, 0.9, 0.3, 1),
    width 0.38s cubic-bezier(0.22, 0.9, 0.3, 1),
    height 0.38s cubic-bezier(0.22, 0.9, 0.3, 1),
    border-radius 0.38s;
}
#fb_head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 14px 16px;
  background: var(--fb-green);
  color: var(--fb-green-text);
  cursor: move;
  user-select: none;
}
#fb_headTitle {
  flex: 1;
  font-weight: 700;
  font-size: 15px;
}
#fb_head button {
  flex: none;
  border: 0;
  background: rgba(255, 255, 255, 0.18);
  color: var(--fb-green-text);
  border-radius: 6px;
  font-size: 12px;
  padding: 3px 8px;
}
#fb_head button:hover {
  background: rgba(255, 255, 255, 0.32);
}
#fb_head button.active {
  background: rgba(255, 255, 255, 0.45);
}
#fb_threadSel {
  max-width: 40%;
  background: rgba(255, 255, 255, 0.2);
  color: var(--fb-green-text);
  border: 0;
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 12px;
}
#fb_threadSel option {
  color: #111;
}
#fb_messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}
#fb_loadOlderBtn {
  align-self: center;
  font-size: 11.5px;
  padding: 5px 14px;
  margin-bottom: 10px;
  border-radius: 999px;
  color: var(--dim);
  background: var(--panel);
}
#fb_messagesList {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.fb-day-divider {
  align-self: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--dim);
  background: var(--panel);
  border-radius: 999px;
  padding: 3px 12px;
  margin: 4px 0;
}
#fb_emptyHint {
  display: none;
  margin: auto;
  max-width: 220px;
  color: var(--dim);
  font-size: 13px;
  text-align: center;
  line-height: 1.5;
}

.fb-msg {
  display: flex;
  flex-direction: column;
  max-width: 82%;
  gap: 3px;
}
.fb-msg.own {
  align-self: flex-end;
  align-items: flex-end;
}
.fb-msg.other {
  align-self: flex-start;
  align-items: flex-start;
}
.fb-msg-bubble {
  border-radius: 15px;
  padding: 9px 13px;
  font-size: 13.5px;
  line-height: 1.42;
  white-space: pre-wrap;
  word-break: break-word;
}
.fb-msg.own .fb-msg-bubble {
  background: var(--fb-green);
  color: var(--fb-green-text);
  border-bottom-right-radius: 4px;
}
.fb-msg.other .fb-msg-bubble {
  background: var(--panel);
  border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
}
.fb-msg-meta {
  display: flex;
  align-items: center;
  gap: 5px;
}
.fb-msg-time {
  font-size: 10.5px;
  color: var(--dim);
  padding: 0 5px;
}
.fb-msg-image {
  display: block;
  max-width: 240px;
  max-height: 200px;
  width: auto;
  height: auto;
  border-radius: 10px;
  cursor: zoom-in;
  margin-bottom: 6px;
  object-fit: cover;
}

/* like button -- revealed on hover of the bubble row, stays visible once liked */
.fb-msg-row {
  display: flex;
  align-items: flex-end;
  gap: 3px;
}
.fb-msg.own .fb-msg-row {
  flex-direction: row-reverse;
}
.fb-like-btn {
  flex: none;
  border: 0;
  background: transparent;
  font-size: 13px;
  line-height: 1;
  padding: 3px;
  color: var(--dim);
  opacity: 0;
  transition:
    opacity 0.15s,
    transform 0.15s;
}
.fb-msg-row:hover .fb-like-btn,
.fb-like-btn.liked {
  opacity: 1;
}
.fb-like-btn.liked {
  color: #e0322c;
}
.fb-like-btn:active {
  transform: scale(1.3);
}
.fb-like-count {
  font-size: 10px;
  color: var(--dim);
  padding: 0 4px;
  align-self: center;
}

/* code snippet "sandbox" card: rendered music preview above, highlighted
   source below -- same order the Score Editor itself always shows things
   (preview above the code that produced it). */
.fb-sandbox {
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  max-width: 260px;
  margin-bottom: 6px;
  background: var(--panel);
  cursor: pointer;
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
.fb-sandbox:hover {
  border-color: var(--accent);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
}
.fb-msg.own .fb-sandbox {
  max-width: 280px;
}
.fb-sandbox-preview {
  padding: 10px;
  background: var(--paper);
  display: flex;
  justify-content: center;
  align-items: center;
  overflow-x: auto;
  min-height: 40px;
}
.fb-sandbox-preview svg {
  max-width: 100%;
  height: auto;
}
.fb-sandbox-code {
  padding: 8px 10px;
  font:
    11.5px/1.5 ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  background: var(--bg);
  border-top: 1px solid var(--border);
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
}
.fb-sandbox-loading,
.fb-sandbox-error {
  padding: 14px;
  text-align: center;
  color: var(--dim);
  font-size: 11.5px;
}
.fb-sandbox-error {
  color: #c0392b;
}

/* ---- composer ---- */
#fb_composer {
  flex: none;
  border-top: 1px solid var(--border);
  padding: 10px 12px;
  background: var(--panel);
}
#fb_attachPreview[hidden] {
  display: none;
}
#fb_attachPreview {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 8px;
}
.fb-attach-thumb {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
}
.fb-attach-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fb-attach-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border: 0;
  font-size: 11px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.fb-attach-spinner {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.5);
  border-top-color: #fff;
  animation: fb-spin 0.7s linear infinite;
}
@keyframes fb-spin {
  to {
    transform: rotate(360deg);
  }
}

#fb_snippetWrap {
  margin-bottom: 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
#fb_snippetHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 9px;
  font-size: 11px;
  font-weight: 600;
  color: var(--dim);
  background: var(--bg);
}
#fb_snippetHead button {
  border: 0;
  background: transparent;
  color: var(--dim);
  padding: 1px 5px;
}
#fb_snippetHead button:hover {
  color: var(--text);
}
#fb_snippetInput {
  display: block;
  width: 100%;
  min-height: 60px;
  max-height: 160px;
  border: 0;
  padding: 8px 10px;
  font:
    12px/1.5 ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  background: var(--panel);
  color: var(--text);
  resize: vertical;
}

#fb_composerRow {
  display: flex;
  align-items: flex-end;
  gap: 6px;
}
#fb_emojiWrap {
  position: relative;
  flex: none;
}
#fb_emojiBtn,
#fb_codeBtn {
  flex: none;
  border: 0;
  background: var(--bg);
  border-radius: 8px;
  width: 32px;
  height: 32px;
  font-size: 15px;
  color: var(--dim);
}
#fb_codeBtn {
  width: 36px;
  font:
    700 12px/1 ui-monospace,
    monospace;
  white-space: nowrap;
  letter-spacing: -0.5px;
}
#fb_emojiBtn:hover,
#fb_codeBtn:hover,
#fb_codeBtn.active {
  background: var(--accent-soft);
  color: var(--text);
}
#fb_textInput {
  flex: 1;
  min-width: 0;
  max-height: 100px;
  overflow-y: hidden;
  resize: none;
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 7px 13px;
  font: 13.5px/1.4 inherit;
  background: var(--bg);
  color: var(--text);
  transition:
    border-radius 0.15s,
    min-height 0.15s;
}
#fb_composerRow.fb-expanded {
  align-items: stretch;
}
#fb_composerRow.fb-expanded #fb_textInput {
  min-height: 120px;
  max-height: 240px;
  overflow-y: auto;
  border-radius: 12px;
  resize: vertical;
}
/* Bigger + higher-contrast than the other composer icon buttons on
   purpose -- this one needs to read clearly at a glance, including for
   users who'd struggle with a small subtle glyph. */
#fb_expandBtn {
  flex: none;
  align-self: flex-end;
  border: 1px solid var(--border);
  background: var(--bg);
  border-radius: 8px;
  width: 36px;
  height: 36px;
  font-size: 19px;
  font-weight: 700;
  color: var(--text);
}
#fb_expandBtn:hover,
#fb_expandBtn.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
#fb_sendBtn {
  flex: none;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: var(--fb-green);
  color: var(--fb-green-text);
  font-size: 14px;
  padding: 0;
}
#fb_sendBtn:hover {
  background: var(--fb-green-hover);
}
#fb_sendBtn:disabled {
  opacity: 0.4;
}

#fb_emojiPicker[hidden] {
  display: none;
}
#fb_emojiPicker {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  width: 220px;
  max-height: 180px;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  padding: 6px;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 2px;
  z-index: 2;
}
.fb-emoji-btn {
  border: 0;
  background: transparent;
  border-radius: 6px;
  font-size: 18px;
  padding: 4px;
  line-height: 1;
}
.fb-emoji-btn:hover {
  background: var(--accent-soft);
}

/* ---- big interactive sandbox: any snippet, full-size and editable, open
   to both sides of the conversation (see fbOpenBigSandbox) ---- */
#fbBigSandbox {
  position: fixed;
  inset: 20px;
  z-index: 200;
  background: var(--panel);
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#fbBigSandbox.fb-hidden {
  display: none;
}
#fbBig_head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  background: var(--fb-green);
  color: var(--fb-green-text);
  font-weight: 700;
  font-size: 14px;
}
#fbBig_head > span:first-child {
  flex: 1;
}
#fbBig_zoomGroup {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
}
#fbBig_zoomGroup button {
  border: 0;
  background: rgba(255, 255, 255, 0.18);
  color: var(--fb-green-text);
  border-radius: 6px;
  width: 24px;
  height: 24px;
}
#fbBig_zoomGroup button:hover {
  background: rgba(255, 255, 255, 0.32);
}
#fbBig_zoomLabel {
  min-width: 3.4em;
  text-align: center;
}
#fbBig_close {
  flex: none;
  border: 0;
  background: rgba(255, 255, 255, 0.18);
  color: var(--fb-green-text);
  border-radius: 6px;
  padding: 3px 9px;
  font-size: 13px;
}
#fbBig_close:hover {
  background: rgba(255, 255, 255, 0.3);
}
#fbBig_body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#fbBig_previewWrap {
  flex: 1;
  min-height: 0;
  overflow: auto;
  background: var(--paper);
  padding: 24px;
}
#fbBig_preview svg {
  display: block;
}
/* Same transparent-textarea-over-colored-mirror trick as the Score
   Editor's own #input/#mirror (see syntax-gutter.js) -- caret and
   selection live on the (invisible) textarea, the coloring lives on the
   div stacked exactly underneath it. */
#fbBig_codeWrap {
  position: relative;
  flex: none;
  height: 160px;
  min-height: 80px;
  max-height: 50vh;
  border-top: 1px solid var(--border);
  resize: vertical;
  overflow: hidden;
}
#fbBig_mirror,
#fbBig_code {
  position: absolute;
  inset: 0;
  margin: 0;
  border: 0;
  padding: 10px 14px;
  font:
    13px/1.5 ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  white-space: pre;
  overflow: auto;
}
#fbBig_mirror {
  pointer-events: none;
  color: var(--text);
  background: var(--bg);
}
#fbBig_code {
  background: transparent;
  color: transparent;
  caret-color: var(--text);
  resize: none;
  z-index: 1;
}

/* ---------- hover-zoom preview (editor/js/hover-zoom.js) ---------- */
#hoverZoomPreview {
  position: fixed;
  z-index: 500;
  pointer-events: none;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow:
    0 12px 34px rgba(0, 0, 0, 0.28),
    0 2px 8px rgba(0, 0, 0, 0.12);
  padding: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: scale(0.88);
  transition:
    opacity 0.16s ease,
    transform 0.16s ease;
}
#hoverZoomPreview.show {
  opacity: 1;
  transform: scale(1);
}
#hoverZoomPreview svg,
#hoverZoomPreview img {
  width: 160px;
  height: 160px;
  object-fit: contain;
}
/* Cloned glyph SVGs lose their original ancestor-scoped fill rules (e.g.
   .prIcon svg.thumb *) once moved here -- restate the same ink color. */
#hoverZoomPreview svg * {
  fill: #1a1a1a;
}
body[data-theme="dark"] #hoverZoomPreview svg * {
  fill: #c9cdd2;
}
