/* RefSlate accent ramp — slate, hue 211. Every stop is the same hue at a
   different lightness, so anything new can pick a stop rather than introduce
   another colour. --accent-strong is the one that carries text and marks on
   the dark canvas; the base is too dim to read at small sizes. */
:root {
  --rs-accent: #6c8197;           /* base — borders, focus rings          */
  --rs-accent-strong: #9badbf;    /* lighter — text, icons, marks on dark */
  --rs-accent-bright: #bbc6d3;    /* lightest — hover of filled controls  */
  --rs-accent-dim: #556577;       /* darker — recessed edges              */
  --rs-accent-rgb: 108, 129, 151; /* for rgba() washes                    */
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  background: #1a1a1a;
  color: #e8e8e8;
  user-select: none;
  /* Lock page zoom/scroll — canvas handles pan/pinch itself */
  touch-action: none;
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Board loading indicator — sits above the toolbar as a hairline at the very
   top, so a slow board shows progress without covering the canvas. */
.load-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: rgba(255, 255, 255, 0.07);
  z-index: 150;
  pointer-events: none;
}

.load-progress.hidden {
  display: none;
}

.load-progress-bar {
  height: 100%;
  width: 0;
  background: var(--rs-accent-strong);
  border-radius: 0 2px 2px 0;
  transition: width 180ms ease-out, opacity 300ms ease-out;
}

#toolbar {
  position: fixed;
  top: 0;
  left: 0;
  /* Give way to the Outliner so the lock button never hides behind it */
  right: var(--rs-outliner-w, 0px);
  display: flex;
  align-items: center;
  gap: 16px;
  /* Taller than the controls it holds: centring then keeps the logo clear of
     the top edge (and of the loading hairline pinned at y=0). Sized so the
     logo's top inset matches its left inset from the 12px padding. */
  height: 58px;
  padding: 0 12px;
  background: transparent;
  border: none;
  pointer-events: none;
  z-index: 100;
}

#toolbar > * {
  pointer-events: auto;
}

.dropdown {
  position: relative;
}

#btn-menu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  font-size: 18px;
  line-height: 1;
  letter-spacing: 0;
  background: none;
  color: #e8e8e8;
  border: none;
  border-radius: 0;
  cursor: pointer;
  box-shadow: none;
  backdrop-filter: none;
}

#btn-menu:hover {
  background: none;
  color: #fff;
}

#btn-menu .menu-icon-hamburger {
  display: block;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

/* Shown in place of the hamburger while the menu is open — sized to fill the
   button so the mark reads clearly rather than floating in whitespace. */
#btn-menu .menu-icon-app {
  display: none;
  width: 32px;
  height: 32px;
  object-fit: contain;
  pointer-events: none;
}

#btn-menu.is-open .menu-icon-hamburger {
  display: none;
}

#btn-menu.is-open .menu-icon-app {
  display: block;
}

#main-menu {
  position: relative;
}

.menu-dropdown {
  position: absolute;
  top: 100%;
  /* Breathing room under the logo. Safe because this menu is click-toggled,
     so no hover bridge is needed across the gap. */
  margin-top: 8px;
  left: 0;
  background: rgba(32, 32, 32, 0.95);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 7px;
  padding: 4px 0;
  min-width: 260px;
  z-index: 200;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
}

.menu-dropdown.hidden {
  display: none;
}

.menu-dropdown button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 9px 16px;
  text-align: left;
  background: none;
  border: none;
  color: #e8e8e8;
  font-size: 13px;
  cursor: pointer;
}

.menu-item-main {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1;
}

.menu-ico {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  display: block;
  color: #8a8a8a;
}

.menu-ico.hidden {
  display: none !important;
}

.menu-ico-title {
  width: 24px;
  height: 24px;
}

/* Nest section children (Local Drive / Google Drive / Sail) evenly */
.menu-under-local {
  padding-left: 40px !important;
}

.menu-note.menu-under-local {
  padding-left: 40px;
}

.menu-dropdown button:hover {
  background: rgba(255, 255, 255, 0.08);
}


.menu-sep {
  border: none;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  margin: 4px 0;
}

.menu-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #888;
  user-select: none;
  pointer-events: none;
}

.menu-drive-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  display: block;
}

.menu-drive-icon.hidden {
  display: none;
}

.menu-drive-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.menu-dropdown.is-fixed .menu-section-title {
  font-size: 13px;
  letter-spacing: 0.06em;
  color: #a8a8a8;
}

.menu-section-title.hidden {
  display: none;
}

.menu-local-fixed.hidden {
  display: none;
}


.menu-submenu-trigger {
  display: flex !important;
  align-items: center;
  justify-content: space-between;
}

.menu-submenu-trigger.hidden {
  display: none !important;
}

.menu-flyout-item {
  position: relative;
}

.menu-flyout-item > .menu-submenu-trigger {
  display: flex !important;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 9px 16px;
  text-align: left;
  background: none;
  border: none;
  color: #e8e8e8;
  font-size: 13px;
  cursor: default;
}

.menu-flyout-item:hover > .menu-submenu-trigger {
  background: rgba(255, 255, 255, 0.08);
}

.menu-flyout {
  display: none;
  position: absolute;
  left: calc(100% - 2px);
  top: -4px;
  min-width: 200px;
  min-height: 36px;
  padding: 4px 0;
  background: rgba(32, 32, 32, 0.98);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 7px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
  z-index: 220;
}

.menu-flyout-item:hover > .menu-flyout {
  display: block;
}

.menu-flyout button {
  display: block;
  width: 100%;
  max-width: 280px;
  padding: 9px 16px;
  text-align: left;
  background: none;
  border: none;
  color: #e8e8e8;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.menu-flyout button:hover {
  background: rgba(255, 255, 255, 0.08);
}

.menu-drive-hover > .menu-submenu-trigger {
  width: 100%;
  padding: 9px 16px;
  text-align: left;
  background: none;
  border: none;
  color: #e8e8e8;
  font-size: 13px;
  cursor: default;
}

.menu-drive-hover:hover > .menu-submenu-trigger {
  background: rgba(255, 255, 255, 0.08);
}

.menu-drive-hover > .menu-drive-panel {
  display: none;
}

.menu-drive-hover:hover > .menu-drive-panel,
.menu-drive-hover.is-fixed > .menu-drive-panel {
  display: block;
}

.menu-chevron {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-left: 8px;
  color: #8a8a8a;
  display: block;
  transition: transform 0.15s ease;
}

/* Google Drive: right chevron → down when submenu is open */
.menu-drive-hover:hover #drive-chevron,
.menu-drive-hover.is-fixed #drive-chevron {
  transform: rotate(90deg);
}

.menu-drive-panel {
  background: rgba(0, 0, 0, 0.22);
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  padding: 2px 0;
}

.menu-drive-panel.hidden {
  display: none;
}

.menu-drive-panel.is-fixed {
  display: flex;
  flex-direction: column;
  background: transparent;
  border: none;
  padding: 0;
}

.menu-drive-panel.is-fixed #drive-auth-btn { order: 1; }
.menu-drive-panel.is-fixed #drive-account { order: 2; }
.menu-drive-panel.is-fixed #drive-save-btn { order: 3; }
.menu-drive-panel.is-fixed #drive-open-btn { order: 4; }
.menu-drive-panel.is-fixed #sail-boards-item { order: 5; }

/* Drive/Sail children use .menu-under-local (40px) — same as Local Drive */

.menu-dropdown button.hidden,
.menu-dropdown hr.hidden,
.menu-dropdown .menu-note.hidden,
.menu-dropdown [data-menu="default"].hidden,
.menu-dropdown [data-menu="fixed"].hidden {
  display: none !important;
}

.menu-note {
  padding: 4px 16px 8px;
  font-size: 11px;
  color: #999;
  line-height: 1.35;
}

.menu-check {
  display: flex !important;
  align-items: center;
  justify-content: flex-start;
}

.menu-check .check-mark {
  display: none;
  width: 16px;
  height: 16px;
  margin-left: 10px;
  color: #e8e8e8;
  flex-shrink: 0;
}

.menu-check .check-mark svg {
  display: block;
  width: 16px;
  height: 16px;
}

.menu-check.is-on .check-mark {
  display: block;
}

.drive-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: #9a9a9a;
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
  max-width: 52vw;
  text-shadow: none;
}

#drive-chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.drive-chip.hidden {
  display: none;
}

.drive-chip.warn {
  color: var(--rs-accent-strong);
}

.drive-chip-reload,
.drive-chip-merge {
  flex-shrink: 0;
  font-size: 11px;
  font-family: inherit;
  border-radius: 4px;
  padding: 1px 8px;
  cursor: pointer;
  line-height: 1.4;
}

/* One hue for both, so weight carries the meaning: Merge is filled because it
   keeps your work, Reload is outlined because it discards it. */
.drive-chip-merge {
  color: #1a1a1a;
  background: var(--rs-accent-strong);
  border: 1px solid var(--rs-accent-strong);
}

.drive-chip-merge:hover {
  background: var(--rs-accent-bright);
  border-color: var(--rs-accent-bright);
}

.drive-chip-reload {
  color: var(--rs-accent-strong);
  background: transparent;
  border: 1px solid rgba(var(--rs-accent-rgb), 0.55);
}

.drive-chip-reload:hover {
  color: var(--rs-accent-bright);
  border-color: var(--rs-accent-bright);
  background: rgba(var(--rs-accent-rgb), 0.14);
}

.drive-chip-reload.hidden,
.drive-chip-merge.hidden {
  display: none;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
  min-width: 0;
}

.fixed-board-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  color: #ccc;
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}

.fixed-board-banner.hidden {
  display: none;
}

.fixed-board-passcode {
  width: 140px;
  max-width: 28vw;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 6px;
  color: #e8e8e8;
  padding: 5px 10px;
  font-size: 12px;
  font-family: inherit;
}

.fixed-board-passcode:focus {
  outline: none;
  border-color: var(--rs-accent-strong);
}

.fixed-board-passcode.hidden {
  display: none;
}

.fixed-board-banner button {
  background: var(--rs-accent-strong);
  border: 1px solid var(--rs-accent-strong);
  border-radius: 6px;
  color: #1a1a1a;
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.fixed-board-banner button:hover {
  background: var(--rs-accent-bright);
  border-color: var(--rs-accent-bright);
  color: #1a1a1a;
}

#fixed-board-signin.hidden {
  display: none;
}

.status {
  font-size: 12px;
  color: #bbb;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
  max-width: min(420px, 40vw);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 300;
  padding: 20px;
}

.modal-backdrop.hidden {
  display: none;
}

.modal {
  width: min(480px, 100%);
  max-height: min(70vh, 560px);
  display: flex;
  flex-direction: column;
  background: #242424;
  border: 1px solid #3a3a3a;
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid #333;
}

.modal-header h2 {
  font-size: 15px;
  font-weight: 600;
}

.modal-close {
  background: none;
  border: none;
  color: #aaa;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}

.modal-close:hover {
  color: #fff;
}

.modal-body {
  padding: 14px 16px 16px;
  overflow: auto;
}

.modal-label {
  display: block;
  font-size: 12px;
  color: #999;
  margin-bottom: 8px;
}

.modal-row {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.modal-row input {
  flex: 1;
  min-width: 0;
  background: #1a1a1a;
  border: 1px solid #444;
  border-radius: 6px;
  color: #e8e8e8;
  padding: 8px 10px;
  font-size: 13px;
}

.modal-row button {
  background: #3a6ea5;
  border: none;
  border-radius: 6px;
  color: #fff;
  padding: 8px 12px;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}

.modal-row button:hover {
  background: #4a9eff;
}

.help-panel {
  position: fixed;
  z-index: 240;
  width: min(380px, calc(100vw - 24px));
  max-height: min(85vh, 640px);
  display: flex;
  flex-direction: column;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}

.help-panel.hidden {
  display: none;
}

.help-panel-head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  /* Roomier than it was: the logo needs clearance from the panel edge above
     and from the first heading below. */
  padding: 22px 36px 16px;
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.help-panel-head:active {
  cursor: grabbing;
}

.help-panel-title {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Clicks fall through to the header, which is the drag handle */
  pointer-events: none;
}

.help-panel-logo {
  width: 48px;
  height: 48px;
  object-fit: contain;
  display: block;
}

.help-panel-x {
  position: absolute;
  right: 8px;
  top: 10px;
  background: none;
  border: none;
  color: #aaa;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 8px;
}

.help-panel-x:hover {
  color: #fff;
}

.help-panel-body {
  padding: 4px 22px 20px;
  overflow: auto;
  text-align: center;
  color: #c8c8c8;
  font-size: 13px;
  line-height: 1.45;
}

.help-section-title {
  margin: 6px 0 10px;
  font-size: 17px;
  font-weight: 700;
  color: #f0f0f0;
}

.help-intro {
  margin: 0 0 12px;
  color: #bdbdbd;
}

.help-controls {
  background: #1a1a1a;
  border: 1px solid #333;
  border-radius: 6px;
  padding: 12px 14px;
  text-align: left;
}

.help-row {
  display: grid;
  grid-template-columns: 1fr auto 1.35fr;
  gap: 8px;
  align-items: baseline;
  padding: 4px 0;
  color: #d0d0d0;
  font-size: 13px;
}

.help-row .help-sep {
  color: #888;
}

.help-row > span:last-child {
  color: #b0b0b0;
}

.drive-file-list {
  border: 1px solid #333;
  border-radius: 6px;
  max-height: 280px;
  overflow: auto;
}

.drive-file-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid #2e2e2e;
  color: #e8e8e8;
  padding: 10px 12px;
  cursor: pointer;
}

.drive-file-item:last-child {
  border-bottom: none;
}

.drive-file-item:hover {
  background: rgba(74, 158, 255, 0.12);
}

.drive-file-name {
  display: block;
  font-size: 13px;
  margin-bottom: 2px;
}

.drive-file-meta {
  display: block;
  font-size: 11px;
  color: #888;
}

/* Both the header and the board give way to the Outliner, so the lock button
   stays on screen and — more usefully — every geometry calculation that
   measures #canvas-root (Fit All, focus, culling, hit-testing) keeps working
   untouched, and the WebGL canvas resizes through the ResizeObserver already
   watching this element. */
#canvas-root {
  position: relative;
  width: calc(100% - var(--rs-outliner-w, 0px));
  height: 100%;
  overflow: hidden;
  cursor: default;
  background: #1a1a1a;
  touch-action: none;
}

/* ── Outliner ───────────────────────────────────────────────────
   Lists every node, topmost first. One flat order by z, no sections
   per type: text and drawings always paint above images whatever
   their z, and that band rule stays an invisible rendering detail
   rather than something the list pretends to explain.            */
.outliner {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--rs-outliner-w, 0px);
  display: flex;
  flex-direction: column;
  /* A shade darker than the canvas (#1a1a1a), so the panel reads as chrome
     sitting behind the board rather than as more canvas. */
  background: #141414;
  border-left: 1px solid #333;
  z-index: 120;
  overflow: hidden;
  /* Closed, the panel has no width; nothing inside can be reached */
  visibility: hidden;
}

.outliner.is-open {
  visibility: visible;
}

body.ol-resizing {
  cursor: col-resize;
  user-select: none;
}

.ol-grip {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 5px;
  cursor: col-resize;
  z-index: 2;
}

.ol-grip:hover {
  background: var(--rs-accent-strong);
  opacity: 0.5;
}

.ol-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 8px 10px 14px;
  border-bottom: 1px solid #333;
  flex-shrink: 0;
}

.ol-title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #e8e8e8;
}

/* Unpinned, the pin lies on its side — the panel is a peek and will step
   aside the moment the board is touched. Upright means it stays put. */
.ol-pin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: none;
  color: #7d8288;
  cursor: pointer;
}

.ol-pin:hover {
  background: #2f2f2f;
  color: #e8e8e8;
}

.ol-pin.is-pinned {
  color: var(--rs-accent-bright, #8fb0d0);
}

.ol-pin svg {
  width: 14px;
  height: 14px;
  transform: rotate(45deg);
  transition: transform 0.12s ease;
}

.ol-pin.is-pinned svg { transform: rotate(0deg); }

.ol-list {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 0;
}

/* ── Outliner scrollbar ─────────────────────────────────────────
   A slim dark thumb on nothing: no track, no stepper arrows.

   Deliberately the -webkit- pseudo-elements rather than the standard
   `scrollbar-width`/`scrollbar-color` pair. Chrome ignores these
   pseudo-elements entirely as soon as `scrollbar-width` is set, and
   `thin` is the narrowest that pair can express — wider than this,
   and not adjustable. Firefox, which has no pseudo-elements, picks
   up the standard properties from the @supports block below.      */
.ol-list::-webkit-scrollbar {
  width: 6px;
}

.ol-list::-webkit-scrollbar-track {
  background: transparent;
}

.ol-list::-webkit-scrollbar-thumb {
  background: #3d3d3d;
  border-radius: 3px;
}

.ol-list::-webkit-scrollbar-thumb:hover {
  background: #545454;
}

/* The up/down steppers at each end */
.ol-list::-webkit-scrollbar-button {
  display: none;
  width: 0;
  height: 0;
}

.ol-list::-webkit-scrollbar-corner {
  background: transparent;
}

@supports not selector(::-webkit-scrollbar) {
  .ol-list {
    scrollbar-width: thin;
    scrollbar-color: #3d3d3d transparent;
  }
}

/* Exactly one line per node, however long the name — it is clipped, never
   wrapped, so the row height stays uniform and the list scans quickly. */
.ol-row {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 28px;
  padding: 0 10px 0 12px;
  cursor: pointer;
  color: #cfd3d7;
  outline: none;
}

.ol-row:hover {
  background: #2a2a2a;
}

.ol-row.is-selected {
  background: var(--rs-accent-strong);
  color: #fff;
}

/* A group's members sit a shade darker than the group row, so a selected
   group reads as one band with its children nested inside it rather than as
   several identical stripes. */
.ol-row.is-child.is-selected {
  background: color-mix(in srgb, var(--rs-accent-strong) 78%, #000);
}

.ol-ico {
  display: inline-flex;
  flex-shrink: 0;
  opacity: 0.75;
}

.ol-row.is-selected .ol-ico { opacity: 1; }
.ol-ico svg { width: 14px; height: 14px; }

.ol-name {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ol-rename {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 12.5px;
  padding: 1px 4px;
  color: #fff;
  background: #111;
  border: 1px solid var(--rs-accent-strong);
  border-radius: 3px;
  outline: none;
}

/* ── Group rows and drag-to-reorder ─────────────────────────── */
.ol-row.is-group .ol-name { font-weight: 600; }
.ol-row.is-child { padding-left: 30px; }

/* Sits after the name, so a clipped name keeps its ellipsis and the control
   stays at the end of the row instead of being pushed out of sight. */
.ol-twisty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  margin-left: 2px;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: none;
  color: #9aa0a6;
  cursor: pointer;
  flex-shrink: 0;
  transform: rotate(90deg);
}

.ol-twisty:hover {
  color: #e8e8e8;
}

.ol-row.is-collapsed .ol-twisty { transform: rotate(0deg); }
.ol-twisty svg { width: 12px; height: 12px; }
.ol-row.is-selected .ol-twisty { color: #fff; }

body.ol-dragging { cursor: grabbing; user-select: none; }
.ol-row.is-dragging { opacity: 0.45; }

/* Where the drop would land */
.ol-drop-line {
  position: absolute;
  left: 8px;
  right: 8px;
  height: 2px;
  margin-top: -1px;
  background: var(--rs-accent-bright, #8fb0d0);
  pointer-events: none;
  display: none;
}

.ol-row.is-drop-into {
  outline: 1px solid var(--rs-accent-bright, #8fb0d0);
  outline-offset: -1px;
  background: rgba(108, 129, 151, 0.25);
}

.ol-list { position: relative; }

.ol-empty {
  display: none;
  margin: 16px 14px;
  font-size: 12.5px;
  color: #7d8288;
}

.outliner.is-empty .ol-empty { display: block; }

#outliner-row-menu {
  z-index: 400;
  min-width: 140px;
}

/* UI chrome: taps OK, no double-tap page zoom */
#toolbar,
#toolbar *,
#text-toolbar,
#text-toolbar *,
.tt-menu,
.tt-popover,
.tt-color-panel,
.help-panel,
.modal-backdrop,
.context-menu,
.menu-dropdown {
  touch-action: manipulation;
}

/* Text caret / form fields still need native touch gestures */
input,
textarea,
select,
[contenteditable="true"] {
  touch-action: manipulation;
  -webkit-user-select: text;
  user-select: text;
}

/* ── Align submenu (context menu flyout) ────────────────────────
   Hover-driven like the main menu's flyouts, but scoped to the context
   menu's own palette. Disabled means no hover highlight and no flyout. */

.ctx-flyout-item {
  position: relative;
}

.ctx-flyout {
  display: none;
  /* left/top are set by positionFlyout() on hover so the submenu can be kept
     inside the viewport on both axes; these are the pre-measurement defaults. */
  position: absolute;
  left: 100%;
  top: -5px;
  min-width: 186px;
  padding: 4px 0;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
  z-index: 210;
}

.ctx-flyout-item:hover > .ctx-flyout {
  display: block;
}

/* Nothing to align: the row is inert, so the flyout must not appear either */
.ctx-flyout-item.is-disabled:hover > .ctx-flyout {
  display: none;
}

/* Section heading inside a flyout — labels the Align and Justify groups */
.ctx-flyout-title {
  padding: 7px 14px 3px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #7f7f7f;
  user-select: none;
  pointer-events: none;
}

.ctx-flyout-title:not(:first-child) {
  margin-top: 3px;
  border-top: 1px solid #3a3a3a;
}

.ctx-row-main {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  white-space: nowrap;
}

/* Sized to its longest row, "Bring to Front" plus Ctrl+Shift+Up */
#ctx-arrange-menu {
  min-width: 244px;
}


/* No explicit colour: both follow the button, so they dim when it is disabled */
.ctx-row-ico {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  display: block;
  opacity: 0.8;
}

/* The lock row holds both padlock states and shows one — without this they
   both render side by side. */
.ctx-row-ico.hidden {
  display: none;
}

.ctx-chevron {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  display: block;
  opacity: 0.7;
}

/* ── Board lock ─────────────────────────────────────────────────
   View mode: pan and zoom still work, but nothing can be selected,
   moved, edited or deleted. Mainly for touch, where dragging the
   board almost always grabs an image instead. */

#ctx-lock-btn.is-locked .ctx-row-ico,
/* Same treatment for the Outliner while its panel is showing */
#ctx-outliner-btn.is-active .ctx-row-ico {
  color: var(--rs-accent-strong);
}

/* Chromeless like the hamburger, not a filled control */
.lock-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  cursor: pointer;
  color: var(--rs-accent-strong);
  flex-shrink: 0;
}

.lock-toggle:hover {
  color: var(--rs-accent-bright);
}

.lock-toggle.hidden {
  display: none;
}

.lock-ico {
  width: 20px;
  height: 20px;
  display: block;
}

.lock-ico.hidden {
  display: none;
}

/* Locked: the board reads as draggable, and nothing highlights on drag */
#canvas-root.locked {
  cursor: grab;
}

#canvas-root.locked.active {
  cursor: grabbing;
}

#canvas-root.locked .text-content,
#canvas-root.locked [contenteditable] {
  -webkit-user-select: none;
  user-select: none;
}

#canvas-root.panning {
  cursor: grab;
}

#canvas-root.panning.active {
  cursor: grabbing;
}

#gl-board {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
  pointer-events: none;
}

#text-layer {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  z-index: 1;
  pointer-events: none;
}

#text-layer .text-node,
#text-layer .video-node {
  pointer-events: auto;
}

.board-node {
  position: absolute;
}

#selection-frame {
  position: absolute;
  left: 0;
  top: 0;
  box-sizing: border-box;
  border: 1.5px solid var(--rs-accent-strong);
  pointer-events: none;
  z-index: 40;
}

#selection-frame.hidden {
  display: none;
}

/* Editing uses the same frame geometry; thicker stroke + larger handles */
#selection-frame.is-editing {
  border-width: 3px;
}

#selection-frame .sel-handle {
  position: absolute;
  width: 9px;
  height: 9px;
  background: var(--rs-accent-strong);
  border: none;
  border-radius: 50%;
  pointer-events: auto;
  z-index: 41;
  box-sizing: border-box;
}

#selection-frame.is-editing .sel-handle {
  width: 13px;
  height: 13px;
}

#selection-frame .sel-handle.nw {
  left: 0;
  top: 0;
  transform: translate(-50%, -50%);
  cursor: nwse-resize;
}

#selection-frame .sel-handle.ne {
  right: 0;
  top: 0;
  transform: translate(50%, -50%);
  cursor: nesw-resize;
}

#selection-frame .sel-handle.sw {
  left: 0;
  bottom: 0;
  transform: translate(-50%, 50%);
  cursor: nesw-resize;
}

#selection-frame .sel-handle.se {
  right: 0;
  bottom: 0;
  transform: translate(50%, 50%);
  cursor: nwse-resize;
}

.context-menu {
  position: fixed;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 6px;
  padding: 4px 0;
  min-width: 208px;
  z-index: 200;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

.context-menu.hidden {
  display: none;
}

.context-menu button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 6px 14px;
  text-align: left;
  background: none;
  border: none;
  color: #e8e8e8;
  font-size: 13px;
  cursor: pointer;
}

/* `display: flex` above outranks the browser's own [hidden] rule, so a row
   hidden from script would otherwise still take up space. Rows that cannot
   work at all in this browser are hidden outright rather than greyed out. */
.context-menu button[hidden] {
  display: none;
}

.context-menu button:hover {
  background: #3a3a3a;
}

/* Nothing to undo/redo — kept visible so the menu shape stays stable */
.context-menu button:disabled {
  color: #5f5f5f;
  cursor: default;
}

.context-menu button:disabled .shortcut-hint {
  color: #4a4a4a;
}

.context-menu button:disabled:hover {
  background: none;
}

.context-sep {
  border: none;
  border-top: 1px solid #3a3a3a;
  margin: 3px 0;
}

.shortcut-hint {
  float: none;
  font-size: 11px;
  color: #777;
  border: 1px solid #555;
  border-radius: 3px;
  padding: 0 4px;
  margin-left: 8px;
  line-height: 16px;
  flex-shrink: 0;
}

.menu-dropdown button .shortcut-hint,
.context-menu button .shortcut-hint {
  float: none;
  margin-left: auto;
}

/* Text nodes — frame always hugs content, resize scales font */
.text-node {
  cursor: move;
  touch-action: none;
  width: max-content;
  height: auto;
}

.text-node.editing {
  /* Selection frame (thicker) is the edit chrome — no separate outline */
  outline: none;
}

/* Relative to .text-content / asset base fontSize — never nest these */
.text-content .tt-size {
  line-height: inherit;
}
.text-content .tt-size .tt-size {
  font-size: inherit !important; /* safety if nesting slips through */
}

.text-content {
  display: block;
  white-space: pre-wrap;
  outline: none;
  cursor: inherit;
  padding: 4px 6px;
  min-width: 20px;
  min-height: 1em;
  line-height: 1.2;
}

.text-node.editing .text-content {
  cursor: text;
}

/* Video nodes — paused still; controls on hover */
/* ── Video frames ───────────────────────────────────────────────
   A video is a poster frame until someone presses play, so it drags
   like any other asset. The overlay controls counter-scale against
   the board zoom so they stay a usable size, and disappear entirely
   once the frame is too small on screen to hold them.            */
.video-node {
  display: block;
  background: #111;
  cursor: move;
  touch-action: none;
  max-width: none;
  overflow: hidden;
}

.video-node .video-poster {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  pointer-events: none;
  user-select: none;
}

.video-node.no-poster .video-poster { opacity: 0; }

/* Marks a still frame as a video. Once the player is up it is redundant —
   and it would sit over the provider's own controls — so it goes away. */
.video-node .video-badge {
  position: absolute;
  left: 0;
  bottom: 0;
  transform: scale(var(--rs-inv-scale, 1));
  transform-origin: 0 100%;
  margin: 6px;
  padding: 4px 5px;
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  line-height: 0;
  pointer-events: none;
}
.video-node .video-badge svg { width: 15px; height: 15px; }
.video-node.is-live .video-badge { display: none; }

/* Down the right edge, clear of the bottom bar every player puts its own
   controls in. */
.video-node .video-ctl {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%) scale(var(--rs-inv-scale, 1));
  transform-origin: 100% 50%;
  margin-right: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 4px;
  border-radius: 8px;
  background: rgba(18, 20, 24, 0.82);
  opacity: 0;
  transition: opacity 0.12s ease;
  pointer-events: none;
}

.video-node:hover .video-ctl,
.video-node.is-live .video-ctl {
  opacity: 1;
  pointer-events: auto;
}

/* Too small on screen to hold buttons — the badge alone says "video" */
.video-node.too-small .video-ctl { display: none; }

.video-btn {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: #e8ecf1;
  cursor: pointer;
  padding: 0;
}
.video-btn:hover { background: rgba(255, 255, 255, 0.14); }
.video-btn svg { width: 16px; height: 16px; }

/* Stop only means anything once something is playing; Play only before */
.video-node .video-btn-stop { display: none; }
.video-node.is-live .video-btn-stop { display: grid; }
.video-node.is-live .video-btn-play { display: none; }

/* The player is appended after the controls, so without an explicit order it
   paints over them and — being an iframe — swallows the click that would stop
   it. The overlay has to sit above the player, not merely beside it. */
.video-node .video-player {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: #000;
  z-index: 1;
}

.video-node .video-ctl { z-index: 3; }
.video-node .video-badge { z-index: 2; }

/* While a drag is running the board owns the pointer. A live player would
   otherwise swallow every move event crossing it, stalling a marquee or a
   node drag until the cursor came out the other side. */
#canvas-root.dragging .video-player { pointer-events: none; }

.text-content a,
.text-content a.tt-link {
  color: var(--rs-accent-strong);
  font-style: italic;
  text-decoration: underline;
  cursor: pointer;
}

.text-content ul,
.text-content ol {
  margin: 0.25em 0;
  padding-left: 1.4em;
  white-space: normal;
}

/* Floating text formatting toolbar */
.text-toolbar {
  position: fixed;
  z-index: 220;
  display: flex;
  align-items: center;
  gap: 0;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 10px;
  padding: 4px 5px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
  max-width: calc(100vw - 16px);
  flex-wrap: wrap;
}

.text-toolbar.hidden {
  display: none;
}

.tt-group {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 0 4px;
}

.tt-group + .tt-group {
  border-left: 1px solid #444;
}

.text-toolbar:not(.is-editing) .tt-edit-only {
  display: none;
}

.tt-btn {
  min-width: 34px;
  height: 34px;
  padding: 0 7px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: #fff;
  font-size: 15px;
  font-family: inherit;
  cursor: pointer;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
}

.tt-btn:hover {
  background: #3a3a3a;
}

.tt-btn.is-active {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}

/* Whole control is one hover target (icon + chevron) */
.tt-btn.tt-drop {
  min-width: 40px;
  gap: 4px;
  padding: 0 6px 0 7px;
  font-size: 13px;
}

.tt-btn.tt-font-btn {
  min-width: 96px;
  max-width: 140px;
  padding: 0 7px;
}

.tt-font-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100px;
  font-size: 13px;
  color: #fff;
}

.tt-chev-svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  display: block;
  color: #fff;
  opacity: 0.8;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.tt-svg {
  width: 18px;
  height: 18px;
  display: block;
  color: #fff;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* .tt-svg assumes stroke artwork; this opts a solid-fill icon back in */
.tt-svg.is-filled {
  fill: currentColor;
  stroke: none;
}

.tt-align-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.tt-align-icon .tt-svg {
  width: 18px;
  height: 18px;
}

.tt-ico-baseline {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  --tt-fore-color: #ffffff;
}

.tt-baseline-svg {
  width: 18px;
  height: 18px;
}

.tt-baseline-svg .tt-baseline-letter {
  stroke: #fff;
}

.tt-baseline-svg .tt-baseline-bar {
  stroke: var(--tt-fore-color, #ffffff);
  stroke-width: 2.75;
}

.tt-ico-tt {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 1px;
  color: #fff;
  line-height: 1;
  width: 18px;
  height: 18px;
}

.tt-t-sm {
  font-size: 11px;
  font-weight: 700;
}

.tt-t-lg {
  font-size: 16px;
  font-weight: 700;
}

.tt-menu {
  position: fixed;
  z-index: 230;
  min-width: 132px;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 8px;
  padding: 4px 0;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}

.tt-menu.hidden {
  display: none !important;
}

.tt-menu button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: #fff;
  padding: 8px 14px;
  font-size: 13px;
  cursor: pointer;
  font-family: inherit;
}

.tt-menu button:hover,
.tt-menu button.is-active {
  background: #3a3a3a;
}

/* Horizontal icon row (alignment) — PureRef style */
.tt-icon-menu {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 2px;
  min-width: 0;
  padding: 6px;
}

.tt-icon-menu button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 6px;
  flex-shrink: 0;
}

.tt-icon-menu button:hover,
.tt-icon-menu button.is-active {
  background: #3f3f3f;
}

.tt-icon-menu .tt-svg {
  width: 18px;
  height: 18px;
}

.tt-has-beak::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -6px;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  background: #2a2a2a;
  border-right: 1px solid #4a4a4a;
  border-bottom: 1px solid #4a4a4a;
  transform: rotate(45deg);
  pointer-events: none;
}

/* In-app confirm, anchored under the control that triggered it. Sits below its
   anchor, so its beak points up rather than down like .tt-has-beak. */
.confirm-popover {
  max-width: 268px;
  padding: 12px 14px;
}

.confirm-popover::after {
  content: '';
  position: absolute;
  left: var(--beak-x, 50%);
  top: -6px;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  background: #2a2a2a;
  border-left: 1px solid #4a4a4a;
  border-top: 1px solid #4a4a4a;
  transform: rotate(45deg);
  pointer-events: none;
}

.confirm-popover-text {
  font-size: 12px;
  line-height: 1.5;
  color: #d6d6d6;
  margin-bottom: 10px;
}

.confirm-popover-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.confirm-btn {
  font-size: 12px;
  font-family: inherit;
  padding: 4px 12px;
  border-radius: 5px;
  cursor: pointer;
  background: transparent;
  color: #e8e8e8;
  border: 1px solid rgba(255, 255, 255, 0.22);
}

.confirm-btn:hover {
  background: rgba(255, 255, 255, 0.09);
}

.confirm-btn:focus-visible {
  outline: 2px solid var(--rs-accent-strong);
  outline-offset: 1px;
}

.confirm-btn-danger {
  color: #ff6b6b;
  border-color: rgba(255, 107, 107, 0.5);
}

.confirm-btn-danger:hover {
  background: rgba(255, 107, 107, 0.14);
  border-color: #ff6b6b;
}

.tt-popover {
  position: fixed;
  z-index: 235;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 10px;
  padding: 8px 10px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
}

.tt-popover.hidden {
  display: none !important;
}

.add-media-note {
  margin: 6px 0 0;
  padding: 0 2px;
  font-size: 11px;
  line-height: 1.35;
  color: #888;
  text-align: left;
}

.tt-link-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tt-link-leading {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}

.tt-link-input {
  width: 220px;
  min-width: 160px;
  max-width: 40vw;
  background: #1a1a1a;
  border: 1px solid #4a4a4a;
  border-radius: 10px;
  color: #e8e8e8;
  padding: 7px 12px;
  font-size: 13px;
  font-family: inherit;
  outline: none;
}

.tt-link-input:focus {
  border-color: #6a6a6a;
}

.tt-link-action {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: #fff;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.tt-link-action:hover {
  background: #3a3a3a;
}

.tt-link-action.hidden {
  display: none !important;
}

.tt-emoji-menu {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
  padding: 8px;
  min-width: 280px;
  max-width: 320px;
}

.tt-emoji-menu.hidden {
  display: none !important;
}

.tt-emoji-menu button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  font-size: 18px;
  border-radius: 4px;
}

.tt-color-panel {
  position: fixed;
  z-index: 240;
  width: 248px;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 8px;
  padding: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

.tt-color-panel.hidden {
  display: none;
}

.tt-color-head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 8px;
  padding: 4px 28px;
  font-size: 12px;
  color: #ccc;
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.tt-color-head:active {
  cursor: grabbing;
}

.tt-color-title {
  text-align: center;
  pointer-events: none;
}

.tt-color-x {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: #aaa;
  font-size: 18px;
  cursor: pointer;
  line-height: 1;
  padding: 2px 6px;
}

#tt-sv {
  width: 228px;
  height: 228px;
  border-radius: 4px;
  cursor: crosshair;
  display: block;
  touch-action: none;
}

.tt-sliders {
  margin-top: 10px;
}

.tt-slider-track {
  position: relative;
  width: 100%;
  height: 12px;
  border-radius: 6px;
  overflow: visible;
}

.tt-hue-track {
  background: linear-gradient(
    to right,
    #f00 0%,
    #ff0 17%,
    #0f0 33%,
    #0ff 50%,
    #00f 67%,
    #f0f 83%,
    #f00 100%
  );
}

.tt-slider-track input[type='range'] {
  -webkit-appearance: none;
  appearance: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 12px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}

.tt-slider-track input[type='range']::-webkit-slider-runnable-track {
  height: 12px;
  background: transparent;
  border: none;
}

.tt-slider-track input[type='range']::-moz-range-track {
  height: 12px;
  background: transparent;
  border: none;
}

.tt-slider-track input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  margin-top: -1px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #222;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
}

.tt-slider-track input[type='range']::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #222;
}

.tt-color-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
}

.tt-hex-label {
  color: #888;
  font-size: 11px;
  letter-spacing: 0.04em;
}

.tt-hex-prefix {
  color: #888;
  font-size: 12px;
}

#tt-hex {
  flex: 1;
  min-width: 0;
  background: #1a1a1a;
  border: 1px solid #4a4a4a;
  border-radius: 4px;
  color: #e8e8e8;
  padding: 5px 6px;
  font-size: 12px;
  font-family: ui-monospace, Consolas, monospace;
  text-transform: uppercase;
}

.tt-eyedrop {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: #fff;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.tt-eyedrop:hover {
  background: #3a3a3a;
}

.tt-swatch-row {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 6px;
  margin-top: 10px;
  align-items: center;
}

.tt-swatch-row > .tt-swatch-clear {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
}

.tt-recent-swatches {
  grid-column: 2 / -1;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
  min-width: 0;
}

.tt-recent-swatches .tt-swatch {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
}

.tt-swatch {
  border-radius: 5px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  padding: 0;
  cursor: pointer;
  background: #444;
}

.tt-swatch:hover {
  outline: 1px solid #fff;
}

.tt-swatch-empty {
  cursor: default;
  background: #333;
  border-color: rgba(255, 255, 255, 0.08);
  pointer-events: none;
}

.tt-swatch-clear {
  background:
    linear-gradient(to top left, transparent calc(50% - 1px), #e66 calc(50% - 1px), #e66 calc(50% + 1px), transparent calc(50% + 1px)),
    #2a2a2a;
  border-radius: 50%;
}

/* Marquee selection rectangle */
/* ── Alignment guides ───────────────────────────────────────────
   Drawn while dragging or resizing, above the selection frame so the
   line the item landed on is never hidden behind its own border. The
   lines are pooled and reused; nothing is created per frame.        */
#snap-guides {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 41;
}

/* ── Group badge ────────────────────────────────────────────────
   An ungroup button on each selected group's bottom-right corner.
   Positioned in screen space beside the selection frame, so it is
   the same size whatever the zoom.                               */
#group-badges {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 42;
}

/* Anchored to the frame's bottom-left corner, then lifted back inside it —
   same treatment as the badge on a video frame. */
.group-badge {
  position: absolute;
  display: none;
  align-items: center;
  justify-content: center;
  transform: translateY(-100%);
  margin: -6px 0 0 6px;
  padding: 4px 5px;
  border: 0;
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  line-height: 0;
  cursor: pointer;
  pointer-events: auto;
}

.group-badge:hover {
  background: rgba(0, 0, 0, 0.75);
}

.group-badge svg {
  width: 15px;
  height: 15px;
}
.snap-guide {
  position: absolute;
  display: none;
  background: var(--rs-accent-strong);
  opacity: 0.9;
}
.snap-guide.v { width: 1px; }
.snap-guide.h { height: 1px; }

/* ── Snip & Pin ─────────────────────────────────────────────────
   Armed state takes over the cursor so it is obvious the next drag
   captures a region rather than selecting. The rubber band is fixed
   to the viewport, not the board, because it is a screen gesture.  */
body.snip-arming,
body.snip-arming #canvas-root {
  cursor: crosshair;
}

.snip-region {
  position: fixed;
  z-index: 300;
  border: 1px solid var(--rs-accent-strong);
  background: rgba(108, 129, 151, 0.16);
  pointer-events: none;
}

/* Guide lines spanning the viewport, so a region can be lined up against
   something on the far side of the board rather than judged by eye. */
.snip-cross {
  position: fixed;
  z-index: 299;
  background: var(--rs-accent-strong);
  opacity: 0.55;
  pointer-events: none;
}

.snip-cross-h {
  left: 0;
  width: 100%;
  height: 1px;
}

.snip-cross-v {
  top: 0;
  width: 1px;
  height: 100%;
}

#marquee {
  position: absolute;
  display: none;
  border: 1px dashed #4a9eff;
  background: rgba(74, 158, 255, 0.08);
  pointer-events: none;
  z-index: 10;
}

/* ── Draw layer ─────────────────────────────────────────────────
   Sits above images and text so annotations are never buried, at
   90% opacity so what is underneath stays readable. The layer
   ignores the pointer; only the strokes themselves catch it, so
   clicking a gap falls through to whatever is below.            */
#draw-layer {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.75;
}
.drawing-node {
  position: absolute;
  overflow: visible;
  pointer-events: none;
}
.drawing-node .draw-stroke {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: stroke;
}
#canvas-root.locked .drawing-node .draw-stroke {
  pointer-events: none;
}
/* Widened invisible twin so thin strokes are still easy to hit */
.drawing-node .draw-hit {
  fill: none;
  stroke: transparent;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: stroke;
}

#canvas-root.drawing {
  cursor: crosshair;
}
/* The active tool is what the cursor should say it is. Hotspots sit on the
   pen nib and the eraser's working corner, not the icon's top-left. */
#canvas-root.drawing[data-draw-tool="free"] {
  cursor: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 18 18%22%3E%3Cpath d=%22M2.25,12.9378906 L2.25,15.75 L5.06210943,15.75 L13.3559575,7.45615192 L10.5438481,4.64404249 L2.25,12.9378906 Z M15.5306555,5.28145396 C15.8231148,4.98899458 15.8231148,4.5165602 15.5306555,4.22410082 L13.7758992,2.46934454 C13.4834398,2.17688515 13.0110054,2.17688515 12.718546,2.46934454 L11.3462366,3.84165394 L14.1583461,6.65376337 Z%22 fill=%22%23ffffff%22 stroke=%22%23000000%22 stroke-width=%221.2%22 stroke-linejoin=%22round%22/%3E%3C/svg%3E") 3 21, crosshair;
}
#canvas-root.drawing[data-draw-tool="eraser"] {
  cursor: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 16 16%22%3E%3Cpath d=%22M8.086 2.207a2 2 0 0 1 2.828 0l3.879 3.879a2 2 0 0 1 0 2.828l-5.5 5.5A2 2 0 0 1 7.879 15H5.12a2 2 0 0 1-1.414-.586l-2.5-2.5a2 2 0 0 1 0-2.828z%22 fill=%22%23ffffff%22 stroke=%22%23000000%22 stroke-width=%221.2%22 stroke-linejoin=%22round%22/%3E%3C/svg%3E") 3 20, cell;
}
/* While drawing, nothing on the board should intercept the pointer */
#canvas-root.drawing #text-layer .text-node,
#canvas-root.drawing #text-layer .video-node,
#canvas-root.drawing .drawing-node .draw-stroke,
#canvas-root.drawing .drawing-node .draw-hit {
  pointer-events: none;
}
/* …except the strokes of the drawing being edited, for the eraser */
#canvas-root.drawing .drawing-node.editing .draw-stroke,
#canvas-root.drawing .drawing-node.editing .draw-hit {
  pointer-events: stroke;
}

/* ── Draw toolbar ───────────────────────────────────────────── */
.draw-toolbar {
  position: fixed;
  z-index: 245;
  background: #2a2a2a;
  border: 1px solid #4a4a4a;
  border-radius: 8px;
  padding: 6px 8px 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  touch-action: manipulation;
  user-select: none;
}
.draw-toolbar.hidden {
  display: none;
}
.draw-head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 6px;
  padding: 2px 26px;
  font-size: 12px;
  color: #ccc;
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.draw-head:active {
  cursor: grabbing;
}
.draw-title {
  pointer-events: none;
}
.draw-x {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: #aaa;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.draw-x:hover {
  background: #3a3a3a;
  color: #fff;
}
.draw-row {
  display: flex;
  align-items: center;
  gap: 2px;
}
.draw-btn {
  min-width: 34px;
  height: 34px;
  padding: 0 7px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: #fff;
  cursor: pointer;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
}
.draw-btn:hover:not(:disabled) {
  background: #3a3a3a;
}
.draw-btn.is-active {
  background: rgba(var(--rs-accent-rgb), 0.35);
  color: var(--rs-accent-bright);
}
.draw-btn:disabled {
  opacity: 0.35;
  cursor: default;
}
.draw-ico {
  width: 18px;
  height: 18px;
  display: block;
}
.draw-chev {
  width: 10px;
  height: 10px;
  display: block;
}
.draw-style-icon {
  display: inline-flex;
}
.draw-color-bar {
  fill: var(--draw-color, #ffffff);
}
.draw-sep {
  width: 1px;
  height: 22px;
  margin: 0 5px;
  background: #4a4a4a;
}
.draw-confirm:hover:not(:disabled) {
  background: rgba(var(--rs-accent-rgb), 0.45);
  color: var(--rs-accent-bright);
}
.drawing-node .draw-arrow {
  pointer-events: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.tt-menu button.is-active {
  background: rgba(var(--rs-accent-rgb), 0.35);
  color: var(--rs-accent-bright);
}
.tt-menu button:disabled {
  opacity: 0.35;
  cursor: default;
}
/* Above the draw toolbar, which the menus anchor to */
#draw-weight-menu,
#draw-style-menu {
  z-index: 250;
}

/* ── Sail board list ────────────────────────────────────────────
   An inline section like the Drive one on the main site, but open by
   default: on Sail, choosing a board is the main thing this menu does. */
.menu-sail-section > .menu-sail-panel {
  display: none;
}
.menu-sail-section.is-open > .menu-sail-panel {
  display: block;
}
.menu-sail-section.is-open > .menu-submenu-trigger .menu-chevron {
  transform: rotate(90deg);
}
.menu-sail-panel {
  background: rgba(0, 0, 0, 0.25);
}
/* A bulleted list, because more boards will be added over time */
.menu-sail-panel button.menu-sail-board {
  width: 100%;
  padding: 7px 16px 7px 72px;
  text-align: left;
  background: none;
  border: none;
  color: #9a9a9a;
  font-size: 13px;
  cursor: pointer;
  justify-content: space-between;
  gap: 16px;
}
.menu-sail-panel .menu-item-label::before {
  content: '•';
  margin-right: 9px;
  color: #6f6f6f;
}
.menu-sail-panel button.menu-sail-board:hover {
  background: rgba(255, 255, 255, 0.06);
  color: #d8d8d8;
}
.menu-sail-panel button.menu-sail-board:disabled {
  cursor: default;
  color: #9a9a9a;
}
.menu-sail-panel button.menu-sail-board:disabled:hover {
  background: none;
  color: #9a9a9a;
}
.menu-sail-panel .check-mark {
  color: #9a9a9a;
}

/* Quiet attribution at the foot of Help — present, not competing */
.help-credit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin: 0;
  padding-top: 22px;
  font-size: 11px;
  color: #6a6a6a;
  user-select: none;
}
.help-credit-ico {
  width: 12px;
  height: 12px;
  display: block;
  flex-shrink: 0;
}
