/* planflow-groups.css — PlanFlow P3 PLAN-GROUP CONTAINER + CHOREOGRAPHY.
 *
 * Source of truth: the owner's prototype, second <style> block of
 * planflow_handover/workflow-template.html (7454-7582). planflow-blocks.css
 * 1235-1241 explicitly RESERVES these names for this file:
 *   ".wf-planframe, .wf-pgsec, .wf-pgout, .wf-block--grp and the
 *    .wf-block--shifting corridor choreography are canvas/group logic
 *    and intentionally NOT extracted here."
 *
 * THREE constraints govern every deviation below; each rule that carries one
 * cites it.
 *
 * C1 FLAG SCOPE. Every selector is scoped under `.aw-newblocks` (the body
 *    class canvas.init adds only when PlanFlowBlocks.isEnabled()). Flag off,
 *    this sheet matches nothing.
 *
 * C2 CLASS COLLISION. AirWanderer's sidebar rows also carry `.wf-block`
 *    (prototype-inventory.md risk 11 / module.js:506,553,1685). Every card
 *    selector is therefore `.block.wf-block`, never bare `.wf-block`.
 *
 * C3 THE COUNTER-TRANSFORM. Cards carry transform:scale(var(--pf-zoom-comp))
 *    = 1/BASE_SCALE = 1.4286 (planflow-blocks.css:88-96, canvas.js:8977) so
 *    they paint at prototype size inside a stage scaled to 0.7. The plan
 *    FRAME is a plain #canvas-stage child with NO counter-transform, so its
 *    box is in stage units and its CHROME must be multiplied by
 *    --pf-zoom-comp to land on the prototype's on-screen pixel sizes.
 *    Everything INSIDE a card (.wf-pgsec, .wf-pgout) already rides the card's
 *    transform and keeps the prototype's raw px verbatim.
 */

/* ===================================================================
   THE FRAME — template:7503-7521
   =================================================================== */

/* template:7503-7508. pointer-events:none is LOAD-BEARING, not cosmetic:
   canvas.js:119 gates marquee, background-deselect and middle-click pan on
   `e.target === viewport|stage|svg`. Measured (frame-hit-probe2-dsf1.json):
   an inert frame leaves the hit target at #canvas-viewport and click-to-
   deselect still fires THROUGH it; the same frame at pointer-events:auto
   kills all three over its whole box. Only __head is interactive. */
.aw-newblocks .wf-planframe{
  position:absolute; z-index:1;
  border-radius:calc(26px * var(--pf-zoom-comp, 1));   /* C3 */
  pointer-events:none;
  background:rgba(92,154,126,.07);
  outline:1.5px solid rgba(92,154,126,.32);
  transition:opacity .3s ease,transform .3s cubic-bezier(.22,.8,.3,1),
    left .5s cubic-bezier(.22,.8,.3,1),top .5s cubic-bezier(.22,.8,.3,1),
    width .5s cubic-bezier(.22,.8,.3,1),height .5s cubic-bezier(.22,.8,.3,1);
  transform-origin:10% 30%;
}
/* template:7509 — enter/exit state; buildFrame drops it on the NEXT rAF so
   the opacity/scale transition actually plays (module.js:771). */
.aw-newblocks .wf-planframe.is-folded{opacity:0;transform:scale(.965)}
/* template:7510 — REPLACES the whole transition list with opacity only, so
   while dragging or while startWatch tracks its children the frame geometry
   follows with ZERO lag. prototype-inventory.md risk 7: writing this
   additively instead introduces a half-second lag on every frame drag and
   every child move — a silent choreography regression. */
.aw-newblocks .wf-planframe.is-live{transition:opacity .3s ease}

/* template:7511-7521. C3: every chrome dimension × --pf-zoom-comp. */
.aw-newblocks .wf-planframe__head{
  position:absolute;
  top:calc(9px * var(--pf-zoom-comp, 1));
  left:calc(14px * var(--pf-zoom-comp, 1));
  right:calc(14px * var(--pf-zoom-comp, 1));
  height:calc(36px * var(--pf-zoom-comp, 1));
  pointer-events:auto;
  display:flex;align-items:center;
  gap:calc(9px * var(--pf-zoom-comp, 1));
  /* PGFOLD — the template's two pad values, 5 and 9, SWAPPED, because the
     fold moved to the other end of this row (see .wf-planframe__fold).
     5 was the template's pad on the fold's side and 9 the pad on the
     text's side; both keep their meaning, so the row's fixed width is
     unchanged (5+27+9+15+9+9+9 = 9+15+9+9+9+27+5 = 83 prototype px) and
     __t's flex:1 therefore resolves to the SAME width as HEAD; the two
     builds' header boxes are compared one by one in pgfold-rects-hd.json
     against pgfold-rects-fx.json. */
  padding:0 calc(9px * var(--pf-zoom-comp, 1)) 0 calc(5px * var(--pf-zoom-comp, 1));
  cursor:pointer;
}
.aw-newblocks .wf-planframe__hic{display:flex;color:#2C6A4D;flex:none}
.aw-newblocks .wf-planframe__hic svg{
  width:calc(15px * var(--pf-zoom-comp, 1));
  height:calc(15px * var(--pf-zoom-comp, 1));
}
.aw-newblocks .wf-planframe__t{
  flex:1;min-width:0;
  font:600 calc(12.5px * var(--pf-zoom-comp, 1))/1 -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  color:#2C6A4D;letter-spacing:.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.aw-newblocks .wf-planframe__n{
  flex:none;
  /* ROUND 12: order 1 — visually a no-op (the count is already the row's
     last item after the fold moved to order:-1) so the review banner's TEXT
     (order 0, appended after the fold) lands before it. */
  order:1;
  font:700 calc(10.5px * var(--pf-zoom-comp, 1)) ui-monospace,'SF Mono',Menlo,monospace;
  color:rgba(44,106,77,.75);
}
/* ===================================================================
   PGFOLD — THE FOLD MOVES TO THE OTHER END OF THE HEADER ROW.
   This is the one deviation from template:7511-7521 in this file, it is
   one declaration, and it is a LAYOUT move, not a hit-test trick: no
   z-index, no pointer-events, no size and no new element, so nothing can
   be stacked over another control.

   THE DEFECT, reproduced on HEAD 7ebfb71 (planflow-groups.css md5
   89a7664a7d565c7dd4d0e4bb9affb20f, 19350 B) with the owner fixture
   wf_d870eb77ae, Canvas.scale .5873, dsf 1 / 1.25 / 1.5: a REAL mouse
   click at the centre of [data-pgfold] does not collapse the group, while
   a DOM .click() on the same button does (pgfold-synth-hd.json; the
   real-mouse half is repeated in every cell of pgfold-matrix-hd.json).
   That .click() is the only synthetic event this track fires and it exists
   solely to make that separation: the handler (planflow-groups.js:2109)
   was never at fault — the pointer never arrives.
   document.elementFromPoint at that centre returns div.wf-block__topbar
   with nothing hovered, and
   button.wf-block__top-btn--danger[data-action=delete] once it is
   (pgfold-quick-hd-dsf1.json: centreCold / centreWarm).

   AND IT IS ALREADY DESTRUCTIVE. Not "the fold does nothing": on HEAD the
   element under the fold's centre at the moment the press is made IS that
   delete button, and the press raises the host's own confirm — measured at
   dsf 1, 1.25 and 1.5, one dialog per press, text "Delete this block?"
   (pgfold-destructive-hd.json; the matrix counts two per cell, one per
   arm, in pgfold-matrix-hd.json `dialogs`). The member survives only
   because the rig dismisses it. The aim point of the collapse control
   therefore already offers to delete a step the user never aimed at, and
   taking the fold off that button REMOVES a destructive misfire instead of
   creating one.

   WHY. .wf-block__topbar is position:absolute; top:-32px; right:0;
   height:32px and pointer-events:auto UNCONDITIONALLY
   (planflow-blocks.css:624-631), i.e. an INVISIBLE 32px hit strip one
   HEAD above its card, and HEAD is 54 (planflow-groups.js:87). It rides
   its card's stacking level 2 (planflow-blocks.css:100) while the frame
   is level 1, so it wins wherever the two boxes meet. Frame-relative, in
   prototype px, measured (pgfold-quick-hd-dsf1.json, client px x 1.1915:
   the stage runs at Canvas.scale .5873 and a card counter-transforms by
   1/BASE_SCALE, so .5873/.7 = .8393 client px to one prototype px):
       head          x [14,   R-14]   y [ 9,  45]
       fold          x [R-46, R-19]   y [13.5, 40.5]
       last member   x [.., R-30]     top 54
       its topbar    x [R-194, R-30]  y [26, 58] resting, [22, 54] hovered
       its DELETE    x [R-58,  R-30]  y [26, 54] resting, [22, 50] hovered
   The fold's own box therefore has 16 x 18.5 prototype px lying inside a
   DELETE button, and the fold's centre is inside that rectangle by 2.5px
   horizontally and 1px vertically. Everything above y 22 and everything
   right of R-30 is already clear, so part of the fold's box does answer on
   HEAD while its middle and its lower left do not; the measured fraction,
   per state and per dsf and on both approach arms, is in
   pgfold-matrix-hd.json (foldWarm / foldCold).

   WHAT WAS REJECTED. Raising the fold over the cards. It wins the hit
   test by standing ON a DELETE button, and a misfire there is
   destructive; that round measured the delete button's reachable area
   96.8% -> 58.7%. Also rejected, and measured on a third build rather
   than guessed at: giving the RESTING toolbar back its pixels with
   `.wf-block--planchild:not(:hover) .wf-block__topbar{pointer-events:none}`
   (pgfold-matrix-alt.json, same grids, same states, same dsf ladder). It
   does free the fold, and it costs the cold arm: that invisible strip is
   the only thing that summons a member's toolbar when the cursor arrives
   from ABOVE the card, so with it inert every toolbar button — DELETE
   included — stops answering on that approach. The numbers are in that
   file next to this build's.

   WHAT THIS IS. The head is 1028.73 client px wide and the first
   member's topbar starts 164 prototype px in from the frame's left edge
   (measured 137.67 client, pgfold-quick-hd-dsf1.json). The band
   x [14, 164] over the head's full height is therefore empty of every
   card and every toolbar in every state, and it is 150 prototype px
   wide against a 27px button. Probed point by point on HEAD before any
   change (pgfold-quick-hd-dsf1.json probeLeft): the head answers at
   +14, +27, +41, +60, +90 and +120 client px from the frame's left edge
   and only at +150 does a toolbar button appear. So the fold is placed
   there — order:-1 in the head's own flex row, which changes NOTHING but
   which end of the row it is laid out at.

   order:-1 and not a DOM reorder on purpose: buildFrame's markup stays
   node-for-node Build-113's (module.js:761-766), the [data-pgfold] click
   binding (planflow-groups.js:2109) and both mousedown guards
   (:2566 `e.target.closest('[data-pgfold]')`, :2713 [data-pghead]) keep
   reading exactly what they read before, and the button remains the
   head's only focusable so tab order is unaffected.

   THE COST, STATED: the collapse chevron is at the header's left end
   instead of its right. Nothing else moves — __t's flex width, the
   fold's 27x27 box, its 9px radius, its vertical centring and the head's
   own inset are all unchanged (pgfold-rects-*.json).
   =================================================================== */
.aw-newblocks .wf-planframe__fold{
  order:-1;                    /* PGFOLD — see above; the only deviation */
  flex:none;
  width:calc(27px * var(--pf-zoom-comp, 1));
  height:calc(27px * var(--pf-zoom-comp, 1));
  display:flex;align-items:center;justify-content:center;
  border:0;border-radius:calc(9px * var(--pf-zoom-comp, 1));
  background:rgba(255,255,255,.55);color:#2C6A4D;cursor:pointer;
  transition:background .15s ease;
}
.aw-newblocks .wf-planframe__fold:hover{background:rgba(255,255,255,.85)}
.aw-newblocks .wf-planframe__fold svg{
  width:calc(13px * var(--pf-zoom-comp, 1));
  height:calc(13px * var(--pf-zoom-comp, 1));
}

/* template:7481 + 7491-7495 — the frame answers selection with the same
   .62s pulse the card halo uses. --ease is defined on .aw-newblocks cards
   (planflow-blocks.css:83) but the frame is NOT a card, so the token is
   restated here rather than inherited by luck. */
.aw-newblocks .wf-planframe{--ease:cubic-bezier(.32,.72,0,1)}
.aw-newblocks .wf-planframe.is-flash{animation:wf-frame-halo .62s var(--ease)}
@keyframes wf-frame-halo{
  0%   { box-shadow:0 0 0 0 rgba(60,122,91,0); }
  28%  { box-shadow:0 0 0 1.5px rgba(60,122,91,.50), 0 0 14px rgba(60,122,91,.22); }
  100% { box-shadow:0 0 0 1px rgba(60,122,91,0), 0 0 22px rgba(60,122,91,0); }
}

/* ===================================================================
   X6 / OPTION A — THE FRAME CARRIES THE GROUP'S RUNNING STATE
   (PROGRESS_LEDGER 5a, evening addendum, owner-ratified; no Build-113
   precedent for an OPEN group — the recipes below are the template's
   own running-block vocabulary, moved onto the frame verbatim):
     · the header's spinner is the card's title-spinner (template
       1642-1673: comet-tail conic ring, amber #F4B83E, 0.7 s rotation,
       .2 s opacity fade) beside the pill's own word "Running…"
       (setBlockRunning, template 6433);
     · the border glow is the running card's breathing gradient outline
       (template 1743-1760: stroke url(#wf-pulse-grad), stroke-opacity
       0.25 <-> 0.70 over 1.6 s ease-in-out) drawn as a gradient ring on
       the frame's own rounded box, plus the running card's quiet depth
       lift (template 1699-1710: drop-shadow 0 12px 26px rgba(55,72,64,.22)).
   The gradient stops are #wf-pulse-grad's (planflow-blocks.js
   ensureRuntimeAssets), restated as a CSS gradient because a box has no
   SVG stroke. C1: flag-scoped. C3: every chrome dimension x --pf-zoom-comp.
   The status element is ALWAYS in the header (buildFrame) and painted
   only inside the running window — display:none outside it, so it can
   never be read as visible when the group is not synthesizing.
   =================================================================== */
.aw-newblocks .wf-planframe__status{
  display:none;
  flex:none;
  align-items:center;
  gap:calc(6px * var(--pf-zoom-comp, 1));
  font:600 calc(11px * var(--pf-zoom-comp, 1))/1 -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  color:#2C6A4D;letter-spacing:.01em;white-space:nowrap;
}
.aw-newblocks .wf-planframe.is-running .wf-planframe__status{
  display:inline-flex;
  animation:wf-frame-status-in .2s var(--ease) both;      /* the spinner's .2s fade, template 1671 */
}
@keyframes wf-frame-status-in{ from{ opacity:0; } to{ opacity:1; } }
.aw-newblocks .wf-planframe__spinner{
  width:calc(14px * var(--pf-zoom-comp, 1));
  height:calc(14px * var(--pf-zoom-comp, 1));
  border-radius:50%;
  /* template 1642-1673 — the comet-tail ring, verbatim stops */
  background:conic-gradient(from 0deg,
    rgba(244,184,62,0)     0%,
    rgba(244,184,62,.20)  28%,
    #F4B83E               92%,
    #F4B83E              100%);
  -webkit-mask:radial-gradient(closest-side, #0000 64%, #000 65%);
          mask:radial-gradient(closest-side, #0000 64%, #000 65%);
  filter:drop-shadow(0 0 4px rgba(244,184,62,.55));
  animation:wf-frame-spin .7s linear infinite;             /* template 1668: 0.7 s */
}
@keyframes wf-frame-spin{ to{ transform:rotate(360deg); } }
.aw-newblocks .wf-planframe.is-running{
  /* template 1699-1710 — the running card's quiet depth lift, as a box */
  box-shadow:0 12px 26px rgba(55,72,64,.22), 0 0 22px rgba(124,91,255,.20);
}
.aw-newblocks .wf-planframe.is-running::before{
  content:'';
  position:absolute;
  inset:calc(-2px * var(--pf-zoom-comp, 1));
  border-radius:calc(28px * var(--pf-zoom-comp, 1));       /* the frame's 26px radius + the 2px inset */
  padding:calc(2.8px * var(--pf-zoom-comp, 1));            /* template 1755 stroke-width 2.8 */
  /* #wf-pulse-grad (planflow-blocks.js ensureRuntimeAssets), x1 0 y1 0 -> x2 100% y2 50% */
  background:linear-gradient(100deg,
    #3CDCFF 0%, #5B6DFF 14%, #9C5BFF 28%, #E84BC8 42%,
    #FF5C7A 56%, #FF8B3D 70%, #FFCB47 84%, #3CDCFF 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask-composite:exclude;
  pointer-events:none;
  animation:wf-frame-border-pulse 1.6s ease-in-out infinite;   /* template 1757-1760 */
}
@keyframes wf-frame-border-pulse{
  0%, 100%{ opacity:.25; }
  50%    { opacity:.70; }
}

/* ===================================================================
   CHOREOGRAPHY — template:7523-7530. C2: .block.wf-block, never bare.
   These four rules ARE the sacred motion; the durations and the two
   cubic-beziers are the owner's hand-tuned values and must not drift.
   =================================================================== */

/* template:7523 — the corridor shift. */
.aw-newblocks .block.wf-block.wf-block--shifting{
  transition:left .52s cubic-bezier(.22,.8,.3,1),top .52s cubic-bezier(.22,.8,.3,1);
}
/* template:7524-7525 — the original group block fading out on expand. */
.aw-newblocks .block.wf-block.wf-block--ghosted{
  opacity:0;transform:scale(.94) ;pointer-events:none;
  transition:opacity .34s ease,transform .34s cubic-bezier(.22,.8,.3,1);
}
/* template:7526 — the converge state. No transition of its own: it rides
   .wf-block--anim. */
.aw-newblocks .block.wf-block.wf-block--foldin{opacity:0;transform:scale(.93)}
/* template:7527-7528 — marker only; members stay 100% stock blocks. */
.aw-newblocks .block.wf-block.wf-block--planchild{}
/* template:7529-7530 — the placement transition. */
.aw-newblocks .block.wf-block.wf-block--anim{
  transition:opacity .34s ease,transform .34s cubic-bezier(.22,.8,.3,1),
    left .52s cubic-bezier(.22,.8,.3,1),top .52s cubic-bezier(.22,.8,.3,1);
}

/* C3 CORRECTION, and the one place these rules cannot be verbatim.
   The prototype's cards carry no transform, so `transform:scale(.94)` is the
   whole story. AirWanderer's cards carry transform:scale(var(--pf-zoom-comp))
   (planflow-blocks.css:88-96); a bare scale() in --ghosted/--foldin would
   REPLACE that counter-transform and the card would snap to 70% mid-fade.
   Multiplying the two keeps the prototype's ratio (.94 / .93 of the card's
   normal painted size) while preserving the counter-transform. */
.aw-newblocks .block.wf-block.wf-block--ghosted{
  transform:scale(calc(var(--pf-zoom-comp, 1) * .94));
}
.aw-newblocks .block.wf-block.wf-block--foldin{
  transform:scale(calc(var(--pf-zoom-comp, 1) * .93));
}

/* ===================================================================
   THE GROUP IDENTITY ON THE BLOCK — template:7531-7539
   "identity lives ONLY in the badge (icon) and the title bar (header);
    every other element keeps the default block styling"
   =================================================================== */
.aw-newblocks .block.wf-block.wf-block--grp .wf-block__layer--title-bar path[fill="#DCE8DF"]{fill:#E6DCC2}
/* a provider logo means nothing on a group — the line reads
   "N planned steps · Group" on its own. */
.aw-newblocks .block.wf-block.wf-block--grp .wf-block__layer--gpt{display:none}

/* template:7580-7581 — the native-look topbar buttons this module adds.
   planflow-blocks.css:624-676 already styles .wf-block__topbar /
   .wf-block__top-btn (hover-reveal, 28px, --cta hover); only the PG tint
   and the count span belong here. */
.aw-newblocks .wf-block__top-btn--pg{color:#2C6A4D}
.aw-newblocks .wf-block__top-btn--pg span{font:800 9.5px ui-monospace,Menlo,monospace;margin-left:2px}

/* ===================================================================
   ENGINEERING v2 — step sections inside the connector panels.
   template:7483-7489. These live INSIDE the card, so they ride the card's
   counter-transform and keep the prototype's raw px verbatim (C3).
   =================================================================== */
.aw-newblocks .wf-pgsec{display:flex;align-items:center;gap:5px;margin:8px 2px 1px;padding:4px 6px 3px 4px;font-size:10.5px;color:var(--muted);border-top:1px solid var(--divider,#E7E2D2);position:relative}
.aw-newblocks .wf-pgsec:not(.is-first)::before{content:"";position:absolute;top:-7px;left:11px;width:1px;height:6px;background:#D8C69E}
.aw-newblocks .wf-pgsec__n{flex:none;width:15px;height:15px;border-radius:5px;background:#E7DBC0;border:1px solid #D8C69E;color:#8F6B33;font-weight:800;font-size:9.5px;display:flex;align-items:center;justify-content:center;font-family:ui-monospace,Menlo,monospace}
.aw-newblocks .wf-pgsec__t{flex:1;min-width:0;font-weight:600;color:var(--label);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.aw-newblocks .wf-pgsec__b{flex:none;font-size:9.5px;color:#8F6B33;background:#F2EAD6;border:1px solid #E2D3AC;border-radius:999px;padding:0 6px;line-height:14px;white-space:nowrap}
.aw-newblocks .wf-pgsec__add{flex:none;width:16px;height:16px;border-radius:5px;border:1px solid var(--well-line,#DCD3BC);background:transparent;color:var(--muted);font:inherit;font-size:12px;line-height:1;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}
.aw-newblocks .wf-pgsec__add:hover{color:var(--accent,#1F6E45);border-color:var(--accent-line,#BFD8C9)}

/* THE STEP-SECTION RESERVE — why a folded group's rows used to hang
   out of the bottom of its own card.

   The card grows to fit its connector panel through the HOST's
   `cbNeededH` (planflow-blocks.js:890-906), which MEASURES the rendered
   panel's bottom and writes the difference into `--cb-h`. Every layer of
   the card silhouette is sized from that one number
   (planflow-blocks.css:150-168 + svgBgOuter/Inner/Panel).

   The measurement is taken at three moments this module does not
   control, and at all three the step sections are NOT in the column:

     1. `refresh()` rebuilds a column and measures in the SAME
        synchronous block (planflow-blocks.js:2337-2341) —
        renderPortColumns replaces the column's innerHTML, which deletes
        every .wf-pgsec, and syncCBHeight runs before any observer can
        put them back (ours is a MutationObserver + rAF, a whole task
        later);
     2. `restoreViewState` settles a rebuilt card (…:1307) before this
        module has re-skinned it;
     3. the fold itself measures while the card is still parked.

   The prototype never hits this: module.js:224-238 wraps window.renderPort
   so decorateEngPanels runs SYNCHRONOUSLY inside it, and module.js:210/220
   then call syncCBHeight with the sections already in place.

   The fix keeps the host's measurement as the single source of truth and
   makes it TRUE AT EVERY INSTANT instead of racing it: while the sections
   are absent the column reserves exactly the box they will occupy, and
   the reserve vanishes at the same instant they appear, so the column's
   height never changes and no re-measure is owed.

   The reserve is EXACT, not an estimate. One .wf-pgsec costs, in the
   column's flex flow:
       24px  border box   = 16 (tallest child, __add/__b) + 4 + 3 padding
                             + 1 border-top   (:180, :184, :185 above)
       + 9px margins      = 8 top + 1 bottom  (:180)
       + one column gap   = calc(1px * var(--scale))
                             (planflow-blocks.css .wf-block__cb-col)
   = calc(33px + 1px * var(--scale)) per section, and --pg-secs is the
   step count this module is about to render (setStepReserve).

   The block-level "+ Add port" tail is hidden under the SAME guard: the
   decorator hides it for the whole folded life of the card
   (planflow-groups.js "the per-step '+' replaces the block-level add
   while folded"), but a column the host has just rebuilt carries a fresh,
   VISIBLE tail for exactly the instant being measured. Hiding it here
   removes that instant without changing what the card ever shows.
   =================================================================== */
.aw-newblocks .block.wf-block.wf-block--grp .wf-block__cb-col:not(:has(> .wf-pgsec)){
  padding-bottom:calc(var(--pg-secs, 0) * (33px + 1px * var(--scale)));
}
.aw-newblocks .block.wf-block.wf-block--grp .wf-block__cb-col:not(:has(> .wf-pgsec)) > [data-add]{
  display:none;
}

/* ===================================================================
   FOLDED OUTPUT PREVIEW — template:7548-7557.
   Inside the card ⇒ --scale (0.72, planflow-blocks.css:97) resolves exactly
   as in the prototype (template:62) and the calc() sizes transfer verbatim.
   .wf-pgout-nl is display:none purely so COPY/PASTE of the preview yields
   plain numbered text (template:7555).
   =================================================================== */
.aw-newblocks .wf-pgout{display:flex;flex-direction:column;gap:2px;max-height:calc(40px * var(--scale));overflow-y:auto;padding-right:3px;overscroll-behavior:contain}
.aw-newblocks .wf-pgout::-webkit-scrollbar{width:4px}
.aw-newblocks .wf-pgout::-webkit-scrollbar-thumb{background:rgba(120,100,60,.28);border-radius:4px}
.aw-newblocks .wf-pgout__row{display:flex;align-items:baseline;gap:5px;min-width:0;font-size:calc(9.5px * var(--scale));line-height:1.2}
.aw-newblocks .wf-pgout__n{flex:none;font:700 calc(8.5px * var(--scale)) ui-monospace,Menlo,monospace;color:#8F6B33}
.aw-newblocks .wf-pgout__t{flex:none;max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;color:#1F2D26}
.aw-newblocks .wf-pgout__x{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#5D7466}
.aw-newblocks .wf-pgout-nl{display:none}
.aw-newblocks .wf-pgout__more{font-size:calc(8.5px * var(--scale));color:#8F6B33;font-weight:600;padding-top:1px}
.aw-newblocks .wf-pgout__more::before{content:"+ " attr(data-n) " more"}

/* NO BOX GEOMETRY HERE — THE HOST OWNS THE OUTPUT PANEL.
   Round 1 asserted .has-output from a rAF and fought planflow-blocks.js
   refresh() for it: 3-7 add/remove pairs inside the first 200 ms of every
   collapse, a visible height blink on the card the fold is about.
   Round 2 stopped fighting but re-declared --output-h and the reveal from
   .wf-block--grp, which moved only the CSS side of a four-sided invariant.
   MEASURED on that build (p3r3-diag-r2-dsf1.json d3_outputInvariant):
   --output-h resolved to 32 while the PAINTED silhouette was still
   viewBox "0 0 414 201" with data-pfb-h="0", because planflow-blocks.js
   syncCardHeight (:954-971) derives the silhouette height from the CLASS and
   caches it. The strip therefore hung out of the card (.wf-pgout-host bottom
   408.4 against a card bottom of 407.3, inside a .wf-block__output 13.2 px
   tall holding a 19.2 px child) and the port chips (planflow-blocks.css:976)
   and legacy handles (planflow-blocks.js:402-403) stayed at the no-output
   centre.
   The class is now produced ONCE, by the host's own writer, from the answer
   this module gives it (planflow-blocks.js:1442 hook ->
   PlanFlowGroups.wantsOutputPanel), so :787, :884, :976, syncCardHeight and
   :3706's outputVisible all fire from that single write — exactly as they do
   for a block with a real run result. What belongs in THIS file is only what
   is specific to a plan group: the host's own text node is not used
   (paintFoldedOutput renders numbered rows into .wf-pgout-host instead), so
   it is hidden rather than contested. */
.aw-newblocks .block.wf-block.wf-block--grp .wf-block__output__text{display:none}
/* The preview is a flex child of the host's own .wf-block__output__body and is
   CLIPPED BY IT, exactly like the host's own output text: measured
   (p3r3-clip.json) the body is max-height:0 / overflow:hidden / clientHeight 0
   and .wf-block__output is overflow:hidden 13.2 px tall, so although the
   preview's intrinsic box is 19.2 px, elementFromPoint one pixel above the
   card's bottom edge returns .wf-block__card — nothing of it is painted outside
   the card. It appears when the user opens the panel, which is where the
   prototype puts it too (module.js:1284 writes into the same body). No sizing
   rule belongs here. */
.aw-newblocks .wf-pgout-host{flex:1;min-width:0}

/* ===================================================================
   WIRES LEAVING A FOLDED GROUP — template:7571-7574.
   Both !important verbatim: they override the per-edge stroke
   planflow-blocks.js writes inline while routing.
   =================================================================== */
.aw-newblocks .wf-conn-group.wf-conn--pg path.wf-conn{stroke:rgba(143,107,51,.62) !important}
.aw-newblocks .wf-conn-group.wf-conn--pg .wf-conn-cap-dot{fill:#B59A6E !important}

/* ===================================================================
   PARK BIN — the PARKED-DOM container.
   NOT in the prototype: module.js:819-821 parks by DETACHING the node from
   the document entirely. That is fatal here. Measured
   (park-probe-dsf1.json / surface-probe-dsf1.json): canvas.js:8818-8830
   indexes block nodes as `stage.querySelectorAll('.block')` by DESCENDANT,
   so a node parked outside #canvas-stage is not found and the next render
   MINTS A SECOND NODE for the same id (duplicateNodesForParkedId: 2).
   Parked inside the stage it is found, reused and left in place
   (nodesForId: 1, stillInsidePark: true).
   The bin is therefore a stage child, and the parked node keeps
   display:none — which is also exactly what makes it invisible to the
   drag-collision probe (_pfbObstacles, canvas.js:1704-1715: a 0x0 card rect
   is skipped; visibility:hidden or opacity:0 would leave invisible walls).
   =================================================================== */
.aw-newblocks .wf-pg-parkbin{position:absolute;left:0;top:0;width:0;height:0;overflow:visible;pointer-events:none}
.aw-newblocks .wf-pg-parkbin > .block{display:none !important}

/* ================= ROUND 11 / 12 — a pause the user can see on an OPEN frame =================
   planflow-groups.js refreshFrameReview: while the group's parked card sits in
   needs_review the frame wears an amber outline and its head carries the
   review banner. ROUND 12: the decision itself lives in the review modal
   (planflow-review-modal.js) — the banner is the kind's text plus ONE opener,
   "Review…". The banner is display:contents so its two children join the
   head's own flex row: the opener at order:-1 AFTER the fold (same order,
   later in the DOM), i.e. in the band beside the fold that the PGFOLD
   measurement above found empty of every member card and toolbar strip in
   every state — a right-end opener sat in the last member's hovered strip
   when the cursor came from the modal (measured, x12/M) — and the text at
   order 0, before the step count (order 1). Every dimension × --pf-zoom-comp
   like the rest of the frame chrome. */
.aw-newblocks .wf-planframe.is-needs-review{
  outline:1.5px solid rgba(244,184,62,.85);
  background:rgba(244,184,62,.06);
  box-shadow:0 0 0 calc(4px * var(--pf-zoom-comp, 1)) rgba(244,184,62,.14);
}
.aw-newblocks .wf-planframe__review{display:contents}
.aw-newblocks .wf-planframe__rtx{
  flex:none;
  margin-left:auto;
  padding:0 calc(4px * var(--pf-zoom-comp, 1));
  /* ROUND 14 (owner round 12): the app's serif, like everything else on the
     frame; the amber stays — it is the paused frame's own colour */
  font:600 calc(12px * var(--pf-zoom-comp, 1))/1 'EB Garamond',Georgia,serif;
  color:#8A5A00;letter-spacing:.01em;white-space:nowrap;
}
.aw-newblocks .wf-planframe__rbtn{
  order:-1;flex:none;
  height:calc(24px * var(--pf-zoom-comp, 1));
  padding:0 calc(10px * var(--pf-zoom-comp, 1));
  border-radius:calc(8px * var(--pf-zoom-comp, 1));
  border:1px solid rgba(60,74,67,.18);
  background:rgba(255,255,255,.92);
  color:#2C3A33;
  font:600 calc(12px * var(--pf-zoom-comp, 1))/1 'EB Garamond',Georgia,serif;   /* round 14: the app's serif */
  white-space:nowrap;
  cursor:pointer;
  pointer-events:auto;
}
.aw-newblocks .wf-planframe__rbtn.is-ok{background:#2C6A4D;border-color:#2C6A4D;color:#fff}
.aw-newblocks .wf-planframe__rbtn:hover{filter:brightness(1.06)}
/* ROUND 13 — the open group's call to action: the opener blinks while the
   pause's modal is away (planflow-groups.js reviewOpenerPulse), the same
   breathe as a paused card's .wf-block__review-cta (keyframes
   wf-review-pulse, planflow-blocks.css). */
.aw-newblocks .wf-planframe__rbtn.is-review-pulse{animation:wf-review-pulse 1.2s ease-in-out infinite}

/* ROUND 11 — a member's invisible toolbar strip (planflow-blocks.css
   .wf-block__topbar: 32px ABOVE the card, opacity 0 yet hit-testable so the
   cursor can travel from the card into a button in one motion) lies inside
   the frame head's band: HEAD 54 = 9 + 36 + 9, so the strip covers the head's
   lower 23px at each member's right end. It swallowed the head's banner
   buttons (measured, r11/newcheck-probe5.js: elementsFromPoint on Approve =
   the last step's .wf-block__topbar, opacity 0, z 7, above the frame's z 1).
   For a MEMBER the strip is inert until its own card is hovered — the
   card→button motion still works (the card is hovered as the cursor enters
   the strip) and the head wins from every other direction. Standalone
   blocks keep the ported behaviour untouched. */
.aw-newblocks .block.wf-block.wf-block--planchild .wf-block__topbar{pointer-events:none}
.aw-newblocks .block.wf-block.wf-block--planchild:hover .wf-block__topbar{pointer-events:auto}

/* =====================================================================
   ROUND 13 (track V) — THE RUN LOCK ON AN OPEN FRAME. planflow-groups.js
   refreshGroupLock puts `is-run-locked` on the frame of a group the run is
   using (its card or any member processing / processed) and aria-disabled +
   the lock title on its fold; the fold is refused (collapseGroup). The look
   mirrors the card toolbar's (planflow-blocks.css, same glyph). Appended at
   the end on purpose — line numbers of this file are cited elsewhere.
   ===================================================================== */
.aw-newblocks .wf-planframe.is-run-locked .wf-planframe__fold[aria-disabled="true"]{
  position:relative; cursor:not-allowed; opacity:.62;
}
.aw-newblocks .wf-planframe.is-run-locked .wf-planframe__fold[aria-disabled="true"]:hover{ background:rgba(255,255,255,.55); }
.aw-newblocks .wf-planframe.is-run-locked .wf-planframe__fold[aria-disabled="true"]::after{
  content:""; position:absolute; right:-3px; bottom:-3px;
  width:calc(11px * var(--pf-zoom-comp, 1)); height:calc(11px * var(--pf-zoom-comp, 1)); border-radius:calc(4px * var(--pf-zoom-comp, 1));
  background:#6E8077 url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'><rect x='5' y='11' width='14' height='9' rx='2'/><path d='M8 11V8a4 4 0 0 1 8 0v3'/></svg>") center/64% 64% no-repeat;
  box-shadow:0 0 0 1.5px #fff;
}
