/* canvas.css — world canvas + cell-node chrome + connections. Z per CONTRACTS §1.6 / style §2.4 */
.canvas-mount { position: relative; overflow: hidden; }
.connections { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; overflow: visible; }
.connections .conn { pointer-events: stroke; cursor: pointer; transition: stroke-width 100ms, opacity 100ms; }
.connections .conn:hover { stroke-width: 3 !important; opacity: 1 !important; }
/* I7 · FLAGS: an edge on a route to a DESTINATION lights brighter than the field — accent, a touch
   thicker, full opacity (CSS overrides the inline presentation stroke/opacity connections.js sets). The
   base .conn transition eases stroke-width/opacity, so a route forming is a calm brighten, never a flash
   (no keyframe — the 3-keyframe motion law is untouched). :hover still wins with its !important. */
.connections .conn-route { stroke: var(--accent); stroke-width: 2.8; opacity: 1; }
.world { position: absolute; top: 0; left: 0; transform-origin: 0 0; will-change: transform; z-index: 5; }
.cell-node { position: absolute; z-index: 5; background: var(--surface); border: 1px solid var(--rule); border-radius: 1px; box-shadow: 0 8px 28px rgba(0,0,0,0.35); }
.cell-node.selected { z-index: 10; border-color: var(--accent); }
/* B6: an applied (nested) modifier shown as a SECOND VIEW node — modifier token. */
.cell-node--mod { border-color: var(--modifier); box-shadow: 0 8px 28px rgba(0,0,0,0.35), inset 0 2px 0 0 var(--modifier); }
.cell-node--mod.selected { border-color: var(--accent); }
/* B6: inferred applies edge (derived from parent_id; not a deletable connection). */
.conn-applies-inferred { pointer-events: none; }
.cell-grip { display: flex; align-items: center; gap: var(--sp-2); padding: 5px 8px; cursor: grab; background: var(--bg-deep); border-bottom: 1px solid var(--rule); user-select: none; }
.cell-grip:active { cursor: grabbing; }
.cg-icon { display: inline-flex; width: 14px; height: 14px; color: var(--ink-dim); }
.cg-icon svg { width: 14px; height: 14px; }
.cg-label { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-dim); }
.cg-focus { margin-left: auto; display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; padding: 0; border: none; background: transparent; color: var(--ink-dim); cursor: pointer; border-radius: 1px; transition: color 120ms ease, background 120ms ease; }
.cg-focus svg { width: 14px; height: 14px; }
.cg-focus:hover { color: var(--accent); background: rgba(212,255,61,0.08); }
/* (B5 canvas host ◈ removed in B6 — the applied-modifier node + applies edge show
   the relationship directly; the outline MODIFIERS ◈ remains.) */
/* B5: child-count badge on a collapsed container node — chartreuse pill, dark text. */
.cc-badge { display: inline-flex; align-items: center; font-family: var(--mono); font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--bg-deep); background: var(--accent); border-radius: 8px; padding: 1px 7px; }
.cell-frame { width: 420px; height: 560px; border: none; background: #fff; display: block; }
.cell-card { width: 240px; padding: var(--sp-3); }
.cell-card .cc-name { font-family: var(--serif); font-style: italic; font-size: 13px; color: var(--ink-mid); }
.cell-card .cc-empty { font-family: var(--serif); font-style: italic; color: var(--ink-faint); }

/* Page cell width driven by viewport mode (prototype-faithful) */
.cell-node[data-type="page"] { transition: width 250ms cubic-bezier(0.2,0.7,0.2,1); }
.cell-node[data-type="page"][data-viewport="desktop"] { width: 480px; }
.cell-node[data-type="page"][data-viewport="tablet"]  { width: 320px; }
.cell-node[data-type="page"][data-viewport="mobile"]  { width: 220px; }
.cell-node[data-type="page"] .cell-frame { width: 100%; }

/* CONN-DRAW — drag-to-connect port, rubber-band, kind popover (AESTHETIC §8: warm-black + chartreuse only) */
.cell-port { position: absolute; top: 50%; right: -7px; transform: translateY(-50%); width: 12px; height: 12px; border-radius: 50%; background: var(--bg-deep); border: 1.5px solid var(--accent); box-shadow: 0 0 0 2px var(--bg-canvas); cursor: crosshair; opacity: 0; pointer-events: none; transition: opacity 120ms ease, transform 120ms ease, box-shadow 120ms ease; z-index: 6; }
.cell-node:hover .cell-port { opacity: 1; pointer-events: auto; }
.cell-port:hover { transform: translateY(-50%) scale(1.25); box-shadow: 0 0 0 3px rgba(212,255,61,0.25); }
.connections .conn-draft { stroke: var(--accent); stroke-width: 1.8; stroke-dasharray: 5 4; opacity: 0.95; pointer-events: none; }
.conn-kind-pop { position: fixed; z-index: 1000; min-width: 172px; background: var(--surface); border: 1px solid var(--rule); border-radius: 2px; box-shadow: 0 12px 40px rgba(0,0,0,0.5); padding: 8px; }
.conn-kind-pop .ckp-title { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-faint); padding: 2px 2px 6px; }
.conn-kind-pop .ckp-row { display: flex; gap: 6px; }
.conn-kind-pop .ckp-chip { flex: 1; padding: 6px 8px; border: 1px solid var(--rule); border-radius: 1px; background: var(--bg-deep); color: var(--ink-mid); font-family: var(--mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer; transition: color 120ms ease, border-color 120ms ease, background 120ms ease; }
.conn-kind-pop .ckp-chip:hover { color: var(--ink); border-color: var(--ink-faint); }
.conn-kind-pop .ckp-chip.is-default { border-color: var(--accent); color: var(--accent); }
.conn-kind-pop .ckp-chip.ckp-data:hover { border-color: var(--accent); color: var(--accent); }
.conn-kind-pop .ckp-chip.ckp-applies:hover { border-color: var(--modifier); color: var(--modifier); }

/* ===== K1 · CANVAS TRIAGE ===== */
/* F-2: a hovered node (and its port) rises ABOVE overlapping siblings so the connect affordance is
   never buried; a selected node sits above the field but below hover (so the port stays reachable). */
.cell-node:hover { z-index: 20; }
.cell-node.inst-selected { z-index: 15; }
/* F-2: ≥24px port hit-zone — the visual dot stays 12px, a transparent ::before extends the target. */
.cell-port::before { content: ""; position: absolute; inset: -8px; border-radius: 50%; }

/* F-3: marquee rubber-band — screen-space rect drawn over the mount while region-selecting. */
.canvas-marquee { position: absolute; z-index: 30; pointer-events: none; border: 1px dashed var(--accent); background: rgba(212,255,61,0.08); border-radius: 1px; }

/* K4 · the cell ACTIONS handle (Dan's gearwheel) — replaces the old fixed top-right meta panel. The ⚙
   sits at the grip's top-right, revealed on hover / when the cell is selected; clicking it opens the
   actions menu (.cell-menu) anchored to the cell. Warm-black + chartreuse (AESTHETIC §8). */
.cg-gear { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; padding: 0; border: none; background: transparent; color: var(--ink-dim); cursor: pointer; border-radius: 1px; opacity: 0; pointer-events: none; transition: color 120ms ease, background 120ms ease, opacity 120ms ease; }
.cg-gear svg { width: 13px; height: 13px; }
.cell-node:not([data-type="page"]) .cg-gear { margin-left: auto; }   /* card grips have no ml:auto element — push the gear right */
.cell-node:hover .cg-gear, .cell-node.inst-selected .cg-gear { opacity: 1; pointer-events: auto; }
.cell-node.inst-selected .cg-gear { color: var(--accent); }          /* on a selected cell the handle reads active */
.cg-gear:hover { color: var(--accent); background: rgba(212,255,61,0.08); }
.cg-gear:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }

/* F-4: the roving-tabindex focus ring (keyboard only — :focus-visible), quieter than the selection
   bracket so a keyboard user sees where they are without a second heavy frame. */
.cell-node:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cell-node:focus { outline: none; }

/* ===== K2 · CITIZEN DISPLAY GRAMMAR ===== */
/* F-15: the meta placard — a hairline footer that finally NAMES the page tile (decode → glance) and
   carries every citizen's structural facts: child-count (≡N) + provenance dots (one per derived-from
   source). NO status dot — cell state lives on the skin (Instrument amendment, §I K2 row). THEON's two
   voices: serif name, mono facts. Kind glyph + KIND label sit in the grip above; together = the grammar
   "kind glyph · name · child-count · provenance dots". Hidden when a bare card carries none of it. */
.cell-meta { display: flex; align-items: center; gap: var(--sp-2); padding: 4px 8px; border-top: 1px solid var(--rule); background: var(--bg-deep); min-width: 0; }
.cell-meta[hidden] { display: none; }
.cmeta-name { font-family: var(--serif); font-style: italic; font-size: 12px; color: var(--ink-mid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 auto; }
.cmeta-name[hidden] { display: none; }
.cmeta-count { font-family: var(--mono); font-size: 9px; letter-spacing: 0.08em; color: var(--ink-dim); flex: none; white-space: nowrap; }
.cmeta-count::before { content: "\2261\00A0"; opacity: 0.7; }                 /* ≡ = "contains N" */
.cmeta-count[hidden] { display: none; }
/* I3 · SYNC: when the shape carries declared ghosts the count reads n/m (live/total) and lifts a touch
   brighter than the plain child-count — a shape in progress, calmly. No bar, no percent: the figure IS it. */
.cmeta-count.cmeta-sync { color: var(--ink-mid); }
.cmeta-prov { display: inline-flex; align-items: center; gap: 3px; flex: none; }
.cmeta-prov[hidden] { display: none; }
/* provenance dots read in the SAME accent as the `data` (derivation) edge — one visual language for lineage */
.cmeta-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--accent); opacity: 0.75; }
.cmeta-more { font-family: var(--mono); font-size: 9px; line-height: 1; color: var(--ink-dim); }

/* §3.6: edge kind-labels — a quiet mono word at each edge midpoint so every connection READS (the
   arrowhead carries direction). Lives inside the camera-transformed <g>, so it tracks its edge. A
   short backing plate keeps it legible over the grid. Quiet at rest; the path's own :hover brightens. */
.connections .conn-label { font-family: var(--mono); font-size: 9px; letter-spacing: 0.14em; fill: var(--ink-dim); text-transform: uppercase; opacity: 0.62; pointer-events: none; }
.connections .conn-label-plate { fill: var(--bg-canvas); opacity: 0.82; pointer-events: none; }

/* ===== K4 · CONTENT CITIZENSHIP ===== */
/* F-7: a page tile lit as the drop target while a rootless content citizen is dragged over it — the
   move-INTO affordance (mirrors the FOCUS outline's fo-drop-into). Chartreuse frame + a faint wash so
   "release here to place onto this page" reads without a label. */
.cell-node--droptarget { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: 0 8px 28px rgba(0,0,0,0.35), inset 0 0 0 2000px rgba(212,255,61,0.06); }

/* F-7: the "place on page…" picker — a warm-black popover (the .conn-kind-pop idiom), shared by the
   meta panel, the shelf, and the FOCUS outline's cross-page move. THEON chrome only. */
.place-menu { position: fixed; z-index: 1000; min-width: 200px; max-width: 280px; background: var(--surface); border: 1px solid var(--rule); border-radius: 2px; box-shadow: 0 12px 40px rgba(0,0,0,0.5); padding: 6px; }
.place-menu .pm-title { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-faint); padding: 3px 6px 6px; }
.place-menu .pm-empty { font-family: var(--serif); font-style: italic; font-size: 12px; color: var(--ink-faint); padding: 4px 6px 6px; }
.place-menu .pm-list { display: flex; flex-direction: column; max-height: 320px; overflow-y: auto; }
.place-menu .pm-item { display: flex; align-items: baseline; gap: var(--sp-2); text-align: left; padding: 6px 8px; border: 0; border-radius: 1px; background: none; cursor: pointer; transition: background 120ms ease; }
.place-menu .pm-item:hover, .place-menu .pm-item:focus-visible { background: var(--bg-deep); outline: none; }
.place-menu .pm-item:focus-visible { box-shadow: inset 0 0 0 1px var(--accent); }
.place-menu .pm-name { font-family: var(--serif); font-style: italic; font-size: 13px; color: var(--ink-mid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.place-menu .pm-slug { font-family: var(--mono); font-size: 9px; letter-spacing: 0.06em; color: var(--ink-faint); white-space: nowrap; }

/* K4 · the cell ACTIONS menu — the gearwheel's popover (Dan's note: spawn BY the cell, a chartreuse
   menu with proper hover). Extends .place-menu chrome; a header names the citizen, the list is the verb
   grammar in the mono machine voice, hover fills warm-black + chartreuse. */
.cell-menu { min-width: 184px; }
.cell-menu .cm-menu-head { display: flex; flex-direction: column; gap: 2px; padding: 3px 8px 7px; margin-bottom: 4px; border-bottom: 1px solid var(--rule); }
.cell-menu .cm-menu-kind { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-dim); }
.cell-menu .cm-menu-name { font-family: var(--serif); font-style: italic; font-size: 13px; color: var(--ink-mid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cell-menu .cm-menu-facts { font-family: var(--mono); font-size: 8px; letter-spacing: 0.06em; color: var(--ink-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cell-menu .cm-menu-list { display: flex; flex-direction: column; }
.cell-menu .cm-menu-item { text-align: left; font-family: var(--mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-dim); background: none; border: 0; border-radius: 1px; padding: 6px 8px; cursor: pointer; transition: color 120ms ease, background 120ms ease; }
.cell-menu .cm-menu-item.is-primary { color: var(--ink-mid); }
.cell-menu .cm-menu-item:hover, .cell-menu .cm-menu-item:focus-visible { color: var(--accent); background: var(--bg-deep); outline: none; }
.cell-menu .cm-menu-item.is-danger { color: var(--ink-faint); }
.cell-menu .cm-menu-item.is-danger:hover, .cell-menu .cm-menu-item.is-danger:focus-visible { color: var(--warn); background: var(--warn-soft); }

/* F-7: the content shelf — a quiet launcher (top-left of the canvas, clear of the meta panel top-right)
   and a left-edge slide-in panel listing rootless content citizens. */
.shelf-launch { position: absolute; top: 12px; left: 12px; z-index: 40; display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; background: var(--surface); border: 1px solid var(--rule); border-radius: 2px; box-shadow: 0 8px 28px rgba(0,0,0,0.4); cursor: pointer; opacity: 0.82; transition: opacity 120ms ease, border-color 120ms ease; }
.shelf-launch:hover, .shelf-launch.is-active { opacity: 1; border-color: var(--ink-faint); }
.shelf-launch.is-active { border-color: var(--accent); }
.shelf-launch-label { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-dim); }
.shelf-launch:hover .shelf-launch-label, .shelf-launch.is-active .shelf-launch-label { color: var(--ink-mid); }
.shelf-count { font-family: var(--mono); font-size: 9px; letter-spacing: 0.04em; color: var(--bg-deep); background: var(--accent); border-radius: 8px; padding: 0 6px; min-width: 14px; text-align: center; }
.shelf-count[hidden] { display: none; }

.shelf { position: absolute; top: 0; left: 0; bottom: 0; z-index: 45; width: 300px; max-width: 84%; display: flex; flex-direction: column; background: var(--surface); border-right: 1px solid var(--rule); box-shadow: 12px 0 40px rgba(0,0,0,0.4); transform: translateX(-100%); transition: transform 220ms cubic-bezier(0.2,0.7,0.2,1); }
.shelf.is-open { transform: translateX(0); }
.shelf[hidden] { display: none; }
.shelf-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid var(--rule); }
.shelf-title { font-family: var(--mono); font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-mid); }
.shelf-close { font-size: 18px; line-height: 1; color: var(--ink-dim); background: none; border: 0; cursor: pointer; padding: 0 2px; transition: color 120ms ease; }
.shelf-close:hover { color: var(--accent); }
.shelf-hint { font-family: var(--serif); font-style: italic; font-size: 12px; color: var(--ink-faint); padding: 8px 12px 4px; }
.shelf-filters { padding: 4px 12px 8px; border-bottom: 1px solid var(--rule); display: flex; flex-direction: column; gap: 5px; }
.shelf-chiprow { display: flex; align-items: center; gap: 6px; }
.shelf-chiplabel { font-family: var(--mono); font-size: 8px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); flex: none; width: 44px; }
.shelf-chips { display: flex; gap: 4px; flex-wrap: wrap; min-width: 0; }
.shelf-chip { font-family: var(--mono); font-size: 9px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-dim); background: var(--bg-deep); border: 1px solid var(--rule); border-radius: 1px; padding: 2px 7px; cursor: pointer; transition: color 120ms ease, border-color 120ms ease; }
.shelf-chip:hover { color: var(--ink-mid); border-color: var(--ink-faint); }
.shelf-chip.is-on { color: var(--accent); border-color: var(--accent); }
/* Campaign (group) chips carry a small ◆ so they read as a lens, distinct from status/kind chips. */
.shelf-chip--group::before { content: "\25C6"; margin-right: 4px; font-size: 7px; opacity: 0.45; vertical-align: 1px; }
.shelf-chip--group.is-on::before { opacity: 1; }
/* CAMPAIGN mode — when a campaign chip is active the head names it (accent + the same ◆ mark), so the
   shelf reads as that campaign's view rather than the default stranded-content list. */
.shelf-title.is-campaign { color: var(--accent); }
.shelf-title.is-campaign::before { content: "\25C6\00A0"; font-size: 8px; opacity: 0.9; }
.shelf-list { flex: 1 1 auto; overflow-y: auto; padding: 6px; }
.shelf-empty { font-family: var(--serif); font-style: italic; font-size: 12px; color: var(--ink-faint); padding: 12px 8px; }
.shelf-item { display: flex; align-items: center; gap: var(--sp-2); padding: 7px 8px; border-radius: 1px; cursor: pointer; transition: background 120ms ease; }
.shelf-item:hover, .shelf-item:focus-visible { background: var(--bg-deep); outline: none; }
.shelf-item:focus-visible { box-shadow: inset 0 0 0 1px var(--accent); }
.shelf-item.is-draft { opacity: 0.82; }
.shelf-glyph { display: inline-flex; width: 14px; height: 14px; color: var(--ink-dim); flex: none; }
.shelf-glyph svg { width: 14px; height: 14px; }
.shelf-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.shelf-name { font-family: var(--serif); font-style: italic; font-size: 13px; color: var(--ink-mid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shelf-name.is-untitled { color: var(--ink-faint); }
.shelf-sub { font-family: var(--mono); font-size: 8px; letter-spacing: 0.08em; color: var(--ink-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shelf-place { font-family: var(--mono); font-size: 8px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-dim); background: none; border: 1px solid transparent; border-radius: 1px; padding: 2px 6px; cursor: pointer; flex: none; opacity: 0; transition: opacity 120ms ease, color 120ms ease, border-color 120ms ease; }
.shelf-item:hover .shelf-place, .shelf-item:focus-within .shelf-place { opacity: 1; }
.shelf-place:hover { color: var(--accent); border-color: var(--accent); }

/* the selection verbs (EDIT/DUPLICATE/ADD TO NAV/GROUP/PLACE/DERIVE/PUBLISH/DELETE) now live in the
   gearwheel .cell-menu popover (K4), styled above — the old fixed .canvas-meta bar is retired. */

/* ===================== K7 · THE ASSEMBLER ===================== */
/* The Tidy (auto-layout) tool, beside the shelf launcher (top-left). Offset clears the launcher + its
   count badge; both are small corner pills. */
.shelf-tidy { left: 106px; }

/* Saved views (campaigns) — the named-filter row atop the shelf; chips reuse .shelf-chip. */
.shelf-views { padding: 6px 12px; border-bottom: 1px solid var(--rule); }
.shelf-view { display: inline-flex; align-items: center; gap: 5px; }
.shelf-view-x { font-size: 11px; line-height: 1; color: var(--ink-faint); cursor: pointer; }
.shelf-view-x:hover { color: var(--accent); }
.shelf-view-add { color: var(--ink-faint); border-style: dashed; }
.shelf-view-input { font-family: var(--mono); font-size: 9px; letter-spacing: 0.04em; color: var(--ink-mid); background: var(--bg-deep); border: 1px solid var(--accent); border-radius: 1px; padding: 2px 6px; width: 118px; }
.shelf-view-input:focus { outline: none; }

/* The group-assign popover — a sibling of .place-menu (K4); highlights the current group + a create input. */
.place-menu .pm-item.is-on { box-shadow: inset 0 0 0 1px var(--accent); }
.group-menu .gm-new { padding: 4px 6px 2px; }
.group-menu .gm-input { width: 100%; box-sizing: border-box; font-family: var(--mono); font-size: 11px; color: var(--ink-mid); background: var(--bg-deep); border: 1px solid var(--rule); border-radius: 1px; padding: 5px 7px; }
.group-menu .gm-input:focus { outline: none; border-color: var(--accent); }
.group-menu .gm-clear { color: var(--ink-faint); font-family: var(--mono); font-size: 9px; letter-spacing: 0.06em; text-transform: uppercase; margin-top: 2px; }
.group-menu .gm-clear:hover { color: var(--accent); }

/* I3 · SYNC — the declare-a-need prompt (the group-menu create-field idiom): a serif line in the register's
   quiet prompt voice that drops a NAMED DRAFT child (a fragment) into a page. Reuses the .place-menu chrome. */
.declare-menu { min-width: 220px; }
.declare-menu .declare-input {
  display: block; box-sizing: border-box; width: calc(100% - 12px); margin: 2px 6px 5px;
  font-family: var(--serif); font-style: italic; font-size: 13px; color: var(--ink);
  background: var(--bg-deep); border: 1px solid var(--rule); border-radius: 1px; padding: 6px 8px;
}
.declare-menu .declare-input::placeholder { color: var(--ink-dim); font-style: italic; }
.declare-menu .declare-input:focus { outline: none; border-color: var(--accent); }

/* ===================== INSTRUMENT I4 · THE HAND ===================== */
/* The K4 shelf re-faced as the Hand: a hand of cards you hold and deliberately PLAY. Register clothing only
   (the accent = --inst-accent, which re-points per organ, §1c). A card lights its leading edge under your
   hand (the pickup cue), a Mine/All toggle keeps the Hand private-by-default, and one field jots a new card. */

/* The card's pickup cue: the leading (accent) edge lights when a card is under your hand — the register's
   "held" read, cheap (one pseudo, one bar), living left of the glyph inside the row's own padding. */
.shelf--hand .shelf-item { position: relative; }
.shelf--hand .shelf-item::before {
  content: ""; position: absolute; left: 0; top: 6px; bottom: 6px; width: 2px; border-radius: 2px;
  background: var(--inst-accent, var(--accent)); opacity: 0; pointer-events: none; transition: opacity 120ms ease;
}
.shelf--hand .shelf-item:hover::before, .shelf--hand .shelf-item:focus-visible::before { opacity: 0.9; }

/* The Mine/All ownership toggle (private-by-default), clustered right of the title with the close button. */
.shelf-head-right { display: inline-flex; align-items: center; gap: 8px; }
.hand-owner { display: inline-flex; align-items: center; border: 1px solid var(--rule); border-radius: 2px; overflow: hidden; }
.hand-owner[hidden] { display: none; }
.hand-owner-opt { font-family: var(--mono); font-size: 8px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-dim); background: var(--bg-deep); border: 0; padding: 3px 7px; cursor: pointer; transition: color 120ms ease, background 120ms ease; }
.hand-owner-opt + .hand-owner-opt { border-left: 1px solid var(--rule); }
.hand-owner-opt:hover { color: var(--ink-mid); }
.hand-owner-opt.is-on { color: var(--bg-deep); background: var(--inst-accent, var(--accent)); }

/* Jot: one field, a card straight into your hand. Serif italic previews the card's own name type. */
.hand-jot-row { padding: 8px 12px; border-bottom: 1px solid var(--rule); }
.hand-jot-row[hidden] { display: none; }
.hand-jot { width: 100%; box-sizing: border-box; font-family: var(--serif); font-style: italic; font-size: 13px; color: var(--ink-mid); background: var(--bg-deep); border: 1px solid var(--rule); border-radius: 2px; padding: 6px 9px; transition: border-color 120ms ease; }
.hand-jot::placeholder { color: var(--ink-faint); font-style: italic; }
.hand-jot:focus { outline: none; border-color: var(--inst-accent, var(--accent)); }

/* ===================== INSTRUMENT I6 · THE SKY ===================== */
/* A second, far way of drawing the same tree (§3.7). Below the zoom threshold (isSky, instrument.js) the
   canvas root gains .inst-sky and the whole board becomes a STARFIELD: every tile + card collapses to a
   point of light sized by kind, the live iframes stop painting (the frame-budget win — a far zoom no
   longer renders N 420×560 documents), threads thin to constant hairlines, and edge labels step aside.
   The SAME signal grammar reads from far for FREE: the skin's opacity classes stay on the node, so a star
   is bright when live, faint when a ghost, dim when quiet; held/selected keep their accent brackets = "you
   are here". Colour-blind-safe like the ground — SIZE carries kind, BRIGHTNESS + BRACKETS carry state, no
   colour carries either. A STATIC mode toggle: no new motion, the 3-keyframe law is untouched. */

/* The point of light IS the node, collapsed to a fixed small box (!important overrides the per-type tile
   widths — a view-mode override) anchored at the tile's origin; the light is the fill at the node's own
   signal opacity. transition:none so crossing the threshold SNAPS (no width morph = off the motion path).
   box-shadow:none drops the tile's drop-shadow so the star reads crisp, not as a dark blob. */
.inst-sky .cell-node {
  width: 11px !important; height: 11px !important;
  border-radius: 2px; background: var(--ink-dim); border-color: var(--ink-faint);
  box-shadow: none; transition: none;
}
/* Sized by KIND (never by colour): a page is the largest, brightest star (the structural anchor); a
   content card is a medium point; an applied modifier is the smallest. */
.inst-sky .cell-node[data-type="page"] { width: 15px !important; height: 15px !important; background: var(--ink-mid); }
.inst-sky .cell-node--mod { width: 8px !important; height: 8px !important; }

/* The live iframes stop painting — THE frame-budget win (§6 QoF 8). Body/meta/port collapse with them. */
.inst-sky .cell-frame,
.inst-sky .cell-body,
.inst-sky .cell-meta,
.inst-sky .cell-port { display: none !important; }

/* The grip stays as the hover target so the PEEK (name · kind · size) is the label-on-hover; its content
   hides (the star shows through). Hover a star → the E7b tooltip names it; nothing labels at rest. */
.inst-sky .cell-grip { position: absolute; inset: 0; padding: 0; background: transparent; border: 0; cursor: pointer; }
.inst-sky .cell-grip > * { display: none; }

/* Threads to hairlines: a constant thin stroke (non-scaling, so it reads at any far zoom instead of
   vanishing sub-pixel), quiet. Edge kind-labels step aside (they would pile up illegibly from far). */
.inst-sky .connections .conn { stroke-width: 0.75px; vector-effect: non-scaling-stroke; opacity: 0.5; }
/* I7: a route stays legible from far — brighter than the field's hairline so the approach to a
   destination still reads in the starfield. AFTER the .conn hairline rule so it wins on equal specificity. */
.inst-sky .connections .conn-route { stroke-width: 2px; opacity: 1; }
.inst-sky .conn-applies-inferred { stroke-width: 0.75px; vector-effect: non-scaling-stroke; opacity: 0.4; }
.inst-sky .conn-label, .inst-sky .conn-label-plate { display: none; }
/* I7: the destination pennant reads from far too — nudge it to sit just above the collapsed star. */
.inst-sky .cell-node.inst-flag::before { left: 3px; top: -14px; }
