/*
  Device hierarchy board (DeviceHierarchyView and the card components underneath it).

  Loaded globally from index.html, the same way the revenue page loads its own sheet. Every rule is
  namespaced with the dhv- prefix because the board spans several components: the view owns the
  bands, DeviceBoardBranch the nesting, and the two card components the cards themselves.
*/

.dhv-root {
    /*
      Card widths. A card carrying its signal tiles puts them beside the figures instead of under them,
      which makes it wide and short rather than narrow and tall — the board has width to spare far more
      often than it has height, because it is scaled to fit the screen rather than scrolled.

      DeviceBoardCardSize mirrors these three figures: it has to predict how big a card comes out in
      order to pick the column layout before anything has been drawn.
    */
    --dhv-card-w: 265px;
    --dhv-card-w-wide: 440px;
    --dhv-card-main-w: 190px;

    --dhv-consume: #0ea5e9;
    --dhv-produce: #10b981;
    /* The connection point is the anchor of the whole board, so it gets a colour of its own
       rather than sharing one with the things hanging off it. */
    --dhv-grid: #7c3aed;
    --dhv-idle-line: #a9b4c4;
}

/* ---- Header / KPI strip / legend ---- */
.dhv-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem 1rem;
    margin-bottom: 0.5rem;
}

.dhv-kpis {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.dhv-kpi {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    border: 1px solid var(--rz-border-color);
    border-radius: 8px;
    padding: 0.3rem 0.7rem;
    background: var(--rz-base-100, rgba(0, 0, 0, 0.015));
}

.dhv-kpi-label {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.66rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--rz-text-secondary-color);
}

.dhv-kpi-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}

.dhv-kpi-value {
    display: flex;
    align-items: baseline;
    gap: 0.25rem;
}

.dhv-kpi-value .v {
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.dhv-kpi-value .u {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--rz-text-tertiary-color);
}

.dhv-controls {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.dhv-legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    font-size: 0.78rem;
    color: var(--rz-text-secondary-color);
}

.dhv-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}

.dhv-legend-swatch {
    width: 26px;
    height: 4px;
    border-radius: 4px;
}

.dhv-legend-swatch.consume { background: var(--dhv-consume); }

/* Board-wide switch, sitting with the other controls rather than on the board itself. */
.dhv-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    white-space: nowrap;
    font-size: 0.78rem;
    color: var(--rz-text-secondary-color);
}

.dhv-toggle label {
    cursor: pointer;
    margin: 0;
    font-size: inherit;
    color: inherit;
}

/* Zoom sits with the other controls; the percentage between the buttons is a readout, not a field. */
.dhv-zoom {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

.dhv-zoom-value {
    min-width: 3rem;
    text-align: center;
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--rz-text-secondary-color);
}
.dhv-legend-swatch.produce { background: var(--dhv-produce); }

/* ---- Board ---- */
.dhv-board {
    position: relative;
    /*
      Claim what is left of the window rather than only as much as the cards happen to need. A site
      diagram is read as one picture, so the board is a screen and the scale adapts to it. Deliberately
      a little short of the full window: nothing here should push the page into scrolling, because the
      wheel over the board is the zoom gesture and there must be nothing left for it to scroll past.
    */
    /* Starting estimate only: once measured, the view pins the exact height that leaves no scroll. */
    min-height: calc(100vh - 19rem);
    display: flex;
    flex-direction: column;
    justify-content: safe center;
    border: 1px solid var(--rz-border-color);
    border-radius: 18px;
    background: var(--rz-base-50, #f7f9fc);
    padding: 1.25rem 1.5rem 1.75rem;
    box-shadow: 0 1px 2px rgba(16, 40, 80, 0.06), 0 10px 30px rgba(16, 40, 80, 0.06);
}

.dhv-zone {
    position: relative;
    z-index: 1;
}

/*
  The bands carry no colour of their own. Every card already says on its accent edge which way its
  energy is going, so tinting the band behind it only repeats that in a weaker form.
*/
.dhv-zone-produce,
.dhv-zone-consume {
    padding: 0.25rem 0 0.5rem;
}

.dhv-zone-label {
    display: flex;
    justify-content: center;
    margin-bottom: 0.85rem;
}

.dhv-zone-label span {
    border: 1px solid var(--rz-border-color);
    border-radius: 999px;
    background: var(--rz-base-background-color, #fff);
    padding: 0.2rem 0.85rem;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--rz-text-secondary-color);
}

/*
  A band is one or more columns of branches. Cards carry a fixed width so every column lines up and a
  lone card does not shrink to its text; a branch that fans out sideways is free to be wider.

  Filled column by column, so a band still reads top to bottom before it moves across. The row count
  comes from the view (--dhv-rows), which is the whole mechanism: with one column it is simply the
  number of cards and nothing has changed, and with more it is where each next column starts.

  The rows are declared rather than implicit, so every column shares them and a row is as tall as the
  tallest card in it. That is what keeps the gaps between rows lined up clear across the band — and
  those gaps are not only gaps, they are the channels the flow paths to the far columns run along.
*/
.dhv-zone-grid {
    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(var(--dhv-rows, 1), auto);
    grid-auto-columns: max-content;
    align-items: center;
    justify-items: center;
    justify-content: center;
    row-gap: 2.75rem;
    /* Wider than the row gap: the paths to the columns beyond it run down the middle of it. */
    column-gap: 3.5rem;
}

/*
  The three bands sit side by side and the energy reads left to right: producers into the connection
  point, the connection point out to the consumers. Centred against each other, so the connection
  point lines up with the middle of the columns feeding it rather than hugging the top.

  Sized to its content rather than stretched across the board, which is what lets the board be fitted
  to the screen at all: a grid of 1fr columns is always exactly as wide as the space it is given, so
  there would never be anything to scale up or down towards.
*/
.dhv-bands {
    display: grid;
    grid-template-columns: auto auto auto;
    gap: 3.5rem;
    align-items: center;
    justify-items: center;
    width: max-content;
    /* "safe" so that content wider than the board falls back to starting at the left edge instead of
       being centred half off it, where the overflowing side could not be reached at all. */
    align-self: safe center;
}

/* The middle column stacks: bidirectional cards above, the connection point, then more below. The
   gap is generous because the flow paths between them are short and need room to be seen. */
.dhv-zone-net {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3rem;
}

.dhv-empty-zone {
    text-align: center;
    font-size: 0.78rem;
    color: var(--rz-text-tertiary-color);
    padding: 0.5rem 0 1rem;
}

/* ---- Flow layer ---- */
.dhv-flow-layer {
    position: absolute;
    inset: 0;
    overflow: visible;
    pointer-events: none;
    z-index: 0;
}

/*
  A ribbon rather than a wire. Its width is how much the path carries, so the board reads as volumes
  at a glance; drawn faintly, because at eighteen pixels a solid line would shout over the cards.
*/
.dhv-flow-line {
    fill: none;
    stroke-linecap: round;
    /* Quick enough to keep up with a zoom gesture; the ribbon should follow the cards, not trail them. */
    transition: stroke-width 0.2s ease, stroke 0.2s ease;
}

/* The dots travelling along a ribbon are what say which way the energy is actually going. */
.dhv-flow-dot {
    opacity: 0.95;
}

@keyframes dhv-shimmer {
    to { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    /* The ribbon still carries the direction in its arrowhead, so the moving dots can simply go. */
    .dhv-flow-dot { display: none; }
    .dhv-flow-line { transition: none; }
    .dhv-skeleton { animation: none; }
    .dhv-age.is-refreshing { animation: none; }
}

/* ---- Card ---- */
.dhv-card {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.4rem 0.7rem;
    box-sizing: border-box;
    /* Fixed so every column lines up and a card never shrinks to the width of its own text. */
    width: var(--dhv-card-w);
    flex: 0 0 auto;
    background: var(--rz-base-background-color, #fff);
    border: 1px solid var(--rz-border-color);
    border-radius: 14px;
    padding: 0.7rem 0.8rem 0.65rem 1.1rem;
    cursor: grab;
    box-shadow: 0 1px 2px rgba(16, 40, 80, 0.06), 0 6px 16px rgba(16, 40, 80, 0.06);
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease, opacity 0.18s ease;
}

.dhv-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 10px rgba(16, 40, 80, 0.09), 0 10px 24px rgba(16, 40, 80, 0.08);
}

.dhv-card:active { cursor: grabbing; }

/*
  Tiles beside the figures instead of under them. Two panes rather than one taller column: the header,
  the primary value and the footer already occupy a fixed amount of height that the tiles can sit
  alongside for free, so the card ends up both shorter and smaller in area than the stacked version.

  The width follows the switch and the panes follow the readings, which are deliberately two different
  things. Every card in a band has to be the same width or its columns stop lining up, but a device that
  only reports its power has no tiles to put beside its figures — so that card is just as wide and gives
  the whole width to its figures instead.
*/
.dhv-card.is-landscape { width: var(--dhv-card-w-wide); }

.dhv-card.has-tiles { grid-template-columns: var(--dhv-card-main-w) minmax(0, 1fr); }

.dhv-card-main {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    min-width: 0;
}

/* Centred against the figures beside it, so a card with one row of tiles does not look top-heavy. */
.dhv-card-side {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
}

/*
  Rows that belong to the card as a whole rather than to either pane. The chips are the reason this
  matters: spanning both panes gives them twice the width, so a group of ten members needs half the
  rows of them. A device card keeps its footer inside the left pane, under the figures it acts on; a
  group card's spans the card, under the chips.
*/
.dhv-card > .dhv-chip-row,
.dhv-card > .dhv-empty-group,
.dhv-card > .dhv-card-foot,
.dhv-card > .dhv-expand { grid-column: 1 / -1; }

/* An expanded group holds full member cards, so it may outgrow the standard card width. */
.dhv-card.is-group.is-expanded { width: auto; max-width: 640px; }

/* A group is picked up as one card, like a device. Only cards a group positions itself sit still. */
.dhv-card.is-static { cursor: default; }

.dhv-card.is-root {
    border-color: color-mix(in srgb, var(--dhv-accent, var(--rz-primary)) 55%, var(--rz-border-color));
    box-shadow:
        0 0 0 4px color-mix(in srgb, var(--dhv-accent, var(--rz-primary)) 12%, transparent),
        0 10px 28px rgba(16, 40, 80, 0.14);
}

/*
  Everything on the board hangs off the connection point, so it is the one card that should read
  as the anchor: its own colour, a heavier accent edge and a deeper lift than the rest.
*/
.dhv-card.is-grid {
    border-color: color-mix(in srgb, var(--dhv-grid) 45%, var(--rz-border-color));
    background: linear-gradient(180deg, color-mix(in srgb, var(--dhv-grid) 6%, var(--rz-base-background-color, #fff)),
        var(--rz-base-background-color, #fff));
    box-shadow:
        0 0 0 4px color-mix(in srgb, var(--dhv-grid) 14%, transparent),
        0 12px 32px rgba(60, 30, 130, 0.18);
}

.dhv-card.is-grid .dhv-accent-bar { width: 7px; }

.dhv-card.is-dragging {
    opacity: 0.45;
    transform: scale(0.97);
}

.dhv-card.is-drop-target {
    border-color: var(--dhv-consume);
    box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.25), 0 8px 22px rgba(20, 184, 166, 0.18);
    transform: translateY(-2px);
}

/*
  Every card takes every other one — a matching type joins the group, anything else hangs
  underneath — so the only card that reads as unavailable during a drag is one that already hangs
  under the card being dragged, which can never become its parent.
*/
.dhv-card.is-invalid-target {
    opacity: 0.4;
    filter: saturate(0.4);
}

.dhv-card.is-invalid-target:hover { transform: none; }

/*
  The same gesture either adds a device to a group or hangs it underneath, so the card being hovered
  says which one it is offering before the drop commits to it.
*/
.dhv-drop-hint {
    position: absolute;
    top: -0.65rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 3;
    border-radius: 999px;
    padding: 0.16rem 0.6rem;
    background: var(--dhv-consume);
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 3px 10px rgba(14, 165, 233, 0.35);
}

/*
  The accent edge says which way the energy is going right now, not what kind of device this is:
  blue draws, green delivers, grey is idle or silent. The icon tile keeps the device type's own
  colour, so the card still tells you at a glance what it is as well as what it is doing.
*/
.dhv-accent-bar {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 5px;
    border-radius: 14px 0 0 14px;
    background: var(--dhv-idle-line);
    transition: background 0.3s ease;
}

.dhv-card.is-consuming .dhv-accent-bar { background: var(--dhv-consume); }

.dhv-card.is-producing .dhv-accent-bar { background: var(--dhv-produce); }

/* The connection point is the anchor of the board and keeps its own colour whichever way it runs. */
.dhv-card.is-grid .dhv-accent-bar { background: var(--dhv-grid); }

.dhv-card-glow {
    position: absolute;
    inset: 0;
    border-radius: 13px;
    pointer-events: none;
    opacity: 0;
    background: radial-gradient(circle at 50% 0%, rgba(20, 184, 166, 0.16), transparent 70%);
    transition: opacity 0.18s ease;
}

.dhv-card.is-drop-target .dhv-card-glow { opacity: 1; }

.dhv-card-head {
    display: flex;
    align-items: center;
    gap: 0.55rem;
}

.dhv-icon-tile {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: 10px;
    color: var(--dhv-accent, var(--rz-primary));
    background: color-mix(in srgb, var(--dhv-accent, var(--rz-primary)) 14%, transparent);
}

.dhv-icon-tile .rzi { font-size: 1.15rem; }

.dhv-head-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.dhv-name {
    font-weight: 600;
    font-size: 0.85rem;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dhv-type {
    font-size: 0.68rem;
    color: var(--rz-text-secondary-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dhv-status-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    border-radius: 999px;
    padding: 0.15rem 0.5rem;
    font-size: 0.64rem;
    font-weight: 700;
    white-space: nowrap;
}

.dhv-status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
    background: currentColor;
}

.dhv-status-badge.is-ok {
    color: var(--rz-success);
    background: color-mix(in srgb, var(--rz-success) 12%, transparent);
}

.dhv-status-badge.is-warning {
    color: var(--rz-warning);
    background: color-mix(in srgb, var(--rz-warning) 14%, transparent);
}

.dhv-status-badge.is-alarm {
    color: var(--rz-danger);
    background: color-mix(in srgb, var(--rz-danger) 12%, transparent);
}

.dhv-status-badge.is-idle {
    color: var(--rz-text-tertiary-color);
    background: var(--rz-base-200, rgba(0, 0, 0, 0.04));
}

.dhv-value-row {
    display: flex;
    align-items: baseline;
    gap: 0.3rem;
    min-height: 1.9rem;
}

.dhv-value {
    font-size: 1.85rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1;
}

.dhv-value.is-empty { color: var(--rz-text-tertiary-color); }

.dhv-value-unit {
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--rz-text-tertiary-color);
}

.dhv-value-delta {
    font-size: 0.7rem;
    color: var(--rz-text-secondary-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dhv-loadbar {
    height: 5px;
    border-radius: 4px;
    background: var(--rz-base-200, #e8edf3);
    overflow: hidden;
}

.dhv-loadbar-fill {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--rz-success), #34d399);
    transition: width 0.6s ease;
}

.dhv-kpi-grid,
.dhv-summary-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.3rem 0.45rem;
}

.dhv-kpi-cell,
.dhv-summary-cell {
    display: flex;
    flex-direction: column;
    min-width: 0;
    border-radius: 8px;
    padding: 0.25rem 0.4rem;
    background: var(--rz-base-100, rgba(0, 0, 0, 0.02));
}

.dhv-kpi-k,
.dhv-summary-k {
    font-size: 0.58rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--rz-text-tertiary-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dhv-kpi-v,
.dhv-summary-v {
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dhv-summary-u {
    font-size: 0.64rem;
    font-weight: 600;
    color: var(--rz-text-tertiary-color);
}

.dhv-kpi-v.is-critical,
.dhv-summary-v.is-critical { color: var(--rz-danger); }

/*
  A tile that must never be cut off, such as the configured kW band: it spans the full card and
  keeps its value intact rather than ellipsising it.
*/
.dhv-kpi-cell.is-wide { grid-column: 1 / -1; }

.dhv-kpi-cell.is-wide .dhv-kpi-v {
    overflow: visible;
    text-overflow: clip;
}

/*
  ---- Hierarchy: a card and whatever hangs underneath it ----

  Children sit in the direction their band's energy travels, so a chain always reads the same way as
  the board does. In the producing column the energy runs towards the connection point, so a child
  sits left of its parent; in the consuming column it runs away from it, so a child sits right. In
  the middle column, where the flow is vertical, children stack underneath instead.
*/
/*
  The gap between a parent and its children is where the flow line is drawn, so it has to be wide
  enough for that line to be a thing you can see rather than a nick between two touching cards.
*/
.dhv-branch {
    display: flex;
    align-items: center;
    gap: 4.5rem;
    min-width: 0;
}

.dhv-branch.is-upstream { flex-direction: row-reverse; }

.dhv-branch.is-downstream { flex-direction: row; }

.dhv-branch.is-stacked { flex-direction: column; }

/*
  Children sit one level deeper than their parent, with enough room above them for the flow path
  to be drawn. Energy runs one way: a nested card is fed by the card above it and never by the
  Net as well, and that line is what says so.
*/
/* Several children of one card line up across the branch's direction of travel. */
.dhv-children {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2.25rem;
}

.dhv-branch.is-upstream > .dhv-children,
.dhv-branch.is-downstream > .dhv-children { flex-direction: column; }

.dhv-branch.is-stacked > .dhv-children { flex-direction: row; }

.dhv-children .dhv-card {
    box-shadow: 0 1px 2px rgba(16, 40, 80, 0.05);
}

/* ---- Skeletons: the structure renders immediately, values arrive per batch ---- */
.dhv-skeleton {
    display: block;
    border-radius: 6px;
    background: linear-gradient(90deg,
        var(--rz-base-200, #e8edf3) 25%,
        var(--rz-base-100, #f2f5f9) 37%,
        var(--rz-base-200, #e8edf3) 63%);
    background-size: 200% 100%;
    animation: dhv-shimmer 1.4s ease-in-out infinite;
}

.dhv-skeleton-value { width: 6.5rem; height: 1.6rem; }
.dhv-skeleton-key { width: 3.5rem; height: 0.5rem; margin: 0.12rem 0; }
.dhv-skeleton-val { width: 2.75rem; height: 0.62rem; margin: 0.12rem 0; }

.dhv-age {
    font-size: 0.6rem;
    font-weight: 600;
    color: var(--rz-text-tertiary-color);
    padding-left: 0.15rem;
    white-space: nowrap;
}

.dhv-age.is-refreshing {
    animation: dhv-pulse 1.1s ease-in-out infinite;
}

@keyframes dhv-pulse {
    50% { opacity: 0.35; }
}

/* ---- Group chips: one compact tile per member, status carried by the accent edge ---- */
.dhv-chip-row {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: 0.35rem;
}

.dhv-chip {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    min-width: 0;
    overflow: hidden;
    border-radius: 8px;
    padding: 0.3rem 0.45rem 0.3rem 0.6rem;
    background: var(--rz-base-100, rgba(0, 0, 0, 0.022));
    border: 1px solid var(--rz-border-color);
    transition: background 0.15s ease, border-color 0.15s ease;
}

/*
  The status colours a slim edge rather than the whole tile: with a dozen members on one card a
  full colour wash turns into noise, while an edge still reads at a glance.
*/
.dhv-chip::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: currentColor;
}

.dhv-chip:hover {
    background: var(--rz-base-200, rgba(0, 0, 0, 0.045));
    border-color: color-mix(in srgb, currentColor 35%, var(--rz-border-color));
}

.dhv-chip-code {
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--rz-text-tertiary-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dhv-chip-v {
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--rz-text-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dhv-chip.is-ok { color: var(--rz-success); }

.dhv-chip.is-warning { color: var(--rz-warning); }

.dhv-chip.is-alarm { color: var(--rz-danger); }

.dhv-chip.is-off,
.dhv-chip.is-neutral { color: var(--rz-text-tertiary-color); }

/* The distribution chips above a large group are counts, so the number leads. */
.dhv-chip-row.is-summary .dhv-chip-v {
    font-size: 0.85rem;
    font-weight: 700;
    color: currentColor;
}

.dhv-empty-group {
    font-size: 0.7rem;
    color: var(--rz-text-tertiary-color);
}

/* ---- Group expansion (grows the card, never scrolls inside it) ---- */
.dhv-expand {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.dhv-expand-divider {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    border-top: 1px dashed var(--rz-border-color);
    padding-top: 0.45rem;
    font-size: 0.64rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--rz-text-tertiary-color);
}

/* The members are full cards, so they get their own grid and the group card grows to fit. */
.dhv-member-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(215px, 290px));
    gap: 0.6rem;
    align-items: start;
    justify-content: center;
}

/* Members fill their own track rather than the board's standard card width. */
.dhv-member-grid .dhv-card {
    width: auto;
    box-shadow: 0 1px 2px rgba(16, 40, 80, 0.05);
}

/*
  A member sits in a track a good deal narrower than a card on the board, so there is no width to put
  its tiles beside the figures — inside a group they stack again.
*/
.dhv-member-grid .dhv-card.has-tiles { grid-template-columns: minmax(0, 1fr); }

/* ---- Card footer ---- */
.dhv-card-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    margin-top: auto;
}

.dhv-flags {
    display: flex;
    align-items: center;
    gap: 0.2rem;
}

.dhv-foot-right {
    display: flex;
    align-items: center;
    gap: 0.2rem;
    flex-shrink: 0;
}

.dhv-badge { font-size: 0.9rem; }
.dhv-badge-warning { color: var(--rz-warning); }
.dhv-badge-info { color: var(--rz-info); }
.dhv-badge-success { color: var(--rz-success); }

/* ---- Responsive: stack the zones and drop the flow layer on narrower screens ---- */
/*
  The bands no longer need a column count per breakpoint: auto-fit already drops a track when the
  board narrows. What still has to change is the flow layer, which needs the three-band geometry to
  make sense, and the middle band, which stops flanking the connection point once it cannot.
*/
/*
  Zooming out buys back a great deal of width, so the three columns survive far narrower screens
  than they used to: the fit scale shrinks the cards until they fit rather than the layout giving up
  on them. Only below this is there too little room for three cards at any readable scale.
*/
@media (max-width: 1099.98px) {
    .dhv-flow-layer { display: none; }
    .dhv-bands { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; width: auto; }
    /* Stacked bands are read by scrolling, so a full-height board would only add empty space. */
    .dhv-board { min-height: 0; display: block; }
    /*
      Splitting a band across columns buys width back on a screen that has width to spare. Here there
      is none, and the board is scrolled rather than fitted, so a band goes back to being one column
      however many the view worked out would fit.
    */
    .dhv-zone-grid {
        grid-auto-flow: row;
        grid-template-rows: none;
        grid-template-columns: minmax(0, 1fr);
        row-gap: 1.5rem;
    }
}

@media (max-width: 899.98px) {
    .dhv-member-grid { grid-template-columns: minmax(0, 1fr); }
    .dhv-chip-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    /* Too narrow to fan a branch out sideways, so children go back to stacking. */
    .dhv-branch { flex-direction: column; gap: 1.5rem; }
    .dhv-branch > .dhv-children { flex-direction: column; }
    .dhv-board { padding: 1rem 0.9rem 1.25rem; }
}
