/* ==========================================================================
   The WBS diagram — Features/Schedule/Components/ScheduleWbs.razor.

   One sheet for the whole piece, in the order it draws it: the container, the controls that float over the canvas
   (the two arrangements, `Fit All` and the percentage), the canvas, the two drawn layers (the wires and the nodes),
   the node with its twelve facts, the fold control with its badge, and the tooltip.

   **Every class here is one this component renders**, and nothing of a shared piece is re-declared: the empty state
   is `feedback.css`'s, the icon is the set's, the `visually-hidden` text is `base.css`'s, and the radius, the
   spacing and the type steps are the tokens of `tokens.css` (`DEC-W75`). The two values that have no token are
   written where they are consumed and carry the measurement that produced them.

   **The numbers are the ones `PLANNING-SCHEDULE-UI.md` §1.4 measured in the origin**, and the ones that belong to
   the geometry rather than to the drawing — the node width, its height, the two gaps and the range of the zoom —
   are not here at all: they live in `Shared/Schedule/WbsDiagramLayout.cs`, which this client is allowed to call and
   which the node's inline style takes them from. A copy of one of those in CSS would be a second declaration of the
   same measurement, which is what `DEC-W74` and E-4 forbid.

   Cascade order is fixed in `wwwroot/index.html`, where the families' sheets are linked after the shared ones.

   **One thing the integrator has to do:** this file is linked into that cascade by a line in `index.html`
   (`<link rel="stylesheet" href="css/schedule-wbs.css" />`, after the family sheets and before `dialogs.css`).
   `wwwroot/index.html` belongs to the integrator and not to this piece, so the line is reported and not added.
   ========================================================================== */

/* ---- The container (§1.4: the origin's `WBSInteractiveView.tsx:647`) ---- */
/* White panel, hairline border, `rounded-xl`, and **no native scroll**: the tree moves with the pan and the zoom,
   which is why the canvas below clips instead of scrolling. */
.schedule-wbs {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
  height: 100%;
  min-width: 0;
  min-height: 0;
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.schedule-wbs__empty {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  min-height: 0;
}

/* ---- The controls that float over the canvas (`:684-717`) ---- */
/* `absolute top-3 right-3 z-10 flex items-center gap-2`, with the sticky layer of the family. */
.schedule-wbs__controls {
  position: absolute;
  top: var(--space-sm);
  right: var(--space-sm);
  z-index: var(--schedule-layer-sticky);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

/* The two arrangements, as one segmented control: the shape `collections.css` gives the artefact view switcher,
   at the size this canvas measures — `px-2 py-1`, and the half in force painted by `aria-pressed`. */
.schedule-wbs__layouts {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  padding: var(--space-3xs);
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}

.schedule-wbs__layout {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 40px;
  padding: var(--space-2xs) var(--space-xs);
  background: transparent;
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  font-family: inherit;
  cursor: pointer;
}

.schedule-wbs__layout:hover {
  color: var(--color-text);
}

.schedule-wbs__layout[aria-pressed="true"] {
  background: var(--color-primary-soft);
  border-color: var(--color-primary-border);
  color: var(--color-primary-strong);
}

/* `Fit All` carries the owner's own word, and the sentence the origin uses is its title (`:711`). */
.schedule-wbs__fit {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 40px;
  padding: var(--space-2xs) var(--space-xs);
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  color: var(--color-text-muted);
  font-family: inherit;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
}

.schedule-wbs__fit:hover {
  color: var(--color-text);
}

/* The percentage of the zoom, as the origin writes it: `px-3 py-1 text-sm font-medium` (`:715-717`). */
.schedule-wbs__zoom {
  padding: var(--space-2xs) var(--space-sm);
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
}

/* ---- The canvas (`WBSCanvas.tsx:228-241`) ---- */
/* The whole viewport is the drawing surface, it clips instead of scrolling, and the cursor says whether a press
   would drag the tree. Text is not selectable: a pan is a drag of the picture and not of a label. */
.schedule-wbs__canvas {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  cursor: grab;
  user-select: none;
}

.schedule-wbs__canvas--panning {
  cursor: grabbing;
}

@media (max-width: 767px) {
  .schedule-wbs__controls {
    right: var(--space-xs);
    left: var(--space-xs);
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  .schedule-wbs__layout,
  .schedule-wbs__fit {
    min-height: 44px;
  }

  .schedule-wbs__fit {
    font-size: var(--font-size-sm);
  }

  .schedule-wbs__canvas {
    min-height: 18rem;
  }
}

/* One transformed wrapper for the two layers, so the wires and the nodes cannot disagree about where a node is. */
.schedule-wbs__world {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}

.schedule-wbs__wires {
  position: absolute;
  top: 0;
  left: 0;
}

/* The parent-to-child link: grey `#d1d5db` at 1,5 px (`:206-220`). */
.schedule-wbs__connector {
  fill: none;
  stroke: var(--schedule-connector);
  stroke-width: 1.5;
}

/* The dependency curve: `#374151`, 2 px, dashed `6 4`, and the width transitions in 150 ms (`:245-249`). */
.schedule-wbs__dependency {
  fill: none;
  stroke: var(--schedule-dependency-strong);
  stroke-width: 2;
  stroke-dasharray: 6 4;
  transition: stroke-width var(--schedule-transition) var(--easing-standard);
}

.schedule-wbs__arrow {
  fill: var(--schedule-dependency-strong);
}

/* ---- The node (`WBSNode.tsx:183-335`) ---- */
/* A 200 × 90 surface at a 6 px radius, padded 8 px, with the fill and the hairline of its activity type. The size
   and the position are the layout's own numbers and arrive in the inline style; everything else is here.
   The origin also transitioned the width of this rectangle in 200 ms (`WBSNode.tsx:193`), and that declaration is
   deliberately not carried over: it was written for the proportional width its own `computeNodeWidth` would have
   given, the width is 200 px for every node because nothing ever called it (GAP-208), and a transition of a value
   that never changes cannot fire. */
.schedule-wbs-node {
  position: absolute;
  box-sizing: border-box;
  padding: var(--space-xs);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--schedule-node-radius);
  cursor: pointer;
}

/* The four activity types, each with the fill and the border `TYPE_COLORS` measures. The word is the one the server
   published and it is never compared with a literal written in C#: the selector matches it. */
.schedule-wbs-node[data-activity-type="Phase"] {
  background: var(--schedule-phase-soft);
  border-color: var(--schedule-phase-border);
}

.schedule-wbs-node[data-activity-type="Deliverable"] {
  background: var(--schedule-deliverable-soft);
  border-color: var(--schedule-deliverable-border);
}

.schedule-wbs-node[data-activity-type="Activity"] {
  background: var(--schedule-activity-soft);
  border-color: var(--schedule-activity-border);
}

.schedule-wbs-node[data-activity-type="Milestone"] {
  background: var(--schedule-milestone-soft);
  border-color: var(--schedule-milestone-border);
}

/* The critical tone is painted from the set the server published, and it wins over the type's own fill — the two
   declarations below come after the four above and carry the same specificity, which is what makes them win. */
.schedule-wbs-node.schedule-wbs-node--critical {
  background: var(--schedule-critical-soft);
  border-color: var(--schedule-critical);
  border-width: 2px;
}

/* A selected node keeps its own fill and takes the selection blue at 2 px, which is the origin's precedence
   (`WBSNode.tsx:60-62`: selected, then critical, then the type). */
.schedule-wbs-node.schedule-wbs-node--selected {
  border-color: var(--schedule-row-selected-border);
  border-width: 2px;
}

/* The WBS code, top left, in the monospace face at 10 px (`:197-205`). */
.schedule-wbs-node__code {
  position: absolute;
  top: var(--space-xs);
  left: var(--space-xs);
  color: var(--color-text-subtle);
  font-family: var(--font-family-mono);
  font-size: var(--schedule-font-tiny);
  line-height: 1;
}

.schedule-wbs-node__actions {
  position: absolute;
  top: var(--space-2xs);
  right: var(--space-2xs);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  color: var(--color-text-muted);
  background: color-mix(in srgb, var(--color-surface) 88%, transparent);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: var(--font-weight-semibold);
  letter-spacing: 1px;
  cursor: pointer;
}

.schedule-wbs-node__actions:hover,
.schedule-wbs-node__actions:focus-visible {
  color: var(--color-primary-strong);
  background: var(--color-primary-soft);
  border-color: var(--color-primary-border);
}

@media (pointer: coarse), (max-width: 47.99rem) {
  .schedule-wbs-node__actions {
    width: 44px;
    height: 44px;
  }
}

/* The name box: from `y = 22` down to `height − 20`, the node's 13 px text at a line height of 1,3. The origin
   clips it at four lines with a box clamp (`:209-231`) and the layout hands this view **at most four lines** — the
   wrap is `WbsDiagramLayout.WrapName` — so the clip is already made and this rule only has to hold the box. */
.schedule-wbs-node__name {
  position: absolute;
  top: 22px;
  right: var(--space-xs);
  left: var(--space-xs);
  height: calc(100% - 42px);
  margin: 0;
  color: var(--color-text);
  font-size: var(--schedule-font-dense);
  font-weight: 400;
  line-height: 1.3;
  overflow: hidden;
  word-break: break-word;
}

/* A container's name is semibold (`:219`). */
.schedule-wbs-node--container .schedule-wbs-node__name {
  font-weight: var(--font-weight-semibold);
}

.schedule-wbs-node__line {
  display: block;
}

/* The responsible and the amount share the row above the foot, at `height − 26` (`:257-283`). */
.schedule-wbs-node__facts {
  position: absolute;
  right: var(--space-xs);
  bottom: 23px;
  left: var(--space-xs);
  display: flex;
  justify-content: space-between;
  gap: var(--space-2xs);
  margin: 0;
  font-size: var(--schedule-font-tiny);
  line-height: 1.2;
}

.schedule-wbs-node__responsible {
  color: var(--schedule-responsible);
}

.schedule-wbs-node__amount {
  color: var(--schedule-amount);
  font-weight: var(--font-weight-semibold);
}

/* The duration at the left and the two dates at the right, in the foot of the node at `height − 12` (`:234-253`). */
.schedule-wbs-node__foot {
  position: absolute;
  right: var(--space-xs);
  bottom: 10px;
  left: var(--space-xs);
  display: flex;
  justify-content: space-between;
  gap: var(--space-2xs);
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--schedule-font-tiny);
  line-height: 1.2;
}

/* The two cells of the foot sit on one line each: the dates are two of them joined by an arrow, and a cell that
   wrapped would put the start of the window and its end on different lines. */
.schedule-wbs-node__duration,
.schedule-wbs-node__dates {
  white-space: nowrap;
}

/* The fold control: a 9 px circle hanging from the middle of the node's bottom edge, its centre 10 px below it
   (`:286-312`), with `+` folded and `−` unfolded. */
.schedule-wbs-node__toggler {
  position: absolute;
  bottom: -30px;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: 50%;
  color: var(--color-text-muted);
  font-family: inherit;
  font-size: var(--font-size-sm);
  font-weight: 700;
  line-height: 1;
  transform: translateX(-50%);
  cursor: pointer;
}

/* The badge of a folded branch: a 10 px circle over the top right corner of the node, carrying the number of
   descendants the fold is hiding (`:315-335`). Its type step is the only value of this sheet with no token — the
   family's smallest step is 10 px and the origin measures 9 — and it is written here with that measurement. */
.schedule-wbs-node__badge {
  position: absolute;
  top: -2px;
  right: -2px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: var(--schedule-critical);
  border-radius: 50%;
  color: var(--color-text-inverse);
  font-size: var(--font-size-sm);
  font-weight: 700;
  line-height: 1;
}

/* ---- The tooltip (`WBSInteractiveView.tsx:834-865`) ---- */
/* A dark card at the pointer, `fixed` so the canvas transform cannot move it, over the tooltip layer of the family:
   `bg-gray-900 text-white text-sm rounded-lg shadow-xl px-4 py-3 min-w-[180px]`. */
.schedule-wbs__tooltip {
  position: fixed;
  z-index: var(--schedule-layer-tooltip);
  min-width: 180px;
  padding: var(--space-sm) var(--space-md);
  background: var(--schedule-tooltip-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  color: var(--color-text-inverse);
  font-size: var(--font-size-sm);
  pointer-events: none;
}

.schedule-wbs__tooltip-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  margin: 0 0 var(--space-2xs);
}

.schedule-wbs__tooltip-code {
  font-family: var(--font-family-mono);
  font-size: var(--schedule-font-compact);
}

.schedule-wbs__tooltip-name {
  font-weight: var(--font-weight-semibold);
}

/* The line under the head: the two dates and, in brackets, the duration, both on the compact step (`:846-855`). */
.schedule-wbs__tooltip-when {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  margin: 0;
}

.schedule-wbs__tooltip-dates,
.schedule-wbs__tooltip-duration {
  font-size: var(--schedule-font-compact);
}

.schedule-wbs__tooltip-responsible,
.schedule-wbs__tooltip-amount {
  margin: 0;
  font-size: var(--schedule-font-compact);
}

/* The amount is the one figure of the card that carries a colour of its own, and on this dark surface the palette's
   lightest green is the one that stays legible (`text-green-300` in the origin, `:861`). */
.schedule-wbs__tooltip-amount {
  color: var(--color-success-soft);
  font-weight: var(--font-weight-semibold);
}

/* ==========================================================================
   The editing half — §2.2 of `PLANNING-SCHEDULE-UI.md` (`P7`).

   The rules above draw the diagram; these draw what a person does to it: the two points a dependency is drawn from,
   the three states of a dependency curve, the rubber band, the ghost and the three indicators of a node drag, the
   inline editor of a node, the context menu of six entries and the panel of a dependency.

   Every number is the one §1.4 measured in the origin, and a value with no token of the family is written here where
   it is consumed, carrying its measurement — which is the rule this sheet already follows for the badge's 9px.
   ========================================================================== */

/* ---- The two points a dependency is drawn from (`WBSNode.tsx:338-367`) ---- */
/* A 6px radius circle centred on each vertical edge, `#3b82f6` with a white hairline at 85 % and a crosshair cursor,
   drawn only while `Ctrl` is held and nothing is being edited (which the markup decides, not this rule). */
.schedule-wbs-node__dot {
  position: absolute;
  top: 50%;
  width: 12px;
  height: 12px;
  background: var(--schedule-drag);
  border: 1.5px solid var(--color-surface);
  border-radius: 50%;
  opacity: 0.85;
  transform: translateY(-50%);
  cursor: crosshair;
}

.schedule-wbs-node__dot--left {
  left: -6px;
}

.schedule-wbs-node__dot--right {
  right: -6px;
}

/* ---- The three states of a dependency curve (`WBSDependencyLayer.tsx:220-251`) ---- */

/* The zone that takes the click: a transparent stroke of 8px over the 2px curve, which is what makes a Bézier
   selectable. It is drawn under the visible curve, so it never hides it. */
.schedule-wbs__dependency-hit {
  fill: none;
  stroke: transparent;
  stroke-width: 8;
  cursor: pointer;
}

/* Selected: 3px and continuous, which is the one state the origin's dashes are dropped for. */
.schedule-wbs__dependency--selected {
  stroke-width: 3;
  stroke-dasharray: none;
}

/* On the critical path the server published: the same red the node's own critical tone uses. */
.schedule-wbs__dependency--critical {
  stroke: var(--schedule-critical);
}

/* And its arrowhead, which is the red one of the three. */
.schedule-wbs__arrow--critical {
  fill: var(--schedule-critical);
}

/* The rubber band of a gesture in course: `#3b82f6`, 2px and dashed `6 4`, from the edge it started at
   (`WBSDependencyLayer.tsx:257-269`). */
.schedule-wbs__rubber-band {
  stroke: var(--schedule-drag);
  stroke-width: 2;
  stroke-dasharray: 6 4;
  pointer-events: none;
}

/* ---- The ghost of a node being dragged (`WBSDragOverlay.tsx:34-64`) ---- */
/* A box of 180 × 60 centred on the pointer — the centring is `translate(-50%, -50%)` so the two halves of the box are
   not written twice — filled `#f0f9ff`, dashed `#3b82f6` at 2px, 70 % opaque, with the origin's drop shadow. */
.schedule-wbs__drag-ghost {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 180px;
  height: 60px;
  padding: var(--space-2xs);
  background: var(--schedule-canvas-ghost);
  border: 2px dashed var(--schedule-drag);
  border-radius: var(--schedule-node-radius);
  opacity: 0.7;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 4px 6px rgb(0 0 0 / 10%));
  pointer-events: none;
}

/* The name inside it: 12px at weight 500 in `#1e40af`, centred and clipped by the markup (`WBSDragOverlay.tsx:50-62`).
   The weight and the ink have no token of the family and are written with the measurement that produced them. */
.schedule-wbs__drag-ghost-name {
  overflow: hidden;
  color: #1e40af;
  font-size: var(--schedule-font-compact);
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- The three indicators of a drop (`WBSDragOverlay.tsx:85-133`) ---- */

/* Hanging from the target or refused: a frame of the size of the target, dashed at 2,5px and, as in the origin, at
   15 % opacity — the whole shape, border included, which is what an SVG `opacity` on the rect does there. */
.schedule-wbs__drop-frame {
  position: absolute;
  box-sizing: border-box;
  background: var(--schedule-drag);
  border: 2.5px dashed var(--schedule-drag);
  border-radius: var(--schedule-node-radius);
  opacity: 0.15;
  pointer-events: none;
}

/* The same frame in red when the target is the node itself or one of its descendants (`RS-74`). */
.schedule-wbs__drop-frame--invalid {
  background: var(--schedule-drop-invalid);
  border-color: var(--schedule-drop-invalid);
}

/* Becoming a sibling: a bar of 4px at the measured 2px above the target's top edge, `#3b82f6` with a 2px radius,
   which is where the origin draws it for both positions (`y − 2`). */
.schedule-wbs__drop-line {
  position: absolute;
  height: 4px;
  background: var(--schedule-insertion-line);
  border-radius: 2px;
  pointer-events: none;
}

/* ---- The inline editor of a node (`WBSInlineEditor.tsx:162-296`) ---- */
/* The card that takes the node's place: white, a 2px blue border, `rounded-xl`, `shadow-xl` and 16px of padding. Its
   position and its size are the layout's and arrive in the inline style. */
.schedule-wbs-editor {
  position: absolute;
  z-index: var(--schedule-layer-sticky);
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
  padding: var(--space-md);
  background: var(--color-surface);
  border: 2px solid var(--schedule-drag);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

/* One field of the card: a 10px label over its control, 4px apart. */
.schedule-wbs-editor__field {
  display: block;
  margin-bottom: var(--space-2xs);
}

/* Measured: `block text-[10px] font-medium text-gray-500 mb-0.5`. */
.schedule-wbs-editor__label {
  display: block;
  margin-bottom: var(--space-3xs);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
}

/* The control: `px-2 py-1 text-xs` inside a grey border of the family, on the focused halo the table's editor uses. */
.schedule-wbs-editor__input {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  padding: var(--space-3xs) var(--space-xs);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--font-size-sm);
  outline: none;
  resize: none;
}

.schedule-wbs-editor__input:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px var(--color-primary-soft);
}

/* The name of a container is drawn one step larger than a leaf's, which is the measurement of the two layouts. */
.schedule-wbs-editor__input--large {
  padding: var(--space-2xs) var(--space-xs);
  font-size: var(--font-size-sm);
}

/* A duration the server would not read: the red border the origin marks it with while it is typed (`:243-247`). */
.schedule-wbs-editor__input--invalid {
  border-color: var(--color-error);
  box-shadow: 0 0 0 2px var(--color-error-soft);
}

/* ---- The context menu of six entries (`WBSContextMenu.tsx:128-158`) ---- */
/* `fixed z-50 bg-white border rounded-lg shadow-lg py-1 min-w-[180px]`, at the position the auto-flip answered. */
.schedule-wbs-menu {
  position: fixed;
  z-index: var(--schedule-layer-floating);
  min-width: 180px;
  padding: var(--space-2xs) 0;
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  outline: none;
}

/* One entry: `w-full flex items-center gap-2 px-3 py-2 text-sm`, and the grey of a control nobody may press. */
.schedule-wbs-menu__entry {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  width: 100%;
  padding: var(--space-xs) var(--space-sm);
  background: none;
  border: 0;
  color: var(--color-text-muted);
  font-family: inherit;
  font-size: var(--font-size-sm);
  text-align: left;
  cursor: pointer;
}

.schedule-wbs-menu__entry:hover:not(:disabled) {
  background: var(--color-surface-muted);
}

/* Measured: a disabled entry is at 50 % with the pointer telling it cannot be pressed. */
.schedule-wbs-menu__entry:disabled {
  color: var(--color-text-subtle);
  opacity: 0.5;
  cursor: not-allowed;
}

/* The 20px cell of the mark before the word. */
.schedule-wbs-menu__mark {
  width: 20px;
  text-align: center;
}

.schedule-wbs-menu__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- The notice of the dependency gesture (`I-37`) ---- */
/* The origin answers the `Create Dependency` entry with a green toast and nothing else. It is drawn over the canvas,
   in the family's success role, and it is a live region (`role="status"` in the markup). */
.schedule-wbs__hint {
  position: absolute;
  bottom: var(--space-sm);
  left: var(--space-sm);
  z-index: var(--schedule-layer-floating);
  margin: 0;
  padding: var(--space-2xs) var(--space-sm);
  background: var(--color-success-soft);
  border: var(--border-width) solid var(--color-success-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  color: var(--color-success);
  font-size: var(--schedule-font-compact);
}

/* ---- The panel of a dependency (`WBSDependencyPanel.tsx:102-169`) ---- */
/* `fixed z-50 bg-white border rounded-lg shadow-xl p-3 min-w-[220px]`, at the pointer and with no auto-flip. */
.schedule-wbs-panel {
  position: fixed;
  z-index: var(--schedule-layer-floating);
  min-width: 220px;
  padding: var(--space-sm);
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}

/* The header: `{predecesor} → {sucesor}` at 12px in grey, truncated, with the two names in a darker semibold. */
.schedule-wbs-panel__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-3xs);
  margin: 0 0 var(--space-xs);
  overflow: hidden;
  color: var(--color-text-subtle);
  font-size: var(--schedule-font-compact);
  white-space: nowrap;
}

.schedule-wbs-panel__from,
.schedule-wbs-panel__to {
  overflow: hidden;
  color: var(--color-text-muted);
  font-weight: var(--font-weight-semibold);
  text-overflow: ellipsis;
}

/* The arrow between the two names, measured: `mx-1`, one of the two things the header says. It is drawn as text
   (`→`) and not as an icon, because the set carries no arrow and the origin drew none either. */
.schedule-wbs-panel__arrow {
  color: var(--color-text-subtle);
}

/* The type selector takes the room left and the lag keeps its measured 80px. */
.schedule-wbs-panel__fields {
  display: flex;
  align-items: flex-end;
  gap: var(--space-xs);
  margin-bottom: var(--space-sm);
}

.schedule-wbs-panel__field {
  display: block;
  flex: 1;
  min-width: 0;
}

.schedule-wbs-panel__field--lag {
  flex: 0 0 80px;
}

.schedule-wbs-panel__label {
  display: block;
  margin-bottom: var(--space-3xs);
  color: var(--color-text-subtle);
  font-size: var(--schedule-font-compact);
}

/* Both controls: `px-2 py-1.5 border rounded text-sm`, with the one focus ring of the application. */
.schedule-wbs-panel__select,
.schedule-wbs-panel__lag {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  padding: var(--space-2xs) var(--space-xs);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--font-size-sm);
  outline: none;
}

.schedule-wbs-panel__select:focus,
.schedule-wbs-panel__lag:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px var(--color-primary-soft);
}

/* The delete control: the red role of the family, `hover:bg-red-50` included. */
.schedule-wbs-panel__delete {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  width: 100%;
  padding: var(--space-2xs) var(--space-sm);
  background: none;
  border: var(--border-width) solid var(--color-error-border);
  border-radius: var(--radius-sm);
  color: var(--color-error);
  font-family: inherit;
  font-size: var(--font-size-sm);
  cursor: pointer;
}

.schedule-wbs-panel__delete:hover {
  background: var(--color-error-soft);
}

@media (max-width: 767px) {
  .schedule-wbs-node__actions {
    width: 44px;
    height: 44px;
  }

  .schedule-wbs-node__toggler {
    bottom: -32px;
    width: 44px;
    height: 44px;
  }
}
