/* Theme-aware glass shell. Tokens live on .sh-app; .sh-app.dark overrides them.
   Light board -> light glass chrome over a paper canvas; dark board -> dark glass
   chrome over a dark canvas. Frames are cards; chrome is glass. */

/* @tokens */
/* The token block (spec 28 A2.2, A2.9): the Mac app copies everything between these two markers into its own pages
   at build time (app/scripts/tokens.mjs, rewritten onto :root), so its strip and pages wear exactly this glass. */
.sh-app {
  --ground: #e7e9ef; --dot: #c9cbd5;
  --accent: #0088ff; --accent-ring: rgba(0, 136, 255, .2); --beam: rgba(0, 136, 255, .42); --beam-blur: 6px; --beam-bottom: -13px; --beam-h: 12px; --beam-inset: 12%; --edge-accent: rgba(0, 136, 255, .8); --inner-tint: rgba(0, 136, 255, .13); --tip-bg: #18181b; --tip-ink: #fafafa; --accent-wash: rgba(0, 136, 255, .07);

  --glass: rgba(255, 255, 255, .64);
  --solid: #ffffff;
  --glass-brd: rgba(24, 24, 27, .1);
  --glass-ink: #18181b;
  --glass-ink-2: rgba(24, 24, 27, .66);
  --glass-ink-3: rgba(24, 24, 27, .4);
  --mk-ask: #f08a00; --mk-new: #0077e6;
  --glass-hover: rgba(24, 24, 27, .06);
  --glass-accent: #0077e6;
  --glass-accent-bg: rgba(0, 136, 255, .13);
  --glass-good: #0e6b57;
  --glass-warn: #7a4a00;
  --shadow-glass: inset 0 1px 0 rgba(255, 255, 255, .65), 0 1px 2px rgba(24, 24, 27, .05), 0 4px 12px -6px rgba(24, 24, 27, .12);

  --node-bg: #fff; --node-brd: #dddee5;
  --head-bg: rgba(255, 255, 255, .55);
  --head-sheen: linear-gradient(100deg, rgba(255, 255, 255, .85), rgba(255, 255, 255, .1) 45%, rgba(255, 255, 255, .45));
  --edge-light: linear-gradient(155deg, rgba(255, 255, 255, .95), rgba(255, 255, 255, .2) 30%, rgba(24, 24, 27, .04) 65%, rgba(255, 255, 255, .55));
  --head-ink: #18181b; --head-dim: rgba(24, 24, 27, .4);
  --card-err-ink: #b3261e; --card-err-bg: #fceceb;
  --card-warn-ink: #7a4a00; --card-warn-bg: #fdf3e1;
  --interact: #db35f2; --interact-ring: rgba(219, 53, 242, .16);
  --interact-strong: rgba(219, 53, 242, 1); --interact-soft: rgba(234, 141, 255, .95);
  --interact-deep: rgba(176, 47, 194, .85); --interact-spark: rgba(255, 255, 255, .95);
  /* comments ride the brand blue: interact keeps purple, and a pin, a thread card
     and a selected frame are told apart by shape, not by hue */
  --comment: #0088ff; --comment-ring: rgba(0, 136, 255, .22);
  /* comment-card field surface: APP-scoped on purpose - the card keys to the board
     theme, and node-scoped --node-bg would flip with the frame underneath it */
  --cm-field: #fff;
  --cm-modal-bg: rgba(255, 255, 255, .95);

  --r-node: 10px; --r-panel: 24px; --edge: 10px;
  --blur: blur(20px) saturate(150%);
  --shadow-node: 0 1px 2px rgba(24, 24, 27, .05);   /* tailwind shadow-sm: present, not loud */
  --morph: .26s cubic-bezier(.32, .72, .35, 1);
}
.sh-app.dark {
  --ground: #1b1c23; --dot: #35363f;
  --accent: #0088ff; --accent-ring: rgba(0, 136, 255, .32); --beam: rgba(0, 136, 255, .5); --beam-blur: 3px; --beam-bottom: -13px; --beam-h: 16px; --beam-inset: 20%; --edge-accent: rgba(92, 179, 255, .85); --inner-tint: rgba(92, 179, 255, .16); --tip-bg: #f4f4f5; --tip-ink: #18181b; --accent-wash: rgba(0, 136, 255, .14);

  --glass: rgba(12, 12, 17, .72);
  --solid: #17171b;
  --glass-brd: rgba(255, 255, 255, .16);
  --glass-ink: #f5f5f7;
  --glass-ink-2: rgba(245, 245, 247, .64);
  --glass-ink-3: rgba(245, 245, 247, .4);
  --mk-ask: #ff9f0a; --mk-new: #5cb3ff;
  --glass-hover: rgba(255, 255, 255, .1);
  --glass-accent: #5cb3ff;
  --glass-accent-bg: rgba(0, 136, 255, .28);
  --glass-good: #7fe0c3;
  --glass-warn: #ffd9a0;
  --shadow-glass: inset 0 1px 0 rgba(255, 255, 255, .09), 0 1px 2px rgba(10, 10, 16, .2), 0 4px 14px -8px rgba(10, 10, 16, .4);

  --node-bg: #0f1015; --node-brd: #2c2d38;
  --head-bg: rgba(22, 23, 30, .6);
  --head-sheen: linear-gradient(100deg, rgba(255, 255, 255, .1), rgba(255, 255, 255, .015) 45%, rgba(255, 255, 255, .06));
  --edge-light: linear-gradient(155deg, rgba(255, 255, 255, .3), rgba(255, 255, 255, .05) 30%, rgba(255, 255, 255, .02) 65%, rgba(255, 255, 255, .16));
  --head-ink: #ececf1; --head-dim: rgba(236, 236, 241, .42);
  --card-err-ink: #ff9d94; --card-err-bg: #2a1512;
  --card-warn-ink: #ffd9a0; --card-warn-bg: #2a2113;
  --interact: #ea8dff; --interact-ring: rgba(219, 53, 242, .3);
  --interact-strong: rgba(219, 53, 242, 1); --interact-soft: rgba(234, 141, 255, .95);
  --interact-deep: rgba(203, 48, 224, .8); --interact-spark: rgba(255, 255, 255, .9);
  --comment: #4da6ff; --comment-ring: rgba(77, 166, 255, .34);
  --cm-field: #0f1015;
  --cm-modal-bg: rgba(22, 22, 27, .96);

  --shadow-node: 0 1px 2px rgba(0, 0, 0, .35);   /* shadow-sm, alpha raised to read on dark */
}

@property --ground { syntax: '<color>'; inherits: true; initial-value: #e7e9ef; }
@property --dot { syntax: '<color>'; inherits: true; initial-value: #c9cbd5; }
@property --glass { syntax: '<color>'; inherits: true; initial-value: rgba(255, 255, 255, .64); }
@property --glass-brd { syntax: '<color>'; inherits: true; initial-value: rgba(24, 24, 27, .1); }
@property --glass-ink { syntax: '<color>'; inherits: true; initial-value: #18181b; }
@property --glass-ink-2 { syntax: '<color>'; inherits: true; initial-value: rgba(24, 24, 27, .66); }
@property --glass-ink-3 { syntax: '<color>'; inherits: true; initial-value: rgba(24, 24, 27, .4); }
@property --glass-hover { syntax: '<color>'; inherits: true; initial-value: rgba(24, 24, 27, .06); }
@property --node-bg { syntax: '<color>'; inherits: true; initial-value: #ffffff; }
@property --node-brd { syntax: '<color>'; inherits: true; initial-value: #dddee5; }
@property --head-bg { syntax: '<color>'; inherits: true; initial-value: rgba(255, 255, 255, .55); }
@property --head-ink { syntax: '<color>'; inherits: true; initial-value: #18181b; }
@property --head-dim { syntax: '<color>'; inherits: true; initial-value: rgba(24, 24, 27, .4); }
@property --tip-bg { syntax: '<color>'; inherits: true; initial-value: #18181b; }
@property --tip-ink { syntax: '<color>'; inherits: true; initial-value: #fafafa; }
@property --accent { syntax: '<color>'; inherits: true; initial-value: #0088ff; }
@property --accent-ring { syntax: '<color>'; inherits: true; initial-value: rgba(0, 136, 255, .2); }
@property --beam { syntax: '<color>'; inherits: true; initial-value: rgba(0, 136, 255, .42); }
@property --edge-accent { syntax: '<color>'; inherits: true; initial-value: rgba(0, 136, 255, .8); }
@property --inner-tint { syntax: '<color>'; inherits: true; initial-value: rgba(0, 136, 255, .13); }
@property --accent-wash { syntax: '<color>'; inherits: true; initial-value: rgba(0, 136, 255, .07); }
@property --glass-accent { syntax: '<color>'; inherits: true; initial-value: #0077e6; }
@property --glass-accent-bg { syntax: '<color>'; inherits: true; initial-value: rgba(0, 136, 255, .13); }

/* Reduce Transparency and Increase Contrast (spec 28 A2.9, A2.13): every glass surface opaque - its fill the solid
   one, its border the node's, no blur - in both themes (the dark rule's own specificity, later in the file); and
   with more contrast the dimmer inks take the full one. macOS's settings reach Chrome too. */
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .sh-app, .sh-app.dark { --glass: var(--solid); --glass-brd: var(--node-brd); --blur: none; }
}
@media (prefers-contrast: more) {
  .sh-app, .sh-app.dark { --glass-ink-2: var(--glass-ink); --glass-ink-3: var(--glass-ink); }
}
/* @end-tokens */

/* interact mode: the whole shell shifts to the interactive purple - one token override,
   and every accent-derived surface (mark, sidebar actives, selection bar, beams, rings,
   handles, device chips) follows without knowing the mode exists */
.sh-app.interacting {
  --accent: #db35f2; --accent-ring: rgba(219, 53, 242, .2); --beam: rgba(219, 53, 242, .42);
  --edge-accent: rgba(219, 53, 242, .8); --inner-tint: rgba(219, 53, 242, .13);
  --accent-wash: rgba(219, 53, 242, .07);
  --glass-accent: #b02fc2; --glass-accent-bg: rgba(219, 53, 242, .13);
}
.sh-app.dark.interacting {
  --accent: #db35f2; --accent-ring: rgba(219, 53, 242, .32); --beam: rgba(219, 53, 242, .5);
  --edge-accent: rgba(234, 141, 255, .85); --inner-tint: rgba(234, 141, 255, .16);
  --accent-wash: rgba(219, 53, 242, .14);
  --glass-accent: #ea8dff; --glass-accent-bg: rgba(219, 53, 242, .28);
}

* { box-sizing: border-box }
html, body, #root { height: 100%; margin: 0 }
body { font-family: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow: hidden }
button { font-family: inherit }
button svg { pointer-events: none }   /* event targets stay on the button - pan exclusion depends on it */
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important } }

/* Default app pointer: the marver arrowhead (tilted left, rounded, thick border, soft shadow),
   theme-adaptive - black/white on light, white/dark on dark. Hotspot at its tip (5,2). Overridden by
   the state cursors: grab (space-pan), resize handles, comment-pin / laser-crosshair (set in-frame by
   the bridge), and a normal pointer in interact / prototype mode. */
.sh-app { --sh-cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 26 26'%3E%3Cdefs%3E%3Cfilter id='s' x='-40%' y='-40%' width='180%' height='180%'%3E%3CfeDropShadow dx='0.4' dy='0.9' stdDeviation='0.7' flood-color='%23000000' flood-opacity='0.4'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23s)'%3E%3Cg transform='rotate(-20 6 3)'%3E%3Cpath fill='%23000000' stroke='%23FFFFFF' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round' d='M5.5 3.21V20.8c0 .45.54.67.85.35l4.86-4.86a1 1 0 0 1 .7-.3h6.87a1 1 0 0 0 .7-1.7L6.35 2.85a.5.5 0 0 0-.85.35Z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E") 5 2, default; cursor: var(--sh-cursor) }
.sh-app.dark { --sh-cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 26 26'%3E%3Cdefs%3E%3Cfilter id='s' x='-40%' y='-40%' width='180%' height='180%'%3E%3CfeDropShadow dx='0.4' dy='0.9' stdDeviation='0.7' flood-color='%23000000' flood-opacity='0.4'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23s)'%3E%3Cg transform='rotate(-20 6 3)'%3E%3Cpath fill='%23FFFFFF' stroke='%2318181b' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round' d='M5.5 3.21V20.8c0 .45.54.67.85.35l4.86-4.86a1 1 0 0 1 .7-.3h6.87a1 1 0 0 0 .7-1.7L6.35 2.85a.5.5 0 0 0-.85.35Z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E") 5 2, default }
.sh-app.interacting { cursor: auto }
.sh-app { position: relative; height: 100%; color: var(--glass-ink); outline: none;
  transition: --accent .4s ease, --accent-ring .4s ease, --beam .4s ease,
    --edge-accent .4s ease, --inner-tint .4s ease, --accent-wash .4s ease,
    --glass-accent .4s ease, --glass-accent-bg .4s ease,
    --ground .4s ease, --dot .4s ease, --glass .4s ease, --glass-brd .4s ease,
    --glass-ink .4s ease, --glass-ink-2 .4s ease, --glass-ink-3 .4s ease,
    --glass-hover .4s ease, --node-bg .4s ease, --node-brd .4s ease,
    --head-bg .4s ease, --head-ink .4s ease, --head-dim .4s ease,
    --tip-bg .4s ease, --tip-ink .4s ease }
.sh-canvas { width: 100% !important; height: 100% !important;
  background-color: var(--ground) }
/* world-space dot grid: size/position/alpha driven per-frame from the transform */
.sh-canvas::before { content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(var(--dot) 1px, transparent 1px);
  background-size: var(--grid-size, 20px 20px);
  background-position: var(--grid-pos, 0 0);
  opacity: var(--grid-alpha, 1) }
/* the scroll edge (0.27.2, spec 28 A2.9 v1.8 #8, A3.8 #31): under the Mac app's transparent strip only (App.tsx renders
   it when inset.ts's TOP is 44). One band over the world and under the chrome (z 9; the panels are 10): opaque ground
   through --mv-top, fading out over 16 px more, the dots drawn from the same three grid variables paintGrid writes on
   .sh-app - so nothing of a frame shows under the tabs, and a frame panned up fades out below them while the dots run
   on. The grid's alpha reaches the dots only. The world itself carries no mask (one would add a render surface to every
   frame). */
.sh-edge { position: absolute; left: 0; right: 0; top: 0; height: calc(var(--mv-top, 0px) + 16px); z-index: 9; pointer-events: none;
  background: var(--ground);
  -webkit-mask-image: linear-gradient(#000 0 var(--mv-top, 0px), transparent calc(var(--mv-top, 0px) + 16px));
  mask-image: linear-gradient(#000 0 var(--mv-top, 0px), transparent calc(var(--mv-top, 0px) + 16px)) }
.sh-edge::before { content: ''; position: absolute; inset: 0;
  background-image: radial-gradient(var(--dot) 1px, transparent 1px);
  background-size: var(--grid-size, 20px 20px);
  background-position: var(--grid-pos, 0 0);
  opacity: var(--grid-alpha, 1) }
.sh-content { will-change: auto }
#sh-world { position: relative; width: 1px; height: 1px }
#sh-world.sh-gesturing .sh-live { pointer-events: none }          /* law G-4 */
/* no gesture promotion (a will-change layer on the world was measured harmful: 18-29 dropped frames
   per pan on a 32-frame board against 0-3 without, spec 16) */
/* preset transitions: armed by animateLayout() around device/tidy mutations - nodes ease
   to their new frame on the same 320ms ease-out the camera fit animates with */
#sh-world.sh-preset .sh-node { transition: transform .32s cubic-bezier(.25,.46,.45,.94),
  width .32s cubic-bezier(.25,.46,.45,.94), height .32s cubic-bezier(.25,.46,.45,.94) }
#sh-world.sh-preset .sh-node-body { transition: width .32s cubic-bezier(.25,.46,.45,.94),
  height .32s cubic-bezier(.25,.46,.45,.94) }
/* the live iframe takes its new size at once (ONE reflow per sweep) while the body's box eases to it;
   the frame sleeps again under the new size once it settles */
/* cursor conventions (Figma): arrow everywhere; grab only while space is held */
body.sh-space .sh-canvas { cursor: grab }
body.sh-space.sh-panning .sh-canvas { cursor: grabbing }
body.sh-space .sh-node { pointer-events: none }                   /* space-drag pans from anywhere */

/* frame nodes: theme-aware cards with a glass header strip. Each node re-declares its
   card tokens from its OWN theme, so a dark frame on a light board wears a dark header
   (easier on the eyes than light chrome over a dark page) - and vice versa. */
.sh-node { position: absolute; top: 0; left: 0; border-radius: var(--r-node); background: transparent;
  border: 1px solid var(--node-brd); box-shadow: var(--shadow-node); display: flex; flex-direction: column;
  transition: border-color .3s ease, --node-bg .4s ease, --node-brd .4s ease,
    --head-bg .4s ease, --head-ink .4s ease, --head-dim .4s ease }
.sh-node[data-theme="light"] {
  --node-bg: #fff; --node-brd: #dddee5;
  --head-bg: rgba(255, 255, 255, .55);
  --head-sheen: linear-gradient(100deg, rgba(255, 255, 255, .85), rgba(255, 255, 255, .1) 45%, rgba(255, 255, 255, .45));
  --head-ink: #18181b; --head-dim: rgba(24, 24, 27, .4);
}
.sh-node[data-theme="dark"] {
  --node-bg: #0f1015; --node-brd: #2c2d38;
  --head-bg: rgba(22, 23, 30, .6);
  --head-sheen: linear-gradient(100deg, rgba(255, 255, 255, .1), rgba(255, 255, 255, .015) 45%, rgba(255, 255, 255, .06));
  --head-ink: #ececf1; --head-dim: rgba(236, 236, 241, .42);
}
/* selection + interact indicators live in world space but keep constant SCREEN width
   via --sh-inv (1/zoom): 2 screen px at every zoom level */
.sh-node.sel { border-color: var(--accent);
  outline: calc(2px * var(--sh-inv, 1)) solid var(--accent);
  outline-offset: calc(-1px * var(--sh-inv, 1));
  box-shadow: 0 0 0 calc(4px * var(--sh-inv, 1)) var(--accent-ring), var(--shadow-node) }
.sh-node-head { height: 28px; display: flex; align-items: center; gap: 8px; padding: 0 11px;
  font-size: 11px; color: var(--head-dim);
  border-bottom: 1px solid var(--node-brd); user-select: none;
  border-radius: var(--r-node) var(--r-node) 0 0;
  background-color: var(--head-bg); background-image: var(--head-sheen) }   /* no backdrop-filter: one render surface less per frame */
.sh-node-head .id { font-weight: 600; color: var(--head-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
/* frame icons: every sidebar row leads with one */
.sh-node-head .iicon { flex: none; color: var(--head-dim) }
.sh-panel .sub .iicon { flex: none; margin-right: 7px; opacity: .72 }
/* variant members sit visibly INSIDE their group: the letter chip starts
   exactly on the parent rows' 51px text column (31 pad + 13 icon + 7 gap) */
.sh-panel .sub.vrow { padding-left: 51px }
.sh-node-head .dim { margin-left: auto; color: var(--head-dim); flex: none; font-variant-numeric: tabular-nums }
.sh-node-body { position: relative; background: var(--node-bg); border-radius: 0 0 var(--r-node) var(--r-node); overflow: hidden }
/* no content-visibility on the body: it flips frames between skipped and rendered as they cross the
   viewport during a zoom, and the raster storm that follows left the page unfinished 2.5 s later */
.sh-node iframe { border: 0; display: block }
.sh-overlay { position: absolute; inset: 0; z-index: 2 }   /* above the lean (z1) so drag-by-body works; inherits the app arrow cursor */
.sh-node.interact { border-color: var(--interact);
  outline: calc(2px * var(--sh-inv, 1)) solid var(--interact);
  outline-offset: calc(-1px * var(--sh-inv, 1));
  box-shadow: 0 0 0 calc(4px * var(--sh-inv, 1)) var(--interact-ring), var(--shadow-node) }

.sh-handle { position: absolute; background: var(--node-bg); border: 1.5px solid var(--accent); border-radius: 4px; z-index: 3;
  transform: scale(var(--sh-inv, 1)) }   /* constant screen size; hit target grows as you zoom out */
.sh-handle.e { right: -5px; top: 50%; width: 9px; height: 26px; margin-top: -13px; cursor: ew-resize }
.sh-handle.s { bottom: -5px; left: 50%; width: 26px; height: 9px; margin-left: -13px; cursor: ns-resize }
.sh-handle.se { right: -5px; bottom: -5px; width: 11px; height: 11px; cursor: nwse-resize }

/* glass surfaces share one recipe; chrome text is never selectable (shift-click = multi-select) */
.sh-ctx, .sh-panel, .sh-fab, .sh-pill, .sh-pill-fab, .sh-menu, .sh-banner, .sh-toast, .sh-update {
  background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-brd); box-shadow: var(--shadow-glass); position: relative;
  user-select: none; -webkit-user-select: none }

/* edge light: a 1px gradient ring over the border, so glass reads as glass even
   with nothing behind it to blur (masked-border technique) */
.sh-ctx::after, .sh-panel::after, .sh-fab::after, .sh-pill::after, .sh-pill-fab::after,
.sh-menu::after, .sh-banner::after, .sh-toast::after, .sh-update::after, .sh-node::after {
  content: ''; position: absolute; inset: -1px; padding: 1px; border-radius: inherit;
  background: var(--edge-light); pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude }
.sh-node.sel::after { display: none }   /* the accent ring owns the selected edge */
@property --sh-rot { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
/* one orbiting light, two intensities: a faint shimmer riding ON the solid border
   (::before, low opacity over the still outline) and the clear glow just outside
   (::after, lightly blurred, sharp glints). Same duration = perfectly in sync. */
.sh-node.interact::before, .sh-node.interact::after {
  content: ''; position: absolute; border-radius: inherit; pointer-events: none;
  background: conic-gradient(from var(--sh-rot),
    var(--interact-strong) 0deg,
    var(--interact-strong) 105deg,
    var(--interact-spark) 135deg,
    var(--interact-strong) 165deg,
    var(--interact-strong) 285deg,
    var(--interact-spark) 315deg,
    var(--interact-strong) 345deg,
    var(--interact-strong) 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  animation: sh-orbit 4.2s linear infinite;
}
.sh-node.interact::before {
  inset: calc(-2.5px * var(--sh-inv, 1));
  padding: calc(2.5px * var(--sh-inv, 1));
  border-radius: calc(var(--r-node) + 2px * var(--sh-inv, 1));
  opacity: .6;
}
.sh-node.interact::after {
  inset: calc(-9px * var(--sh-inv, 1));
  padding: calc(5px * var(--sh-inv, 1));
  border-radius: calc(var(--r-node) + 8px * var(--sh-inv, 1));
  filter: blur(calc(2px * var(--sh-inv, 1)));
  opacity: .95;
}
@keyframes sh-orbit { to { --sh-rot: 360deg } }
@media (prefers-reduced-motion: reduce) {
  .sh-node.interact::before, .sh-node.interact::after,
  .sh-node.working::before { animation: none } }

/* Live Jam "working": the SELECTED state's exact geometry - crisp border + 2px screen-px
   outline + 4px ring, edge-light off - in MARVER BLUE, composed of three
   layers: the border shimmer (::before orbit), the periodic content WAVE (.sh-work-wave), and the
   shimmer MATRIX of tiny marks on the left flank (.sh-work-ind). Every animated layer is phased by
   --mv-w0 (negative ms since THIS frame's job started), so parallel frames never pulse in sync.
   When a human is actually IN the frame, interact's magenta treatment wins. */
.sh-node.working { --work: var(--mv-blue); --work-ring: rgba(0, 136, 255, .2) }
.sh-app.dark .sh-node.working { --work: #4db1ff; --work-ring: rgba(0, 136, 255, .3) }
.sh-node.working:not(.interact) { border-color: var(--work);
  outline: calc(2px * var(--sh-inv, 1)) solid var(--work);
  outline-offset: calc(-1px * var(--sh-inv, 1));
  box-shadow: 0 0 0 calc(4px * var(--sh-inv, 1)) var(--work-ring), var(--shadow-node) }
.sh-node.working:not(.interact)::after { display: none }   /* the blue geometry owns the edge, like .sel */
.sh-node.working:not(.interact)::before {
  content: ''; position: absolute; pointer-events: none;
  inset: calc(-2.5px * var(--sh-inv, 1));
  padding: calc(2.5px * var(--sh-inv, 1));
  border-radius: calc(var(--r-node) + 2px * var(--sh-inv, 1));
  background: conic-gradient(from var(--sh-rot),
    var(--work) 0deg,
    var(--work) 105deg,
    rgba(255, 255, 255, .95) 135deg,
    var(--work) 165deg,
    var(--work) 285deg,
    rgba(255, 255, 255, .95) 315deg,
    var(--work) 345deg,
    var(--work) 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  opacity: .6;
  animation: sh-orbit 4.2s linear infinite;
  animation-delay: var(--mv-w0, 0s) }

/* THE WAVE (Option A: content sweep). One 36s cycle holds five ~1.7s sweeps - dense right after
   the trigger (0s, 5s, 10s), then spaced (19s, 29s) - so a fresh job announces itself and a long
   one keeps a calmer heartbeat. Jumps between sweeps happen at opacity 0 (invisible). */
.sh-work-wave { position: absolute; inset: 0; overflow: hidden; border-radius: inherit;
  pointer-events: none; z-index: 4 }
.sh-work-wave::before { content: ''; position: absolute; left: 0; right: 0; top: -55%; height: 55%;
  opacity: 0;
  background: linear-gradient(180deg,
    rgba(0, 136, 255, 0) 0%, rgba(0, 136, 255, .07) 30%, rgba(0, 136, 255, .16) 52%,
    rgba(0, 136, 255, .07) 74%, rgba(0, 136, 255, 0) 100%);
  animation: sh-work-wave 36s linear infinite;
  animation-delay: var(--mv-w0, 0s) }
@keyframes sh-work-wave {
  0%     { transform: translateY(0); opacity: 0 }
  0.4%   { opacity: 1 }
  3.9%   { opacity: 1 }
  4.7%   { transform: translateY(282%); opacity: 0 }
  13.8%  { transform: translateY(0); opacity: 0 }
  14.2%  { opacity: 1 }
  17.7%  { opacity: 1 }
  18.5%  { transform: translateY(282%); opacity: 0 }
  27.7%  { transform: translateY(0); opacity: 0 }
  28.1%  { opacity: 1 }
  31.6%  { opacity: 1 }
  32.4%  { transform: translateY(282%); opacity: 0 }
  52.7%  { transform: translateY(0); opacity: 0 }
  53.1%  { opacity: 1 }
  56.6%  { opacity: 1 }
  57.4%  { transform: translateY(282%); opacity: 0 }
  80.5%  { transform: translateY(0); opacity: 0 }
  80.9%  { opacity: 1 }
  84.4%  { opacity: 1 }
  85.2%  { transform: translateY(282%); opacity: 0 }
  100%   { transform: translateY(282%); opacity: 0 }
}

/* THE SHIMMER MATRIX: 3 x 6 tiny marver marks on the left flank, top-aligned (the vbadge lane).
   Screen-constant via --sh-inv (tight at every zoom); each mark twinkles on its own scattered
   beat, phased per frame by --mv-w0. */
/* CLAMPED scaling (the vbadge pattern): screen-constant ~4px marks in the working zoom band,
   but floored at 3 world px (deep zoom-in: grows slightly on screen instead of vanishing) and
   capped at 13 world px (far zoom-out: shrinks with the canvas instead of dominating the frame
   and bleeding onto the left neighbor). No transform scale - the sizes ARE the clamp. */
.sh-work-ind { position: absolute; top: 0;
  --shm: clamp(3px, calc(4px * var(--sh-inv, 1)), 13px);
  --shg: clamp(1px, calc(1.5px * var(--sh-inv, 1)), 4px);
  right: calc(100% + clamp(6px, calc(10px * var(--sh-inv, 1)), 26px));
  display: grid; grid-template-columns: repeat(2, var(--shm)); gap: var(--shg);
  pointer-events: none; z-index: 5 }
/* a variant badge (A / B / C + name) owns the top of the left flank - the shimmer sits below it.
   The offset mirrors the badge's own zoom clamps (letter 40px-120px + label), so it tracks the
   badge as it grows and shrinks across the zoom range. */
.sh-work-ind.below-vbadge { top: min(clamp(64px, calc(32px * var(--sh-inv, 1)), 170px), calc(64px * var(--sh-inv, 1))) }
.sh-work-ind svg { display: block; width: var(--shm); height: var(--shm); color: var(--work, var(--mv-blue));
  opacity: .12; animation: sh-work-shim .95s ease-in-out infinite }
@keyframes sh-work-shim { 0%, 100% { opacity: .12; transform: scale(.75) } 35% { opacity: 1; transform: scale(1.15) } }
@media (prefers-reduced-motion: reduce) {
  .sh-work-wave::before, .sh-work-ind svg { animation: none } }

/* selection toolbar: screen-space overlay, constant size at any zoom */
.sh-ctx { position: absolute; display: flex; align-items: center; gap: 1px;
  border-radius: 999px; padding: 4px; z-index: 9; white-space: nowrap;
  /* a teeny inner glow hugging the bottom edge - 8px tall, cannot climb into the body */
  background-image: radial-gradient(46% 8px at 50% calc(100% + 1px), var(--inner-tint), transparent 80%) }
/* the accent lives ON the border line, not in the body: layered into the masked 1px
   edge ring, so the bottom border glows blue at center and fades along the arc -
   the bar's surface stays untouched */
.sh-ctx::after {
  background:
    radial-gradient(52% 16px at 50% 100%, var(--edge-accent), transparent 75%),
    var(--edge-light) }
/* connection glow: a soft accent beam under the middle ~60% of the bar - deepest and
   tallest at the center, fading to nothing at the edges - ties the bar to its frame */
.sh-ctx::before { content: ''; position: absolute; left: var(--beam-inset); right: var(--beam-inset);
  bottom: var(--beam-bottom); height: var(--beam-h);
  background: radial-gradient(50% 100% at 50% 0%, var(--beam), transparent 70%);
  filter: blur(var(--beam-blur, 4px)); pointer-events: none; z-index: -1 }
.sh-ctx button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 28px;
  font: 600 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2); background: none; border: 0;
  padding: 0 11px; border-radius: 999px; cursor: pointer }
.sh-ctx button.icon { min-width: 28px; width: 30px; padding: 0 }
.sh-ctx .cnt { font: 600 11px -apple-system, system-ui, sans-serif; font-variant-numeric: tabular-nums; color: var(--glass-ink-2); background: var(--glass-hover);
  border-radius: 999px; min-width: 22px; height: 22px; display: inline-flex; align-items: center;
  justify-content: center; padding: 0 6px; margin: 0 2px 0 3px }
.sh-ctx button.on { background: var(--glass-accent-bg); color: var(--glass-accent) }
.sh-ctx button:hover:not(.on) { background: var(--glass-hover); color: var(--glass-ink) }
/* multi-select / no-op states read as quiet, not broken */
.sh-ctx button:disabled { cursor: default; opacity: .45 }
.sh-ctx button:disabled:hover { background: none; color: var(--glass-ink-2) }
/* copy-as-image while the headless render runs (1-4s): a slow breathe on the icon */
.sh-ctx button.busy { opacity: 1; color: var(--glass-accent); animation: sh-ctx-breathe 1.1s ease-in-out infinite }
@keyframes sh-ctx-breathe { 0%, 100% { opacity: .35 } 50% { opacity: 1 } }
.sh-ctx .sep { width: 1px; height: 14px; background: var(--glass-brd); margin: 0 3px }

/* error / missing cards (inside the frame body) */
.sh-card { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; gap: 6px;
  padding: 14px; font-size: 12px; background: var(--node-bg) }
.sh-card.err { color: var(--card-err-ink); background: var(--card-err-bg) }
.sh-card.warn { color: var(--card-warn-ink); background: var(--card-warn-bg) }
.sh-card b { font-size: 12px }
.sh-card .msg { white-space: pre-wrap; overflow: auto }
.sh-card .dim { opacity: .55 }
.sh-card .row { display: flex; gap: 6px; margin-top: auto }
.sh-card button { display: inline-flex; align-items: center; gap: 5px; font: 600 11px -apple-system, system-ui, sans-serif;
  border: 1px solid currentColor; background: transparent; color: inherit; border-radius: 999px;
  padding: 4px 10px; cursor: pointer }

/* still-loading pill: a slow (not failed) frame after its one auto-retry. Non-covering, sits above
   the drag overlay (z2) so its reload button is clickable, and stays out of the frame's content. */
.sh-loading { position: absolute; left: 8px; bottom: 8px; z-index: 6; display: inline-flex; align-items: center;
  gap: 8px; padding: 4px 4px 4px 10px; border-radius: 999px; font: 500 11px -apple-system, system-ui, sans-serif;
  color: var(--card-warn-ink); background: var(--card-warn-bg); box-shadow: 0 1px 4px rgba(0, 0, 0, .16) }
.sh-loading button { display: inline-flex; align-items: center; gap: 4px; font: 600 11px -apple-system, system-ui, sans-serif;
  border: 1px solid currentColor; background: transparent; color: inherit; border-radius: 999px; padding: 3px 9px; cursor: pointer }

/* shared icon button (glass surfaces) */
.sh-ibtn { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 999px;
  border: 0; background: none; color: var(--glass-ink-3); cursor: pointer }
.sh-ibtn:hover { background: var(--glass-hover); color: var(--glass-ink) }

/* floating glass panel; collapses into the fab with a scale-fade morph */
.sh-panel { position: absolute; left: var(--edge); top: calc(var(--mv-top, 0px) + var(--edge)); width: 236px;
  max-height: calc(100% - 2 * var(--edge) - var(--mv-top, 0px)); z-index: 10;
  border-radius: var(--r-panel); padding: 10px; display: flex; flex-direction: column;
  font-size: 13px; color: var(--glass-ink);
  transform-origin: 22px 22px; transition: transform var(--morph), opacity .2s ease }
.sh-panel.closed { transform: scale(.16); opacity: 0; pointer-events: none }
.sh-panel-top { display: flex; align-items: center; gap: 8px; padding: 2px 2px 8px 8px }
.sh-panel-top .mark-link { flex: none; display: flex; border-radius: 6px; outline-offset: 2px; transition: opacity .15s ease }
.sh-panel-top .mark-link:hover { opacity: .72 }
.sh-panel-top .mark { flex: none; color: var(--accent); display: block }
.sh-panel-top .name { margin-right: auto; min-width: 0; font-weight: 700; font-size: 15px; letter-spacing: -0.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.sh-panel-scroll { overflow-y: auto; min-height: 0; padding-bottom: 2px; scrollbar-width: thin;
  scrollbar-color: var(--glass-ink-3) transparent }
/* Sidebar list system (macOS-sidebar conventions): every row is 28px tall with an
   8px radius and a fixed 16px icon column, so all labels share one vertical line.
   Hierarchy is carried by section labels + indent + ink - never bold-on-bold:
   boards and scene folders read at 500/primary, frames at 400/secondary one indent
   in, counts and idle icons tertiary. Actives use the accent wash + accent ink. */
.sh-panel .hd { font: 600 11px -apple-system, system-ui, sans-serif; letter-spacing: .02em;
  color: var(--glass-ink-3); margin: 16px 10px 5px }
.sh-panel .hd:first-child { margin-top: 2px }
.sh-panel .it { width: 100%; height: 28px; padding: 0 8px; border-radius: 8px; color: var(--glass-ink);
  font: 500 13px -apple-system, system-ui, sans-serif; background: none; border: 0; cursor: pointer; text-align: left;
  display: flex; align-items: center; gap: 7px; margin-bottom: 1px }
/* a scene holding a selected frame keeps a half-strength wash (Xcode-style ancestor
   highlight) so the selection's home stays visible even with the group collapsed;
   same specificity as :hover but declared first, so hover still wins under pointer */
.sh-panel .it.held { background: color-mix(in srgb, var(--glass-hover) 55%, transparent) }
.sh-panel .it:hover { background: var(--glass-hover) }
.sh-panel .it .tw { color: var(--glass-ink-3); flex: none; margin: 0 2.5px; transition: transform .15s ease }
.sh-panel .it span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.sh-panel .it small { color: var(--glass-ink-3); font: 500 11px -apple-system, system-ui, sans-serif; font-variant-numeric: tabular-nums }
/* board rows: places, not folders - icon idles tertiary, lights accent when active */
.sh-panel .it.board svg { color: var(--glass-ink-3); flex: none; margin: 0 1px; transition: color .2s ease }
.sh-panel .it.board.cur { background: var(--accent-wash); color: var(--glass-accent); font-weight: 600 }
.sh-panel .it.board.cur svg { color: var(--glass-accent) }
/* spec 20: a feature or project board's status ring sits at the row's end, in its own colours -
   never the accent of the current row - with its evidence in the tooltip */
.sh-panel .it.board .st { flex: none; display: inline-flex; margin-left: auto; font-style: normal }
.sh-panel .it.board .st-error { width: 14px; height: 14px; border-radius: 7px; justify-content: center; align-items: center; font: 700 10px/1 system-ui; color: #fff; background: #ff3b30 }
/* the settled statuses' fills, one value per theme: done is the content palette's green (Apple's
   systemGreen); archived is Apple's brown - its increased-contrast value on light, its default on
   dark, where the increased-contrast one turns peach - so it reads as the same brown box in both */
.sh-app { --status-done: #34c759; --status-archived: #956d51; --status-building: #0088ff; --live-glint: #b3dbff }
.sh-app.dark { --status-done: #30d158; --status-archived: #b78a66; --status-building: #0088ff; --live-glint: #d6ecff }
/* the live signal (spec 20): an agent working on what a sidebar row holds - its icon accent blue, a
   highlight sweeping across it. The glint is the icon again, masked to a band that travels left to right */
.sh-panel .it .sh-live-ic { position: relative; display: inline-flex; flex: none }
.sh-panel .it .sh-live-ic[data-live-icon] svg { color: var(--status-building) }   /* Marver's blue, whatever the mode */
.sh-panel .it .sh-live-ic .glint { position: absolute; inset: 0; display: inline-flex; pointer-events: none;
  -webkit-mask-image: linear-gradient(100deg, transparent 38%, #000 50%, transparent 62%); mask-image: linear-gradient(100deg, transparent 38%, #000 50%, transparent 62%);
  -webkit-mask-size: 300% 100%; mask-size: 300% 100%; animation: sh-live-glint 1.8s ease-in-out infinite }
.sh-panel .it .sh-live-ic[data-live-icon] .glint svg { color: var(--live-glint) }
@keyframes sh-live-glint { from { -webkit-mask-position: 100% 0; mask-position: 100% 0 } to { -webkit-mask-position: 0 0; mask-position: 0 0 } }
@media (prefers-reduced-motion: reduce) { .sh-panel .it .sh-live-ic .glint { display: none } }
.sh-panel .it.board .st svg, .sh-panel .it.board.cur .st svg { color: inherit; margin: 0 }
/* drag-to-reorder: a grab cursor, the lifted row dims, and a 2px accent rule marks the
   drop seam above or below the hovered row */
/* a board row is click-to-switch first (pointer on hover); the grabbing hand appears the
   moment it is pressed (:active) and - because reorder is pointer-driven, not native DnD -
   the body class below holds that grabbing cursor for the WHOLE drag, everywhere the pointer
   goes, instead of the OS reverting it to an arrow. The base .it already sets cursor: pointer. */
.sh-panel .it.board[data-reorderable]:active { cursor: grabbing }
.sh-panel .it.board.dragging { opacity: .4 }
.sh-board-dragging, .sh-board-dragging * { cursor: grabbing !important }
.sh-board-dragging { user-select: none }
/* drop seam: a rounded BRAND-BLUE bar overlaid in the gap at the landing edge. Absolutely
   positioned (::after), so it marks the seam without shifting a single row. Fixed brand blue
   #0088ff - never the interact-mode purple that --glass-accent shifts to. */
.sh-panel .it.board.drop-before, .sh-panel .it.board.drop-after { position: relative }
.sh-panel .it.board.drop-before::after, .sh-panel .it.board.drop-after::after {
  content: ''; position: absolute; left: var(--seam-left, 6px); right: 6px; height: 3px; border-radius: 3px;
  background: #0088ff; pointer-events: none }
.sh-panel .it.board.drop-before::after { top: -1px }
.sh-panel .it.board.drop-after::after { bottom: -1px }
/* inline rename: the input wears the row's own type so the swap is seamless */
.sh-panel .it.board.editing, .sh-panel .it.folder.editing { cursor: default }
.sh-panel .it.editing input { flex: 1; min-width: 0; padding: 0; border: 0; outline: 0; background: none;
  color: var(--glass-ink); font: inherit }
.sh-panel .it.editing input::placeholder { color: var(--glass-ink-3) }
/* folders: two levels, same row grammar as boards (idle icon tertiary, count tertiary). A folder
   holding the current board wears the ancestor wash so the active board's home survives a
   collapse; what it holds indents one step - a sub-folder's header one step, its boards two. Folder rows share the board seam rules; dropping INTO a
   folder lights the whole row (wash + brand-blue ring) instead of a seam. */
.sh-panel .it.folder svg { color: var(--glass-ink-3); flex: none; margin: 0 1px; transition: color .2s ease }
.sh-panel .it.folder[data-reorderable]:active { cursor: grabbing }
.sh-panel .it.folder.dragging { opacity: .4 }
.sh-panel .it.folder.drop-before, .sh-panel .it.folder.drop-after { position: relative }
.sh-panel .it.folder.drop-before::after, .sh-panel .it.folder.drop-after::after {
  content: ''; position: absolute; left: var(--seam-left, 6px); right: 6px; height: 3px; border-radius: 3px;
  background: #0088ff; pointer-events: none }
.sh-panel .it.folder.drop-before::after { top: -1px }
.sh-panel .it.folder.drop-after::after { bottom: -1px }
.sh-panel .it.folder.drop-into { background: var(--accent-wash); box-shadow: inset 0 0 0 1.5px #0088ff }
.sh-panel .it.folder.drop-into svg { color: #0088ff }
/* 8px row padding + INDENT (22px, board-tree.ts) per level: a nested row's icon starts exactly
   where its folder's name starts, at every level */
.sh-panel .it.board.in-folder, .sh-panel .it.folder.in-folder { padding-left: 30px }
.sh-panel .it.board.in-sub { padding-left: 52px }
.sh-panel .it.board.draft { cursor: default; opacity: .6 }
/* seams are indented with the list they land in (--seam-left, set on the row that draws them),
   so "inside", "inside the sub-folder" and "at the root" never draw alike; an open EMPTY folder
   draws that indented seam under its own header (drop-in) */
.sh-panel .it.folder.drop-in { position: relative }
.sh-panel .it.folder.drop-in::after { content: ''; position: absolute; left: var(--seam-left, 30px); right: 6px; bottom: -1px; height: 3px; border-radius: 3px;
  background: #0088ff; pointer-events: none }
/* the Boards header carries a quiet folder-plus: tertiary, shows on hover of the header row */
.sh-panel .sh-boards .hd { display: flex; align-items: center; margin-right: 6px }
.sh-panel .sh-boards .hd span { flex: 1 }
/* a bare glyph, no button chrome (padding would shrink it): tertiary, pointer, full ink on hover */
.sh-panel .sh-hd-add { flex: none; color: var(--glass-ink-3); cursor: pointer; outline: none; border-radius: 4px;
  opacity: 0; transition: opacity .15s ease, color .15s ease }
.sh-panel .sh-boards .hd:hover .sh-hd-add, .sh-panel .sh-hd-add:focus-visible { opacity: 1 }
.sh-panel .sh-hd-add:hover { color: var(--glass-ink) }
.sh-panel .sh-hd-add:focus-visible { box-shadow: 0 0 0 2px var(--accent) }
/* frame rows: one indent in (aligned to the label line), quieter ink */
.sh-panel .sub { display: flex; align-items: center; height: 28px; padding: 0 8px 0 31px; margin-bottom: 1px;
  color: var(--glass-ink-2); font-size: 13px; font-weight: 400; border-radius: 8px; cursor: pointer }
.sh-panel .sub:hover { background: var(--glass-hover); color: var(--glass-ink) }
.sh-panel .sub.on { background: var(--accent-wash); color: var(--glass-accent); font-weight: 500 }
.sh-panel .sub.dim { color: var(--glass-ink-3); cursor: default; line-height: 1.4; height: auto; padding-top: 4px; padding-bottom: 4px }
.sh-panel .sub.dim:hover { background: none; color: var(--glass-ink-3) }

/* collapsed panel: a round glass button; morphs against the panel */
.sh-fab { position: absolute; left: var(--edge); top: calc(var(--mv-top, 0px) + var(--edge)); z-index: 11; width: 44px; height: 44px;
  display: grid; place-items: center; border-radius: 999px;
  color: var(--glass-ink-2); cursor: pointer;
  transition: transform var(--morph), opacity .2s ease }
.sh-fab:hover { color: var(--glass-ink); background: var(--glass-hover) }
.sh-fab.hidden { transform: scale(.5); opacity: 0; pointer-events: none }

/* pill nav */
/* uniform 5px inset on every side: 34px buttons + 2*5px = 44px, same as the fab */
.sh-pill { position: absolute; right: var(--edge); top: calc(var(--mv-top, 0px) + var(--edge)); z-index: 10; display: flex; align-items: center; gap: 1px;
  border-radius: 999px; padding: 5px;
  transform-origin: calc(100% - 22px) 22px; transition: transform var(--morph), opacity .2s ease }
.sh-pill.closed { transform: scale(.16); opacity: 0; pointer-events: none }
/* the pill's expand chip - the sidebar fab, mirrored top-right: same glass (shared
   surface rule above), same morph, the bar shrinking into the chip's spot */
.sh-pill-fab { position: absolute; right: var(--edge); top: calc(var(--mv-top, 0px) + var(--edge)); z-index: 11; width: 44px; height: 44px;
  display: grid; place-items: center; border-radius: 999px;
  color: var(--glass-ink-2); cursor: pointer;
  transition: transform var(--morph), opacity .2s ease }
.sh-pill-fab:hover { color: var(--glass-ink); background: var(--glass-hover) }
.sh-pill-fab.hidden { transform: scale(.5); opacity: 0; pointer-events: none }
.sh-pill-btn { display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 34px;
  min-width: 34px; font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2); background: none; border: 0;
  padding: 0 10px; border-radius: 999px; cursor: pointer; white-space: nowrap }
.sh-pill-btn:hover { background: var(--glass-hover); color: var(--glass-ink) }
.sh-pill-btn.pct { font-variant-numeric: tabular-nums; min-width: 46px }
.sh-pill-btn.off { color: var(--glass-ink-3); cursor: default }
.sh-pill-btn.off:hover { background: none; color: var(--glass-ink-3) }
.sh-pill-btn.on { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent) }
.sh-pill-btn.on:hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent) }
.sh-pill .sep { width: 1px; height: 16px; background: var(--glass-brd); margin: 0 3px }

/* dropdown menu (theme) - portaled to .sh-app (its own backdrop root), left-aligned to its trigger */
.sh-theme { position: relative }
/* z above the play backdrop (.sh-play is z-30): a dropdown portals to .sh-app, so in the
   prototype it must clear the full-window overlay or it renders behind it, invisible */
.sh-menu { position: absolute; min-width: 136px; z-index: 40;
  border-radius: 16px; padding: 5px; display: flex; flex-direction: column;
  transform-origin: top left; animation: sh-pop .14s ease }
@keyframes sh-pop { from { opacity: 0; transform: scale(.95) translateY(-4px) } }
.sh-menu button { display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px;
  font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink); background: none; border: 0; border-radius: 12px;
  cursor: pointer; text-align: left }
.sh-menu button:hover { background: var(--glass-hover) }
.sh-menu button span { flex: 1; text-transform: capitalize }
/* the sidebar right-click menu keeps its labels verbatim (they match the toolbar exactly);
   it scrolls rather than overflowing the window when the folder list grows long */
.sh-ctxmenu { max-height: calc(100vh - 16px - var(--mv-top, 0px)); max-width: 240px; overflow-y: auto; scrollbar-width: thin }
.sh-ctxmenu button { flex: none; max-width: 100% }
.sh-ctxmenu button span { text-transform: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0 }
.sh-menu .chk { color: var(--glass-accent) }
.sh-menu kbd { font: 500 10.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); background: none; border: 0 }
.sh-menu .div { height: 1px; background: var(--glass-brd); margin: 4px 6px }
/* the board status picker (StatusPicker.tsx): opens in place of the right-click menu - a filter,
   what the evidence says now, the statuses a person may set, numbered, and a line on the rest */
.sh-ctxpanel { width: 248px; max-width: 248px }
.sh-status-picker { display: flex; flex-direction: column }
.sh-status-picker .sp-input { height: 32px; margin: 0 0 4px; padding: 0 10px; border: 0; border-bottom: 1px solid var(--glass-brd);
  border-radius: 0; background: none; color: var(--glass-ink); font: 500 12.5px -apple-system, system-ui, sans-serif; outline: 0 }
.sh-status-picker .sp-input::placeholder { color: var(--glass-ink-3) }
.sh-status-picker .sp-now { display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px; margin-bottom: 2px;
  font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.sh-status-picker .sp-now small { margin-left: auto; color: var(--glass-ink-3); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px }
.sh-status-picker .sp-list { display: flex; flex-direction: column }
.sh-status-picker .sp-list button { width: 100% }
.sh-status-picker .sp-list button.hi { background: var(--glass-hover) }
.sh-status-picker .sp-list button span { text-transform: none }
.sh-status-picker .sp-chk { color: var(--glass-ink); flex: none }
.sh-status-picker .sp-head { display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px; font: 600 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.sh-status-picker .sp-empty { padding: 8px 10px; color: var(--glass-ink-3); font: 500 12px -apple-system, system-ui, sans-serif }
.sh-status-picker .sp-foot { border-top: 1px solid var(--glass-brd); margin-top: 4px; padding: 7px 10px 3px; color: var(--glass-ink-3);
  font: 500 11px/1.35 -apple-system, system-ui, sans-serif }
.sh-status-picker[data-status-picker="reason"] .sp-input { border: 1px solid var(--glass-brd); border-radius: 9px; margin: 2px 6px 0; height: 30px }

/* shadcn-style tooltip: contrast-flipped solid, zoom-fade in */
.sh-tip { position: absolute; z-index: 400; pointer-events: none; padding: 5px 10px; border-radius: 8px;   /* topmost ephemeral chrome - above modals (300) or in-dialog tips vanish */
  font: 500 12px -apple-system, system-ui, sans-serif; white-space: nowrap; transform: translate(-50%, -100%);
  display: flex; flex-direction: row; align-items: center; gap: 10px;
  background: var(--tip-bg); color: var(--tip-ink);
  box-shadow: 0 2px 8px -2px rgba(0, 0, 0, .25);
  animation: sh-tip-pop .12s ease }
@keyframes sh-tip-pop { from { opacity: 0; transform: translate(-50%, -100%) scale(.95) } }
/* top-of-screen chrome flips its tooltip below the trigger */
.sh-tip.below { transform: translate(-50%, 0); animation-name: sh-tip-pop-b }
@keyframes sh-tip-pop-b { from { opacity: 0; transform: translate(-50%, 0) scale(.95) } }
.sh-tip.right { transform: translate(0, -50%); animation-name: sh-tip-pop-r }
@keyframes sh-tip-pop-r { from { opacity: 0; transform: translate(0, -50%) scale(.95) } }
/* a lane tile's whole title: wraps past one line, never wider than a short paragraph */
.sh-tip .jm-tip-title { display: block; max-width: 320px; white-space: normal; line-height: 16px }
/* a status's tooltip: the status, then where it came from - each piece of evidence on its own line */
.sh-tip .sh-tip-lines { display: flex; flex-direction: column; gap: 2px; max-width: 420px; max-height: calc(100vh - 32px - var(--mv-top, 0px)); overflow: hidden; white-space: normal }
/* read by a screen reader, never seen: what a glyph says to the eye */
.sh-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0 }
.sh-tip .sh-tip-lines small { opacity: .62; font-size: 11px; line-height: 1.35; overflow-wrap: anywhere }
/* play chrome is fixed dark glass regardless of board theme - its tips pin the light bubble */
.sh-tip.inv { background: #f4f4f5; color: #18181b }
.sh-tip b { font-weight: 600 }
.sh-tip span { opacity: .55; font-size: 11px; margin-left: auto }
.sh-tip span.k { opacity: .4; margin-left: 0; font-weight: 600 }

.sh-banner { position: absolute; bottom: var(--edge); right: var(--edge); z-index: 10; font: 500 12px/16px -apple-system, system-ui, sans-serif;
  color: var(--glass-warn); border-radius: 16px; padding: 8px 14px;
  max-width: min(460px, calc(100% - 2 * var(--edge))) }   /* wraps rather than running under a panel on the left */

/* update pill: bottom-center, the quietest possible member of the pill family.
   The command IS the button - one click copies it for the terminal or the agent. */
.sh-update { position: absolute; left: 50%; bottom: var(--edge); transform: translateX(-50%); z-index: 10;
  display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 7px 0 16px; border-radius: 999px;
  max-width: min(92vw, 620px); white-space: nowrap;
  font: 500 12.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2);
  animation: sh-update-in .35s cubic-bezier(.2, .9, .3, 1.2) }
@keyframes sh-update-in { from { opacity: 0; transform: translate(-50%, 8px) scale(.96) } }
.sh-update b { font-weight: 650; color: var(--glass-ink) }
.sh-update .cmd { border: 1px solid var(--glass-brd); background: var(--glass-hover); border-radius: 999px;
  padding: 4px 11px; cursor: pointer; min-width: 0; overflow: hidden; transition: color .15s }
.sh-update .cmd code { font: 500 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--glass-ink-2);
  display: block; overflow: hidden; text-overflow: ellipsis }
.sh-update .cmd:hover code { color: var(--glass-ink) }
.sh-update .x { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px;
  border: 0; background: none; border-radius: 999px; color: var(--glass-ink-3); cursor: pointer;
  transition: color .15s, background .15s }
.sh-update .x:hover { background: var(--glass-hover); color: var(--glass-ink) }

/* bottom-RIGHT now: jam reply pills live here; plain toasts ride along */
.sh-toasts { position: absolute; right: var(--edge); bottom: var(--edge); z-index: 32; display: flex;
  flex-direction: column; align-items: flex-end; gap: 8px; max-width: min(360px, 40vw) }
.sh-toast { display: flex; align-items: center; gap: 6px; font: 500 12px -apple-system, system-ui, sans-serif;
  color: var(--glass-ink-2); border-radius: 999px; padding: 7px 13px }
.sh-toast svg { color: var(--glass-good); flex: none }
/* the jam pill's svgs are NOT the toast checkmark: the mark stays white/90 on blue, the X keeps
   its own muted ink - undo the blanket green above */
.sh-toast.jam svg { color: currentColor }
.sh-toast-more { color: var(--glass-ink-3); font-size: 11px; padding: 2px 10px }

/* the Live Jam reply pill: our full glass treatment, full radius, one row (§9) */
.sh-toast.jam { gap: 12px; padding: 12px 12px 12px 14px; width: 380px; max-width: 100%; border-radius: 999px;
  background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-brd); box-shadow: var(--shadow-glass), 0 12px 32px -12px rgba(24,24,27,.4);
  color: var(--glass-ink); animation: sh-jam-in .18s ease }
@keyframes sh-jam-in { from { opacity: 0; transform: translateY(6px) } to { opacity: 1; transform: none } }
/* Marver is ALWAYS its own blue - never the shell accent, which swaps to magenta in interact mode
   (.sh-app.interacting). A fixed var the swap can't touch keeps the avatar + notification on-brand. */
:root { --mv-blue: #0088ff }
.sh-jam-mark { flex: none; width: 34px; height: 34px; border-radius: 50%; background: var(--mv-blue); color: rgba(255,255,255,.9);
  display: inline-flex; align-items: center; justify-content: center }
.sh-jam-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0; line-height: 1.25 }
/* row 1: the FRAME is the news - its title in blue (the mark already says it is Marver) */
.sh-jam-frame { display: flex; align-items: center; font-size: 13.5px; font-weight: 600; color: var(--mv-blue); min-width: 0 }
.sh-jam-frame .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
/* row 2: the message alone, darker for readability */
.sh-jam-prev { font-size: 12.5px; color: var(--glass-ink-2, var(--glass-ink)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }

/* the DECK (3+): newest pill on top, two card edges peeking beneath; +N badge; click to expand */
.sh-jam-deck { position: relative; cursor: pointer }
.sh-jam-deck .sh-toast.jam { position: relative; margin: 0 }
.sh-jam-ghost { position: absolute; left: 0; right: 0; height: 100%; border-radius: 999px;
  background: var(--glass); border: 1px solid var(--glass-brd); box-shadow: var(--shadow-glass) }
.sh-jam-ghost.g1 { top: 6px; left: 5px; right: 5px; opacity: .8 }
.sh-jam-ghost.g2 { top: 12px; left: 11px; right: 11px; opacity: .5 }
.sh-jam-deck { margin-bottom: 12px }   /* room for the peeking edges */
.sh-jam-badge { flex: none; font: 700 11px -apple-system, system-ui, sans-serif; color: var(--glass-ink);
  background: var(--glass-hover); border-radius: 999px; padding: 4px 9px }

/* the EXPANDED list: newest first, header with count + Clear all, scrolls past ~6.
   The scroller CLIPS at its box - pad it out to the pills' shadow reach (12px drop, 32px
   blur) and cancel with negative margins, so the shadows breathe and nothing moves. */
.sh-jam-list { display: flex; flex-direction: column; gap: 8px; align-items: stretch;
  max-height: min(60vh, 520px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;
  padding: 22px 26px 32px; margin: -22px -26px -32px }
.sh-jam-listhead { display: flex; align-items: center; gap: 8px; padding: 0 6px;
  font: 700 10px -apple-system, system-ui, sans-serif; letter-spacing: .06em; color: var(--glass-ink-3) }
.sh-jam-listhead button { margin-left: auto; border: 0; background: none; cursor: pointer;
  font: 600 11px -apple-system, system-ui, sans-serif; color: var(--mv-blue); padding: 3px 6px }
.sh-jam-listhead button + button { margin-left: 0; color: var(--glass-ink-3); display: inline-flex }
.sh-jam-view { flex: none; border: 0; border-radius: 999px; padding: 5px 12px; cursor: pointer;
  background: var(--mv-blue); color: #fff; font: 600 12px -apple-system, system-ui, sans-serif; transition: filter .15s }
.sh-jam-view:hover { filter: brightness(1.08) }
.sh-jam-x { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  border: 0; border-radius: 50%; background: none; color: var(--glass-ink-3); cursor: pointer; transition: background .12s, color .12s }
.sh-jam-x:hover { background: var(--glass-hover); color: var(--glass-ink) }

/* ---- Play mode: near-black stage, one centered device, auto-hiding bar.
   Fixed dark palette - the backdrop never follows the board theme, so no tokens here. */
.sh-play { position: absolute; inset: 0; z-index: 30; background: #0a0a0b; display: flex; padding-top: var(--mv-top, 0px);
  align-items: center; justify-content: center; animation: sh-play-in .28s ease-out; cursor: auto }
@keyframes sh-play-in { from { opacity: 0 } }
/* the device wears the frame-node card language: same theme border tokens, the same
   masked 1px edge-light gradient ring (glass catching light), and a real drop shadow
   below. Radius + clipping live on the WRAPPER at whole pixels - the iframe is
   transparent and scaled to land exactly on its edges, which killed the corner seams.
   The ring is an inside overlay, not a border: border-box would clip a pixel of content. */
/* LIGHT device: its own treatment, fully separate from dark - no masked border, just a
   soft gray RING hugging the outside edge plus the luminous halo lifting it off black */
.sh-play .dev { position: relative; overflow: hidden; border-radius: 14px;
  --pdev-bg: #fff;
  background: var(--pdev-bg);
  box-shadow: 0 0 0 1px rgba(148, 152, 164, .6), 0 0 54px rgba(255, 255, 255, .12),
    0 30px 70px -16px rgba(0, 0, 0, .85), 0 8px 24px rgba(0, 0, 0, .45);
  transition: width .28s ease, height .28s ease }
/* DARK device: the original glint recipe, verbatim - do not touch */
.sh-play .dev[data-theme="dark"] { --pdev-bg: #0f1015;
  box-shadow: 0 30px 70px -16px rgba(0, 0, 0, .85), 0 8px 24px rgba(0, 0, 0, .45) }
.sh-play .dev[data-theme="dark"]::after { content: ''; position: absolute; inset: 0; padding: 1px; border-radius: inherit;
  background-color: #2c2d38;
  background-image: linear-gradient(155deg, rgba(255, 255, 255, .3), rgba(255, 255, 255, .05) 30%, rgba(255, 255, 255, .02) 65%, rgba(255, 255, 255, .16));
  pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude }
.sh-play .dev iframe { display: block; border: 0; background: transparent; transform-origin: 0 0 }
.sh-play.fill .dev { border-radius: 0; box-shadow: none; transition: none }
.sh-play.fill .dev::after { display: none }

/* the two floating chrome pieces share one glass language and one idle behavior. Of them only .sh-play-nav is still
   rendered: play's top chrome is the shared pill (Play.tsx: nav.sh-pill.sh-play-pill, .sh-pill-fab), which takes the
   Mac app's inset through .sh-pill's own rule - .sh-play-bar, its menu and .sh-play-chip below are unused, left as
   they were */
.sh-play-bar, .sh-play-nav { position: absolute; display: flex; align-items: center; gap: 1px;
  padding: 4px; border-radius: 999px;
  background: rgba(18, 18, 24, .82); border: 1px solid rgba(255, 255, 255, .12);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  transition: opacity .35s ease; font: 500 12px -apple-system, system-ui, sans-serif; color: #f5f5f7 }
.sh-play-bar { top: 14px; right: 16px }
.sh-play-nav { bottom: 16px; left: 16px }
.sh-play-bar.idle, .sh-play-nav.idle { opacity: 0; pointer-events: none }
.sh-play-bar .sep, .sh-play-nav .sep { width: 1px; height: 16px; background: rgba(255, 255, 255, .14); margin: 0 4px }
.sh-play-bar button, .sh-play-nav button { display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border: 0; border-radius: 999px; background: transparent;
  color: rgba(245, 245, 247, .64); cursor: pointer }
.sh-play-bar button:hover, .sh-play-nav button:hover { background: rgba(255, 255, 255, .1); color: #f5f5f7 }
.sh-play-bar button.on { background: rgba(255, 255, 255, .14); color: #f5f5f7 }

/* board switcher */
.sh-play-bar .bd-wrap { position: relative }
.sh-play-bar .bd { width: auto; gap: 6px; padding: 0 10px 0 12px; white-space: nowrap; font: inherit }
.sh-play-bar .sh-play-update { width: auto; gap: 5px; padding: 0 11px; font-size: 12px; font-weight: 600; color: #6db3ff; white-space: nowrap }
.sh-play-bar .sh-play-update:hover { background: rgba(109, 179, 255, .16); color: #8ec5ff }
/* no backdrop-filter here: the menu nests inside the blurred bar, and glass never nests
   (a nested backdrop-filter samples the bar, not the page) - near-opaque ink instead */
.sh-play-menu { position: absolute; top: calc(100% + 10px); left: 0; min-width: 150px; padding: 4px;
  border-radius: 12px; background: rgba(20, 20, 26, .97); border: 1px solid rgba(255, 255, 255, .12);
  box-shadow: 0 12px 40px rgba(0, 0, 0, .5); display: flex; flex-direction: column; gap: 1px }
.sh-play-menu button { width: 100%; height: 28px; justify-content: flex-start; gap: 8px; padding: 0 10px;
  border-radius: 8px; font: inherit }
.sh-play-menu button span { flex: 1; text-align: left; white-space: nowrap }

/* walk position readout */
.sh-play-nav .pos { padding: 0 8px; color: rgba(245, 245, 247, .64); font-variant-numeric: tabular-nums; white-space: nowrap }
.sh-play-nav .pos em { font-style: normal; opacity: .45; margin: 0 2px }

/* collapsed chip - the bar's fab. Always mounted so collapse/expand crossfades. */
.sh-play-chip { position: absolute; top: 14px; right: 16px; width: 38px; height: 38px;
  display: grid; place-items: center; border-radius: 999px;
  background: rgba(18, 18, 24, .82); border: 1px solid rgba(255, 255, 255, .12);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  color: rgba(245, 245, 247, .64); cursor: pointer;
  transition: opacity .35s ease, transform .35s ease }
.sh-play-chip:hover { color: #f5f5f7 }
.sh-play-chip.idle { opacity: 0; pointer-events: none; transform: scale(.6) }


/* ---- Focus: silent for pointer + shortcut use; ONE branded inset ring, and only while
   the user is actually Tab-navigating (body.sh-kbd, armed by Tab, disarmed by pointer).
   Inset so scroll containers can never clip it; outline follows the border radius. */
.sh-app :focus { outline: none }
body.sh-kbd .sh-app :focus-visible { outline: 2px solid var(--accent); outline-offset: -2px }

/* ---- Variant groups: badge left of grouped frames + group caption.
   Both live in WORLD space (scale with the canvas) with a screen-space
   minimum via --sh-inv, the resize-handle trick - legible at overview zoom, proportionate
   up close. Colors are on-canvas ink (the dot-grid's world), not chrome glass. */
/* gap to the frame is ~12px screen at working zooms, capped at 40 world px far out:
   a pure world gap reads ever wider zoomed in, an uncapped screen gap outgrows the
   gutter zoomed out */
.sh-vbadge { position: absolute; right: 100%; top: 0;
  /* margin caps at 40 WORLD px: below ~30% zoom an uncapped screen-constant margin
     alone would outgrow the gutter and push the badge onto the left neighbor */
  margin-right: clamp(6px, calc(12px * var(--sh-inv, 1)), 40px);
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  text-align: right; user-select: none; -webkit-user-select: none;
  font-family: -apple-system, system-ui, sans-serif }
.sh-vbadge b { font-size: min(clamp(40px, calc(20px * var(--sh-inv, 1)), 120px), calc(40px * var(--sh-inv, 1))); line-height: 1; font-weight: 750;
  /* world cap 120px: past ~17% zoom the letter stops growing (in world terms) and
     shrinks with the canvas instead of bleeding across the gutter onto the neighbor */
  letter-spacing: -0.02em; color: rgba(24, 24, 27, .55);
  /* the letter OUTLIVES the name (drive feedback 2026-08-12): the name leaves at
     ~30%, the letter stays useful until ~10-16% - the world cap keeps it inside the
     gutter down there - and then hands identity to the group caption */
  opacity: clamp(0, calc((var(--sh-s, 1) - 0.1) * 15), 1) }
.sh-vbadge span { font-size: min(max(15px, calc(10px * var(--sh-inv, 1))), calc(15px * var(--sh-inv, 1))); font-weight: 550;
  color: rgba(24, 24, 27, .38); max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* the letter is the identity at overview zoom; the name earns pixels only close up */
  opacity: clamp(0, calc((var(--sh-s, 1) - 0.3) * 6), 1) }
.sh-app.dark .sh-vbadge b { color: rgba(245, 245, 247, .6) }
.sh-app.dark .sh-vbadge span { color: rgba(245, 245, 247, .4) }

.sh-gcaption { position: absolute; top: 0; left: 0; user-select: none; -webkit-user-select: none;
  /* screen-clamped both ways: 12px floor at overview, 18px ceiling zoomed in - world
     text that keeps growing past 100% zoom dwarfs the fixed-size floating menu above */
  font: 600 clamp(calc(12px * var(--sh-inv, 1)), 17px, calc(18px * var(--sh-inv, 1)))/1.2 -apple-system, system-ui, sans-serif;
  letter-spacing: .01em; color: rgba(24, 24, 27, .45); white-space: nowrap }
.sh-app.dark .sh-gcaption { color: rgba(245, 245, 247, .45) }

/* sidebar variant rows: group header carries the experimentation mark; each variant
   row carries its letter CHIP (accent-filled when selected) + name */
/* gap 0: the leading .iicon's margin-right carries the spacing, so the group
   label lands on the SAME 51px text column as every sibling row */
.sub.vgroup { display: flex; align-items: center; gap: 0 }
.sub.vgroup .glabel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.sub.vgroup .gicon { margin-left: auto; flex: none; color: var(--glass-ink-3); transition: color .15s }
.sub.vgroup:hover .gicon { color: var(--glass-ink) }
.sub.vgroup.on .gicon { color: var(--accent) }
.sub .chip { width: 20px; height: 20px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--glass-brd); border-radius: 7px; background: none; cursor: pointer;
  font: 700 10px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3);
  /* optical centering: trim the text box to CAP height so flex centers the glyph
     itself, not the em box (whose descender space floats caps high) */
  line-height: 1; letter-spacing: 0; text-box: trim-both cap alphabetic;
  transition: color .15s, background .15s, border-color .15s }
.sub .chip:hover { color: var(--glass-ink); background: var(--glass-hover) }
.sub .chip.on { color: #fff; background: var(--accent); border-color: var(--accent) }

/* play-mode variant chips: the SAME badge language as the sidebar's
   variant rows (20px, 7px-radius square, one consistent shape in every state) so the
   two surfaces read as one concept - but in the pill's own dark-glass inks, never
   theme tokens (the nav is always dark; theme ink goes invisible in light mode). */
.sh-play-nav .vchip { width: 20px; height: 20px; min-width: 0; flex: none; margin: 0 1px;
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 7px;
  font: 700 10px -apple-system, system-ui, sans-serif; color: rgba(245, 245, 247, .6);
  line-height: 1; letter-spacing: 0; text-box: trim-both cap alphabetic }
.sh-play-nav .vchip:hover { color: #f5f5f7; background: rgba(255, 255, 255, .1) }
.sh-play-nav .vchip.on { color: #fff; background: var(--accent); border-color: var(--accent) }
/* bordered chips read tighter than borderless icons at the same distance - the
   divider needs a touch more air before the first chip */
.sh-play-nav .sep + .vchip { margin-left: 5px }

/* --- prototype-review: shared toolbar in play, Hide-UI, comment overlay --- */

/* Hide-UI: one binary body class (canvas + prototype) drops all operating chrome. Not
   persisted - a page refresh always restores it. Comment pins/threads (the review
   annotations) stay; only the marver chrome hides, for a clean point-and-shoot frame. */
body.sh-hide-ui .sh-pill,
body.sh-hide-ui .sh-pill-fab,
body.sh-hide-ui .sh-panel,
body.sh-hide-ui .sh-fab,
body.sh-hide-ui .sh-ctx,
body.sh-hide-ui .sh-update,
body.sh-hide-ui .sh-toasts,
body.sh-hide-ui .sh-banner:not(.sh-stopped),   /* a stopped canvas stays said: the page holds what only it has */
body.sh-hide-ui .sh-play-nav { display: none !important }

/* the prototype pill reuses the shared pill LAYOUT but wears the discreet DARK skin of the
   bottom-left navigator (not the bright canvas glass), so it recedes into the near-black
   stage: dark translucent fill, a faint white hairline, light-on-dark controls. */
.sh-play-pill, .sh-play .sh-pill-fab { z-index: 32 }
.sh-play-pill.sh-pill, .sh-play .sh-pill-fab {
  background: rgba(18, 18, 24, .8); border: 1px solid rgba(255, 255, 255, .1);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .38) }
.sh-play-pill::after, .sh-play .sh-pill-fab::after { display: none }   /* no light edge-light overlay */
.sh-play-pill .sh-pill-btn, .sh-play .sh-pill-fab { color: rgba(245, 245, 247, .6) }
.sh-play-pill .sh-pill-btn:hover, .sh-play .sh-pill-fab:hover { background: rgba(255, 255, 255, .1); color: #f5f5f7 }
.sh-play-pill .sh-pill-btn.on { background: rgba(255, 255, 255, .14); color: #f5f5f7 }
.sh-play-pill .sep { background: rgba(255, 255, 255, .12) }
.sh-play-pill .bd { color: rgba(245, 245, 247, .82) }
.sh-pill-btn.bd { width: auto; gap: 6px; padding: 0 8px 0 11px; white-space: nowrap; font-weight: 600 }

/* ---- present/focus chrome (sharing v1): brand pill top-left, counter in the
   toolbar, doc reading preset. Same glass skin as the play pill. */
/* the brand pill matches the toolbar pill to the pixel: the SAME .sh-pill
   padding (5px) and the SAME 34px inner height as .sh-pill-btn - its two
   children are sized like buttons, so text metrics never set the height */
.sh-play-brand.sh-pill { left: var(--edge); right: auto; transform-origin: 22px 22px; padding: 5px 9px 5px 5px }
.sh-play-mark { display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 8px 0 10px; border-radius: 999px;
  color: rgba(245, 245, 247, .88); text-decoration: none; cursor: pointer }
.sh-play-mark:hover { background: rgba(255, 255, 255, .1); color: #f5f5f7 }
.sh-play-mark svg { color: #6db3ff }
.sh-play-mark .wd { font: 600 13px -apple-system, system-ui, sans-serif; letter-spacing: -.01em }
.sh-play-title { display: inline-block; height: 34px; line-height: 34px; font: 500 13px/34px -apple-system, system-ui, sans-serif; color: rgba(245, 245, 247, .82);
  max-width: 143px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 6px }
.sh-play-pos { font: 500 12.5px -apple-system, system-ui, sans-serif; color: rgba(245, 245, 247, .64);
  font-variant-numeric: tabular-nums; padding: 0 8px; white-space: nowrap }
/* doc preset: the page IS the surface - reading column on a calm ground, no
   device shell, natural document scrolling inside the frame */
.sh-play.doc { background: #f4f4f6 }
.sh-play.doc.t-dark { background: #101116 }
.sh-play.doc .dev { --pdev-bg: #fff; box-shadow: none }
.sh-play.doc.t-dark .dev { --pdev-bg: #0f1015 }
/* the doc chrome floats over a LIGHT ground in light theme - the dark pill skin
   still reads (it is glass over anything), matching the design's fixed pills */
.sh-play-update { width: auto !important; gap: 5px; padding: 0 11px !important; font-size: 12px; font-weight: 600 }
/* the picker dropdowns portal to .sh-app; in play they carry .sh-menu-dark for the dark skin */
.sh-menu-dark { background: rgba(20, 20, 26, .97); border-color: rgba(255, 255, 255, .12); box-shadow: 0 12px 40px rgba(0, 0, 0, .5) }
.sh-menu-dark::after { display: none }
.sh-menu-dark button { color: rgba(245, 245, 247, .82) }
.sh-menu-dark button:hover { background: rgba(255, 255, 255, .1) }
.sh-menu-dark .chk { color: #6db3ff }
.sh-menu-dark kbd { color: rgba(245, 245, 247, .5) }
.sh-menu-dark .div { background: rgba(255, 255, 255, .1) }

/* device + comment overlay share one flex-centered box; the overlay is inset:0 over it, a
   SIBLING of the clipping .dev so a thread card is never eaten by the device's overflow.
   overflow:visible lets a card spill past the device edge; only its markers catch the
   pointer, the stage below stays fully interactive. */
.sh-play-stage { position: relative; flex: none }
/* the canvas writes --sh-inv (1/zoom) for screen-constant pins; the prototype has no
   zoom, so neutralise it or the leaked value scales every comment pin by ~12x at overview */
.sh-play { --sh-inv: 1 }
.sh-play-comments { position: absolute; inset: 0; z-index: 31; overflow: visible; pointer-events: none;
  --sh-inv: 1 }   /* the stage does not zoom: its markers are placed in screen px */
.sh-play-comments > * { pointer-events: auto }

/* the current variant's name trails the chips at natural width - the chips anchor,
   so a name change grows the pill rightward without shifting any control underfoot.
   A max caps runaway titles; the Tip carries the full name. */
.sh-play-nav .vname { font-size: 11px; font-weight: 600; color: rgba(245, 245, 247, .78);
  max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-transform: capitalize; padding: 0 11px 0 5px }

/* variant chrome goes LIVE with selection (drive feedback 2026-08-12): accent when the
   frame is selected, the interact purple when it is being interacted with - the badge,
   name, caption, and frame title all agree with the frame's state */
.sh-vbadge { cursor: pointer }
/* children stay click-transparent: rzpp's pan exclusion and the select handler both
   need the BADGE DIV to be the event target (same pattern as button svg) */
.sh-vbadge b, .sh-vbadge span { pointer-events: none }
.sh-node.sel .sh-vbadge b, .sh-node.sel .sh-vbadge span { color: var(--accent) }
.sh-node.interact .sh-vbadge b, .sh-node.interact .sh-vbadge span { color: var(--interact) }
/* the frame header sits INSIDE the selection border - tinting its title too would
   double-signal (drive feedback 2026-08-12); the badge/caption/sidebar carry state */
.sh-gcaption { cursor: pointer }
.sh-gcaption.on { color: var(--accent) }
.sh-gcaption:hover { color: var(--glass-ink-2) }
.sh-gcaption.on:hover { color: var(--accent) }

/* per-variant sidebar rows under the group header */
/* variant rows read one level QUIETER than frame rows: shorter, smaller, lighter -
   the scannable hierarchy is scene > frame/surface > variants */
.sub.vrow { display: flex; align-items: center; gap: 7px; padding-left: 31px; height: 24px; font-size: 12px }
.sub.vrow .chip { width: 16px; height: 16px; border-radius: 5px; font-size: 8.5px }
.sub.vrow .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.sub.vgroup { cursor: pointer }
.sub.vgroup.held { background: color-mix(in srgb, var(--glass-hover) 55%, transparent) }
.sub.vgroup.held .gicon { color: var(--glass-ink-2) }

/* ---- comments ----------------------------------------------------------
   The marker family (pins, stacks) is SOLID with the Figma teardrop silhouette - a
   marker must hold contrast on any artwork. The surfaces (card, composer, dialog)
   are OUR glass - the shell's own token language, theme-aware where Figma is flat. */
.cm-avatar { display: inline-flex; align-items: center; justify-content: center; border-radius: 50%;
  color: #fff; font-weight: 700; font-family: -apple-system, system-ui, sans-serif;
  object-fit: cover; flex: none; user-select: none }

/* markers - pins and stacks share one face: overlapping avatars + a total count.
   A pin shows one thread's participants (tail points at its div); a stack shows
   everyone across the frame's threads (tail points up-right at the frame corner). */
.cm-pin, .cm-stack { display: inline-flex; align-items: center; padding: 4px;
  background: #fff; border: 1px solid rgba(24,24,27,.1); cursor: pointer;
  font: 700 11px -apple-system, system-ui, sans-serif; color: #18181b }
.cm-pin .cm-avatar, .cm-stack .cm-avatar { border: 2px solid #fff }
.cm-pin .cm-avatar + .cm-avatar, .cm-stack .cm-avatar + .cm-avatar { margin-left: -8px }
.cm-pin b, .cm-stack b { padding: 0 8px 0 6px }

/* pin: the teardrop. Bottom-left tail points at the anchored element. Its face draws inside ONE
   fixed box (pin-layout.ts MARKER: 80 x 34 screen px), the box markers are placed by - so a reply
   or a new participant never moves a marker, and two never overlap. */
.cm-pin { position: absolute; z-index: 30; transform: translate(-2px, -100%) scale(var(--sh-inv, 1));
  transform-origin: bottom left; border-radius: 18px 18px 18px 4px;
  height: 34px; max-width: 80px; overflow: hidden; white-space: nowrap;
  box-shadow: 0 1px 2px rgba(24,24,27,.18), 0 6px 16px -6px rgba(24,24,27,.35);
  transition: box-shadow .15s, transform .15s }
.cm-pin:hover { box-shadow: 0 1px 3px rgba(24,24,27,.22), 0 10px 24px -6px rgba(24,24,27,.45) }
/* selected pin wears the selected frame's exact geometry - border, 2px
   outline hugging the edge, 4px ring halo - in the comment green (the pin
   is already screen-space via scale(--sh-inv), so plain px match the
   frame's calc'd screen px) */
.cm-pin.on { border-color: var(--cm-line, var(--comment));
  outline: 2px solid var(--cm-line, var(--comment)); outline-offset: -1px;
  box-shadow: 0 0 0 4px var(--cm-line-ring, var(--comment-ring)), 0 1px 2px rgba(24,24,27,.18), 0 6px 16px -6px rgba(24,24,27,.35) }
.cm-pin.orphan { border-style: dashed; opacity: .75 }
/* a marker moved off its point (another sat there first) keeps a thin line up to it - under the
   markers, never in the way of a click */
.cm-lead { position: absolute; z-index: 29; pointer-events: none !important; width: calc(1.5px * var(--sh-inv, 1));
  transform: translateX(-50%); background: rgba(24,24,27,.45); border-radius: 1px }

/* stack: the frame-corner cluster - everyone across the frame's threads */
.cm-stack { position: absolute; top: 10px; right: 10px; z-index: 30;
  transform: scale(var(--sh-inv, 1)); transform-origin: top right; border-radius: 18px 18px 4px 18px;
  box-shadow: 0 1px 2px rgba(24,24,27,.15), 0 6px 16px -6px rgba(24,24,27,.3);
  transition: box-shadow .15s }
.cm-stack:hover { box-shadow: 0 1px 3px rgba(24,24,27,.2), 0 10px 24px -6px rgba(24,24,27,.4) }

/* card: OUR glass - the floating-menu language, theme-aware */
.cm-card { position: absolute; z-index: 40; width: 300px; padding: 16px;
  transform: scale(var(--sh-inv, 1)); transform-origin: top left;
  background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  /* an open card is the active selection - the frame's exact geometry, comment green */
  color: var(--glass-ink); border-radius: 20px; border: 1px solid var(--cm-line, var(--comment));
  outline: 2px solid var(--cm-line, var(--comment)); outline-offset: -1px;
  box-shadow: 0 0 0 4px var(--cm-line-ring, var(--comment-ring)), var(--shadow-glass), 0 16px 40px -12px rgba(24,24,27,.35);
  display: flex; flex-direction: column; gap: 12px;
  font: 400 13px -apple-system, system-ui, sans-serif; letter-spacing: -.005em; text-align: left }
.cm-card.flip { transform: translateX(-100%) scale(var(--sh-inv, 1)); transform-origin: top right }
/* the open thread on the CANVAS is UI, not artwork: a FIXED screen-space panel that never zooms or
   pans with the canvas. Viewport-bounded; the messages scroll inside (.cm-scroll), the composer
   stays pinned at the bottom. */
/* parked beside the frame (canvas): a WORLD object - it stays put with its frame through panning.
   Scale + max-height come inline (clamped 0.9..1.35 of screen-constant; height capped at the
   frame's). A screen-ish gutter separates card from frame. Long threads scroll inside. */
/* parked beside the frame (canvas): a world object that scales EXACTLY like the pins - the base
   .cm-card scale(--sh-inv) - so it zooms smoothly with the board and stays readable at any zoom.
   Screen-constant gutters via margins (the left one wider - it clears the working shimmer). */
.cm-card.parked { width: 320px; overflow: hidden; z-index: 50 }
.cm-card.parked:hover { z-index: 60 }   /* reading/replying wins over neighbouring chrome */
/* gutters: SNUG by default (~12px screen), and only as wide as what actually occupies the flank -
   the working shimmer strip (.flank-shim) or a variant badge (.flank-badge, the widest). All
   screen-targeted with world caps so they stay sane at both zoom extremes. */
.cm-card.parked.dock-r { transform-origin: top left; margin-left: clamp(8px, calc(12px * var(--sh-inv, 1)), 36px) }
.cm-card.parked.dock-l { transform: translateX(-100%) scale(var(--sh-inv, 1)); transform-origin: top right;
  margin-left: calc(-1 * clamp(8px, calc(12px * var(--sh-inv, 1)), 36px)) }
.cm-card.parked.dock-l.flank-shim { margin-left: calc(-1 * clamp(18px, calc(28px * var(--sh-inv, 1)), 68px)) }
.cm-card.parked.dock-l.flank-badge { margin-left: calc(-1 * clamp(26px, calc(44px * var(--sh-inv, 1)), 108px)) }
/* a sticky column (spec 18) is world-sized: the card clears it and its gutter */
.cm-card.parked.dock-l.flank-note { margin-left: calc(-1 * (var(--sh-note-w, 260px) + 36px)) }
/* PLAY: fixed beside the static device, viewport-clamped (position comes inline). Near-solid
   ground - the stage floats the card over arbitrary artwork on a dark room, glass is unreadable
   there. No transform: play has no zoom, and a leaked --sh-inv must never scale it. */
.cm-card.stage-dock { width: 320px; overflow: hidden; z-index: 60; transform: none;
  background: var(--cm-modal-bg, var(--glass)) }
/* the scroller reaches INTO the card's right padding so its scrollbar rides the card's far
   edge - right of the close button, 3px off the border, a 13px gap to the text. The bar is
   OURS: a slim glass-gray thumb on a transparent track, and it only exists when the thread
   actually overflows. Text width never shifts when it appears. */
.cm-scroll { display: flex; flex-direction: column; gap: 12px; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; margin-right: -13px; padding-right: 13px }
.cm-scroll::-webkit-scrollbar { width: 6px }
.cm-scroll::-webkit-scrollbar-track { background: transparent }
.cm-scroll::-webkit-scrollbar-thumb { border-radius: 99px;
  background: color-mix(in srgb, var(--glass-ink-3) 50%, transparent) }
.cm-scroll::-webkit-scrollbar-thumb:hover { background: var(--glass-ink-3) }
@supports not selector(::-webkit-scrollbar) {
  .cm-scroll { scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--glass-ink-3) 50%, transparent) transparent }
}
/* "there is more": the scroller masks its OWN content at the overflowing edge - a clean fade of
   the text itself, theme-proof (no paint layer fighting the glass) */
.cm-scroll.fade-top { -webkit-mask-image: linear-gradient(180deg, transparent, #000 30px); mask-image: linear-gradient(180deg, transparent, #000 30px) }
.cm-scroll.fade-bot { -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 30px), transparent); mask-image: linear-gradient(180deg, #000 calc(100% - 30px), transparent) }
.cm-scroll.fade-top.fade-bot { -webkit-mask-image: linear-gradient(180deg, transparent, #000 30px, #000 calc(100% - 30px), transparent); mask-image: linear-gradient(180deg, transparent, #000 30px, #000 calc(100% - 30px), transparent) }
.cm-card header { display: flex; align-items: center; gap: 9px }
.cm-card header b { font-size: 14px; font-weight: 600; letter-spacing: -.01em }
/* Jam V2 (spec 27): where a tag's work stands - one icon right of the message's time, only while
   there is something to wait for or act on. Click keeps its detail open with the card's one move. */
.cm-tstat { position: relative; display: inline-flex; align-items: center; margin-left: -4px }
.cm-tstat-btn { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 6px;
  background: none; cursor: pointer }
.cm-tstat-btn:hover, .cm-tstat.on .cm-tstat-btn { background: var(--glass-hover) }
.cm-tstat-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px }
.cm-tstat-pop { position: absolute; left: -4px; top: calc(100% + 6px); z-index: 50; display: flex; align-items: center; gap: 10px; width: max-content; max-width: 320px;
  padding: 7px 7px 7px 11px; border-radius: 8px; background: var(--tip-bg); color: var(--tip-ink);
  font: 500 12px -apple-system, system-ui, sans-serif; box-shadow: 0 8px 22px -8px rgba(0, 0, 0, .45); animation: sh-tip-pop-b .12s ease }
@keyframes sh-tstat-pop { from { opacity: 0; transform: translateY(-3px) } }
.cm-tstat-pop { animation-name: sh-tstat-pop }
.cm-tstat-pop .sh-tip-lines { display: flex; flex-direction: column; gap: 2px; white-space: normal; min-width: 0 }
.cm-tstat-pop .sh-tip-lines b { font-weight: 600; font-size: 12px; letter-spacing: 0; white-space: normal; overflow: visible; text-overflow: clip; max-width: none; color: inherit }
.cm-tstat-pop .sh-tip-lines small { opacity: .62; font-size: 11px; line-height: 1.35 }
.cm-tstat-act { flex: none; height: 24px; padding: 0 10px; border: 0; border-radius: 6px; cursor: pointer;
  background: color-mix(in srgb, var(--tip-ink) 14%, transparent); color: var(--tip-ink); font: 600 12px -apple-system, system-ui, sans-serif }
.cm-tstat-act:hover { background: color-mix(in srgb, var(--tip-ink) 22%, transparent) }
.cm-card:has(.cm-tstat.on), .cm-card .cm-scroll:has(.cm-tstat.on) { overflow: visible }
/* a jam reply that changed a shared file it was not given says so in one line */
.cm-also { margin-top: 4px; font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
.jm-spin { transform-origin: 7px 7px; animation: jm-spin 1.1s linear infinite }
@keyframes jm-spin { to { transform: rotate(360deg) } }
@media (prefers-reduced-motion: reduce) { .jm-spin { animation: none } }
.cm-card .dim { color: var(--glass-ink-3); font-size: 11.5px; font-variant-numeric: tabular-nums }
/* pinned above the scroller so the close button always wins the click - bare buttons on the
   card's own glass, no chip: the custom scrollbar lives at the card's far edge, right of the
   X, so the two never collide. */
.cm-actions { position: absolute; top: 13px; right: 12px; display: flex; gap: 2px; z-index: 5 }
/* the root header shares its line with the pinned actions - reserve their width
   so a long display name ellipsizes instead of running under the icons.
   (root header + body live INSIDE .cm-scroll - scope there, not .cm-card >) */
.cm-scroll > header { padding-right: 84px }
.cm-scroll > header b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
/* every message - root and replies - is the same unit: avatar + name + time,
   body indented to the name column (24px avatar + 9px gap) */
.cm-card .cm-body { margin: 0; padding-left: 33px; font-size: 13px; line-height: 1.55;
  color: var(--glass-ink); white-space: pre-wrap; overflow-wrap: break-word }
.cm-scroll > .cm-body { margin-top: -10px }  /* pulls against the scroller's 12px gap -> the same 2px replies get */
.cm-msg { display: flex; flex-direction: column; gap: 2px }
.cm-icon { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px;
  border: 0; border-radius: 8px; background: none; color: var(--glass-ink-3); cursor: pointer;
  transition: background .12s, color .12s }
.cm-icon:hover { background: var(--glass-hover); color: var(--glass-ink) }
/* copy-link morphs into a check on the shell's morph curve, then reverts */
.cm-copy { position: relative }
.cm-copy .a, .cm-copy .b { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  transition: transform var(--morph), opacity .2s ease }
.cm-copy .b { transform: scale(.4); opacity: 0; color: var(--comment) }
.cm-copy.ok .a { transform: scale(.4); opacity: 0 }
.cm-copy.ok .b { transform: scale(1); opacity: 1 }
/* composer row: my avatar (list size) + an auto-growing textarea with a round send button inside.
   Multiline: Enter sends, Shift+Enter is a newline (Live Jam §6). The textarea grows 1-6 rows. */
.cm-compose { display: flex; align-items: flex-end; gap: 8px }
/* the row bottom-aligns (the avatar holds still while the textarea grows), so the avatar
   needs a lift to sit optically centered against a ONE-LINE pill: (38-24)/2 */
.cm-compose > .cm-me, .cm-compose > .cm-avatar { margin-bottom: 7px }
.cm-inputwrap { position: relative; flex: 1; min-width: 0 }
/* the mirror layer (.cm-hl) and the textarea share an IDENTICAL box so the caret + styled text align
   exactly. The textarea sits on top with TRANSPARENT text + bg (caret visible); .cm-hl behind paints the
   field + the styled text, so @marver shows its trigger colour live as you type (Live Jam §1). */
.cm-inputwrap textarea, .cm-hl { box-sizing: border-box; width: 100%; min-height: 38px; max-height: 132px;
  margin: 0; padding: 9px 42px 9px 15px; border: 1px solid transparent; border-radius: 19px;
  /* the math must CLOSE: 1 + 9 + 18 + 9 + 1 = 38 exactly, so a single line sits dead-center
     in the pill (a fractional line box + uncounted borders left the text riding off-center) */
  font: 400 13px/18px -apple-system, system-ui, sans-serif; letter-spacing: normal;
  white-space: pre-wrap; overflow-wrap: break-word; word-break: break-word }
.cm-hl { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  background: var(--cm-field); color: var(--glass-ink) }
.cm-inputwrap textarea { position: relative; z-index: 1; display: block; resize: none; overflow-y: auto;
  background: transparent; color: transparent; caret-color: var(--glass-ink);
  border-color: var(--glass-brd); outline: none; transition: border-color .15s, box-shadow .15s }
.cm-inputwrap textarea::placeholder { color: var(--glass-ink-3) }
.cm-inputwrap textarea:focus { border-color: var(--cm-line, var(--comment)); box-shadow: 0 0 0 3px var(--cm-line-ring, var(--comment-ring)) }
.cm-inputwrap textarea:disabled { opacity: .6; cursor: default }
.cm-send { position: absolute; right: 5px; bottom: 5px;   /* (38 - 28) / 2 - centered in the one-line pill */
  z-index: 2;   /* above the textarea (z1, the @marver mirror stack) - or clicks land on the field, not the button */
  width: 28px; height: 28px; border-radius: 50%; border: 0; display: flex; align-items: center; justify-content: center;
  background: var(--cm-solid, var(--comment)); color: #fff; cursor: pointer; transition: background .15s, opacity .15s }
.cm-send:hover:not(:disabled) { filter: brightness(1.08) }
.cm-send:disabled { background: var(--glass-ink-3); opacity: .5; cursor: default }
/* signed-out viewer: one clear button in place of the composer */
.cm-signin-cta { width: 100%; height: 40px; border: 0; border-radius: 999px;
  background: var(--cm-solid, var(--comment)); color: #fff; cursor: pointer;
  font: 600 13px -apple-system, system-ui, sans-serif; transition: filter .15s }
.cm-signin-cta:hover { filter: brightness(1.06) }
/* the draft composer is JUST the pill - no card chrome around a single input */
.cm-draft { padding: 0; width: 272px; background: none; border: none; box-shadow: none; outline: none;
  backdrop-filter: none; -webkit-backdrop-filter: none }
.cm-draft textarea, .cm-draft .cm-hl { min-height: 40px; padding-top: 10px; padding-bottom: 10px }   /* 1+10+18+10+1 = 40, same closed math */
.cm-draft textarea { box-shadow: 0 2px 6px rgba(24,24,27,.15), 0 12px 32px -8px rgba(24,24,27,.35) }
.cm-draft .cm-send { right: 6px; bottom: 6px }   /* (40 - 28) / 2 for the taller draft pill */

/* Live Jam: @marver mention styling. Owner-authored = a live trigger (bold accent-blue);
   anyone else's = plain-weight, read like any comment, with a teaching tooltip (§1). */
.cm-at { color: var(--glass-ink-2, var(--glass-ink)); font-weight: 500 }
.cm-at.owner { color: var(--mv-blue); font-weight: 700 }
/* IN THE COMPOSER MIRROR the mention may change COLOR + PAINT, never METRICS: real bold
   glyphs are WIDER than the invisible textarea's regular ones, so any font-weight change
   drifts the caret further off with every mention. The bold LOOK comes from a hairline
   text-stroke instead - it thickens the glyph paint without touching a single advance
   width, so the mirror stays pixel-locked to the textarea and the caret never lies. */
.cm-hl .cm-at { font-weight: inherit; -webkit-text-stroke: .4px currentColor }
.cm-at-tip { display: block; max-width: 220px; line-height: 1.4 }

/* v1.1: @Person mentions - the comment accent, medium weight (the mirror rule above
   already keeps composer metrics honest: color + stroke only, never font-weight). */
.cm-at.person { color: var(--cm-line, var(--comment)); font-weight: 600 }
.cm-hl .cm-at.person { font-weight: inherit }
/* The typeahead: a small glass list ABOVE the composer; rows follow the pick. */
/* SOLID, never glass: the picker floats over thread text, and translucency
   made the names unreadable */
.cm-mentionlist { position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 5; min-width: 180px; max-width: 260px;
  display: flex; flex-direction: column; padding: 4px; border-radius: 10px;
  background: var(--solid); border: 1px solid var(--glass-brd); box-shadow: 0 10px 28px rgba(0,0,0,.22) }
.cm-mentionlist button { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 0; border-radius: 7px;
  background: none; color: var(--glass-ink); font: 500 12.5px/1.2 inherit; text-align: left; cursor: pointer; white-space: nowrap }
.cm-mentionlist button span { overflow: hidden; text-overflow: ellipsis }
.cm-mentionlist button.on { background: var(--glass-hover) }

/* Marver identity: the agent's avatar mark + provenance tooltip (§7). Always accent, never a hue. */
.cm-avatar.cm-marver { background: var(--mv-blue); color: rgba(255,255,255,.9); cursor: default }   /* white/90 mark, embedded in the accent */
.cm-marver-wrap { display: inline-flex; border-radius: 50% }
.cm-marver-name { color: var(--glass-ink) }              /* black, not blue */
/* provenance tooltip: matches the toolbar-button tooltip - a BOLD BRIGHT value (what you scan) + a
   muted qualifier label after it, one fact per row, left-aligned. Overrides the house single-row
   `.sh-tip span` dim/right-drift so nothing washes out. */
/* two-row shortcut tooltip (toolbar): one action per row, key right-aligned - the same
   bold-value/muted-key language as the provenance tooltip below. opacity:1 overrides the
   house `.sh-tip span` dim so the wrapper rows stay full-bright; only keys mute. */
.sh-tip:has(.sh-tip-rows) { padding: 7px 11px }
.sh-tip .sh-tip-rows { display: flex; flex-direction: column; align-items: stretch; gap: 5px;
  opacity: 1; margin: 0; font-size: 12px; line-height: 1.2 }
.sh-tip .sh-tip-rows .r { display: flex; align-items: baseline; justify-content: space-between;
  gap: 18px; opacity: 1; margin: 0; font-size: 12px; white-space: nowrap }
.sh-tip .sh-tip-rows .r b { font-weight: 600 }
.sh-tip .sh-tip-rows .r span { opacity: .55; font-size: 11px; font-weight: 600; margin-left: auto }

.sh-tip:has(.cm-meta-tip) { padding: 8px 12px }
/* opacity:1 is the fix - .cm-meta-tip is a <span>, so the house `.sh-tip span{opacity:.55}` was
   dimming the ENTIRE tooltip, and a child's opacity:1 can't undo a parent's reduced opacity. */
.sh-tip .cm-meta-tip { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; line-height: 1.2; opacity: 1; font-size: 12.5px }
.sh-tip .cm-meta-row { display: flex; gap: 8px; align-items: baseline; margin: 0; opacity: 1; font-size: 12.5px; white-space: nowrap }
.sh-tip .cm-meta-row b { font-weight: 600; opacity: 1; margin: 0; color: var(--tip-ink) }        /* value: bold, full-bright */
.sh-tip .cm-meta-row .k { margin: 0; opacity: .5; font-weight: 500; color: var(--tip-ink) }       /* label: muted qualifier */
/* identity modal - same glass family */
.cm-modal-wrap { position: fixed; inset: var(--mv-top, 0px) 0 0 0; z-index: 300; display: flex; align-items: center; justify-content: center;
  background: rgba(24,24,27,.45); backdrop-filter: blur(5px) }
/* the auth modal is a focused surface, not a floating glass panel - near-solid so
   the canvas behind never bleeds through the fields */
.cm-modal { width: 344px; padding: 26px; border-radius: 24px;
  background: var(--cm-modal-bg); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  color: var(--glass-ink); border: 1px solid var(--glass-brd);
  display: flex; flex-direction: column; gap: 8px; font: 400 13px -apple-system, system-ui, sans-serif;
  box-shadow: 0 1px 2px rgba(24,24,27,.1), 0 20px 60px -12px rgba(24,24,27,.5) }
.cm-modal h2 { margin: 0; font-size: 16px; letter-spacing: -.01em }
.cm-modal .dim { margin: 0 0 8px; color: var(--glass-ink-2); font-size: 12.5px; line-height: 1.5 }
.cm-fields { display: flex; flex-direction: column; gap: 9px }
.cm-modal input { height: 38px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--glass-brd);
  background: var(--cm-field); color: var(--glass-ink); font: inherit; outline: none }
.cm-modal input:focus { border-color: var(--comment); box-shadow: 0 0 0 3px var(--comment-ring) }
.cm-err { color: #b42318; font-size: 12px }
.cm-chip { height: 38px; box-sizing: border-box; padding: 0 14px; border-radius: 999px;
  border: 1px solid transparent; background: var(--glass-hover);
  display: flex; align-items: center; justify-content: space-between; gap: 10px; overflow: hidden }
.cm-div { border: 0; height: 1px; background: var(--glass-brd); margin: 1px 2px; align-self: stretch }
.cm-chip b { font-weight: 500; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.cm-chip span { font-size: 10.5px; font-weight: 600; letter-spacing: .04em; color: var(--glass-ink-3); flex: none }
.cm-idrow { display: flex; align-items: center; gap: 10px }
.cm-pfp { width: 44px; height: 44px; border-radius: 50%; border: 1.5px dashed var(--glass-ink-3);
  background: var(--cm-field); color: var(--glass-ink-3); flex: none; overflow: hidden;
  display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0;
  transition: border-color .15s, color .15s }
.cm-pfp:hover { border-color: var(--comment); color: var(--comment) }
.cm-pfp.set { border-style: solid; border-color: var(--glass-brd) }
/* the photo is a REAL img filling the clipped circle - background-image layering left
   uncovered edges */
.cm-pfp img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block }
.cm-row { display: flex; gap: 8px; margin-top: 12px }
.cm-row button:disabled, .cm-row button.cm-primary:disabled {
  background: var(--glass-ink-3); color: var(--glass); cursor: default; opacity: 1 }
.cm-switch { margin: 2px auto 0; border: 0; background: none; padding: 4px 8px; cursor: pointer;
  font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); border-radius: 999px }
.cm-switch:hover { color: var(--glass-ink); background: var(--glass-hover) }
.cm-row button { height: 36px; padding: 0 16px; border-radius: 999px; border: 1px solid var(--glass-brd);
  background: none; color: var(--glass-ink); font: 600 12.5px -apple-system, system-ui, sans-serif; cursor: pointer }
.cm-row button:hover { background: var(--glass-hover) }
.cm-row button.cm-primary { background: var(--glass-ink); color: var(--glass); border-color: transparent; flex: 1 }
.cm-row button.cm-primary:hover { opacity: .88 }

/* the dev identity door: your avatar in the composer opens the profile popover. Unset shows a
   quiet + badge - the whole first-comment nudge, no modal in the way. */
.cm-me { position: relative; display: inline-flex; flex: none }
.cm-mebtn { position: relative; display: inline-flex; padding: 0; border: 0; background: none;
  cursor: pointer; border-radius: 50% }
/* hover morphs the avatar into a pen on quiet gray - "this is editable" without a badge */
.cm-pen-face { position: absolute; inset: 0; border-radius: 50%; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--glass-ink) 10%, var(--cm-field));
  border: 1px solid var(--glass-brd); color: var(--glass-ink-2);
  opacity: 0; transition: opacity .12s; pointer-events: none }
.cm-mebtn:hover .cm-pen-face, .cm-mebtn:focus-visible .cm-pen-face { opacity: 1 }

/* the unclipped comment plane over each frame: itself transparent to the pointer,
   its children (pins, cards, stacks) fully interactive */
.cm-layer { position: absolute; left: 0; width: 100%; pointer-events: none; z-index: 25 }
.cm-layer > * { pointer-events: auto }

/* v1.1: an unseen mention of YOU pulses the pin - accent lights until the
   thread is opened (opening marks it seen). Motion-reduced readers keep a
   steady accent ring instead of the pulse. */
.cm-pin.working { box-shadow: 0 0 0 1.5px var(--mv-blue), 0 2px 8px -2px rgba(0, 0, 0, .25) }
.cm-pin.mention, .cm-stack.mention { outline: 2px solid var(--accent); outline-offset: 1px;
  animation: cm-mention-pulse 1.7s ease-out infinite }
@keyframes cm-mention-pulse {
  0% { box-shadow: 0 0 0 0 var(--accent-ring), 0 0 0 0 rgba(0, 136, 255, .45) }
  70% { box-shadow: 0 0 0 6px rgba(0, 136, 255, 0), 0 0 0 12px rgba(0, 136, 255, 0) }
  100% { box-shadow: 0 0 0 0 rgba(0, 136, 255, 0), 0 0 0 0 rgba(0, 136, 255, 0) }
}
@media (prefers-reduced-motion: reduce) {
  .cm-pin.mention, .cm-stack.mention { animation: none }
}
/* a mention of YOU inside a thread: the loudest chip - accent, heavier */
.cm-at.person.me { color: var(--accent); font-weight: 700 }

/* human notification pill: the author's face, then "name mentioned you".
   The face outsizes the agent mark (34px) on purpose - a person is the news. */
.sh-jam-ava { width: 36px; height: 36px; border-radius: 999px; object-fit: cover; flex: none }
.sh-jam-ava.init { display: inline-flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,.92); font: 700 13px/1 -apple-system, system-ui, sans-serif; letter-spacing: .02em }
/* the title row is flex, which swallows the JSX whitespace - the verb carries its own gap */
.sh-jam-frame .v { color: var(--glass-ink-2); font-weight: 500; margin-left: 4px; flex: none }

/* v1.5 slides mode: the slim progress strip + the zero-chrome escape hatch */
.sh-slides-strip { position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%); z-index: 30;
  display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-radius: 999px;
  background: var(--glass); border: 1px solid var(--glass-brd); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur) }
.sh-slides-strip .n { font: 600 12px/1 -apple-system, system-ui, sans-serif; color: var(--glass-ink-2); white-space: nowrap }
.sh-slides-strip .bar { width: 140px; height: 3px; border-radius: 999px; background: var(--glass-hover); overflow: hidden }
.sh-slides-strip .bar i { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width .25s ease }
@media (max-width: 480px) { .sh-slides-strip .bar { width: 80px } }


/* ---- sticky notes (spec 18): the yellow column left of a frame ------------------------------
   World-sized (it scales with the canvas, like the artwork); the fold's hit target keeps a screen
   minimum through --sh-inv. Yellow in both shell themes - a sticky is yellow. */
.sh-node { --note-bg: #fff3a3; --note-bg-2: #ffeb85; --note-ink: #2b2500; --note-dim: rgba(43, 37, 0, .62);
  --note-line: rgba(107, 90, 0, .28); --note-link: #7a4d00; --note-fold: #e9cf5e; --note-fold-2: #c9ae3c }
/* dark canvas: a deeper mustard so the paper reads as paper, not as a highlight; ink darker for contrast */
.sh-node[data-theme="dark"] { --note-bg: #e6c94f; --note-bg-2: #d6b73c; --note-ink: #1f1a00; --note-dim: rgba(31, 26, 0, .68);
  --note-line: rgba(70, 56, 0, .35); --note-link: #5c3a00; --note-fold: #c9aa33; --note-fold-2: #8f7518 }
.sh-notes { position: absolute; right: 100%; top: 0; margin-right: 24px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 12px; pointer-events: none }
.sh-notes.below-vbadge { top: 72px }
.sh-notes > * { pointer-events: auto }
.sh-sticky { position: relative; box-sizing: border-box; background: var(--note-bg); color: var(--note-ink);
  border-radius: 2px 10px 2px 2px; padding: 14px 16px 12px;
  box-shadow: 0 1px 2px rgba(60, 45, 0, .18), 0 6px 18px -6px rgba(60, 45, 0, .35);
  font: 400 13px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  transform-origin: top right; opacity: 1; visibility: visible;
  transition: transform .18s cubic-bezier(.2, .7, .3, 1), opacity .16s ease, visibility 0s linear 0s;
  user-select: text; -webkit-user-select: text; cursor: default }
.sh-sticky[data-sticky="scene"] { padding: 18px 20px 16px; font-size: 14px }
.sh-notes.off .sh-sticky { transform: scale(.04); opacity: 0; visibility: hidden;
  transition: transform .18s cubic-bezier(.4, 0, .8, .4), opacity .14s ease .04s, visibility 0s linear .18s; pointer-events: none }
/* the dog-ear: on the column it is the top sticky's folded corner; folded, it is the tab that stays */
.sh-notes-fold { position: absolute; top: 0; right: 0; z-index: 2; padding: 0; border: 0; cursor: pointer;
  width: clamp(22px, calc(14px * var(--sh-inv, 1)), 72px); height: clamp(22px, calc(14px * var(--sh-inv, 1)), 72px);
  border-radius: 0 10px 0 4px;
  background: linear-gradient(225deg, transparent 50%, var(--note-fold) 50%, var(--note-fold-2) 100%);
  transition: background .18s ease, border-radius .18s ease, box-shadow .18s ease, transform .18s ease }
.sh-notes-fold:hover { filter: brightness(.96) }
.sh-notes-fold:focus-visible { outline: 2px solid var(--accent, #2f6df6); outline-offset: 2px }
.sh-notes.off .sh-notes-fold { border-radius: 3px 3px 3px 8px; background: linear-gradient(160deg, var(--note-bg) 0%, var(--note-bg-2) 100%);
  box-shadow: 0 1px 2px rgba(60, 45, 0, .25), 0 3px 8px -2px rgba(60, 45, 0, .35) }
.sh-notes.off .sh-notes-fold::after { content: ""; position: absolute; right: 0; top: 0; width: 38%; height: 38%;
  border-radius: 0 3px 0 3px; background: linear-gradient(225deg, transparent 50%, var(--note-fold-2) 50%) }
@media (prefers-reduced-motion: reduce) { .sh-sticky, .sh-notes-fold { transition: none } }
/* comment mode: hover names the element the click would pick; the lock is the shell's own outline */
body.sh-commenting .sh-sticky-body :is(p, li, h1, h2, h3, h4, blockquote, pre, img, table, .sh-sticky-diagram):hover { outline: 1.5px solid var(--accent, #2f6df6); outline-offset: 2px; border-radius: 3px }
body.sh-commenting .sh-sticky-body { cursor: crosshair }
.sh-sticky-body [data-sh-lock] { outline: 2px solid hsl(var(--cm-h, 48) 80% 42%); outline-offset: 3px; border-radius: 3px;
  box-shadow: 0 0 0 5px hsl(var(--cm-h, 48) 90% 60% / .28) }
/* prose: the Md block's vocabulary, sized for an aside */
.sh-sticky-body > :first-child { margin-top: 0 }
.sh-sticky-body > :last-child { margin-bottom: 0 }
.sh-sticky-body h1, .sh-sticky-body h2, .sh-sticky-body h3, .sh-sticky-body h4 { margin: 0 0 6px; line-height: 1.25; letter-spacing: -0.01em; text-wrap: balance }
.sh-sticky-body h1 { font-size: 1.28em; font-weight: 700 }
.sh-sticky-body h2 { font-size: 1.14em; font-weight: 650 }
.sh-sticky-body h3, .sh-sticky-body h4 { font-size: 1em; font-weight: 650 }
.sh-sticky-body p, .sh-sticky-body ul, .sh-sticky-body ol, .sh-sticky-body blockquote, .sh-sticky-body pre, .sh-sticky-body table { margin: 0 0 8px }
.sh-sticky-body ul, .sh-sticky-body ol { padding-left: 18px }
.sh-sticky-body li { margin: 2px 0 }
.sh-sticky-body li > ul, .sh-sticky-body li > ol { margin-bottom: 0 }
.sh-sticky-body blockquote { padding: 2px 0 2px 10px; border-left: 3px solid var(--note-line); color: var(--note-dim) }
.sh-sticky-body a { color: var(--note-link); text-decoration: underline; text-underline-offset: 2px; text-decoration-color: rgba(122, 77, 0, .45) }
.sh-sticky-body a:hover { text-decoration-color: currentColor }
.sh-sticky-body a[data-goto]::after { content: "\2197"; font-size: .8em; margin-left: 2px; text-decoration: none; display: inline-block }
.sh-sticky-body code { font: 500 .9em/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; background: rgba(43, 37, 0, .07); padding: 1px 4px; border-radius: 3px }
.sh-sticky-body pre { padding: 8px 10px; border-radius: 6px; background: rgba(43, 37, 0, .07); overflow-x: auto; white-space: pre }
.sh-sticky-body pre code { background: none; padding: 0; font-weight: 400 }
.sh-sticky-body pre.err { background: rgba(190, 40, 20, .1); color: #7a1f0f }
.sh-sticky-body hr { border: 0; border-top: 1px solid var(--note-line); margin: 10px 0 }
.sh-sticky-body img { max-width: 100%; border-radius: 4px; display: block }
.sh-sticky-body strong { font-weight: 650 }
.sh-sticky-body table { border-collapse: collapse; font-size: .92em; width: 100%; table-layout: auto }
.sh-sticky-body td, .sh-sticky-body th { overflow-wrap: anywhere }
.sh-sticky-body th, .sh-sticky-body td { border: 1px solid var(--note-line); padding: 3px 6px; text-align: left; vertical-align: top }
.sh-sticky-body th { font-weight: 650; background: rgba(43, 37, 0, .05) }
.sh-sticky-body input[type="checkbox"] { margin: 0 6px 0 0; vertical-align: -1px }
.sh-sticky-body .mv-md-noimg { color: var(--note-dim); font-style: italic }
.sh-sticky-body .mv-c-blue { color: #0070d6 } .sh-sticky-body .mv-c-orange { color: #c9640a } .sh-sticky-body .mv-c-purple { color: #9a23ad }
.sh-sticky-body .mv-c-green { color: #1a8a3f } .sh-sticky-body .mv-c-red { color: #c72a22 } .sh-sticky-body .mv-c-gray { color: #6b7480 }
/* the hand-drawn diagram: the fence's place, the paper's colors, scaled to the column */
.sh-sticky-diagram { margin: 4px 0 10px; overflow: visible; display: flex; justify-content: center }
.sh-sticky-diagram svg { display: block; max-width: 100%; height: auto; margin: 0 auto;
  /* the canvas scales the world with a CSS transform, and Chrome lays SVG text out ONCE for the
     scale it was inserted at (a diagram born at 13 % zoom keeps 13 %-zoom glyph positions at
     140 %: labels drift, some vanish). geometricPrecision lays glyphs out scale-free - measured,
     research/notes/diagprobe5.ts */
  text-rendering: geometricPrecision }
.sh-sticky-diagram svg text, .sh-sticky-diagram svg tspan { text-rendering: geometricPrecision }

/* sidebar marks (spec 25, variant B - one slot): colour on the icon and title carries the state,
   blue new, orange needs you; the row's one right-hand slot holds the bubble or the dot. Their own
   tokens: the accent turns purple in interact mode, a mark never does */
.sh-panel .sub .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.mk-slot { flex: none; display: inline-flex; align-items: center; justify-content: center; min-width: 16px; margin-left: 6px; font-style: normal }
.sh-node-head .mk-slot { margin-left: 0 }
.mk-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--mk-new); flex: none }
.mk-bubble { flex: none; min-width: 16px; height: 15px; padding: 0 4px; border-radius: 8px 8px 8px 2px;
  background: var(--mk-ask); color: #fff; font: 700 10px/15px -apple-system, system-ui, sans-serif; font-style: normal;
  text-align: center; font-variant-numeric: tabular-nums }
.mk-bubble.hollow { background: transparent; color: var(--mk-ask); box-shadow: inset 0 0 0 1.5px var(--mk-ask) }
.sh-panel .sub.mk-new, .sh-panel .sub.mk-new .nm { color: var(--mk-new); font-weight: 600 }
.sh-panel .sub.mk-new .iicon, .sh-panel .sub.mk-new .chip { color: var(--mk-new); opacity: 1 }
.sh-panel .sub.mk-ask .iicon, .sh-panel .sub.mk-ask .chip { color: var(--mk-ask); opacity: 1 }
/* a selected variant's chip is filled with the accent: its letter stays white - the bubble carries the mark */
.sh-panel .sub.mk-new .chip.on, .sh-panel .sub.mk-ask .chip.on { color: #fff }
.sh-panel .it.board.mk-new { color: var(--mk-new) }
.sh-panel .it.board.mk-new > .sh-live-ic svg, .sh-panel .it.board.mk-new > svg { color: var(--mk-new) }
.sh-panel .it.board.mk-ask > .sh-live-ic svg, .sh-panel .it.board.mk-ask > svg { color: var(--mk-ask) }
.sh-panel .it small.mk-fresh { color: var(--mk-new); font-weight: 700 }
.sh-node-head.mk-new .id { color: var(--mk-new) }

/* ============================== Jam V2 (spec 27): captures, the lane, the focus panel ==============================
   Ported from the approved hi-fi (platform canvas design/scenes/jam/_jam.css), in the shell's tokens. Recording is
   teal (--jm-rec); red is for failures only; colour lives in the state glyph. */
.sh-app {
  /* recording (round 3): Apple's system teal - red stays for errors and failures. `strong` is the
     increased-contrast teal, for fills that carry white text (the numbered points) */
  --jm-rec: #00c3d0;
  --jm-rec-strong: #008198;
  --jm-rec-on: #fff;
  --jm-rec-ring: rgba(0, 195, 208, .26);
  --jm-rec-wash: rgba(0, 195, 208, .12);
  --jm-err: #e5484d;
  /* the lane: 44px tiles + 12px air. The lane runs the full width, so everything else on the bottom edge
     (the Update pill, toasts, notices) rises by this much while it shows */
  --jm-lane: 56px;
}
.sh-app.dark, .jm-stage {
  --jm-rec: #00d2e0; --jm-rec-strong: #00d2e0; --jm-rec-on: #04252a;
  --jm-rec-ring: rgba(0, 210, 224, .28); --jm-rec-wash: rgba(0, 210, 224, .14) }


/* ---- shared: the glass recipe + edge light, for Jam's PANELS (read-back, review, sheets, caption) ---- */
.jm-panel {
  background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-brd); box-shadow: var(--shadow-glass); position: relative;
  color: var(--glass-ink); user-select: none; -webkit-user-select: none;
  font-family: -apple-system, system-ui, sans-serif }
.jm-panel::after {
  content: ''; position: absolute; inset: -1px; padding: 1px; border-radius: inherit;
  background: var(--edge-light); pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude }
/* floating panels lift a little further off the canvas than the tiles (the comment card's drop) */
.jm-panel { box-shadow: var(--shadow-glass), 0 16px 40px -14px rgba(24, 24, 27, .3) }
.sh-app.dark .jm-panel { box-shadow: var(--shadow-glass), 0 18px 44px -14px rgba(0, 0, 0, .6) }


/* ---- the TILE: Jam's one bottom-edge material (v2). No bar holds the items: each one floats on its own -
   much more transparent than the shell's glass, a strong backdrop blur so text reads over any frame, a
   glaze (top highlight + a thin light rim) and a teeny shadow. Colour lives in the state glyph only. ---- */
.sh-app {
  --jm-tile: rgba(255, 255, 255, .6);
  --jm-tile-hover: rgba(255, 255, 255, .78);
  --jm-tile-glaze: linear-gradient(180deg, rgba(255, 255, 255, .55), rgba(255, 255, 255, .08) 55%, rgba(255, 255, 255, 0));
  --jm-tile-blur: blur(18px) saturate(180%);
  --jm-tile-shadow: inset 0 0 0 .5px rgba(255, 255, 255, .75), inset 0 1px 0 rgba(255, 255, 255, .9),
    0 0 0 .5px rgba(24, 24, 27, .09), 0 1px 1.5px rgba(24, 24, 27, .06), 0 3px 8px -4px rgba(24, 24, 27, .14);
  --jm-r: 11px }
.sh-app.dark, .jm-stage {
  --jm-tile: rgba(34, 34, 42, .62);
  --jm-tile-hover: rgba(52, 52, 62, .76);
  --jm-tile-glaze: linear-gradient(180deg, rgba(255, 255, 255, .09), rgba(255, 255, 255, .015) 55%, rgba(255, 255, 255, 0));
  --jm-tile-shadow: inset 0 0 0 .5px rgba(255, 255, 255, .1), inset 0 1px 0 rgba(255, 255, 255, .1),
    0 0 0 .5px rgba(0, 0, 0, .4), 0 1px 1.5px rgba(0, 0, 0, .25), 0 3px 8px -4px rgba(0, 0, 0, .45) }
.jm-card, .jm-chip {
  background: var(--jm-tile-glaze), var(--jm-tile); backdrop-filter: var(--jm-tile-blur); -webkit-backdrop-filter: var(--jm-tile-blur);
  box-shadow: var(--jm-tile-shadow); border: 0; border-radius: var(--jm-r); position: relative;
  user-select: none; -webkit-user-select: none; font-family: -apple-system, system-ui, sans-serif }
.jm-card:hover { background: var(--jm-tile-glaze), var(--jm-tile-hover) }


/* ---- the lane: full width from the bottom-left corner, items left to right, scrolls sideways - the
   run's captures in the order made, the one recording now last at the right end (never cut) ---- */
.jm-lane { position: absolute; left: var(--edge); right: var(--edge); bottom: var(--edge); z-index: 31; display: flex; pointer-events: none; min-width: 0 }
.jm-lane-in { display: flex; align-items: center; gap: 10px; min-width: 0; max-width: 100%; overflow-x: auto; overflow-y: hidden; pointer-events: auto;
  padding: 6px 4px; margin: -6px -4px; scrollbar-width: none; overscroll-behavior-x: contain }   /* room for the tiles' shadow inside the scroller */
.jm-lane-in::-webkit-scrollbar { display: none }
/* the edge fades: two strips BESIDE the scroller, never a mask on it - a masked ancestor is a backdrop root,
   and every tile inside it would lose its blur (0.26.2: the lane was unreadable exactly when it was full).
   Each strip blurs what is under it and tints it toward the ground, under its own mask (its own mask leaves
   its own backdrop filter alone). */
.jm-lane-edge { position: absolute; top: -6px; bottom: -6px; width: 56px; pointer-events: none; z-index: 1;
  background: linear-gradient(90deg, var(--ground), transparent); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  -webkit-mask: linear-gradient(90deg, #000, transparent); mask: linear-gradient(90deg, #000, transparent) }
.jm-lane-edge.l { left: -4px }
.jm-lane-edge.r { right: -4px; transform: scaleX(-1) }
.jm-lane .jm-chip { flex: none }                           /* the recording tile: last, whole */

/* ---- the toolbar's Jam button (between Laser and Tidy). No blue while a session runs: blue is hover and
   press only (the shell's own pill states). The session reads as the waveform + minutes, in ink; while a
   capture records, a teal dot pulses in the waveform's place. ---- */
.sh-pill-btn.jm-hover { background: var(--glass-hover); color: var(--glass-ink) }
.sh-pill-btn.jm-jam.live, .sh-pill-btn.jm-jam.rec { gap: 7px; padding: 0 12px 0 11px; color: var(--glass-ink-2); background: none }
.sh-pill-btn.jm-jam.live.jm-hover, .sh-pill-btn.jm-jam.rec.jm-hover { background: var(--glass-hover); color: var(--glass-ink) }
.sh-pill-btn.jm-jam.press { background: var(--glass-accent-bg); color: var(--glass-accent) }
.sh-pill-btn.jm-jam.rec .jm-clock { color: var(--glass-ink) }
/* in play: the dark pill's own ink */
.sh-play-pill .sh-pill-btn.jm-jam.live, .sh-play-pill .sh-pill-btn.jm-jam.rec { background: none; color: rgba(245, 245, 247, .82) }
/* the collapsed toolbar keeps the recording dot on its corner (only while a capture records) */
.sh-pill-fab .jm-fab-dot { position: absolute; right: 8px; top: 8px; width: 6px; height: 6px }
.jm-live-dot { position: relative; width: 8px; height: 8px; border-radius: 50%; background: var(--jm-rec); flex: none }
.jm-live-dot::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: var(--jm-rec);
  animation: jm-pulse 1.6s cubic-bezier(.2, .6, .3, 1) infinite }
@keyframes jm-pulse { 0% { transform: scale(1); opacity: .55 } 80%, 100% { transform: scale(2.6); opacity: 0 } }
.jm-clock { font: 600 12px -apple-system, system-ui, sans-serif; font-variant-numeric: tabular-nums }
.sh-pill-btn.jm-jam .jm-nomic { color: var(--glass-ink-2) }

/* ---- a capture's tile (round 3): two lines, a little squarer - glyph | title over a status line
   ("Ready to review", "Agent working · 0:41", "Done · 1 frame changed"). Colour only in the glyph. ---- */
.jm-card { display: inline-flex; align-items: center; gap: 10px; height: 44px; width: 216px; flex: none;   /* one width: a tile never resizes */
  padding: 0 14px 0 12px; border-radius: 10px; color: var(--glass-ink); text-align: left; cursor: pointer }
.jm-card .jm-st { flex: none }
.jm-card .tx { display: flex; flex-direction: column; gap: 1px; min-width: 0 }
.jm-card .t { min-width: 0; font: 500 12.5px/16px -apple-system, system-ui, sans-serif; letter-spacing: -.005em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.jm-card .m { min-width: 0; font: 500 11px/14px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums }
.jm-card .x { flex: none; display: inline-flex; color: var(--glass-ink-3); margin-left: auto }
.jm-card.review .m { color: var(--glass-ink-2) }
/* the Done fold (0.26.1): the group tile, the narrow collapse tile that leads the opened done tiles, and their slide */
.jm-card.close { width: auto; gap: 6px; padding: 0 12px; color: var(--glass-ink-2) }
.jm-card.close .t { font: 600 12px -apple-system, system-ui, sans-serif }
.jm-card.unfold { animation: jm-unfold .16s cubic-bezier(.2, .7, .3, 1) both }
@keyframes jm-unfold { from { transform: translateX(-14px); opacity: 0 } }
@media (prefers-reduced-motion: reduce) { .jm-card.unfold { animation: none } }
.jm-card.queued .t, .jm-card.confirming .t { color: var(--glass-ink-2) }
.jm-card.done .t, .jm-card.kept .t { color: var(--glass-ink-3) }
.jm-card.held { color: var(--glass-ink-3) }
.jm-card.held .jm-st { opacity: .55 }
.jm-card.ghost { opacity: .35 }
/* selected (clicked, or Q's focus): the ONE place blue shows on the lane - a 2px accent ring round the tile */
.jm-card.focus { color: var(--glass-ink); border-radius: 10px;
  box-shadow: var(--jm-tile-shadow), 0 0 0 2px var(--accent), 0 0 0 5px var(--accent-ring) }

/* a tile's Rename, in place of its menu */
.jm-rename { padding: 6px }
.jm-rename input { width: 100%; height: 30px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--glass-brd); background: var(--glass-hover);
  color: var(--glass-ink); font: 500 12.5px -apple-system, system-ui, sans-serif; outline: none }
.jm-rename input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring) }

/* ---- the capture: an edge ring round the window, the chip, the caption, points ---- */
.jm-edge { position: absolute; inset: var(--mv-top, 0px) 0 0 0; pointer-events: none; z-index: 40;
  box-shadow: inset 0 0 0 2px var(--jm-rec), inset 0 0 0 6px var(--jm-rec-ring) }
/* the capture recording NOW (round 3): the last tile of the lane, two lines like the others - a pulsing
   teal dot, "Capturing" and the timer over what it holds so far - then Stop. A little wider, never cut. */
.jm-chip { display: inline-flex; align-items: center; gap: 8px; height: 44px; padding: 0 6px 0 12px; flex: none; border-radius: 10px;
  font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2); white-space: nowrap }
.jm-chip .tx { display: flex; flex-direction: column; gap: 1px; min-width: 0 }
.jm-chip .lead { display: inline-flex; align-items: center; gap: 7px; font: 600 12.5px/16px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-chip .time { font-weight: 600; color: var(--glass-ink-2); font-variant-numeric: tabular-nums }
.jm-chip .stats { display: inline-flex; align-items: center; gap: 9px; font: 500 11px/14px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
.jm-chip .sep { width: 1px; height: 24px; background: color-mix(in srgb, var(--glass-ink) 10%, transparent); margin: 0 2px; flex: none }
.jm-chip .stat { display: inline-flex; align-items: center; gap: 3px; color: var(--glass-ink-3); font-variant-numeric: tabular-nums }
.jm-chip .stat svg { color: var(--glass-ink-3) }
.jm-chip .stat.warn { color: var(--glass-warn) }
.jm-chip .stat.warn svg { color: var(--glass-warn) }
.jm-chip .tag { display: inline-flex; align-items: center; gap: 4px; color: var(--glass-ink-2) }
.jm-chip .tag svg { color: var(--glass-ink-3) }
.jm-chip .stop { display: inline-flex; align-items: center; justify-content: center; gap: 5px; height: 30px; padding: 0 9px; flex: none; border: 0;
  border-radius: 7px; background: none; color: var(--glass-ink-2); cursor: pointer; font: 500 11px -apple-system, system-ui, sans-serif }
.jm-chip .stop svg { color: var(--jm-rec) }
.jm-chip .stop kbd { font: 500 10.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); background: none; border: 0; padding: 0 }
.jm-chip .stop:hover { background: var(--glass-hover); color: var(--glass-ink) }
.jm-chip .stop:disabled svg { color: var(--glass-ink-3) }
.jm-chip.finishing .time { color: var(--glass-ink-2) }
/* a session between captures (trial 2): still on - the same dot - and Capture (S) starts the next */
.jm-chip.between .stats { gap: 5px }
.jm-chip .go { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 30px; padding: 0 9px; flex: none; border: 0;
  border-radius: 7px; background: none; font: 600 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink); cursor: pointer }
.jm-chip .go::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--jm-rec); flex: none }
.jm-chip .go kbd { font: 500 10.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); background: none; border: 0; padding: 0 }
.jm-chip .go:hover { background: var(--glass-hover) }

/* points: screen-constant markers (scale by --sh-inv inside a World) */
.jm-pt { position: absolute; transform: translate(-50%, -50%) scale(var(--sh-inv, 1)); display: inline-flex; align-items: center;
  justify-content: center; width: 20px; height: 20px; border-radius: 50%; z-index: 6; pointer-events: none;
  font: 700 11px/1 -apple-system, system-ui, sans-serif; font-variant-numeric: tabular-nums }
.jm-pt.pick { background: var(--jm-rec-strong); color: var(--jm-rec-on); box-shadow: 0 0 0 2px var(--solid), 0 2px 6px rgba(24, 24, 27, .3) }
.jm-pt.click { background: var(--solid); color: var(--jm-rec-strong); box-shadow: inset 0 0 0 2px var(--jm-rec), 0 0 0 1.5px var(--solid), 0 2px 6px rgba(24, 24, 27, .25) }
.jm-pt.hover { width: 16px; height: 16px; background: none; border: 1.5px dashed color-mix(in srgb, var(--jm-rec) 70%, transparent) }
/* the dwell's centre: a solid red dot, so the ring never reads as a spinner or a status glyph */
.jm-pt.hover::after { content: ''; width: 4px; height: 4px; border-radius: 50%; background: var(--jm-rec) }
/* the element a pick landed on (world box, screen-constant line) */
.jm-pickbox { position: absolute; border-radius: 6px; pointer-events: none; z-index: 5;
  box-shadow: 0 0 0 calc(1.5px * var(--sh-inv, 1)) var(--jm-rec), 0 0 0 calc(5px * var(--sh-inv, 1)) var(--jm-rec-ring) }


/* ---- panels: read-back, review card, sheets ---- */
.jm-panel { display: flex; flex-direction: column; gap: 12px; padding: 16px; border-radius: 20px;
  font: 400 13px -apple-system, system-ui, sans-serif; letter-spacing: -.005em; white-space: normal }
.jm-panel h3 { margin: 0; font: 600 14px -apple-system, system-ui, sans-serif; letter-spacing: -.01em; color: var(--glass-ink) }
.jm-panel .hd { font: 600 11px -apple-system, system-ui, sans-serif; letter-spacing: .02em; color: var(--glass-ink-3) }
.jm-panel .dim { color: var(--glass-ink-3); font-size: 11.5px; font-variant-numeric: tabular-nums }
.jm-panel p { margin: 0; line-height: 1.5; color: var(--glass-ink-2) }
.jm-panel .top { display: flex; align-items: center; gap: 8px; min-height: 24px }
.jm-panel .top h3 { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.jm-panel .meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: -6px;
  font: 500 11.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); font-variant-numeric: tabular-nums }
.jm-panel .meta i { width: 2px; height: 2px; border-radius: 1px; background: currentColor; opacity: .7 }
.jm-panel .row { display: flex; align-items: center; gap: 9px; min-height: 30px; padding: 0 8px; border-radius: 8px;
  font: 500 13px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-panel .row > svg { flex: none; color: var(--glass-ink-3) }
.jm-panel .row .v { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; color: var(--glass-ink-2); font-weight: 500; font-size: 12px }
.jm-panel .row small { color: var(--glass-ink-3); font: 500 11.5px -apple-system, system-ui, sans-serif }
.jm-panel .rows { display: flex; flex-direction: column; margin: 0 -8px }
.jm-panel .actions { display: flex; align-items: center; gap: 6px }
.jm-panel .actions .sp { flex: 1 }
.jm-panel kbd { font: 500 10.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); background: none; border: 0; padding: 0 }
.jm-panel .rule { height: 1px; background: var(--glass-brd); margin: 0 -16px }
.jm-panel code, .jm-code { font: 500 11px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--glass-ink-3) }
.jm-panel .note-line { display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px; border-radius: 10px;
  font: 500 12px/1.45 -apple-system, system-ui, sans-serif }
.jm-panel .note-line svg { flex: none; margin-top: 1px }
.jm-panel .note-line.warn { background: var(--card-warn-bg); color: var(--card-warn-ink) }
.jm-panel .note-line.err { background: var(--card-err-bg); color: var(--card-err-ink) }
.jm-panel .note-line.info { background: var(--glass-hover); color: var(--glass-ink-2) }
.jm-panel .note-line.info svg { color: var(--glass-ink-3) }
.jm-ic { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 999px; flex: none;
  background: var(--glass-hover); color: var(--glass-ink-2) }
.jm-ic.blue { background: color-mix(in srgb, var(--mv-blue) 13%, transparent); color: var(--mv-blue) }
.jm-ic.err { background: var(--card-err-bg); color: var(--card-err-ink) }
.jm-ic.warn { background: var(--card-warn-bg); color: var(--card-warn-ink) }
.jm-iconbtn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border: 0; border-radius: 8px;
  background: none; color: var(--glass-ink-3); cursor: pointer; flex: none }
.jm-iconbtn:hover { background: var(--glass-hover); color: var(--glass-ink) }
.jm-iconbtn:disabled { opacity: .4 }

/* the transcript: time | glyph | line */
.jm-lines { display: flex; flex-direction: column; gap: 3px; font: 400 12px/1.5 -apple-system, system-ui, sans-serif; color: var(--glass-ink-2) }
.jm-lines > div { display: grid; grid-template-columns: 30px 16px 1fr; gap: 6px; align-items: baseline }
.jm-lines .ts { font: 500 11px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); font-variant-numeric: tabular-nums }
.jm-lines .g { color: var(--glass-ink-3); display: inline-flex; transform: translateY(2px) }
.jm-lines .words { color: var(--glass-ink); font-size: 13px }
.jm-lines .pt { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; border-radius: 50%; margin-right: 5px;
  font: 700 9.5px/1 -apple-system, system-ui, sans-serif; vertical-align: 1px }
.jm-lines .pt.pick { background: var(--jm-rec-strong); color: var(--jm-rec-on) }
.jm-lines .pt.click { box-shadow: inset 0 0 0 1.5px var(--jm-rec); color: var(--jm-rec-strong) }
.jm-lines code { margin-left: 4px }
.jm-lines .secret { letter-spacing: .1em; color: var(--glass-ink-3) }
.jm-added { display: flex; flex-direction: column; gap: 8px; margin-top: 10px }
.jm-added-rule { display: flex; align-items: center; gap: 8px; font: 500 11px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
.jm-added-rule::before, .jm-added-rule::after { content: ''; flex: 1; height: 1px; background: color-mix(in srgb, var(--glass-ink) 10%, transparent) }
.jm-addnote { display: flex; gap: 8px; align-items: center }
.jm-addnote input { flex: 1; min-width: 0; height: 32px; padding: 0 10px; border-radius: 8px; border: 1px solid color-mix(in srgb, var(--glass-ink) 12%, transparent);
  background: var(--glass-field, #fff); color: var(--glass-ink); font: 400 13px -apple-system, system-ui, sans-serif; outline: none }
.jm-addnote input:focus { border-color: var(--glass-accent); box-shadow: 0 0 0 3px var(--glass-accent-bg) }
/* the editable words: the comment field's surface and the accent focus ring */
.jm-edit { padding: 8px 10px; margin: -4px -6px; border-radius: 10px; background: var(--cm-field); color: var(--glass-ink);
  box-shadow: 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-ring); font: 400 13px/1.5 -apple-system, system-ui, sans-serif }
.jm-edit .caret { display: inline-block; width: 1px; height: 15px; background: var(--accent); vertical-align: -3px; margin-left: 1px }

/* pictures: before/after pairs and capture thumbs */
.jm-shots { display: grid; grid-template-columns: 1fr 1fr; gap: 8px }
.jm-shot { display: flex; flex-direction: column; gap: 5px; min-width: 0 }
.jm-shot .pic { position: relative; aspect-ratio: 16 / 10; border-radius: 8px; overflow: hidden; border: 1px solid var(--glass-brd); background: var(--node-bg) }
.jm-shot .pic.none { background: none; border: 1px dashed var(--glass-ink-3); display: flex; align-items: center; justify-content: center;
  color: var(--glass-ink-3); font: 500 11px -apple-system, system-ui, sans-serif; gap: 5px }
.jm-shot .cap { font: 500 11px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
.jm-shot .cap b { color: var(--glass-ink-2); font-weight: 600 }
.jm-thumbs { display: flex; gap: 8px }
.jm-thumbs .jm-shot { width: 112px }
.jm-framehd { display: flex; align-items: center; gap: 6px; font: 600 11.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2) }
.jm-framehd svg { color: var(--glass-ink-3) }

/* the agent's reply in a panel */
.jm-reply { display: grid; grid-template-columns: 20px 1fr; gap: 9px; align-items: start }
.jm-reply p { font-size: 13px; line-height: 1.5; color: var(--glass-ink); display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden }
.jm-reply .cm-avatar { margin-top: 1px }
.jm-link { color: var(--glass-accent); font: 600 12px -apple-system, system-ui, sans-serif; cursor: pointer; white-space: nowrap }
.jm-flink { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 7px 0 6px; border-radius: 6px;
  background: var(--glass-hover); color: var(--glass-ink-2); font: 600 11px -apple-system, system-ui, sans-serif }
.jm-flink svg { color: var(--glass-ink-3) }
.jm-file { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 10px; background: var(--glass-hover);
  font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2) }
.jm-file svg { flex: none; color: var(--glass-ink-3) }
.jm-file code { color: var(--glass-ink) }
.jm-file .dim { margin-left: auto }

/* More work: the composer with a fixed @marver */
.jm-more { display: flex; align-items: center; gap: 6px; height: 38px; padding: 0 5px 0 13px; border-radius: 19px; background: var(--cm-field);
  box-shadow: 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-ring); font: 400 13px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-more .at { color: var(--mv-blue); font-weight: 700 }
.jm-more .txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.jm-more .ph { color: var(--glass-ink-3) }
.jm-more { padding-right: 13px }
.jm-more kbd { font: 500 11px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); background: none; border: 0; flex: none }

/* the capture's detail view: wide enough to read - pictures large, then the timeline */
.jm-readback { width: 520px }
.jm-readback .jm-thumbs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px }
.jm-readback .jm-thumbs .jm-shot { width: auto }
.jm-capglyph { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 7px; flex: none;
  background: var(--glass-hover); color: var(--glass-ink-2) }
.jm-lines b.ui { font-weight: 600; color: var(--glass-ink) }
.jm-sheet { width: 320px; border-radius: var(--r-panel) }
.jm-sheet code { white-space: nowrap }                  /* a path or package name never breaks mid-token */
.jm-wrapup { width: 440px; border-radius: var(--r-panel) }
.jm-review { width: 480px }


/* buttons inside panels: 34px pills; primary is Marver's blue (the Jam pill's View) */
.jm-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 32px; padding: 0 13px;
  border-radius: 999px; border: 1px solid var(--glass-brd); background: none; color: var(--glass-ink); cursor: pointer;
  font: 600 12px -apple-system, system-ui, sans-serif; white-space: nowrap }
.jm-btn:hover { background: var(--glass-hover) }
.jm-btn.primary { background: var(--mv-blue); border-color: transparent; color: #fff }
.jm-btn.primary:hover { filter: brightness(1.08) }
.jm-btn.ghost { border-color: transparent; color: var(--glass-ink-2) }
.jm-btn.ghost:hover { color: var(--glass-ink) }
.jm-btn kbd { color: inherit; opacity: .55; font: 500 11px -apple-system, system-ui, sans-serif }
.jm-btn:disabled { opacity: .45 }


/* ---- round 2 refinements of the capture tile (folded in from 06-capture / 08-capture-in-play) ----
   Stop is a small filled red square; the count that just moved gets a brief wash (wrap the lane in
   .jm-tick); the live words wear the tile material; in play the tile matches the navigator. */
.jm-chip .stop { gap: 6px; padding: 0 9px }
.jm-chip .stop svg { display: none }
.jm-chip .stop::before { content: ''; width: 8px; height: 8px; border-radius: 2px; background: var(--jm-rec); flex: none }
.jm-chip .stop:disabled::before { background: var(--glass-ink-3) }
.jm-stage .jm-chip { height: 40px; padding: 0 5px 0 14px; border-radius: 999px; background: rgba(18, 18, 24, .82);
  border: 1px solid rgba(255, 255, 255, .12); box-shadow: none; backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px) }
.jm-stage .jm-chip .note, .jm-stage .jm-chip .stop { height: 30px; border-radius: 999px }
.jm-stage .jm-chip .note { padding: 0 11px }
.jm-stage .jm-chip .stop { padding: 0 11px }

/* ---- a capture in a thread (round 3): the comment a confirmed capture leaves, labelled as one ---- */
.jm-capcm { display: flex; flex-direction: column; gap: 6px }
.jm-capcm .hd { display: flex; flex-wrap: wrap; align-items: center; column-gap: 6px; row-gap: 1px; font: 600 11.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2) }
.jm-capcm .hd > span { white-space: nowrap }
.jm-capcm .hd svg { color: var(--jm-rec) }
.jm-capcm .hd .dim { font-weight: 500; color: var(--glass-ink-3) }
.jm-capcm .w { font: 400 13px/1.45 -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-capcm .jm-tchip { margin-top: 2px }

/* "Finishing" after E is still the capture's own moment: its turning arc is teal, not the agent's blue */
.jm-chip.finishing .jm-st circle, .jm-chip.finishing .jm-st path { stroke: var(--jm-rec) }


/* the capture tile's Note button */
.jm-chip .notebtn { display: inline-flex; align-items: center; gap: 5px; height: 30px; padding: 0 9px; border: 0; border-radius: 7px; background: none;
  color: var(--glass-ink-2); font: 500 12px -apple-system, system-ui, sans-serif; cursor: pointer; flex: none }
.jm-chip .notebtn svg { color: var(--glass-ink-3) }
.jm-chip .notebtn b { min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--glass-hover); color: var(--glass-ink); font: 700 10.5px -apple-system, system-ui, sans-serif }
.jm-chip .notebtn kbd { font: 500 10.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); background: none; border: 0; padding: 0 }
.jm-chip .notebtn:hover { background: var(--glass-hover); color: var(--glass-ink) }
.jm-chip .notebtn.on { background: var(--glass-accent-bg); color: var(--glass-accent) }
.jm-chip .notebtn.on svg { color: var(--glass-accent) }
/* trial 2: open, the count and the key sit on white - blue on white, never grey on blue */
.jm-chip .notebtn.on b { background: #fff; color: var(--glass-accent); box-shadow: 0 0 0 .5px color-mix(in srgb, var(--glass-accent) 25%, transparent) }
.jm-chip .notebtn.on kbd { min-width: 16px; height: 16px; padding: 0 4px; border-radius: 5px; display: inline-flex; align-items: center; justify-content: center;
  background: #fff; color: var(--glass-accent); box-shadow: 0 0 0 .5px color-mix(in srgb, var(--glass-accent) 25%, transparent) }
/* the notes card */
.jm-notes { width: 340px; gap: 10px; padding: 14px }
.jm-notes .top h3 { flex: none }
.jm-notelist { display: flex; flex-direction: column; gap: 6px; font: 400 12.5px/1.45 -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-notelist > div { display: grid; grid-template-columns: 32px 1fr; gap: 6px }
.jm-notelist .ts { font: 500 11px/18px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); font-variant-numeric: tabular-nums }
.jm-notefield { min-height: 58px; padding: 9px 11px; border-radius: 10px; background: var(--cm-field); color: var(--glass-ink);
  box-shadow: 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-ring); font: 400 13px/1.45 -apple-system, system-ui, sans-serif }
.jm-notefield .ph { color: var(--glass-ink-3) }
.jm-notefield .caret { display: inline-block; width: 1px; height: 15px; background: var(--accent); vertical-align: -3px; margin-left: 1px }
.jm-notes .foot { display: flex; gap: 12px; justify-content: flex-end; font: 500 11px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
/* the focus panel: top edge to just above the lane; the panel inside fills it and its middle scrolls */
.jm-focus { position: absolute; top: calc(var(--mv-top, 0px) + var(--edge)); bottom: calc(var(--edge) + var(--jm-lane) + 2px); z-index: 31; display: flex }
.jm-focus > .jm-panel { width: 100%; height: 100%; min-height: 0 }
/* one big picture at a time: the frame tabs and a Before | After switch above it (B flips) */
.jm-fbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap }   /* a narrow window wraps the switch under the tabs */
.jm-fbar .sp { flex: 1 }
.jm-fbar kbd { font: 500 10.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); background: none; border: 0; padding: 0 4px 0 2px; align-self: center }
.jm-big { flex: 1; min-height: 0; display: flex }
.jm-big .jm-shot { width: 100% }
.jm-big .jm-shot .pic { aspect-ratio: 16 / 10 }
.jm-ftabs { display: flex; gap: 4px; padding: 3px; border-radius: 10px; background: var(--glass-hover); width: fit-content }
.jm-ftabs button { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border: 0; border-radius: 7px; background: none;
  color: var(--glass-ink-2); font: 500 12px -apple-system, system-ui, sans-serif; cursor: pointer }
.jm-ftabs button svg { color: var(--glass-ink-3) }
/* trial 2: a capture under review - its review, or the capture itself (in the panel's title row) */
.jm-ftabs.jm-panes { padding: 2px; margin-left: 4px; flex: none }
.jm-ftabs.jm-panes button { height: 22px; padding: 0 9px; font-size: 11.5px }
.jm-newtag { margin-left: 2px; padding: 1px 6px; border-radius: 999px; background: var(--glass-accent-bg); color: var(--glass-accent); font: 600 10px/14px -apple-system, system-ui, sans-serif }
.jm-ftabs button small { font: 500 10.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
.jm-ftabs button.on { background: var(--solid); color: var(--glass-ink); font-weight: 600; box-shadow: 0 1px 2px rgba(24, 24, 27, .12), 0 0 0 .5px var(--glass-brd) }
.jm-focus > .jm-readback .jm-thumbs { gap: 12px }
/* the review's big picture sits centred in a quiet well that takes the panel's spare height */
.jm-focus .jm-big { align-items: center; padding: 10px; border-radius: 14px; background: var(--glass-hover) }
/* in play the Note button is a pill like Stop beside it (the navigator material) */
.jm-stage .jm-chip .notebtn { height: 30px; border-radius: 999px; padding: 0 11px }

/* ---- the shell's own additions to the kit (real controls where the hi-fi drew pictures of them) ---- */
.jm-focus { flex-direction: column }
.jm-focus > .jm-panel { overflow: hidden }
.jm-focus-x { position: absolute; top: 14px; right: 14px; z-index: 1 }
/* the header leaves the close button its own room: "1 of 3", the arrows, then the X - never under it */
.jm-focus > .jm-panel > .top { padding-right: 34px }
/* "For Claude Code" stays on one line beside the actions */
.jm-focus .jm-panel .actions .dim { white-space: nowrap; flex: none }
/* the panel's middle scrolls; its head and its footer stay in view */
.jm-panel .jm-body { display: flex; flex-direction: column; gap: 12px; min-height: 0; overflow-y: auto; margin: 0 -16px; padding: 0 16px }
.jm-focus .jm-panel .jm-body { flex: 1 }
.jm-review .jm-big { min-height: 160px }
.jm-shot .pic img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top center }
/* the review's one big picture: the shot at its own proportions, centred in the well, never cropped */
.jm-big .jm-shot { height: 100% }
.jm-big .jm-shot .pic { aspect-ratio: auto; height: 100%; min-height: 140px; display: flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 0 }
.jm-big .jm-shot .pic img { width: auto; height: auto; max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 8px;
  box-shadow: 0 0 0 1px var(--glass-brd), 0 2px 10px -4px rgba(24, 24, 27, .18) }
.jm-big .jm-shot .pic.none { border: 1px dashed var(--glass-ink-3); border-radius: 8px }
/* before and after at once (0.26.1): side by side for a tall frame, stacked for a wide one - each a caption over its
   picture, both at the frame's own proportions */
.jm-big.pair { gap: 10px; align-items: stretch }
.jm-big.pair.side { flex-direction: row }
.jm-big.pair.stack { flex-direction: column }
.jm-big.pair .jm-shot { flex: 1; min-width: 0; min-height: 0; height: auto; display: flex; flex-direction: column-reverse; gap: 4px }
.jm-big.pair .jm-shot .pic { flex: 1; min-height: 0; height: auto }
.jm-big.pair .jm-shot .cap { flex: none; height: 14px; font: 600 11px/14px -apple-system, system-ui, sans-serif; color: var(--glass-ink-2); text-align: center }
/* the editable words: a quiet hover says "click to edit" */
.jm-editable { margin: -6px -8px; padding: 6px 8px; border-radius: 10px; cursor: text }
.jm-editable:hover { background: var(--glass-hover) }
.jm-edited { display: inline-flex; align-items: center; gap: 5px; margin-bottom: 6px; font: 600 11px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
textarea.jm-edit { display: block; width: 100%; box-sizing: border-box; margin: 0; border: 0; outline: 0; resize: vertical }
textarea.jm-notefield { display: block; width: 100%; box-sizing: border-box; border: 0; outline: 0; resize: none }
textarea.jm-notefield::placeholder, .jm-more textarea.txt::placeholder { color: var(--glass-ink-3) }
.jm-more { height: auto; min-height: 38px; padding: 4px 5px 4px 13px }
.jm-more textarea.txt { flex: 1; min-width: 0; border: 0; outline: 0; resize: none; background: none; padding: 7px 0; color: inherit;
  font: 400 13px/1.4 -apple-system, system-ui, sans-serif; white-space: pre-wrap; overflow: hidden }
.jm-send { display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 11px; border: 0; border-radius: 999px; flex: none;
  background: var(--mv-blue); color: #fff; font: 600 12px -apple-system, system-ui, sans-serif; cursor: pointer }
.jm-send kbd { color: inherit; opacity: .6; font: 500 11px -apple-system, system-ui, sans-serif; background: none; border: 0; padding: 0 }
.jm-send:disabled { opacity: .45; cursor: default }
button.jm-link { padding: 0; border: 0; background: none; text-align: left; width: fit-content }
.jm-lines .miss { color: var(--glass-ink-3); font-style: italic }
.jm-chip .notebtn:disabled { opacity: .45; cursor: default }
@media (prefers-reduced-motion: reduce) { .jm-live-dot::after { animation: none } }

/* Jam V2: while the lane shows, the sidebar stops above it and the bottom edge rises one lane - the
   Update pill, toasts and notices (LANE_H, jam-lane.tsx) */
.sh-app.jm-lane-on .sh-panel { max-height: calc(100% - 2 * var(--edge) - 56px - var(--mv-top, 0px)); bottom: auto }
.sh-app.jm-lane-on .sh-update { bottom: calc(var(--edge) + 56px) }
.sh-app.jm-lane-on .sh-toasts { bottom: calc(var(--edge) + 56px) }
.sh-app.jm-lane-on .sh-banner { bottom: calc(var(--edge) + 56px) }
/* the canvas stopped (spec 28 A1.11): on the toolbar's centre line in the gap between the sidebar and the
   toolbar, or just below the toolbar row - placed by the shell (App.tsx placeBanner), which measures both; above
   play and focus. The fallback before it measures: top centre, on the line (34px tall, the row 46px) */
.sh-app .sh-banner.sh-stopped { top: calc(var(--mv-top, 0px) + var(--edge) + 6px); bottom: auto; left: 50%; right: auto; transform: translateX(-50%);
  z-index: 40; width: max-content; max-width: none; white-space: nowrap; text-align: center; text-wrap: balance; pointer-events: auto }
.sh-banner.sh-stopped code { font: 500 11.5px/14px ui-monospace, SFMono-Regular, Menlo, monospace; padding: 1px 5px; border-radius: 5px;
  background: color-mix(in srgb, currentColor 11%, transparent); white-space: nowrap }
.sh-banner.sh-stopped .kept { color: var(--glass-ink-2) }
.sh-banner.sh-stopped:is([data-at="stack"], [data-at="below"]) .dot { display: none }
.sh-banner.sh-stopped:is([data-at="stack"], [data-at="below"]) .kept { display: block }
/* over play and focus: the play chrome's dark skin (its pills, the navigator), warm light text - 13:1 */
.sh-banner.sh-stopped.dark { background: rgba(18, 18, 24, .86); border-color: rgba(255, 255, 255, .1); color: #ffd9a0;
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: 0 2px 10px rgba(0, 0, 0, .35) }   /* tight: never a smudge on the stage under it */
.sh-banner.sh-stopped.dark::after { display: none }
.sh-banner.sh-stopped.dark .kept { color: rgba(245, 245, 247, .78) }
/* a frame (or the stage) whose canvas is away shows another project's "another canvas" page: one calm line over
   it, in the frame's own theme - the banner says what happened, once. Screen-size text, never wider than its frame */
.sh-stranded { position: absolute; inset: 0; z-index: 2; display: grid; place-items: center; padding: 8%; container-type: size;
  background: var(--node-bg, var(--pdev-bg, #fff)); color: color-mix(in srgb, var(--head-ink, #18181b) 64%, var(--node-bg, #fff));
  pointer-events: none; text-align: center }
.sh-stranded span { font-family: -apple-system, system-ui, sans-serif; font-weight: 500; font-size: min(calc(12px * var(--sh-inv, 1)), 7cqi); line-height: 1.35 }
.sh-play .dev .sh-stranded { --node-bg: #fff; --head-ink: #18181b }
.sh-play .dev[data-theme="dark"] .sh-stranded { --node-bg: #0f1015; --head-ink: #ececf1 }
/* the tools that need the server, while the canvas is stopped: quiet, their tooltip says why */
.sh-pill-btn[data-stopped], .sh-pill-btn[data-stopped]:hover { opacity: .38; background: none; cursor: default }


/* ---- words on this Mac (spec 27 Part 4): the live caption over the capture tile, the one question ---- */
.jm-caption { display: flex; gap: 10px; align-items: flex-start; max-width: 420px; padding: 9px 14px 10px 12px; border-radius: 16px;
  background: var(--jm-tile-glaze), var(--jm-tile); backdrop-filter: var(--jm-tile-blur); -webkit-backdrop-filter: var(--jm-tile-blur);
  box-shadow: var(--jm-tile-shadow); font: 400 13px/1.45 -apple-system, system-ui, sans-serif; color: var(--glass-ink); pointer-events: none }
.jm-caption .old { color: var(--glass-ink-3) }
.jm-bars { display: inline-flex; align-items: center; gap: 2px; height: 14px; flex: none; margin-top: 2px }
.jm-bars i { width: 2px; border-radius: 1px; background: var(--jm-rec); animation: jm-bar 1s ease-in-out infinite }
.jm-bars i:nth-child(1) { height: 6px; animation-delay: -.2s } .jm-bars i:nth-child(2) { height: 12px; animation-delay: -.5s }
.jm-bars i:nth-child(3) { height: 8px; animation-delay: -.8s } .jm-bars i:nth-child(4) { height: 10px; animation-delay: -.35s }
@keyframes jm-bar { 50% { transform: scaleY(.45) } }
@media (prefers-reduced-motion: reduce) { .jm-bars i { animation: none } }
.jm-voiceask { width: 340px; gap: 10px; padding: 14px }
.jm-voiceask .top h3 { flex: 1 }
.jm-voiceask p { margin: 0; font: 400 12.5px/1.45 -apple-system, system-ui, sans-serif }
.jm-progress { height: 4px; border-radius: 2px; background: var(--glass-hover); overflow: hidden }
.jm-progress i { display: block; height: 100%; background: var(--jm-rec); transition: width .3s ease }
.jm-voiceask p.lead { color: var(--glass-ink); font-size: 13px }
/* checking: no percentage to show - a short bar that sweeps */
.jm-progress.busy i { width: 30%; animation: jm-sweep 1.1s ease-in-out infinite alternate }
@keyframes jm-sweep { from { transform: translateX(0) } to { transform: translateX(233%) } }
@media (prefers-reduced-motion: reduce) { .jm-progress.busy i { animation: none; width: 100%; opacity: .5 } }
/* the capture tile's microphone: teal while it hears you, crossed out when it cannot */
.jm-chip .mic { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px; background: none; color: var(--jm-rec); flex: none; cursor: pointer }
.jm-chip .mic:hover { background: var(--glass-hover) }
.jm-chip .mic.off { color: var(--glass-ink-3) }

/* ---- sessions (spec 27 Part 5), ported from the hi-fi kit (_jam.css): the shortcuts row and its tooltip, the
   switch, the wrap-up list and field, the record, the play counter ---- */
.jm-record { padding: 10px 12px; border-radius: 10px; background: var(--cm-field); border: 1px solid var(--glass-brd);
  font: 400 12px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--glass-ink-2); white-space: pre-wrap }
.jm-record b { color: var(--glass-ink); font-weight: 600 }

.jm-list { display: flex; flex-direction: column; margin: 0 -8px }
.jm-list > div { display: grid; grid-template-columns: 14px 1fr auto; gap: 9px; align-items: center; height: 30px; padding: 0 8px; border-radius: 8px;
  font: 500 12.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-list > div:hover { background: var(--glass-hover) }
.jm-list > div > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.jm-list > div > small { font: 500 11.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3); font-variant-numeric: tabular-nums }
.jm-list > div.dim > span { color: var(--glass-ink-2) }
.jm-list .more { display: block; height: auto; padding: 4px 8px; font: 500 11.5px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }

/* the instructions field */
.jm-field { min-height: 86px; padding: 9px 12px; border-radius: 12px; background: var(--cm-field); border: 1px solid var(--glass-brd);
  font: 400 13px/1.5 -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-field .ph { color: var(--glass-ink-3) }
.jm-field.on { border-color: transparent; box-shadow: 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-ring) }

/* a switch: the accent pill */
.jm-switch { position: relative; width: 28px; height: 17px; border-radius: 999px; flex: none; background: var(--glass-ink-3) }
.jm-switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .25); transition: transform var(--morph) }
.jm-switch.on { background: var(--accent) }
.jm-switch.on::after { transform: translateX(11px) }
.jm-agent { display: inline-flex; align-items: center; gap: 6px; font: 600 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-agent i { width: 6px; height: 6px; border-radius: 50%; background: var(--status-done, #34c759) }
.jm-count { position: absolute; bottom: 16px; z-index: 32; display: flex; align-items: center; gap: 2px; height: 40px; padding: 4px 6px;
  border-radius: 999px; background: rgba(18, 18, 24, .82); border: 1px solid rgba(255, 255, 255, .12);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); font: 600 12px -apple-system, system-ui, sans-serif; color: #f5f5f7;
  font-variant-numeric: tabular-nums }
.jm-count > span { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 8px; border-radius: 999px }
.jm-count > span:hover { background: rgba(255, 255, 255, .1) }
.jm-count .q { color: rgba(245, 245, 247, .4); font: 600 10.5px -apple-system, system-ui, sans-serif; padding: 0 6px 0 4px }
.jm-count .sep { width: 1px; height: 16px; background: rgba(255, 255, 255, .14); margin: 0 2px }
.jm-sc-row { display: flex; align-items: center; gap: 9px; height: 32px; padding: 0 8px; margin: 0 -8px; border-radius: 8px;
  font: 500 13px -apple-system, system-ui, sans-serif; color: var(--glass-ink) }
.jm-sc-row > svg { flex: none; color: var(--glass-ink-3) }
.jm-sc-row .v { margin-left: auto; display: inline-flex; align-items: center; gap: 3px; font: 500 12px -apple-system, system-ui, sans-serif; color: var(--glass-ink-3) }
.jm-sc-row.hover { background: var(--glass-hover) }
.jm-sc-row.hover .v { color: var(--glass-ink-2) }
.jm-sctip { position: absolute; z-index: 40; width: 196px; padding: 8px 4px; border-radius: 12px;
  background: rgba(28, 28, 32, .96); color: #f5f5f7; box-shadow: 0 10px 28px -10px rgba(0, 0, 0, .45), 0 0 0 .5px rgba(0, 0, 0, .3);
  font: 500 12px -apple-system, system-ui, sans-serif }
.jm-sctip > div { display: flex; align-items: center; height: 26px; padding: 0 10px }
.jm-sctip > div b { margin-left: auto; min-width: 20px; height: 20px; padding: 0 5px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 5px; background: rgba(255, 255, 255, .12); font: 600 11px -apple-system, system-ui, sans-serif; color: #f5f5f7 }
.jm-sctip > .hd { height: 22px; font: 600 10.5px -apple-system, system-ui, sans-serif; letter-spacing: .03em; color: rgba(245, 245, 247, .5); text-transform: uppercase }
:is(.dark .sh-app:not(.light), .sh-app.dark) .jm-sctip { background: rgba(250, 250, 252, .97); color: #1d1d1f; box-shadow: 0 10px 28px -10px rgba(0, 0, 0, .6) }
:is(.dark .sh-app:not(.light), .sh-app.dark) .jm-sctip > div b { background: rgba(0, 0, 0, .07); color: #1d1d1f }
:is(.dark .sh-app:not(.light), .sh-app.dark) .jm-sctip > .hd { color: rgba(29, 29, 31, .5) }

/* the session's sheets, in the shell: rows that are buttons (the microphone, the talk switch), the
   instructions field (a real textarea, three lines and growing), the record's page filling its panel */
.jm-panel button.row { width: 100%; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer }
.jm-panel button.row:hover { background: var(--glass-hover) }
textarea.jm-field { width: 100%; resize: none; outline: none; overflow: hidden; display: block }
textarea.jm-field:focus { border-color: transparent; box-shadow: 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-ring) }
.jm-sheet-at { position: absolute; right: var(--edge); top: calc(var(--mv-top, 0px) + 64px); z-index: 42 }
.jm-sheet .rows, .jm-wrapup .rows { margin: 0 -8px }
.jm-sc-row { position: relative; cursor: default; outline: none }
.jm-record-panel .jm-body { overflow: auto }
.jm-record-panel .jm-record { white-space: pre-wrap; overflow-wrap: anywhere }
.jm-count { cursor: pointer }
/* in play the Jam button's crossed microphone wears the dark pill's ink (the canvas grey would vanish) */
.sh-play-pill .sh-pill-btn.jm-jam .jm-nomic { color: inherit }
