  /* base elements (box-sizing, body colors/font, button, button.tiny, inputs,
     range) come from the gg-ui kit. Only app-shell layout + product chrome here. */
  body { height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
  header { background: var(--well); padding: 10px 16px;
           display: flex; gap: 12px; align-items: center; flex-wrap: wrap; flex: 0 0 auto;
           position: relative; z-index: 100060; }   /* stays above the import overlay (#startscreen) */
  /* The menu bar sits above BOTH the header and the import overlay: a menu bar
     that disappears behind a screen is not a menu bar. Its dropdown backdrop is
     raised to 100063 in menubar.js - one below this - so the bar itself stays
     hit-testable while a menu is open, which is what lets the pointer slide
     from File to Edit the way a desktop menu does. */
  #menubar { background: var(--well); padding: 2px 10px; position: relative; z-index: 100064; }
  #menubar .grow { flex: 1; }
  /* the layout switch rides the bar's right end; it sets the bar's height, so
     the menu names centre against it rather than the other way round */
  .gg-statusbar { background: var(--well); }   /* match the top bar (kit default is --panel) */
  header h1 { font-size: var(--fs-title); margin: 0; font-weight: 600; }
  header .grow { flex: 1; }
  #status { color: var(--text2); font-size: var(--fs-control); }
  .video-wrap { display: flex; justify-content: center; align-items: center; background: var(--well); padding: 8px; flex: 1 1 auto; min-height: 0; }
  .vid-captions { position:absolute; left:50%; bottom:7%; transform:translateX(-50%); max-width:92%; text-align:center; display:none;
    font:700 clamp(13px,2.6vw,26px)/1.3 Arial, system-ui, sans-serif; color:#fff; pointer-events:none; z-index:6;
    text-shadow:0 2px 5px rgba(0,0,0,.95), 0 0 3px rgba(0,0,0,.9); }
  .vid-captions .cap-w { opacity:.9; }
  .vid-captions .cap-w.on { color:var(--lime); opacity:1; }
  #stage { position: relative; overflow: hidden; line-height: 0; border-radius: var(--radius,5px); }
  video { max-height: 36vh; max-width: 100%; background: #000; display: block; }
  #cropbox { position: absolute; border: 2px solid var(--frame-blue); box-shadow: 0 0 0 9999px rgba(0,0,0,.5);
             pointer-events: none; display: none; box-sizing: border-box; }
  #cropbox::after { content: attr(data-label); position: absolute; top: 2px; left: 2px;
                    font: var(--fs-data)/1.4 system-ui; color: var(--text2); background: rgba(0,0,0,.6); padding: 0 4px; border-radius: var(--radius-sm,3px); }
  /* the Sequence: a panel of the tl dock (trad.css sizes it to its pane) */
  .timeline { flex: 1 1 auto; background: var(--inset);
              display: flex; flex-direction: column; padding: 7px 10px; }
  .tl-head { font-size: var(--fs-control); color: var(--text2); display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
  .tl-head .hint { margin-left: auto; }
  .tl-track { flex: 1 1 auto; display: flex; gap: 5px; overflow-x: auto; align-items: stretch; padding-bottom: 2px; }
  .tl-item { flex: 0 0 auto; min-width: 72px; max-width: 260px; background: var(--control); border: none;
             border-radius: var(--radius,5px); padding: 5px 7px; font-size: var(--fs-data); color: var(--text2); position: relative;
             cursor: grab; display: flex; flex-direction: column; justify-content: space-between; user-select: none; }
  .tl-item.dragging { opacity: .4; }
  .tl-item.dragover { border-color: var(--hue-green); box-shadow: inset 0 0 0 1px var(--hue-green); }
  .tl-item .t { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tl-item .d { color: var(--muted); margin-top: 4px; }
  /* z-index: the title (.t) is position:relative and comes later, so it painted OVER this
     and took the click across most of the control's height - only the sliver above the
     title's box worked. Found when the typed ✕ became an icon and a scripted click on its
     centre did nothing; the overlap predates that. 5 is above the trim handles (4). */
  .tl-item .x { position: absolute; top: 1px; right: 4px; z-index: 5; cursor: default; color: var(--text2); font-size: var(--fs-control); }
  .tl-empty { color: var(--muted); font-size: var(--fs-control); margin: auto; }
  .tw-unit { font-size: var(--fs-label); color: var(--muted); margin-left: 4px; white-space: nowrap; }
  .panel { overflow: auto; padding: 12px 14px; min-height: 0; }
  /* clips: full-height left column, fixed head (controls) + scrolling list */
  .panel.clips { flex: 0 0 clamp(320px, 30%, 480px); min-width: 300px; overflow: hidden;
                 padding: 0; display: flex; flex-direction: column; }
  /* (legacy .clips-head base removed; .gg-panel-head skeleton from the kit covers it) */
  .clips-head h2 { margin: 0 0 6px; }
  .clips-body { flex: 1 1 auto; overflow: auto; padding: 4px 6px 10px; min-height: 0; }
  /* the transcript fills its pane under its sticky head */
  .panel.transcript { flex: 1 1 auto; min-height: 0; }
  .panel h2 { font-size: var(--fs-body); text-transform: uppercase; letter-spacing: .05em; color: var(--text2); margin: 0 0 10px; }
  /* top is the panel's padding, negated: a sticky box is held inside the scroller's CONTENT box,
     so at top:0 it sat 12px down and scrolled lines showed in the strip above it */
  .sticky-head { position: sticky; top: -12px; z-index: 3; background: var(--bg); margin: -12px -14px 6px;
                 padding: 12px 14px 8px; border-bottom: 1px solid var(--border); }
  .sticky-head h2 { margin: 0 0 6px; }
  .sticky-head .hint { margin: 6px 0 0; }
  /* ticked = in the "Export selected…" set (Ctrl-click / Shift-click a card) */
  .w.cur, .w.now { background: var(--card-sel); color: #fff; }
  .badge { font-size: var(--fs-data); padding: 1px 6px; border-radius: var(--radius-lg,9px); background: var(--chip); color: var(--text2); }
  .badge.hi { background: color-mix(in srgb, var(--hue-green) 45%, var(--well)); } .badge.mid { background: color-mix(in srgb, var(--hue-amber) 40%, var(--well)); } .badge.lo { background: color-mix(in srgb, var(--danger) 45%, var(--well)); }
  #transcript { font-size: var(--fs-read); line-height: 1.9; user-select: text; overflow-wrap: break-word; }
  .w { cursor: text; padding: 0 .5px; border-radius: var(--radius-sm,3px); }
  .w:hover { background: var(--control); }
  .seg-time { color: var(--muted); font-size: var(--fs-data); margin-right: 6px; user-select: none; cursor: default; }
  .seg-spk { color: var(--muted); font-family: var(--f-mono); font-size: var(--fs-label); font-weight: 600; letter-spacing: .02em;
             margin-right: 6px; padding: 0 5px; border: 1px solid currentColor; border-radius: var(--radius-lg,9px);
             opacity: .85; user-select: none; white-space: nowrap; }
  /* wrap: the two Add-selection buttons carry translated labels, and in es/fr/
     de/it the row outgrew the panel and put a horizontal scrollbar on the whole
     transcript (measured 2026-08-11, +49px in es). A second header line costs
     less than a scrollbar over the words you are reading. English is unaffected
     - it still fits on one line. */
  .tr-headrow { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; min-width: 0; flex-wrap: wrap; }
  .tr-headrow h2 { margin: 0 !important; }
  .tr-search { width: 180px; max-width: 50%; min-width: 0; font-size: var(--fs-control); padding: 4px 8px; background: var(--inset);
               color: var(--text); border: none; border-radius: var(--radius,5px); outline: none; }   /* min-width:0 - must SHRINK in a squeezed panel, not bleed over the gutter */
  .tr-search:focus { box-shadow: 0 0 0 2px rgba(var(--lime-rgb),.4); }
  .tr-count { font-family: var(--f-mono); font-size: var(--fs-label); color: var(--muted); white-space: nowrap; }
  /* in-app guide viewer: full-screen panel over everything (incl. the start screen) */
  #guidemodal { position:fixed; inset:0; z-index:100075; background:var(--bg);
                display:flex; flex-direction:column; }
  #guidemodal .guide-head { display:flex; align-items:center; gap:10px; padding:8px 12px;
                background:var(--panel); }
  #guidemodal iframe { flex:1 1 auto; width:100%; border:none; background:var(--bg); }
  /* Learn modal: the guide + the guided-tour list with completion checks */
  #learnmodal { --gg-modal-w: 540px; }
  .lm-guide { display:flex; align-items:center; gap:12px; background:var(--well); border-radius:var(--radius-lg,9px); padding:12px 14px; margin-bottom:14px; }
  .lm-h { margin:4px 0 8px; font-family:var(--f-head); font-weight:700; font-size:var(--fs-title);
          letter-spacing:-.01em; color:var(--text); }
  /* fixed name column so every row's description starts at the same x */
  .lm-row { display:grid; grid-template-columns:14px 178px minmax(0,1fr) auto; align-items:baseline; gap:10px;
            padding:7px 10px; border-radius:var(--radius,5px); background:transparent;
            margin-bottom:1px; cursor:default; transition:background 120ms ease; }
  .lm-row:hover { background:var(--control); }
  .lm-row.off { cursor:default; opacity:.6; }
  .lm-row.off:hover { background:transparent; }
  .lm-check { font-family:var(--f-mono); color:var(--muted); opacity:.35; }
  .lm-check.on { color:var(--lime); opacity:1; }
  .lm-name { font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .lm-blurb { font-size:var(--fs-data); color:var(--muted); line-height:1.35; min-width:0; }
  .lm-hint { margin-left:auto; font-family:var(--f-mono); font-size:var(--fs-label); color:var(--muted); white-space:nowrap; }
  /* word timing nudge: a regular header button (gg-button sm) + a small anchored popover */
  .tr-timing-pop { position: absolute; right: 8px; top: calc(100% + 4px); z-index: 30; width: 270px;
                   background: var(--panel); border-radius: var(--radius-lg,9px); padding: 10px 12px;
                   box-shadow: 0 6px 22px rgba(0,0,0,.45); }
  .tr-timing-pop .ttp-row { display: flex; align-items: center; gap: 8px; }
  .tr-timing-pop .ttp-row input[type=range] { flex: 1; min-width: 0; -webkit-appearance: none; appearance: none;
                   height: 5px; border-radius: var(--radius-sm,3px); cursor: default;
                   background: linear-gradient(90deg, var(--lime) var(--p, 50%), rgba(255,255,255,.14) var(--p, 50%)); }
  .tr-timing-pop .ttp-row input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none;
                   width: 13px; height: 13px; border-radius: 50%; background: var(--text2); border: 2px solid #fff;
                   box-shadow: 0 1px 3px rgba(0,0,0,.45); cursor: default; }
  .tr-timing-pop .lbl { font-family: var(--f-mono); font-size: var(--fs-data); color: var(--text2); min-width: 42px; text-align: right; }
  .tr-timing-pop .ttp-hint { font-size: var(--fs-data); color: var(--muted); margin-top: 7px; line-height: 1.35; }
  .w.thit { background: rgba(var(--lime-rgb),.28); border-radius: var(--radius-sm,3px); }
  .w-edit { background:var(--control); outline:1px solid var(--lime, #ff8a2e); border-radius:var(--radius-sm,3px); cursor:text; white-space:pre; }
  .tline { padding: 2px 6px; border-radius: var(--radius,5px); transition: background .15s; }
  .tline.active { background: color-mix(in srgb, var(--frame-blue) 18%, var(--card-sel)); }
  .hint { color: var(--muted); font-size: var(--fs-control); }
  /* Merger outputs box hidden for launch (owner call 2026-08-02: doesn't fit
     the Clip Library panel; renders land in Exports anyway). merger.js still
     populates #outputs - remove this rule to bring the box back. */
  #outputs { display: none !important; }
  #outputs:not(:empty) { border-radius: var(--radius-lg,9px); padding: 8px; margin-bottom: 10px; background: color-mix(in srgb, var(--hue-green) 12%, var(--well)); }   /* tint carries it - no accent outline */
  #outputs .out-head { font-size: var(--fs-control); color: var(--text2); margin-bottom: 6px; display: flex; align-items: center; gap: 8px; }
  #outvideo { width: 100%; max-height: 30vh; background: #000; border-radius: var(--radius,5px); margin: 6px 0; display: none; }
  .out-row { display: flex; align-items: center; gap: 8px; font-size: var(--fs-control); padding: 1px 0; }
  .out-row a { color: var(--text2); text-decoration: none; }
  .out-row a:hover { text-decoration: underline; }
  /* the composition's panels: the canvas, the lane timeline, the inspector and the Output column are each a panel of the dock engine */
  .comp-canvaswrap { position: relative; flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; min-height: 0; }
  .comp-stage { display: flex; flex: 1 1 auto; overflow: auto; min-height: 0; background: var(--well); border-radius: var(--radius,5px); isolation: isolate; }
  /* Composer Timeline · full width below the body; drives every layer to its frame at time T */
  .comp-scrub { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 7px; padding: 8px 12px 10px; --cs-label-w: 176px;   /* lane-label width: shared by scrub pad + ruler spacer so they always line up */
                border-top: 1px solid var(--divider); background: var(--well); }
  .cs-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; row-gap: 6px; }
  .cs-toolbar .grow { flex: 1; }
  /* Panel slots: a plugin with a panel gets one, in the composer HEADER beside
     Templates. They were in the timeline toolbar first, which put them among
     buttons that insert layers - nothing about opening a workspace touches the
     timeline (owner, 2026-08-13). Lit while their panel is open. */
  .comp-panelgrp { display: inline-flex; align-items: center; gap: 4px; margin-left: 10px; }
  .comp-panelgrp:empty { display: none; }
  .cs-addgrp { display: inline-flex; align-items: center; gap: 4px; padding-left: 8px; margin-left: 2px; border-left: 1px solid var(--divider); }
  .cs-toolbtn.cs-add { color: var(--text); font-weight: 600; }
  .cs-toolbtn.cs-add.has { background: var(--lime); color: var(--on-lime); border-color: transparent; }   /* audio track loaded: filled accent, dark label (same rule as markers/cuts - coloured text on dark reads generated) */
  /* per-lane upcoming transcript words, anchored at the playhead. With the preview on, a
     clip's row is taller by one line and the words have that line to themselves, UNDER the
     bar - they used to be drawn across the bar's own label. */
  .cs-laneword { position: absolute; bottom: 1px; left: 0%; margin-left: 5px; max-width: 60%; z-index: 5; pointer-events: none;
    font-size: var(--fs-data); line-height: 14px; color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #cs_tracks.words-on .cs-row:has(> .cs-lane > .cs-laneword) { height: calc(var(--cs-rowh, 33px) + 15px); }
  #cs_tracks.words-on .cs-row:has(> .cs-lane > .cs-laneword) > .cs-lane { height: calc(var(--cs-rowh, 33px) + 13px); }
  #cs_tracks.words-on .cs-lane:has(> .cs-laneword) > .cs-block { bottom: 17px; }
  /* the scrub track row is inset by the lane-label width so it lines up with the lanes below */
  .cs-bar { display: flex; align-items: center; gap: 0; }
  .cs-bar-pad { flex: 0 0 var(--cs-label-w, 116px); }
  .comp-scrub .cs-time { font-family: var(--f-mono); font-size: var(--fs-data); color: var(--text2); min-width: 34px; }
  .comp-scrub .cs-total { color: var(--muted); min-width: 0; }
  .comp-scrub .cs-dim { color: var(--faint); font-family: var(--f-mono); font-size: var(--fs-data); }
  .cs-track { position: relative; flex: 1 1 auto; height: 8px; border-radius: var(--radius,5px); background: var(--well); cursor: default; }
  .cs-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0%; border-radius: var(--radius,5px); background: var(--lime); opacity: .55; pointer-events: none; }
  .cs-head { position: absolute; top: 50%; left: 0%; width: 13px; height: 13px; margin: -6.5px 0 0 -6.5px; border-radius: 50%;
             background: var(--lime); box-shadow: 0 1px 4px rgba(0,0,0,.5); pointer-events: none; }
  /* per-layer tracks (one row per video box) */
  .cs-tracks { position: relative; flex: 1 1 auto; min-height: 96px; overflow: auto; }
  /* inner wrapper scales with the zoom so % block positions stretch; lanes scroll horizontally */
  .cs-tracks-inner { position: relative; display: flex; flex-direction: column; gap: 4px; width: calc(100% * var(--tl-zoom, 1)); min-width: 100%; }
  .cs-empty-hint { padding: 18px 12px; color: var(--muted); font-size: var(--fs-control); text-align: center; }
  .cs-snapguide { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--lime); box-shadow: 0 0 4px var(--lime); pointer-events: none; display: none; z-index: 6; }
  /* (inline-flex with a gap: a label here may have a drawn icon in front of it - the typed
     ＋, ⇕ and ⊹ these buttons carried are icons since the 2.0 pass) */
  .cs-toolbtn { display: inline-flex; align-items: center; gap: 4px; --gg-icon-size: 12px;
                font-family: var(--f-body); font-size: var(--fs-data); line-height: 1; padding: 4px 8px; border: 1px solid transparent; border-radius: var(--radius,5px); background: var(--control); color: var(--text2); cursor: default; flex: 0 0 auto; }
  /* ONE hover for every button on this row - Split, ⇕ Full, Aa Preview and the
     ＋ adders are all .cs-toolbtn and used to hover three different ways
     (owner, 2026-08-23). --raise-hi, not --raise: in def2 --raise and --control
     are the SAME colour, so a hover to --raise is invisible, and it is also
     what the kit's own buttons hover to, so <gg-button> beside them matches.
     Lime is reserved for STATE (.on / .has) - if hover were lime too, hover
     and "this toggle is on" would look identical on the same button. */
  .cs-toolbtn:hover { color: var(--text); background: var(--raise-hi); }
  .cs-toolbtn.on { background: var(--lime); color: var(--on-lime); }
  .cs-wordcount { width: 40px; flex: 0 0 auto; font-family: var(--f-mono); font-size: var(--fs-data); padding: 3px 4px; text-align: center;
                  border: none; border-radius: var(--radius,5px); background: var(--control); color: var(--text2); }
  .cs-wordcount-lbl { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; font-size: var(--fs-data); color: var(--text2); }
  .cs-zoom { display: flex; align-items: center; flex: 0 0 auto; }
  .cs-zoom button { font-family: var(--f-mono); font-size: var(--fs-label); line-height: 1; padding: 3px 6px; border: 1px solid transparent; background: var(--control); color: var(--text2); cursor: default; }
  .cs-zoom button:first-child { border-radius: var(--radius,5px) 0 0 var(--radius,5px); }
  .cs-zoom button:last-child { border-radius: 0 var(--radius,5px) var(--radius,5px) 0; }
  .cs-zoom button:not(:first-child) { border-left: 0; }
  .cs-zoom button:hover { color: var(--text); }
  .cs-zoom #cs_zoom_lbl { min-width: 40px; }
  .cs-row { display: flex; align-items: center; gap: 0; height: var(--cs-rowh, 33px); flex: 0 0 auto; }
  /* "new layer" as a real target, below the last lane. Only exists mid-drag, so
     it costs nothing at rest; dashed because it is a drop zone, which is one of
     the deliberate edges the no-hairline rule keeps. */
  .cs-newdrop { flex: 0 0 auto; height: var(--cs-rowh, 33px); margin-top: 3px;
                display: flex; align-items: center; justify-content: center;
                border: 1px dashed var(--divider); border-radius: var(--radius,5px);
                color: var(--muted); font-size: var(--fs-data); letter-spacing: .02em;
                pointer-events: none; }   /* hit-tested by rect, never by elementFromPoint */
  .cs-newdrop.on { color: var(--text);
                   background: rgba(var(--lime-rgb), .10); }
  .cs-rlabel.dragging { opacity: .4; }
  /* the restack indicator draws on the edge you would land on - top half of a
     row means above it, bottom half means below. It only ever drew on top
     before, which is why the bottom of the stack looked unreachable: it was. */
  .cs-row.dragover-top .cs-rlabel { box-shadow: inset 0 2px 0 var(--lime); }
  .cs-row.dragover-bottom .cs-rlabel { box-shadow: inset 0 -2px 0 var(--lime); }
  .cs-row.multisel .cs-rlabel { background: rgba(var(--frame-rgb), .3); color: var(--text); }
  .cs-rlabel { flex: 0 0 var(--cs-label-w, 116px); padding-right: 6px; position: sticky; left: 0; z-index: 3; background: var(--well); cursor: grab;
               display: flex; align-items: center; gap: 5px; font-family: var(--f-mono); font-size: var(--fs-label);
               color: var(--text2); white-space: nowrap; overflow: hidden; }
  .cs-rlabel::before { content: ""; flex: 0 0 auto; width: 3px; height: 12px; border-radius: var(--radius-sm,3px); background: var(--rc, var(--muted)); }
  .cs-rname { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cs-rico { flex: 0 0 auto; font-weight: 700; opacity: .85; }
  .cs-rlock, .cs-rtop, .cs-reye { flex: 0 0 auto; width: 17px; height: 17px; padding: 0; border: none; border-radius: var(--radius,5px); background: none;
               color: var(--muted); display: inline-flex; align-items: center; justify-content: center; cursor: default; opacity: .5; font-size: var(--fs-body); }
  .cs-row:hover .cs-rlock, .cs-row:hover .cs-rtop, .cs-row:hover .cs-reye { opacity: 1; }
  .cs-rlock.on, .cs-rtop.on { color: var(--lime); opacity: 1; }
  .cs-rlock:hover, .cs-rtop:hover, .cs-reye:hover { background: var(--control); color: var(--text); }
  .cs-reye.off { color: var(--amber); opacity: 1; }              /* hidden layer: eye-off stays lit */
  .cs-row.hidden .cs-rname { opacity: .4; text-decoration: line-through; }
  /* non-timed overlay lanes (text / watermark / captions): a slim full-width bar */
  .cs-row-ov { height: 22px; }
  .cs-row-ov .cs-lane { height: 20px; }
  .cs-block.ov { background: rgba(var(--frame-rgb), .26);
               box-shadow: inset 1px 0 0 rgba(var(--frame-rgb), .5), inset -1px 0 0 rgba(var(--frame-rgb), .5);
               cursor: default; color: var(--text2); }
  .cs-block.ov.sel { background: rgba(var(--frame-rgb), .44);
                     box-shadow: inset 2px 0 0 var(--frame-blue), inset -2px 0 0 var(--frame-blue); }
  .cs-ovtxt { font-size: var(--fs-label); opacity: .7; letter-spacing: .03em; }
  .cs-row-ov.pinned .cs-rlabel { cursor: default; }
  /* timed overlay lanes (text / image): a draggable, trimmable block with opacity-fade ◆ handles */
  .cs-row-ov.timed { height: 30px; }
  .cs-row-ov.timed .cs-lane { height: 28px; }
  .cs-ovblock { position: absolute; top: 2px; bottom: 2px; border-radius: var(--radius-sm,3px); cursor: grab; display: flex; align-items: center;
                overflow: hidden; background: rgba(var(--frame-rgb), .36);
                box-shadow: inset 1px 0 0 rgba(var(--frame-rgb), .6), inset -1px 0 0 rgba(var(--frame-rgb), .6); }
  .cs-ovblock.sel { background: rgba(var(--frame-rgb), .52);
                    box-shadow: inset 2px 0 0 var(--frame-blue), inset -2px 0 0 var(--frame-blue); }
  .cs-ovlabel { font-family: var(--f-mono); font-size: var(--fs-label); color: var(--text); margin: 0 9px; pointer-events: none;
                white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cs-ovfade { position: absolute; top: 0; bottom: 0; pointer-events: none; }
  .cs-ovfade.in { left: 0; background: linear-gradient(90deg, rgba(0,0,0,.5), transparent); }
  .cs-ovfade.out { right: 0; background: linear-gradient(270deg, rgba(0,0,0,.5), transparent); }
  .cs-ovtrim { position: absolute; top: 0; bottom: 0; width: 7px; cursor: ew-resize; z-index: 7; }   /* above the fade handle so the EDGE always trims */
  .cs-ovtrim.l { left: 0; } .cs-ovtrim.r { right: 0; }
  .cs-ovtrim:hover { background: rgba(255,255,255,.28); }
  /* per-layer caption toggle (lane header) + the tied orange caption row */
  .cs-rcc { flex: 0 0 auto; height: 16px; padding: 0 4px; border: 1px solid var(--border); border-radius: var(--radius-sm,3px); background: none;
            color: var(--muted); font: 700 var(--fs-label)/1 var(--f-mono); letter-spacing: .04em; cursor: default; opacity: .55; }
  .cs-row:hover .cs-rcc { opacity: 1; }
  .cs-rcc.on { color: var(--amber); background: rgba(var(--amber-rgb,240,180,60),.18); opacity: 1; }
  .cs-rcc:hover { color: var(--text); }
  /* caption row sits flush ON its clip lane (gap gone); a gradient strip fills the seam to link them */
  .cs-row-cap { height: 18px; margin-bottom: -4px; position: relative; z-index: 4; }
  .cs-row-cap .cs-lane { height: 15px; background: transparent; cursor: default; overflow: visible; }
  .cs-rlabel.cap .cs-rico { color: var(--amber); }
  .cs-caprect { position: absolute; top: 1px; bottom: 1px; border-radius: var(--radius-sm,3px) var(--radius-sm,3px) 0 0; cursor: default;
                background: rgba(255,140,0,.62); box-shadow: inset 1px 0 0 var(--amber), inset -1px 0 0 var(--amber); }
  .cs-caprect:hover { background: rgba(255,140,0,.82); }
  .cs-row-cap.sel .cs-caprect { box-shadow: inset 2px 0 0 #fff, inset -2px 0 0 #fff; }
  /* fill the space between the caption rect and the clip below with a gradient → reads as one connected unit */
  .cs-caprect::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 7px; pointer-events: none;
    background: linear-gradient(to bottom, var(--amber), var(--rc, var(--amber))); }
  .cs-ovblock .cs-fadeh { z-index: 5; }
  /* keyframe row: a diamond per keyframe time, drawn under an animated layer's lane */
  .cs-row-key { height: 14px; }
  .cs-row-key .cs-lane { height: 12px; background: transparent; cursor: default; }
  .cs-rlabel.key { color: var(--muted); }
  .cs-rlabel.key .cs-rico { color: var(--lime); font-size: var(--fs-label); }
  .cs-kf { position: absolute; top: 50%; width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; transform: rotate(45deg);
           background: var(--lime); border: 1px solid rgba(0,0,0,.55); cursor: ew-resize; z-index: 3; box-shadow: 0 1px 2px rgba(0,0,0,.4); }
  .cs-kf:hover { background: #fff; }
  .cs-kf.ease-in, .cs-kf.ease-out, .cs-kf.ease-inout { background: var(--amber); border-radius: var(--radius-sm,3px); }   /* eased keys read as rounded amber */
  .cs-lane { position: relative; flex: 1 1 auto; height: calc(var(--cs-rowh, 33px) - 2px); border-radius: var(--radius,5px); background: var(--well); overflow: hidden; cursor: default; }
  /* Timeline bars carry NO top/bottom hairline — a ringed translucent block is the
     generated look. The fill does the work; only the left/right edges stay, because
     those mark where the clip starts and ends in time. (owner note 2026-08-10) */
  .cs-block { position: absolute; top: 2px; bottom: 2px; border-radius: var(--radius-sm,3px); display: flex; align-items: center; padding: 0 7px;
              font-family: var(--f-mono); font-size: var(--fs-label); color: var(--text); white-space: nowrap; overflow: hidden; cursor: grab; user-select: none;
              background: var(--bc-fill, rgba(var(--lime-rgb), .35));
              box-shadow: inset 1px 0 0 var(--bc-bd, rgba(var(--lime-rgb), .5)), inset -1px 0 0 var(--bc-bd, rgba(var(--lime-rgb), .5)); }
  .cs-block.sel { background: var(--bc-fill-sel, rgba(var(--lime-rgb), .55));
                  box-shadow: inset 2px 0 0 var(--bc, var(--lime)), inset -2px 0 0 var(--bc, var(--lime)); }
  .cs-block.base { background: rgba(255,255,255,.1);
                   box-shadow: inset 1px 0 0 var(--border), inset -1px 0 0 var(--border); cursor: default; color: var(--text2); }
  .cs-block.loop:not(.seg) { background: repeating-linear-gradient(45deg, var(--bc-fill, rgba(var(--lime-rgb),.18)) 0 7px, var(--bc-fill-sel, rgba(var(--lime-rgb),.28)) 7px 14px); }
  /* a multi-clip lane: the block is an invisible, click-through container — only the sub-blocks
     (clips) show + take events, so gaps look like empty track and clicking a gap scrubs the lane */
  .cs-block.seg { background: transparent; box-shadow: none; pointer-events: none; }
  .cs-block.seg .cs-seg, .cs-block.seg .cs-movegrip, .cs-block.seg .cs-sfadeh { pointer-events: auto; }
  .cs-block .cs-loop { margin-right: 5px; opacity: .85; }
  /* segmented-layer sub-blocks (drag to reorder) + left move-grip (drag layer in time) */
  .cs-seg { position: absolute; top: 2px; bottom: 2px; border-radius: var(--radius-sm,3px); cursor: grab; z-index: 3;
            background: var(--bc-fill, rgba(var(--lime-rgb), .35));
            box-shadow: inset 1px 0 0 var(--bc-bd, rgba(var(--lime-rgb), .5)), inset -1px 0 0 var(--bc-bd, rgba(var(--lime-rgb), .5)); }
  .cs-seg:hover { background: var(--bc-hov, rgba(var(--lime-rgb), .6)); box-shadow: inset 0 0 0 1.5px var(--bc, var(--lime)); }   /* a single segment under the cursor reads clearly above the whole block */
  .cs-seg.dragging { background: var(--bc-hov, rgba(var(--lime-rgb), .7)); box-shadow: inset 0 0 0 2px var(--bc, var(--lime)), 0 2px 9px rgba(0,0,0,.5); z-index: 6; cursor: grabbing; }
  /* dashed outline showing where a dragged clip will land if released */
  .cs-dropslot { position: absolute; top: 2px; bottom: 2px; border: 1.5px dashed var(--gc, var(--lime)); border-radius: var(--radius-sm,3px);
    background: rgba(255,255,255,.07); pointer-events: none; z-index: 7; }
  /* red overlay over the section where a dragged clip would overlap another (a conflict) */
  .cs-dropconflict { position: absolute; top: 2px; bottom: 2px; background: rgba(255,60,60,.45); border: 1px solid var(--danger);
    border-radius: var(--radius-sm,3px); pointer-events: none; z-index: 8; }
  /* floating preview that follows the cursor while dragging a clip-piece */
  .cs-dragghost { position: fixed; z-index: 100090; pointer-events: none; left: 0; top: 0; transform: translate(12px, 10px);
    max-width: 200px; padding: 3px 9px; border-radius: var(--radius,5px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font: 600 var(--fs-data)/1.3 var(--f-mono); color: var(--on-lime); background: var(--gc, var(--lime)); box-shadow: 0 4px 12px rgba(0,0,0,.5); opacity: .96; }
  .cs-block.sel .cs-seg { background: var(--bc-fill-sel, rgba(var(--lime-rgb), .34)); }
  .cs-block.sel .cs-seg:hover { background: var(--bc-hov, rgba(var(--lime-rgb), .62)); }
  .cs-movegrip { position: absolute; left: 0; top: 0; bottom: 0; width: 13px; z-index: 5; cursor: grab; user-select: none;
                 display: flex; align-items: center; justify-content: center; font-size: var(--fs-data); color: var(--text);
                 background: rgba(0,0,0,.22); border-radius: var(--radius-sm,3px) 0 0 var(--radius-sm,3px); }
  .cs-seglabel { position: absolute; left: 17px; top: 50%; transform: translateY(-50%); z-index: 4; pointer-events: none;
                 font-family: var(--f-mono); font-size: var(--fs-label); color: var(--text); white-space: nowrap; overflow: hidden;
                 max-width: calc(100% - 24px); text-overflow: ellipsis; text-shadow: 0 1px 2px rgba(0,0,0,.55); }
  .cs-block .cs-trim { position: absolute; right: 0; top: 0; bottom: 0; width: 8px; cursor: ew-resize;
                       background: rgba(var(--lime-rgb), .55); border-radius: 0 var(--radius-sm,3px) var(--radius-sm,3px) 0; }
  .cs-block.base .cs-trim { display: none; }
  /* fade ramps (visual) + draggable handles for layer fade in/out */
  .cs-fade { position: absolute; top: 0; bottom: 0; pointer-events: none; z-index: 1; }
  .cs-fade.in { left: 0; background: linear-gradient(to right, rgba(0,0,0,.6), rgba(0,0,0,0)); }
  .cs-fade.out { right: 0; background: linear-gradient(to left, rgba(0,0,0,.6), rgba(0,0,0,0)); }
  /* an Enter/Exit EFFECT band reads amber (vs the dark plain-fade ramp), with a solid edge stripe */
  .cs-fade.fx.in, .cs-ovfade.fx.in, .cs-sfade.fx.in { background: linear-gradient(to right, rgba(255,140,0,.5), rgba(255,140,0,.05)); border-left: 2px solid var(--amber); }
  .cs-fade.fx.out, .cs-ovfade.fx.out, .cs-sfade.fx.out { background: linear-gradient(to left, rgba(255,140,0,.5), rgba(255,140,0,.05)); border-right: 2px solid var(--amber); }
  .cs-fadeh { position: absolute; top: 1px; width: 9px; height: 9px; margin-left: -4.5px; transform: rotate(45deg);
              background: var(--lime); border: 1px solid rgba(0,0,0,.45); border-radius: var(--radius-sm,3px); cursor: ew-resize;
              z-index: 5; box-shadow: 0 1px 2px rgba(0,0,0,.4); }
  .cs-fadeh:hover { background: #fff; }
  /* an Enter/Exit EFFECT handle is a distinct amber BAR (vs the lime fade diamond) */
  .cs-fadeh.fx { transform: none; background: var(--amber); border-radius: var(--radius-sm,3px); width: 6px; height: 13px; top: 1px; margin-left: -3px;
                 box-shadow: 0 0 0 1px rgba(0,0,0,.45); }
  .cs-fadeh.fx:hover { background: var(--amber); }
  /* Content boundary: where ONE layer changes what it shows. A cut line rather
     than a grip, because it is the same idea as a clip's split - the layer is
     continuous, the content is not. Wide invisible hit area, thin visible line. */
  /* A plugin-marked stretch of transcript: the word keeps its own colour and
     sits on a wash of the mark's, so a marked line still reads as text rather
     than as a chip. No outline - the tint IS the delineation. */
  #transcript .w.w-mark { background: color-mix(in srgb, var(--mk) 22%, transparent);
                          border-radius: var(--radius-sm,3px); box-shadow: 0 0 0 2px color-mix(in srgb, var(--mk) 22%, transparent); }
  /* Plugin-owned layer: a small diamond next to the icon, in the lane's own
     colour. Not a badge or a chip - the rail is dense and this is a fact about
     the layer, not a control. */
  .cs-rsmart { color: var(--rc, var(--frame-blue)); font-size: var(--fs-label); margin: 0 3px 0 1px; opacity: .95; }
  /* A lane a plugin owns takes the plugin's colour for the whole block, at the
     same weights the theme accent uses - so four players' cells are four
     colours while every ordinary layer stays on the single accent def2 is
     built around. */
  .cs-row-ov.tinted .cs-ovblock { background: color-mix(in srgb, var(--rc) 36%, transparent);
      box-shadow: inset 1px 0 0 color-mix(in srgb, var(--rc) 60%, transparent),
                  inset -1px 0 0 color-mix(in srgb, var(--rc) 60%, transparent); }
  .cs-row-ov.tinted .cs-ovblock.sel { background: color-mix(in srgb, var(--rc) 52%, transparent);
      box-shadow: inset 2px 0 0 var(--rc), inset -2px 0 0 var(--rc); }
  .cs-row-ov.tinted.multisel .cs-rlabel { background: color-mix(in srgb, var(--rc) 30%, transparent); }
  /* the same, for the lanes that span the whole comp (captions, watermark) */
  .cs-row-ov.tinted .cs-block.ov { background: color-mix(in srgb, var(--rc) 26%, transparent);
      box-shadow: inset 1px 0 0 color-mix(in srgb, var(--rc) 50%, transparent),
                  inset -1px 0 0 color-mix(in srgb, var(--rc) 50%, transparent); }
  .cs-row-ov.tinted .cs-block.ov.sel { background: color-mix(in srgb, var(--rc) 44%, transparent); }
  .cs-segb { position: absolute; top: 0; bottom: 0; width: 11px; margin-left: -5.5px; cursor: ew-resize;
             z-index: 6; touch-action: none; }
  .cs-segb::after { content: ""; position: absolute; left: 4px; top: 0; bottom: 0; width: 2px;
                    background: var(--panel); box-shadow: 0 0 0 1px rgba(0,0,0,.5); }
  /* a grip at the top, so the mark reads as something you can take hold of -
     the line alone said "a boundary is here" but not "move me" */
  .cs-segb::before { content: ""; position: absolute; left: 2.5px; top: 0; width: 6px; height: 5px;
                     border-radius: 0 0 var(--radius-sm,3px) var(--radius-sm,3px); background: var(--rc, var(--panel));
                     box-shadow: 0 0 0 1px rgba(0,0,0,.5); }
  .cs-segb:hover::after, .cs-segb:hover::before { background: #fff; }
  /* what each piece shows, written along it; too narrow a piece simply hides it */
  .cs-segname { position: absolute; top: 0; bottom: 0; display: flex; align-items: center;
                padding-left: 7px; font-family: var(--f-mono); font-size: var(--fs-label); color: var(--text2);
                overflow: hidden; white-space: nowrap; pointer-events: none; z-index: 2; }
  .cs-segb.kill::after { background: var(--coral, #ff6b57); width: 3px; left: 3.5px; }
  /* per-piece fade ramps + ◆ handles (inside a sub-block) */
  .cs-sfade { position: absolute; top: 0; bottom: 0; pointer-events: none; z-index: 2; }
  .cs-sfade.in { left: 0; background: linear-gradient(to right, rgba(0,0,0,.55), rgba(0,0,0,0)); }
  .cs-sfade.out { right: 0; background: linear-gradient(to left, rgba(0,0,0,.55), rgba(0,0,0,0)); }
  .cs-sfadeh { position: absolute; top: 1px; width: 8px; height: 8px; margin-left: -4px; transform: rotate(45deg);
               background: #fff; border: 1px solid rgba(0,0,0,.5); border-radius: var(--radius-sm,3px); cursor: ew-resize; z-index: 5; box-shadow: 0 1px 2px rgba(0,0,0,.45); }
  .cs-sfadeh:hover { background: var(--lime); }
  .cs-sfadeh.fx { transform: none; background: var(--amber); border-radius: var(--radius-sm,3px); width: 6px; height: 12px; top: 1px; margin-left: -3px; }   /* effect handle = amber bar */
  .cs-seg.sel { box-shadow: inset 0 0 0 2px var(--amber), 0 0 0 1px var(--amber) !important; }   /* the chunk whose In/Out the inspector targets */
  /* per-piece trim handles on each clip edge (below the fade diamonds so they don't fight) */
  .cs-strim { position: absolute; top: 11px; bottom: 0; width: 7px; z-index: 4; cursor: ew-resize; }
  .cs-strim.l { left: 0; } .cs-strim.r { right: 0; }
  .cs-strim:hover { background: rgba(255,255,255,.32); }
  .cs-block.seg .cs-strim { pointer-events: auto; }
  /* where two clips overlap (= a crossfade): a red hatch over the overlap region */
  .cs-overlap { position: absolute; left: 0; top: 0; bottom: 0; z-index: 4; pointer-events: none; border-right: 1px solid rgba(255,90,90,.85);
    background: repeating-linear-gradient(45deg, rgba(255,60,60,.45) 0 5px, rgba(255,60,60,.18) 5px 10px); }
  /* the transcript words a clip starts with (updates live as you trim the in-point) */
  .cs-segtxt { position: absolute; left: 8px; right: 8px; bottom: 1px; z-index: 3; pointer-events: none;
    font-size: var(--fs-label); line-height: 1.25; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    text-shadow: 0 1px 2px rgba(0,0,0,.6); opacity: .92; }
  .cs-lanehead { position: absolute; top: 0; bottom: 0; left: 0%; width: 2px; margin-left: -1px; background: var(--lime); pointer-events: none; }
  /* timecode ruler (sticky top) + draggable playhead over the lanes */
  .cs-ruler { display: flex; align-items: stretch; height: 18px; flex: 0 0 auto; position: sticky; top: 0; z-index: 4; background: var(--well); }
  .cs-ruler-spacer { flex: 0 0 var(--cs-label-w, 132px); position: sticky; left: 0; z-index: 5; background: var(--well); border-right: 1px solid var(--divider); }
  .cs-label-resize { position: absolute; top: 0; bottom: 0; right: -3px; width: 7px; cursor: ew-resize; z-index: 6; }
  .cs-label-resize:hover { background: var(--lime); opacity: .55; }
  .cs-ruler-track { position: relative; flex: 1 1 auto; overflow: hidden; cursor: default; }
  .cs-tick { position: absolute; top: 9px; bottom: 0; width: 1px; background: var(--border); }
  .cs-tick-lbl { position: absolute; top: 1px; font-family: var(--f-mono); font-size: var(--fs-label); color: var(--muted); margin-left: 3px; pointer-events: none; white-space: nowrap; }
  .cs-playhead { position: absolute; top: 0; bottom: 0; left: 0%; width: 1px; background: var(--lime); pointer-events: none; z-index: 6; }
  .cs-playhead::before { content: ""; position: absolute; top: 0; left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 7px solid var(--lime); }
  /* margin auto centers it when it fits and collapses to 0 (scrollable) when zoomed past the stage.
     flex 0 0 auto: it is never SHRUNK to the stage. As a flex item it was, sideways, so a zoomed-in
     canvas was clipped at the panel's width and could not be scrolled to (2026-10-04). */
  .comp-stage > #workspace { margin: auto; flex: 0 0 auto; }
  .snapline { position: absolute; background: var(--lime); z-index: 99998; pointer-events: none; display: none; opacity: .9; }
  .snapline:not(.h) { top: 0; bottom: 0; width: 1px; }
  .snapline.h { left: 0; right: 0; height: 1px; }
  /* on-canvas zoom / snap overlays · float in the dimmed margin above the output frame */
  .canvas-ctl { position: absolute; top: 7px; z-index: 6; display: flex; align-items: center; gap: 2px;
                background: rgba(10,11,13,.5); border: 1px solid rgba(255,255,255,.09); border-radius: var(--radius-lg,9px); padding: 2px;
                backdrop-filter: blur(3px); }
  .canvas-ctl.snap { left: 8px; }
  .canvas-ctl.zoom { right: 8px; }
  .canvas-ctl.pin { left: 8px; top: auto; bottom: 8px; }   /* pin grid for the selected element */
  .canvas-ctl button { display: inline-flex; align-items: center; justify-content: center; gap: 5px; --gg-icon-size: 13px;
             background: transparent; border: none; color: var(--text2); font-family: var(--f-mono);
             font-size: var(--fs-control); cursor: default; padding: 3px 7px; border-radius: var(--radius,5px); min-width: 26px; }
  .canvas-ctl button:hover { background: var(--control); color: var(--text); }
  .canvas-ctl #snap_toggle.on { color: var(--lime); }
  /* left-hand layers / selected-item panel */
  .comp-layers { overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; gap: 10px; }
  .comp-canvaswrap { min-width: 170px; container-type: inline-size; }
  @container (max-width: 250px) { #zoom_lbl, #snap_toggle > span { display: none; } }
  .comp-stage.comp-drop, .comp-layers.comp-drop { outline:2px dashed var(--lime); outline-offset:-4px; border-radius:var(--radius-lg,9px); background:rgba(var(--lime-rgb),.06); }
  /* locked layers: dimmed + no-drag cursor on the timeline lane and canvas box */
  .cs-block.locked { opacity: .5; }
  .cs-ovblock.locked { opacity: .5; }
  .vbox.locked, .tbox.locked, .imgbox.locked, .subbox.locked { outline-style: dashed; cursor: not-allowed; }
  /* locked overlays: hide their move/resize/rotate/delete handles on the canvas */
  .tbox.locked .mv, .tbox.locked .rz, .tbox.locked .rh, .tbox.locked .del, .tbox.locked .tc,
  .imgbox.locked .mv, .imgbox.locked .rz, .imgbox.locked .rh, .imgbox.locked .del,
  .subbox.locked .mv, .subbox.locked .rz, .subbox.locked .rh, .subbox.locked .del { display: none !important; }
  /* preview approximation of the glitch/rgb-split Enter/Exit burst (export uses ffmpeg rgbashift+noise) */
  @keyframes glitchflick {
    0%   { filter: drop-shadow(3px 0 0 rgba(255,0,40,.85)) drop-shadow(-3px 0 0 rgba(0,255,235,.85)); }
    50%  { filter: drop-shadow(-5px 0 0 rgba(255,0,40,.85)) drop-shadow(4px 1px 0 rgba(0,255,235,.85)); }
    100% { filter: drop-shadow(2px -1px 0 rgba(255,0,40,.85)) drop-shadow(-2px 0 0 rgba(0,255,235,.85)); }
  }
  .glitch-fx { filter: drop-shadow(3px 0 0 rgba(255,0,40,.85)) drop-shadow(-3px 0 0 rgba(0,255,235,.85)); }   /* static when paused (clips + images) */
  .glitch-fx.glitch-play { animation: glitchflick .09s steps(2) infinite; }   /* flicker only during playback */
  .vbox.locked .h, .vbox.locked .rh, .vbox.locked .del,
  .imgbox.locked .h, .imgbox.locked .rh { display: none; }
  /* on-canvas handles appear only while the item is hovered or selected (via canvas or timeline) */
  .vbox .h, .vbox .rh, .vbox .del,
  .tbox .mv, .tbox .tc, .tbox .rz, .tbox .rh, .tbox .del,
  .subbox .mv, .subbox .rz, .subbox .rh, .subbox .del,
  .imgbox .mv, .imgbox .h, .imgbox .rh,
  #wmbox .rz { opacity: 0; pointer-events: none; transition: opacity .1s; }
  .vbox:hover .h, .vbox:hover .rh, .vbox:hover .del,
  .vbox.selected .h, .vbox.selected .rh, .vbox.selected .del,
  .tbox:hover .mv, .tbox:hover .tc, .tbox:hover .rz, .tbox:hover .rh, .tbox:hover .del,
  .tbox.selected .mv, .tbox.selected .tc, .tbox.selected .rz, .tbox.selected .rh, .tbox.selected .del,
  .subbox:hover .mv, .subbox:hover .rz, .subbox:hover .rh, .subbox:hover .del,
  .subbox.selected .mv, .subbox.selected .rz, .subbox.selected .rh, .subbox.selected .del,
  .imgbox:hover .mv, .imgbox:hover .h, .imgbox:hover .rh,
  .imgbox.selected .mv, .imgbox.selected .h, .imgbox.selected .rh,
  #wmbox:hover .rz, #wmbox.selected .rz { opacity: 1; pointer-events: auto; }
  /* rotate handles sit ~22px outside the box; a transparent pad bridges the gap so hovering toward
     them keeps the element :hover (otherwise they vanish before you can grab them) */
  .vbox .rh::before, .tbox .rh::before, .subbox .rh::before, .imgbox .rh::before { content: ""; position: absolute; inset: -9px; }
  /* hovering a caption's timeline lane reveals its on-canvas handles + glows it, so you see which one */
  .subbox.tl-peek { box-shadow: 0 0 11px rgba(var(--frame-rgb), .65); outline-color: var(--frame-blue); }
  .subbox.tl-peek .mv, .subbox.tl-peek .rz, .subbox.tl-peek .rh, .subbox.tl-peek .del { opacity: 1; pointer-events: auto; }
  /* selection highlight on canvas elements */
  .vbox.selected, .tbox.selected, .subbox.selected, #wmbox.selected { outline: 2px solid var(--frame-blue) !important; box-shadow: 0 0 10px rgba(var(--frame-rgb),.5); }
  /* right-hand vertical tool panel */
  .comp-tools { width: 430px; flex: 0 0 430px; display: flex; flex-direction: column; min-height: 0; gap: 0; }   /* wide enough to start in the two-column layout (cutoff 380px) */
  /* the column's name: the same small capitals as Arrange and Output across the canvas */
  #inspector .insp-title { flex: 0 0 auto; padding: 1px 3px 8px; font-family: var(--f-mono); font-size: var(--fs-label);
                           letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
  #inspector .insp-header { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto;
                            padding: 7px 9px; margin-bottom: 10px; border: none;
                            border-radius: var(--radius-lg,9px); background: var(--card-sel); }
  /* two rows, always: the layer (kind, footage and clip, name), then its actions. Groups of
     actions are parted by a hairline divider at rest (a divider is allowed to rest; it never
     lights). Hidden and locked are lit as the kit lights a primary button: on. */
  #inspector .insp-header .hdr-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
  #inspector .insp-header .hdr-ico { flex: 0 0 auto; --gg-icon-size: 16px; width: 16px; height: 16px; color: var(--text2); }
  #inspector .insp-header .hdr-btns { gap: 2px; }
  #inspector .insp-header .ins-multi { flex: 0 0 auto; color: var(--muted); font-size: var(--fs-label); white-space: nowrap; }   /* "3 layers selected" (selprops.js) */
  #inspector .insp-header .hdr-sep { flex: 0 0 auto; width: 1px; height: 14px; margin: 0 4px; background: var(--divider); }
  /* dedicated animation control panel (below the header) — vertical stack of rows */
  #inspector .insp-anim { display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; padding: 8px 9px; margin-bottom: 10px;
                          border: none; border-radius: var(--radius-lg,9px); background: var(--well); }
  #inspector :is(.insp-anim, .ia-rows) .ia-head { display: flex; align-items: center; gap: 7px; min-width: 0; }
  #inspector :is(.insp-anim, .ia-rows) .ia-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  #inspector :is(.insp-anim, .ia-rows) .ia-title { display: inline-flex; align-items: center; gap: 5px; --gg-icon-size: 9px; font-family: var(--f-mono); font-size: var(--fs-label); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
  #inspector :is(.insp-anim, .ia-rows) .ia-count { font-family: var(--f-mono); font-size: var(--fs-label); color: var(--lime); white-space: nowrap; }
  #inspector :is(.insp-anim, .ia-rows) .ia-fx { display: flex; align-items: center; gap: 5px; flex: 1 1 130px; min-width: 0; font-size: var(--fs-label); color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
  #inspector :is(.insp-anim, .ia-rows) .ia-fx .ia-lbl { flex: 0 0 auto; }
  /* effect picker = select + inline duration, styled as one pill */
  #inspector :is(.insp-anim, .ia-rows) .ia-fxpick { display: flex; align-items: stretch; flex: 1 1 auto; min-width: 0; border: none; border-radius: var(--radius,5px); overflow: hidden; background: var(--card); }
  #inspector :is(.insp-anim, .ia-rows) .ia-fxpick select { flex: 1 1 auto; min-width: 0; font-size: var(--fs-data); padding: 3px 4px; border: none; background: transparent; color: var(--text); text-transform: none; letter-spacing: 0; }
  #inspector :is(.insp-anim, .ia-rows) .ia-fxpick select option { background: var(--card); color: var(--text); }
  #inspector :is(.insp-anim, .ia-rows) .ia-fxpick .ia-durwrap { flex: 0 0 auto; display: flex; align-items: center; border-left: 1px solid var(--border); background: var(--well); padding-right: 5px; }
  #inspector :is(.insp-anim, .ia-rows) .ia-fxpick .ia-dur { width: 28px; border: none; background: transparent; text-align: right; font-size: var(--fs-data); padding: 3px 0; color: var(--text); }
  #inspector :is(.insp-anim, .ia-rows) .ia-fxpick .ia-durs { font-size: var(--fs-label); color: var(--muted); padding-left: 2px; }
  /* per-effect parameter sliders under the Clip FX dropdown */
  #inspector :is(.insp-anim, .ia-rows) .ia-fxparams { display: flex; flex-direction: column; gap: 5px; padding: 2px 2px 0 4px; }
  #inspector :is(.insp-anim, .ia-rows) .ia-prow { display: grid; grid-template-columns: 62px 1fr 24px; align-items: center; gap: 6px; font-size: var(--fs-label); color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
  #inspector :is(.insp-anim, .ia-rows) .ia-prow input[type=range] { min-width: 0; -webkit-appearance: none; appearance: none; height: 5px; border-radius: var(--radius-sm,3px); outline: none; cursor: default;
        background: linear-gradient(90deg, var(--lime) var(--p, 0%), rgba(255,255,255,.14) var(--p, 0%)); }
  #inspector :is(.insp-anim, .ia-rows) .ia-prow input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 13px; height: 13px; border-radius: 50%; background: var(--text2); border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,.45); cursor: default; }
  #inspector :is(.insp-anim, .ia-rows) .ia-prow .ia-pval { text-align: right; color: var(--text2); font-variant-numeric: tabular-nums; }
  #inspector :is(.insp-anim, .ia-rows) .ia-seg { font-family: var(--f-mono); font-size: var(--fs-label); color: var(--amber); text-transform: uppercase; letter-spacing: .05em; white-space: nowrap; }
  #inspector :is(.insp-anim, .ia-rows) .ia-btns { display: flex; gap: 6px; }
  #inspector :is(.insp-anim, .ia-rows) .ia-btns gg-button { flex: 1 1 0; min-width: 0; }   /* equal-width buttons fill the row; all stay visible */
  #inspector .insp-anim .grow { flex: 1 1 auto; }
  #inspector .ins-name { font-family: var(--f-head); font-weight: 600; font-size: var(--fs-body); color: var(--text);
                         white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #inspector .insp-header button { background: transparent; border: none; color: var(--text2); font-size: var(--fs-body);
                                   cursor: default; padding: 2px 5px; border-radius: var(--radius,5px); }
  #inspector .insp-header button:hover { background: var(--control); color: var(--text); }
  /* ONE scroll for the whole panel (2026-10-04). The body used to be the only part that scrolled
     and the only part that gave way: the header, the group strip, the source-scale line and the
     Animation panel kept their height and the body took what was left. With a grouped layer -
     which every split clip now is - that was 66 px in Compose and NOTHING in the layouts where
     Properties shares the right-hand side (measured on the exe: 374 px of panel, 399 px of fixed
     parts). Everything under the header scrolls together now, and the header stays in view. */
  #inspector { overflow-y: auto; }
  #inspector > * { flex-shrink: 0; }   /* a flex child gives way before its container scrolls: none of these may */
  #inspector .insp-body { flex: 0 0 auto; padding: 0 0 8px; display: flex; flex-direction: column; gap: 10px; }
  /* the header stays: its name and stacking buttons are about the layer being edited. The
     spread shadow is the panel's own colour, so what scrolls under it does not show at its
     rounded corners or in the gap beneath it. */
  #inspector .insp-header { position: sticky; top: 0; z-index: 3; box-shadow: 0 0 0 9px var(--panel); }
  /* control panels extend off the right screen edge: square right corners, flush */
  #inspector .tgroup { border-radius: 0 var(--radius-lg,9px) var(--radius-lg,9px) 0; }   /* inspector is on the LEFT now: round the canvas-facing (right) edge */
  #inspector .insp-sec { display: flex; flex-direction: column; gap: 10px; }
  /* two-column mode: flow the property cards into balanced columns so the panel scrolls less */
  #inspector.two-col .insp-sec { display: block; columns: 2; column-gap: 10px; }
  #inspector.two-col .insp-sec > * { break-inside: avoid; margin-bottom: 10px; }
  #inspector.two-col .insp-sec > *:last-child { margin-bottom: 0; }
  /* a section with a single card shouldn't be squeezed into one column — let it span full width */
  #inspector.two-col .insp-sec > .tgroup:only-child, #inspector.two-col .insp-sec > details:only-child { column-span: all; }
  /* default to only the canvas (nothing-selected) section; renderInspector() reveals the rest */
  #inspector .insp-sec[data-insp="box"],
  #inspector .insp-sec[data-insp="text"],
  #inspector .insp-sec[data-insp="sub"],
  #inspector .insp-sec[data-insp="top"],
  #inspector .insp-sec[data-insp="bottom"],
  #inspector .insp-sec[data-insp="wm"] { display: none; }
  #inspector .tgroup select.full { width: 100%; }
  /* "nothing selected" hint: always centered in the column (even when two-col mode is on elsewhere) */
  #inspector .insp-sec[data-insp="canvas"] { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 45vh; }
  #inspector .insp-nosel { text-align: center; padding: 14px 8px 4px; color: var(--muted); max-width: 300px; }
  #inspector .insp-nosel .etitle { font-family: var(--f-head); font-weight: 600; font-size: var(--fs-title); color: var(--text2); }
  #inspector .insp-nosel .ehint { font-size: var(--fs-control); line-height: 1.45; margin-top: 4px; }
  #inspector .insp-nosel .ehint b { color: var(--text2); }
  #inspector .canvas-media { border: none; border-radius: var(--radius-lg,9px); background: var(--well); }
  #inspector .canvas-media > summary { list-style: none; cursor: default; padding: 9px 11px;
        font-family: var(--f-mono); font-size: var(--fs-label); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
  #inspector .canvas-media > summary::-webkit-details-marker { display: none; }
  #inspector .canvas-media > summary::before { content: "▸ "; color: var(--faint); }
  #inspector .canvas-media[open] > summary::before { content: "▾ "; }
  #inspector .canvas-media[open] > summary { color: var(--text2); border-bottom: 1px solid var(--border); }
  #inspector .canvas-media .tgroup { border: none; border-radius: 0; background: transparent; }
  #inspector .canvas-media .tgroup + .tgroup { border-top: 1px solid var(--divider); }
  .tgroup { border: none; border-radius: var(--radius-lg,9px); background: var(--card); padding: 8px 9px; }
  .tgroup h4 { margin: 0 0 7px; font-size: var(--fs-data); letter-spacing: .04em; text-transform: uppercase;
               color: var(--muted); font-weight: 700; }
  .tgroup label { display: flex; align-items: center; gap: 6px; font-size: var(--fs-control); margin: 4px 0; }
  /* number-field rows: label text on the left, the input + unit pushed to the right edge */
  #inspector .tgroup label.spread { justify-content: space-between; }
  #inspector .tgroup .trow label.spread { flex: 1; }
  #inspector .tgroup .num { display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; }
  #inspector .tgroup .num input[type=number] { width: 60px; }
  /* motion chips: single-select pills that bake keyframe movement onto every layer */
  .mo-chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .mo-chip { font-size: var(--fs-data); padding: 4px 10px; border-radius: 999px; cursor: default;
             background: var(--card); border: 1px solid transparent; color: var(--text2); transition: border-color .12s, color .12s, background .12s; }
  .mo-chip:hover { color: var(--text); background: var(--control); }
  .mo-chip.on { background: var(--lime); color: var(--on-lime, #15170e); font-weight: 700; }
  .tgroup .trow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 4px 0; }
  .tgroup select, .tgroup input[type=file] { width: 100%; font-size: var(--fs-control); }
  .tgroup .trow select, .tgroup .trow button { width: auto; flex: 1; }
  /* shared slider look — matches the gg-ui <gg-range> (lime progress fill + round thumb), applied to
     every panel slider so the whole inspector is visually consistent. --p is the fill %, set in JS. */
  .tgroup input[type=range] { flex: 1; min-width: 60px; -webkit-appearance: none; appearance: none;
        height: 5px; border-radius: var(--radius-sm,3px); outline: none; cursor: default; margin: 7px 0;
        background: linear-gradient(90deg, var(--lime, #ff8a2e) var(--p, 0%), rgba(255,255,255,.14) var(--p, 0%)); }
  .tgroup input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 14px; height: 14px;
        border-radius: 50%; background: var(--text2); border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,.45); cursor: default; }
  .tgroup input[type=range]::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--text2); border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,.45); }
  /* line up slider rows: fixed label + value columns → every slider track starts AND ends at the same x */
  .tgroup label:has(> input[type=range]) { display: grid; grid-template-columns: 78px 1fr 24px; align-items: center; gap: 6px; }
  .tgroup label:has(> input[type=range]) > input[type=range] { min-width: 0; }
  .tgroup label:has(> input[type=range]) > .lbl { text-align: right; font-variant-numeric: tabular-nums; }
  /* Properties' value rows (propxform.js, proptext.js): a stopwatch where the property can be
     keyed, the name, the key arrows once it is, then its numbers, each with a unit. The name
     column is the slider rows' 78px (13px of stopwatch, a 6px gap, 59px of name), so a
     number starts where a slider's track does. A value in lime is keyed; in red it is keyed
     with keyframe mode off, and read-only until the mode is on or the stopwatch clears it. */
  #inspector .pf-rows { display: flex; flex-direction: column; }
  #inspector .pf-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 26px; font-size: var(--fs-control); }   /* only the note wraps */
  #inspector .pf-w { flex: 0 0 13px; display: flex; align-items: center; justify-content: center; color: var(--faint); transition: color .12s; }
  #inspector .pf-w.can:hover { color: var(--text); }
  #inspector .pf-w.on, #inspector .pf-w.on.can:hover { color: var(--lime); }
  #inspector .pf-ico { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; display: block; }
  #inspector .pf-l { flex: 0 0 59px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #inspector .pf-row:not(:has(> .pf-w)) .pf-l { flex-basis: 78px; }   /* a row with no stopwatch column (Timing, Size): the name spans both */
  #inspector .pf-kn { flex: 0 0 auto; display: flex; align-items: center; gap: 1px; color: var(--muted); }
  #inspector .pf-kn i { display: flex; align-items: center; height: 18px; padding: 0 1px; border-radius: var(--radius-sm,3px); transition: background .12s, color .12s; }
  #inspector .pf-kn i:hover { background: var(--raise-hi); color: var(--text); }
  #inspector .pf-kn i.on { color: var(--lime); }
  #inspector .pf-kn i.on .pf-ico { fill: currentColor; }
  /* the fields share the row and never wrap: W x H line up under X Y. A field grows with the
     panel (to 120px, room for 3367.44 s) and shrinks to 50px, never below */
  #inspector .pf-v { flex: 1 1 0; min-width: 0; display: flex; align-items: center; gap: 8px; }
  #inspector .pf-f { display: inline-flex; align-items: center; gap: 3px; flex: 1 1 0; min-width: 0; }
  #inspector .pf-f input[type=number] { width: 100%; min-width: 50px; max-width: 120px; flex: 1 1 auto; text-align: right; font-family: var(--f-mono); font-size: var(--fs-data); font-variant-numeric: tabular-nums; -moz-appearance: textfield; }
  #inspector .pf-f input[type=number]::-webkit-inner-spin-button, #inspector .pf-f input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }   /* a value scrubs; the spinner is noise */
  #inspector .pf-f input[type=number].scrub { cursor: ew-resize; }
  #inspector .pf-f input[type=number][readonly] { color: var(--muted); }
  #inspector .pf-u { color: var(--muted); font-size: var(--fs-label); }
  #inspector .pf-x { color: var(--muted); font-size: var(--fs-label); margin: 0 -2px; }
  #inspector .pf-row.keyed .pf-f input[type=number] { color: var(--lime); }
  #inspector .pf-row.locked .pf-f input[type=number] { color: var(--danger); }
  /* the Size row's percentage: its own line under the fields, aligned with them */
  #inspector .pf-note { flex: 0 0 calc(100% - 84px); margin: -6px 0 2px 84px; color: var(--muted); font: 400 var(--fs-label)/14px var(--f-mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #inspector .pf-note b { font-weight: 400; }
  #inspector .pf-note.up b { background: var(--amber); color: var(--on-amber); padding: 0 5px; border-radius: var(--radius-sm,3px); }
  /* the percentage is a field (a typed one scales W and H): one short number and its unit */
  #inspector .pf-note:has(input) { display: flex; align-items: center; margin-top: 0; overflow: visible; }
  #inspector .pf-note .pf-f { flex: 0 0 auto; gap: 5px; }
  #inspector .pf-note .pf-f input[type=number] { width: 64px; min-width: 64px; flex: 0 0 auto; }
  #inspector .pf-note.up .pf-f input[type=number] { background: var(--amber); color: var(--on-amber); }
  /* Origin as a Transform row: the 3x3 picker and the anchor's name */
  #inspector .pf-origin .origin-grid { flex: 0 0 auto; }
  #inspector .pf-origin-lbl { margin-left: 4px; color: var(--muted); font: 400 var(--fs-label) var(--f-mono); white-space: nowrap; }
  body.pf-scrubbing, body.pf-scrubbing * { cursor: ew-resize !important; user-select: none; }
  /* two columns are too narrow for a row of two numbers: Transform and Timing keep the panel's
     width, and Timing's four time rows go two by two instead */
  #inspector.two-col .insp-sec[data-insp="top"] { columns: 1; }
  #inspector.two-col .pf-grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 12px; }
  /* the keyframe strip heads the Transform group: inside a card, not a well of its own */
  #inspector #pf_transform .insp-anim { margin: 0 0 6px; padding: 0 0 6px; background: transparent; border-radius: 0; }
  /* the Effects group draws the Animation block's rows: the ia-* rules take both hosts */
  #inspector .ia-rows h4 .ia-seg { margin-left: 8px; text-transform: none; letter-spacing: 0; }
  #inspector .tgroup .trow > .pf-l { flex: 0 0 78px; }
  #inspector .tx-text { width: 100%; min-height: 40px; resize: vertical; font: inherit; font-size: var(--fs-control); line-height: 1.35; }
  .tgroup.render { border: none; background: none; padding: 0; margin-top: auto; }
  .tgroup.render .primary { width: 100%; padding: 9px; font-size: var(--fs-body); }
  /* workspace extends past the frame; frame is the actual 9:16 output region */
  #workspace { position: relative; overflow: hidden; background: var(--well); border-radius: var(--radius,5px); }
  #vigoverlay { position: absolute; inset: 0; pointer-events: none; z-index: 9000; display: none; border-radius: var(--radius,5px); }
  #grainoverlay { position: absolute; inset: 0; pointer-events: none; z-index: 8999; display: none; border-radius: var(--radius,5px); mix-blend-mode: overlay; }
  .look-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; margin: 2px 0 6px; }
  .look-strip .lk { padding: 5px 2px; border: 1px solid transparent; border-radius: var(--radius,5px); background: var(--control, #1b1f27); color: var(--text2, #cdd6e0); font-size: var(--fs-label); cursor: default; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: border-color .12s, background .12s; }
  .look-strip .lk:hover { background: var(--raise-hi); color: var(--text, #fff); }
  .look-strip .lk.on { background: rgba(var(--lime-rgb,255,138,46),.22); color: var(--text, #fff); font-weight: 600; }
  .look-adjust { margin-top: 4px; } .look-adjust summary { cursor: default; font-size: var(--fs-data); color: var(--muted); user-select: none; }
  #frame { position: absolute; background: #000; overflow: hidden; z-index: 0; }
  #bgimg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: none; }
  #framemask { position: absolute; z-index: 99999; pointer-events: none;
               box-shadow: 0 0 0 9999px rgba(0,0,0,.5); outline: 2px solid var(--frame-blue); }
  .vbox, #wmbox, .tbox { position: absolute; cursor: move; touch-action: none; z-index: 1; }
  .vbox { outline: 2px solid var(--frame-blue); }
  /* subtle cue: this box is the Composer-Timeline lane currently hovered/dragged */
  .vbox.tl-linked { outline-color: var(--tl-rc, var(--lime)); box-shadow: 0 0 13px 3px var(--tl-rc, var(--lime)); }
  .vbox .vinner { position: absolute; inset: 0; overflow: hidden; }
  /* live motion previews (illustrative; render uses exact ffmpeg math) */
  @keyframes moScrollUp   { from { transform: scale(1.6) translateY(11%);  } to { transform: scale(1.6) translateY(-11%); } }
  @keyframes moScrollDown { from { transform: scale(1.6) translateY(-11%); } to { transform: scale(1.6) translateY(11%);  } }
  @keyframes moPanRight   { from { transform: scale(1.6) translateX(11%);  } to { transform: scale(1.6) translateX(-11%); } }
  @keyframes moPanLeft    { from { transform: scale(1.6) translateX(-11%); } to { transform: scale(1.6) translateX(11%);  } }
  @keyframes moZoomIn     { from { transform: scale(1.0); } to { transform: scale(1.4); } }
  @keyframes moZoomOut    { from { transform: scale(1.4); } to { transform: scale(1.0); } }
  .vbox video { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; object-fit: contain; display: block; pointer-events: none; transform-origin: center center; }
  /* reframe mode: a drag-catcher over the cell to pan the cover-cropped footage */
  .vbox.reframing, .imgbox.reframing { outline: 2px dashed var(--lime) !important; }
  .imgbox.reframing .rz, .imgbox.reframing .rh, .imgbox.reframing .del, .imgbox.reframing .mv { display:none; }
  /* reframe owns the surface: pan + scroll-zoom adjust the CROP - the cell's
     scale/rotate handles would read as "still just scaling the clip" */
  .vbox.reframing .h, .vbox.reframing .rh, .vbox.reframing .del { display:none; }
  .reframe-catch { position: absolute; inset: 0; z-index: 30; cursor: grab; background: rgba(0,0,0,.04); }
  .reframe-catch.grabbing { cursor: grabbing; }
  .reframe-hint { position: absolute; left: 50%; top: 8px; transform: translateX(-50%); pointer-events: none;
                  background: rgba(0,0,0,.66); color: var(--lime); font-size: var(--fs-label); font-weight: 600; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
  .reframe-val { font-family: var(--f-mono); font-size: var(--fs-label); color: var(--muted); margin-left: 6px; }
  .vbox .vid2 { display: none; z-index: 2; }   /* incoming clip during a crossfade (over the main video) */
  /* static frame snapshot (shown when the preview is paused, so idle layers hold no video decoder) */
  .vbox .vsnap { position: absolute; inset: 0; width: 100%; height: 100%; display: none; pointer-events: none; }
  div.del { position: absolute; right: -9px; top: -9px; width: 18px; height: 18px; line-height: 15px;
         text-align: center; background: color-mix(in srgb, var(--danger) 45%, var(--well)); color: #fff; border: 1px solid var(--danger); border-radius: 50%;
         cursor: default; font-size: var(--fs-control); z-index: 6; }
  #wmbox { outline: 1px dashed var(--hue-amber); }
  #wmbox img { width: 100%; height: 100%; object-fit: contain; display: block; pointer-events: none; }
  /* demo build: the pinned render-credit layer. Mirrors the burned ASS style
     (_credit_ass: Permanent Marker, white fill, black outline, hard #ff8a2e
     shadow, \an5 center anchor) - keep them in step. Hardcoded orange on
     purpose: the burn doesn't follow the UI theme. Sits above the vignette
     (z 9000) like the burn order; under the frame mask. */
  #creditbox { position: absolute; display: none; z-index: 9100; cursor: move; touch-action: none;
               transform: translate(-50%, -50%); white-space: nowrap; user-select: none;
               font-family: 'Permanent Marker', 'Yu Gothic UI', 'Meiryo', cursive; font-weight: 400; color: #fff;
               -webkit-text-stroke: 0.09em #000; paint-order: stroke fill;
               text-shadow: 0.065em 0.065em 0 #ff8a2e; }
  #creditbox:hover { outline: 1px dashed rgba(255,255,255,.45); outline-offset: 3px; }
  .rz { position: absolute; right: -7px; bottom: -7px; width: 16px; height: 16px; background: var(--frame-blue);
        border: 2px solid #fff; border-radius: var(--radius-sm,3px); cursor: nwse-resize; touch-action: none; z-index: 6; }
  #wmbox .rz { background: var(--hue-amber); }
  /* 8 resize handles on video boxes AND image layers (corners + edge midpoints) */
  .vbox .h, .imgbox .h { position: absolute; width: 13px; height: 13px; background: var(--frame-blue); border: 2px solid #fff;
             border-radius: var(--radius-sm,3px); touch-action: none; z-index: 6; }
  .vbox .h.nw, .imgbox .h.nw { left: -7px; top: -7px; cursor: nwse-resize; }
  .vbox .h.ne, .imgbox .h.ne { right: -7px; top: -7px; cursor: nesw-resize; }
  .vbox .h.sw, .imgbox .h.sw { left: -7px; bottom: -7px; cursor: nesw-resize; }
  .vbox .h.se, .imgbox .h.se { right: -7px; bottom: -7px; cursor: nwse-resize; }
  .vbox .h.n, .imgbox .h.n { left: calc(50% - 7px); top: -7px; cursor: ns-resize; }
  .vbox .h.s, .imgbox .h.s { left: calc(50% - 7px); bottom: -7px; cursor: ns-resize; }
  .vbox .h.e, .imgbox .h.e { right: -7px; top: calc(50% - 7px); cursor: ew-resize; }
  .vbox .h.w, .imgbox .h.w { left: -7px; top: calc(50% - 7px); cursor: ew-resize; }
  /* rotation handles: small circles outside the corners - drag to spin around center */
  .vbox .rh { position: absolute; width: 13px; height: 13px; border-radius: 50%; background: var(--hue-amber);
              border: 2px solid #fff; z-index: 7; cursor: grab; touch-action: none; }
  .vbox .rh.nw { left: -22px; top: -22px; }
  .vbox .rh.ne { right: -22px; top: -22px; }
  .vbox .rh.sw { left: -22px; bottom: -22px; }
  .vbox .rh.se { right: -22px; bottom: -22px; }
  .vbox .cliprow { position: absolute; left: 6px; right: 6px; top: 5px; z-index: 6; display: none; align-items: center; gap: 5px; }
  .vbox:hover .cliprow { display: flex; }
  .vbox .cliprow select { flex: 1; font-size: var(--fs-label); background: rgba(0,0,0,.6); color: var(--text2); min-width: 30px; }
  .vbox .cliprow .cc { font-size: var(--fs-label); color: var(--text2); background: rgba(0,0,0,.6); border-radius: var(--radius,5px); padding: 1px 4px; white-space: nowrap; }
  .vbox .ctlrow { position: absolute; left: 6px; right: 6px; display: none; align-items: center;
                  gap: 5px; z-index: 6; background: rgba(0,0,0,.6); border-radius: var(--radius,5px); padding: 2px 5px; }
  .vbox:hover .ctlrow { display: flex; }   /* keep the preview clean; reveal controls on hover */
  .vbox .ctlrow input { flex: 1; min-width: 30px; }
  .vbox .ctlrow select { font-size: var(--fs-label); background: rgba(0,0,0,.6); color: var(--text2); border: 1px solid var(--border); flex: 1; }
  .vbox .ctlrow .lbl { font-size: var(--fs-label); color: var(--text2); min-width: 30px; text-align: right; }
  .tbox .ttext { color: #fff; font: 700 16px Arial, sans-serif; white-space: pre; outline: none;
                 min-width: 24px; min-height: 1em; cursor: text; text-shadow: 0 0 3px #000, 0 0 3px #000; }
  /* a text's background (textbg.js): under the letters, never in the way of the pointer */
  .tbox .tbg { position: absolute; z-index: -1; pointer-events: none; }
  .tbox .mv { position: absolute; left: -16px; top: -4px; cursor: move; color: var(--text2); user-select: none; z-index: 6; }
  .tbox .tc { position: absolute; left: -2px; top: -24px; z-index: 6; }   /* a <gg-color size="sm">: 26 x 18 of its own */
  .tbox .rz { background: var(--hue-amber); }
  .tbox .rh { position: absolute; width: 12px; height: 12px; border-radius: 50%; background: var(--hue-amber);
              border: 2px solid #fff; z-index: 7; cursor: grab; touch-action: none; }
  .tbox .rh.nw { left: -20px; top: -20px; } .tbox .rh.ne { right: -20px; top: -20px; }
  .tbox .rh.sw { left: -20px; bottom: -20px; } .tbox .rh.se { right: -20px; bottom: -20px; }
  /* freely-placed subtitle element (captions sourced from one chosen clip) */
  .subbox { position: absolute; cursor: move; touch-action: none; z-index: 2;
            outline: 1px dashed var(--hue-green); display: flex; align-items: center; justify-content: center; }
  .subbox .subtext { color: #fff; font: 700 16px Arial, sans-serif; text-align: center; padding: 0 6px;
                     white-space: nowrap; text-shadow: 0 0 3px #000, 0 0 3px #000; pointer-events: none; }   /* explicit <br> breaks only (matches the ASS render's \N, no auto-wrap) */
  .subbox .mv { position: absolute; left: -16px; top: -4px; cursor: move; color: var(--text2); user-select: none; z-index: 6; }
  .subbox .rz { background: var(--hue-green); }
  .subbox .rh { position: absolute; width: 13px; height: 13px; border-radius: 50%; background: var(--hue-amber);
                border: 2px solid #fff; z-index: 7; cursor: grab; touch-action: none; }
  .subbox .rh.nw { left: -22px; top: -22px; }
  .subbox .rh.ne { right: -22px; top: -22px; }
  .subbox .rh.sw { left: -22px; bottom: -22px; }
  .subbox .rh.se { right: -22px; bottom: -22px; }
  /* placeable image element (multiple, freely positioned + rotatable) */
  .imgbox { position: absolute; cursor: move; touch-action: none; z-index: 2; outline: 1px dashed var(--frame-blue); transform-origin: center center; }
  .imgbox img { width: 100%; height: 100%; object-fit: contain; display: block; pointer-events: none; }
  .imgbox.is-shape img { object-fit: fill; }   /* a shape's picture is one colour, stretched to the layer's proportion: the export scales it the same way */
  .imgbox .iclip { position: absolute; inset: 0; overflow: hidden; }   /* zoom/reframe crop + rounded corners */
  /* lost image file: hide the browser's broken-image glyph, label the box instead */
  .imgbox.img-missing img { visibility: hidden; }
  .imgbox.img-missing::after { content: "image missing - Replace it in the inspector"; position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center; text-align: center; padding: 6px;
    font-size: var(--fs-data); color: var(--muted); background: rgba(0,0,0,.25); }
  .imgbox .mv { position: absolute; left: -16px; top: -4px; cursor: move; color: var(--text2); user-select: none; z-index: 6; }
  .imgbox .rh { position: absolute; width: 13px; height: 13px; border-radius: 50%; background: var(--hue-amber);
                border: 2px solid #fff; z-index: 7; cursor: grab; touch-action: none; }
  .imgbox .rh.nw { left: -22px; top: -22px; }
  .imgbox .rh.ne { right: -22px; top: -22px; }
  .imgbox .rh.sw { left: -22px; bottom: -22px; }
  .imgbox .rh.se { right: -22px; bottom: -22px; }
  .imgbox.selected { outline: 2px solid var(--frame-blue) !important; box-shadow: 0 0 10px rgba(var(--frame-rgb),.5); }
  /* start screen (no project open) */
  #startprog { color: var(--text2); min-height: 0; font-size: var(--fs-body); }

  /* ===================== jumpcut.GG theme (Phase 2 reskin) ===================== */
  /* Design tokens (:root) now come from the shared gg-ui kit (gg-theme.css),
     linked in <head> before this <style>. App-specific rules below still win. */
  /* body / header / button / inputs / range base now from the gg-ui kit */
  h2, .panel h2, .sticky-head h2, .clips-head h2, .tgroup h4 { font-family:var(--f-head); }
  .badge { background:var(--chip); color:var(--text2); font-family:var(--f-mono); }
  .badge.hi { background:color-mix(in srgb, var(--hue-green) 45%, var(--well)); } .badge.mid { background:color-mix(in srgb, var(--hue-amber) 40%, var(--well)); } .badge.lo { background:color-mix(in srgb, var(--danger) 45%, var(--well)); }
  #status, .seg-time, .clip .meta input { font-family:var(--f-mono); }
  .hint, .sub { color:var(--muted); }
  /* panels */
  .panel.clips, .clips-head { background:var(--panel); }
  .clips-body, .panel.transcript { background:var(--bg); }
  .panel.transcript { position:relative; }
  .clips-head, .panel.clips { border-color:var(--border); }
  /* clip cards */
  /* focus is TONAL: a warmer card, no ring (an inset accent outline read as a
     neon AI tell). The tint carries the state alone, so it runs warmer than the
     old ringed version; .clip's grounded drop shadow stays. */
  /* "the selected layer plays this Merger" - tonal like the focused clip card,
     no accent ring. Warmer than the ringed version so the tint reads alone. */
  #timeline.focused { background:color-mix(in srgb, var(--lime) 16%, var(--panel)); transition:background .2s; }
  /* accents → lime */
  .tline.active { background:color-mix(in srgb, var(--lime) 14%, var(--card-sel)); }
  .w.cur, .w.now { background:rgba(var(--lime-rgb),.22); color:var(--text); }
  /* composer surfaces */
  .comp-canvaswrap { background:var(--panel); }
  .tgroup { background:var(--well); border-color:var(--border); }
  #workspace { background:var(--well); }
  #frame { background:#000; }
  /* output frame stays blue per design */
  #framemask { outline:2px solid var(--frame-blue); }
  .vbox { outline:2px solid var(--frame-blue); }
  .vbox.selected, .tbox.selected, .subbox.selected, #wmbox.selected { outline:2px solid var(--lime) !important; box-shadow:0 0 10px rgba(var(--lime-rgb),.5); }
  /* start screen shell/card/input/or-divider = .gg-start* from the kit */
  .start-logo { display:flex; }
  .start-field { display:flex; gap:8px; }

  /* gg-button hosts a real <button> in shadow DOM. Size it via the kit's CSS-var
     hooks, NOT by styling this host like a native button (that drew a button-in-a-button). */
  .start-go { flex:0 0 auto; --gg-btn-h:46px; --gg-btn-radius:10px; --gg-btn-pad:0 20px; }
  /* advanced-import "More options" disclosure + inline explanations */
  /* A disclosure is a TARGET, not a caption. At padding:2px it measured 16px
     tall, which is a poor thing to ask anyone to hit - and it was the control
     the press-shift bug bit hardest (owner, 2026-08-23). The row is wider than
     the text either way, so the padding costs nothing but a few pixels of card.
     The label stays the same size; only the hit area grows. */
  .start-more { display:flex; align-items:center; justify-content:flex-start; gap:5px; --gg-icon-size:11px; width:100%; text-align:left; margin:8px 0 0; padding:7px 0; background:none; border:none;
                box-shadow:none; font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.05em;
                color:var(--muted); cursor:default; }
  .start-more:hover { color:var(--text2); }
  /* it has no shadow to drop, so its press reads on the label */
  .start-more:active { color:var(--text); filter:none; }
  .start-more-hint { font-size:var(--fs-data); line-height:1.45; color:var(--muted); margin:3px 2px 8px; }
  /* Import options rows (2026-08-23). The problem to solve was ragged: each
     control sized to its own text, so Language / Speed / Device ended at three
     different right edges and the native device <select> - whose options carry
     full adapter names - ran wider than the card itself.
     ONE label column and controls that fill what is left, so every row starts
     and ends on the same two lines. No rules, no boxes: alignment is the
     grouping, which is what def2 uses instead of borders. */
  .more-sec { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.08em;
              text-transform:uppercase; color:var(--faint); margin:12px 2px 5px; }
  .mo-row { display:flex; align-items:center; gap:8px; margin-top:6px; }
  .mo-lbl { flex:0 0 64px; font-size:var(--fs-data); color:var(--muted); white-space:nowrap; }
  /* the kit's segmented is inline-flex and hugs its labels; these two ::part
     rules are the sanctioned way in - it exposes part="track"/"option" - and
     make it stretch with its options sharing the width evenly, so two-option
     and three-option rows still line up */
  .mo-row gg-segmented { flex:1 1 auto; min-width:0; display:flex; }
  .mo-row gg-segmented::part(track) { display:flex; width:100%; }
  .mo-row gg-segmented::part(option) { flex:1 1 0; text-align:center; padding-inline:6px; }
  /* the adapter list is the widest thing here by far - hold it to the column
     and let the name ellipsis rather than push the card open */
  .mo-row > select { flex:1 1 auto; min-width:0; max-width:100%; }
  .mo-row .start-input { flex:1 1 0; min-width:0; }
  /* demo build: honest notice on the start card (shown via body.demo-build) */
  .start-demo-note { display:none; font-family:var(--f-body); font-size:var(--fs-control); line-height:1.5;
                     background:var(--amber); color:var(--on-amber); border-radius:var(--radius-lg,9px);
                     padding:8px 12px; text-align:center; margin:8px 0 0; }
  body.demo-build .start-demo-note { display:block; }
  /* (the start page's own rules - the home window, its recents and its status row - are css/home.css) */
  /* a dialog's title: the title face (DESIGN-2.0-PLAN.md). The brush face is the logo's. */
  .set-title { font-family:var(--f-head); font-weight:700; font-size:var(--fs-title); letter-spacing:-.01em; color:var(--text); }
  .set-row { display:flex; align-items:flex-start; gap:11px; padding:6px 2px; }
  /* Animation panel: keyframe group (toggle + chips) above, quick FX/origin below */
  .ia-div { height:1px; background:var(--divider, rgba(128,128,128,.18)); margin:1px 0; }
  .ia-chips { display:flex; flex-wrap:wrap; gap:4px; }
  .ia-chip { display:inline-flex; align-items:center; gap:5px; background:var(--well);
             border-radius:var(--radius,5px); padding:2px 7px; font:600 var(--fs-label) var(--f-mono);
             color:var(--text2); cursor:default; user-select:none; }
  .ia-chip:hover { background:var(--control); color:var(--text); }
  .ia-chip .x { color:var(--muted); padding:0 1px; }
  .ia-chip .x:hover { color:var(--danger); }
  /* keyframe-mode chrome (3ds Max auto-key cue, scoped to the SELECTED Animating
     object): the Animation panel tinted, the canvas-bounds outline at double width with a
     KEYFRAME MODE stamp, the object's selection chrome and its timeline row label.
     ONE colour for all of it, the accent - the button is the accent when the mode is on,
     and the frame and stamp used to be record-red beside it, with an amber Clear: three
     colours for one state (DESIGN-2.0-PLAN.md, batch 4). Red is left for the refusal below. */
  .vbox.recording.selected, .tbox.recording.selected, .subbox.recording.selected,
  #wmbox.recording.selected { outline-color: var(--lime) !important; box-shadow: 0 0 10px rgba(var(--lime-rgb),.5); }
  .imgbox.recording.selected { outline-color: var(--lime) !important; box-shadow: 0 0 10px rgba(var(--lime-rgb),.5); }
  #inspector .insp-anim.recording { background: color-mix(in srgb, var(--lime) 12%, var(--well)); }
  #workspace.kf-recording #framemask { outline: 4px solid var(--lime); }
  .kf-stamp { display:none; position:absolute; top:calc(100% + 6px); left:50%; transform:translateX(-50%);
              font:600 var(--fs-label) var(--f-mono); letter-spacing:.14em; text-transform:uppercase; color:var(--lime);
              pointer-events:none; white-space:nowrap; }   /* BELOW the frame - never over content */
  #workspace.kf-recording .kf-stamp { display:block; }
  /* refused move on a kf-locked layer: transient note in the stamp spot + a red pulse.
     (The note and the mode stamp can't collide: the lock only exists with mode OFF.) */
  .kf-locked-note { position:absolute; top:calc(100% + 6px); left:50%; transform:translateX(-50%);
                    font:600 var(--fs-label) var(--f-mono); letter-spacing:.14em; text-transform:uppercase; color:var(--danger);
                    pointer-events:none; white-space:nowrap; opacity:0; transition:opacity 120ms; }
  .kf-locked-note.show { opacity:1; }
  @keyframes kfLockPulse {
    0%, 100% { box-shadow: 0 0 10px rgba(var(--frame-rgb), .5); }
    50% { box-shadow: 0 0 0 3px var(--danger), 0 0 16px rgba(224,88,79,.8); }
  }
  .kf-locked-pulse { animation: kfLockPulse .45s ease-in-out 2; }
  .cs-row.recording .cs-rlabel { background: color-mix(in srgb, var(--lime) 20%, var(--well)); color: var(--text); }
  /* keyframed prop marker while Animating: the value reading turns lime with a small
     diamond. NB the marker must live INSIDE the value span - inspector labels are grid
     containers, and a ::before on the label itself becomes an extra grid item that
     shifts every column (the squished-sliders bug, 2026-08-08). */
  /* the ◆ hangs OUTSIDE the fixed 24px value column (absolute, off the left edge) -
     inline it widened the .lbl past the column and horizontally scrolled the panel */
  #inspector label.keyed .lbl, #inspector label.kflock .lbl { position:relative; }
  #inspector label.keyed .lbl::before, #inspector label.kflock .lbl::before {
    content:"◆"; font-size:var(--fs-label); position:absolute; right:calc(100% + 2px); top:50%; transform:translateY(-50%); }
  #inspector label.keyed .lbl { color:var(--lime); }
  /* keys exist but keyframe mode is OFF: the prop is locked. Same ◆ in danger red at
     rest; the handler refuses the edit with a pulse + the below-canvas note. Clicking
     the red value swaps the row into an inline delete-keyframes action. */
  #inspector label.kflock .lbl { color:var(--danger); cursor:default; }
  #inspector label.kfconfirm > input[type=range], #inspector label.kfconfirm > .lbl { display:none; }
  #inspector .kfdel { grid-column:2 / -1; color:var(--danger); cursor:default; font-size:var(--fs-data);
                      white-space:nowrap; text-align:right; }
  #inspector .kfdel:hover { text-decoration:underline; }
  /* Text bounds: a right-edge grip that sets the width the text wraps into, and
     a hairline showing where those bounds are - only while the layer is selected,
     since it is an editing aid rather than part of the composition. */
  .tbox .wz { position:absolute; right:-7px; top:12px; bottom:12px; width:12px; cursor:ew-resize;
              display:none; touch-action:none; }
  .tbox .wz::after { content:""; position:absolute; left:5px; top:0; bottom:0; width:2px;
                     background:var(--coral, #ff6b57); opacity:.85; border-radius:var(--radius-sm,3px); }
  .tbox.sel .wz, .tbox:hover .wz { display:block; }
  .tbox.sel.boxed .ttext { box-shadow:0 0 0 1px rgba(255,107,87,.35); }
  .plugin-body { padding:2px 0 4px; }   /* plugin panels bring their own layout inside */
  /* The plugins modal has its own item block. It used to borrow .set-row /
     .set-hint from Settings, which is a toggle-and-label idiom: 11px incidental
     text, one line tall. A plugin item is a name, a description, what it
     declares and what it was granted - card content, and the description is copy
     you are meant to READ, not a hint. This list is a surface you rest on, so it
     takes the generous end of the density hierarchy. */
  /* Widen the CARD, not its contents: gg-modal's card is width:var(--gg-modal-w,
     480px) with overflow:auto, so a section wider than the card scrolls the card
     sideways instead of growing it. The custom property crosses the shadow
     boundary; a min-width on the section cannot. */
  #pluginsmodal { --gg-modal-w:620px; }
  #pluginsmodal .set-line .set-hint { font-size:var(--fs-control); line-height:1.55; color:var(--text2); }
  #plugins_list { display:flex; flex-direction:column; gap:7px; padding:4px 0 2px;
                  max-height:54vh; overflow-y:auto; overflow-x:hidden; }
  .plug-item { display:flex; align-items:flex-start; gap:11px; cursor:default;
               background:var(--card); border-radius:var(--radius-lg,9px); padding:10px 12px;
               transition:background 120ms ease; }
  .plug-item:hover { background:var(--control); }
  .plug-item gg-toggle { flex:0 0 auto; margin-top:1px; }
  .plug-main { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:3px; }
  .plug-head { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
  .plug-name { font-size:var(--fs-body); font-weight:600; color:var(--text); }
  .plug-meta { font-size:var(--fs-data); color:var(--muted); }   /* version/author/state: reference, not reading */
  /* a single unbroken hostname or a description with no spaces must wrap, not
     widen the item - the item is what decides the card's width */
  .plug-desc { font-size:var(--fs-control); line-height:1.5; color:var(--text2); overflow-wrap:anywhere; }
  .plug-declares { font-size:var(--fs-data); line-height:1.45; color:var(--muted); overflow-wrap:anywhere; }
  .plug-err { font-size:var(--fs-control); line-height:1.45; color:var(--danger); }
  .plug-warn { font-size:var(--fs-control); line-height:1.45; color:var(--warn, #e0a63f); }
  .plug-hosts { display:flex; flex-wrap:wrap; gap:4px; padding-top:2px; }
  /* floating plugin panel: non-modal so the canvas stays visible while inserting */
  .plugin-float { position:fixed; top:64px; right:20px; width:400px; max-height:76vh;
                  display:flex; flex-direction:column; z-index:60;
                  background:var(--panel); border-radius:var(--radius-lg,9px);
                  box-shadow:0 10px 28px rgba(0,0,0,.45); }
  .plugin-float:not(.docked) { max-width:calc(100vw - 8px); }   /* never wider than the window it is drawn in */
  .plugin-float.sized { max-height:calc(100vh - 8px); }         /* resized by hand: its own height, up to the window's */
  .plugin-float.docked.sized { max-height:none; }
  .plugin-float-head { display:flex; align-items:center; gap:8px; padding:9px 12px 7px;
                       cursor:grab; user-select:none; touch-action:none; }
  .plugin-float-head:active { cursor:grabbing; }
  .plugin-float-title { font-weight:600; }
  .plugin-float-x { border:none; background:none; color:var(--muted); cursor:default;
                    font-size:var(--fs-control); padding:2px 6px; border-radius:var(--radius,5px); }
  .plugin-float-x:hover { color:var(--text); background:var(--control); }
  .plugin-float .plugin-body { overflow-y:auto; padding:0 12px 12px; flex:1; min-height:0; }
  /* Docked into the inspector rail: the SAME element, restyled and repositioned.
     The frame inside is never reparented - re-inserting an iframe discards its
     document, which would restart the plugin on every selection change. Sitting
     on the rail rather than floating over the canvas, it drops the shadow and
     the drag/resize affordances it no longer has. */
  .plugin-float.docked { box-shadow:none; max-height:none; background:var(--card); }
  .plugin-float.docked .plugin-float-head { cursor:default; }
  .plugin-float.docked .plugin-float-rz { display:none; }
  /* its own column beside the inspector: a panel, not a card sat on one */
  .plugin-float.docked-col { background:var(--panel); }
  .plugin-float-dockmode { border:none; background:none; color:var(--muted); cursor:default;
                           font-size:var(--fs-control); padding:2px 6px; border-radius:var(--radius,5px); line-height:1; }
  .plugin-float-dockmode:hover { color:var(--text); background:var(--control); }
  .plugin-float-pop { font-size:var(--fs-body); }   /* "open in its own window": the same button, a larger glyph */
  /* the rail does not scroll at rest; while something is docked over its lower
     part it has to, or the last section is unreachable behind the panel */
  #inspector.has-dock { overflow-y:auto; overflow-x:hidden; }
  .plugin-float-rz { position:absolute; right:1px; bottom:1px; width:15px; height:15px;
                     cursor:nwse-resize; touch-action:none;
                     background:linear-gradient(135deg, transparent 55%, var(--muted) 55%, var(--muted) 62%,
                                transparent 62%, transparent 72%, var(--muted) 72%, var(--muted) 79%, transparent 79%);
                     opacity:.5; border-bottom-right-radius:var(--radius-lg,9px); }
  .plugin-float-rz:hover { opacity:.9; }
  .set-txt { display:flex; flex-direction:column; gap:2px; font-size:var(--fs-body); color:var(--text); }
  .set-hint { font-size:var(--fs-data); color:var(--muted); line-height:1.4; }
  /* a dialog's groups are named, not ruled off: a mono caption (.set-cap) starts each */
  .set-sec { padding:4px 0 8px; min-width:340px; }
  .set-cap { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.14em; text-transform:uppercase; color:var(--text2); padding:8px 2px 4px; }
  .set-line { display:flex; align-items:center; gap:10px; padding:5px 2px; font-size:var(--fs-body); color:var(--text); }
  .brand-thumb { height:26px; max-width:110px; object-fit:contain; background:var(--well);
                 border:none; border-radius:var(--radius,5px); padding:2px 4px; }
  .brand-thumb.wide { max-width:160px; }
  .set-lbl { flex:0 0 150px; color:var(--text2); }
  .set-line select { flex:1; }
  .set-path { flex:1; min-width:0; font-family:var(--f-mono); font-size:var(--fs-label); color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #startscreen .row { display:flex; gap:8px; }
  /* transcription speed (Quick / Balanced) segmented control */
  /* (start-screen Device/Speed toggles moved into Settings - their styles went with them) */
  /* content-rights consent · fetch is disabled until checked, required each time */
  .consent { display:flex; align-items:flex-start; gap:8px; margin:2px 2px 0; cursor:default;
             font-family:var(--f-body); font-size:var(--fs-control); color:var(--text2); line-height:1.4; text-align:left; }
  .consent input { margin:2px 0 0; flex:0 0 auto; width:15px; height:15px; accent-color:var(--accent,#5b8cff); cursor:default; }
  .consent.flash { animation:consentflash .5s ease; }
  /* held on by another option (Re-fetch forces Transcribe again). Dimmed and
     not-allowed rather than hidden: the setting is still TRUE and worth seeing,
     it just is not yours to change while the other one is on. */
  .consent.forced { opacity:.55; cursor:not-allowed; }
  .consent.forced input { cursor:not-allowed; }
  @keyframes consentflash { 0%,100%{color:var(--text2)} 30%{color:var(--danger-hi)} }
  .loadcard { display:none; width:300px; max-width:26vw; margin:0; padding:16px 18px; }   /* shell = .gg-dock.r */
  .loadcard.show { display:block; }
  .loadcard .lc-row { display:flex; align-items:center; gap:10px; }

  .lc-stage { font-family:var(--f-head); font-weight:600; font-size:var(--fs-title); color:var(--text); }
  .lc-pct { margin-left:auto; font-family:var(--f-mono); font-size:var(--fs-control); color:var(--lime); }
  .lc-bar { margin-top:11px; }   /* bar/fill/indet = .gg-bar from the kit */
  .lc-detail { margin-top:8px; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); min-height:1.1em; overflow-wrap:anywhere; }
  /* the stall line: warn-toned so a quiet import reads differently from its
     ordinary detail text, without becoming an error state - it may still finish */
  .lc-stall { margin-top:6px; font-size:var(--fs-data); color:var(--warn, #e0a63f); overflow-wrap:anywhere; }

  /* ---- the import screen (IMPORT-SCREEN-PLAN.md) ----
     100065: above the header (100060) and the start screen (100050) because an
     import owns the app while it runs, but below gg-modal (100070) so a confirm
     or the guide can still open over it. Generous padding - this is a screen you
     WAIT at, not one you work in. */
  .impscreen { position:fixed; inset:0; z-index:100065; display:flex;
               align-items:center; justify-content:center;
               background:radial-gradient(120% 90% at 50% 0%, var(--panel) 0%, var(--bg) 60%); }
  .impscreen.show { display:flex; }
  .imp-card { width:560px; max-width:92vw; background:var(--card, var(--panel)); border-radius:var(--radius-lg,9px);
              padding:26px 28px 22px; box-shadow:0 10px 30px rgba(0,0,0,.45); }
  .imp-head { display:flex; align-items:baseline; gap:10px; }
  .imp-stage { font-size:var(--fs-title); font-weight:600; flex:1 1 auto; }
  .imp-elapsed { font-family:var(--f-mono); font-size:var(--fs-control); color:var(--muted); font-variant-numeric:tabular-nums; }
  /* what is actually being fetched - the line that would have shown a playlist
     immediately, because the id on screen would not match the id pasted */
  .imp-what { margin-top:6px; font-size:var(--fs-body); color:var(--text2); overflow-wrap:anywhere; min-height:1.2em; }
  .imp-bar { margin-top:14px; }
  .imp-detail { margin-top:8px; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted);
                min-height:1.1em; overflow-wrap:anywhere; }
  .imp-stall { margin-top:6px; font-size:var(--fs-control); color:var(--warn, #e0a63f); overflow-wrap:anywhere; }
  .imp-steps { margin-top:12px; display:flex; flex-direction:column; gap:3px;
               font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); }
  .imp-steps span { font-variant-numeric:tabular-nums; }
  /* errors get ROOM. The whole complaint was a failure with nowhere to be read. */
  .imp-err { margin-top:14px; padding:12px 14px; border-radius:var(--radius,5px); background:var(--well);
             color:var(--danger, #e06c5a); font-size:var(--fs-body); line-height:1.5;
             max-height:34vh; overflow:auto; overflow-wrap:anywhere; white-space:pre-wrap; }
  .imp-actions { margin-top:18px; display:flex; gap:8px; justify-content:flex-end; }
  .lc-queue { margin-top:12px; border-top:1px solid var(--border); padding-top:10px; }
  .lcq-title { font-family:var(--f-head); font-size:var(--fs-data); font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--muted); margin-bottom:7px; }
  /* queue rows = .gg-queue-* from the kit */
  .loadcard.error { border-color:var(--danger); }
  .loadcard.error .lc-spin { display:none; }
  .loadcard.error .lc-stage { color:var(--danger); }
  /* ---- inline "add a source" panel (lives in the center column; the rest of the
     editor · clips, merger, composer · stays put while fetching) ---- */
  .srcadd { flex:1 1 auto; min-height:0; display:flex; align-items:center; justify-content:center;
            padding:24px; background:radial-gradient(120% 90% at 50% 0%, var(--panel) 0%, var(--well) 70%); }
  .srcadd-card { width:460px; max-width:100%; display:flex; flex-direction:column; align-items:stretch; gap:13px; }
  .srcadd-title { font-family:var(--f-head); font-weight:700; font-size:var(--fs-title); color:var(--text); text-align:center; }
  .srcadd-sub { text-align:center; color:var(--text2); font-size:var(--fs-control); line-height:1.5; margin-bottom:2px; }
  .srcadd-actions { display:flex; justify-content:center; margin-top:2px; }
  /* the shared loadcard is reparented here during an inline fetch → make it flow in-card */
  #srcadd .loadcard { position:static; transform:none; right:auto; top:auto; width:100%; max-width:none;
                      margin:0; border-radius:var(--radius-lg,9px); }
  /* ---- brand logo (raster wordmark from /img) ---- */
  .brand-logo { height:26px; width:auto; display:block; flex:0 0 auto; }
  .brand-logo.big { height:60px; margin:14px 0 22px; }   /* the start page sets its own (home.css) */
  /* ---- Clip Merger dock ---- */
  .timeline { background:var(--panel); padding:9px 12px; }
  .tl-title { font-family:var(--f-head); font-weight:600; font-size:var(--fs-body); color:var(--text); }
  .tl-head .hint { margin-left:6px; }
  .tl-ruler { position:relative; height:13px; margin:6px 0 3px; border-bottom:1px solid var(--divider); }
  .tl-ruler span { position:absolute; top:0; font-family:var(--f-mono); font-size:var(--fs-label); color:var(--faint); transform:translateX(-50%); }
  .tl-ruler span:first-child { transform:none; }
  .tl-ruler span:last-child { transform:translateX(-100%); }   /* keep the last timestamp inside the panel */
  /* hybrid slicer: duration-true card widths (JS sets flex-basis, 56px floor),
     horizontal scroll for long sequences, edge-trim handles, word-texture strip */
  .tl-track { position:relative; flex:1 1 auto; display:flex; gap:3px; overflow-x:auto; overflow-y:hidden; align-items:stretch; padding-bottom:2px; }
  .tl-item { flex:0 0 auto; min-width:0; max-width:none; background:var(--card); border:none; border-radius:var(--radius,5px);
             padding:9px 10px; color:var(--text2); position:relative; cursor:grab; overflow:hidden;
             display:flex; flex-direction:column; gap:4px;
             background-size:cover; background-position:center; }   /* first-frame backdrop (JS sets the image + scrim) */
  .tl-item .t, .tl-item .d, .tl-item .wstrip { position:relative; text-shadow:0 1px 2px rgba(0,0,0,.6); }
  .tl-item .t { font-weight:600; font-size:var(--fs-body); line-height:1.25; color:var(--text); white-space:nowrap;
                overflow:hidden; text-overflow:ellipsis; }
  .tl-item .wstrip { font-family:var(--f-mono); font-size:var(--fs-label); color:rgba(255,255,255,.88); white-space:nowrap;
                     overflow:hidden; text-overflow:ellipsis; }   /* near-white: --faint sank into the frame backdrops */
  .tl-item .wstrip span.on { color:var(--lime); }   /* the word playback just reached */
  .tl-item.narrow { padding:6px 6px; }
  .tl-item.narrow .t, .tl-item.narrow .wstrip { display:none; }
  .tl-item .tl-trim { position:absolute; top:0; bottom:0; width:8px; cursor:ew-resize; z-index:4;
                      opacity:0; transition:opacity .12s; }
  .tl-item .tl-trim.l { left:0; border-radius:var(--radius,5px) 0 0 var(--radius,5px); }
  .tl-item .tl-trim.r { right:0; border-radius:0 var(--radius,5px) var(--radius,5px) 0; }
  .tl-item:hover .tl-trim { opacity:1; background:rgba(var(--lime-rgb), .3); }
  /* merger owns playback: the transcript stays a readout (highlight continues) but steps back */
  .panel.transcript { transition:opacity .12s; }
  .panel.transcript.dimmed { opacity:.55; }
  .tl-item .d { font-family:var(--f-mono); font-size:var(--fs-label); color:var(--muted); margin-top:auto; }
  .tl-track.tl-dropzone { outline:2px dashed var(--lime); outline-offset:-3px; background:rgba(var(--lime-rgb),.06); border-radius:var(--radius,5px); }
  .tl-item .d { color:var(--muted); font-family:var(--f-mono); font-size:var(--fs-label); }
  .tl-playhead { position:absolute; top:0; bottom:0; left:0; width:2px; background:var(--lime); z-index:3; pointer-events:none; opacity:0; box-shadow:0 0 5px var(--lime); transition:left .06s linear, opacity .12s; }
  .tl-playhead.live { pointer-events:auto; cursor:ew-resize; }   /* a visible needle is a drag handle; hidden it must not eat clicks */
  .tl-playhead::after { content:""; position:absolute; top:0; bottom:0; left:-5px; right:-5px; }   /* grab zone wider than the 2px line */
  .tl-ruler:not(:empty) { cursor:ew-resize; }   /* the ruler doubles as the scrub strip */
  /* ---- clip cards (design layout) ---- */
  /* per-clip identity marker (unique color + shape) */
  .clip-id { width:12px; height:12px; flex:0 0 auto; display:inline-block; vertical-align:middle; background:var(--cc,#888); }
  .clip-id.sh-circle { border-radius:50%; }
  .clip-id.sh-square { border-radius:var(--radius-sm,3px); }
  .clip-id.sh-triangle { clip-path:polygon(50% 0,100% 100%,0 100%); }
  .clip-id.sh-diamond { clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%); }
  .clip-id.sh-hex { clip-path:polygon(25% 0,75% 0,100% 50%,75% 100%,25% 100%,0 50%); }
  .tl-item .clip-id { width:15px; height:15px; margin-right:6px; }   /* identity icon, inline with the clip text */
  /* .cl-btn / .gg-tp-btn are gg-button HOSTS (real button is in shadow DOM). Size them via
     the kit's CSS-var hooks; never set background/border/hover on the host or it double-boxes. */
  /* flat/segmented/toggle/icon controls opt OUT of the raised-button shadow + press-shift */
  .canvas-ctl button, .mk-chip, .cliptabs .ctab, #inspector .insp-header button,
  .tl-item .x, .clip .title { box-shadow:none; }
  /* ---- right-click context menu ---- */
  /* context menu = .gg-menu family from the kit */
  /* ---- top bar ---- */
  /* The header row is gone: its last live controls moved to the menu bar and
     the Composer header, so the whole chrome is now the 30px bar against the
     old 54px row. It stays in the DOM holding buttons that are clicked by id -
     see the comment on the element. */
  header { display:none; }
  /* .gg-pill (import pills) + .gg-cut (top action) come from the gg-ui kit */
  .sb-status { font-family:var(--f-mono); font-size:var(--fs-data); color:var(--lime); max-width:340px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #status_sep:has(+ .sb-status:empty) { display:none; }   /* divider precedes the text now */
  .sb-hint { color:var(--text2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .sb-hint:empty, .sb-hint:empty + .sb-sep { display:none; }
  .sb-save { font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); }
  .sb-save:not(:empty)::before { content:"·"; color:var(--faint); margin:0 8px 0 0; }
  .sb-save.pending { color:var(--text2); }
  .sb-save.error { color:var(--danger); }
  /* what is wrong now (errbar.js): a tonal danger fill, as .badge.lo; hover deepens the fill */
  .sb-err { display:none; margin-left:8px; padding:1px 8px; border-radius:var(--radius,5px); font-family:var(--f-mono); font-size:var(--fs-data);
            color:var(--text); background:color-mix(in srgb, var(--danger) 45%, var(--well)); white-space:nowrap; max-width:460px; overflow:hidden; text-overflow:ellipsis; transition:background .12s; }
  .sb-err.on { display:inline-block; }
  .sb-err:hover { background:color-mix(in srgb, var(--danger) 60%, var(--well)); }
  /* in the Edit / Plugins / Help menus now; still in the DOM, still clicked by
     id, still bound without null guards. Used by the status bar AND the start
     screen's corner - one class, because it means one thing. */
  .sb-moved { display:none; }

  @keyframes txpulse { 0%{box-shadow:0 0 0 0 rgba(var(--lime-rgb),.5);} 70%{box-shadow:0 0 0 7px rgba(var(--lime-rgb),0);} 100%{box-shadow:0 0 0 0 rgba(var(--lime-rgb),0);} }
  /* ---- tighten-clip modal ---- */
  .tt-body { display:flex; flex-direction:column; gap:12px; min-width:340px; max-width:430px; }
  .tt-sub { line-height:1.45; }
  .tt-line { display:flex; align-items:center; gap:12px; }
  .tt-lbl { flex:0 0 auto; font-size:var(--fs-control); color:var(--text2); }
  .tt-fillers { display:flex; align-items:center; gap:8px; font-size:var(--fs-control); color:var(--text2); cursor:default; }
  .tt-fillers input { flex:0 0 auto; }
  /* a result, in plain body text: it was large coral mono, louder than the controls it reports on */
  .tt-stats { font-size:var(--fs-body); font-weight:500; color:var(--text); min-height:1.2em; }
  /* in-modal preview player (segpreview.js) - the source player may not even be on screen */
  .tt-player { background:#000; border-radius:var(--radius,5px); overflow:hidden; }
  .tt-player video { display:block; width:100%; max-height:250px; object-fit:contain; background:#000; }

  /* ---- voiceover recorder modal ---- */
  .rec-body { display:flex; flex-direction:column; gap:10px; min-width:340px; max-width:420px; }
  .rec-meter { height:10px; border-radius:var(--radius,5px); background:var(--well); overflow:hidden; }
  .rec-meter-fill { display:block; height:100%; width:0%; border-radius:var(--radius,5px);
                    background:linear-gradient(90deg,var(--lime),var(--warn)); transition:width .05s linear; }
  .rec-row { display:flex; align-items:center; gap:9px; }
  .rec-time { font-family:var(--f-mono); font-size:var(--fs-title); color:var(--text); }
  .rec-dot { width:11px; height:11px; border-radius:50%; background:var(--faint); flex:0 0 auto; }
  .rec-dot.on { background:var(--danger); animation:txpulse 1.4s infinite; }
  .rec-actions { display:flex; align-items:center; gap:8px; margin-top:2px; }

  /* ---- batch export modal ---- */
  .be-body { display:flex; flex-direction:column; gap:11px; min-width:360px; }
  .be-line { display:flex; align-items:center; gap:12px; }
  .be-lbl { flex:0 0 84px; font-size:var(--fs-control); color:var(--text2); }
  .be-grow { flex:1 1 auto; min-width:0; }
  /* split control: Queue Render | view queue - one visual unit, inner corners
     square, a 1px seam of header background as the divider */
  .hdr-split { display:inline-flex; align-items:stretch; }
  /* follow the chrome radius rather than a hard 5px, or a split control keeps
     the old corner after phase 4 brought the chrome down to 4 (and stays
     rounded in win95, which is square everywhere else) */
  .hdr-split gg-button:first-child { --gg-btn-radius: var(--chrome-r) 0 0 var(--chrome-r); }
  .hdr-split gg-button:last-child { --gg-btn-radius: 0 var(--chrome-r) var(--chrome-r) 0; margin-left:1px; }
  /* the ▾ half is narrow: it is a disclosure, not a second button */
  #rendermenu { --gg-btn-pad: 0 6px; font-size: var(--fs-data); }
  /* pin grid: 3x3 anchor dots + an off chip, tonal well (no hairlines).
     origin-grid shares the dot styling (inspector Origin row: no off chip) */
  .pin-grid, .origin-grid { display:inline-grid; grid-template-columns:repeat(3, 14px); gap:2px; padding:4px;
              background:var(--well); border-radius:var(--radius,5px); vertical-align:middle; align-items:center; }
  .pin-grid .pin-dot, .origin-grid .pin-dot { width:14px; height:14px; min-width:0; min-height:0; box-sizing:border-box;
                       border:none; border-radius:var(--radius-sm,3px); cursor:default; background:var(--control); padding:0; }
  .pin-grid .pin-dot:hover, .origin-grid .pin-dot:hover { background:var(--raise-hi, #343b45); }
  .pin-grid .pin-dot.on, .origin-grid .pin-dot.on { background:var(--lime); }
  .pin-grid .pin-off { grid-column:1 / -1; min-width:0; min-height:0; box-sizing:border-box;
                       border:none; border-radius:var(--radius,5px); cursor:default; margin-top:2px;
                       font:600 var(--fs-label) var(--f-mono); letter-spacing:.08em; text-transform:uppercase;
                       color:var(--muted); background:var(--control); padding:2px 0; }
  .pin-grid .pin-off:hover { color:var(--text); }
  .pin-grid .pin-off.on { color:var(--text); }
  .lcq-x { margin-left:auto; border:none; background:none; color:var(--muted); cursor:default; font-size:var(--fs-data); padding:1px 4px; border-radius:var(--radius,5px); }
  .lcq-x:hover { color:var(--text); background:var(--control); }
  .be-layouts { max-height:180px; overflow-y:auto; background:var(--well); border-radius:var(--radius-lg,9px); padding:4px 2px; }
  /* "Render with more layouts" modal: two be-layouts pick lists + a footer line */
  .ta-body { display:flex; flex-direction:column; gap:12px; min-width:440px; max-width:560px; }
  .ta-rows { display:flex; flex-direction:column; gap:8px; }
  .ta-row { display:flex; align-items:center; gap:12px; }
  .ta-lbl { flex:0 0 96px; display:flex; flex-direction:column; font-size:var(--fs-control); color:var(--text2); }
  .ta-lbl .ta-n { font-size:var(--fs-label); color:var(--muted); }
  .ta-sel { flex:1 1 auto; min-width:0; }
  .ml-body { display:flex; flex-direction:column; gap:10px; min-width:400px; }
  .ml-sec h4 { margin:0 0 4px; font:600 var(--fs-label) var(--f-mono); letter-spacing:.12em; text-transform:uppercase; color:var(--muted); }
  .ml-list { max-height:200px; }
  .be-layouts .blh { font:600 var(--fs-label) var(--f-mono); letter-spacing:.1em; text-transform:uppercase; color:var(--faint); padding:5px 9px 2px; }
  .be-layouts label { display:flex; align-items:center; gap:8px; padding:3px 9px; font-size:var(--fs-control); color:var(--text); cursor:default; border-radius:var(--radius,5px); }
  .be-layouts label:hover { background:var(--control); }
  .be-layouts .kbd2 { margin-left:auto; font-family:var(--f-mono); font-size:var(--fs-label); color:var(--muted); }
  .be-name { font-family:var(--f-mono); font-size:var(--fs-control); padding:5px 8px; background:var(--inset);
             border:1px solid var(--faint); border-radius:var(--radius-lg,9px); color:var(--text); }
  .be-name-prev { font-family:var(--f-mono); font-size:var(--fs-data); margin:-5px 0 0 96px;
                  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .be-warn { font-size:var(--fs-control); line-height:1.45; color:var(--amber,#f2b03c);
             background:rgba(255,140,0,.1); border:1px solid rgba(255,140,0,.35); border-radius:var(--radius-lg,9px); padding:7px 10px; }

  /* ---- Template Mode banner (composer is editing a template; the scene is stashed) ---- */
  /* tinted surface only - the 1px amber bottom border was the accent-hairline
     tell (same family as the removed modal top border); the tint IS the signal */
  .tpl-banner { display:flex; align-items:center; gap:9px; padding:7px 12px; flex:0 0 auto;
                background:rgba(255,140,0,.13); }
  .tpl-banner gg-icon { color:var(--amber,#f2b03c); --gg-icon-size:15px; }
  .tpl-banner-lbl { font:600 var(--fs-data) var(--f-mono); color:var(--amber,#f2b03c); text-transform:uppercase; letter-spacing:.08em; }
  #tpl_name { font:600 var(--fs-body) var(--f-head); color:var(--text); }
  .tpl-banner-hint { font:var(--fs-label) var(--f-mono); color:var(--muted); }

  /* ---- composer header + inspector polish ---- */
  .badge.out { background:rgba(79,143,245,.16); color:var(--hue-sky); border:1px solid rgba(79,143,245,.4); }
  .tgroup h4 { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); font-weight:500; }
  /* ---- composer Output panel (pinned at the bottom of the Layers column) ---- */
  /* .comp-output is now the Output <details> itself; co-body carries the field gap */
  .comp-output .co-field { display:flex; flex-direction:column; gap:5px; }
  .comp-output .co-label { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.12em; text-transform:uppercase; color:var(--muted); }
  .comp-output .cl-row { display:flex; align-items:center; gap:7px; }
  .comp-output .cl-input { width:78px; font-family:var(--f-mono); text-align:center; }
  .comp-output #comp_name { width:100%; text-align:left; }   /* the name field owns its column width */
  /* ---- right column: ONE section system, the LEFT column's boxed-foldout
     look (well surface, padded header row, divider when open - reads as
     click-to-expand). Sections: Layout / Output / Canvas & media. Sub-headers
     inside a section (Scene motion, Background, ...) stay head-font. */
  .out-sec { background:var(--well); border-radius:var(--radius-lg,9px); flex:0 0 auto; }
  .out-sec[open] { padding-bottom:10px; }
  .out-sec > summary { list-style:none; cursor:default; user-select:none; padding:9px 11px;
                       font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.14em;
                       text-transform:uppercase; color:var(--muted); }
  .out-sec > summary::-webkit-details-marker { display:none; }
  .out-sec > summary::before { content:"▸ "; color:var(--faint); }
  .out-sec[open] > summary::before { content:"▾ "; }
  .out-sec > summary:hover, .out-sec[open] > summary { color:var(--text2); }
  .out-sec[open] > summary { border-bottom:1px solid var(--divider); margin-bottom:9px; }
  .out-sec > *:not(summary) { margin-left:11px; margin-right:11px; }
  /* wide panel -> sections pair into a 2-col GRID. NOT css multicol: the panel
     is the scroll container (definite height), so multicol overflows sideways
     into clipped phantom columns - content vanished when heights shifted. */
  .comp-layers.two-col { display:grid; grid-template-columns:1fr 1fr; gap:10px; align-content:start; }
  .comp-layers.two-col > * { min-width:0; }
  .comp-layers.two-col > gg-button { grid-column:1 / -1; }   /* Render spans the row */
  /* NB: rules below outrank the generic `> *:not(summary)` side margins by
     file order - anything here that sets margin MUST carry the 11px sides */
  .out-sec .out-sub, .out-sec .tgroup h4 { font-family:var(--f-head); font-size:var(--fs-data); letter-spacing:.04em;
                       text-transform:uppercase; color:var(--text2); font-weight:700; }
  .out-sec .out-sub { margin:12px 11px 7px; }
  .out-sec .out-hint { font-size:var(--fs-data); line-height:1.45; color:var(--muted); margin-bottom:8px; }
  .co-body { display:flex; flex-direction:column; gap:9px; }
  /* fold internals: flat (no cards), breathing room + a divider between groups */
  .out-sec .tgroup { background:transparent; border-radius:0; padding:8px 0 6px; margin:0 11px; }
  .out-sec .tgroup + .tgroup { border-top:1px solid var(--divider); }
  .out-sec .tgroup h4 { margin:0 0 7px; }
  /* custom output size: full-width input (the placeholder must fit) + Set */
  .comp-output .aspect-custom-row { display:flex; gap:6px; }
  .comp-output .aspect-custom-row input { flex:1 1 auto; min-width:0; font-family:var(--f-mono); }
  .comp-output .aspect-custom-row gg-button { flex:0 0 auto; }
  .comp-output #comp_len_auto.on { --gg-btn-bg:var(--lime); --gg-btn-fg:var(--on-lime); }
  .comp-output .out-pick-foot select { width:100%; }
  .comp-output .outdir-path { display:block; width:100%; box-sizing:border-box; background:var(--inset); border:none;
                              border-radius:var(--radius,5px); padding:5px 8px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .comp-output .outdir-row { display:flex; align-items:center; gap:6px; margin:0; }
  .comp-output .outdir-row gg-button { flex:1 1 auto; }
  .comp-output #compcut2 { width:100%; }
  .tgroup.render .primary { font-family:var(--f-body); }
  .clips-head { position:relative; }
  /* ---- source panel eyebrow + collapse ---- */
  /* (legacy .src-head base removed; .gg-panel-head skeleton from the kit covers it) */

  #playerarea { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
  #playerarea #stage { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
  #playerarea video { width: auto; height: auto; max-height: 100%; max-width: 100%; object-fit: contain; }
  #newclip { flex:0 0 auto; }
  /* ---- custom player transport: .gg-transport / .gg-tp-* from the kit ---- */
  /* ---- marker bar (source-time markers: manual + auto audio-energy peaks) ---- */
  /* Three cells: the cut navigator under the transport's play, speed and time; the track EXACTLY under
     the slider (markeralign.js measures #tp_seek and sets --mk-l / --mk-r, so a clip at 0:00 and the
     slider's 0:00 are one x); the legend under the transport's right-hand buttons. An outer cell
     whose content is wider than its share grows, and the track gives way, never the buttons. */
  .marker-bar { display:grid; grid-template-columns:minmax(var(--mk-l, 0px), max-content) minmax(0, 1fr) minmax(var(--mk-r, 0px), max-content);
                align-items:center; padding:5px 14px 7px; background:var(--panel); flex:0 0 auto; }
  /* each cell is named: a hidden navigator must not hand its cell to the track */
  .marker-bar > .mk-cutnav { grid-column:1; grid-row:1; justify-self:start; margin-right:8px; }
  .marker-bar > .mk-track { grid-column:2; grid-row:1; }
  .marker-bar > .mk-legend { grid-column:3; grid-row:1; justify-self:end; margin-left:8px; }
  /* too narrow for the buttons beside the track (markeralign.js sets it): they take a second row,
     the navigator at the left and the legend at the right, and the track keeps the slider's span */
  .marker-bar.mk-stack > .mk-cutnav { grid-column:1 / 2; grid-row:2; margin:4px 0 0; }
  .marker-bar.mk-stack > .mk-legend { grid-column:2 / -1; grid-row:2; margin:4px 0 0; }
  .marker-bar.mk-stack > .mk-legend { flex-wrap:wrap; justify-content:flex-end; max-width:100%; }
  /* narrower still (the two together are wider than the bar): a row each, the legend wrapping */
  .marker-bar.mk-stack2 > .mk-cutnav { grid-column:1 / -1; grid-row:2; }
  .marker-bar.mk-stack2 > .mk-legend { grid-column:1 / -1; grid-row:3; }
  .mk-track { position:relative; flex:1 1 auto; height:14px; border-radius:var(--radius,5px); background:var(--inset); border:none; cursor:default; }
  .mk-playhead { position:absolute; top:-1px; bottom:-1px; width:2px; background:var(--text2); margin-left:-1px; pointer-events:none; }
  .mk { position:absolute; top:1px; bottom:1px; width:3px; margin-left:-1.5px; border-radius:var(--radius-sm,3px); cursor:default; }
  .mk.manual { background:var(--lime); }
  .mk.cut { background:var(--hue-sky); }
  .mk:hover { width:5px; margin-left:-2.5px; box-shadow:0 0 6px currentColor; }
  /* the focused clip's range (clipmarks.js): its own colour at a third, a grip at each end in the
     full colour; drawn before the ticks and the playhead, which paint over it. A hover deepens the
     fill - a tonal step, never an outline. */
  .mkc { position:absolute; top:0; bottom:0; min-width:8px; border-radius:var(--radius-sm,3px);
         background:color-mix(in srgb, var(--cc) 34%, transparent); transition:background .12s; }
  .mkc:hover { background:color-mix(in srgb, var(--cc) 46%, transparent); }
  .mkc-g { position:absolute; top:0; bottom:0; width:min(6px, 30%); background:var(--cc); }   /* a grip never covers the body: a narrow band keeps a middle to drag */
  .mkc-g.l { left:0; border-radius:var(--radius-sm,3px) 0 0 var(--radius-sm,3px); }
  .mkc-g.r { right:0; border-radius:0 var(--radius-sm,3px) var(--radius-sm,3px) 0; }
  body.mkc-dragging, body.mkc-dragging * { cursor:ew-resize !important; user-select:none; }
  .mkc.mkc-new { --cc:var(--lime); }   /* a clip being drawn by Shift+drag: lime until it is a clip with a colour of its own */
  /* a video layer dragged off the layer Timeline over Project or Clips (layertoclip.js): the list steps
     its surface while the hand is over it, and the hand shows a copy, as a drag between lists does */
  .trad-proj.ltc-drop .tp-rows, .clips-body.ltc-drop { background:rgba(var(--lime-rgb), .08); }
  body.ltc-over, body.ltc-over * { cursor:copy !important; user-select:none; }
  /* a clip's Start / End field with its to-playhead button beside it (clipedit.js) */
  .ce-v { display:flex; align-items:center; gap:3px; flex:1 1 auto; min-width:0; }
  .ce-v input { flex:1 1 auto; min-width:0; }
  .ce-v .ce-ph { flex:0 0 auto; }
  /* cut navigator · prev/next jumps between scene cuts (tied to the blue cut color) */
  .mk-cutnav { display:inline-flex; align-items:center; gap:1px; padding:2px; border-radius:var(--radius,5px); background:var(--inset); }
  /* what < > steps through, named with the dot of its ticks on the track (sky = cuts,
     accent = markers): the same dot the Markers / Cuts toggles carry. */
  .mk-cutnav-lbl { font-family:var(--f-body); font-size:var(--fs-data); font-weight:600; padding:0 6px; user-select:none; }
  .mk-cutnav-btn { --cnc:var(--hue-sky); border:none; cursor:default; min-width:56px;
                   align-self:stretch; display:inline-flex; align-items:center; justify-content:center; gap:5px;
                   border-radius:var(--radius-sm,3px); background:transparent; color:var(--text); transition:background .12s; }
  .mk-cutnav-btn::before { content:""; flex:0 0 auto; width:7px; height:7px; border-radius:50%; background:var(--cnc); }
  .mk-cutnav-btn.mode-marker { --cnc:var(--lime); }
  .mk-cutnav-btn:hover { background:var(--control); }
  .mk-step { display:inline-flex; align-items:center; justify-content:center; width:22px; height:18px; padding:0;
             background:none; border:none; border-radius:var(--radius,5px); color:var(--text2); cursor:default; --gg-icon-size:14px; transition:background .12s, color .12s; }
  .mk-step:hover { background:var(--control); color:var(--hue-sky); }
  .mk-step:disabled { opacity:.3; cursor:default; }
  /* Markers and Cuts are ordinary toggles: a dot in the colour of their ticks on the track,
     then the name. On is the dot filled and the name at full strength; off is the dot hollow
     and the name muted. They were blocks filled with the two colours, which made a show / hide
     switch the loudest thing under the player (DESIGN-2.0-PLAN.md, batch 4). */
  .mk-legend { display:inline-flex; align-items:center; gap:2px; }
  .mk-toggle { display:inline-flex; align-items:center; gap:6px; height:22px; padding:0 8px; border:none; border-radius:var(--radius,5px);
               background:none; font-family:var(--f-body); font-size:var(--fs-control); font-weight:600; color:var(--text); cursor:default; white-space:nowrap; transition:background .12s, color .12s; }
  .mk-toggle::before { content:""; flex:0 0 auto; width:7px; height:7px; border-radius:50%; background:var(--mkc); }
  .mk-toggle:hover { background:var(--control); }
  .mk-toggle.mk-manual { --mkc:var(--lime); }
  .mk-toggle.mk-cut { --mkc:var(--hue-sky); }
  .mk-toggle:not(.on) { color:var(--muted); }
  .mk-toggle:not(.on)::before { background:transparent; box-shadow:inset 0 0 0 1.5px var(--muted); }
  .mk-kbd { font-family:var(--f-mono); font-size:var(--fs-label); font-weight:400; color:var(--text2); background:var(--inset); border:none; border-radius:var(--radius-sm,3px); padding:0 4px; }
  .mk-toggle:not(.on) .mk-kbd { opacity:.6; }
  /* ---- bottom status bar ---- */
  /* .gg-statusbar container from the gg-ui kit; sb-* content is app-specific */
  .gg-statusbar .sb-sep { color:var(--faint); }
  .gg-statusbar .sb-mono { color:var(--text2); letter-spacing:.04em; }
  .gg-statusbar #sb_render.active { color:var(--lime); }
  .gg-statusbar #sb_render { cursor:default; }
  .gg-statusbar #sb_render:hover { color:var(--text); }
  .gg-statusbar .sb-out { cursor:default; max-width:200px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .gg-statusbar .sb-out:hover { color:var(--text); }
  .gg-statusbar .sb-cog { color:var(--text2); font-size:var(--fs-body); line-height:1; }
  .gg-statusbar .sb-cog:hover { color:var(--lime); }
  /* ---- render modal (shell .gg-overlay/.gg-card from the kit; internals below) ---- */
  /* ---- keyboard-shortcut cheat sheet (? key · js/shortcuts.js) ---- */
  #shortcutsmodal { z-index:100080; }   /* above everything - it's help, not workflow */
  .sc-card { width:690px; max-height:82vh; overflow-y:auto; }
  .sc-grid { display:grid; grid-template-columns:1fr 1fr; gap:6px 26px; margin-top:12px; }
  .sc-foot { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:14px; padding-top:12px; border-top:1px solid var(--divider); }
  .sc-modehint { font-family:var(--f-mono); font-size:var(--fs-label); color:var(--muted); }
  .sc-sec-title { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.14em; text-transform:uppercase; color:var(--text2); margin:10px 0 6px; }
  .sc-row { display:flex; align-items:baseline; gap:10px; padding:2.5px 0; }
  .sc-keys { flex:0 0 132px; display:flex; gap:3px; flex-wrap:wrap; }
  .sc-keys kbd { font-family:var(--f-mono); font-size:var(--fs-label); color:var(--text); background:var(--control);
                 border:none; border-radius:var(--radius-sm,3px); padding:2px 6px; }
  .sc-desc { font-size:var(--fs-body); color:var(--text); }
  /* ---- Load Project modal (in-app project picker from appdata) ---- */
  .lm-list { display:flex; flex-direction:column; gap:1px; overflow-y:auto; }
  .lm-empty { color:var(--muted); font-size:var(--fs-body); padding:18px 4px; text-align:center; }
  /* its rows are the kit's list row (.gg-list-row.two). They used to borrow .lm-row, which is
     ALSO the Learn dialog's row - a four-column grid whose first column is 14px - so a
     project's name was laid out in 14px and read "U.", under a wide Open pill. */
  /* audio waveform inside a timeline lane block (overlay layers, clip blocks, segment pieces) */
  .cs-ovblock .cs-wave, .cs-block .cs-wave, .cs-seg .cs-wave {
    position:absolute; inset:0; width:100%; height:100%; pointer-events:none; opacity:.85; }
  .cs-ovblock .cs-ovlabel, .cs-seg .cs-segtxt, .cs-seglabel { position:relative; }   /* labels read above the wave */
  /* music strip: no drag/trim, but clicking the waveform SELECTS the track
     (inspector: volume/duck), same as clicking any other lane's block.
     Blue = audio (matches the scene-cut blue family). */
  .cs-row-music .cs-ovblock.music { background:rgba(90,160,255,.12); box-shadow:none; cursor:default; }
  /* restore points inside the Open modal */
  .lm-snaps-head { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.12em; text-transform:uppercase;
                   color:var(--muted); margin:14px 2px 7px; }
  .lm-snap .lm-restore { flex:0 0 auto; }
  /* every overlay dialog's card holds its own Close: without this the Shortcuts sheet's and
     Exports' sat at the corner of the WINDOW, away from the dialog they close */
  .gg-overlay .gg-card { position:relative; }
  /* a destructive action at rest is red TEXT on an ordinary button; a red fill is for the
     button that confirms it (DESIGN-2.0-PLAN.md, colour roles) */
  gg-button.btn-danger-text { --gg-btn-fg:var(--danger-hi); }
  /* gg-button with [icon][size=sm]: the kit draws the square close button; only position it here. */
  .rm-x { position:absolute; top:9px; right:9px; z-index:1; }
  /* an overlay dialog's title row: the title, with Close at its end (.rm-x) */
  .dlg-title { font-family:var(--f-head); font-weight:700; font-size:var(--fs-title); letter-spacing:-.01em; color:var(--text); margin:-4px 40px 10px 0; }
  .rm-top { display:flex; gap:14px; align-items:center; margin-bottom:16px; }
  .rm-thumb { width:54px; height:96px; flex:0 0 54px; border-radius:var(--radius-lg,9px); background:linear-gradient(160deg,var(--card),var(--well));
              border:none; display:flex; align-items:center; justify-content:center; }
  .rm-spin { --gg-spin-size:20px; }
  .rm-check { width:54px; height:54px; flex:0 0 54px; border-radius:50%; background:rgba(var(--lime-rgb),.16);
              color:var(--lime); display:flex; align-items:center; justify-content:center; font-size:26px; }   /* tint carries it - no accent ring (banner precedent) */
  .rm-title { font-family:var(--f-head); font-weight:700; font-size:var(--fs-head); letter-spacing:-.01em; color:var(--text); }
  .rm-file, .rm-meta { font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); margin-top:3px; word-break:break-all; }
  .rm-folder { display:flex; align-items:center; gap:8px; margin:10px 0 12px; padding:7px 9px; border-radius:var(--radius-lg,9px);
               background:var(--well); border:none; }
  .rm-folder .rm-folder-path { flex:1 1 auto; min-width:0; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted);
               white-space:nowrap; overflow:hidden; text-overflow:ellipsis; direction:rtl; text-align:left; }
  .rm-folder gg-button { flex:0 0 auto; }
  .rm-bar { --gg-bar-h:8px; }
  .rm-stat { font-family:var(--f-mono); font-size:var(--fs-data); color:var(--text2); margin-top:9px; }
  .rm-stat.err { white-space:pre-wrap; overflow-wrap:anywhere; max-height:10em; overflow:auto; user-select:text; }   /* a failed render's message, whole and selectable */
  #rm_rendering.failed .rm-spin { display:none; }
  .rm-sub { font-family:var(--f-mono); font-size:var(--fs-label); color:var(--muted); margin-top:3px; min-height:1.1em; }
  .rm-foot { display:flex; align-items:center; gap:8px; margin-top:18px; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); }
  .rm-video { width:100%; max-height:42vh; border-radius:var(--radius-lg,9px); margin-bottom:14px; background:#000; }
  .rm-actions { display:grid; grid-template-columns:repeat(3, 1fr); gap:8px; }
  /* Play takes the row and the three others share the one under it. (Save as GIF left the
     card 2026-10-06, owner: a render is mostly long; Make GIF is in Exports.) */
  .rm-actions gg-button[variant="primary"] { grid-column:1 / -1; }
  /* the render dialog's first step (renderdlg.js): two field rows on the dialog's 38px row */
  .rd-line { display:flex; align-items:center; gap:8px; min-height:38px; }
  .rd-lbl { flex:0 0 58px; font-size:var(--fs-control); color:var(--text2); }
  .rd-input { flex:1 1 auto; min-width:0; height:30px; box-sizing:border-box; padding:0 9px; border:none; border-radius:var(--radius,5px);
              background:var(--well); color:var(--text); font-family:var(--f-mono); font-size:var(--fs-control); }
  .rd-ext::after { content:".mp4"; }   /* drawn, not text: a file extension is not a string to translate */
  .rd-ext { flex:0 0 auto; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); }
  .rd-path { flex:1 1 auto; min-width:0; height:30px; line-height:30px; box-sizing:border-box; padding:0 9px; border-radius:var(--radius,5px);
             background:var(--well); font-family:var(--f-mono); font-size:var(--fs-data); color:var(--text2);
             white-space:nowrap; overflow:hidden; text-overflow:ellipsis; direction:rtl; text-align:left; }
  .rd-line gg-button { flex:0 0 auto; }
  .rd-note { margin:2px 0 0 66px; font-family:var(--f-mono); font-size:var(--fs-label); color:var(--amber,#f2b03c); word-break:break-all; }
  .rd-sum { margin:12px 0 0; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); }
  /* the render settings: the card is wider while the first step is up, Video and Audio side by side */
  #rendermodal .gg-card.rd-wide { width:850px; }
  #rm_setup .rd-lbl { flex:0 0 96px; }
  #rm_setup .rd-note { margin-left:104px; }
  .rd-cols { display:flex; gap:22px; margin-top:8px; }
  .rd-col { flex:1 1 0; min-width:0; }
  .rd-col:first-child { flex:1.12 1 0; }
  .rd-head { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.12em; text-transform:uppercase; color:var(--muted); margin:6px 0 2px; }
  .rd-select { flex:1 1 auto; min-width:0; height:30px; }
  .rd-num { flex:0 0 96px; }
  .rd-unit { flex:0 0 auto; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); }
  .rd-unit-mbps::after { content:"Mbps"; }   /* drawn, as .rd-ext is: a unit is not a string to translate */
  .rd-unit-kbps::after { content:"kbps"; }
  .rd-preset gg-icon { margin-left:6px; }
  .rd-hint { margin-top:10px; font-size:var(--fs-label); line-height:1.45; color:var(--amber,#f2b03c); }
  .rd-hint:empty { display:none; }
  .rd-line.rd-off { opacity:.4; pointer-events:none; }
  /* ---- exports history list ---- */
  /* ---- background render queue (top of the Exports modal) ---- */
  .exq { border-bottom:1px solid var(--line, rgba(128,128,128,.25)); padding-bottom:10px; margin:4px 0 10px; }
  .exq-head { font-family:var(--f-mono); font-size:var(--fs-label); letter-spacing:.12em; text-transform:uppercase; color:var(--muted); margin:2px 0 6px; }
  .exq-row { display:flex; align-items:center; gap:10px; padding:5px 2px; }
  .exq-info { flex:1 1 auto; min-width:0; }
  .exq-name { font-size:var(--fs-control); color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .exq-sub { font-size:var(--fs-data); color:var(--text2); overflow-wrap:anywhere; display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; }
  .exq-row.error .exq-sub { color:var(--warn, #e66d3f); }
  .exq-bar { flex:0 0 120px; height:6px; border-radius:var(--radius-sm,3px); background:var(--chip); overflow:hidden; }
  .exq-bar span { display:block; height:100%; background:var(--lime, #ff8a2e); transition:width .4s; }
  .exq-clear { margin-top:6px; }
  /* ---- Exports: a full-height two-pane surface (queue + history | preview + detail).
     The preview cell is flex-bounded with object-fit contain, so a tall video can
     NEVER stretch the modal past the window (the old single-column overflow bug). ---- */
  .ex-card { width:min(1150px, 92vw); height:min(88vh, 940px); display:flex; flex-direction:column; }
  .ex-head { margin-bottom:10px; flex:0 0 auto; }
  .ex-body { flex:1 1 auto; min-height:0; display:flex; gap:16px; }
  .ex-left { flex:0 0 360px; min-width:0; display:flex; flex-direction:column; min-height:0; }
  .ex-right { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:10px; min-height:0; }
  .ex-preview { flex:1 1 auto; min-height:0; display:flex; align-items:center; justify-content:center;
                background:var(--well); border-radius:var(--radius-lg,9px); overflow:hidden; }
  .ex-preview video, .ex-preview img { max-width:100%; max-height:100%; object-fit:contain; display:block; }
  .ex-none { color:var(--muted); font-size:var(--fs-control); }
  .ex-detail { flex:0 0 auto; display:flex; align-items:center; gap:10px; padding:9px 12px;
               background:var(--well); border-radius:var(--radius-lg,9px); }
  .ex-dtext { min-width:0; }
  .ex-dname { font-size:var(--fs-body); color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .ex-dmeta { font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); margin-top:2px; }
  .ex-list { flex:1 1 auto; min-height:0; overflow-y:auto; margin:4px 0 0; display:flex; flex-direction:column; gap:1px; padding-right:2px; }
  .ex-empty { color:var(--muted); font-size:var(--fs-control); text-align:center; padding:24px 8px; }
  /* a list row, as the kit's .gg-list-row is: the panel showing through at rest, a surface
     step for hover and for selected (it was a rounded card per file, tinted coral when picked) */
  .ex-row { display:flex; align-items:center; gap:10px; min-height:44px; padding:0 10px; box-sizing:border-box;
            border-radius:var(--radius,5px); background:transparent; cursor:default; }
  .ex-row:hover { background:var(--control); }
  .ex-row.sel, .ex-row.sel:hover { background:var(--card-sel); }
  .ex-row .ex-info { flex:1 1 auto; min-width:0; }
  .ex-row .ex-name { font-size:var(--fs-body); font-weight:600; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .ex-row .ex-sub { font-family:var(--f-mono); font-size:var(--fs-label); color:var(--text2); margin-top:3px; }
  .ex-row .ex-kind { display:none; }   /* "mp4" beside a name that ends in .mp4 */
  /* ---- composer empty state ---- */
  /* the frame itself stays on screen at the output's shape; this is its size and one line, written over it.
     It was a small dashed stand-in in place of the frame, so an empty composition showed no canvas. */
  .comp-empty { display:none; position:absolute; inset:0; z-index:5; pointer-events:none; flex-direction:column; align-items:center; justify-content:center;
                gap:8px; box-sizing:border-box; text-align:center; color:var(--muted); padding:8%; line-height:normal; }
  .comp-stage.empty .comp-empty { display:flex; }
  .comp-stage.empty.has-bg .comp-empty { display:none; }
  .comp-empty .etitle { font-family:var(--f-mono); font-size:var(--fs-body); letter-spacing:.06em; color:var(--text2); }
  .comp-empty .ehint { font-size:var(--fs-control); max-width:200px; line-height:1.5; }
  .comp-empty .ehint b { color:var(--text2); }
  /* ---- empty states ---- */
  /* empty-state shell = .gg-empty from the kit (the eglyph brand mark below stays ours) */
  .empty .eglyph { width:46px; height:46px; border-radius:var(--radius-lg,9px); background:var(--well);
                   position:relative; opacity:.5; border:none; }
  .empty .eglyph::before { content:""; position:absolute; left:50%; top:9px; width:9px; height:9px;
                   transform:translateX(-50%); background:var(--faint); border-radius:var(--radius-sm,3px);
                   clip-path:polygon(0 0,100% 0,100% 38%,0 53%); }
  .empty .eglyph::after { content:""; position:absolute; left:50%; top:21px; width:9px; height:18px;
                   transform:translateX(-50%); background:var(--faint); border-radius:var(--radius-sm,3px);
                   clip-path:polygon(0 14%,100% 4%,100% 100%,0 100%); }

  .tl-empty { flex:1 1 auto; display:flex; align-items:center; justify-content:center;
              border:1px dashed var(--border); border-radius:var(--radius-lg,9px); margin:6px 10px 10px;
              color:var(--muted); font-size:var(--fs-control); }
  /* ---- output folder row (composer render group) ---- */
  .outdir-row { display:flex; align-items:center; gap:6px; margin-bottom:8px; }
  .out-pick-foot select { width:100%; }
  .outdir-path { flex:1 1 auto; min-width:0; font-family:var(--f-mono); font-size:var(--fs-data); color:var(--text2);
                 background:var(--inset); border:none; border-radius:var(--radius,5px);
                 padding:5px 8px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; direction:rtl; text-align:left; }
  /* ---- unified panel headers: Clips / Source / Composer (same height, title, flush collapse) ---- */
  /* unified panel-header skeleton (.gg-panel-head) comes from the gg-ui kit;
     the three headers carry it as a second class + their own specifics below */
  .grow { flex: 1 1 auto; }   /* global spacer · pushes trailing items (e.g. collapse chevrons) to the right */
  .panel-title { font-family:var(--f-head); font-weight:700; font-size:var(--fs-title); color:var(--text); white-space:nowrap; margin:0; }
  .gg-panel-head > gg-icon, .tl-head > gg-icon, .tr-headrow > gg-icon { color:var(--text2); --gg-icon-size:18px; margin-right:-4px; }
  .pt-count { font-family:var(--f-mono); font-size:var(--fs-data); color:var(--muted); }
  .src-select { font-family:var(--f-body); font-size:var(--fs-control); color:var(--text); background:var(--control); border:none; border-radius:var(--radius,5px); padding:4px 7px; max-width:240px; cursor:default; }
  .src-swatch { width:11px; height:11px; flex:0 0 11px; border-radius:var(--radius-sm,3px); display:none; box-shadow:0 0 0 1px rgba(0,0,0,.3) inset; }
  /* .gg-collapse (panel collapse chevron) comes from the gg-ui kit */
  .clips-subhead { flex:0 0 auto; padding:7px 14px 8px; border-bottom:1px solid var(--divider); background:var(--panel); }
  .clips-subhead .hint { font-size:var(--fs-data); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; color:var(--muted); margin:0; }
  /* EVERY modal must sit above the import/start overlay (.gg-start, z 100050)
     and above the header (z 100060), or it opens invisibly behind them and the
     header stays clickable through the backdrop.
     This was a hand-listed set of ids, so every modal added later inherited the
     kit's z 300 and broke: #langmodal and #projmodal both opened behind the
     start screen (2026-08-10). A type selector cannot fall out of date.
     NO !important - #shortcutsmodal (100080) and #askmodal (100090) must still
     be able to outrank this by id. */
  gg-modal { z-index:100070; }
  #askmodal { z-index:100090 !important; }   /* confirms sit above other modals (e.g. clear-cache from Settings) */
  .about-body { display:flex; flex-direction:column; align-items:center; gap:12px; min-width:300px; max-width:360px; margin:0 auto; text-align:center; padding:4px 2px 2px; }
  .about-ver { font-family:var(--f-mono); font-size:var(--fs-control); color:var(--muted); }
  .about-tagline { font-family:'Permanent Marker', 'Yu Gothic UI', 'Meiryo', cursive; font-weight:400; font-size:25px; color:var(--text); letter-spacing:.01em; line-height:1.1; }
  .about-stance { display:flex; flex-wrap:wrap; justify-content:center; gap:5px 14px; font-size:var(--fs-body); }
  .about-stance span { color:var(--lime); font-weight:600; }
  .about-drm { font-size:var(--fs-body); color:var(--text2); line-height:1.5; max-width:330px; }
  .about-drm i { color:var(--text); }
  .about-links { display:flex; justify-content:center; gap:18px; font-family:var(--f-mono); font-size:var(--fs-control); }
  /* ---- header groups + dividers ---- */
  /* .gg-hdr-sep from the kit */
  body.on-start .hdr-sep { display:none; }   /* landing screen header = logo only */
  /* active project-file indicator */
  .filestate { flex:0 0 auto; font-family:var(--f-mono); font-size:var(--fs-data); white-space:nowrap; max-width:200px;
               overflow:hidden; text-overflow:ellipsis; }
  .filestate:empty { display:none; }
  .filestate.saved { color:var(--muted); }
  .filestate.dirty { color:var(--amber, #f2b03c); }
  .filestate.nofile { color:var(--faint); font-style:italic; }
  .hdr-grp { display:flex; align-items:center; gap:5px; flex:0 0 auto; }
  /* ---- header project name ---- */
  /* It IS a <gg-button size="sm"> now, exactly like New / Open / Save / Undo
     beside it - not a hand-rolled button styled to resemble one. Every
     button property (fill, radius, padding, height, shadow, hover, press)
     comes from the component, so it cannot drift away from its neighbours
     again (owner, 2026-08-23). What is left here is only what is specific to
     showing a project NAME: a width limit, an ellipsis, and the muted look
     when there is no name yet. */
  .proj-name { max-width:220px; min-width:120px; overflow:hidden; }
  .proj-name gg-icon { --gg-icon-size:14px; flex:0 0 auto; }
  .proj-name #projname_txt { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
  .proj-name.empty #projname_txt { color:var(--faint); }
  /* first-run tutorial: spotlight ring (scrim via the 9999px shadow) + coach card */
  #coach_ring { position:fixed; z-index:100085; border:2px solid var(--lime); border-radius:var(--radius-lg,9px);
                pointer-events:none; display:none;
                transition:left .2s ease, top .2s ease, width .2s ease, height .2s ease;
                animation:coachpulse 1.6s ease-out infinite; }
  @keyframes coachpulse {
    0%,100% { box-shadow:0 0 0 9999px rgba(8,9,11,.55), 0 0 0 0 rgba(var(--lime-rgb),.55); }
    50%     { box-shadow:0 0 0 9999px rgba(8,9,11,.55), 0 0 0 7px rgba(var(--lime-rgb),0); }
  }
  #coach_card { position:fixed; left:50%; bottom:54px; transform:translateX(-50%); width:400px; max-width:90vw;
                z-index:100086; display:none; }
  #coach_card.show { display:block; }
  #coach_card p { font-size:var(--fs-body); line-height:1.5; margin:10px 0; }
  #coach_card #coach_prog { font-size:var(--fs-data); color:var(--lime); min-height:14px; margin:0 0 12px; }
  #coach_card .coach-actions { display:flex; justify-content:flex-end; gap:8px; }
  #coach_card [hidden] { display:none !important; }   /* hidden attr must beat the component's :host display */
  /* post-import nudge: breathe the accent on the name field a few times */
  /* import-screen cancel button: .gg-cut .gg-cancel (warm) from the gg-ui kit */
  /* .gg-start-ver / .gg-start-foot / .gg-link from the kit */


  /* ===================== Desktop feel — phase 6 =====================
     The invisible tells: the things that say "browser" without anyone being
     able to name why. DESKTOP-FEEL-PLAN.md phase 6. */

  /* 1. Chrome is not a document. Text you cannot act on should not select,
     drag-highlight blue, or show an I-beam. Scoped to the chrome ONLY - the
     transcript is the app's core interaction and #transcript keeps
     `user-select: text` above; inputs are exempted below or typing breaks. */
  header, .gg-statusbar, .cs-toolbar, .cliptabs, .sticky-head,
  .set-lbl, .set-hint, .set-title, .mo-lbl, .more-sec,
  .look-strip, .exq-head, .srcadd-title, .srcadd-sub {
    user-select: none; -webkit-user-select: none; cursor: default; }
  input, textarea, select, [contenteditable="true"], #transcript,
  .set-path, .imp-err {
    user-select: text; -webkit-user-select: text; cursor: auto; }

  /* 2. Slim themed scrollbars. Default browser scrollbars were the single
     loudest web tell left: nothing styled them at all, so every panel showed
     the OS/Chromium bar. Track is the surface it sits on, thumb is one step
     up - the same tonal ramp everything else uses, no borders. */
  * { scrollbar-width: thin; scrollbar-color: var(--raise-hi) transparent; }
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    background: var(--raise-hi); border-radius: var(--radius,5px);
    border: 3px solid transparent; background-clip: padding-box; }
  ::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: padding-box; }
  ::-webkit-scrollbar-corner { background: transparent; }

  /* Drop target (DESKTOP-FEEL phase 7). A tint and an inset accent edge on the
     whole window - not a modal, not a bouncing icon. It has to read instantly
     while a file is under the cursor and leave nothing behind when it goes.
     pointer-events:none so it never eats the drop it is advertising. */
  body.dropping::after {
    content: ""; position: fixed; inset: 0; z-index: 100090; pointer-events: none;
    background: rgba(var(--lime-rgb), .07);
    box-shadow: inset 0 0 0 3px var(--lime); }

  /* Status bar: the open document (DESKTOP-FEEL phase 5). Reads as state, not
     a link - no pointer, no hover. The dot marks unsaved, the same marker the
     window title uses, so the two never disagree. */
  .sb-doc { font-family:var(--f-mono); font-size:var(--fs-data); color:var(--text2);
            max-width:260px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sb-doc.dirty::before { content:"• "; color:var(--lime); }

  /* ===================== Desktop feel — phase 4: chrome density =====================
     Token scoping, not per-element hacks. The kit's button reads --gg-btn-*
     with fallbacks, and custom properties inherit THROUGH the shadow boundary,
     so setting them on the chrome containers reaches the real <button> inside
     every <gg-button> without a single override selector. That only works
     because both copies of the kit's button agree (phase 4 step 0).

     Chrome only. The timeline and canvas are already dense and correct, and
     nothing here escapes header/.gg-statusbar.

     Radius is min(4px, --radius) rather than a flat 4px so the novelty themes
     keep their own look: win95 sets --radius:0 and stays square, def2 is 5px
     and comes down to 4. A hard value would have overridden both. */
  header, .gg-statusbar {
    --gg-btn-h: 24px;
    --gg-btn-fs: 12px;
    --chrome-r: min(4px, var(--radius, 8px));
    --gg-btn-radius: var(--chrome-r);
    /* NB no --gg-btn-pad here: it would do nothing. The kit's SIZE variants
       (:host([size="sm"]) and button.sm) set padding directly rather than
       through the hook, so the hook only reaches default-size buttons - and
       chrome uses size="sm" throughout. Measured, not assumed: setting it left
       the header buttons on 0 11px. Left out rather than left in as a token
       that quietly does nothing. */
  }
  /* the bar itself follows its buttons down. --head-h has existed as a token
     all along (46px); the header was hard-coded to 54 and never used it. */
  header { height: var(--head-h, 46px); }

  /* The pre-phase-3 queue cluster. Retired, not deleted: its handlers stay
     wired and the guided tour still points at #compqueue, and the ▾ menu calls
     the same functions. Hidden in CSS rather than inline, because the header
     show/hide sets style.display = "" on entering the editor and would clear
     an inline none. */
  #compqueue_wrap { display: none; }

  /* ---- panelhead.js: a header's actions fold into a More menu ---- */
  .ph-folded { display:none !important; }
  .tr-headrow, .tl-head { flex-wrap:nowrap; }                    /* they wrapped onto two and three rows */
  .tr-headrow > h2, .tl-head > .tl-title { flex:0 0 auto; }
  .tl-head .hint { flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }   /* gives way before a button folds */
  .tr-headrow .tr-search { flex:0 1 180px; min-width:96px; }
  /* a control that can shrink absorbs the overflow before anything folds: the source picker was
     squeezed to 34px with every button still showing. It keeps a usable width and the actions fold. */
  .src-head .src-select { flex:0 1 250px; min-width:120px; }
  /* ---- transport.js: the app's own transport under a preview video ---- */
  .pv-transport { flex:0 0 auto; background:var(--well); border-radius:var(--radius,5px); }
  .ex-preview video { cursor:default; }
  .rm-video + .pv-transport { margin:-8px 0 14px; }
  /* a browser's own radio and checkbox are blue; here they take the accent */
  input[type="radio"], input[type="checkbox"] { accent-color:var(--lime); }
