/* The tree, and the toolbar every list screen shares with it. */

/* The proportions this table is built from, stated once. tokens.css holds what
   the whole product shares and is not this screen's to rewrite, so the sizes
   that belong to this one table are named here and never written again as a
   number inside a rule. Colours, spaces and radii all come from tokens.css. */
:root {
    /* The fixed columns, widest first. */
    --tree-owner-col: 132px;
    --tree-progress-col: 148px;
    /* What the bar takes once the table has given up a column. */
    --tree-progress-col-tight: 110px;
    --tree-history-col: 120px;
    /* The room the figure at the end of the bar takes, so every bar in the
       column ends at the same place whether the figure is a percentage or a
       word. */
    --tree-figure-col: 48px;
    /* The reading column is held between these: a floor so a tree of short
       readings still rules a column, a ceiling so one long reading cannot take
       the name's room. */
    --tree-value-min: 11ch;
    --tree-value-max: 22ch;
    /* One line of a name. The marks that stand beside a name are boxed to it,
       so a name that wraps keeps them on its first line. */
    --tree-line: calc(var(--text-base) * var(--leading-tight));
    /* The chevron's box and the dot beside it. */
    --tree-disclosure: 18px;
    --tree-mark: 9px;
    --tree-mark-ring: 2px;
    /* The shape of the history, at the size it is drawn in a row. */
    --tree-spark-height: 26px;
    --tree-spark-stroke: 1.5px;
}

/* The table ------------------------------------------------------------- */

/* The panel holds the table and the control that adds to it. What the rows can
   fit is decided by how wide this panel is, not by how wide the window is: the
   sidebar takes the same room whatever the window does, and a table that reads
   the window instead of its own column folds up while it still has space to
   stand in. */
.tree {
    container: tree / inline-size;
    /* What one level of nesting costs. A step wide enough to read across a full
       table is a step that eats the name on a narrow one, so it shortens as the
       column does. */
    --tree-step: var(--space-7);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

/* The reading column is as wide as the longest reading on screen: the row counts
   its characters, this turns the count into a width.

   It is worked out here, on the table, and handed down as a length. A character
   is a unit of the type it is set in, and the header is set smaller than the
   rows it heads — so a column computed on each of them separately comes out two
   different widths, and every label between the name and the progress bar sits
   beside its data instead of over it. The table settles the width once, at the
   size the readings themselves are set in, and the header and the rows are given
   the same answer. */
@property --tree-value-col {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}

.tree-table {
    font-size: var(--text-base);
    --tree-value-col: clamp(
        var(--tree-value-min),
        calc((var(--value-chars, 12) + 1) * 1ch),
        var(--tree-value-max)
    );
}

.tree-head,
.tree-row {
    display: grid;
    grid-template-columns:
        minmax(0, 1fr) var(--tree-owner-col) var(--tree-value-col)
        var(--tree-progress-col) var(--tree-history-col);
    align-items: center;
    gap: var(--space-5);
    padding: 0 var(--space-6);
}

.tree-head {
    height: var(--field-height);
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--line-strong);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--ink-muted);
}

/* A row grows to hold its name. A name is the only thing a row carries that
   cannot be worked out from anything else, so it is never cut short. */
.tree-row {
    min-height: var(--row-height);
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--line);
    position: relative;
}

.tree-row:last-child {
    border-bottom: 0;
}

.tree-row:hover {
    background: var(--surface-hover);
}

/* Archived rows only appear when they are asked for, and when they do they sit
   among live ones. Their colour is still theirs, held back far enough that live
   work reads first. */
.tree-row-archived .tree-name-text,
.tree-row-archived .tree-owner,
.tree-row-archived .tree-value {
    color: var(--ink-muted);
}

.tree-row-archived .progress,
.tree-row-archived .sparkline {
    opacity: 0.4;
}

.tree-history {
    justify-self: end;
}

/* Name cell: depth, disclosure, kind, link ------------------------------ */

/* One step per level of nesting, taken by the whole cell rather than by a
   spacer inside it. Everything in the cell stands on the name's first line: a
   name long enough to wrap must not carry its own chevron off to the middle of
   the block. */
.tree-name {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    min-width: 0;
    padding-left: calc(var(--depth, 0) * var(--tree-step));
}

.tree-disclosure,
.tree-disclosure-empty,
.tree-kind {
    flex: none;
    height: var(--tree-line);
    display: grid;
    place-items: center;
}

.tree-disclosure,
.tree-disclosure-empty {
    width: var(--tree-disclosure);
}

.tree-disclosure {
    border-radius: var(--radius-sm);
    color: var(--ink-faint);
    transition: transform var(--duration) ease, color var(--duration) ease;
    /* The whole row is a link, and the link's hit area covers everything in the
       row. The controls inside the row have to sit above it or they cannot be
       clicked at all. */
    position: relative;
    z-index: 1;
}

/* The chevron is the control pressed most often on this screen and it is drawn
   the size of one line of text. What is pressed reaches past what is drawn, as
   far as it can without meeting the name beside it. */
.tree-disclosure::after {
    content: '';
    position: absolute;
    inset: calc(var(--space-2) * -1);
}

.tree-disclosure:hover {
    color: var(--ink);
    background: var(--track);
}

.tree-disclosure[aria-expanded='true'] {
    transform: rotate(90deg);
}

/* An Objective is a solid square, a Key Result an open circle. Which of the two
   a row is has to be read at a glance, five levels down, so the two marks differ
   in weight as well as in shape. The mark carries no other meaning. */
.tree-kind {
    width: var(--tree-mark);
}

.tree-kind::before {
    content: '';
    display: block;
    width: var(--tree-mark);
    height: var(--tree-mark);
}

.tree-kind-objective::before {
    border-radius: var(--radius-mark);
    background: var(--ink-secondary);
}

.tree-kind-key-result::before {
    border: var(--tree-mark-ring) solid var(--span-strong);
    border-radius: 50%;
}

.tree-name-text {
    font-size: var(--text-base);
    color: var(--ink);
    line-height: var(--leading-tight);
    /* A name is never cut short and never pushes the columns out of line, so a
       long one wraps, and one long unbroken word breaks. */
    overflow-wrap: anywhere;
}

.tree-row-objective .tree-name-text {
    font-weight: var(--weight-semibold);
}

.tree-name-link {
    min-width: 0;
}

.tree-name-link::after {
    content: '';
    position: absolute;
    inset: 0;
}

.tree-row:hover .tree-name-text {
    color: var(--accent-strong);
}

.tree-owner {
    font-size: var(--text-base);
    color: var(--ink-secondary);
    overflow-wrap: anywhere;
}

/* The person is a link to everything that is theirs. The name of the row
   reaches across the whole row, so this stands above that reach — and only as
   wide as the name, so the rest of the cell still belongs to the row. */
.tree-owner-link {
    position: relative;
    z-index: 1;
    display: inline-block;
    max-width: 100%;
    transition: color var(--duration) ease;
}

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

/* The reading, and what it is aimed at. The target is quieter than the value:
   one is what happened, the other is what was asked for. The whole reading
   stands on one line — a figure split across two stops being a figure, and a
   unit dropped under it makes one row taller than every other. */
.tree-value {
    font-size: var(--text-base);
    color: var(--ink);
    line-height: var(--leading-tight);
    white-space: nowrap;
    /* A reading past the width the column is allowed to reach is cut rather than
       run into the bar beside it. It is written out in full on the Key Result's
       own screen. */
    overflow: hidden;
    text-overflow: ellipsis;
}

.tree-value-target,
.tree-value-unit {
    color: var(--ink-muted);
}

/* The bar itself is defined once, in controls.css, and is the same object on
   every screen. Nothing about its colour or its shape is restated here.

   One shape all the way down the column: a satisfied-or-not direction has no
   percentage — a figure would invent a precision it does not have — so the word
   stands where a percentage stands, and every reading in the column is a bar
   and a figure ending at one edge. */

/* The sparkline --------------------------------------------------------- */

/* The shape of the readings, given the weight of a chart rather than of a rule
   drawn under them: the line, and the ground it covers. A column narrower than
   the drawing scales it down rather than letting it out of its cell. */
.sparkline {
    display: block;
    max-width: 100%;
    overflow: visible;
}

.sparkline-line {
    fill: none;
    stroke: var(--span-strong);
    stroke-width: var(--tree-spark-stroke);
    stroke-linecap: round;
    stroke-linejoin: round;
}

.sparkline-area {
    fill: var(--track);
    stroke: none;
}

/* The reading the row is reporting, marked on the shape that produced it. With
   one reading it is the whole sparkline, which is what one reading is. */
.sparkline-latest {
    fill: var(--span-strong);
}

.sparkline-green .sparkline-line {
    stroke: var(--green-mark);
}

.sparkline-green .sparkline-latest {
    fill: var(--green-mark);
}

.sparkline-green .sparkline-area {
    fill: var(--green-soft);
}

.sparkline-amber .sparkline-line {
    stroke: var(--amber-mark);
}

.sparkline-amber .sparkline-latest {
    fill: var(--amber-mark);
}

.sparkline-amber .sparkline-area {
    fill: var(--amber-soft);
}

.sparkline-red .sparkline-line {
    stroke: var(--red-mark);
}

.sparkline-red .sparkline-latest {
    fill: var(--red-mark);
}

.sparkline-red .sparkline-area {
    fill: var(--red-soft);
}

.tree-history .sparkline {
    width: var(--tree-history-col);
    height: var(--tree-spark-height);
}

/* A search that found nothing says so and stops. */
.tree-nothing {
    padding: var(--space-6);
    font-size: var(--text-base);
    color: var(--ink-muted);
}

/* Between a full table and a stacked row ---------------------------------
   Five columns stop fitting long before the name does. The name is the one
   thing in a row that cannot be worked out from anything else, so the column
   that can — the owner, who is on the row's own screen and in the filter above
   it — goes first, and the reading gives up the room it was holding for a
   width it does not need.

   The two widths below are the table's own, measured against the widest name
   and the longest reading: a query cannot be written in terms of a token, so
   they are the only two numbers in this file that stand outside the block at
   the top. */
@container tree (max-width: 939px) {
    .tree-table {
        --tree-step: var(--space-6);
        --tree-value-max: 16ch;
        --tree-progress-col: var(--tree-progress-col-tight);
    }

    .tree-head,
    .tree-row {
        grid-template-columns:
            minmax(0, 1fr) var(--tree-value-col) var(--tree-progress-col)
            var(--tree-history-col);
    }

    .tree-owner,
    .tree-owner-head {
        display: none;
    }
}

/* Narrower than a table ---------------------------------------------------
   Below this four columns leave a name too little to be read in — the name
   shreds into five and six lines while the figures beside it sit in the room
   they were promised. So the row stops being a row of columns: the name and
   whose it is, then the reading, the bar and the shape it came from. The whole
   row steps in by its depth — the name and the numbers under it belong to the
   same row and move together. */
@container tree (max-width: 679px) {
    .tree-table {
        --tree-step: var(--space-5);
    }

    .tree-head {
        display: none;
    }

    .tree-row {
        /* The reading and the bar divide the line in a fixed proportion, so
           they start at the same place on every row and the column can still be
           read down. The shape of the history keeps its own width at the end of
           the line rather than being sized by what happens to sit above it. */
        grid-template-columns: repeat(3, minmax(0, 1fr));
        grid-template-areas:
            'name name owner'
            'value progress history';
        align-items: center;
        gap: var(--space-3) var(--space-4);
        padding: var(--space-5) var(--space-5) var(--space-5)
            calc(var(--space-5) + var(--depth, 0) * var(--tree-step));
    }

    /* An Objective has no reading, so its row is one line: what it is called and
       whose it is. */
    .tree-row-objective {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: 'name owner';
    }

    .tree-name {
        grid-area: name;
        padding-left: 0;
    }

    /* Whose the row is went with the columns; on a stacked row there is room
       for it again, at the end of the name's own line. */
    .tree-owner {
        display: block;
        grid-area: owner;
        justify-self: end;
        color: var(--ink-muted);
        font-size: var(--text-sm);
    }

    .tree-value {
        grid-area: value;
    }

    /* The bar never grows past the width it has on a full table: a stacked row
       is a narrow column, not a licence for a bar the width of the screen. */
    .tree-row .tree-history {
        grid-area: history;
    }

    .tree-row-objective .tree-value,
    .tree-row-objective .progress,
    .tree-row-objective .tree-history {
        display: none;
    }
}
