  :root {
    --bg: #fbfbfa;
    --panel: #ffffff;
    --ink: #1f2328;
    --muted: #6e7781;
    --line: #e5e7eb;
    --line-strong: #d0d7de;
    --accent: #2f6feb;
    --accent-soft: #ddeafe;
    --ctx-fill: #ffffff;
    --ctx-stroke: #1f2328;
    --rel: #6e7781;
    --rel-strong: #1f2328;
    --selected: #2f6feb;
    --danger: #b91c1c;
    --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  }

  * { box-sizing: border-box; }
  html, body { height: 100%; margin: 0; overflow: hidden; }
  body {
    font-family: var(--sans);
    color: var(--ink);
    background: var(--bg);
    font-size: 13px;
    -webkit-font-smoothing: antialiased;
  }

  .app { display: flex; flex-direction: column; height: 100vh; }

  /* --- Top bar (two rows) ---
     Row 1 (right): tools (share / language / user).
     Row 2 (right): tabs.
     Brand + solution-label sit on the left and span both rows. */
  .topbar {
    display: grid;
    grid-template-columns: auto auto 1fr;
    grid-template-rows: 32px 32px;
    height: 64px;
    border-bottom: 1px solid var(--line);
    background: var(--panel);
    flex-shrink: 0;
  }
  .topbar > .brand,
  .topbar > .solution-label { grid-row: 1 / span 2; align-self: stretch; }
  .topbar > .brand          { grid-column: 1; }
  .topbar > .solution-label { grid-column: 2; }
  .topbar > .tabs           { grid-column: 3; grid-row: 2; justify-self: stretch; }
  .topbar > .perspectives   { grid-column: 3; grid-row: 1; justify-self: start; }
  /* Right column: Documents + Exports tabs (180 px total) form the visual
     anchor for the top-row icons and the zoom-controls row below — both pin
     themselves to the same 180 px so the leftmost icon / leftmost zoom button
     line up directly under Documents' left edge. */
  .tabs .tab[data-view="documents"] { margin-left: auto; border-left: 1px solid var(--line); width: 100px; padding: 0 12px; }
  .tabs .tab[data-view="exports"]   { border-left: 1px solid var(--line); width:  80px; padding: 0 12px; }
  .perspectives {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 12px;
    font-size: 11px;
    color: var(--ink);
  }
  .perspectives-title {
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    font-size: 10px;
  }
  .perspectives label {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    cursor: pointer;
    font-weight: 500;
  }
  .perspectives input { margin: 0; }
  .topbar > .topbar-tools   { grid-column: 3; grid-row: 1; justify-self: end;
                              display: flex; align-items: center; gap: 8px; }
  /* "Discuss…" — wide CTA-style button immediately left of the
     hamburger / icon row. Uses the brand-green palette to stand out
     from the muted icon buttons. Hidden whenever the user isn't
     signed in (the underlying endpoint requires auth). */
  .tb-discuss {
    appearance: none;
    border: 0;
    background: #0e9b6b;
    color: #ffffff;
    font: inherit;
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.01em;
    padding: 0 14px;
    height: 26px;
    border-radius: 5px;
    cursor: pointer;
    white-space: nowrap;
  }
  .tb-discuss:hover { background: #0c8a5e; }
  .tb-discuss[hidden] { display: none; }
  /* Brand + solution-label together span the same 200 px as the SHAPES sidebar
     below them and the Tab guidance + Guided tour pair in the footer, so the
     left edge of the app reads as one tidy vertical column. */
  .brand {
    appearance: none;
    border: 0;
    width: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0 4px;
    font: inherit;
    font-weight: 700;
    font-size: 10.5px;
    letter-spacing: 0.01em;
    line-height: 1.15;
    white-space: normal;
    word-break: break-word;
    color: #ffffff;
    background: #0e9b6b;
    cursor: pointer;
  }
  .brand:hover { background: #0c8a5e; }

  .solution-label {
    width: 140px;
    display: flex;
    align-items: center;
    padding: 0 10px;
    font-weight: 600;
    font-size: 12px;
    line-height: 1.15;
    white-space: normal;
    word-break: break-word;
    color: var(--ink);
    border-right: 1px solid var(--line);
    cursor: text;
  }
  .solution-label:hover { background: var(--bg); }
  /* Tiny pending-load indicator. Sits just below the solution name so
     a slow backend round-trip is visible to the user (and to me, when
     a flaky empty-briefing report comes in). Hidden by default; the
     openSolution / loadSolutionFromBackend pair toggles it. */
  .solution-loading {
    grid-column: 2;
    grid-row: 2;
    align-self: end;
    padding: 0 10px 4px;
    font-size: 10px;
    line-height: 1.1;
    color: var(--muted);
    font-style: italic;
  }
  .solution-loading[hidden] { display: none; }
  .solution-rename {
    align-self: center;
    margin: 0 10px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 3px 6px;
    border: 1px solid var(--accent);
    border-radius: 4px;
    outline: 0;
    background: #fff;
    color: var(--ink);
    min-width: 120px;
  }

  /* All-guidance modal: left nav with tab list, right pane with the
     selected guidance's rendered markdown. */
  .guidance-all {
    display: flex;
    gap: 14px;
    min-height: 420px;
    max-height: 70vh;
  }
  .guidance-all-nav {
    flex: 0 0 200px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    border-right: 1px solid var(--line);
    padding-right: 12px;
    overflow-y: auto;
  }
  .guidance-all-link {
    display: block;
    padding: 6px 10px;
    border-radius: 4px;
    color: var(--ink);
    text-decoration: none;
    font-size: 13px;
    line-height: 1.3;
  }
  .guidance-all-link:hover { background: #f3f4f6; }
  .guidance-all-link.active {
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 600;
  }
  .guidance-all-body {
    flex: 1;
    overflow-y: auto;
    padding-right: 6px;
    line-height: 1.5;
  }
  .guidance-all-body h1 { font-size: 18px; margin: 0 0 10px; }
  .guidance-all-body h2 { font-size: 15px; margin: 16px 0 6px; }
  .guidance-all-body h3 { font-size: 13px; margin: 14px 0 4px; }
  .guidance-all-body p, .guidance-all-body li { font-size: 13px; }
  .guidance-all-body ul, .guidance-all-body ol { padding-left: 22px; }

  /* Overview empty-state for anonymous users in backend mode. */
  .overview-signin-cta {
    max-width: 520px;
    margin: 28px auto;
    padding: 22px 26px;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 6px;
    text-align: center;
  }
  .overview-signin-cta h3 { margin: 0 0 10px; font-size: 18px; font-weight: 600; color: var(--ink); }
  .overview-signin-cta p { margin: 8px 0; font-size: 13px; color: var(--ink); line-height: 1.5; }
  .overview-signin-cta .overview-guidance-hint { color: var(--muted); font-size: 12px; margin-top: 14px; }
  .overview-signin-cta a { color: var(--accent); text-decoration: none; }
  .overview-signin-cta a:hover { text-decoration: underline; }

  /* AI Assistant panel — fixed to the left side, overlays the per-tab
     palette ("Shapes") area when the user opens it via the AI topbar
     icon. Only shown when body.ai-on (i.e. ?ai=true is set in
     backend mode) AND the user clicked the icon. */
  .ai-panel {
    position: fixed;
    top: 32px;                 /* below the topbar + tabs (.tabs height is 32px) */
    left: 0;
    bottom: 24px;              /* leave room for the footer */
    width: 280px;
    background: var(--panel);
    border-right: 1px solid var(--line);
    display: none;
    flex-direction: column;
    z-index: 40;
    font: 13px/1.4 var(--sans);
  }
  body.ai-active .ai-panel { display: flex; }
  body.ai-active .map-sidebar,
  body.ai-active .summary-palette,
  body.ai-active .doc-palette { visibility: hidden; }
  .ai-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    border-bottom: 1px solid var(--line);
  }
  .ai-panel-title {
    font-weight: 700;
    font-size: 13px;
    color: var(--ink);
  }
  .ai-panel-close {
    appearance: none;
    background: transparent;
    border: 0;
    font-size: 18px;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 3px;
  }
  .ai-panel-close:hover { background: #f3f4f6; color: var(--ink); }
  .ai-panel-scope {
    padding: 6px 12px;
    font-size: 11px;
    color: var(--muted);
    background: #fff7ed;
    border-bottom: 1px solid var(--line);
  }
  .ai-messages {
    flex: 1;
    overflow-y: auto;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .ai-msg {
    padding: 8px 10px;
    border-radius: 6px;
    white-space: pre-wrap;
    word-wrap: break-word;
    font-size: 12.5px;
  }
  .ai-msg.user      { background: var(--accent-soft); color: var(--ink); align-self: flex-end; max-width: 90%; }
  .ai-msg.assistant { background: #f3f4f6;           color: var(--ink); align-self: flex-start; max-width: 95%; }
  .ai-msg.error     { background: #fdeaea;           color: var(--danger); align-self: stretch; font-size: 11px; }
  .ai-msg.loading   { background: #f3f4f6;           color: var(--muted); align-self: flex-start; font-style: italic; }
  .ai-input {
    border-top: 1px solid var(--line);
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: var(--panel);
  }
  .ai-input textarea {
    appearance: none;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    padding: 6px 8px;
    font: inherit;
    font-size: 13px;
    color: var(--ink);
    resize: vertical;
    min-height: 60px;
    outline: 0;
  }
  .ai-input textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-soft);
  }
  .ai-input-actions { display: flex; justify-content: flex-end; }
  .ai-send {
    appearance: none;
    background: var(--accent);
    color: #fff;
    border: 0;
    padding: 5px 14px;
    border-radius: 4px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
  }
  .ai-send:hover { background: #1e58c4; }
  .ai-send:disabled { background: var(--muted); cursor: not-allowed; }
  /* The topbar AI icon — visible only when ?ai=true is set. */
  body.ai-on #tb-ai { display: inline-flex; }
  body:not(.ai-on) #tb-ai { display: none; }
  body.ai-active #tb-ai { color: var(--accent); }

  /* In overview mode, the solution-scoped chrome (label + tabs) hides */
  .app.in-overview .solution-label,
  .app.in-overview .tabs,
  .app.in-overview #tb-share,
  .app.in-overview .tb-menu-item[data-menu="versions"],
  .app.in-overview .tb-menu-item[data-menu="settings"],
  .app.in-overview #overview-import-btn { display: none; }
  /* Import JSON only makes sense from the Solutions overview, so it's
     scoped to the hamburger there. Hidden when the user is inside a
     solution. Also hidden when the user isn't signed in — the import
     POST requires auth so the menu entry would be a dead end. */
  .app:not(.in-overview) .tb-menu-item[data-menu="import-json"] { display: none; }
  body:not(.signed-in)   .tb-menu-item[data-menu="import-json"] { display: none; }
  /* Management dashboard + My Discussions are admin-only — hide the
     entry points for everyone else. Also scoped to the overview
     screen so they don't take menu real-estate while the user is
     deep inside a single solution. */
  body:not(.is-admin) .tb-menu-item[data-menu="management"],
  body:not(.is-admin) .tb-menu-item[data-menu="discussions"] { display: none; }
  .app:not(.in-overview) .tb-menu-item[data-menu="management"],
  .app:not(.in-overview) .tb-menu-item[data-menu="discussions"] { display: none; }

  /* --- Management dashboard (full-viewport overlay) ----------------- */
  .mgmt-overlay {
    position: fixed; inset: 0;
    background: #f6f7f9;
    z-index: 1000;
    display: flex; flex-direction: column;
    overflow: auto;
  }
  .mgmt-overlay[hidden] { display: none; }
  .mgmt-overlay .mgmt-head {
    display: flex; align-items: center; gap: 12px;
    padding: 18px 28px 0;
  }
  .mgmt-overlay .mgmt-range {
    appearance: none; -webkit-appearance: none;
    background: #fff; border: 1px solid var(--line);
    border-radius: 6px; padding: 6px 28px 6px 12px;
    font: inherit; font-size: 13px; color: var(--ink);
    cursor: pointer;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="%23666" stroke-width="2" stroke-linecap="round"><path d="M6 9 l6 6 6 -6"/></svg>');
    background-repeat: no-repeat;
    background-position: right 8px center;
  }
  .mgmt-overlay .mgmt-close {
    margin-left: auto;
    appearance: none; border: 0; background: transparent;
    width: 32px; height: 32px; border-radius: 6px;
    cursor: pointer; color: var(--muted);
    font-size: 20px; line-height: 1;
  }
  .mgmt-overlay .mgmt-close:hover { background: rgba(0,0,0,0.06); color: var(--ink); }
  .mgmt-overlay h1 {
    font-size: 34px; font-weight: 400;
    margin: 18px 28px 28px;
    color: var(--ink);
  }
  .mgmt-overlay .mgmt-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 28px;
    padding: 0 28px 32px;
  }
  .mgmt-overlay .mgmt-card {
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 18px 20px 14px;
  }
  .mgmt-overlay .mgmt-card-label {
    font-size: 14px; color: var(--muted);
    margin: 0 0 10px;
  }
  .mgmt-overlay .mgmt-card svg {
    display: block; width: 100%; height: 240px;
  }
  .mgmt-overlay .mgmt-empty {
    text-align: center; color: var(--muted);
    font-size: 13px; padding: 90px 0;
  }
  /* SVG styling */
  .mgmt-grid .mgmt-grid-line { stroke: #e5e7eb; stroke-width: 1; }
  .mgmt-grid .mgmt-axis-text { fill: #6b7280; font-size: 11px; }
  .mgmt-grid .mgmt-line       { fill: none; stroke-width: 1.6; }
  .mgmt-grid .mgmt-line-dark  { stroke: #1f2a44; }
  .mgmt-grid .mgmt-line-green { stroke: #0e9b6b; }
  .mgmt-grid .mgmt-dot-dark   { fill: #1f2a44; }
  .mgmt-grid .mgmt-dot-green  { fill: #0e9b6b; }
  /* Transparent hit-targets over each 2 px data dot. r=10 makes the
     point hoverable without changing the visual. */
  .mgmt-grid .mgmt-hit { fill: transparent; cursor: default; }

  /* Tooltip — same dark navy as the Discuss send button so it reads as
     a single design language across modals. */
  .mgmt-tooltip {
    position: fixed;
    background: #1f2a44;
    color: #fff;
    padding: 5px 9px;
    border-radius: 4px;
    font-size: 12px;
    line-height: 1.3;
    pointer-events: none;
    z-index: 1100;
    transform: translate(-50%, calc(-100% - 6px));
    white-space: nowrap;
    box-shadow: 0 4px 12px rgba(0,0,0,0.18);
  }
  .mgmt-tooltip[hidden] { display: none; }

  /* --- Heatmap (world map under the 4 line-charts) ----------------- */
  .mgmt-overlay .mgmt-map-card {
    margin: 0 28px 32px;
    padding: 18px 20px 14px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 8px;
  }
  .mgmt-overlay .mgmt-map-card-label {
    font-size: 14px; color: var(--muted);
    margin: 0 0 10px;
  }
  .mgmt-overlay .mgmt-map-card .mgmt-map-hint {
    color: var(--muted); font-size: 12px;
    margin: 0 0 8px;
  }
  .mgmt-overlay .mgmt-map-container { position: relative; }
  .mgmt-overlay .mgmt-map-container svg { display: block; width: 100%; height: auto; }
  /* Country default — pale grey when no data, otherwise the brand green is
     applied via inline fill-opacity (set in renderHeatmap). */
  .mgmt-overlay .world-countries path {
    fill: #0e9b6b;
    fill-opacity: 0;
    stroke: #d0d4dc;
    stroke-width: 0.4;
    transition: fill-opacity 0.15s ease;
    cursor: default;
  }
  .mgmt-overlay .world-countries path.no-data {
    /* Visible fill-of-last-resort so countries with 0 events still show up
       as something other than the background. */
    fill: #eef0f3;
    fill-opacity: 1;
  }
  .mgmt-overlay .world-countries path:hover { stroke: #1f2a44; stroke-width: 1; }

  /* --- Live-event pings on the heatmap ----------------------------- */
  .mgmt-overlay .mgmt-map-container { /* needs to be a positioning context */
    overflow: hidden;
  }
  .mgmt-overlay .mgmt-ping {
    position: absolute;
    pointer-events: none;
    transform: translate(-50%, -50%);
    z-index: 5;
  }
  .mgmt-overlay .mgmt-ping-dot {
    width: 10px; height: 10px;
    background: #0e9b6b;
    border: 2px solid #fff;
    border-radius: 50%;
    box-shadow: 0 0 0 0 rgba(14, 155, 107, 0.55);
    animation: mgmt-ping-pulse 1.6s ease-out infinite;
  }
  /* Different ping colours per event kind so the admin can read the
     map at a glance. */
  .mgmt-overlay .mgmt-ping[data-kind="design"]  .mgmt-ping-dot { background: #1f2a44; box-shadow: 0 0 0 0 rgba(31,42,68,0.55); }
  .mgmt-overlay .mgmt-ping[data-kind="account"] .mgmt-ping-dot { background: #d97706; box-shadow: 0 0 0 0 rgba(217,119,6,0.55); }
  @keyframes mgmt-ping-pulse {
    0%   { box-shadow: 0 0 0 0   currentColor; }
    70%  { box-shadow: 0 0 0 18px transparent; }
    100% { box-shadow: 0 0 0 0   transparent; }
  }
  .mgmt-overlay .mgmt-ping-label {
    position: absolute;
    left: 14px; top: -4px;
    font-size: 11px; line-height: 1.2;
    background: rgba(31,42,68,0.92);
    color: #fff;
    padding: 3px 7px;
    border-radius: 4px;
    white-space: nowrap;
    pointer-events: none;
  }
  .mgmt-overlay .mgmt-ping.fading {
    transition: opacity 1.2s ease-out;
    opacity: 0;
  }

  /* --- My Discussions overlay -------------------------------------- */
  .disc-overlay {
    position: fixed; inset: 0;
    background: #f6f7f9;
    z-index: 1000;
    display: flex; flex-direction: column;
    overflow: auto;
  }
  .disc-overlay[hidden] { display: none; }
  .disc-overlay .disc-head {
    display: flex; align-items: center; gap: 12px;
    padding: 18px 28px 0;
  }
  .disc-overlay .disc-toggle-label {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 13px; color: var(--ink);
    cursor: pointer;
  }
  .disc-overlay .disc-close {
    margin-left: auto;
    appearance: none; border: 0; background: transparent;
    width: 32px; height: 32px; border-radius: 6px;
    cursor: pointer; color: var(--muted);
    font-size: 20px; line-height: 1;
  }
  .disc-overlay .disc-close:hover { background: rgba(0,0,0,0.06); color: var(--ink); }
  .disc-overlay h1 {
    font-size: 34px; font-weight: 400;
    margin: 18px 28px 28px;
    color: var(--ink);
  }
  .disc-overlay .disc-list {
    margin: 0 28px 32px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 8px;
    overflow: hidden;
  }
  .disc-overlay .disc-empty {
    text-align: center; padding: 60px 0;
    color: var(--muted); font-size: 13px;
  }
  .disc-overlay .disc-row {
    display: grid;
    grid-template-columns: 220px 1fr 110px 80px;
    gap: 16px;
    padding: 14px 18px;
    border-top: 1px solid var(--line);
    cursor: pointer;
    align-items: center;
    font-size: 13px;
  }
  .disc-overlay .disc-row > * { min-width: 0; }   /* let grid cells truncate */
  .disc-overlay .disc-row:first-child { border-top: 0; }
  .disc-overlay .disc-row:hover { background: var(--accent-soft); }
  .disc-overlay .disc-row-meta  { color: var(--muted); font-size: 12px; }
  .disc-overlay .disc-row-meta .disc-row-email {
    display: block; margin-top: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .disc-overlay .disc-row-text  {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--ink);
  }
  .disc-overlay .disc-badge {
    display: inline-block;
    font-size: 11px;
    padding: 2px 7px;
    border-radius: 4px;
    font-weight: 600;
  }
  .disc-overlay .disc-badge.open    { background: #d1fae5; color: #047857; }
  .disc-overlay .disc-badge.closed  { background: #e5e7eb; color: #4b5563; }
  .disc-overlay .disc-badge.share   { background: #ddeafe; color: #1e40af; font-weight: 500; }
  .disc-overlay .disc-badge.replied { background: #fef3c7; color: #92400e; font-weight: 500; }
  /* Stack the status + replied badges vertically in the last column. */
  .disc-overlay .disc-status-cell {
    display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  }

  /* Read-only mode — applied to <body> when the signed-in user is in the
     current solution's sharedReaders but isn't the owner or an editor.
     Almost every editing affordance grays out or hides; explicit allow-
     listed bits (notes + replies) stay live via :not(...) selectors. */
  body.read-only #tb-share { display: none; }
  /* Live-presence pill sits at the right edge of the footer next to
     the read-only banner. Hidden on overview and when nobody else is
     here; renderPresenceIndicator() toggles its display inline. */
  #backend-presence {
    display: none;
    align-items: center;
    padding: 0 12px;
    gap: 4px;
    border-left: 1px solid var(--line);
  }
  /* Read-only banner — lives inside the footer so it stays visible
     without overlapping the floating "Discuss…" button at the top
     of the solution chrome. Hidden by default; revealed when
     body.read-only is set. */
  body.read-only .ro-banner { display: flex; }
  .ro-banner {
    display: none;
    align-items: center;
    padding: 0 14px;
    background: #fff7ed;
    color: #92400e;
    font-size: 11px;
    font-weight: 500;
    border-left: 1px solid #f6c896;
  }
  /* Hide the Edit / Preview toggles on the markdown-driven tabs so the
     prose can only be read. */
  body.read-only .view-toggle-edit { display: none !important; }
  /* Whenever an .editor textarea is paired with a .preview, the read-only
     viewer only ever needs the preview. */
  body.read-only .editor { display: none !important; }
  body.read-only .preview { display: block !important; }
  /* Canvas palette: grey out every shape except the Note + Relationship
     (those two stay live so a reader can still add questions / problems
     and reply-thread relations onto the diagram). The MD-tab note-palette
     items (Strategy briefing / Values / UI-views / Summary / Exports)
     drag via data-summary-shape / data-doc-shape — keep those clickable
     too. */
  body.read-only .palette-item:not(.pal-note):not(.pal-rel):not([data-summary-shape]):not([data-doc-shape]) {
    opacity: 0.35;
    pointer-events: none;
    cursor: not-allowed;
    filter: grayscale(0.8);
  }
  /* Side-palette toggles (Show Bounded Contexts / Show Verbs / Show
     resolved Q&P / Bounded contexts checklists in the right panel etc.)
     stay clickable — they only change view, not state. The non-Note
     drag-onto-canvas guard is enforced in JS too (startPaletteDrag). */

  /* Props panel — disable every editable input except those tagged
     .ro-allow (used by note replies). Selects + buttons disabled via
     pointer-events; text inputs / textareas blocked through readonly
     attr set in JS post-render. CSS just nudges the visual weight so
     it's obvious nothing is going to take a change. */
  body.read-only .props-body input:not(.ro-allow),
  body.read-only .props-body textarea:not(.ro-allow),
  body.read-only .props-body select:not(.ro-allow),
  body.read-only .props-body button:not(.ro-allow) {
    opacity: 0.55;
    cursor: not-allowed;
  }
  body.read-only .props-body input[type="checkbox"]:not(.ro-allow),
  body.read-only .props-body input[type="radio"]:not(.ro-allow) {
    pointer-events: none;
  }
  /* Summary tab carries inline form inputs (Revenue, Cost, Margin etc.)
     plus a Set-cost / Pay-per-usage radio group — all of those need to be
     read-only too. The .cost-mode labels also need pointer-events:none
     because clicking a label toggles the wrapped radio even when the
     input itself was greyed out. */
  body.read-only .view-summary input,
  body.read-only .view-summary select,
  body.read-only .view-summary textarea,
  body.read-only .view-summary .cost-mode label {
    pointer-events: none;
    opacity: 0.7;
  }
  /* UI-views' Usage pattern select (+ its "Other…" fallback input). */
  body.read-only .view-ui .ui-props select,
  body.read-only .view-ui .ui-props input { pointer-events: none; opacity: 0.7; }
  /* EventStorming's phase-bar radios — same pattern as cost-mode: lock
     both the input and its wrapping label so clicks don't fall through. */
  body.read-only .es-phase-bar label,
  body.read-only .es-phase-bar input { pointer-events: none; opacity: 0.7; }
  /* Pipeline + Agentic shapes render their stage / step checkboxes inside
     foreignObject. Disable those — and the "+ Add row" button — so the
     state on each pipeline is frozen from the reader's perspective. The
     <label> wrappers (.pipe-stage, .pipe-custom-stage) need pointer-events
     too: clicking a label's text toggles the wrapped input even when the
     input itself has pointer-events: none. */
  body.read-only .pipeline foreignObject input,
  body.read-only .pipeline foreignObject button,
  body.read-only .pipeline foreignObject label,
  body.read-only .agentic foreignObject input,
  body.read-only .agentic foreignObject button,
  body.read-only .agentic foreignObject label { pointer-events: none; opacity: 0.7; }
  /* On-canvas inline editors (rename node, edit note text) also disabled
     — they're driven by JS guards too, this is just the visual cue. */
  body.read-only .inline-edit { display: none !important; }
  /* The "+ New session" button in EventStorming session sidebar; the BC
     "+" add button; module variant pickers; pipeline custom-row add etc.
     All these are decorated by JS at render time and can carry a
     conventional read-only class. CSS nudges visual weight. */
  body.read-only .pipe-custom-add,
  body.read-only .ns-btn:not(.ro-allow),
  body.read-only .es-new-session,
  body.read-only #overview-new-btn { opacity: 0.55; pointer-events: none; }
  /* Modals (login, etc.) must stay fully interactive — the user needs to
     be able to sign out / sign in even when the currently-open solution
     is read-only, otherwise they're trapped. This override re-enables
     every control inside the modal backdrop, beating the read-only rules
     above by virtue of being later in the cascade. */
  body.read-only #modal-backdrop input,
  body.read-only #modal-backdrop textarea,
  body.read-only #modal-backdrop select,
  body.read-only #modal-backdrop button,
  body.read-only #modal-backdrop label,
  body.read-only #modal-backdrop .ns-btn {
    opacity: 1 !important;
    pointer-events: auto !important;
    cursor: auto;
  }
  body.read-only #modal-backdrop button,
  body.read-only #modal-backdrop .ns-btn { cursor: pointer; }
  .tabs { display: flex; }
  .tab {
    appearance: none;
    background: transparent;
    border: 0;
    border-right: 1px solid var(--line);
    padding: 0 16px;
    font: inherit;
    font-size: 12px;
    color: var(--muted);
    cursor: pointer;
    position: relative;
  }
  .tab:hover { color: var(--ink); }
  .tab.active {
    color: var(--ink);
    background: var(--bg);
  }
  .tab.active::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: -1px;
    height: 4px;
    background: var(--accent);
  }
  .topbar-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 0 8px 0 4px;
    border-left: 1px solid var(--line);
    width: 180px;                       /* match Documents + Exports below */
    justify-content: space-between;     /* spread the four icons so the
                                            leftmost sits under Documents */
  }
  .tb-icon {
    appearance: none;
    background: transparent;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    height: 26px;
    min-width: 28px;
    padding: 0 6px;
    border-radius: 5px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .tb-icon:hover { background: var(--bg); color: var(--ink); }
  .tb-icon svg { display: block; }
  .tb-lang {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
  }
  /* Hamburger dropdown to the left of Share. */
  .tb-menu-wrap { position: relative; }
  .tb-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    min-width: 160px;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 6px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 1px;
    z-index: 50;
  }
  .tb-menu[hidden] { display: none; }
  .tb-menu-item {
    appearance: none;
    background: transparent;
    border: 0;
    font: inherit;
    font-size: 13px;
    color: var(--ink);
    text-align: left;
    padding: 6px 10px;
    border-radius: 4px;
    cursor: pointer;
  }
  .tb-menu-item:hover { background: var(--accent-soft); color: var(--accent); }

  /* --- Footer --- */
  .footer {
    display: flex;
    align-items: stretch;
    height: 30px;
    border-top: 1px solid var(--line);
    background: var(--panel);
    flex-shrink: 0;
  }
  .app.in-overview .msg-panel { display: none; }
  /* In overview mode the footer stays — but only the two solution-agnostic
     buttons (Tab guidance and Guided tour) make sense. Solution-scoped
     ones (Messages, Reload, etc.) hide. */
  .app.in-overview #footer-messages,
  .app.in-overview #footer-reload,
  .app.in-overview #footer-versions,
  .app.in-overview #footer-guidance { display: none; }
  .footer-btn {
    appearance: none;
    background: transparent;
    border: 0;
    border-right: 1px solid var(--line);
    padding: 0 14px;
    font: inherit;
    font-size: 11.5px;
    color: var(--ink);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .footer-btn:hover { background: var(--bg); }
  /* First two footer buttons share the left column width with brand+solution
     label (top) and the SHAPES sidebar (middle), so the left edge of the app
     reads as one tidy 200 px column. Padding is shrunk to 0 10px so the text
     fits on one row at the smaller widths. */
  #footer-guidance, #footer-tour {
    justify-content: center;
    white-space: nowrap;
    padding: 0 10px;
  }
  #footer-guidance { width: 105px; }
  #footer-tour     { width:  95px; }
  .footer-spacer { flex: 1; }
  .msg-dot {
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--line-strong);
    flex-shrink: 0;
  }
  .msg-dot.sev-comment { background: #2f6feb; }
  .msg-dot.sev-warning { background: #d29200; }
  .msg-dot.sev-error   { background: #b91c1c; }
  .msg-count {
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--line-strong);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    display: none;
    align-items: center;
    justify-content: center;
  }
  .msg-count.show { display: flex; }
  .msg-count.sev-comment { background: #2f6feb; }
  .msg-count.sev-warning { background: #d29200; }
  .msg-count.sev-error   { background: #b91c1c; }

  /* Messages panel (expands above the footer) */
  .msg-panel {
    flex-shrink: 0;
    max-height: 38vh;
    overflow: auto;
    border-top: 1px solid var(--line);
    background: var(--panel);
    padding: 10px 16px;
  }
  .msg-panel:empty::before {
    content: "No messages for this tab.";
    color: var(--muted);
    font-size: 12px;
  }
  .msg-item {
    display: flex;
    gap: 9px;
    padding: 8px 10px;
    border-radius: 6px;
    margin-bottom: 7px;
    font-size: 12px;
    line-height: 1.45;
    border: 1px solid var(--line);
  }
  .msg-item:last-child { margin-bottom: 0; }
  .msg-item .sev-tag {
    flex-shrink: 0;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 2px 7px;
    border-radius: 4px;
    height: fit-content;
    color: #fff;
  }
  .msg-item.sev-comment { background: #f0f5ff; border-color: #cdddfb; }
  .msg-item.sev-comment .sev-tag { background: #2f6feb; }
  .msg-item.sev-warning { background: #fff7e6; border-color: #ffe0a3; }
  .msg-item.sev-warning .sev-tag { background: #d29200; }
  .msg-item.sev-error   { background: #fdecec; border-color: #f6c6c6; }
  .msg-item.sev-error .sev-tag { background: #b91c1c; }

  /* Modal (Assistant / Guidance) */
  .modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.38);
    display: flex;
    align-items: center;
    justify-content: center;
    /* Higher than the full-screen overlays (.mgmt-overlay,
       .disc-overlay) so a modal opened from inside them floats on
       top instead of getting trapped behind. */
    z-index: 1200;
  }
  .modal-backdrop[hidden] { display: none; }
  .modal {
    background: #fff;
    border-radius: 10px;
    width: min(680px, 92vw);
    max-height: 82vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 12px 40px rgba(0,0,0,0.25);
  }
  .modal.modal-lg {
    width: min(900px, 94vw);
    max-height: 90vh;
  }
  .modal.modal-lg .modal-body { min-height: 60vh; }
  .modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    border-bottom: 1px solid var(--line);
  }
  .modal-title { margin: 0; font-size: 15px; }
  .modal-close {
    appearance: none;
    background: transparent;
    border: 0;
    font-size: 22px;
    line-height: 1;
    color: var(--muted);
    cursor: pointer;
  }
  .modal-close:hover { color: var(--ink); }
  .modal-body {
    padding: 16px 20px;
    overflow: auto;
    font-size: 13px;
    line-height: 1.55;
  }
  .modal-body h1 { font-size: 18px; }
  .modal-body h2 { font-size: 16px; }
  .modal-body h3 { font-size: 14px; }
  .modal-body p:first-child { margin-top: 0; }
  /* MD lists in guidance modals get the same vertical spacing as the
     on-screen Strategy briefing preview, otherwise the bullets read as one
     dense block. */
  .modal-body ul, .modal-body ol { margin: 6px 0; padding-left: 22px; }
  .modal-body li { margin: 8px 0; }
  .modal-body code {
    font-family: var(--mono);
    background: var(--bg);
    padding: 1px 4px;
    border-radius: 3px;
  }
  .modal-body pre {
    background: var(--bg);
    padding: 10px 12px;
    border-radius: 6px;
    overflow: auto;
  }
  .assistant-options {
    display: flex;
    gap: 14px;
    margin-top: 14px;
  }
  .assistant-card {
    flex: 1;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 14px;
  }
  .assistant-card h4 { margin: 0 0 6px; font-size: 13px; }
  .assistant-card p { margin: 0; font-size: 12px; color: var(--muted); }

  /* New-solution dialog */
  .ns-field { margin-bottom: 16px; }
  .ns-field > label.ns-label {
    display: block;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    margin-bottom: 6px;
  }
  .ns-field input[type=text],
  .ns-field select {
    width: 100%;
    font: inherit;
    font-size: 13px;
    padding: 7px 9px;
    border: 1px solid var(--line-strong);
    border-radius: 6px;
    box-sizing: border-box;
  }
  .ns-opt {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 7px 0;
    font-size: 13px;
  }
  .ns-opt input[type=radio] { margin-top: 2px; }
  .ns-opt .ns-opt-main { flex: 1; }
  .ns-opt select { margin-top: 7px; }
  .ns-opt select:disabled { opacity: 0.45; }
  /* Fade out an option whose radio is disabled (Review / Old when empty). */
  .ns-opt:has(input[type=radio]:disabled) { opacity: 0.45; cursor: not-allowed; }
  .ns-opt:has(input[type=radio]:disabled) * { cursor: not-allowed; }
  .ns-review-uploads {
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin-top: 8px;
  }
  .ns-up {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-size: 11px;
    color: var(--muted);
  }
  .ns-up input[type=file] { font-size: 11px; }
  .ns-up input[type=file]:disabled { opacity: 0.45; }
  .ns-tour {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 13px;
    margin: 4px 0 18px;
  }
  .ns-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
  }
  .ns-btn {
    appearance: none;
    border: 1px solid var(--line-strong);
    background: #fff;
    font: inherit;
    font-size: 13px;
    padding: 8px 16px;
    border-radius: 6px;
    cursor: pointer;
  }
  .ns-btn:hover { background: var(--bg); }
  .ns-btn.primary {
    border-color: #0e9b6b;
    background: #0e9b6b;
    color: #fff;
    font-weight: 600;
  }
  .ns-btn.primary:hover { background: #0c8a5e; }

  /* Guided tour card (non-modal, floats above the footer) */
  .tour-card {
    position: fixed;
    right: 22px;
    bottom: 44px;
    width: 598px;
    max-height: 78vh;
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid var(--line-strong);
    border-radius: 10px;
    box-shadow: 0 10px 34px rgba(0,0,0,0.22);
    z-index: 45;
  }
  .tour-card[hidden] { display: none; }
  .tour-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 11px 14px;
    border-bottom: 1px solid var(--line);
  }
  .tour-head .tour-step {
    font-size: 11px;
    color: var(--muted);
    font-weight: 600;
  }
  .tour-head h4 { margin: 2px 0 0; font-size: 14px; }
  .tour-body {
    padding: 12px 16px;
    overflow: auto;
    font-size: 12.5px;
    line-height: 1.55;
  }
  .tour-body h1 { font-size: 16px; }
  .tour-body h2 { font-size: 14px; }
  .tour-body p:first-child { margin-top: 0; }
  /* MD lists in the guided tour get the same vertical breathing room as
     elsewhere — otherwise the bullets read as one dense block. */
  .tour-body ul, .tour-body ol { margin: 6px 0; padding-left: 22px; }
  .tour-body li { margin: 8px 0; }
  .tour-actions {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 11px 14px;
    border-top: 1px solid var(--line);
  }

  /* --- Views --- */
  main { flex: 1; overflow: hidden; position: relative; }
  .view { position: absolute; inset: 0; display: none; }
  .view.active { display: flex; }

  /* --- Summary (approximate monthly cost) --- */
  .view-summary {
    flex-direction: row;
    background: var(--bg);
    padding: 0;
    overflow: hidden;
  }
  .view-summary .summary-inner {
    flex: 1;
    overflow: auto;
    padding: 32px 40px;
    min-width: 0;
  }
  .summary-palette {
    flex: 0 0 200px;
    border-right: 1px solid var(--line);
    background: var(--panel);
    padding: 12px;
    overflow: auto;
  }
  .summary-palette h4 {
    margin: 0 0 8px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
  }
  /* Highlight the section when a Note is dragged over it */
  .sum-section.drag-over {
    background: #fff7e6;
    outline: 1px dashed #d29200;
    outline-offset: 4px;
    border-radius: 6px;
  }
  /* Inline note cards inside a Summary section */
  .summary-notes { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
  .summary-note-card {
    border: 1px solid var(--ctx-stroke);
    border-radius: 6px;
    background: #fff7b3;
    padding: 8px 10px;
    font-size: 12px;
    color: var(--ink);
    display: flex; flex-direction: column; gap: 6px;
  }
  .summary-note-card.type-question { background: #dbeafe; border-color: #2563eb; }
  .summary-note-card.type-problem  { background: #fed7aa; border-color: #ea580c; }
  .summary-note-card.resolved      { background: #d1fae5; border-color: #16a34a; }
  .summary-note-card .snc-head {
    display: flex; align-items: center; gap: 8px;
  }
  .summary-note-card .snc-type {
    font: inherit; font-size: 11px;
    padding: 3px 6px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: rgba(255,255,255,0.7);
  }
  .summary-note-card .snc-resolved { font-size: 11px; color: var(--ink); display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
  .summary-note-card .snc-spacer { flex: 1; }
  .summary-note-card .snc-del {
    appearance: none; background: transparent; border: 0;
    width: 22px; height: 22px; border-radius: 4px;
    color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer;
  }
  .summary-note-card .snc-del:hover { color: var(--danger); background: rgba(255,255,255,0.6); }
  .summary-note-card .snc-text {
    font: inherit; font-size: 12px;
    padding: 6px 8px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: rgba(255,255,255,0.7);
    resize: vertical;
    min-height: 50px;
  }
  /* --- Exports --- */
  .view-exports {
    flex-direction: row;
    background: var(--bg);
    padding: 0;
    overflow: hidden;
  }
  .exports-inner {
    flex: 1;
    overflow: auto;
    padding: 32px 40px;
    max-width: 640px;
    min-width: 0;
  }
  .exports-inner h2 {
    margin: 0 0 6px;
    font-size: 16px;
    font-weight: 600;
    color: var(--ink);
  }
  .exports-inner .export-subhead {
    margin: 36px 0 6px;
    padding-top: 18px;
    border-top: 1px solid var(--line);
    font-size: 14px;
    font-weight: 600;
    color: var(--ink);
  }
  .exports-inner .sub {
    margin: 0 0 22px;
    font-size: 12px;
    color: var(--muted);
  }
  .export-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 26px;
  }
  .export-item {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 13px;
    color: var(--ink);
    cursor: pointer;
  }
  .export-item input { margin: 0; }
  .export-item.export-sub { margin-left: 24px; font-size: 12px; }
  .export-group-header {
    appearance: none; background: transparent; border: 0;
    font: inherit; font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--muted);
    display: flex; align-items: center; gap: 6px;
    padding: 0;
    margin-top: 18px;
    cursor: default;
    text-align: left;
  }
  .export-group-header[hidden] { display: none; }
  .export-spacer-above { margin-top: 10px; }
  .export-group-chev { display: none; }
  .export-group {
    display: flex; flex-direction: column; gap: 12px;
    margin-top: 10px;
    margin-left: 14px;
  }
  .export-group[hidden] { display: none; }
  .export-item.export-sub input:disabled + *,
  .export-item.export-sub:has(input:disabled) { color: var(--muted); cursor: default; }
  /* Two side-by-side export items (e.g. Values & Principles + Extracted Practices). */
  .export-row { display: flex; gap: 18px; align-items: center; }
  .export-row .export-item { flex: 0 0 auto; }
  .export-start {
    appearance: none;
    border: 0;
    background: #0e9b6b;
    color: #fff;
    font: inherit;
    font-weight: 600;
    font-size: 13px;
    padding: 9px 18px;
    border-radius: 6px;
    cursor: pointer;
  }
  .export-start:hover { background: #0c8a5e; }
  /* Breathing room above the JSON-export button so it doesn't crowd
     the "Include UI-view images" checkbox that sits directly above. */
  #btn-export-json { margin-top: 18px; }

  .summary-inner { max-width: 900px; }
  /* Strategy briefing & UI-views: cap reading width (and inline images)
     so paragraphs and pasted screenshots don't go full-screen. The
     :not(.note-preview) guard keeps the palette icon's <span class="preview
     note-preview"> from inheriting the same centring rule. */
  .view-start .preview:not(.note-preview),
  .view-ui    .preview:not(.note-preview) { max-width: 900px; margin-inline: auto; }
  .summary-inner h2 {
    margin: 30px 0 6px;
    font-size: 16px;
    font-weight: 600;
    color: var(--ink);
  }
  .summary-inner > h2:first-child { margin-top: 0; }
  /* Collapsible Summary sections */
  .sum-section { margin-top: 30px; }
  .sum-section:first-child { margin-top: 0; }
  .sum-header {
    appearance: none;
    background: transparent;
    border: 0;
    width: 100%;
    text-align: left;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 6px;
    padding: 0;
    font: inherit;
    font-size: 20px;
    font-weight: 600;
    color: var(--ink);
    cursor: pointer;
  }
  .sum-header:hover { color: var(--accent); }
  .sum-header .sum-chev {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1;
    color: var(--muted);
    border: 1px solid var(--line-strong);
    border-radius: 3px;
  }
  .sum-header:hover .sum-chev { color: var(--accent); border-color: var(--accent); }
  .sum-content[hidden] { display: none; }
  /* Per-tab breakdown list inside Digital autonomy / Notes sections —
     each row is a clickable shortcut to that tab. */
  .sum-breakdown {
    list-style: none;
    margin: 6px 0 0;
    padding: 0;
  }
  .sum-breakdown li { margin: 4px 0; }
  .sum-jump {
    display: inline-block;
    color: var(--accent);
    text-decoration: none;
    font-size: 13px;
  }
  .sum-jump:hover { text-decoration: underline; }
  .summary-inner .sub {
    margin: 0 0 22px;
    font-size: 12px;
    color: var(--muted);
  }
  .cost-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 0;
    border-bottom: 1px solid var(--line);
  }
  .cost-row .label { font-size: 13px; color: var(--ink); }
  .cost-row .label small { display: block; color: var(--muted); font-size: 11px; margin-top: 2px; }
  .cost-row .amount { font-size: 18px; font-weight: 600; color: var(--ink); white-space: nowrap; }
  .cost-row.total { border-bottom: 0; border-top: 2px solid var(--line-strong); margin-top: 6px; }
  .cost-row.total .amount { color: var(--accent); }
  .summary-inner h3 {
    margin: 26px 0 2px;
    font-size: 11px;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }
  .cost-row.mini { padding: 9px 0; }
  .cost-row.mini .label { font-size: 12px; color: var(--muted); }
  .cost-row.mini .amount { font-size: 14px; font-weight: 600; color: var(--ink); }
  .bd-toggle {
    appearance: none;
    margin: 10px 0 0;
    padding: 6px 10px;
    background: transparent;
    border: 1px solid var(--line-strong);
    border-radius: 5px;
    font: inherit;
    font-size: 12px;
    color: var(--muted);
    cursor: pointer;
  }
  .bd-toggle:hover { color: var(--ink); border-color: var(--ink); }
  .bd-box { margin-top: 4px; }
  /* Pay per usage / Set cost toggle at the top of Approximate monthly cost. */
  .cost-mode {
    display: flex;
    gap: 18px;
    margin: 4px 0 12px;
    font-size: 13px;
    color: var(--ink);
  }
  .cost-mode-opt {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
  }
  .cost-mode-opt input { margin: 0; }
  /* Sub-heading inside a summary section (e.g. OH, marketing & education). */
  .sum-subhead {
    margin: 18px 0 4px;
    font-size: 12px;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }
  .chart-title {
    margin: 16px 0 4px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink);
  }
  .chart-section-gap { height: 20px; }
  /* position: relative anchors the absolutely-positioned hover tooltip
     (.chart-tip) inside the wrap rather than against the viewport. */
  .chart-wrap { margin-top: 10px; position: relative; }
  .chart-tip {
    position: absolute;
    pointer-events: none;
    background: rgba(255, 255, 255, 0.97);
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    padding: 6px 8px;
    font: 11px/1.45 var(--sans);
    color: var(--ink);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
    display: none;
    min-width: 150px;
    z-index: 10;
  }
  .chart-tip .tip-head { font-weight: 700; margin-bottom: 4px; font-size: 11px; }
  .chart-tip .tip-row { display: flex; align-items: center; gap: 6px; }
  .chart-tip .tip-row i {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
  }
  .chart-tip .tip-row span {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
  }
  .chart-wrap svg {
    width: 100%;
    height: 250px;
    display: block;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--panel);
  }
  .chart-wrap.chart-wrap-tall svg { height: 500px; }
  .chart-wrap svg .axis { stroke: var(--line-strong); stroke-width: 1; }
  .chart-wrap svg .grid { stroke: var(--line); stroke-width: 1; }
  .chart-wrap svg .tick {
    fill: var(--muted);
    font: 10px var(--sans);
    text-anchor: middle;
  }
  .chart-legend {
    display: flex;
    gap: 18px;
    margin-top: 8px;
    font-size: 12px;
    color: var(--muted);
  }
  .chart-legend span { display: inline-flex; align-items: center; gap: 6px; }
  .chart-legend i {
    width: 14px;
    height: 3px;
    border-radius: 2px;
    display: inline-block;
  }
  .rev-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    margin: 6px 0 4px;
  }
  .rev-grid.rev-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Yearly breakdown table inside the Outlook section. */
  table.outlook-yearly {
    width: 100%;
    border-collapse: collapse;
    margin: 6px 0 14px;
    font-size: 12px;
  }
  table.outlook-yearly th,
  table.outlook-yearly td {
    padding: 6px 10px;
    border-bottom: 1px solid var(--line);
    text-align: left;
    vertical-align: top;
  }
  table.outlook-yearly th {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    border-bottom: 1px solid var(--line-strong);
  }
  table.outlook-yearly td.num,
  table.outlook-yearly th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
  table.outlook-yearly td.neg { color: #b91c1c; }
  table.outlook-yearly tr.spacer td { padding: 0; height: 6px; border-bottom: 0; }
  table.outlook-yearly tr.profit td { font-weight: 700; border-top: 2px solid var(--line-strong); }
  table.outlook-yearly tr.future td { color: var(--muted); font-style: italic; }
  .rev-field { display: flex; flex-direction: column; gap: 5px; }
  .rev-field label { font-size: 12px; color: var(--ink); }
  .rev-field input {
    font: inherit;
    font-size: 13px;
    color: var(--ink);
    padding: 7px 8px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: #fff;
    outline: 0;
    width: 100%;
    box-sizing: border-box;
  }
  .rev-field input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
  .summary-note {
    width: 100%;
    box-sizing: border-box;
    min-height: 160px;
    margin-top: 6px;
    resize: vertical;
    font: inherit;
    font-size: 13px;
    line-height: 1.5;
    color: var(--ink);
    padding: 10px 12px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: #fff;
    outline: 0;
  }
  .summary-note:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
  /* Warning callout at the bottom of Guessed revenue and profit */
  .rev-warn {
    margin: 16px 0 0;
    padding: 9px 12px;
    background: #fff7e6;
    border: 1px solid #ffe0a3;
    border-radius: 6px;
    font-size: 12px;
    color: #7a5500;
  }

  /* --- Solutions overview --- */
  .view-overview {
    flex-direction: column;
    background: var(--bg);
    padding: 28px 36px;
    overflow: auto;
  }
  .overview-inner { max-width: 960px; }
  .overview-title {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }
  /* Title row: heading on the left, "+ New solution" on the right. */
  .overview-titlebar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 14px;
  }
  .overview-titlebar .overview-title { margin-right: auto; }
  /* Outline-style sibling for the Import JSON button so it reads as the
     secondary action next to the primary "+ New solution". */
  #overview-import-btn {
    background: transparent;
    color: var(--muted);
    border-color: var(--line-strong);
  }
  #overview-import-btn:hover {
    background: var(--bg);
    color: var(--ink);
    border-color: var(--ink);
  }
  .overview-show-inactive {
    margin-right: auto;
    margin-left: 16px;
    font-size: 13px;
    color: var(--muted);
    display: inline-flex; align-items: center; gap: 6px;
    cursor: pointer;
  }
  .solution-card.inactive {
    opacity: 0.55;
    border-style: dashed;
  }
  .solution-card.inactive::after {
    content: 'Inactive';
    position: absolute; top: 8px; right: 10px;
    font-size: 11px; font-weight: 600;
    color: var(--muted); letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .overview-new-btn {
    appearance: none;
    border: 1px solid var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
    border-radius: 5px;
    padding: 4px 11px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
  }
  .overview-new-btn:hover { background: var(--accent); color: #fff; }
  .solution-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 14px;
  }
  .solution-card {
    position: relative;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 20px 22px;
    min-height: 160px;
    cursor: pointer;
    transition: border-color 80ms, transform 60ms;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  /* Snippet preview pulled from the Strategy briefing's Context section. */
  .solution-card-snippet {
    font-size: 12px;
    color: var(--muted);
    line-height: 1.45;
    white-space: pre-wrap;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 6;
    line-clamp: 6;
    -webkit-box-orient: vertical;
  }
  .solution-card-snippet-empty {
    font-size: 12px;
    color: var(--muted);
    font-style: italic;
  }
  .solution-card:hover { border-color: var(--line-strong); }
  .solution-card-del {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 22px;
    height: 22px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: var(--muted);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    display: none;
  }
  .solution-card:hover .solution-card-del { display: block; }
  .solution-card-del:hover { background: #fdeaea; color: var(--danger); }
  .solution-card:active { transform: translateY(1px); }
  .solution-card h3 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink);
  }
  .solution-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 4px;
    margin-bottom: 2px;
    font-size: 11px;
    line-height: 1.3;
  }
  /* Language chip — small uppercase locale tag (EN / SV) next to the
     owner badge so the reader can spot the solution's authoring
     language at a glance. */
  .solution-card-lang {
    display: inline-block;
    padding: 1px 6px;
    border: 1px solid var(--line-strong);
    border-radius: 9px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--muted);
    background: var(--bg);
  }
  .solution-card-owner {
    color: var(--ink-soft);
  }
  .solution-card-owner-none {
    color: #a07a00;
    font-style: italic;
  }
  .solution-card-shared {
    background: var(--accent-soft);
    color: var(--accent);
    border-radius: 9px;
    padding: 1px 7px;
    font-weight: 600;
  }
  /* Topbar user icon — dim when nobody is signed in, normal when signed in. */
  #tb-user { opacity: 0.55; }
  #tb-user.tb-user-on { opacity: 1; color: var(--accent); }
  /* Share modal chip styling */
  .share-section { margin-bottom: 14px; }
  .share-section > label {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ink-soft);
    margin-bottom: 4px;
  }
  .share-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    min-height: 22px;
    margin-bottom: 6px;
  }
  .share-list:empty::before {
    /* Filled in by applyI18n() so the placeholder follows locale. */
    content: var(--share-empty-text, '(none)');
    color: var(--ink-soft);
    font-style: italic;
    font-size: 12px;
  }
  .share-chip {
    background: var(--accent-soft);
    color: var(--accent);
    border-radius: 11px;
    padding: 2px 4px 2px 10px;
    font-size: 12px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
  }
  .share-chip-x {
    background: transparent;
    border: none;
    color: var(--accent);
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0 4px;
  }
  .share-chip-x:hover { color: var(--danger); }
  .share-add {
    display: flex;
    gap: 6px;
  }
  .share-add input {
    flex: 1;
  }
  .solution-card-new {
    border: 2px solid var(--accent);
    color: var(--accent);
    font-weight: 600;
    font-size: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 160px;
    background: var(--accent-soft);
  }
  .solution-card-new:hover {
    color: #fff;
    border-color: var(--accent);
    background: var(--accent);
  }

  /* --- Start view --- */
  .view-start { flex-direction: row; }
  .editor, .preview {
    flex: 1;
    min-width: 0;
    height: 100%;
    overflow: auto;
  }
  .editor {
    border-right: 1px solid var(--line);
    background: var(--panel);
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .start-toolbar {
    flex-shrink: 0;
    height: 32px;
    display: flex;
    align-items: center;
    padding: 0 8px;
    border-bottom: 1px solid var(--line);
    background: var(--panel);
  }
  .start-restart {
    appearance: none;
    background: transparent;
    border: 1px solid var(--line-strong);
    padding: 3px 10px;
    font: inherit;
    font-size: 12px;
    color: var(--ink);
    border-radius: 4px;
    cursor: pointer;
  }
  .start-restart:hover { color: var(--danger); border-color: var(--danger); background: #fdeaea; }
  .editor textarea {
    width: 100%;
    flex: 1;
    min-height: 0;
    border: 0;
    outline: 0;
    resize: none;
    overflow: auto;
    padding: 16px 20px;
    font-family: var(--mono);
    font-size: 13px;
    line-height: 1.55;
    color: var(--ink);
    background: transparent;
    tab-size: 2;
  }
  .preview {
    padding: 16px 28px;
    background: var(--bg);
    line-height: 1.6;
  }
  .preview h1 {
    font-size: 22px;
    margin: 24px 0 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--line);
    font-weight: 600;
  }
  .preview h1:first-child { margin-top: 4px; }
  .preview h2 { font-size: 15px; margin: 18px 0 6px; font-weight: 600; }
  .preview h3 { font-size: 13px; margin: 14px 0 4px; font-weight: 600; }
  .preview p { margin: 12px 0; }
  /* Extra blank lines in the source produce visible vertical space */
  .preview p.md-spacer { margin: 0; height: 0.9em; }

  /* Shapes palette to the left of Strategy briefing / UI-views */
  .doc-palette {
    flex: 0 0 200px;
    border-right: 1px solid var(--line);
    background: var(--panel);
    padding: 12px;
    overflow: auto;
  }
  .doc-palette h4 {
    margin: 0 0 8px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
  }
  /* Highlight drop target when dragging a Note shape */
  .view-start.drag-over,
  .view-ui    .view-ui-main.drag-over,
  .view-ui    .preview.drag-over { outline: 2px dashed #d29200; outline-offset: -6px; }
  /* Note cards appended to the preview pane (Strategy briefing / UI-views) */
  .doc-notes {
    display: flex; flex-direction: column; gap: 10px;
    margin-top: 22px;
    padding-top: 14px;
    border-top: 1px dashed var(--line);
  }
  .doc-note-card {
    border: 1px solid var(--ctx-stroke);
    border-radius: 6px;
    background: #fff7b3;
    padding: 8px 10px;
    font-size: 12px;
    color: var(--ink);
    display: flex; flex-direction: column; gap: 6px;
  }
  .doc-note-card.type-question { background: #dbeafe; border-color: #2563eb; }
  .doc-note-card.type-problem  { background: #fed7aa; border-color: #ea580c; }
  .doc-note-card.resolved      { background: #d1fae5; border-color: #16a34a; }
  .doc-note-card .dn-head {
    display: flex; align-items: center; gap: 8px;
  }
  .doc-note-card .dn-type,
  .doc-note-card .dn-heading {
    font: inherit; font-size: 11px;
    padding: 3px 6px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: rgba(255,255,255,0.7);
  }
  .doc-note-card .dn-heading { max-width: 180px; }
  .doc-notes-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    margin-bottom: 2px;
  }
  .doc-notes-orphan { border-top-style: solid; border-top-color: var(--line-strong); }
  .doc-note-card .dn-resolved {
    font-size: 11px; color: var(--ink);
    display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  }
  .doc-note-card .dn-spacer { flex: 1; }
  .doc-note-card .dn-del {
    appearance: none; background: transparent; border: 0;
    width: 22px; height: 22px; border-radius: 4px;
    color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer;
  }
  .doc-note-card .dn-del:hover { color: var(--danger); background: rgba(255,255,255,0.6); }
  .doc-note-card .dn-text {
    font: inherit; font-size: 12px;
    padding: 6px 8px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: rgba(255,255,255,0.7);
    resize: vertical;
    min-height: 56px;
  }
  .doc-note-card .dn-render {
    padding: 6px 8px;
    background: rgba(255,255,255,0.5);
    border: 1px solid var(--line);
    border-radius: 4px;
    font-size: 12px;
  }
  .doc-note-card .dn-render p:first-child { margin-top: 0; }
  .doc-note-card .dn-render p:last-child  { margin-bottom: 0; }

  /* "Edit" toggle floating in the top-right of Strategy briefing / UI-views.
     The view sections are position:absolute (inset:0), so position:absolute
     here anchors against the view. */
  .view-toggle-edit {
    position: absolute;
    top: 4px; right: 14px;
    z-index: 5;
    appearance: none;
    background: rgba(255,255,255,0.92);
    border: 1px solid var(--line-strong);
    border-radius: 5px;
    padding: 4px 9px;
    font: inherit; font-size: 12px;
    color: var(--ink);
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 5px;
  }
  .view-toggle-edit:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
  }
  .view-toggle-edit.active {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
  }
  /* Hide the editor pane until the toggle is on */
  .view-start.editor-hidden > .editor { display: none; }
  .view-ui.editor-hidden .ui-pane.editor { display: none; }
  .preview ul, .preview ol { margin: 6px 0; padding-left: 22px; }
  .preview li { margin: 8px 0; }
  /* Pandoc-style superscript / subscript (^x^, ~x~). Use explicit positioning
     instead of the browser default `vertical-align: super` so they render
     reliably both on screen and in the PDF print preview, where some engines
     ignore the default vertical-align on inline children of <p>/<li>. */
  sup, sub {
    font-size: 0.75em;
    line-height: 0;
    position: relative;
    vertical-align: baseline;
  }
  sup { top: -0.5em; }
  sub { bottom: -0.25em; }
  .preview code {
    font-family: var(--mono);
    font-size: 12px;
    background: #f1f3f5;
    padding: 1px 5px;
    border-radius: 3px;
  }
  .preview pre {
    font-family: var(--mono);
    font-size: 12px;
    background: #f6f8fa;
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 10px 12px;
    overflow: auto;
  }
  .preview pre code { background: transparent; padding: 0; }
  .preview a { color: var(--accent); }
  .preview blockquote {
    margin: 8px 0;
    padding: 2px 12px;
    border-left: 3px solid var(--line-strong);
    color: var(--muted);
  }
  .preview img {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 8px 0;
    border: 1px solid var(--line);
    border-radius: 4px;
  }
  /* Per-image size control inserted by applyUiImageSizes for the UI-views
     preview. Sits flush under the image as a discrete editor — no
     equivalent emitted in the PDF export. */
  .ui-img-size-row {
    margin: -4px 0 10px 0;
    font-size: 11px;
    color: var(--muted);
    display: flex;
    align-items: center;
    gap: 4px;
  }
  .ui-img-size-label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: default;
  }
  .ui-img-size {
    width: 56px;
    padding: 2px 4px;
    border: 1px solid var(--line);
    border-radius: 3px;
    text-align: right;
    font-size: 11px;
    font-family: inherit;
    background: #fff;
  }
  .preview table {
    border-collapse: collapse;
    margin: 10px 0;
    width: 100%;
    font-size: 12px;
  }
  .preview th, .preview td {
    border: 1px solid var(--line-strong);
    padding: 6px 9px;
    text-align: left;
    vertical-align: top;
  }
  .preview th {
    background: #f1f3f5;
    font-weight: 600;
  }
  .preview td { min-width: 60px; height: 22px; }

  /* --- UI-views (per-BC markdown doc) --- */
  .view-ui { flex-direction: row; }
  .view-ui .view-ui-main {
    flex: 1; display: flex; flex-direction: column;
    min-width: 0; overflow: hidden;
  }
  .ui-split {
    flex: 1;
    display: flex;
    flex-direction: row;
    min-height: 0;
  }
  .ui-pane { height: 100%; }
  .ui-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    font-size: 13px;
    background: var(--bg);
  }
  /* When no BC is chosen we show only the empty hint */
  .view-ui:not(.has-doc) .ui-pane { display: none; }
  .view-ui.has-doc .ui-empty { display: none; }
  /* MD editor is narrower than the rendered preview so the view dominates */
  .view-ui .ui-pane.editor  { flex: 0 0 38%; }
  .view-ui .ui-pane.preview { flex: 1; min-width: 0; }
  /* Strategy briefing: a slight tilt in favour of the rendered preview */
  .view-start .editor  { flex: 0 0 42%; }
  .view-start .preview:not(.note-preview) { flex: 1; min-width: 0; }
  .ui-props {
    flex: 0 0 240px;
    border-left: 1px solid var(--line);
    background: var(--panel);
    padding: 14px 16px;
    overflow: auto;
  }
  .ui-prop-head {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    margin-bottom: 10px;
  }
  .ui-prop { display: flex; flex-direction: column; gap: 4px; }
  .ui-prop-label { font-size: 11px; color: var(--muted); font-weight: 600; }
  .ui-prop select {
    font: inherit;
    font-size: 13px;
    padding: 6px 8px;
    border: 1px solid var(--line-strong);
    border-radius: 5px;
    background: #fff;
    width: 100%;
  }

  /* --- Context Map view --- */
  .view-map { flex-direction: row; }
  .map-sidebar {
    width: 200px;
    flex-shrink: 0;
    background: var(--panel);
    border-right: 1px solid var(--line);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
  }
  .palette-section { padding: 10px 12px; display: flex; flex-direction: column; }
  .palette-section + .palette-section { border-top: 1px solid var(--line); }
  /* Shape ordering: Relationship sits at the bottom of the shapes (when the
     active tab has one) and Note is the very last shape. Toggle rows
     ("Show Bounded Contexts") stay below them. */
  .palette-section .pal-rel  { order: 10; }
  .palette-section .pal-note { order: 20; }
  .palette-section .sub-showbc { order: 30; }
  .palette-section .show-resolved-row { order: 40; }
  .palette-section h4 {
    margin: 0 0 8px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
  }
  .sub-showbc {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 10px 12px;
    border-top: 1px solid var(--line);
    font-size: 12px;
    color: var(--ink);
    cursor: pointer;
  }
  .sub-showbc input { margin: 0; }
  /* "Show resolved Q/P" toggle — same look as sub-showbc; appears in all
     palette panels (canvas, doc, summary) at the bottom */
  .show-resolved-row {
    display: flex; align-items: center; gap: 7px;
    margin-top: 14px;
    padding-top: 10px;
    border-top: 1px solid var(--line);
    font-size: 12px;
    color: var(--ink);
    cursor: pointer;
  }
  .show-resolved-row input { margin: 0; }
  /* Hide resolved Question/Problem cards/notes when the toggle is off */
  .app.hide-resolved .note.resolved,
  .app.hide-resolved .doc-note-card.resolved,
  .app.hide-resolved .summary-note-card.resolved { display: none !important; }
  .palette-item {
    appearance: none;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 10px;
    margin-bottom: 4px;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 5px;
    font: inherit;
    font-size: 12px;
    color: var(--ink);
    cursor: grab;
    text-align: left;
    user-select: none;
  }
  .palette-item:last-child { margin-bottom: 0; }
  .palette-item:hover { background: #f6f8fa; border-color: var(--line-strong); }
  .palette-item:active { cursor: grabbing; }
  .palette-item .preview {
    flex: 0 0 28px;
    width: 28px;
    height: 18px;
    padding: 0;
    border-radius: 3px;
    background: var(--ctx-fill);
    border: 1.2px solid var(--ctx-stroke);
    position: relative;
    box-sizing: border-box;
    overflow: visible;            /* don't inherit Start-view's overflow:auto
                                     (a stray scrollbar otherwise shows next
                                     to the taller Operations icons) */
  }
  .palette-item .note-preview {
    background: #fff7b3;
    border-color: var(--ctx-stroke);
    border-radius: 0;
  }
  .palette-item .dp-preview,
  .palette-item .sub-preview,
  .palette-item .role-preview,
  .palette-item .team-preview,
  .palette-item .op-preview,
  .palette-item .endpoint-preview,
  .palette-item .bbom-preview {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .palette-item .dp-preview svg,
  .palette-item .sub-preview svg,
  .palette-item .role-preview svg,
  .palette-item .team-preview svg,
  .palette-item .op-preview svg,
  .palette-item .endpoint-preview svg,
  .palette-item .bbom-preview svg { display: block; }

  /* Palette items show/hide depending on which diagram is active.
     pal-map → Context Map · pal-sub → Sub-domains · pal-teams → Teams
     pal-ops → Operations · pal-end → Endpoints
     pal-rel (Relationship) → Context Map + Sub-domains + Operations
     pal-note (Note) → everywhere except Teams */
  .view-map:not(.mode-map)   .pal-map   { display: none; }
  .view-map:not(.mode-sub)   .pal-sub   { display: none; }
  .view-map:not(.mode-teams) .pal-teams { display: none; }
  .view-map:not(.mode-ops)   .pal-ops   { display: none; }
  .view-map:not(.mode-end)   .pal-end   { display: none; }
  .view-map:not(.mode-pipe)  .pal-pipe  { display: none; }
  .view-map:not(.mode-mod)   .pal-mod   { display: none; }
  /* Future-only generic modules are hidden unless ?future=true. */
  body:not(.future-on) .pal-mod-future { display: none; }
  /* Generic-module category groups. The header is always visible (when
     in Modules mode); the body slides in only when data-expanded="true".
     Default-collapsed because the catalogue is long and users mostly
     know which group they want before they look. */
  .palette-cat {
    display: block;
    margin: 4px 0 6px;
  }
  .palette-cat-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 4px 8px;
    font: inherit;
    font-size: 12px;
    color: var(--ink);
    cursor: pointer;
    text-align: left;
  }
  .palette-cat-toggle:hover { background: var(--bg); border-color: var(--line-strong); }
  .palette-cat-caret {
    display: inline-block;
    font-size: 9px;
    color: var(--muted);
    transition: transform 0.12s ease-out;
    width: 10px;
    text-align: center;
  }
  .palette-cat[data-expanded="true"] .palette-cat-caret { transform: rotate(90deg); }
  .palette-cat-name { flex: 1; font-weight: 500; }
  .palette-cat-body { display: none; padding: 4px 0 0 12px; }
  .palette-cat[data-expanded="true"] .palette-cat-body { display: block; }
  body:not(.future-on) #export-module-design-md-row,
  body:not(.future-on) #export-module-data-md-row,
  body:not(.future-on) #export-module-edit2d-md-row,
  body:not(.future-on) #export-module-render3d-md-row,
  body:not(.future-on) #export-module-cad-md-row { display: none; }
  .view-map:not(.mode-spikes) .pal-spike { display: none; }
  .view-map:not(.mode-docs)   .pal-docs  { display: none; }
  /* Relationship was previously hidden on Teams / Endpoints / Automations.
     Removed — the user wants to be able to wire those shapes up too. */
  .palette-item .rel-preview {
    background: transparent;
    border: 0;
    border-radius: 0;
  }
  .palette-item .rel-preview::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0; right: 0;
    height: 1.2px;
    background: var(--rel-strong);
    transform: translateY(-50%);
  }
  .palette-item .meta {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
  }
  .palette-item .meta .name { font-weight: 600; }
  .palette-item .meta .sub  { font-size: 10px; color: var(--muted); }

  /* Drag ghost following the cursor while dragging from palette */
  .drag-ghost {
    position: fixed;
    pointer-events: none;
    z-index: 100;
    padding: 14px 18px;
    background: var(--ctx-fill);
    border: 1.2px solid var(--ctx-stroke);
    border-radius: 6px;
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 600;
    color: var(--ink);
    opacity: 0.92;
    box-shadow: 0 4px 14px rgba(0,0,0,0.12);
    transform: translate(-50%, -50%);
  }
  /* Line-style ghost used when dragging the Relationship tool */
  .drag-ghost.line {
    width: 64px;
    height: 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-top: 1.5px dashed var(--accent);
    border-radius: 0;
    box-shadow: none;
    opacity: 1;
  }
  /* Highlight a hovered node while the relationship tool is being dragged */
  .ctx.drop-hover rect,
  .note.drop-hover rect {
    stroke: var(--accent);
    stroke-width: 2;
  }
  .rel.drop-hover line { stroke: var(--accent); stroke-width: 2; }
  .map-stage.drop-target {
    outline: 2px dashed var(--accent);
    outline-offset: -2px;
  }

  /* --- Properties panel (right) --- */
  /* Floats over the canvas instead of taking layout space, so opening or
     closing it doesn't shift the diagram underneath. */
  .props-panel {
    position: absolute;
    top: 32px;                     /* clear .map-toolbar (32 px tall) so zoom
                                       controls remain visible on every tab */
    right: 0;
    bottom: 0;
    width: 180px;                  /* align with the zoom-controls row above
                                       (180 px wide → meets Documents' left edge) */
    background: var(--panel);
    border-left: 1px solid var(--line);
    box-shadow: -4px 0 12px rgba(0, 0, 0, 0.06);
    display: none;
    flex-direction: column;
    overflow: hidden;
    z-index: 5;
  }
  .props-panel.open { display: flex; }
  .props-header {
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-shrink: 0;
  }
  .props-header .kind {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
  }
  .props-body {
    padding: 12px;
    overflow-y: auto;
    flex: 1;
  }
  .field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 14px;
  }
  .field:last-child { margin-bottom: 0; }
  .field label {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
  }
  .field input[type="text"],
  .field textarea,
  .field select {
    font: inherit;
    font-size: 13px;
    color: var(--ink);
    padding: 5px 8px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: white;
    outline: 0;
    width: 100%;
  }
  .field input[type="text"]:focus,
  .field textarea:focus,
  .field select:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-soft);
  }
  .field input:disabled,
  .field textarea:disabled,
  .field select:disabled {
    color: var(--muted);
    background: #f6f8fa;
    cursor: not-allowed;
  }
  /* Auxiliary text input that follows a select when the user picks
     "Other…" — same look as a normal text field, just a tiny gap above. */
  .field .field-other { margin-top: 6px; }
  .field textarea {
    resize: vertical;
    min-height: 60px;
    font-family: var(--sans);
    line-height: 1.4;
  }
  .field .hint {
    font-size: 11px;
    color: var(--muted);
  }
  .field-heading {
    margin: 18px 0 2px;
    font-size: 11px;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
  .field select.deviation,
  .field input.deviation {
    border-color: var(--danger);
    color: var(--danger);
    background: #fdeaea;
    font-weight: 600;
  }
  .field select.warn,
  .field input.warn {
    border-color: #d29200;
    color: #9a6c00;
    background: #fff7e6;
    font-weight: 600;
  }
  .field .field-btn {
    appearance: none;
    border: 1px dashed var(--line-strong);
    background: #fff;
    font: inherit;
    font-size: 12px;
    padding: 7px 12px;
    border-radius: 5px;
    color: var(--ink);
    cursor: pointer;
  }
  .field .field-btn:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
  }
  .field .computed-value {
    font: inherit;
    font-size: 13px;
    padding: 7px 9px;
    border: 1px dashed var(--line-strong);
    border-radius: 4px;
    background: var(--bg);
    color: var(--ink);
  }
  .props-body > .hint {
    font-size: 12px;
    color: var(--muted);
    line-height: 1.5;
  }

  .map-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
  }
  .map-toolbar {
    display: flex; align-items: center;
    gap: 4px;
    height: 32px;
    padding: 0 8px;
    background: var(--panel);
    border-bottom: 1px solid var(--line);
    flex-shrink: 0;
  }
  .node-index {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    min-width: 0;
    height: 100%;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .node-index::-webkit-scrollbar { height: 0; }
  .node-index:empty::before {
    content: 'No bounded contexts or data products yet';
    font-size: 11px;
    color: var(--muted);
  }
  /* Pipelines never lists nodes in row 2 — the empty hint is irrelevant */
  .view-map.mode-pipe .node-index:empty::before { content: none; }
  /* Sub-domains, Context Map, Teams, Operations: the chip strip just adds
     clutter without aiding navigation, so the whole row is hidden. Spikes
     and Documents render no chips at all — hide the empty placeholder too. */
  .view-map.mode-sub   .node-index,
  .view-map.mode-map   .node-index,
  .view-map.mode-teams .node-index,
  .view-map.mode-ops   .node-index,
  .view-map.mode-spikes .node-index,
  .view-map.mode-docs   .node-index,
  .view-map.mode-es    .node-index { display: none; }
  /* In EventStorming mode the bottom-of-palette group (Relationship, Note,
     Show resolved) sits a noticeable gap below the sticky shapes — Rel is
     first by flex-order, so a single margin-top on it does the trick. */
  .view-map.mode-es .palette-section .pal-rel { margin-top: 24px; }
  /* EventStorming session bar replaces .node-index inside the toolbar when
     the EventStorming tab is active. */
  .view-map:not(.mode-es) #es-session-bar { display: none !important; }
  .view-map.mode-es #es-session-bar { display: flex; flex: 1; min-width: 0; align-items: center; gap: 6px; overflow-x: auto; }
  #es-session-bar .es-new-session {
    appearance: none;
    flex: 0 0 auto;
    padding: 4px 10px;
    background: var(--accent-soft);
    color: var(--accent);
    border: 1px dashed var(--accent);
    border-radius: 5px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
  }
  #es-session-bar .es-new-session:hover { background: var(--accent); color: #fff; }
  #es-session-bar .es-session-list { display: flex; flex-direction: row; gap: 4px; flex-wrap: nowrap; }
  #es-session-bar .es-session-item {
    appearance: none;
    flex: 0 0 auto;
    padding: 3px 10px;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 4px;
    font: inherit;
    font-size: 12px;
    color: var(--ink);
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    white-space: nowrap;
  }
  #es-session-bar .es-session-item:hover { background: var(--bg); border-color: var(--line-strong); }
  #es-session-bar .es-session-item.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
  #es-session-bar .es-session-item .es-session-del {
    appearance: none; background: transparent; border: 0;
    color: var(--muted); font-size: 14px; line-height: 1; padding: 0 2px; cursor: pointer; display: none;
  }
  #es-session-bar .es-session-item:hover .es-session-del { display: inline-block; }
  #es-session-bar .es-session-item .es-session-del:hover { color: var(--danger); }
  #es-session-bar .es-session-item.is-active .es-session-lbl::after {
    content: '✓';
    color: #0e9b6b;
    font-weight: 700;
    margin-left: 6px;
    font-size: 13px;
  }
  #es-session-bar .es-session-rename {
    appearance: none;
    font: inherit;
    font-size: 12px;
    border: 1px solid var(--accent);
    border-radius: 3px;
    padding: 1px 5px;
    outline: 0;
    min-width: 80px;
    background: #fff;
    color: var(--ink);
  }
  .node-chip {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 3px 9px;
    font: inherit;
    font-size: 12px;
    color: var(--ink);
    cursor: pointer;
    white-space: nowrap;
  }
  .node-chip:hover { background: #f3f4f6; }
  .node-chip.selected {
    background: var(--accent-soft);
    border-color: #c7dafd;
    color: var(--accent);
  }
  .node-chip svg { display: block; flex-shrink: 0; }
  .zoom-controls {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: auto;
    flex-shrink: 0;
    width: 180px;                    /* align with Documents + Exports above */
    margin-right: -8px;              /* negate .map-toolbar's right padding
                                         so the right edge meets the viewport
                                         and the leftmost button (−) lines up
                                         with Documents' left edge */
  }
  /* Fit-to-view stays pinned to the far right; the −, 100 %, + cluster sits
     at the left of the 180 px container, directly under Documents. */
  .zoom-controls #zoom-fit { margin-left: auto; }
  .zoom-controls button {
    appearance: none;
    background: var(--panel);
    border: 1px solid var(--line);
    color: var(--ink);
    font: inherit;
    font-size: 12px;
    height: 22px;
    min-width: 24px;
    padding: 0 6px;
    border-radius: 3px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .zoom-controls button:hover { background: #f3f4f6; }
  .zoom-controls #zoom-level { min-width: 44px; font-variant-numeric: tabular-nums; }
  .map-toolbar .hint {
    flex-shrink: 0;
    margin-left: 8px;
    font-size: 11px;
    color: var(--muted);
  }
  .map-stage {
    flex: 1;
    position: relative;
    overflow: hidden;
    background:
      radial-gradient(circle, #e5e7eb 1px, transparent 1px) 0 0 / 18px 18px;
    background-color: var(--bg);
  }
  .map-stage.panning-ready { cursor: grab; }
  .map-stage.panning        { cursor: grabbing; }
  .canvas-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0 24px;
    color: var(--muted);
    font-size: 13px;
    pointer-events: none;
  }
  .canvas-empty[hidden] { display: none; }
  .map-stage svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    user-select: none;
  }
  /* A noticeably thicker outline distinguishes Bounded Contexts at a
     glance from Modules (square white box, thin stroke). With both
     symbols being rounded white rectangles before, you had to read
     the label to tell which canvas you were on. */
  .ctx rect {
    fill: var(--ctx-fill);
    stroke: var(--ctx-stroke);
    stroke-width: 2.6;
  }
  .ctx text {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 600;
    fill: var(--ink);
    pointer-events: none;
    dominant-baseline: middle;
    text-anchor: middle;
  }
  .ctx text.mt-mark,
  .bbom text.mt-mark {
    font-size: 18px;
    font-weight: 700;
    fill: var(--ink);
    dominant-baseline: alphabetic;
    text-anchor: end;
  }
  /* Digital-autonomy badge in the lower-left corner (BCs, Data Products,
     Operations nodes and Vendor/Geo areas). */
  text.aut-mark {
    font-size: 18px;
    font-weight: 700;
    dominant-baseline: alphabetic;
    text-anchor: start;
  }
  .aut-mark.sev-ok   { fill: #0e9b6b; font-size: 22px; }   /* Yes → green ✓ (bigger to match the optical weight of ?/!) */
  .aut-mark.sev-warn { fill: #d29200; }   /* Not evaluated → orange ? */
  .aut-mark.sev-err  { fill: #b91c1c; }   /* No (autonomy negatively affected) → red ! */
  /* Note-type symbol in the upper-left corner (Question = ?, Problem = !) */
  text.note-mark {
    font-size: 18px;
    font-weight: 700;
    dominant-baseline: alphabetic;
    text-anchor: start;
  }
  .note-mark.sev-warn { fill: #d29200; }
  .note-mark.sev-err  { fill: #b91c1c; }
  /* Leave room for the upper-left symbol so it doesn't crowd the text */
  .note.type-question .note-text,
  .note.type-problem  .note-text { padding-left: 28px; }
  /* Inline textarea for editing a note's body via double-click */
  .edit-overlay textarea.note-edit {
    border: 1px solid var(--accent);
    border-radius: 3px;
    background: rgba(255,255,255,0.96);
    font: 12px/1.4 var(--sans);
    color: var(--ink);
    padding: 8px 10px;
    box-sizing: border-box;
    resize: none;
    outline: 0;
  }
  .ctx:hover rect { stroke-width: 3.0; }
  .ctx.selected rect {
    stroke: var(--selected);
    stroke-width: 3.2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .ctx.linking-source rect { stroke: var(--accent); stroke-width: 3.2; stroke-dasharray: 4 3; }
  .ctx { cursor: grab; }
  .ctx.dragging { cursor: grabbing; }

  /* --- Data Products (hexagon) --- */
  .dp polygon {
    fill: #ffffff;
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
    stroke-linejoin: round;
  }
  /* "Managed" (Context Map: someone else responsible · Operations: vendor-
     hosted) is signalled by the cloud badge alone — the light-blue fill the
     shapes used to carry was redundant once the cloud was clear enough on
     its own. The .op-bg rect is still emitted by the render loop but kept
     transparent so it doesn't paint a default-black rectangle. */
  .op .op-bg { fill: none; pointer-events: none; }
  .managed-badge { pointer-events: none; }
  /* Transparent hit overlay used to widen the tooltip target around tiny
     symbols (managed cloud, public globe, multi-tenant *, factor10 "10").
     !important wins over container styles like .ctx rect (BC outline). */
  .tip-hit {
    fill: transparent !important;
    stroke: none !important;
    cursor: help;
  }
  /* Custom tooltip — no native <title> delay */
  .hover-tip {
    position: fixed;
    pointer-events: none;
    background: rgba(15, 23, 42, 0.92);
    color: #fff;
    font-size: 11px;
    padding: 4px 8px;
    border-radius: 4px;
    z-index: 100;
    white-space: nowrap;
    display: none;
  }
  .managed-badge path {
    fill: none;
    stroke: #1f2328;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
  }
  .dp:hover polygon { stroke-width: 1.6; }
  .dp.selected polygon {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .dp.linking-source polygon { stroke: var(--accent); stroke-width: 2; stroke-dasharray: 4 3; }
  .dp text {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 600;
    fill: var(--ink);
    pointer-events: none;
    dominant-baseline: middle;
    text-anchor: middle;
  }
  .dp { cursor: grab; }
  .dp.dragging { cursor: grabbing; }
  .dp.drop-hover polygon { stroke: var(--accent); stroke-width: 2; }

  /* --- Big Ball of Mud (irregular blob — used when boundaries are blurred) --- */
  /* Direct-child selector only — otherwise this rule also painted the
     cloud badge's nested <path> in muddy brown/cream and stomped over the
     .managed-badge styling. */
  .bbom > path {
    fill: #efe2cb;
    stroke: #8b6b3d;
    stroke-width: 1.4;
    stroke-linejoin: round;
  }
  .bbom:hover > path { stroke-width: 1.8; }
  .bbom.selected > path {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .bbom.linking-source > path { stroke: var(--accent); stroke-width: 2; stroke-dasharray: 4 3; }
  /* Body-text styling for the BBoM's name only. Excludes the badge glyphs
     (mt-mark, aut-mark) which are also direct text children but want their
     own font-size / anchor / fill defined by .ctx text.mt-mark / text.aut-mark. */
  .bbom > text:not(.mt-mark):not(.aut-mark) {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 600;
    fill: var(--ink);
    pointer-events: none;
    dominant-baseline: middle;
    text-anchor: middle;
  }
  .bbom { cursor: grab; }
  .bbom.dragging { cursor: grabbing; }

  /* --- Sub-domains (dashed cloud) --- */
  .subdomain path {
    fill: transparent;
    stroke: var(--ctx-stroke);
    stroke-width: 1.4;
    stroke-dasharray: 6 4;
    stroke-linejoin: round;
  }
  /* Only Core gets a background tint; the rest stay outline-only */
  .subdomain.type-core path { fill: #dff3e6; }
  .subdomain:hover path { stroke-width: 1.8; }
  .subdomain.selected path {
    stroke: var(--selected);
    stroke-width: 2.2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .subdomain.linking-source path { stroke: var(--accent); stroke-width: 2.2; }
  .subdomain.drop-hover path { stroke: var(--accent); stroke-width: 2.2; }
  .subdomain text.title {
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 600;
    fill: var(--ink);
    pointer-events: none;
    dominant-baseline: middle;
    text-anchor: middle;
  }
  .subdomain text.kind-tag {
    font-family: var(--sans);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    fill: var(--muted);
    pointer-events: none;
    dominant-baseline: middle;
    text-anchor: middle;
  }
  .subdomain { cursor: grab; }
  .subdomain.dragging { cursor: grabbing; }

  /* Member BC/DP chips shown inside / on the border of clouds */
  .member { pointer-events: none; }
  .member rect, .member polygon, .member path {
    fill: #ffffff;
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
    stroke-linejoin: round;
  }
  /* BBoM member chip carries the same muddy palette as the canvas blob
     so it reads as "a Big Ball of Mud lives here" at a glance. */
  .member.kind-bbom path {
    fill: #efe2cb;
    stroke: #8b6b3d;
  }
  .member text {
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 600;
    fill: var(--ink);
    text-anchor: middle;
    dominant-baseline: middle;
  }

  /* Members checklist in the properties panel */
  .checklist {
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    max-height: 220px;
    overflow-y: auto;
    background: #fff;
  }
  .checklist-row {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 5px 8px;
    font-size: 12px;
    cursor: pointer;
    border-bottom: 1px solid var(--line);
  }
  .checklist-row:last-child { border-bottom: 0; }
  .checklist-row:hover { background: #f6f8fa; }
  .checklist-row input { margin: 0; }
  .checklist-tag { display: inline-flex; align-items: center; }
  .checklist-tag svg { display: block; }
  .checkbox-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--ink);
    cursor: pointer;
  }
  .checkbox-row input { margin: 0; }

  /* Team participants (name + % of time) */
  .people-list { display: flex; flex-direction: column; gap: 8px; }
  .people-row {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 7px 8px;
    border: 1px solid var(--line);
    border-radius: 5px;
    background: #fcfcfc;
  }
  .people-row .p-top,
  .people-row .p-bot { display: flex; align-items: center; gap: 6px; }
  .summary-pdf-skip-note {
    margin: 4px 0 8px;
    padding: 6px 10px;
    background: #fff7ed;
    border-left: 3px solid #d29200;
    border-radius: 3px;
    font-size: 12px;
    color: #92400e;
  }
  .people-row .p-name { flex: 1; min-width: 0; }
  .people-row .p-url-row { margin-top: 4px; }
  .people-row .p-url {
    width: 100%;
    box-sizing: border-box;
    appearance: none;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: #fff;
    padding: 4px 6px;
    font: inherit;
    font-size: 12px;
    color: var(--ink);
    outline: 0;
  }
  .people-row .p-url:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-soft);
  }
  .people-row .p-pct,
  .people-row .p-rate {
    flex-shrink: 0;
    font: inherit;
    font-size: 13px;
    color: var(--ink);
    padding: 5px 6px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    background: #fff;
    outline: 0;
    text-align: right;
  }
  .people-row .p-pct  { width: 38px; }
  .people-row .p-rate { width: 44px; }
  .people-row .p-pct:focus,
  .people-row .p-rate:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
  /* Hide the native number-input spinner — it ate ~18 px of horizontal space
     inside the narrow %/amount boxes and read as "something is covering the
     text". The fields are typed into; nobody clicks the stepper arrows. */
  .people-row .p-pct::-webkit-outer-spin-button,
  .people-row .p-pct::-webkit-inner-spin-button,
  .people-row .p-rate::-webkit-outer-spin-button,
  .people-row .p-rate::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
  .people-row .p-pct,
  .people-row .p-rate {
    -moz-appearance: textfield;
    appearance: textfield;
  }
  .people-row .p-suffix { font-size: 11px; color: var(--muted); }
  .people-row .p-suffix.grow { margin-left: auto; }
  .people-row .p-del {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
  }
  .people-row .p-del:hover { color: var(--danger); background: #fdeaea; }
  .people-add {
    appearance: none;
    margin-top: 8px;
    align-self: flex-start;
    background: transparent;
    border: 1px dashed var(--line-strong);
    color: var(--muted);
    font: inherit;
    font-size: 12px;
    padding: 5px 10px;
    border-radius: 4px;
    cursor: pointer;
  }
  .people-add:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

  /* --- Teams (Team Topologies) --- */
  .team rect {
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
  }
  .team.tt-stream      rect { fill: #f4d35e; }
  .team.tt-enabling    rect { fill: #9d80e6; }
  .team.tt-complicated rect { fill: #e0455f; }
  .team.tt-platform    rect { fill: #79e8c9; }
  .team:hover rect { stroke-width: 1.6; }
  .team.selected rect {
    stroke: var(--selected);
    stroke-width: 2.4;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.3));
  }
  .team.linking-source rect { stroke: var(--accent); stroke-width: 2.4; stroke-dasharray: 5 3; }
  .team.drop-hover rect { stroke: var(--accent); stroke-width: 2.4; }
  .team text.title {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 700;
    fill: #1f2328;
    pointer-events: none;
    dominant-baseline: middle;
    text-anchor: middle;
  }
  .team { cursor: grab; }
  .team.dragging { cursor: grabbing; }

  /* --- Operations (line-icon nodes) --- */
  .op { cursor: grab; }
  .op.dragging { cursor: grabbing; }
  .op .op-sel {
    fill: none;
    stroke: transparent;
    stroke-width: 2;
  }
  .op:hover .op-sel { stroke: var(--line-strong); }
  .op.selected .op-sel {
    stroke: var(--selected);
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .op.linking-source .op-sel { stroke: var(--accent); stroke-dasharray: 5 3; }
  .op.drop-hover .op-sel { stroke: var(--accent); }
  .op .op-icon path,
  .op .op-icon circle,
  .op .op-icon ellipse,
  .op .op-icon line,
  .op .op-icon polyline,
  .op .op-icon rect {
    fill: none;
    stroke: #1f2328;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
  }
  .op .op-icon text { stroke: none; fill: #1f2328; }
  .op text.title {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 600;
    fill: var(--ink);
    pointer-events: none;
    text-anchor: middle;
  }
  .op text.sub {
    font-family: var(--sans);
    font-size: 11px;
    fill: var(--muted);
    pointer-events: none;
    text-anchor: middle;
  }

  /* --- Area (Vendor / Geo dashed container) --- */
  .area .area-box {
    fill: transparent;
    stroke: var(--rel-strong);
    stroke-width: 1.6;
    rx: 8;
  }
  /* Border style per variant */
  .area.v-vendor .area-box,
  .area.v-xaas   .area-box { stroke-dasharray: 10 7; }
  .area.v-facilitating  .area-box { stroke-dasharray: 0.1 7; stroke-linecap: round; stroke-width: 2.4; }
  .area.v-collaboration .area-box { stroke-dasharray: none; }
  .area:hover .area-box { stroke-width: 2; }
  .area.v-facilitating:hover .area-box { stroke-width: 3; }
  .area.selected .area-box { stroke: var(--selected); stroke-width: 2; }
  .area.linking-source .area-box { stroke: var(--accent); }
  .area .area-label {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 700;
    fill: var(--ink);
    pointer-events: none;
  }
  .area .area-label-bg { fill: #fbfbfa; stroke: var(--line); }
  .area { cursor: grab; }
  .area.dragging { cursor: grabbing; }
  .rz { fill: #ffffff; stroke: var(--selected); stroke-width: 1.4; }
  .rz.nw, .rz.se { cursor: nwse-resize; }
  .rz.ne, .rz.sw { cursor: nesw-resize; }
  .rz.n, .rz.s   { cursor: ns-resize; }
  .rz.e, .rz.w   { cursor: ew-resize; }

  /* --- Roles (UML actor figure) --- */
  .role .figure {
    fill: none;
    stroke: var(--ctx-stroke);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .role .figure .head { fill: #ffffff; }
  .role .hit { fill: transparent; }
  .role:hover .figure { stroke-width: 2; }
  .role.selected .figure {
    stroke: var(--selected);
    stroke-width: 2.2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .role.linking-source .figure { stroke: var(--accent); stroke-width: 2.2; }
  .role.drop-hover .figure { stroke: var(--accent); stroke-width: 2.2; }
  .role text {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 600;
    fill: var(--ink);
    pointer-events: none;
    text-anchor: middle;
  }
  .role { cursor: grab; }
  .role.dragging { cursor: grabbing; }

  /* --- Notes (sticky, square corners, small folded top-right) --- */
  /* Default colours = Note (yellow). type-question / type-problem override. */
  .note .note-main {
    fill: #fff7b3;
    stroke: #c9a227;
    stroke-width: 1;
    stroke-linejoin: miter;
  }
  .note .note-fold {
    fill: #f5e08f;
    stroke: #c9a227;
    stroke-width: 1;
    stroke-linejoin: miter;
  }
  .note.type-question .note-main { fill: #dbeafe; stroke: #2563eb; }
  .note.type-question .note-fold { fill: #bcd2f5; stroke: #2563eb; }
  .note.type-problem  .note-main { fill: #fed7aa; stroke: #ea580c; }
  .note.type-problem  .note-fold { fill: #f5be7e; stroke: #ea580c; }
  /* Resolved Question/Problem turns green */
  .note.resolved .note-main { fill: #d1fae5; stroke: #16a34a; }
  .note.resolved .note-fold { fill: #a7f3d0; stroke: #16a34a; }
  .note-check circle { fill: #16a34a; }
  .note-check path   { fill: none; stroke: #fff; stroke-width: 2.6;
                       stroke-linecap: round; stroke-linejoin: round; }
  /* Tiny right-arrow hint shown when a Question/Problem has replies */
  .note .note-replies path { fill: none; stroke: var(--ink); stroke-width: 1.6;
                             stroke-linecap: round; stroke-linejoin: round; }
  .note .note-replies text { fill: var(--ink); font: 700 9px var(--sans); }
  .note:hover .note-main { stroke-width: 1.4; }
  .note.selected .note-main {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .note.selected .note-fold { stroke: var(--selected); stroke-width: 2; }
  .note.linking-source .note-main,
  .note.linking-source .note-fold {
    stroke: var(--accent); stroke-width: 2; stroke-dasharray: 4 3;
  }
  .note { cursor: grab; }
  .note.dragging { cursor: grabbing; }
  .note-text {
    width: 100%;
    height: 100%;
    padding: 8px 10px;
    box-sizing: border-box;
    font: 12px/1.4 var(--sans);
    color: var(--ink);
    overflow: hidden;
    white-space: pre-wrap;
    word-break: break-word;
    pointer-events: none;
  }

  /* Replies tree (in the properties panel) */
  .replies-section { margin-top: 6px; }
  .replies-header  {
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.05em; color: var(--muted); margin: 4px 0 6px;
  }
  .reply-row {
    border: 1px solid var(--line);
    border-radius: 5px;
    background: #fcfcfc;
    margin-bottom: 6px;
  }
  .reply-children .reply-row { background: #f6f7f9; }
  .reply-head {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 6px 8px;
    cursor: pointer;
    font-size: 12px;
  }
  .reply-toggle {
    appearance: none;
    background: transparent;
    border: 0;
    color: var(--muted);
    font-size: 10px;
    width: 12px;
    padding: 0;
    cursor: pointer;
  }
  .reply-sym { font-size: 12px; }
  .reply-preview {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--ink);
  }
  .reply-row.resolved .reply-preview { text-decoration: line-through; color: var(--muted); }
  .reply-resolved-tag {
    font-size: 11px; font-weight: 700; color: #16a34a;
  }
  .reply-body { padding: 4px 8px 8px; display: flex; flex-direction: column; gap: 6px; }
  .reply-body textarea {
    font: inherit; font-size: 12px; padding: 6px 8px;
    border: 1px solid var(--line-strong); border-radius: 4px;
    min-height: 56px; resize: vertical;
  }
  .reply-meta { font-size: 11px; color: var(--muted); display: inline-flex; align-items: center; gap: 5px; }
  .reply-tools { display: flex; gap: 6px; }
  .reply-add-btn, .reply-del-btn, .replies-add-btn {
    appearance: none; background: transparent;
    border: 1px dashed var(--line-strong);
    color: var(--muted); font: inherit; font-size: 11px;
    padding: 4px 9px; border-radius: 4px; cursor: pointer;
  }
  .reply-add-btn:hover, .replies-add-btn:hover {
    color: var(--accent); border-color: var(--accent); background: var(--accent-soft);
  }
  .reply-del-btn:hover { color: var(--danger); border-color: var(--danger); background: #fdeaea; }
  .reply-children { margin-left: 14px; border-left: 2px solid var(--line); padding-left: 8px; }

  /* --- Endpoint (white box, centred rows, top-aligned) --- */
  .endpoint rect {
    fill: #ffffff;
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
  }
  .endpoint:hover rect { stroke-width: 1.5; }
  .endpoint.selected rect {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .endpoint { cursor: grab; }
  .endpoint.dragging { cursor: grabbing; }
  .endpoint-text {
    width: 100%;
    padding: 8px 10px;
    box-sizing: border-box;
    font: 12px/1.5 var(--sans);
    color: var(--ink);
    text-align: center;
    word-break: break-word;
    pointer-events: none;
  }
  .endpoint-text .ep-name {
    font-weight: 700;
    font-size: 13px;
    margin-bottom: 4px;
  }
  .endpoint-text .ep-name:empty::before {
    content: 'Endpoint';
    color: var(--muted);
    font-weight: 600;
  }
  .endpoint-text .ep-fields {
    white-space: pre-wrap;
    color: var(--ink);
  }
  /* Verb pills on the right edge of an endpoint, shown when the "Show Verbs"
     toggle is on. Colour-coded with the Swagger / Postman convention so the
     read / write / delete intent reads at a glance. */
  .endpoint rect.ep-verb { stroke: none; }
  .endpoint .ep-verb.verb-get,
  .endpoint .ep-verb.verb-get-id { fill: #0e9b6b; }
  .endpoint .ep-verb.verb-post   { fill: #2563eb; }
  .endpoint .ep-verb.verb-put    { fill: #d97706; }
  .endpoint .ep-verb.verb-patch  { fill: #7c3aed; }
  .endpoint .ep-verb.verb-delete { fill: #b91c1c; }
  .endpoint text.ep-verb-text {
    fill: #ffffff;
    font: 700 9.5px var(--sans);
    dominant-baseline: middle;
    text-anchor: middle;
    pointer-events: none;
    letter-spacing: 0.03em;
  }

  /* --- Pipeline (box with stage checkboxes in the body) --- */
  .pipeline rect {
    fill: #ffffff;
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
  }
  .pipeline:hover rect { stroke-width: 1.5; }
  .pipeline.selected rect {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .pipeline { cursor: grab; }
  .pipeline.dragging { cursor: grabbing; }
  .pipe-box {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    font: 12px/1.4 var(--sans);
    color: var(--ink);
    overflow: hidden;
  }
  .pipe-box .pipe-name {
    font-weight: 700;
    font-size: 13px;
    text-align: center;
    margin-bottom: 6px;
    padding-bottom: 5px;
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .pipe-box .pipe-budget {
    font-size: 11px;
    color: var(--muted);
    text-align: center;
    margin: -2px 0 6px;
  }
  .pipe-box .pipe-stage {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 2px 2px;
    cursor: pointer;
  }
  .pipe-box .pipe-stage input { margin: 0; }
  .pipe-box .pipe-stage.off { color: var(--muted); }
  /* Custom stages cluster at the bottom of a pipeline, separated visually
     by a "Custom" heading + a small gap from the built-in stages above. */
  .pipe-box .pipe-custom-wrap {
    margin-top: 10px;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .pipe-box .pipe-custom-head {
    font-size: 9.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    margin: 2px 0 2px;
    padding-top: 4px;
    border-top: 1px solid var(--line);
  }
  .pipe-box .pipe-custom-stage { display: flex; align-items: center; gap: 6px; }
  .pipe-box .pipe-custom-label {
    flex: 1;
    appearance: none;
    border: 0;
    border-bottom: 1px dashed transparent;
    background: transparent;
    font: inherit;
    font-size: 12px;
    color: inherit;
    padding: 1px 0;
    min-width: 0;
    outline: 0;
  }
  .pipe-box .pipe-custom-label:hover,
  .pipe-box .pipe-custom-label:focus { border-bottom-color: var(--line-strong); }
  .pipe-box .pipe-custom-del {
    appearance: none;
    background: transparent;
    border: 0;
    color: var(--muted);
    font-size: 14px;
    line-height: 1;
    padding: 0 4px;
    cursor: pointer;
    display: none;
  }
  .pipe-box .pipe-custom-stage:hover .pipe-custom-del { display: inline-block; }
  .pipe-box .pipe-custom-del:hover { color: var(--danger); }
  .pipe-box .pipe-custom-add {
    appearance: none;
    margin-top: 4px;
    padding: 3px 8px;
    background: transparent;
    border: 1px dashed var(--line-strong);
    border-radius: 4px;
    font: inherit;
    font-size: 11px;
    color: var(--muted);
    cursor: pointer;
    align-self: flex-start;
  }
  .pipe-box .pipe-custom-add:hover { color: var(--accent); border-color: var(--accent); }

  /* --- Agentic workflow (box; only a name + custom rows in the body, green-bordered) --- */
  .agentic rect {
    fill: #ffffff;
    stroke: #16a34a;
    stroke-width: 1.5;
  }
  .agentic:hover rect { stroke-width: 2; }
  .agentic.selected rect {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .agentic { cursor: grab; }
  .agentic.dragging { cursor: grabbing; }
  /* Re-use .pipe-box internals via a shared selector so existing styles
     (name header, stage rows, custom rows + add button) apply identically
     inside an Agentic workflow without copy-pasting the whole block. */
  .agentic .pipe-name { border-bottom-color: #bbf7d0; }

  /* --- Module (white box, centred name; Generic ones get a "10" mark) --- */
  .module rect.mod-body {
    fill: #ffffff;
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
  }
  .module:hover rect.mod-body { stroke-width: 1.5; }
  .module.selected rect.mod-body {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .module { cursor: grab; }
  .module.dragging { cursor: grabbing; }
  .module-text {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 8px 12px;
    font: 700 13px/1.35 var(--sans);
    color: var(--ink);
    text-align: center;
    word-break: break-word;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
  }
  .ten-badge rect { fill: #0e9b6b; }
  .ten-badge text {
    fill: #ffffff;
    font: 700 10px var(--sans);
  }

  /* --- Spike (planning card with status pill + optional resolved tint) --- */
  .spike rect.sp-body {
    fill: #ffffff;
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
  }
  .spike:hover rect.sp-body { stroke-width: 1.5; }
  .spike.selected rect.sp-body {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .spike.resolved rect.sp-body { fill: #d1fae5; stroke: #16a34a; }
  .spike { cursor: grab; }
  .spike.dragging { cursor: grabbing; }
  .spike-card {
    width: 100%; height: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    font: 12px/1.4 var(--sans);
    color: var(--ink);
    overflow: hidden;
    display: flex; flex-direction: column; gap: 4px;
    /* .canvas-snapshot in the PDF sets text-align:center to centre the SVG
       on the page — that propagates into the foreignObject and centres our
       text. Force left here so the PDF matches the on-screen layout. */
    text-align: left;
  }
  .spike-card .sp-name { font-weight: 700; font-size: 13px;
    word-break: break-word; }
  .spike-card .sp-label { font-size: 11px; font-weight: 700; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.04em; margin-top: 2px; }
  /* Result lives below Purpose — pull it down a touch so the two sections
     read as separate blocks rather than running together. */
  .spike-card .sp-label.sp-label-result { margin-top: 10px; }
  .spike-card .sp-text  { font-size: 11.5px; color: var(--ink);
    white-space: pre-wrap; word-break: break-word; }
  .spike-card .sp-pill {
    align-self: flex-start;
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 2px 7px;
    border-radius: 4px;
    color: #fff;
  }
  .spike-card .sp-pill.sp-suggested { background: #6b7280; }
  .spike-card .sp-pill.sp-decided   { background: #2563eb; }
  .spike-card .sp-pill.sp-skipped   { background: #9ca3af; }
  .spike-card .sp-meta {
    font-size: 11px; color: var(--muted);
    display: flex; flex-direction: column; gap: 1px;
  }
  .spike-card .sp-purpose {
    font-size: 11.5px; color: var(--ink);
    white-space: pre-wrap; word-break: break-word;
  }

  /* --- Document (uploaded artefact card) --- */
  .document rect.doc-body {
    fill: #ffffff;
    stroke: var(--ctx-stroke);
    stroke-width: 1.2;
  }
  .document:hover rect.doc-body { stroke-width: 1.5; }
  .document.selected rect.doc-body {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .document.active rect.doc-body { fill: #d1fae5; stroke: #16a34a; }
  .document { cursor: grab; }
  .document.dragging { cursor: grabbing; }
  .document-card {
    width: 100%; height: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    font: 12px/1.4 var(--sans);
    color: var(--ink);
    overflow: hidden;
    display: flex; flex-direction: column; gap: 3px;
    /* Same defence as .spike-card — keep PDF text left-aligned despite the
       centring rule on .canvas-snapshot. */
    text-align: left;
  }
  .document-card .doc-name {
    font-weight: 700; font-size: 13px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .document-card .doc-meta {
    font-size: 11px; color: var(--muted);
    display: flex; flex-direction: column; gap: 1px;
  }

  .rel line { stroke: var(--rel); stroke-width: 1.2; }
  .rel:hover line, .rel.selected line { stroke: var(--rel-strong); stroke-width: 1.8; }
  .rel.selected line { stroke: var(--selected); }
  /* Operations connectors: clearly dashed (visible line only, not hit line) */
  .view-map.mode-ops .rel line:not(.rel-pick) {
    stroke-width: 2;
    stroke-dasharray: 11 7;
    stroke-linecap: round;
  }
  .rel text {
    font-family: var(--sans);
    font-size: 11px;
    fill: var(--muted);
    text-anchor: middle;
    pointer-events: none;
  }
  .rel.selected text { fill: var(--selected); }

  .rel-marker rect {
    fill: #ffffff;
    stroke: var(--rel-strong);
    stroke-width: 1.2;
  }
  .rel-marker text {
    font-family: var(--sans);
    font-size: 10px;
    font-weight: 700;
    fill: var(--rel-strong);
    text-anchor: middle;
    dominant-baseline: middle;
    pointer-events: none;
    letter-spacing: 0.04em;
  }
  .rel.selected .rel-marker rect { stroke: var(--selected); }
  .rel.selected .rel-marker text { fill: var(--selected); }
  /* U / D side-mark sitting next to a relationship end. Smaller +
     italic so it reads as a secondary annotation rather than the
     primary end-marker. */
  .rel-ud-mark text {
    font-family: var(--sans);
    font-size: 10px;
    font-style: italic;
    font-weight: 700;
    fill: var(--rel-strong);
    pointer-events: none;
  }
  .rel.selected .rel-ud-mark text { fill: var(--selected); }

  .rel-pick { cursor: pointer; }

  #link-preview {
    stroke: var(--accent);
    stroke-width: 1.5;
    stroke-dasharray: 5 3;
    pointer-events: none;
    display: none;
  }
  /* Floating "start anchor" dot shown while the user is choosing the source
     of a new relationship (Phase 1: linking mode entered, no node picked yet). */
  #link-start-dot {
    fill: var(--accent);
    fill-opacity: 0.18;
    stroke: var(--accent);
    stroke-width: 1.6;
    pointer-events: none;
    display: none;
  }
  /* "Drop here" dot at the cursor end of the preview line (Phase 2). */
  #link-end-dot {
    fill: #fff;
    stroke: var(--accent);
    stroke-width: 1.6;
    pointer-events: none;
    display: none;
  }
  /* Crosshair cursor while in linking mode so the user knows we're waiting
     for a node click. !important defeats the per-node `.ctx { cursor: grab; }`
     etc. rules so the cursor stays a crosshair when hovering a candidate node. */
  .map-stage.linking-mode,
  .map-stage.linking-mode * { cursor: crosshair !important; }

  /* Rubber-band selection rectangle drawn while the user drags an empty
     part of the canvas. Hidden by default; JS sets x/y/width/height + display. */
  #select-rect {
    fill: var(--accent);
    fill-opacity: 0.08;
    stroke: var(--accent);
    stroke-width: 1;
    stroke-dasharray: 4 3;
    pointer-events: none;
    display: none;
  }
  /* Dashed bounding box around a multi-selected group so it's obvious those
     items are bound together as a single unit (drag/delete/copy/paste). */
  #multi-bbox {
    fill: none;
    stroke: var(--accent);
    stroke-width: 1.2;
    stroke-dasharray: 6 4;
    pointer-events: none;
    display: none;
  }

  /* --- EventStorming --- */
  /* pal-es items mirror the other pal-X visibility pattern: only shown on
     the EventStorming tab, and within ES they're further filtered per-phase
     by the .es-phase-N class on .view-map. */
  .view-map:not(.mode-es) .pal-es { display: none; }
  /* Same goes for the phase bar above the canvas and the session block. */
  .view-map:not(.mode-es) #es-phase-bar { display: none !important; }
  .view-map.mode-es #es-phase-bar:not([hidden]) { display: flex; }
  /* Per-phase + per-type visibility is computed in JS — see
     esApplyShapeVisibility(). Items the JS marks as locked carry the
     es-hidden class; everything else falls back to the default palette-item
     display rules. */
  .pal-es.es-shape.es-hidden { display: none !important; }
  /* Definition sits at the tail of the ES shape list, separated from
     the previous (Bounded Context for big-picture / Read Model for
     process-modeling) by a small gap so its terminology role reads
     as distinct from the workflow shapes above. */
  .pal-es.es-shape-definition { margin-top: 12px; }
  /* Sticky preview swatches in the palette. */
  .palette-item .es-sticky-preview {
    background: #fff;
    border: 1px solid var(--ctx-stroke);
  }
  .es-color-definition { background: #fff066 !important; }
  .es-color-event     { background: #ffb347 !important; }
  .es-color-command   { background: #60a5fa !important; }
  .es-color-hotspot   { background: #ec4899 !important; }
  .es-color-policy    { background: #c084fc !important; }
  .es-color-actor     { background: #fde68a !important; }
  .es-color-system    { background: #f9a8d4 !important; }
  .es-color-readmodel { background: #86efac !important; }
  .es-color-bc        { background: transparent !important; border: 1.5px dashed var(--ctx-stroke) !important; }
  /* Reflect the relative sticky sizes in the SHAPES palette so the user
     can see that External System lands as a big sticky and Actor / Person
     as a small one. */
  .palette-item .es-color-actor   { flex: 0 0 18px !important; width: 18px !important; height: 18px !important; }
  .palette-item .es-color-system  { flex: 0 0 40px !important; width: 40px !important; height: 22px !important; }

  /* Phase bar above the canvas. */
  .es-phase-bar {
    height: 36px;
    padding: 0 10px;
    background: var(--panel);
    border-bottom: 1px solid var(--line);
    flex-shrink: 0;
    align-items: center;
    gap: 14px;
    font-size: 11.5px;
    color: var(--ink);
    overflow-x: auto;
    white-space: nowrap;
  }
  .es-phase-bar label {
    display: inline-flex; align-items: center; gap: 5px;
    cursor: pointer;
    flex: 0 0 auto;
  }
  .es-phase-bar input { margin: 0; }
  .es-phase-bar .es-phase-title {
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 10px;
    flex: 0 0 auto;
  }

  /* Sticky shapes on the EventStorming canvas. Handwritten font, slightly
     bold, no auto-grow. Text wraps and is clipped by .es-text overflow. */
  .es-sticky rect.es-bg { stroke: #1f2328; stroke-width: 1.2; }
  .es-sticky.kind-event     rect.es-bg { fill: #ffb347; }
  .es-sticky.kind-command   rect.es-bg { fill: #60a5fa; }
  .es-sticky.kind-hotspot   rect.es-bg { fill: #ec4899; }
  .es-sticky.kind-policy    rect.es-bg { fill: #c084fc; }
  .es-sticky.kind-actor     rect.es-bg { fill: #fde68a; }
  .es-sticky.kind-system    rect.es-bg { fill: #f9a8d4; }
  .es-sticky.kind-readmodel rect.es-bg { fill: #86efac; }
  .es-sticky.kind-definition rect.es-bg { fill: #fff066; }
  .es-sticky.kind-bc        rect.es-bg { fill: rgba(255,255,255,0.15); stroke-dasharray: 4 3; stroke-width: 1.5; }
  .es-sticky { cursor: grab; }
  .es-sticky.dragging { cursor: grabbing; }
  .es-sticky.selected rect.es-bg {
    stroke: var(--selected);
    stroke-width: 2;
    filter: drop-shadow(0 1px 3px rgba(47,111,235,0.25));
  }
  .es-sticky-text {
    width: 100%; height: 100%;
    box-sizing: border-box;
    padding: 8px 9px;
    color: #1f2328;
    overflow: hidden;
    word-break: break-word;
    text-align: center;
    display: flex; align-items: center; justify-content: center;
    /* Handwritten / marker look — best-available system fonts first, then
       generic cursive. Slightly bold + italic so it reads at canvas zoom
       levels and conveys the workshop-y, sticky-note feel. */
    font: italic 700 13px/1.2 'Marker Felt', 'Bradley Hand', 'Chalkboard SE',
                              'Comic Sans MS', 'Apple Chancery', cursive, sans-serif;
    letter-spacing: 0.02em;
    pointer-events: none;
  }
  /* Sidebar palette labels for the ES shapes get the same italic treatment
     so the SHAPES list matches what ends up on the canvas. */
  .palette-item.es-shape .meta .name { font-style: italic; }
  .es-sticky.kind-bc .es-sticky-text {
    align-items: flex-start;
    text-align: left;
    padding: 6px 10px;
    font-weight: 700;
  }
  /* Definition sticky reads "term → explanation". Stacked: bold name on
     top, regular description below. justify-content:flex-start anchors
     the name at the very top of the box; without it the .es-sticky-text
     base rule centres the column vertically. */
  .es-sticky.kind-definition .es-sticky-text {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    text-align: left;
    padding: 6px 10px;
    white-space: pre-wrap;
  }
  .es-sticky.kind-definition .es-def-name {
    font-weight: 700;
    font-style: italic;
    margin-bottom: 4px;
  }
  /* Description text reads as ordinary prose — same sans font + colour
     as the Note shape rather than the handwritten ES sticky style. */
  .es-sticky.kind-definition .es-def-body {
    font: 12px/1.4 var(--sans);
    font-style: normal;
    color: var(--ink);
    letter-spacing: normal;
  }
  /* Inline editor for sticky text reuses the .edit-overlay; this is just
     a one-off font override so the textarea reads like the sticky itself. */
  .es-text-edit {
    border: 1px solid var(--accent);
    border-radius: 3px;
    background: rgba(255,255,255,0.96);
    color: #1f2328;
    padding: 8px 9px;
    box-sizing: border-box;
    resize: none;
    outline: 0;
    text-align: center;
    font: italic 700 13px/1.2 'Marker Felt', 'Bradley Hand', 'Chalkboard SE',
                              'Comic Sans MS', 'Apple Chancery', cursive, sans-serif;
  }

  /* Empty state when there's no session yet. */
  .es-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    font-size: 13px;
    text-align: center;
    pointer-events: none;
    padding: 0 24px;
  }

  /* --- Toast (global error notifications) --- */
  .toast-stack {
    position: fixed;
    bottom: 16px;
    right: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    z-index: 100;
    max-width: 360px;
    pointer-events: none;          /* let toast itself opt in via auto */
  }
  .toast {
    pointer-events: auto;
    background: #fff;
    border: 1px solid var(--line);
    border-left: 4px solid var(--line-strong);
    border-radius: 6px;
    padding: 10px 12px;
    box-shadow: 0 4px 18px rgba(0,0,0,0.12);
    font-size: 12px;
    color: var(--ink);
  }
  .toast.toast-err { border-left-color: #b91c1c; }
  .toast-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; margin-bottom: 2px;
  }
  .toast-title { font-weight: 700; color: var(--ink); }
  .toast-close {
    appearance: none; background: transparent; border: 0;
    font-size: 18px; line-height: 1; color: var(--muted); cursor: pointer;
    padding: 0; min-width: 18px;
  }
  .toast-close:hover { color: var(--ink); }
  .toast-msg { white-space: pre-wrap; word-break: break-word; color: var(--ink); }
  .toast-details {
    appearance: none; background: transparent; border: 0;
    font: inherit; font-size: 11px; color: var(--accent); cursor: pointer;
    padding: 4px 0 0; text-decoration: underline;
  }
  .toast-details:hover { color: var(--ink); }

  /* --- Inline edit overlay --- */
  .edit-overlay {
    position: absolute;
    display: none;
    z-index: 10;
  }
  .edit-overlay input {
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 4px 6px;
    border: 1px solid var(--accent);
    border-radius: 3px;
    background: white;
    outline: 0;
    min-width: 100px;
  }
  .edit-overlay select {
    font: inherit;
    font-size: 11px;
    padding: 3px 4px;
    border: 1px solid var(--accent);
    border-radius: 3px;
    background: white;
    outline: 0;
  }

  /* --- Generic --- */
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-thumb { background: #d8dbe0; border-radius: 5px; border: 2px solid var(--bg); }
  ::-webkit-scrollbar-thumb:hover { background: #b9bec6; }
  ::-webkit-scrollbar-track { background: transparent; }
