/*
  Layout concept: an extensible canvas — a plane much larger than the
  viewport, panned by dragging empty space or scrolling; items drift
  freely on it. The orb is the voice/text interaction surface, not a
  node in the relationship graph — only cards link to other cards (the
  backend's GraphEdge is item-to-item), so threads only ever connect
  card to card, never orb to card.
*/
:root{
  --paper:#F6F4F0; --surface:rgba(255,253,249,.88); --ink:#27303D;
  --slate:#526071; --ash:#8C94A0; --line:rgba(70,90,116,.16);
  --tone-a:#4E7FBC; --tone-b:#84AADA; --tone-deep:#325885;
  --amber:#B86018; --amber-dim:#96500E; --amber-soft:#FFF4E6;
  --accent-keep:#C98A5E; --accent-work:#4E7FBC; --accent-who:#C06B7A;
  --accent-ahead:#6E9C7C; --accent-remember:#A68FC9; --accent-identity:#B99347;

  /* z-index, named and banded instead of ad-hoc numbers assigned as each
     feature was built. Relative ordering preserved exactly from before
     this pass — only the gaps changed. Scaled ×10 from the original
     1-50 range (2026-10-04) to leave room to insert new bands later
     (audio/video, embedded/sandboxed code running inside a card) without
     ever needing to renumber existing ones again — only consumers that
     reference these by name needed zero changes for this rescale, which
     is the actual payoff of naming them in the first place. Added
     originally after the orb-response drag bug, where an element
     escaping its parent via reparenting lost an inherited z-index with
     no replacement — these names make that kind of dependency visible
     instead of implicit.

     Canvas content — the pannable plane and its own internal ordering */
  --z-link-paths:10;    /* .card-links */
  --z-card:20;          /* .card */
  --z-unlink-layer:30;  /* #unlink-layer */
  --z-unlink-btn:40;    /* .unlink-btn, .why-label */

  /* UI chrome — orb, topbar, minimap, controls anchored around the canvas */
  --z-topbar:60;        /* .topbar, .why-prompt */
  --z-chrome-btn:80;    /* .minimap */
  --z-link-drag:90;     /* #link-drag-svg */
  --z-controls:150;     /* .controls */
  /* Moved above --z-controls 2026-10-05: #orb-zone relocated from the
     bottom of the screen to top-center, now sharing visual space with
     .topbar/.controls instead of sitting far from them — its old value
     (50, below --z-topbar) would have let the topbar's own gradient
     background render on top of it. */
  --z-orb-zone:170;     /* #orb-zone */
  --z-add-menu:200;     /* .add-cascade, .field-stack */

  /* Overlays — dim backdrop, slide-in panels, floating/reparented response */
  --z-scrim:100;        /* .scrim */
  --z-sheet:110;        /* .sheet */
  --z-modal:120;        /* .card-modal */
  --z-ping:300;         /* .offscreen-ping */
  --z-toast:350;        /* .toast */
  --z-orb-response:400; /* .orb-response — explicit: can escape #orb-zone via reparenting while dragging */

  /* Full-screen takeover — above everything else on the page */
  --z-signin:500;       /* .signin-overlay */
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --paper:#1C2430; --surface:rgba(42,52,67,.88); --ink:#EDF1F6;
    --slate:#C5CEDB; --ash:#8591A3; --line:rgba(151,190,226,.18);
    --tone-a:#6E9BD6; --tone-b:#9BC0E8; --tone-deep:#4E7FBC;
    --amber:#C4854A; --amber-dim:#7A5230; --amber-soft:#1E1610;
    color-scheme: dark;
  }
}
:root[data-theme="dark"]{
  --paper:#1C2430; --surface:rgba(42,52,67,.88); --ink:#EDF1F6;
  --slate:#C5CEDB; --ash:#8591A3; --line:rgba(151,190,226,.18);
  --tone-a:#6E9BD6; --tone-b:#9BC0E8; --tone-deep:#4E7FBC;
  --amber:#C4854A; --amber-dim:#7A5230; --amber-soft:#1E1610;
  color-scheme: dark;
}

*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;background:var(--paper);color:var(--ink);font-family:'Plus Jakarta Sans',sans-serif;overflow:hidden}
.app{display:flex;flex-direction:column;height:100%}
body.visitor-mode .app{display:none}

.topbar{position:relative;z-index:var(--z-topbar);padding:24px 24px 16px calc(24px + env(safe-area-inset-left,0px));
  background:linear-gradient(var(--paper) 60%,transparent)}
:root{--controls-w:300px}
.brand{max-width:min(420px, calc(100vw - var(--controls-w) - 48px))}
.brand h1{font-family:'Fraunces',serif;font-weight:460;font-size:clamp(24px,3.4vw,32px);
  line-height:1.1;margin:0 0 6px;text-wrap:balance}
.brand p{margin:0;color:var(--slate);font-size:13.5px;line-height:1.5}

.controls{position:fixed;top:calc(20px + env(safe-area-inset-top,0px));
  right:calc(20px + env(safe-area-inset-right,0px));display:flex;align-items:center;gap:10px;z-index:var(--z-controls)}
.toggle{display:inline-flex;background:var(--surface);border:1px solid var(--line);border-radius:999px;padding:3px;gap:2px}
.toggle button{border:0;background:none;font:500 12px 'Plus Jakarta Sans',sans-serif;letter-spacing:.04em;
  text-transform:uppercase;color:var(--slate);padding:7px 14px;border-radius:999px;cursor:pointer;
  transition:background .2s,color .2s}
.toggle button.active{background:var(--tone-a);color:#fff}

.pill-btn{border:1px solid var(--line);background:var(--surface);color:var(--ink);font:500 13px 'Plus Jakarta Sans',sans-serif;
  padding:9px 16px;border-radius:999px;cursor:pointer;transition:border-color .2s,transform .15s}
.pill-btn:hover{border-color:var(--tone-a)}
.pill-btn:active{transform:scale(.97)}
.pill-btn.primary{background:var(--tone-deep);color:#fff;border-color:transparent}

.identity-btn{width:38px;height:38px;border-radius:50%;border:1px solid var(--line);background:var(--surface);
  display:grid;place-items:center;cursor:pointer;color:var(--accent-identity);flex:none;transition:border-color .2s}
.identity-btn:hover{border-color:var(--accent-identity)}
.identity-btn svg{width:17px;height:17px}

/* Add-menu trigger — moved 2026-10-05 from a standalone top-bar button
   into the orb's own input bar (Google "+"-in-search-bar pattern, direct
   owner reference), so there's one unified input surface instead of
   scattered top-bar chrome. Opens upward (not the old downward-right),
   since the bar it's anchored to is now fixed to the bottom of the
   screen — a downward menu would render off-screen. */
.orb-add-wrap{position:relative;flex:none}
.orb-add-btn{width:34px;height:34px;flex:none;border:1px solid var(--line);border-radius:50%;background:var(--surface);
  color:var(--slate);display:grid;place-items:center;cursor:pointer;transition:border-color .2s,color .2s}
.orb-add-btn:hover{border-color:var(--tone-a);color:var(--tone-a)}
.add-cascade{position:absolute;top:calc(100% + 10px);left:0;display:flex;flex-direction:column;gap:8px;
  opacity:0;transform:translateY(-6px);pointer-events:none;transition:opacity .18s,transform .18s;z-index:var(--z-add-menu);
  align-items:flex-start}
.add-cascade.on{opacity:1;transform:translateY(0);pointer-events:auto}
.type-pill{border:1px solid var(--line);background:var(--surface);color:var(--ink);
  font:600 12.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.02em;padding:11px 20px;border-radius:999px;
  cursor:pointer;white-space:nowrap;box-shadow:0 10px 26px rgba(39,48,61,.1);transform-origin:left center;
  transition:border-color .2s,transform .12s ease-out}
.type-pill:hover{border-color:var(--tone-a)}

.type-chip{display:inline-flex;align-items:center;gap:10px;border:1.5px solid var(--tone-a);
  background:color-mix(in srgb, var(--tone-a) 10%, var(--surface));color:var(--tone-deep);
  font:600 12.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.02em;padding:10px 10px 10px 20px;
  border-radius:999px;align-self:flex-start;box-shadow:0 10px 26px rgba(39,48,61,.1)}
.type-chip button{width:22px;height:22px;border-radius:50%;border:none;
  background:color-mix(in srgb, var(--tone-a) 18%, transparent);color:var(--tone-deep);
  display:grid;place-items:center;cursor:pointer;flex:none}

.field-stack{display:none;position:absolute;top:calc(100% + 10px);left:0;flex-direction:column;gap:10px;
  width:270px;max-height:calc(100vh - 110px);overflow-y:auto;z-index:var(--z-add-menu)}
.field-stack.on{display:flex}
.field-card{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:13px 16px;
  box-shadow:0 10px 26px rgba(39,48,61,.08)}
.field-card .tag{display:block;font:600 10px 'Plus Jakarta Sans',sans-serif;letter-spacing:.07em;text-transform:uppercase;
  color:var(--ash);margin-bottom:6px}
.field-card .tag b{color:var(--tone-a);font-weight:700}
.field-card input, .field-card textarea{width:100%;border:none;background:none;outline:none;padding:0;
  font:400 15px 'Plus Jakarta Sans',sans-serif;color:var(--ink);resize:none}
.field-card input::placeholder, .field-card textarea::placeholder{color:var(--ash)}

.add-more-btn{background:none;border:1.4px dashed var(--line);border-radius:14px;padding:12px 16px;
  color:var(--tone-a);font:600 12.5px 'Plus Jakarta Sans',sans-serif;cursor:pointer;text-align:left;
  transition:border-color .2s}
.add-more-btn:hover{border-color:var(--tone-a)}
.field-submit{background:var(--tone-deep);color:#fff;border:none;border-radius:999px;padding:13px;
  font:700 12.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.04em;text-transform:uppercase;cursor:pointer}

.upload-zone{border:1.4px dashed var(--line);border-radius:10px;padding:14px 10px;text-align:center;cursor:pointer;
  transition:border-color .2s,background .2s}
.upload-zone:hover{border-color:var(--tone-a);background:color-mix(in srgb, var(--tone-a) 5%, transparent)}
.upload-zone svg{color:var(--ash);margin-bottom:4px}
.upload-zone .t{font:600 12.5px 'Plus Jakarta Sans',sans-serif;color:var(--ink)}
.upload-zone .d{font-size:11px;color:var(--ash);margin-top:2px}
.drive-btn{display:flex;align-items:center;justify-content:center;gap:8px;border:1px solid var(--line);
  border-radius:10px;padding:9px;background:var(--surface);cursor:pointer;font:600 12.5px 'Plus Jakarta Sans',sans-serif;
  color:var(--ink);transition:border-color .2s;width:100%;margin-top:10px}
.drive-btn:hover{border-color:var(--tone-a)}
.drive-btn.connected{border-color:var(--tone-a);color:var(--tone-a);background:color-mix(in srgb, var(--tone-a) 8%, transparent)}

.email-addr{display:flex;align-items:center;gap:8px}
.email-addr code{flex:1;font:400 12px 'Plus Jakarta Sans',monospace;color:var(--ink);overflow-wrap:anywhere}
.email-addr button{flex:none;border:none;background:var(--tone-deep);color:#fff;border-radius:7px;padding:6px 10px;
  font:600 11px 'Plus Jakarta Sans',sans-serif;cursor:pointer}
.qf-note{font-size:11.5px;color:var(--ash);line-height:1.5;margin:0 0 10px}

.canvas-viewport{flex:1;position:relative;overflow:auto;cursor:grab;scrollbar-width:thin}
.canvas-viewport.panning{cursor:grabbing}
.canvas-plane{position:relative;width:2400px;height:1500px}

.card{position:absolute;width:218px;
  background:linear-gradient(color-mix(in srgb, var(--accent, var(--tone-a)) 9%, var(--surface)),
    color-mix(in srgb, var(--accent, var(--tone-a)) 9%, var(--surface)));
  border:1px solid color-mix(in srgb, var(--accent, var(--tone-a)) 22%, var(--line));
  border-radius:16px;padding:14px 16px 14px 19px;box-shadow:0 10px 28px rgba(39,48,61,.07);cursor:grab;
  z-index:var(--z-card);backdrop-filter:blur(6px);transition:box-shadow .2s,opacity .25s,filter .25s,background .2s,border-color .2s}
.card:active{cursor:grabbing}
.card:hover{box-shadow:0 16px 36px rgba(39,48,61,.12)}
.card::before{content:'';position:absolute;left:0;top:0;bottom:0;width:6px;border-radius:16px 0 0 16px;
  background:var(--accent, var(--tone-a))}
.card .eyebrow{font:600 10px 'Plus Jakarta Sans',sans-serif;letter-spacing:.07em;text-transform:uppercase;
  color:var(--accent, var(--tone-a));margin:0 0 5px;display:flex;align-items:center;justify-content:space-between;gap:6px}
.card h3{font-family:'Fraunces',serif;font-weight:460;font-size:17px;margin:0 0 3px;line-height:1.25}
.card .meta{margin:0;font-size:12.5px;color:var(--ash)}
.card.pinned{box-shadow:0 10px 28px rgba(39,48,61,.07),0 0 0 1.5px var(--accent,var(--tone-a))}

.eyebrow-icons{display:flex;align-items:center;gap:6px;flex:none}

.doc-icon{display:flex;align-items:center;justify-content:center;color:var(--ash);flex:none;width:16px;height:16px}

.share-dot{width:9px;height:9px;border-radius:50%;border:1.4px solid var(--ash);background:transparent;cursor:pointer;flex:none}
.share-dot.on{background:var(--tone-a);border-color:var(--tone-a)}
body.owner-mode .card[data-shareable="0"] .share-dot{opacity:.5}

.link-btn{display:flex;align-items:center;justify-content:center;color:var(--ash);cursor:pointer;flex:none;
  width:16px;height:16px;border-radius:50%;transition:color .15s,background .15s}
.link-btn:hover{color:var(--tone-a);background:color-mix(in srgb, var(--tone-a) 12%, transparent)}
.link-btn.link-hint{color:var(--tone-a);background:color-mix(in srgb, var(--tone-a) 16%, transparent);
  animation:linkHintPulse 1.8s ease-out}
@keyframes linkHintPulse{0%,40%,80%{box-shadow:0 0 0 0 color-mix(in srgb, var(--tone-a) 35%, transparent)}
  20%,60%{box-shadow:0 0 0 6px transparent}}
.card.link-source{outline:1.5px solid var(--tone-a);outline-offset:2px}
.card.link-target{outline:1.5px dashed var(--tone-a);outline-offset:2px;background:color-mix(in srgb, var(--tone-a) 6%, var(--surface))}
body.linking .card{cursor:crosshair}
/* A soft, ambient glow — not the link-gesture's dashed outline above,
   which means "drop here to link deliberately". This means "you're close
   enough that the system is about to notice this on its own", live while
   dragging, not only revealed after release via the toast. */
.card.proximity-near{box-shadow:0 0 0 2px color-mix(in srgb, var(--accent, var(--tone-a)) 40%, transparent),
  0 0 18px color-mix(in srgb, var(--accent, var(--tone-a)) 35%, transparent),
  0 10px 28px rgba(39,48,61,.07);transition:box-shadow .15s}
#link-drag-svg{position:absolute;inset:0;pointer-events:none;z-index:var(--z-link-drag)}
#link-drag-svg path{stroke:var(--tone-a);stroke-width:1.6;fill:none;stroke-dasharray:3 4}

.card-links{position:absolute;inset:0;pointer-events:none;z-index:var(--z-link-paths)}
.card-links path.visible{fill:none;stroke:var(--tone-a);
  stroke-width:calc(0.6px + var(--link-strength, 0.7) * 2.6px);
  opacity:calc(0.12 + var(--link-strength, 0.7) * 0.78)}
.card-links path.visible.inferred{stroke-dasharray:2 5}
.card-links path.visible.lit{opacity:.92;stroke-width:2.2px}
.card-links path.hit{fill:none;stroke:transparent;stroke-width:16;pointer-events:stroke;cursor:pointer}
#unlink-layer{position:absolute;inset:0;pointer-events:none;z-index:var(--z-unlink-layer)}
.unlink-btn{position:absolute;width:26px;height:26px;border-radius:50%;background:var(--surface);
  border:1.3px solid var(--line);color:var(--ash);display:flex;align-items:center;justify-content:center;
  cursor:pointer;transform:translate(-50%,-50%) scale(.6);z-index:var(--z-unlink-btn);font-size:12px;box-shadow:0 3px 10px rgba(39,48,61,.1);
  opacity:0;pointer-events:none;transition:border-color .15s,color .15s,transform .15s,opacity .15s}
.unlink-btn.show{opacity:1;pointer-events:auto;transform:translate(-50%,-50%) scale(1)}
.unlink-btn:hover{border-color:#c0392b;color:#c0392b;transform:translate(-50%,-50%) scale(1.12)}
.why-label{position:absolute;transform:translate(-50%,-50%);font:italic 11px 'Fraunces',serif;color:var(--slate);
  background:var(--surface);border:1px solid var(--line);border-radius:999px;padding:3px 10px;
  pointer-events:none;z-index:var(--z-unlink-btn);white-space:nowrap}
.why-prompt{position:absolute;display:none;transform:translate(-50%,-50%);width:150px;z-index:var(--z-topbar);
  border:1.4px dashed var(--tone-a);border-radius:999px;background:var(--surface);padding:6px 12px;
  font:italic 12px 'Fraunces',serif;color:var(--ink);outline:none;text-align:center}
.why-prompt.on{display:block}
.why-prompt::placeholder{color:var(--ash)}

.toast{position:fixed;top:20px;left:50%;transform:translateX(-50%) translateY(-12px);
  background:var(--ink);color:var(--paper);font:500 12.5px 'Plus Jakarta Sans',sans-serif;padding:11px 20px;
  border-radius:999px;box-shadow:0 14px 34px rgba(0,0,0,.2);z-index:var(--z-toast);opacity:0;pointer-events:none;
  transition:opacity .25s,transform .25s;white-space:nowrap;display:flex;align-items:center;gap:8px}
.toast.on{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
.toast .tag{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--amber);
  border:1px solid color-mix(in srgb, var(--amber) 50%, transparent);border-radius:999px;padding:2px 7px}
.toast-undo{display:none;border:none;background:none;color:var(--paper);font:700 11.5px 'Plus Jakarta Sans',sans-serif;
  letter-spacing:.03em;text-transform:uppercase;text-decoration:underline;text-underline-offset:2px;
  cursor:pointer;padding:0;margin-left:2px}
.toast.has-undo .toast-undo{display:inline}

/* Fixed to the viewport, not the pannable canvas — desktop redesign,
   2026-10-05 (owner decision: text entry should be always visible
   regardless of pan position, not "visible if you haven't panned
   away"). Deliberately diverges from mobile, which keeps the orb as a
   canvas citizen (see the mobile media query below) since speech-first
   + swipe-to-capture make sense there in a way they don't on desktop,
   where typing is the dominant real use case and voice isn't even
   implemented yet. No transform anywhere in #orb-zone's ancestor chain
   (#plane/#viewport are untransformed — panning here is native scroll,
   not a CSS transform), so this works without moving the element in
   the DOM at all, unlike the earlier orb-response drag bug.

   Top-center, not bottom — real issue found via live test, same day:
   bottom placement floats the bar inside the pannable canvas region
   itself, so it visually competes with whatever cards happen to be
   underneath it (and always will, for any fixed position inside that
   region). Top-center sits in the same zone as .topbar/.controls,
   which is structurally outside the canvas — nothing can ever be
   dragged under it, so the overlap problem doesn't just move
   elsewhere, it goes away. */
/* display:flex stays on the shared .orb-zone class — .vv-orb-zone
   (the visitor preview, below) relies on inheriting it, never
   redeclares display itself. Positioning properties move to #orb-zone
   (ID, not class): the visitor preview shares the .orb-zone class with
   its own position:relative override, and a class-vs-class specificity
   tie is source-order-fragile — confirmed it would actually have broken
   the visitor preview on mobile via the media query further down. An ID
   is specificity-safe regardless of where either rule sits in the file. */
.orb-zone{display:flex}
#orb-zone{position:fixed;left:50%;top:24px;transform:translateX(-50%);z-index:var(--z-orb-zone);
  flex-direction:column;align-items:center;gap:10px}
.orb{width:80px;height:80px;border-radius:50%;background:var(--paper);border:1.5px solid var(--amber);
  display:flex;align-items:center;justify-content:center;cursor:pointer;user-select:none;-webkit-user-select:none;
  touch-action:none;position:relative;box-shadow:0 0 40px color-mix(in srgb, var(--amber) 14%, transparent),0 20px 50px rgba(39,48,61,.14)}
/* Morph transition only for visitor preview — owner orb (#orb) is a static pill via inline style */
.vv-orb-zone .orb{transition:width .4s cubic-bezier(.22,1,.36,1),height .4s cubic-bezier(.22,1,.36,1),border-radius .4s cubic-bezier(.22,1,.36,1)}
.orb-ring{position:absolute;border-radius:50%;border:1px solid var(--amber);opacity:0;pointer-events:none}
.orb-ring-1{inset:-14px}.orb-ring-2{inset:-26px}.orb-ring-3{inset:-40px}
.orb.listening .orb-ring{animation:ring-pulse 2.2s ease-out infinite}
.orb.listening .orb-ring-2{animation-delay:.45s}.orb.listening .orb-ring-3{animation-delay:.9s}
@keyframes ring-pulse{0%{transform:scale(.94);opacity:.28}100%{transform:scale(1.06);opacity:0}}
.orb-bars{display:flex;align-items:center;gap:3px}
.orb-bar{width:3px;height:8px;border-radius:2px;background:var(--amber);opacity:.4}
.orb.listening .orb-bar{animation:bar-anim .75s ease-in-out infinite}
.orb.listening .orb-bar:nth-child(1){animation-delay:0s}.orb.listening .orb-bar:nth-child(2){animation-delay:.12s}
.orb.listening .orb-bar:nth-child(3){animation-delay:.06s}.orb.listening .orb-bar:nth-child(4){animation-delay:.18s}
.orb.listening .orb-bar:nth-child(5){animation-delay:.09s}
@keyframes bar-anim{0%,100%{height:4px;opacity:.35}50%{height:22px;opacity:1}}

.orb-zone.typing .orb{width:min(420px,78vw);height:56px;border-radius:999px}
.orb-zone.typing .orb-bars,.orb-zone.typing .orb-ring{display:none}
.orb-input{opacity:0;pointer-events:none;position:absolute;inset:0;display:flex;align-items:center;gap:8px;
  padding:0 8px 0 10px;transition:opacity .2s .1s}
.orb-zone.typing .orb-input{opacity:1;pointer-events:auto}
.orb-input input{flex:1;border:0;outline:none;background:none;min-width:0;font:400 15px 'Plus Jakarta Sans',sans-serif;color:var(--ink)}
.orb-input input::placeholder{color:var(--ash)}
.orb-send{width:38px;height:38px;flex:none;border:0;border-radius:50%;background:var(--amber);color:#fff;
  display:grid;place-items:center;cursor:pointer}

/* Owner input bar (#orb) — always a static pill; no morph, no typing-class dependency.
   Visitor preview (#vv-orb) keeps the circle-→-pill morph via .orb/.orb-zone.typing above. */
#orb{width:min(460px,84vw);height:52px;border-radius:999px;cursor:default;transition:border-color .4s}
#orb .orb-input{opacity:1;pointer-events:auto}

/* Thinking state: solid border becomes marching dashes (_____ → ·····) via SVG
   stroke-dashoffset animation — the border itself animates rather than any overlay.
   Solid amber returns when .listening is removed. */
/* inset:-1.5px aligns the SVG outer edge with the CSS border outer edge so dashes
   trace exactly where the solid border sits at rest */
.orb-border-svg{position:absolute;inset:-1.5px;width:calc(100% + 3px);height:calc(100% + 3px);
  pointer-events:none;display:none;overflow:visible}
.orb-border-rect{x:0.75px;y:0.75px;width:calc(100% - 1.5px);height:calc(100% - 1.5px);rx:26px;
  fill:none;stroke:var(--amber);stroke-width:1.5;stroke-dasharray:4 5}
#orb.listening{border-color:transparent}
#orb.listening .orb-border-svg{display:block}
#orb.listening .orb-border-rect{animation:march .9s linear infinite}
@keyframes march{to{stroke-dashoffset:-9}}
.orb-mic{width:38px;height:38px;flex:none;border:0;border-radius:50%;background:var(--amber);color:#fff;
  display:grid;place-items:center;cursor:pointer}

/* No longer suppressed while .typing — on desktop .typing is permanent
   (see initOrb), so this is now the live status line ("Thinking…")
   rather than an open/closed-state hint. */
.orb-hint{font-size:12.5px;color:var(--ash);font-style:italic;font-family:'Fraunces',serif;text-align:center;
  transition:opacity .2s;white-space:nowrap}

.orb-response{position:absolute;top:calc(100% + 18px);left:50%;transform:translateX(-50%) translateY(6px) scale(.97);
  width:min(300px,78vw);padding:12px 16px;border:1px solid color-mix(in srgb, var(--amber) 30%, var(--line));
  border-radius:16px;background:var(--surface);box-shadow:0 16px 40px rgba(45,57,73,.14);backdrop-filter:blur(14px);
  font:italic 13.5px/1.5 'Fraunces',serif;color:var(--slate);text-align:center;opacity:0;pointer-events:none;
  /* Explicit, not inherited from #orb-zone's --z-orb-zone — while
     dragging this is reparented to <body>, which escapes that stacking
     context entirely, so it needs its own z-index to still sit above
     regular cards regardless of which parent it's currently in. */
  z-index:var(--z-orb-response);
  transition:opacity .3s,transform .35s cubic-bezier(.22,1,.36,1)}
.orb-response.on{opacity:1;transform:translateX(-50%) translateY(0) scale(1)}
/* Grabbable anywhere on the card, matching real canvas cards — not a
   dedicated handle (see initOrb's pointerdown handler in ui.js for why
   that was the actual bug, not just a positioning glitch).
   -webkit-user-drag:none + user-select:none across the whole card (not
   just a sub-element) stop the browser's own native text/link drag-ghost
   from taking over on a click-drag that starts off-handle — that native
   ghost detaches from the card and follows the cursor independently,
   which is what looked like "the hand icon is somewhere else." */
.orb-response.has-cards{pointer-events:auto;width:min(360px,88vw);text-align:left;max-height:70vh;overflow-y:auto;
  user-select:none;-webkit-user-drag:none;cursor:grab;touch-action:none}
.orb-response.has-cards a{-webkit-user-drag:none}
.orb-response.has-cards.dragging{cursor:grabbing}
.orb-response.has-cards a,.orb-response.has-cards button{cursor:pointer}

.orb-reply-text{margin:0 0 10px}
.orb-event-cards{display:flex;flex-direction:column;gap:8px;margin-bottom:10px}

/* Research progress card — same floating/draggable/stacking shell as
   event cards (.has-cards), but for a long-running background task
   (search_research tool) rather than a static result. The pulsing dots
   are the "something is actually happening" signal a plain auto-hiding
   text reply couldn't give — real owner complaint, 2026-10-05. */
.orb-research-card{border:1px solid var(--line);border-radius:12px;background:var(--paper);padding:12px 14px;
  font-style:normal;text-align:left;display:flex;align-items:center;gap:10px}
.orb-research-dots{display:flex;gap:4px;flex:0 0 auto}
.orb-research-dots span{width:6px;height:6px;border-radius:50%;background:var(--tone-a);
  animation:research-dot-pulse 1.1s ease-in-out infinite}
.orb-research-dots span:nth-child(2){animation-delay:.15s}
.orb-research-dots span:nth-child(3){animation-delay:.3s}
@keyframes research-dot-pulse{0%,60%,100%{opacity:.25;transform:scale(.85)}30%{opacity:1;transform:scale(1)}}
.orb-research-text{font:500 12.5px 'Plus Jakarta Sans',sans-serif;color:var(--ink)}
.orb-research-card.done .orb-research-dots{display:none}
.orb-event-card{border:1px solid var(--line);border-radius:12px;background:var(--paper);padding:10px 12px;
  font-style:normal;text-align:left}
.orb-event-account{font:600 9.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.06em;text-transform:uppercase;
  color:var(--tone-a);margin-bottom:4px}
.orb-event-title{font:600 13px 'Plus Jakarta Sans',sans-serif;color:var(--ink);margin-bottom:2px}
.orb-event-time{font:500 12px 'Plus Jakarta Sans',sans-serif;color:var(--tone-a)}
.orb-event-more-toggle{display:block;margin:6px 0 0;padding:0;background:none;border:none;
  font:600 11px 'Plus Jakarta Sans',sans-serif;color:var(--ash);cursor:pointer}
.orb-event-more-toggle:hover{color:var(--tone-a)}
.orb-event-more{margin-top:6px}
.orb-event-attendees{font:400 11.5px 'Plus Jakarta Sans',sans-serif;color:var(--ash);margin-top:3px}
.orb-event-link{display:inline-block;margin-top:6px;font:600 11.5px 'Plus Jakarta Sans',sans-serif;color:var(--tone-a);text-decoration:none}
.orb-event-link:hover{text-decoration:underline}
.orb-response-close{display:block;margin:0 auto;background:none;border:1px solid var(--line);border-radius:999px;
  padding:5px 16px;font:600 11.5px 'Plus Jakarta Sans',sans-serif;color:var(--slate);cursor:pointer;
  font-style:normal}
.orb-response-close:hover{border-color:var(--tone-a);color:var(--tone-a)}

.orb-form{display:flex;flex-direction:column;gap:10px;font-style:normal}
.orb-form input,.orb-form select{user-select:text}
.orb-form-label{display:flex;flex-direction:column;gap:4px;font:600 10.5px 'Plus Jakarta Sans',sans-serif;
  letter-spacing:.04em;text-transform:uppercase;color:var(--ash)}
.orb-form-label input,.orb-form-label select{font:400 13.5px 'Plus Jakarta Sans',sans-serif;color:var(--ink);
  background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:8px 10px;text-transform:none;
  letter-spacing:normal;cursor:text}
.orb-form-label select{cursor:pointer}
.orb-form-label input:focus,.orb-form-label select:focus{outline:none;border-color:var(--tone-a)}
.orb-form-row{display:flex;gap:8px}
.orb-form-row .orb-form-label{flex:none}
.orb-form-when{flex:1 1 auto;min-width:0}
.orb-form-duration{flex:0 0 84px}
.orb-form-duration select{width:100%}
.orb-form-error{margin:0;min-height:14px;font:500 11.5px 'Plus Jakarta Sans',sans-serif;color:#c0392b}
.orb-form-actions{display:flex;gap:8px;margin-top:2px}
.orb-form-create{flex:1;background:var(--tone-a);border:none;border-radius:10px;padding:10px 14px;color:#fff;
  font:600 13px 'Plus Jakarta Sans',sans-serif;cursor:pointer}
.orb-form-create:hover{background:var(--tone-deep)}
.orb-form-create:disabled{opacity:.6;cursor:default}
.orb-form-cancel{background:none;border:1px solid var(--line);border-radius:10px;padding:10px 14px;
  color:var(--slate);font:600 13px 'Plus Jakarta Sans',sans-serif;cursor:pointer}
.orb-form-cancel:hover{border-color:var(--tone-a);color:var(--tone-a)}

.minimap{position:fixed;right:20px;bottom:20px;width:150px;height:94px;border-radius:12px;
  border:1px solid var(--line);background:var(--surface);backdrop-filter:blur(8px);z-index:var(--z-chrome-btn);
  box-shadow:0 10px 26px rgba(39,48,61,.12);cursor:pointer;overflow:hidden}
.minimap-dot{position:absolute;width:5px;height:5px;border-radius:50%;background:var(--accent,var(--tone-a))}
.minimap-cluster{position:absolute;min-width:14px;height:14px;padding:0 3px;border-radius:999px;
  background:var(--tone-deep);color:#fff;font:700 8.5px 'Plus Jakarta Sans',sans-serif;
  display:flex;align-items:center;justify-content:center;transform:translate(-50%,-50%);
  box-shadow:0 2px 6px rgba(39,48,61,.25)}
.minimap-view{position:absolute;border:1.4px solid var(--tone-a);border-radius:4px;
  background:color-mix(in srgb, var(--tone-a) 10%, transparent);pointer-events:none}

.offscreen-ping{position:fixed;width:34px;height:34px;border-radius:50%;background:var(--tone-deep);
  color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:var(--z-ping);
  opacity:0;pointer-events:none;transition:opacity .2s;box-shadow:0 8px 20px rgba(39,48,61,.25)}
.offscreen-ping.on{opacity:1;pointer-events:auto}
.offscreen-ping svg{width:16px;height:16px}

.visitor-view{display:none;height:100%;flex-direction:column;align-items:center;justify-content:center;
  position:relative;gap:28px;padding:24px}
body.visitor-mode .visitor-view{display:flex}
.vv-orb-zone{position:relative;left:auto;top:auto;transform:none;flex-direction:column;align-items:center;gap:18px}
.vv-greeting{font-family:'Fraunces',serif;font-style:italic;font-weight:420;font-size:17px;color:var(--slate);
  text-align:center;line-height:1.5;max-width:360px;margin:0}
.vv-back{position:absolute;top:24px;left:24px;border:1px solid var(--line);background:var(--surface);
  color:var(--slate);font:500 12.5px 'Plus Jakarta Sans',sans-serif;padding:8px 14px;border-radius:999px;
  cursor:pointer;transition:border-color .2s}
.vv-back:hover{border-color:var(--tone-a)}
#vv-orb-response{position:static;opacity:1;transform:none;pointer-events:none;width:min(380px,84vw);display:none}
#vv-orb-response.on{display:block}

/* ── Sign-in — voice is the default (matches the product's own trust
   model), the static key stays an explicit, always-available fallback. ── */
.signin-overlay{position:fixed;inset:0;background:var(--paper);z-index:var(--z-signin);display:none;align-items:center;justify-content:center}
.signin-overlay.on{display:flex}
.signin-card{width:min(380px,88vw);text-align:center;padding:36px 30px;border:1px solid var(--line);
  border-radius:20px;background:var(--surface);box-shadow:0 30px 70px rgba(28,36,48,.16)}
.signin-card h2{font-family:'Fraunces',serif;font-weight:460;font-size:26px;margin:0 0 8px}
.signin-sub{color:var(--slate);font-size:13.5px;line-height:1.5;margin:0 0 22px}
.signin-voicemark-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;
  background:var(--tone-deep);color:#fff;border:none;border-radius:999px;padding:13px 20px;
  font:700 13px 'Plus Jakarta Sans',sans-serif;letter-spacing:.03em;text-transform:uppercase;
  cursor:pointer;transition:opacity .2s}
.signin-voicemark-btn:hover{opacity:.92}
.signin-status{font-size:12.5px;color:var(--ash);min-height:18px;margin:12px 0 0}
.signin-fallback{display:block;margin:18px auto 0;border:none;background:none;color:var(--slate);
  font:500 12px 'Plus Jakarta Sans',sans-serif;text-decoration:underline;text-underline-offset:2px;cursor:pointer}

.scrim{position:fixed;inset:0;background:rgba(28,36,48,.32);opacity:0;pointer-events:none;transition:opacity .25s;z-index:var(--z-scrim)}
.scrim.on{opacity:1;pointer-events:auto}
.sheet{position:fixed;right:0;top:0;bottom:0;width:min(380px,92vw);background:var(--paper);
  border-left:1px solid var(--line);box-shadow:-20px 0 50px rgba(28,36,48,.18);transform:translateX(100%);
  transition:transform .35s cubic-bezier(.22,1,.36,1);z-index:var(--z-sheet);padding:24px 22px;overflow-y:auto}
.sheet.on{transform:translateX(0)}
.sheet h2{font-family:'Fraunces',serif;font-weight:460;font-size:22px;margin:0 0 4px}
.sheet .sub{color:var(--ash);font-size:13px;margin:0 0 20px}
.sheet .section-label{font:600 10.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ash);margin:26px 0 4px}
.sheet .section-label:first-of-type{margin-top:4px}
.recipe-label-row{display:flex;align-items:center;gap:6px}
.recipe-info-btn{width:16px;height:16px;flex:none;border-radius:50%;border:1px solid var(--ash);background:none;
  color:var(--ash);font:600 10px 'Plus Jakarta Sans',sans-serif;cursor:pointer;display:grid;place-items:center;
  line-height:1;padding:0}
.recipe-info-btn:hover{border-color:var(--tone-a);color:var(--tone-a)}

/* Plain-language explainer popup, same centered-overlay pattern as
   .card-modal. Direct owner request, 2026-10-05: the Recipe section's
   real model names/call-counts aren't obvious to a new owner — "suggest
   being able to click on brain and get a pop up with further details
   in laypersons terms... ST owners can become more educated about
   their AI." Static copy, not fetched — this is explanation, not data. */
.recipe-info-modal{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%) scale(.96);
  width:min(420px,88vw);max-height:80vh;overflow-y:auto;background:var(--paper);border-radius:18px;
  border:1px solid var(--line);box-shadow:0 40px 90px rgba(28,36,48,.28);z-index:var(--z-modal);
  opacity:0;pointer-events:none;padding:26px 26px 20px;transition:opacity .25s,transform .25s cubic-bezier(.22,1,.36,1)}
.recipe-info-modal.on{opacity:1;transform:translate(-50%,-50%) scale(1);pointer-events:auto}
.recipe-info-modal h3{font-family:'Fraunces',serif;font-weight:460;font-size:19px;margin:0 0 16px}
.recipe-info-close{position:absolute;top:18px;right:18px;width:26px;height:26px;border-radius:50%;
  border:1px solid var(--line);background:var(--surface);color:var(--slate);display:grid;place-items:center;
  cursor:pointer}
.recipe-info-item{padding:12px 0;border-top:1px solid var(--line)}
.recipe-info-item:first-of-type{border-top:none;padding-top:0}
.recipe-info-item .t{font:600 13px 'Plus Jakarta Sans',sans-serif;color:var(--ink);margin-bottom:3px}
.recipe-info-item p{margin:0;font-size:12.5px;line-height:1.5;color:var(--slate)}
.sheet .row{display:flex;align-items:center;justify-content:space-between;padding:13px 0;border-top:1px solid var(--line);gap:12px}
.sheet .row .label{font:600 14px 'Plus Jakarta Sans',sans-serif}
.sheet .row .desc{font-size:12px;color:var(--ash);margin-top:2px}
.switch{width:38px;height:22px;border-radius:999px;background:var(--line);position:relative;cursor:pointer;flex:none;transition:background .2s}
.switch.on{background:var(--tone-a)}
.switch::after{content:'';position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.2);transition:transform .2s}
.switch.on::after{transform:translateX(16px)}
.recipe-pair{display:flex;gap:8px;padding:10px 0;border-top:1px solid var(--line)}
.recipe-pair .side{flex:1;border:1px solid var(--line);border-radius:12px;padding:10px 12px;cursor:pointer;
  transition:border-color .2s,background .2s}
.recipe-pair .side.on{border-color:var(--tone-a);background:color-mix(in srgb, var(--tone-a) 8%, transparent)}
.recipe-pair .side .t{font:600 12.5px 'Plus Jakarta Sans',sans-serif}
.recipe-pair .side .d{font-size:11px;color:var(--ash);margin-top:2px}
.recipe-pair#recipe-scale .side{cursor:default}
.recipe-note{margin:2px 0 0;font-size:10.5px;color:var(--ash);font-style:italic}
.close-sheet{position:absolute;top:22px;right:20px;width:30px;height:30px;border-radius:50%;border:1px solid var(--line);
  background:var(--surface);display:grid;place-items:center;cursor:pointer;color:var(--slate)}

.card-modal{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%) scale(.96);width:min(560px,92vw);
  max-height:85vh;overflow-y:auto;background:var(--paper);border-radius:20px;border:1px solid var(--line);
  box-shadow:0 40px 90px rgba(28,36,48,.28);z-index:var(--z-modal);opacity:0;pointer-events:none;
  transition:opacity .25s,transform .25s cubic-bezier(.22,1,.36,1)}
.card-modal.on{opacity:1;transform:translate(-50%,-50%) scale(1);pointer-events:auto}
.cm-topbar{height:4px;background:var(--accent,var(--tone-a));border-radius:20px 20px 0 0}
.cm-body{padding:28px 30px 24px}
.cm-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:18px}
.cm-eyebrow{font:600 11px 'Plus Jakarta Sans',sans-serif;letter-spacing:.07em;text-transform:uppercase;
  color:var(--accent,var(--tone-a));padding-top:4px}
.cm-nav{display:flex;align-items:center;gap:8px;flex:none}
.cm-nav button{width:30px;height:30px;border-radius:50%;border:1px solid var(--line);background:var(--surface);
  display:grid;place-items:center;cursor:pointer;color:var(--slate);transition:border-color .2s}
.cm-nav button:hover{border-color:var(--tone-a)}
.cm-nav button:disabled{opacity:.35;cursor:default;pointer-events:none}
.cm-title{font-family:'Fraunces',serif;font-weight:460;font-size:36px;line-height:1.1;margin:0 0 10px;outline:none;text-wrap:balance}
.cm-title[contenteditable="true"]{border-bottom:1.5px dashed var(--tone-a)}
.cm-subtitle{font-family:'Fraunces',serif;font-style:italic;font-size:16px;color:var(--slate);margin:0 0 22px;outline:none}
.cm-subtitle[contenteditable="true"]{border-bottom:1.5px dashed var(--tone-a)}
.cm-share{display:inline-flex;align-items:center;gap:7px;font-size:13px;color:var(--ash);cursor:pointer;margin-bottom:16px;padding:4px 0}
.cm-share .dot{width:8px;height:8px;border-radius:50%;border:1.4px solid var(--ash)}
.cm-share.on .dot{background:var(--tone-a);border-color:var(--tone-a)}
.cm-note-zone{border:1.6px dashed var(--line);border-radius:10px;padding:13px 16px;cursor:pointer;
  color:var(--slate);font-size:13.5px;transition:border-color .2s,background .2s;min-height:20px}
.cm-note-zone:hover{border-color:var(--tone-a)}
.cm-note-zone textarea{width:100%;border:none;background:none;outline:none;resize:vertical;min-height:60px;
  font:400 13.5px 'Plus Jakarta Sans',sans-serif;color:var(--ink)}
.cm-colours{display:flex;align-items:center;gap:9px;margin-top:18px}
.cm-colours .label{font:600 10.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.06em;text-transform:uppercase;color:var(--ash);margin-right:3px}
/* "What's linked here" — the card modal never listed its own links before
   (only a button to start a new one), so there was no way to see
   connections without hunting for the thread on the canvas. The data
   model has no direction (item_a/item_b is canonical storage order, not
   semantics — upsert_link discards whichever end initiated the link), so
   one list genuinely covers "backlinks" in full, not just outgoing. */
/* Documents sheet — generic browse/preview across every source (manual
   upload, Drive, research), not tied to any one card. Direct owner
   request, 2026-10-05: a document was otherwise only reachable through
   the one card that happened to hold it, with no way to browse past
   ones at all. Preview body reuses .cm-document-* below as-is. */
.documents-list{display:flex;flex-direction:column;gap:2px;margin-top:4px}
.documents-list-item{display:flex;align-items:center;gap:11px;padding:11px 4px;border-bottom:1px solid var(--line);
  cursor:pointer}
.documents-list-item:hover{background:color-mix(in srgb, var(--tone-a) 6%, transparent)}
.documents-list-icon{width:30px;height:30px;border-radius:9px;flex:none;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb, var(--tone-a) 12%, transparent);color:var(--tone-a)}
.documents-list-meta{display:flex;flex-direction:column;gap:2px;min-width:0}
.documents-list-name{font:600 13px 'Plus Jakarta Sans',sans-serif;color:var(--ink);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.documents-list-sub{font:500 11px 'Plus Jakarta Sans',sans-serif;color:var(--ash)}
.documents-empty{font:italic 12.5px 'Fraunces',serif;color:var(--ash)}
.documents-back{margin:0 0 14px;font:600 12px 'Plus Jakarta Sans',sans-serif;color:var(--tone-a);cursor:pointer}
.documents-back:hover{text-decoration:underline}

.cm-document{margin-top:16px}
.cm-document .label{display:block;font:600 10.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ash);margin-bottom:8px}
.cm-document-loading{font:italic 12.5px 'Fraunces',serif;color:var(--ash)}
.cm-document-add{margin:0;font:500 12.5px 'Plus Jakarta Sans',sans-serif;color:var(--tone-a);cursor:pointer}
.cm-document-add:hover{text-decoration:underline}
.cm-document-card{border:1px solid var(--line);border-radius:14px;background:var(--surface);overflow:hidden;
  box-shadow:0 1px 2px rgba(39,48,61,.04)}
.cm-document-head{display:flex;align-items:center;gap:11px;padding:13px 14px;border-bottom:1px solid var(--line)}
.cm-document-open{display:block;padding:9px 14px;font:600 11.5px 'Plus Jakarta Sans',sans-serif;color:var(--tone-a);
  border-bottom:1px solid var(--line);text-decoration:none}
.cm-document-open:hover{text-decoration:underline}
.cm-document-icon{width:34px;height:34px;border-radius:10px;flex:none;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb, var(--tone-a) 14%, var(--surface));color:var(--tone-a)}
.cm-document-meta{display:flex;flex-direction:column;gap:2px;min-width:0}
.cm-document-name{font:600 13px 'Plus Jakarta Sans',sans-serif;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cm-document-sub{font:500 11.5px 'Plus Jakarta Sans',sans-serif;color:var(--ash)}
.cm-document-preview-wrap{position:relative;max-height:200px;overflow-y:auto}
.cm-document-preview{margin:0;padding:14px;font:400 13.5px/1.65 'Plus Jakarta Sans',sans-serif;color:var(--slate)}
.cm-document-fade{position:absolute;left:0;right:0;bottom:0;height:44px;pointer-events:none;
  background:linear-gradient(to bottom, transparent, var(--surface))}

.cm-drive{margin-top:16px}
.cm-drive .label{display:block;font:600 10.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ash);margin-bottom:8px}
.cm-drive-sources{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.cm-drive-source{display:flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:10px;
  padding:7px 10px;background:var(--surface)}
.cm-drive-source-label{flex:1;min-width:0;font:600 12px 'Plus Jakarta Sans',sans-serif;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cm-drive-source-acct{font:500 10.5px 'Plus Jakarta Sans',sans-serif;color:var(--ash);flex:none}
.cm-drive-source-rm{color:var(--ash);cursor:pointer;flex:none;font-size:11px;padding:2px}
.cm-drive-source-rm:hover{color:#c0392b}
.cm-drive-add{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.cm-drive-url,.cm-drive-acct{background:var(--surface);border:1px solid var(--line);border-radius:10px;
  padding:8px 10px;font:400 12.5px 'Plus Jakarta Sans',sans-serif;color:var(--ink);outline:none}
.cm-drive-url:focus,.cm-drive-acct:focus{border-color:var(--tone-a)}
.cm-drive-add-btn{background:none;border:1.4px dashed var(--line);border-radius:10px;padding:8px 12px;
  color:var(--tone-a);font:600 12px 'Plus Jakarta Sans',sans-serif;cursor:pointer;text-align:left;margin:0}
.cm-drive-add-btn:hover{border-color:var(--tone-a)}
.cm-drive-browse-btn{background:var(--tone-a);border:none;border-radius:10px;padding:9px 12px;color:#fff;
  font:600 12.5px 'Plus Jakarta Sans',sans-serif;cursor:pointer}
.cm-drive-browse-btn:hover{background:var(--tone-deep)}
.cm-drive-url-row{display:flex;flex-direction:column;gap:6px}
.cm-drive-sync-btn{background:var(--tone-a);border:none;border-radius:10px;padding:9px 12px;color:#fff;
  font:600 12.5px 'Plus Jakarta Sans',sans-serif;cursor:pointer;width:100%}
.cm-drive-sync-btn:hover{background:var(--tone-deep)}
.cm-drive-sync-btn:disabled{opacity:.5;cursor:default}
.cm-drive-msg{margin:6px 0 0;font:500 11.5px 'Plus Jakarta Sans',sans-serif;color:var(--ash);min-height:14px}

.cm-links{margin-top:16px}
.cm-links .label{display:block;font:600 10.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ash);margin-bottom:8px}
.cm-links-empty{font:italic 12.5px 'Fraunces',serif;color:var(--ash)}
.cm-links-list{display:flex;flex-wrap:wrap;gap:7px}
.cm-link-chip{display:inline-flex;align-items:center;gap:6px;border:1px solid color-mix(in srgb, var(--chip-accent, var(--tone-a)) 35%, var(--line));
  border-radius:999px;padding:6px 12px 6px 10px;background:color-mix(in srgb, var(--chip-accent, var(--tone-a)) 8%, var(--surface));
  cursor:pointer;font:500 12.5px 'Plus Jakarta Sans',sans-serif;color:var(--ink);transition:border-color .15s,transform .15s}
.cm-link-chip:hover{border-color:var(--chip-accent, var(--tone-a));transform:translateY(-1px)}
.cm-link-chip .dot{width:7px;height:7px;border-radius:50%;background:var(--chip-accent, var(--tone-a));flex:none}
.swatch{width:22px;height:22px;border-radius:50%;cursor:pointer;border:2px solid transparent;transition:transform .15s,border-color .15s}
.swatch:hover{transform:scale(1.12)}
.swatch.on{border-color:var(--ink)}
.swatch.reset{background:var(--surface);border:1.4px dashed var(--line);display:flex;align-items:center;justify-content:center;color:var(--ash);font-size:11px}
.swatch.disabled{opacity:.3;cursor:default;pointer-events:none}
.swatch.disabled:hover{transform:none}
.swatch-divider{width:1px;height:20px;background:var(--line);margin:0 2px}
.colour-picker-wrap{position:relative;width:22px;height:22px}
.colour-picker-trigger{width:22px;height:22px;border-radius:50%;border:1.4px dashed var(--ash);
  display:flex;align-items:center;justify-content:center;color:var(--ash);cursor:pointer;font-size:13px;
  transition:border-color .15s,color .15s}
.colour-picker-trigger:hover{border-color:var(--tone-a);color:var(--tone-a)}
.colour-picker{position:absolute;inset:0;opacity:0;pointer-events:none;width:22px;height:22px}
.cm-actions{display:flex;align-items:center;gap:8px;margin-top:22px;flex-wrap:wrap}
.cm-save{background:var(--tone-a);color:#fff;border:none;border-radius:999px;padding:10px 22px;
  font:600 12.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.03em;text-transform:uppercase;cursor:pointer}
.cm-btn{background:var(--surface);border:1px solid var(--line);color:var(--ink);border-radius:999px;
  padding:10px 18px;font:600 12.5px 'Plus Jakarta Sans',sans-serif;letter-spacing:.03em;text-transform:uppercase;
  cursor:pointer;transition:border-color .2s}
.cm-btn:hover{border-color:var(--tone-a)}
.cm-btn.danger{color:#c0392b;margin-left:auto}
.cm-btn.danger:hover{border-color:#c0392b}

@media (max-width:760px){
  .canvas-plane{width:1600px;height:2400px}
  /* Mobile deliberately keeps the pre-2026-10-05 behavior: the orb
     stays a citizen of the pannable canvas (not viewport-fixed),
     matching its own tap-to-reveal/hold-to-type interaction and the
     planned speech-first + swipe-to-capture mobile design — see
     project_supertwin_frontend_build_2026_10 memory. Not yet built
     (Mobile ST rebuild is separate, later work); this override exists
     so today's desktop change doesn't silently alter mobile too.
     z-index explicitly lowered back to its original value — the base
     rule bumped to 170 when the orb moved to top-center (sharing space
     with .topbar/.controls on desktop); mobile's orb sits mid-canvas
     and never needs to render above a .scrim/.sheet/.card-modal (100-
     120), which 170 would wrongly do here. */
  #orb-zone{position:absolute;left:800px;top:1200px;transform:translate(-50%,-50%);z-index:45}
  .add-cascade,.field-stack{left:auto;right:0;align-items:flex-end}
  .type-pill{transform-origin:right center}
  .type-chip{align-self:flex-end}
}
@media (max-width:460px){
  :root{--controls-w:250px}
  .topbar{padding-left:16px;padding-right:16px}
  .controls{top:calc(16px + env(safe-area-inset-top,0px));right:calc(16px + env(safe-area-inset-right,0px));gap:8px}
  .toggle button{padding:7px 10px;font-size:11px}
  .pill-btn{padding:8px 12px;font-size:12px}
  .identity-btn{width:34px;height:34px;flex:none}
}
