/* The objective map. Every value comes from tokens.css; the numbers the map
   writes into style attributes are positions worked out at runtime from these. */

/* The layout reads these back, so they are declared as lengths and resolve to
   real pixels rather than to the text of a calc. Each one is a whole multiple of
   a spacing step: the map never invents a size of its own. */
@property --map-gap-x {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}
@property --map-gap-y {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}
@property --map-gap-stack {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}
@property --map-card-min {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}
@property --map-card-max {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}
@property --map-step {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}
@property --map-corner {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}
@property --map-lane {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}

.map {
    --map-gap-x: var(--space-6);
    --map-gap-y: calc(var(--space-10) * 1.5);
    --map-gap-stack: var(--space-4);
    /* The narrowest a card may be and still hold a name, an owner and a
       reading, and the widest one is allowed to grow to. A surface too narrow
       for a row of the first cascades instead. */
    --map-card-min: calc(var(--space-10) * 4);
    --map-card-max: calc(var(--space-10) * 6);
    /* What one level costs when the tree cascades, the radius the line turns
       through, and how far inside a card its line drops. */
    --map-step: var(--space-9);
    --map-corner: var(--space-4);
    --map-lane: var(--space-4);
    /* The canvas the cards stand on, and one line of a name: the glyph beside a
       name is boxed to it, so a name that wraps keeps its mark on the first
       line. */
    --map-grid: var(--space-7);
    --map-line: calc(var(--text-md) * var(--leading-tight));
    --map-glyph: var(--space-4);

    background-color: var(--surface-sunken);
    background-image: radial-gradient(var(--line-strong) 1px, transparent 1px);
    background-size: var(--map-grid) var(--map-grid);
    background-position: calc(var(--map-grid) / 2) calc(var(--map-grid) / 2);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    padding: var(--space-8);
}

/* Once the window is narrower than the content it can hold (--content-max), the
   columns close up before they give way. */
@media (max-width: 1180px) {
    .map {
        --map-gap-x: var(--space-5);
    }
}

.map-surface {
    position: relative;
    min-width: 0;
}

/* Nothing is placed until the width is known, so no card is ever seen in the
   wrong place. It is faded rather than hidden: a chevron pressed from the
   keyboard is handed the keyboard back on the card that replaces it, and
   nothing hidden can take it. */
.map-surface:not([data-painted]) {
    opacity: 0;
}

.map-edges {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
}

/* One line from a parent's foot to each child's head. It carries no arrow: a
   tree read from the top says which way it runs. */
.map-edge {
    fill: none;
    stroke: var(--span-strong);
    stroke-width: var(--stroke-hair);
    stroke-linecap: round;
}

/* A card ---------------------------------------------------------------- */

.map-node {
    position: absolute;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-lg);
    transition: border-color var(--duration) ease;
}

/* The whole card is the link, so the name's reach is stretched across it. */
.map-node-link::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: var(--radius-lg);
}

.map-node-head {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    min-width: 0;
}

/* An Objective is a solid square, a Key Result an open circle — the same pair
   the tree puts beside every row. The mark carries no other meaning. */
.map-node-glyph {
    flex: none;
    width: var(--map-glyph);
    height: var(--map-line);
    display: grid;
    place-items: center;
}

.map-node-glyph::before {
    content: '';
    display: block;
    width: var(--map-glyph);
    height: var(--map-glyph);
}

.map-node-glyph-objective::before {
    border-radius: var(--radius-mark);
    background: var(--ink-secondary);
}

.map-node-glyph-key-result::before {
    border: var(--space-1) solid var(--span-strong);
    border-radius: 50%;
}

.map-node-name {
    font-size: var(--text-md);
    line-height: var(--leading-tight);
    color: var(--ink);
    /* A name is never cut short, so a long one wraps and one long unbroken word
       breaks. */
    overflow-wrap: anywhere;
    transition: color var(--duration) ease;
}

.map-node-objective .map-node-name {
    font-weight: var(--weight-semibold);
}

/* The person is a link to everything that is theirs. The card is a link over its
   whole face, so this stands above that reach — and only as wide as the name, so
   the rest of the line still opens the card. */
.map-node-owner {
    position: relative;
    z-index: 1;
    align-self: flex-start;
    max-width: 100%;
    font-size: var(--text-sm);
    color: var(--ink-muted);
    overflow-wrap: anywhere;
    transition: color var(--duration) ease;
}

.map-node-owner:hover {
    color: var(--accent-strong);
    text-decoration: underline;
}

.map-node .progress {
    /* The reading sits on the card's own rail, under the name it belongs to. */
    gap: var(--space-3);
}

/* On a cascading card the bar does not run the card's whole width: a bar longer
   than a spread card's is the same reading taking more room to say it. */
.map-node .progress-track {
    max-width: calc(var(--space-10) * 4);
}

.map-node .progress-figure {
    font-size: var(--text-sm);
    min-width: 0;
}

/* The control that opens and shuts what hangs below, on the card's own foot. It
   stands above the link that covers the card, or it could not be pressed. */
.map-node-foot {
    display: flex;
    justify-content: flex-end;
    margin-top: auto;
}

.map-disclosure {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--ink-muted);
    transition: color var(--duration) ease, border-color var(--duration) ease,
        background var(--duration) ease;
}

.map-disclosure:hover {
    color: var(--ink);
    border-color: var(--ink-faint);
    background: var(--surface-hover);
}

.map-chevron {
    width: var(--space-5);
    height: var(--space-5);
    transition: transform var(--duration) ease;
}

.map-disclosure[aria-expanded='true'] .map-chevron {
    transform: rotate(180deg);
}

.map-count {
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    font-variant-numeric: tabular-nums;
}

.map-node:hover {
    border-color: var(--accent);
}

.map-node:hover .map-node-name {
    color: var(--accent-strong);
}

/* Archived cards only appear when they are asked for, and when they do they
   stand among live ones, held back far enough that live work reads first. */
.map-node-archived .map-node-name,
.map-node-archived .map-node-owner {
    color: var(--ink-muted);
}

.map-node-archived .progress {
    opacity: 0.4;
}

.map-bare {
    padding: var(--space-6) var(--space-8);
}

.map-none {
    font-size: var(--text-base);
    color: var(--ink-muted);
}

@media (max-width: 720px) {
    .map {
        padding: var(--space-5);
    }
}
