/* ============================================================================
   The roadmap, drawn as bands and waves

   Three regions, and the reason each one exists.

   The RAIL, down the left, is one card per block. It sits outside the pane
   that scrolls sideways, so a reader four waves deep still knows which block
   they are looking at. Its cards carry counts and never a percentage: a block
   does not end, and "0% delivered" is a sentence about a feature dressed up as
   a sentence about roadmap.

   The PLANE is the picture. Horizontal position is dependency depth, so a box
   further right is work that literally cannot start yet, and the column
   headings say how many waves deep that is. Vertical position is which block
   the feature hangs off. Nothing here is arranged by hand and there is no
   stored order: the layout is the plan, recomputed on every read.

   The WIRES are the dependencies, drawn from the thing that has to finish into
   the left edge of the thing waiting on it. They carry an arrowhead because
   direction is the whole content of a dependency, and a plain curve between
   two boxes says only that the two are related.
   ========================================================================== */

/* The one page in this application whose subject is width. Everything else is a
   column of prose or a grid of cards and --content-max is right for those; a
   roadmap five waves wide inside a 1280px cap spends its width on a scrollbar.
   Written as a :has() rule here rather than a class on <main>, because _Layout
   renders that element and a page cannot reach it. */
.app-main:has(.roadmap-map) { max-width: none; }

.roadmap-map {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    gap: var(--space-6);
    align-items: start;
}

/* Every write and every redraw goes through one render, and a screen that looks
   identical while one is in flight is a screen people press twice. */
.roadmap-busy { opacity: 0.72; }

/* ---- the rail ----------------------------------------------------------- */

.roadmap-rail {
    display: flex;
    flex-direction: column;
    /* No gap. Each card's height is set by the script to its band's height, and
       a gap here would put the fourth card half a band out of line with the
       fourth band. The separation is a border instead. */
    gap: 0;
}

.roadmap-rail-lane {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-6);
    border-bottom: var(--border-width) solid var(--border);
    overflow: hidden;
}

.roadmap-rail-lane:first-child { border-top: var(--border-width) solid var(--border); }

.roadmap-rail-title {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--text);
    line-height: var(--leading-snug);
}

.roadmap-rail-title:hover { color: var(--text-link); }

.roadmap-rail-tallies {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.roadmap-tally {
    font-size: var(--text-2xs);
    padding: var(--space-1) var(--space-4);
    border-radius: var(--radius-pill);
    background: var(--neutral-soft);
    color: var(--neutral-on-soft);
    white-space: nowrap;
}

.roadmap-rail-empty {
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    line-height: var(--leading-snug);
}

/* ---- the plane ---------------------------------------------------------- */

/* Sideways only. The page owns the vertical scroll, which is what keeps the
   rail beside the bands without a sticky element inside a transformed box. */
.roadmap-viewport {
    position: relative;
    overflow-x: auto;
    overflow-y: hidden;
    background: var(--surface-sunken);
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-lg);
    user-select: none;
}

/* Transform does not change layout, so the scroll extent has to be set here
   from the plane's size times the zoom, or half a zoomed-in roadmap would be
   unreachable. */
.roadmap-zoom {
    width: var(--plane-width);
    height: var(--plane-height);
}

.roadmap-plane {
    position: relative;
    width: var(--plane-natural-width);
    height: var(--plane-natural-height);
    transform: scale(var(--plane-zoom, 1));
    transform-origin: 0 0;
}

.roadmap-columns {
    position: absolute;
    inset: 0 0 auto 0;
    height: var(--column-head);
}

.roadmap-column {
    position: absolute;
    top: 0;
    left: var(--column-x);
    width: var(--column-width);
    padding: var(--space-4) var(--space-5);
    font-size: var(--text-2xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    color: var(--text-subtle);
}

/* The bands. Alternating, faintly, because a roadmap with nine blocks is nine
   rows a reader has to keep their place in and a hairline is not enough. */
.roadmap-band {
    position: absolute;
    left: 0;
    top: var(--band-y);
    width: 100%;
    height: var(--band-height);
    border-bottom: var(--border-width) solid var(--border);
}

.roadmap-band-alt { background: var(--surface-alt); }

.roadmap-band-empty {
    position: absolute;
    top: var(--band-y);
    left: 0;
    height: var(--band-height);
    display: flex;
    align-items: center;
    padding: 0 var(--space-8);
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* ---- a feature ---------------------------------------------------------- */

.roadmap-node {
    position: absolute;
    left: var(--node-x);
    top: var(--node-y);
    width: var(--node-width);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-6);
    background: var(--surface);
    border: var(--border-width) solid var(--border);
    border-left: var(--border-accent) solid var(--border-strong);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    text-decoration: none;
    transition: box-shadow var(--transition-fast) var(--ease-out);
}

.roadmap-node:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--brand);
}

.roadmap-node-title {
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--text);
    line-height: var(--leading-snug);
}

.roadmap-node-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-2xs);
    color: var(--text-subtle);
}

/* How many features this one waits on, on the box itself. The wires say the
   same thing and say it better, right up until forty of them cross the plane,
   which is exactly when somebody needs to know. */
.roadmap-node-waits {
    font-size: var(--text-2xs);
    color: var(--text-muted);
    white-space: nowrap;
}

/* Hovering one box answers one question: what does this wait on, and what waits
   on it. Everything unrelated goes quiet rather than away, because a box that
   vanishes takes the shape of the roadmap with it. */
.roadmap-node-dim { opacity: 0.28; }

.roadmap-node-lit {
    border-color: var(--brand);
    box-shadow: var(--shadow-md);
}

/* ---- the wires ---------------------------------------------------------- */

.roadmap-wires {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* Under the boxes, and never swallowing a click aimed at one. */
    pointer-events: none;
}

.roadmap-wire {
    fill: none;
    stroke: var(--border-strong);
    stroke-width: var(--border-width-thick);
}

.roadmap-wire-lit { stroke: var(--brand); }

.roadmap-wire-dim { opacity: 0.2; }

.roadmap-arrow { fill: var(--border-strong); }

.roadmap-arrow-lit { fill: var(--brand); }

/* ---- what the picture cannot draw --------------------------------------- */

.roadmap-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-6);
    margin-top: var(--space-6);
    font-size: var(--text-2xs);
    color: var(--text-subtle);
}

.roadmap-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    padding: var(--space-18);
    font-size: var(--text-sm);
    color: var(--text-subtle);
    text-align: center;
}

/* A screen narrow enough that a 260px rail beside a graph leaves no graph. The
   rail goes above, which loses the block name while scrolling sideways and is
   the better of the two bad answers at this width. */
@media (max-width: 900px) {
    .roadmap-map { grid-template-columns: minmax(0, 1fr); }
    .roadmap-rail { flex-direction: row; flex-wrap: wrap; }
    .roadmap-rail-lane { height: auto !important; flex: 1 1 200px; }
}
