/* The diagram of the schedule — `Features/Schedule/Components/ScheduleGantt`.

   The sheet of the piece: the sticky two-row time header, the chart the bars are drawn in, and the shapes of a bar.
   It declares no token — every measure and every colour it uses is the family's, declared once in `tokens.css`
   (`DEC-W75`), and the geometry of the axis and of the bars is not here at all: it is the arithmetic the client
   consumes from `Shared/Schedule/ScheduleTimeScale.cs` and `Shared/Schedule/GanttBarLayout.cs`, which the structural
   gate allows as visual geometry and which a rule of CSS cannot restate (`PLANNING-SCHEDULE-UI.md` §8 `E-10`).
   `schedule-gantt.css` is the sheet of this piece of the family: the table of the same screen has its own, and the
   family's sheet, if the integrator opens one, declares what they share.

   The row of 24px is the reason the table and the diagram can share a vertical position at all: both headers measure
   the same 50px and both rows the same 24px, so the same offset puts the same row under the same bar. */

/* The slot of the diagram inside the frame of the Gantt view. It is the box the table and the splitter share, and it
   clips rather than scrolls: the scrollport is the one the shared position belongs to, and it is one level in. */
.schedule-gantt {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}

/* The scrollport. `auto` on both axes, and only the vertical offset is shared with the table: the horizontal
   position is this panel's own (`I-26`). */
.schedule-gantt__scroll {
  height: 100%;
  overflow: auto;
}

/* The drawing, as wide as the axis and as tall as its header plus its rows. `relative` because the header's columns
   are placed from its box; it scrolls under the header, which is why the header is sticky and not a separate box. */
.schedule-gantt__canvas {
  position: relative;
}

/* ---- The two-row time header, sticky at the top of the scrollport ------------------------------- */

/* 50px, split in two rows of 25px, opaque so the rows of the chart pass behind it. */
.schedule-gantt__header {
  position: sticky;
  top: 0;
  z-index: var(--schedule-layer-sticky);
  height: var(--schedule-header-height);
  background: var(--color-surface-muted);
  border-bottom: var(--border-default);
}

/* The two halves. The first carries the groups of the scale — a month, a year, a decade — and the second the columns
   themselves, which is what a reader aligns a bar with. */
.schedule-gantt__header-primary {
  position: absolute;
  inset: 0 0 auto 0;
  height: 50%;
  border-bottom: var(--border-width) solid var(--schedule-grid-line);
}

.schedule-gantt__header-secondary {
  position: absolute;
  inset: auto 0 0 0;
  height: 50%;
}

/* One group of the scale. The label inside it sticks to the left edge of the scrollport while its own column is on
   screen, so a long month keeps saying which one it is (`GanttChartPanel.tsx:592-606`). */
.schedule-gantt__group {
  position: absolute;
  top: 0;
  height: 100%;
  border-left: var(--border-width) solid var(--color-border);
}

.schedule-gantt__group-label {
  position: sticky;
  left: 0;
  display: inline-flex;
  align-items: center;
  height: 100%;
  padding: 0 var(--space-xs);
  background: var(--color-surface-muted);
  color: var(--color-text);
  font-size: var(--schedule-font-compact);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

/* One column of the scale: the day, the week, the month. */
.schedule-gantt__period {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: var(--border-width) solid var(--schedule-grid-line);
}

.schedule-gantt__period-label {
  color: var(--color-text-muted);
  font-size: var(--schedule-font-tiny);
  white-space: nowrap;
}

/* The shaded weekend. Only the `day` scale produces one, and it is one band per Saturday and Sunday together
   (`F-6`, `AC-220`): the shading is decorative and changes no date. */
.schedule-gantt__weekend {
  position: absolute;
  top: 0;
  height: 100%;
  background: var(--schedule-weekend);
  opacity: 0.5;
}

/* ---- The chart: the grid, the bands of the rows and the bars ------------------------------------ */

/* The drawing takes no pointer of its own: the only surface of the chart a pointer reaches is the band of a row,
   which is what reports the highlight and the selection. It is also not selectable, as the origin measures. */
.schedule-gantt__chart {
  display: block;
  pointer-events: none;
  user-select: none;
}

/* One line per row, at the top of it. The grid says where a row begins; the bars carry the dates. */
.schedule-gantt__grid {
  stroke: var(--schedule-grid-line);
  stroke-width: 0.5;
}

/* The band of a row. Transparent while nothing points at it and nothing selected it, and always the surface that
   takes the pointer. */
.schedule-gantt__row-band {
  fill: none;
  pointer-events: all;
}

/* The row under the pointer, as the table highlights it too: the same tone at 30 % (`GanttChartPanel.tsx:630-632`). */
.schedule-gantt__row-band--hovered {
  fill: var(--schedule-row-hover);
  opacity: 0.3;
}

/* The selected row. The origin painted the selection in the table and not in the diagram; the diagram selects now —
   it is what this panel emits — so it draws the state with the token the table's own selected row uses, and a
   selection made in either panel is visible in both. */
.schedule-gantt__row-band--selected {
  fill: var(--schedule-row-selected);
}

/* The today line: one red dashed line down the whole chart and its label beside it. It is drawn only when today
   falls between the two ends of the axis. */
.schedule-gantt__today-line {
  stroke: var(--schedule-today);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  opacity: 0.7;
}

/* The label of the today line. It is HTML and not a `<text>` of the drawing, because Razor reserves that tag for its
   own markup blocks; the place it holds is the one the origin gives it, four pixels right of the line at the top of
   the chart. The origin states the vertical place as the baseline of a 9px text on the twelfth pixel of the chart,
   and a box is placed by its top edge: the five pixels below the header are where that baseline falls. Nothing but a
   browser with the real font settles that pixel, and it is the owner's visual pass that owns it (`DEC-W84`). It takes
   no pointer, so the row behind it still reports its hover. */
.schedule-gantt__today-label {
  position: absolute;
  top: calc(var(--schedule-header-height) + 5px);
  margin-left: 4px;
  color: var(--schedule-today);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
  white-space: nowrap;
  opacity: 0.8;
  pointer-events: none;
}

/* ---- The bars: one shape per kind of activity, one tone per type --------------------------------- */

/* The body of a bar: the soft fill of its tone inside an outline of the strong one. The tone itself is a modifier
   below, so a bar is one class of shape plus one class of colour and never a rule that knows both. */
.schedule-gantt__bar {
  stroke-width: 0.5;
}

.schedule-gantt__bar--phase {
  fill: var(--schedule-phase-soft);
  stroke: var(--schedule-phase);
}

.schedule-gantt__bar--deliverable {
  fill: var(--schedule-deliverable-soft);
  stroke: var(--schedule-deliverable);
}

.schedule-gantt__bar--activity {
  fill: var(--schedule-activity-soft);
  stroke: var(--schedule-activity);
}

/* An activity the server published on the critical path it computed. The red replaces **both** colours of its type,
   which is what the origin does with its two variables of colour (`GanttChartPanel.tsx:670-671`) — and it is why a
   critical bar is drawn with this tone alone and not with the two. */
.schedule-gantt__bar--critical {
  fill: var(--schedule-critical-soft);
  stroke: var(--schedule-critical);
}

/* The progress of an activity over the bar: the same width times the percentage the server published, in the strong
   colour of the tone, at 60 % (`GanttChartPanel.tsx:724`). */
.schedule-gantt__bar-progress {
  opacity: 0.6;
}

/* The two feet of a phase's or a deliverable's bracket, which are what tells a summary from a task at a glance
   (`GanttChartPanel.tsx:691-692`). They are filled with the strong colour of the tone, like the progress. */
.schedule-gantt__bar-tab {
  stroke: none;
}

/* The milestone: a diamond at its start date, and nothing else — it has no width and no bar
   (`bar-positioning.ts:25-26`, `AC-221`). */
.schedule-gantt__milestone {
  stroke: none;
}

/* The strong colour of each tone, written once for the three shapes that are filled with it: the progress of an
   activity, the feet of a bracket and the diamond of a milestone. */
.schedule-gantt__accent--phase {
  fill: var(--schedule-phase);
}

.schedule-gantt__accent--deliverable {
  fill: var(--schedule-deliverable);
}

.schedule-gantt__accent--activity {
  fill: var(--schedule-activity);
}

.schedule-gantt__accent--milestone {
  fill: var(--schedule-milestone);
}

.schedule-gantt__accent--critical {
  fill: var(--schedule-critical);
}

/* ---- The dependency arrows ---------------------------------------------------------------------- */

/* One arrow from a predecessor's bar to its successor's, along the polyline the shared geometry describes. Its head
   is the marker of the same colour, which is one per document because a marker is referenced by identifier. */
.schedule-gantt__dependency {
  fill: none;
  stroke: var(--schedule-dependency);
  stroke-width: 1.5;
}

.schedule-gantt__arrow-head {
  fill: var(--schedule-dependency);
}

/* ---- The three drags: the surfaces, the two hooks, the ghosts and the rubber band --------------- */

/* The body of a task bar while the screen may write: the surface a drag takes hold of. It is the only shape of the
   chart that takes the pointer when it is drawn, so a bar the screen may not move (a milestone, a phase, or any bar
   of a project that may not be written) lets the pointer through to the band of its row, which is what reports the
   highlight and the selection — the behaviour the diagram had before these gestures existed. The cursor is the
   origin's own (`cursor-grab`, GanttChartPanel.tsx:719) and it is withdrawn with Ctrl, because with Ctrl a press on
   the body starts nothing. */
.schedule-gantt__bar--draggable {
  pointer-events: all;
  cursor: grab;
}

/* The bar that is being dragged, at the opacity the origin fades it to (`GanttChartPanel.tsx:718`). The ghost
   follows the pointer; this is the bar it left behind. */
.schedule-gantt__bar--moving {
  opacity: 0.4;
}

/* The resize handle: an invisible target of 10px centred on an end of the bar, with the visible 2.5px tab drawn
   over it. The origin measures both (GanttChartPanel.tsx:730, :732) and only draws it while the bar is wider than
   8px, which the component decides; the width of the target is the component's constant. */
.schedule-gantt__grip {
  pointer-events: all;
}

.schedule-gantt__grip--left {
  cursor: w-resize;
}

.schedule-gantt__grip--right {
  cursor: e-resize;
}

/* The visible tab: a white sliver outlined in the drag blue, two pixels in from the end of the bar
   (`GanttChartPanel.tsx:732`, `:740`). It takes no pointer of its own, so the whole 10px of the target answers. */
.schedule-gantt__grip-tab {
  fill: var(--color-surface);
  stroke: var(--schedule-drag);
  stroke-width: 0.8;
  pointer-events: none;
}

/* The two ends of a bar while Ctrl is held, or while a dependency is being drawn: one little blue point each, with a
   transparent target of the radius the component declares around it. The pointer over them is the crosshair the
   origin asks for (`GanttChartPanel.tsx:745-790`). */
.schedule-gantt__hook {
  pointer-events: all;
  cursor: crosshair;
}

/* The generous target: it is drawn as nothing at all, which is why it has a rule of its own — a shape with no fill
   paints black, and this one must not be seen. */
.schedule-gantt__hook-area {
  fill: none;
}

.schedule-gantt__hook-point {
  fill: var(--schedule-drag);
  stroke: var(--color-surface);
  stroke-width: 2;
}

/* The point the gesture started from, which the origin paints in the darker blue so the two ends of the line being
   drawn are told apart at a glance (`GanttChartPanel.tsx:762`, `:783`). */
.schedule-gantt__hook-point--origin {
  fill: var(--schedule-drag-strong);
}

/* The bar a gesture would land on. Two colours, one shape: blue while a bar is being moved and green while it is
   being resized, which is what the origin's two ghosts are (`GanttChartPanel.tsx:817-859`). It is a promise and not
   the state: the bar of the row does not move until the server answered. */
.schedule-gantt__ghost {
  opacity: 0.3;
  stroke-width: 1;
  stroke-dasharray: 4 2;
}

.schedule-gantt__ghost--move {
  fill: var(--schedule-drag);
  stroke: var(--schedule-drag);
}

.schedule-gantt__ghost--resize {
  fill: var(--schedule-activity);
  stroke: var(--schedule-activity);
}

/* The elastic line of the dependency gesture, from the end it started at to the pointer
   (`GanttChartPanel.tsx:862-877`). */
.schedule-gantt__rubber-band {
  stroke: var(--schedule-drag);
  stroke-width: 2;
  stroke-dasharray: 4 2;
  opacity: 0.7;
}
