/* Boxing — NTP Styles (Warm Neutral, Modern, Minimal) */
* {
  box-sizing: border-box;
}

/* ═══════════════════════════════════════════════
 * Entry Choreography — @keyframes (ADR-0008 Phase: Motion-B)
 * Motion tokens: --dur-fast 140ms (hover), --dur-base 220ms (panel),
 *   --dur-slow 360ms (layout). Curves: --ease-out (enter), --ease-default (toggle).
 * Usage: .fadeInUp etc. applied via class toggle or [data-anim] attributes.
 * ═══════════════════════════════════════════════ */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes slideDown {
  from { opacity: 0; max-height: 0; }
  to   { opacity: 1; max-height: var(--anim-max-h, 500px); }
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--color-canvas);
  color: var(--color-ink);
  font-family: var(--font-stack-ui);
  font-size: var(--font-size-base);
  line-height: 1.5;
  /* BX-DEV-135 (B3 font crispness): preserve the design-system font stack's
     smoothing + features here — ntp.css loads AFTER design-system.css so its
     body block silently dropped -moz-osx-font-smoothing / ligatures / kern,
     which was the actual root of the “字体发虚不清晰” symptom (Firefox lost
     grayscale smoothing; Chrome Fontations stack had no kerning/ligature hints). */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
  font-variant-ligatures: common-ligatures contextual;
  /* prevent fake synth bold/italic that adds visual noise on Windows */
  font-synthesis: weight style;
}

/* === MAIN LAYOUT === */
.ntp {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  padding: var(--space-5) var(--space-6) var(--space-4);
  gap: var(--space-4);
}

/* === HEADER === */
.ntp__bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-hairline);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}

/* Header auto-hide mode: header slides up & fades out, canvas fills viewport */
.ntp--autohide .ntp__bar {
  pointer-events: none;
  transform: translateY(-100%);
  max-height: 0;
  padding: 0;
  margin: 0;
  border-bottom-width: 0;
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out), max-height var(--dur-slow) var(--ease-out);
}

.ntp--autohide .ntp {
  padding: 0;
  overflow: hidden;
  /* prevent browser scroll when header is hidden */
  transition: padding var(--dur-slow) var(--ease-out);
}

.ntp--autohide .library {
  flex: 1;
  margin: 0;
  padding: 0;
  height: 100vh;
  /* extend canvas to fill entire viewport including footer space */
  overflow: hidden;
  /* canvas fills viewport, no scroll */
  transition: margin var(--dur-slow) var(--ease-out), padding var(--dur-slow) var(--ease-out), height var(--dur-slow) var(--ease-out);
}

.ntp--autohide .foot {
  max-height: 0;
  padding: 0;
  margin: 0;
  border-top-width: 0;
  overflow: hidden;
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease-default), max-height var(--dur-slow) var(--ease-default), padding var(--dur-slow) var(--ease-default), margin var(--dur-slow) var(--ease-default);
}

#back-btn {
  order: 0;
  margin-right: auto;
  display: none;
}

#back-btn[data-show="1"] {
  display: inline-flex;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  order: 1;
}

.brand__label {
  display: flex;
  flex-direction: column;
}

.brand__name {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.4px;
}

.brand__sub {
  font-size: 11px;
  color: var(--color-muted);
}

/* === SEARCH === */
.search {
  flex: 1;
  max-width: 420px;
  order: 2;
  display: flex;
  align-items: center;
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  padding: var(--space-2) var(--space-3);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}

.search:focus-within {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-accent-soft);
}

.search__icon {
  color: var(--color-muted);
  margin-right: var(--space-2);
  font-size: 14px;
}

.search input {
  flex: 1;
  border: 0;
  background: transparent;
  font-size: 14px;
  color: var(--color-ink);
  outline: none;
}

.search input::placeholder {
  color: var(--color-muted);
}

.search__hint {
  color: var(--color-muted);
  font-size: 11px;
  font-weight: 500;
  background: var(--color-surface);
  padding: 2px 6px;
  border-radius: 3px;
  margin-left: var(--space-2);
}
.search-results {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: min(360px, 60vh);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-2);
  z-index: 50;
  padding: var(--space-1) 0;
  font-size: 13px;
}
.search-results[hidden] { display: none; }
.search-results__empty,
.search-results__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px var(--space-3);
  cursor: pointer;
  color: var(--color-ink);
}
.search-results__empty {
  cursor: default;
  color: var(--color-muted);
  font-style: italic;
}
.search-results__item:hover {
  background: var(--color-surface);
}
.search-results__item-title {
  font-weight: 500;
}
.search-results__item-meta {
  font-size: 11px;
  color: var(--color-muted);
}
.search-results__item-url {
  font-size: 11px;
  color: var(--color-muted);
  word-break: break-all;
}
.ntp--dark .search-results {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}
.ntp--dark .search-results__item:hover {
  background: var(--color-surface);
}

/* === ACTIONS === */
.actions {
  order: 3;
  display: flex;
  gap: var(--space-1);
}

.header-count {
  order: 2;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-muted);
  padding: 0 var(--space-2);
  white-space: nowrap;
  display: flex;
  align-items: center;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-hairline);
  background: var(--color-elevated);
  color: var(--color-ink);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.btn:hover {
  background: var(--color-surface);
  border-color: var(--color-card-edge);
}

.btn:active {
  transform: scale(0.98);
}

.btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--color-muted);
}

.btn--ghost:hover {
  background: var(--color-surface);
  border-color: var(--color-hairline);
  color: var(--color-ink);
}

.btn--icon {
  padding: var(--space-2);
  min-width: 36px;
  justify-content: center;
}

/* === LIBRARY === */
.library {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  flex: 1;
  min-height: 360px;
}

/* library__head removed — crumbs moved to inner view */
.crumbs {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 13px;
  font-weight: 500;
  padding: var(--space-2) 0;
}

.crumbs__item {
  padding: 2px 4px;
  border-radius: 4px;
  cursor: pointer;
  color: var(--color-ink);
}

.crumbs__item:hover {
  background: var(--color-surface);
}

.crumbs__item--current {
  color: var(--color-accent-ink);
  cursor: default;
}

.crumbs__sep {
  color: var(--color-faint);
}

.library__caption {
  margin: 0;
  font-size: 12px;
  color: var(--color-muted);
}

/* === CANVAS (TOP LEVEL) === */
.canvas {
  position: relative;
  flex: 1;
  min-height: 440px;
  border-radius: var(--radius-card);
  background:
    radial-gradient(circle at 1px 1px, var(--color-card-edge) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--color-surface);
  border: 1px solid var(--color-hairline);
  overflow: hidden;
  user-select: none; /* BX-SEL-01: prevent native dblclick text selection */
}

/* BX-SEL-01: contenteditable titles must remain selectable/editable despite canvas user-select: none */
.large-box__title[contenteditable="true"],
.small-box__title[contenteditable="true"],
.inner__crumb-title[contenteditable="true"] {
  user-select: text;
}

/* BX-DEV-020: CSS `display:flex` overrides HTML `hidden` attribute (MDN:
   "changing the value of the CSS display property on a hidden element will
   override the hidden state"). Without this fallback, a container carrying
   `<div class="canvas" hidden>` stays visible despite the attribute. */
.canvas[hidden] { display: none; }

.canvas__surface {
  position: absolute;
  inset: 0;
  /* virtual infinite canvas; size grows with content + padding */
  min-width: 100%;
  min-height: 100%;
  backface-visibility: hidden;
  user-select: none;
}

.canvas__empty {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  pointer-events: none;
  color: var(--color-muted);
  user-select: none;
}

.canvas__empty-icon {
  font-size: 36px;
  opacity: .5;
}

.canvas__empty-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-ink);
}

.canvas__empty-hint {
  font-size: 12px;
}

.canvas__empty[hidden] {
  display: none;
}

/* Phase 5: Canvas Empty State Action Button (ADR-0008 Motion-B)
   Mirrors .inner__empty-action / .large-box__empty-action language for
   a single visual shared across all three empty-state entry points. */
.canvas__empty-action {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-4);
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  color: var(--color-accent-ink);
  background: var(--color-accent-soft);
  border: 1px solid var(--color-accent-soft-2);
  border-radius: var(--radius-sm, 6px);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-hover), border-color var(--dur-fast) var(--ease-hover), transform var(--dur-fast) var(--ease-hover);
}

.canvas__empty-action:hover {
  background: var(--color-accent-soft-2);
  border-color: var(--color-accent);
  transform: scale(1.02);
}

/* === LARGE BOX (draggable, fixed size) === */
/* ========================================================================
 * BX-CSS-DUAL-WRITE CONVENTION
 * Rules touching .large-box and .small-box share the same visual language.
 * Any CSS property added/changed for one surface MUST be mirrored on the other.
 * Markers:
 *   BX-CSS-DUAL-WRITE  — paired rule; changing one requires changing the other.
 *   LARGE-ONLY     — large-box design difference (no small-box counterpart).
 *   SMALL-ONLY     — small-box design difference (no large-box counterpart).
 * See: docs/css-dual-write-convention.md
 * ======================================================================== */
.large-box {
  position: absolute;
  z-index: 1;
  width: 320px;
  height: 220px;
  display: flex;
  flex-direction: column;
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-card);
  overflow: hidden;
  transition: box-shadow var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  user-select: none;
}

/* BX-CSS-DUAL-WRITE: :hover vs :hover */
.large-box:hover {
  box-shadow: var(--shadow-2);
  border-color: var(--color-card-edge);
}

/* BX-CSS-DUAL-WRITE: --dragging vs --dragging */
.large-box.large-box--dragging {
  box-shadow: var(--shadow-pop);
  border-color: var(--color-accent);
  cursor: grabbing;
  z-index: 5;
  border-radius: var(--radius-card);
  overflow: hidden !important; /* Q6: beat hover-expand :hover overflow:visible */
}

/* BX-CSS-DUAL-WRITE: --ghost vs --ghost */
.large-box--ghost {
  box-shadow: 0 0 0 2px var(--color-accent-soft-2);
}

/* BX-CSS-DUAL-WRITE: __bar vs __bar */
.large-box__bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-hairline);
  cursor: grab;
  flex-shrink: 0;
}

.large-box.large-box--dragging .large-box__bar {
  cursor: grabbing;
  border-radius: 0 0 0 0; /* Q6: inner bar top corners follow outer during drag (outer clip handles rounding) */
}

/* LARGE-ONLY: __icon (large-box only content) */
.large-box__icon {
  font-size: 14px;
  opacity: .8;
}

/* BX-CSS-DUAL-WRITE: __title vs __title */
.large-box__title {
  flex: 1;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: var(--color-ink);
  outline: none;
  cursor: text;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* BX-CSS-DUAL-WRITE: __title[contenteditable]:focus */
.large-box__title[contenteditable="true"]:focus {
  background: var(--color-elevated);
  padding: 2px 6px;
  border-radius: 4px;
  text-overflow: clip;
  white-space: nowrap;
}

/* LARGE-ONLY: __meta (large-box only content) */
.large-box__meta {
  font-size: 11px;
  font-weight: 500;
  color: var(--color-muted);
  flex-shrink: 0;
}

/* pin + expand buttons — minimal icons */
.box-pin-btn,
.box-expand-btn {
  font-family: inherit;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  box-shadow: none;
  color: inherit;
}

.box-pin-btn {
  font-size: 12px;
}

.box-expand-btn {
  font-size: 13px;
}

/* BX-CSS-DUAL-WRITE: __delete vs __delete */
.large-box__delete {
  background: transparent;
  border: 0;
  color: var(--color-faint);
  cursor: pointer;
  font-size: 14px;
  padding: 0 4px;
  border-radius: 4px;
  line-height: 1;
}

/* BX-CSS-DUAL-WRITE: __delete:hover */
.large-box__delete:hover {
  color: var(--color-accent-ink);
  background: var(--color-accent-soft);
}

/* === BOX PIN & AUTO-EXPAND BUTTONS === */
.box-pin-btn {
  background: transparent;
  border: 0;
  cursor: pointer;
  flex-shrink: 0;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  box-shadow: none;
  color: inherit;
}

.box-pin-btn:hover {
  opacity: 0.9;
  background: var(--color-accent-soft);
  border-radius: 3px;
}

.box-expand-btn {
  background: transparent;
  border: 0;
  cursor: pointer;
  flex-shrink: 0;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  box-shadow: none;
  color: inherit;
}

.box-expand-btn:hover {
  opacity: 0.9;
  background: var(--color-accent-soft);
  border-radius: 3px;
}

/* Pinned box: no drag */
/* BX-CSS-DUAL-WRITE: __bar (second rule) vs __bar */
.box--pinned .large-box__bar {
  cursor: default;
}

.box--pinned .small-box__bar {
  cursor: default;
}

.box--pinned .box-pin-btn {
  opacity: 0.9;
}

/* BX-140: parent box highlight — subtle accent ring on starred boxes */
.box--starred {
  box-shadow: 0 0 0 2px var(--color-accent, #A08060), 0 2px 8px rgba(160, 128, 96, 0.15);
}

/* Auto-expand: true drawer pull-down from under title bar (BX-DEV-111)
   Uses pure max-height transition on the __body panel itself.
   When collapsed, body has max-height:0 + overflow:hidden — entire panel,
   including background, borders, and content, is hidden cleanly under the title bar.
   On hover, body slides down with its full measured height.
   No scaleY — that squishes content; this pulls the entire panel out like a tissue drawer. */
/* BX-DEV-111 v2: Real tissue-pull drawer.
   Strategy: collapsed = box shrinks to bar-only height via max-height on the BOX itself.
   Body & resize-handle hidden. On hover: box max-height expands, body fades in.
   The whole box panel (including background/border) grows/shrinks — true drawer. */

/* Collapsed state: box shrinks to bar-only, body hidden */
.box--hover-expand.box--collapsed {
  height: auto !important;
  /* override JS inline style */
  max-height: 60px;
  /* bar + padding, tightly clipped */
  overflow: hidden;
  border-radius: var(--radius-card);
  /* BX-DEV-111i: preserve rounded corners when collapsed clips body */
  transition: max-height var(--dur-base) var(--ease-default);
  /* Material deceleration — smooth collapse */
}

/* BX-CSS-DUAL-WRITE-SHARED: __body hover-expand pair — both in one rule, safe */
.box--hover-expand.box--collapsed .large-box__body,
.box--hover-expand.box--collapsed .small-box__body {
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.box--hover-expand.box--collapsed .box-resize-handle {
  display: none;
  /* BX-DEV-111g: instantly gone while collapsed, no flash during animation */
}

/* Hover: tissue-pull expand — box grows to measured height, body fades in */
.box--hover-expand.box--collapsed:hover {
  max-height: var(--expand-height, 800px);
  /* JS-measured exact content height, avoids empty-range animation */
  overflow: visible;
  border-radius: var(--radius-card) !important;
  /* BX-DEV-111i: keep rounded during expand */
  transition: max-height var(--dur-slow) var(--ease-default);
  /* Material acceleration — crisp expand */
}

.box--hover-expand.box--collapsed:hover .large-box__body,
.box--hover-expand.box--collapsed:hover .small-box__body {
  opacity: 1;
  transition: opacity var(--dur-base) var(--ease-out) 0.08s;
}
.box--hover-expand.box--collapsed:hover .large-box__body,
.box--hover-expand.box--collapsed:hover .small-box__body {
  /* Auto-expand drawer fully fits body (box max-height = measured full
     scrollHeight via JS --expand-height), so no scrollbar should appear
     when popped. While collapsed body uses its own overflow; here override
     to visible to prevent the right vertical scrollbar popping out at the
     edge of the expanded drawer. */
  overflow: visible;
}
.box--hover-expand:not(.box--collapsed) .large-box__body,
.box--hover-expand:not(.box--collapsed) .small-box__body {
  /* BOX-DEV-124 (B6): auto-expand mode uncollapsed state — no vertical scrollbar.
     Box owns overflow:hidden on its border; body uses overflow:visible so the
     drawer shows full content without a scrollbar at the right edge. */
  overflow: visible;
}

.box--hover-expand.box--collapsed:hover .box-resize-handle {
  display: block;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out) var(--dur-slow);
  /* BX-DEV-111g: fade in after drawer fully expanded */
}

.large-box__body {
  flex: 1;
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
  cursor: pointer;
}

/* LARGE-ONLY: __chips (large-box only content) */
.large-box__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  flex: 1;
  align-content: flex-start;
}

/* LARGE-ONLY: __chip (large-box only content) */
/* Bug4: Chip is now a <button> — add appearance reset + hover + cursor */
.large-box__chip {
  font-size: 11px;
  font-weight: 500;
  font-family: inherit;
  color: var(--color-muted);
  background: var(--color-surface);
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--color-hairline);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  transition: background var(--dur-fast) var(--ease-hover), border-color var(--dur-fast) var(--ease-hover), color var(--dur-fast) var(--ease-hover);
}

.large-box__chip:hover {
  background: var(--color-accent-soft);
  border-color: var(--color-accent-soft-2);
  color: var(--color-accent-ink);
}

.large-box__chip:focus-visible {
  border-color: var(--color-accent);
}

.large-box__chip--more {
  cursor: default;
}

.large-box__chip--more:hover {
  background: var(--color-surface);
  border-color: var(--color-hairline);
  color: var(--color-muted);
}

/* Bug4: Highlight pulse for located small box — 2s flash */
.small-box--located {
  animation: locate-pulse 2s ease-out;
}

@keyframes locate-pulse {
  /* ADR-0015: outline (not box-shadow) escapes contain:layout clipping */
  0%   { outline: 0 solid var(--color-accent); outline-offset: 0; }
  30%  { outline: 4px solid var(--color-accent); outline-offset: 4px; }
  100% { outline: 0 solid transparent; outline-offset: 0; }
}
/* Phase 5: Empty State Action Button (ADR-0008 Motion-B) */
.large-box__empty-action {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-2);
  padding: var(--space-1) var(--space-3);
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  color: var(--color-accent-ink);
  background: var(--color-accent-soft);
  border: 1px solid var(--color-accent-soft-2);
  border-radius: var(--radius-sm, 6px);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-hover), border-color var(--dur-fast) var(--ease-hover), transform var(--dur-fast) var(--ease-hover);
}

.large-box__empty-action:hover {
  background: var(--color-accent-soft-2);
  border-color: var(--color-accent);
  transform: scale(1.02);
}

/* Phase 5: Inner Canvas Empty State (ADR-0008 Motion-B) */
.inner__empty-state {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

.inner__empty-hint {
  font-size: 14px;
  color: var(--color-muted);
  font-style: italic;
}

.inner__empty-action {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-4);
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  color: var(--color-accent-ink);
  background: var(--color-accent-soft);
  border: 1px solid var(--color-accent-soft-2);
  border-radius: var(--radius-sm, 6px);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-hover), border-color var(--dur-fast) var(--ease-hover), transform var(--dur-fast) var(--ease-hover);
}

.inner__empty-action:hover {
  background: var(--color-accent-soft-2);
  border-color: var(--color-accent);
  transform: scale(1.02);
}

/* === INNER (DRILL-IN) VIEW === */
.inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
  min-height: 0;
}

/* BX-DEV-020: CSS `display:flex` overrides HTML `hidden` attribute (MDN:
   "changing the value of the CSS display property on a hidden element will
   override the hidden state"). Without this fallback, a container carrying
   `<div class="inner" hidden>` stays visible despite the attribute. */
.inner[hidden] { display: none; }

/* inner surface — mirrors canvas for true infinite canvas */
.inner__canvas {
  position: relative;
  flex: 1;
  min-height: 440px;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-card);
  background:
    radial-gradient(circle at 1px 1px, var(--color-card-edge) 1px, transparent 1px) 0 0 / 16px 16px,
    var(--color-surface);
  border: 1px solid var(--color-hairline);
  overflow: hidden;
  user-select: none;
}

/* BX-DEV-111Pv2: mirror large .canvas / .canvas:active pan cursor for inner canvas (fix 5 cursor-shadowing bug) */

/* inner__canvas-head: lightweight bar inside canvas (v3.7.3 - replaced inner__head) */
.inner__canvas-head {
  position: relative;
  flex-shrink: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 12px;
  background: var(--color-elevated);
  border-bottom: 1px solid var(--color-hairline);
  border-radius: var(--radius-card) var(--radius-card) 0 0;
}

.inner__crumb-title {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.3px;
  outline: none;
  cursor: text;
  min-width: 0;
  border-radius: 4px;
  padding: 2px 6px;
}

.inner__crumb-title[contenteditable="true"]:focus {
  background: var(--color-surface);
}

.inner__canvas-head .btn {
  flex-shrink: 0;
}

.inner__surface {
  position: relative;
  flex: 1;
  min-height: 0;
  min-width: 100%;
  cursor: grab;
  overflow: hidden;
  backface-visibility: hidden;
  /* Surface is below inner__canvas-head (flex column); small-box world origin
     is at surface top; world height = canvas - head. inner__canvas-head
     (z-index:5) sits above in DOM stacking order. */
  user-select: none;
}

/* === SMALL BOX (fixed, second-level container) === */
.small-box {
  position: absolute;
  z-index: 1;
  width: 300px;
  height: 340px;
  display: flex;
  flex-direction: column;
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-card);
  overflow: hidden;
  transition: box-shadow var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  user-select: none;
}

.small-box:hover {
  box-shadow: var(--shadow-2);
  border-color: var(--color-card-edge);
}

.small-box.small-box--dragging {
  box-shadow: var(--shadow-pop);
  border-color: var(--color-accent);
  z-index: 5;
  cursor: grabbing;
  border-radius: var(--radius-card);
  overflow: hidden !important; /* Q6: beat hover-expand :hover overflow:visible */
}

.small-box--ghost {
  box-shadow: 0 0 0 2px var(--color-accent-soft-2);
}

.small-box__bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-hairline);
  cursor: grab;
  flex-shrink: 0;
  min-height: 40px;
}

.small-box__title {
  flex: 1;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: var(--color-ink);
  outline: none;
  cursor: text;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.small-box.small-box--dragging .small-box__bar {
  cursor: grabbing;
  border-radius: 0 0 0 0; /* Q6: inner bar top corners follow outer during drag */
}


/* SMALL-ONLY: __mode (small-box only view toggle) */
.small-box__mode {
  background: transparent;
  border: 0;
  color: var(--color-faint);
  font-size: 12px;
  padding: 0 4px;
  border-radius: 4px;
  cursor: pointer;
}

.small-box__mode:hover {
  color: var(--color-accent-ink);
  background: var(--color-accent-soft);
}

.small-box__delete {
  background: transparent;
  border: 0;
  color: var(--color-faint);
  cursor: pointer;
  font-size: 11px;
  padding: 0 2px;
  border-radius: 4px;
  line-height: 1;
}

.small-box__delete:hover {
  color: var(--color-accent-ink);
  background: var(--color-accent-soft);
}

/* small-box body: list or grid */
.small-box__body {
  flex: 1;
  padding: 4px 6px;
  overflow: auto;
}

/* SMALL-ONLY: --list .small-box__body (small-box only view mode) */
.small-box--list .small-box__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* SMALL-ONLY: --grid .small-box__body (small-box only view mode) */
.small-box--grid .small-box__body {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 4px;
  align-content: flex-start;
}

.bm-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px;
  font-size: 11px;
  font-weight: 500;
  color: var(--color-ink);
  text-decoration: none;
  border-radius: 4px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  cursor: pointer;
  min-width: 0;
}

.bm-row:hover {
  background: var(--color-surface);
}

.bm-row__dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--color-card-edge);
}

.bm-row__title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.small-box--grid .bm-row {
  flex-direction: column;
  align-items: flex-start;
  padding: 6px;
  gap: 2px;
  height: 100%;
}

.small-box--grid .bm-row__title {
  white-space: normal;
}

.bm-empty {
  font-size: 11px;
  color: var(--color-muted);
  font-style: italic;
  padding: 4px 6px;
}

/* === FOOTER === */
.foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  margin-top: auto;
  border-top: 1px solid var(--color-hairline);
  font-size: 11px;
  color: var(--color-muted);
}

.foot__dot {
  width: 4px;
  height: 4px;
  background: var(--color-accent);
  border-radius: 50%;
  opacity: .6;
}

.foot__txt {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  user-select: none; /* BX-SEL-01 */
}

.kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 4px;
  background: var(--color-surface);
  border: 1px solid var(--color-hairline);
  border-radius: 3px;
  font-family: var(--font-stack-mono);
  font-size: 10px;
  font-weight: 500;
  color: var(--color-ink);
}

/* === GLOBAL UI === */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


/* BX-CSS-DUAL-WRITE-SHARED: decorative button focus-visible — keyboard-only outline */
.box-pin-btn:focus-visible,
.box-expand-btn:focus-visible,
.box-star-btn:focus-visible,
.large-box__delete:focus-visible,
.small-box__delete:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
/* Mouse focus: no outline for decorative buttons */
.box-pin-btn:focus:not(:focus-visible),
.box-expand-btn:focus:not(:focus-visible),
.box-star-btn:focus:not(:focus-visible),
.large-box__delete:focus:not(:focus-visible),
.small-box__delete:focus:not(:focus-visible) {
  outline: none;
}


/* Bug6: will-change + contain for first-interaction performance.
   will-change:transform pre-creates compositor layers.
   contain:layout style limits layout recalculation scope — counteracts
   content-visibility:auto first-render cost when box scrolls into view. */
.large-box {
  will-change: transform;
  contain: layout style;
}
.small-box {
  will-change: transform;
  contain: layout style;
}


/* Bug5: Bookmark add (+) button — design-token styled, matches empty state button language.
   Uses same border-radius, transition, hover behavior as .inner__empty-action / .large-box__empty-action.

   Ticket 102 (A-056 / B66) — light-theme contrast contract, measured on the small-box backdrop
   (--color-elevated #EBE5DB; 3.81:1 is the worst case, canvas 4.12:1 / canvas-2 3.91:1):
     before: color --color-muted  #7B7167 = 3.81:1  -> BELOW SC 1.4.3 4.5:1 for 13px/500 text.
             border --color-hairline rgba(42,37,32,.06) = 1.12:1 -> far below SC 1.4.11 3:1.
     after : color --color-ink-soft #3B342C = 9.78:1; border --color-muted #7B7167 = 3.81:1.
   Why the border obligation stands: SC 1.4.11 exempts a boundary only when the control is
   identified by other sufficient content (W3C Understanding 1.4.11, "Boundaries"). Here the
   glyph was itself sub-threshold, so the dashed outline is the only affordance and must carry
   3:1 — the same reasoning that produced the dark fix in ticket 88. W3C's antialiasing note on
   hairline strokes asks for headroom over the bare 3:1; 3.81:1 keeps ~27% margin.
   Token symmetry: light now uses the exact pair the dark override already uses
   (--color-ink-soft / --color-muted), so the two themes cannot drift apart again. */
.bm-add-row .bm-add-btn {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  background: transparent;
  border: 1px dashed var(--color-muted);
  color: var(--color-ink-soft);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  transition: background var(--dur-fast) var(--ease-hover), border-color var(--dur-fast) var(--ease-hover), color var(--dur-fast) var(--ease-hover);
}

.bm-add-row .bm-add-btn:hover {
  background: var(--color-accent-soft);
  /* ticket 102: --color-accent-soft-2 rgba(160,128,96,.18) composites to ~1.3:1 — it is a tint,
     not a boundary. --color-accent (#A08060) is only 2.91:1 in light, so the hover outline uses
     --color-accent-ink (#6E5540) = 5.05:1 over the settled hover fill; it doubles as the label
     colour, which is also 5.05:1. */
  border-color: var(--color-accent-ink);
  border-style: solid;
  color: var(--color-accent-ink);
}

.bm-add-row .bm-add-btn:focus-visible {
  /* ticket 102: --color-accent is 2.91:1 in light — below the 3:1 line a focus indicator must
     clear. --color-accent-ink is 5.52:1 on --color-elevated. */
  border-color: var(--color-accent-ink);
  border-style: solid;
}

/* ═══════════════════════════════════════════════
 * Ticket 60 (Wave7 zero-flash): boot content mask
 * html.boot-pending is set by ntp/boot-theme.js (classic blocking head script) and
 * removed by render.js renderCanvas/_enterLargeBox once the remembered state is
 * rendered. Canvas content stays invisible while the page background (already the
 * remembered theme color) paints — no wrong-theme frame, no default-box flash.
 * A 4s failsafe in boot-theme.js clears the class if init dies (never permanently hidden).
 * ═══════════════════════════════════════════════ */
html.boot-pending .canvas__surface,
html.boot-pending .canvas__empty,
html.boot-pending .inner {
  visibility: hidden;
}
/* === MODAL (settings overlay) === */

@layer overrides;

.modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--color-surface); /* BX-DEV-140: was hardcoded rgba — now follows theme */
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  /* Ticket 05 (ADR-0014 v3): backdrop-filter removed — see block comment. */
  /*
   * Root cause: BX-DEV-140 changed background from rgba (semi-transparent) to
   * var(--color-surface) (opaque #EEE9E1 light / #2A2724 dark). With an opaque
   * background the blur is visually invisible (background fully covers the
   * filtered backdrop) yet Firefox still rasterizes it every frame — a pure
   * performance tax. Removing it eliminates the residual Firefox smoothScroll
   * jank with zero visual regression.
   * Evidence: Bug 1995379 (3x memory / 98% CPU / scroll stutter, New Tab);
   *   Bug 1809738 (picture-caching slice collapse); Bug 1418923 (per-frame
   *   recompute). atomcode-research indexed under atomcode-backdrop-filter-research.
   * If a semi-transparent overlay background is ever restored, re-add
   * backdrop-filter here AND gate it under prefers-reduced-motion (see
   * design-system.css reduced-motion block).
   */
}

.modal-overlay[hidden] {
  display: none;
}

.modal {
  background: var(--color-surface);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-pop);
  width: min(760px, 94vw);
  height: min(560px, 86vh);
  min-height: min(560px, 86vh);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-hairline);
}

.modal__title {
  margin: 0;
  font-size: 20px;
  font-weight: 650;
  color: var(--color-ink);
  letter-spacing: -0.4px;
}

.modal__body {
 padding: var(--space-5);
 display: flex;
 flex-direction: column;
 gap: var(--space-6);
 flex: 1;
 min-height: 0;
  overflow: hidden;
}

.modal__section {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* === SYNC TAB VISUAL GROUPING (T-39 / 04-sync-ui) ===
   Shared (provider-agnostic) vs WebDAV vs GitHub Gist config cards.
   Settings-panel-only selectors — NOT subject to BX-CSS-DUAL-WRITE pairing
   (no .large-box / .small-box surface is touched).
   .sync-group sets a layout display value -> the [hidden] fallback pair is
   MANDATORY (BX-DEV-020): without it display:flex overrides the HTML hidden
   attribute, and the provider mutex driven by sync-engine.js toggling
   #webdav-config / #gist-config [hidden] would visually leak both configs at
   once. Supersedes the old #remote-backup-zone sibling-margin rule (BX-DEV-133):
   inter-section spacing now flows from .sync-group gap. */
.sync-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-card);
  background: var(--color-elevated);
}
.sync-group[hidden] {
  display: none; /* BX-DEV-020: hidden fallback pair — keeps provider mutex visually exclusive */
}
.sync-group + .sync-group {
  margin-top: var(--space-5);
}
.sync-group__title {
  margin: 0;
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-hairline);
  font-size: 13px;
  font-weight: 700;
  color: var(--color-ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.sync-group .btn {
  margin: 0; /* mirror .modal__section .btn — no stray margin for buttons inside a group */
}

.modal__label {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.modal__select {
  padding: var(--space-2) var(--space-3);
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  font-size: 14px;
  cursor: pointer;
  color: var(--color-ink);
}

.modal__input {
  padding: var(--space-2) var(--space-3);
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  font-size: 14px;
  color: var(--color-ink);
  border-radius: var(--radius-card);
}

.modal__input:focus {
  border-color: var(--color-accent);
  outline: none;
}

.modal__hint {
  margin: 0;
  font-size: 12px;
  color: var(--color-muted);
}

.modal__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.modal__row input[type="range"] {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: var(--color-elevated);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}

/* BX-DEV-136: Chrome/Chromium requires explicit background on thumb after
   -webkit-appearance:none, otherwise thumb is transparent/invisible (Chrome 49+, Chromium 149).
   Firefox needs ::-moz-range-thumb + ::-moz-range-track for cross-browser parity. */
.modal__row input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: var(--color-elevated);
}

.modal__row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--color-accent, #A08060);
  cursor: pointer;
  margin-top: -6px; /* center thumb on 6px track */
  border: 2px solid var(--color-surface, #F3EFE7);
}

.modal__row input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--color-elevated);
}

.modal__row input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-accent, #A08060);
  cursor: pointer;
  border: 2px solid var(--color-surface, #F3EFE7);
}

.modal__value {
  min-width: 42px;
  text-align: right;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-accent-ink);
  font-family: var(--font-stack-mono);
}

.modal__foot {
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--color-hairline);
  display: flex;
  justify-content: flex-end;
}

.modal__version {
  margin: 0;
  font-size: 11px;
  color: var(--color-faint);
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  user-select: none;
}

.checkbox-label input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background: var(--color-surface);
  border: 1.5px solid var(--color-card-edge);
  border-radius: 4px;
  display: grid;
  place-content: center;
  transition: background var(--dur-fast) var(--ease-hover), border-color var(--dur-fast) var(--ease-hover);
}

.checkbox-label input[type="checkbox"]:hover {
  border-color: var(--color-accent);
}

.checkbox-label input[type="checkbox"]:checked {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.checkbox-label input[type="checkbox"]:checked::after {
  content: '';
  width: 5px;
  height: 10px;
  border: solid #F7F3ED;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}

/* === ZOOM CONTROLS === */
.zoom-controls {
  position: absolute;
  bottom: var(--space-3);
  right: var(--space-3);
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  padding: 2px 4px;
  z-index: 2;
  /* BX-DEV-112F: own layout context + compositor layer so children do not collapse to 0 on
     parent hidden=>visible transitions in Chrome (mirrors the standard pattern used by
     side-panel / sidebar extensions to keep small abs-pos controls reliably visible). */
  contain: layout;
  isolation: isolate;
}

.zoom-btn {
  background: transparent;
  border: 0;
  color: var(--color-ink-soft);
  font-size: 14px;
  padding: 2px 6px;
  border-radius: 4px;
  cursor: pointer;
  line-height: 1;
  /* BX-DEV-112E: inline-flex + min size ensures Chrome renders the button
     consistently (was block with no min-size; Chrome kept 0x0 after parent
     unhide in some extension load contexts). Firefox auto-reflows fine. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;
}

/* BX-DEV-135 (B6): pure CSS border triangle — zero font/Unicode glyph dependency,
   so ungood-chromium/other-UAs without a good ‹› fallback glyph still see the arrows.
   The Unicode literal kept in HTML is hidden via font-size:0; ::before paints the triangle. */
.zoom-arrow {
  display: block;
  position: relative;
  width: 10px;
  height: 10px;
  font-size: 0;
  line-height: 0;
  color: var(--color-ink-soft);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: geometricPrecision;
  pointer-events: none;
}
.zoom-arrow::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-right: 6px solid currentColor;
  transform: translate(-50%, -50%);
}
.zoom-arrow--right::before {
  border-right: 0;
  border-left: 6px solid currentColor;
}
.zoom-btn:hover .zoom-arrow {
  color: var(--color-ink);
}
.zoom-btn:hover .zoom-arrow--right {
  color: var(--color-ink);
}

.zoom-btn:hover {
  background: var(--color-surface);
  color: var(--color-ink);
}

.zoom-value {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-muted);
  font-family: var(--font-stack-mono);
  min-width: 38px;
  text-align: center;
}

/* === RESIZE HANDLE === */
.box-resize-handle {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 14px;
  height: 14px;
  cursor: nwse-resize;
  background: linear-gradient(135deg, transparent calc(50% - 1px), var(--color-muted) calc(50% - 1px), var(--color-muted) calc(50% + 1px), transparent calc(50% + 1px));
  opacity: 0.4;
  border-radius: 0 0 var(--radius-card) 0;
}

/* BX-CSS-DUAL-WRITE-SHARED: :hover .box-resize-handle — both in one rule, safe */
.large-box:hover .box-resize-handle,
.small-box:hover .box-resize-handle {
  opacity: 0.7;
}

/* BX-DEV-111g: When box is hover-expand and NOT collapsed (fully open), handle visible normally */
.box--hover-expand:not(.box--collapsed) .box-resize-handle {
  display: block;
  opacity: 0.4;
  pointer-events: auto;
}

body.box-resizing {
  cursor: nwse-resize !important;
  user-select: none !important;
}

/* Corner style: square corners override */
/* BX-CSS-DUAL-WRITE-SHARED: .ntp--square-corners — both in one rule, safe */
.ntp--square-corners .large-box,
.ntp--square-corners .small-box,
.ntp--square-corners .canvas,
.ntp--square-corners .inner__canvas,
.ntp--square-corners .inner__canvas-head,
.ntp--square-corners .modal,
.ntp--square-corners .confirm-modal,
.ntp--square-corners .zoom-controls,
.ntp--square-corners .settings-nav,
.ntp--square-corners .settings-nav__item,
.ntp--square-corners .settings-content input,
.ntp--square-corners .settings-content select,
.ntp--square-corners .settings-content button {
  border-radius: 0 !important;
}
.ntp--square-corners .box--hover-expand.box--collapsed,
.ntp--square-corners .box--hover-expand.box--collapsed:hover {
  /* Higher specificity than the .box--collapsed/:hover drawers' own
     `border-radius: var(--radius-card) !important` so square corners win
     in BOTH collapsed and mid-hover-expanded states. Fixes the
     "上两角在圆/方之间反复跳" regression. */
  border-radius: 0 !important;
}

.ntp--square-corners .modal__input {
  border-radius: 0 !important;
}

/* === BOOKMARK ADD INPUT === */
.bm-add-row {
  display: flex;
  gap: 4px;
  padding: 3px 6px;
}

.bm-add-row input {
  flex: 1;
  border: 0;
  background: var(--color-canvas-2);
  border-radius: 4px;
  padding: 2px 6px;
  font-size: 11px;
  color: var(--color-ink);
  outline: none;
}

.bm-add-row input::placeholder {
  color: var(--color-faint);
  font-style: italic;
}

.bm-add-row button {
  color: #F4EFE5;
  border: 0;
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
}

/* === GHOST DRAG === */
.small-box--ghost {
  box-shadow: 0 0 0 2px var(--color-accent-soft-2);
}

/* === INNER EMPTY === */
.inner__empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 13px;
  color: var(--color-muted);
}

/* === RESPONSIVE === */
@media (max-width: 900px) {
  .ntp {
    padding: var(--space-4);
  }

  .ntp__bar {
    flex-wrap: wrap;
  }

  .search {
    order: 4;
    flex-basis: 100%;
    max-width: 100%;
  }

  .large-box {
    width: 280px;
  }

  .small-box {
    width: 240px;
    height: 180px;
  }
}

/* === BOOKMARK FAVICON & EDIT === */
.bm-row__favicon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border-radius: 2px;
}

.bm-row__edit-btn {
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: 14px;
  color: var(--color-muted);
  padding: 0 4px;
  flex-shrink: 0;
  opacity: 0.4;
  transition: opacity var(--dur-fast);
}

.bm-row:hover .bm-row__edit-btn {
  opacity: 1;
}

.bm-row__edit-btn:hover {
  color: var(--color-ink);
}

/* === BOOKMARK EDIT POPUP === */
.bm-edit-popup input {
  padding: 4px 8px;
  border: 1px solid var(--color-hairline);
  border-radius: 4px;
  font-size: 12px;
  background: var(--color-surface);
  color: var(--color-ink);
}

.bm-edit-popup input:focus {
  border-color: var(--color-focus);
  outline: none;
}

.bm-edit-popup button:hover {
  opacity: 0.9;
}

/* === OBSIDIAN-STYLE CANVAS === */
.canvas {
  overflow: hidden;
  cursor: grab;
}

.canvas { cursor: grab; } /* BX-DEV-124B (Bug3): JS sets grabbing after threshold to avoid :active stuck */

/* === CONFIRM MODAL === */
.confirm-modal {
  width: min(420px, 90vw);
}

.confirm-modal {
  border-radius: var(--radius-card);
}

.confirm-modal .modal__body {
  padding: var(--space-4) var(--space-4);
  text-align: center;
}

#confirm-delete-btn:hover {
  opacity: 0.85;
}

/* === DARK MODE TOGGLE BUTTON === */
#dark-mode-btn {
  font-size: 15px;
}

#dark-mode-btn span {
  transition: transform var(--dur-base) var(--ease-default);
}

/* === MODAL EXTENDED (v3.4 wider) === */
.modal__section .btn {
  margin: 0;
}

/* ══════════════════════════════════════════════
   Dark Mode — comprehensive UI adaptation
   Every visible element must invert for dark theme
   ══════════════════════════════════════════════ */
.ntp--dark body,
.ntp--dark html {
  background: var(--color-canvas);
}

.ntp--dark .ntp {
  background: var(--color-canvas);
}

.ntp--dark .ntp__bar {
  background: var(--color-canvas);
  border-bottom-color: var(--color-hairline);
}

.ntp--dark .brand__name {
  color: var(--color-ink);
}


.ntp--dark .search {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}





.ntp--dark .btn {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
  color: var(--color-ink);
}


.ntp--dark .btn--ghost {
  color: var(--color-muted);
  background: transparent;
  border-color: transparent;
}



.ntp--dark .modal {
  background: var(--color-surface);
  border-color: var(--color-hairline);
}




.ntp--dark .modal__select {
  background: var(--color-elevated);
  color: var(--color-ink);
  border-color: var(--color-hairline);
}




.ntp--dark .modal-overlay {
  background: var(--color-surface); /* BX-DEV-140: was hardcoded rgba — now follows theme */
}

.ntp--dark .confirm-modal {
  background: var(--color-surface);
}

.ntp--dark .confirm-modal .modal__title {
  color: var(--color-ink);
}

.ntp--dark .confirm-modal .modal__body {
  color: var(--color-ink);
}


.ntp--dark .checkbox-label input[type="checkbox"] {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}


.ntp--dark .canvas {
  background: radial-gradient(circle at 1px 1px, var(--color-card-edge) 1px, transparent 1px) 0 0 / 24px 24px, var(--color-surface);
  border-color: var(--color-hairline);
}



.ntp--dark .large-box {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}

.ntp--dark .large-box__bar {
  background: var(--color-surface);
  border-bottom-color: var(--color-hairline);
}




.ntp--dark .large-box__chip {
  background: var(--color-surface);
  border-color: var(--color-hairline);
  color: var(--color-muted);
}

.ntp--dark .large-box__chip:hover {
  background: var(--color-accent-soft);
  border-color: var(--color-accent-soft-2);
  color: var(--color-accent-ink);
}

.ntp--dark .large-box__chip--more:hover {
  background: var(--color-surface);
  border-color: var(--color-hairline);
  color: var(--color-muted);
}




.ntp--dark .inner__canvas {
  background: radial-gradient(circle at 1px 1px, var(--color-card-edge) 1px, transparent 1px) 0 0 / 16px 16px, var(--color-surface);
  border-color: var(--color-hairline);
}

.ntp--dark .inner__canvas-head {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}



.ntp--dark .small-box {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}

.ntp--dark .small-box__bar {
  background: var(--color-surface);
  border-bottom-color: var(--color-hairline);
}












.ntp--dark .bm-add-row .bm-add-btn {
  /* ticket 13: legacy element-selector override removed — bm-add-btn is the only
     button in .bm-add-row (popups.js); explicit transparent reset beats base (0-3-0 > 0-2-0) */
  background: transparent;
  /* ticket 88 (A-042): dark ghost affordance. --color-hairline in dark resolves to
     rgba(255,255,255,0.06) = 1.20:1 against --color-elevated (#302D29); with a
     transparent fill that hairline was the only boundary cue. --color-muted (#9A9285)
     measures 4.45:1 and --color-ink-soft (#C8C2B6) 7.72:1 — both clear the 3:1
     non-text and 4.5:1 text lines. Semantic tokens only; no literal colors. */
  border-color: var(--color-muted);
  color: var(--color-ink-soft);
}
.ntp--dark .bm-add-row .bm-add-btn:hover {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
  color: var(--color-accent-ink);
}


.ntp--dark .bm-edit-popup input {
  background: var(--color-surface);
  color: var(--color-ink);
  border-color: var(--color-hairline);
}


.ntp--dark .zoom-controls {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}




.ntp--dark .box-resize-handle {
  background: linear-gradient(135deg, transparent calc(50% - 1px), var(--color-muted) calc(50% - 1px), var(--color-muted) calc(50% + 1px), transparent calc(50% + 1px));
}

.ntp--dark .foot {
  border-top-color: var(--color-hairline);
  color: var(--color-muted);
}

.ntp--dark .kbd {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
  color: var(--color-ink);
}

.ntp--dark .crumbs {
  color: var(--color-ink);
}





.ntp--dark #confirm-delete-btn {
  background: var(--color-accent-ink);
  color: var(--color-canvas);
  border-color: var(--color-accent-ink);
}



/* --- dark mode: ntp container + body background --- */
.ntp--dark body,
body.ntp--dark {
  background: var(--color-canvas);
}

.ntp--dark html,
html.ntp--dark {
  background: var(--color-canvas);
}

/* dark mode pinned header bar */
.ntp--dark .ntp__bar {
  background: var(--color-canvas);
  border-bottom-color: var(--color-hairline);
}

/* dark mode canvas surface */
.ntp--dark .canvas__surface {
  background: transparent;
}

/* dark mode inner surface */
.ntp--dark .inner__surface {
  background: transparent;
}

/* dark mode settings nav */





/* dark mode settings label + checkbox */


/* dark mode font-size slider value */
.ntp--dark #font-slider-value,
.ntp--dark #zoom-slider-value {
  color: var(--color-accent-ink);
}

/* dark mode square corners checkbox label */
.ntp--dark #square-corners-cb+.checkbox-label__text {
  color: var(--color-ink);
}

/* ══════════════════════════════════════════════
   Settings Tabbed Layout
   ══════════════════════════════════════════════ */
.settings-body {
  flex-direction: row;
  gap: 0;
  padding: 0 !important;
  overflow: hidden;
  /* BX-DEV-111k-v4: removed contain:layout style (caused scroll jank); overflow:hidden alone prevents resize */
}

.settings-nav {
  display: flex;
  flex-direction: column;
  min-width: 160px;
  padding: var(--space-4) var(--space-3);
  border-right: 1px solid var(--color-hairline);
  gap: var(--space-1);
}

.settings-nav__item {
  background: transparent;
  border: 0;
  border-radius: var(--radius-tile);
  padding: var(--space-2) var(--space-3);
  font-size: 13px;
  font-weight: 500;
  color: var(--color-muted);
  text-align: left;
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}

.settings-nav__item:hover {
  background: var(--color-surface);
  color: var(--color-ink);
}

/* BX-DEV-111f: Active tab retains its own background on hover — only text intensifies */
.settings-nav__item--active:hover {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
}

.settings-nav__item--active {
  background: var(--color-accent-soft);
  color: var(--color-accent-ink);
  font-weight: 600;
}

.settings-content {
  flex: 1;
  min-width: 0;
  min-height: 0;
  padding: var(--space-5);
  overflow-y: auto;
 overscroll-behavior: contain;
  /* ADR-0014.updated: overflow-anchor:none prevents Firefox from auto-scrolling
     to keep content in view when DOM changes above the fold — eliminates a
     source of scroll-position jitter when the sync/backup panels mutate. */
  overflow-anchor: none;
 scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
  -webkit-overflow-scrolling: touch;
  /* ADR-0014.updated: will-change: scroll-position promotes the scroll container to
     its own compositor layer so Firefox's general.smoothScroll animation runs on
     the GPU instead of main-thread layout/paint per frame — eliminates the user-visible
     "一抽一抽的" jank when FF smooth scrolling is enabled.
     Spec: MDN will-change (scroll-position keyword). VRAM cost: one static container
     texture, bounded by the settings-modal size (~600×500). No will-change:transform
     side-effect (no containing-block/stacking-context creation). */
  will-change: scroll-position;
}

.settings-tab {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.settings-tab {
  min-height: 0;
  padding-right: var(--space-2);
  overflow: visible;
}

.settings-tab[hidden] {
  display: none;
}





/* ══════════════════════════════════════════════
   Header Pin Float Button (v3.6.2 — canvas-relative)
   ══════════════════════════════════════════════ */
/* Default state: button sits inline in header bar, no special positioning */
/* Base: always above canvas__surface stacking context to prevent pointer-event interception */
#header-pin-btn {
  position: relative;
  z-index: 10;
  cursor: pointer !important;
}

#header-pin-btn:hover {
  background: var(--color-surface);
  border-color: var(--color-hairline);
  color: var(--color-ink);
}

.header-pin--floating {
  position: absolute !important;
  top: 12px;
  right: 16px;
  z-index: 1000 !important;
  background: var(--color-elevated);
  border-radius: var(--radius-tile);
  box-shadow: var(--shadow-2);
  padding: 4px 8px;
  transition: opacity var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

.header-pin--floating:hover {
  box-shadow: var(--shadow-3);
  cursor: pointer;
}


.inner__canvas .header-pin--floating {
  /* BX-DEV-136: inner-canvas-head was de-coupled from the canvas and floated
     at the app-title-bar level above it, so the pin no longer needs to clear
     an in-canvas head strip. Small offset keeps it off the canvas top edge. */
  top: var(--space-2) !important;
}
/* ══════════════════════════════════════════════
   Curated Theme Pack System (ADR-0012)
   Curated theme presets — user picks a complete theme, no free hue slider
   ══════════════════════════════════════════════ */
.theme-presets {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.theme-preset {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-tile);
  border: 2px solid var(--color-hairline);
  background: var(--color-elevated);
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}

.theme-preset:hover {
  border-color: var(--color-card-edge);
  box-shadow: var(--shadow-1);
}

.theme-preset--active {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px var(--color-accent-soft-2);
}

.theme-preset__swatch {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: block;
}

/* Dark mode parity */
.ntp--dark .theme-preset {
  background: var(--color-elevated);
  border-color: var(--color-hairline);
}
.ntp--dark .theme-preset:hover {
  border-color: var(--color-card-edge);
}
.ntp--dark .theme-preset--active {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px var(--color-accent-soft-2);
}
/* BX-CSS-DUAL-WRITE-SHARED: accent theme controls — shared selectors, no dual-write needed */
/* Q4: Chrome UA button reset */
.box-expand-btn, .box-pin-btn, .box-mode-btn, .box-resize-handle,
.large-box__delete, .small-box__delete {
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  box-shadow: none;
}

/* Q5: Chrome select/input focus ring reset */
.modal select:focus,
.modal input:focus,
.modal button:focus,
.modal textarea:focus {
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  outline-offset: 0;
  box-shadow: none;
  border-color: var(--color-focus);
}
/* === Onboarding (first-run guided tour) === */
.onboarding-modal {
  width: min(520px, 92vw);
  height: auto;
  min-height: 0;
  max-height: min(620px, 90vh);
  overflow: hidden;
}

.onboarding__body {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
  padding: var(--space-5) var(--space-5) var(--space-3);
  box-sizing: border-box;
  gap: var(--space-3);
}
.onboarding__step {
  /* Single step never scrolls on its own; the modal itself owns the
     legit max-height. Avoids the right vertical scrollbar on Step 3
     (which has restore button + long description). */
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  max-width: 420px;
}

.onboarding__step[hidden] {
  display: none;
}

.onboarding__step-icon {
  font-size: 48px;
  line-height: 1;
  width: 72px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--color-elevated);
  border: 1px solid var(--color-hairline);
  margin-bottom: var(--space-2);
}

.onboarding__step-num {
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-muted);
  font-weight: 600;
}

.onboarding__step-title {
  margin: 0;
  font-size: 18px;
  font-weight: 650;
  color: var(--color-ink);
}

.onboarding__step-desc {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-muted);
}

.onboarding__dots {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.onboarding__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-hairline);
  transition: background var(--dur-fast) var(--ease-hover);
}

.onboarding__dot.is-active {
  background: var(--color-accent-ink);
}

.onboarding__foot {
  justify-content: space-between;
}

.ntp--dark .onboarding-modal {
  background: var(--color-surface);
}

.ntp--dark .onboarding__step-icon {
  background: var(--color-elevated);
}

.ntp--dark .onboarding__step-title {
  color: var(--color-ink);
}.onboarding__lang {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  max-width: 420px;            /* match .onboarding__step so divider spans the same content width */
  margin: 0 auto var(--space-2);
  padding: var(--space-3) 0 var(--space-2);
  box-sizing: border-box;
  border-bottom: 1px solid var(--border-soft, rgba(0,0,0,0.08));
}
.onboarding__lang-label {
  font-weight: 600;
  font-size: 0.95rem;
}
.onboarding__lang-select {
  width: 100%;
  max-width: 260px;
}
.onboarding__lang-hint {
  font-size: 0.82rem;
  opacity: 0.7;
  margin: 0;
}
.ntp--dark .onboarding__lang {
  border-bottom-color: rgba(255,255,255,0.12);
}

/* BX-DEV-123: Performance — content-visibility for engineering-scale canvas (1000+ boxes).
   Browser auto-skips layout/paint of offscreen boxes; 7x render boost per web.dev/MDN.
   Must pair with contain-intrinsic-size to prevent scrollbar jumping.
   Exclude dragging/hover-expand/dragged states to keep interaction smooth. */
/* BX-CSS-DUAL-WRITE: content-visibility:auto (paired) */
.large-box:not(.large-box--dragging):not(.large-box--ghost) {
  content-visibility: auto;
  contain-intrinsic-size: auto 320px auto 220px;
}
/* Bug1: disable content-visibility during canvas pan — avoids per-box viewport check on every transform tick */
/* BX-CSS-DUAL-WRITE: .panning override (paired) */
.panning .large-box {
  content-visibility: visible !important;
}
.panning .small-box {
  content-visibility: visible !important;
}

.small-box:not(.small-box--dragging):not(.small-box--ghost) {
  content-visibility: auto;
  contain-intrinsic-size: auto 300px auto 340px;
}

/* BX-DEV-SEARCH (B9): search highlight — match boxes glow, non-match dim */
/* BX-CSS-DUAL-WRITE-SHARED: --search-match — both in one rule, safe */
.large-box--search-match, .small-box--search-match {
  box-shadow: 0 0 0 2px var(--color-accent, #5b8def), var(--shadow-2);
  opacity: 1;
}
/* BX-CSS-DUAL-WRITE-SHARED: --search-hidden — both in one rule, safe */
.large-box--search-hidden, .small-box--search-hidden {
  opacity: 0.25;
  filter: grayscale(0.5);
}


/* BX-DEV-137: box-connections / star-mark UI (leader-line draws the actual SVG)
   color uses --color-ink so it adapts to dark mode automatically. */
:root { --connection-color: var(--color-ink); }
.ntp--dark { --connection-color: var(--color-ink); /* #E8E4DB in dark mode — light line on dark bg */ }
.ntp--dark .conn-line { opacity: 0.82; } /* BX-145: reduce high-contrast aliasing visibility in dark mode */
.conn-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 0; }
.conn-line { stroke: var(--connection-color, #333); stroke-width: 2.5; fill: none; shape-rendering: geometricPrecision; vector-effect: non-scaling-stroke; pointer-events: stroke; cursor: default; }
.conn-line:hover { stroke-width: 4; cursor: pointer; }
.conn-line--selected { stroke-width: 4; stroke: var(--color-accent, #5b7cfa); filter: drop-shadow(0 0 3px var(--color-accent, #5b7cfa)); cursor: pointer; }
.conn-line--provisional { stroke-dasharray: 5,3; opacity: 0.7; vector-effect: non-scaling-stroke; }
.box-tool-btn { background: transparent; border: 0; cursor: pointer;
  color: var(--color-ink-soft); font-size: 12px; line-height: 1; padding: 0 4px;
  border-radius: 4px; opacity: 0.55; transition: opacity 120ms; flex-shrink: 0; }
.box-tool-btn:hover { opacity: 1; }
.box-tool-btn--on { opacity: 1; color: var(--color-accent, #A08060); }
body.cx--connecting, body.cx--connecting * { cursor: crosshair !important; }
/* BX-DEV-137++++: edge-midpoint connection hotspots — mouse hover shows + cursor */
.box-edge-anchor {
  position: absolute; z-index: 5; pointer-events: auto;
  width: 16px; height: 16px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity 150ms ease;
}
.box-edge-anchor::after {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--color-accent, #A08060); opacity: 0.6;
}
/* BX-CSS-DUAL-WRITE-SHARED: :hover .box-edge-anchor — both in one rule, safe */
.large-box:hover .box-edge-anchor,
.small-box:hover .box-edge-anchor { opacity: 0.7; }
.box-edge-anchor:hover { opacity: 1 !important; cursor: crosshair; }
.box-edge-anchor:hover::after { width: 10px; height: 10px; opacity: 1; }
/* Position: 4 edge midpoints */
.box-edge-anchor--top    { top: -8px; left: 50%; transform: translateX(-50%); }
.box-edge-anchor--bottom { bottom: -8px; left: 50%; transform: translateX(-50%); }
.box-edge-anchor--left   { left: -8px; top: 50%; transform: translateY(-50%); }
.box-edge-anchor--right  { right: -8px; top: 50%; transform: translateY(-50%); }

