/*
================================================
The dashboard - energy flow and the cards around it (issue #686)
================================================

Proposal A of A_Documents/plans/mockups/dashboard-redesign-mockup.html: the drawn energy flow is
the top of the page, a "Now" column sits beside it, and the rest of the page is grouped by what a
figure is - right now, today, this year.

The flow used to be a five-column table of 64 and 80 px GIFs; common/energyFlow.xhtml draws it as
one SVG now. What moves there moves because of a reading:

  - a stream's dashes travel faster and are drawn thicker the more power the line carries
    (--dur and stroke-width come from EnergyFlow.Stream), and run backwards for an import or a
    discharging battery
  - the battery's fill is its state of charge and breathes while it charges
  - the heat pump's fan turns while it runs
  - the roof and the wallbox send out a ring while they produce or charge
  - a figure that changed on the 60 s poll counts to its new value (js/dashboard.js)

With prefers-reduced-motion all of it stands still; the drawing and every number stay.

One colour per role, used for the node, its stream and its figure alike: amber is the roof,
violet the grid you buy from, green what is sold, teal the battery, blue the house, orange the car,
red the heat pump. Loaded for every page from common/commonHead.xhtml; only base.xhtml uses it.
*/

:root {
    --flow-sun: #e09a00;
    --flow-grid: #7a4fd0;
    --flow-export: #12805c;
    --flow-batt: #0d8f8f;
    --flow-house: #1a73e8;
    --flow-car: #c2410c;
    --flow-heat: #c5303e;
    --flow-sock: #6b7290;
    --flow-track: #e3e6f1;
    --flow-ink: #2a2f45;
    --flow-ink-soft: #6b7290;
    --flow-ink-faint: #949bb5;
    --flow-rule: #eceef6;
    --flow-card: #ffffff;
    --flow-good: #12805c;
    --flow-good-bg: #e6f4ee;
    --flow-warn: #b45309;
    --flow-warn-bg: #fdf0e2;
}

/* ── the drawing ─────────────────────────────────────────────────────── */

.flow {
    display: block;
    width: 100%;
    max-width: 660px;
    height: auto;
    margin: 0 auto;
}

.flow text {
    fill: var(--flow-ink);
    font-size: 12px;
}

.flow .val {
    font-size: 15px;
    font-weight: 600;
    text-anchor: middle;
    font-variant-numeric: tabular-nums;
}

.flow .sub {
    font-size: 11px;
    fill: var(--flow-ink-soft);
    text-anchor: middle;
}

.flow .sub.start {
    text-anchor: start;
}

.flow .track {
    fill: none;
    stroke: var(--flow-track);
    stroke-width: 3;
    stroke-linecap: round;
}

.flow .stream {
    fill: none;
    stroke-linecap: round;
    stroke-dasharray: 2 16;
    animation: flow-stream var(--dur, 2s) linear infinite;
}

.flow .stream.rev {
    animation-direction: reverse;
}

@keyframes flow-stream {
    to {
        stroke-dashoffset: -18;
    }
}

.flow .stream.sun { stroke: var(--flow-sun); }
.flow .stream.grid { stroke: var(--flow-grid); }
.flow .stream.export { stroke: var(--flow-export); }
.flow .stream.batt { stroke: var(--flow-batt); }
.flow .stream.house { stroke: var(--flow-house); }
.flow .stream.car { stroke: var(--flow-car); }
.flow .stream.heat { stroke: var(--flow-heat); }
.flow .stream.sock { stroke: var(--flow-sock); }

.flow .node { --c: var(--flow-ink-faint); }
.flow .node.sun { --c: var(--flow-sun); }
.flow .node.grid { --c: var(--flow-grid); }
.flow .node.export { --c: var(--flow-export); }
.flow .node.batt { --c: var(--flow-batt); }
.flow .node.house { --c: var(--flow-house); }
.flow .node.car { --c: var(--flow-car); }
.flow .node.heat { --c: var(--flow-heat); }

.flow .node-bg {
    fill: var(--flow-card);
    stroke: var(--c);
    stroke-width: 2.5;
}

.flow .glyph,
.flow .outline {
    fill: none;
    stroke: var(--c);
    stroke-width: 2.2;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.flow .cap,
.flow .fill,
.flow .blade {
    fill: var(--c);
}

.flow .fill {
    transition: height 1s ease, y 1s ease;
}

.flow .fill.charging {
    animation: flow-breathe 2.2s ease-in-out infinite;
}

@keyframes flow-breathe {
    50% {
        opacity: 0.55;
    }
}

.flow .fan {
    transform-box: fill-box;
    transform-origin: center;
    animation: flow-spin 1.4s linear infinite;
}

@keyframes flow-spin {
    to {
        transform: rotate(360deg);
    }
}

.flow .pulse {
    fill: none;
    stroke: var(--c);
    stroke-width: 3;
    transform-box: fill-box;
    transform-origin: center;
    animation: flow-pulse 1.8s ease-out infinite;
}

@keyframes flow-pulse {
    from {
        transform: scale(1);
        opacity: 0.55;
    }
    to {
        transform: scale(1.45);
        opacity: 0;
    }
}

/* nothing flows through it right now: still there, just quieter */
.flow .node.idle .node-bg,
.flow .node.idle .glyph,
.flow .node.idle .outline,
.flow .node.idle image {
    opacity: 0.5;
}

.flow .ring-track {
    fill: none;
    stroke: var(--flow-track);
    stroke-width: 4;
}

.flow .ring {
    fill: none;
    stroke: var(--flow-good);
    stroke-width: 4;
    stroke-linecap: round;
}

.flow .hub circle {
    fill: var(--flow-card);
    stroke: var(--flow-ink-faint);
    stroke-width: 2;
}

.flow .hub .dot {
    fill: var(--flow-ink-faint);
    stroke: none;
}

.flow .chip rect {
    fill: var(--flow-card);
    stroke: var(--flow-sock);
}

.flow .chip text {
    font-size: 11px;
}

.flow .chip .name {
    font-weight: 600;
}

.flow .chip .emoji {
    font-size: 13px;
}

/* ── the cards around it ────────────────────────────────────────────── */

.dash-hero {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    gap: 16px;
    margin-bottom: 1.5rem;
}

.dash-hero > .card,
.dash-side > .card {
    margin-bottom: 0;
}

.dash-side {
    display: grid;
    gap: 16px;
    align-content: start;
}

@media (max-width: 991.98px) {
    .dash-hero {
        grid-template-columns: minmax(0, 1fr);
    }
}

.dash-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px 12px;
    margin-bottom: 12px;
}

.dash-head h5 {
    margin: 0;
    font-weight: 600;
}

.dash-section-title {
    font-size: 16px;
    font-weight: 600;
    margin: 0 0 10px 2px;
}

.dash-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--flow-track);
    color: var(--flow-ink-soft);
    white-space: nowrap;
}

.dash-chip.good {
    background: var(--flow-good-bg);
    color: var(--flow-good);
}

.dash-chip.warn {
    background: var(--flow-warn-bg);
    color: var(--flow-warn);
    white-space: normal;
}

.dash-chip .dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

.dash-chip.live .dot {
    animation: flow-breathe 1.6s ease-in-out infinite;
}

.dash-warnings {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* the house photo heads the "Now" column, with the time of the data on it */
.dash-photo {
    position: relative;
    border-radius: 10px;
    overflow: hidden;
    margin: -4px -4px 14px;
}

.dash-photo img {
    display: block;
    width: 100%;
    height: 170px;
    object-fit: cover;
}

.dash-photo .stamp {
    position: absolute;
    left: 10px;
    bottom: 10px;
    background: rgba(20, 24, 40, 0.72);
    color: #fff;
    font-size: 12px;
    padding: 3px 9px;
    border-radius: 999px;
}

.dash-now {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 16px;
    align-items: center;
}

.dash-ring text {
    font-size: 17px;
    font-weight: 600;
    fill: var(--flow-ink);
    font-variant-numeric: tabular-nums;
}

.dash-kv {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 5px 12px;
    margin: 0;
    font-size: 13px;
}

.dash-kv dt {
    font-weight: 400;
    color: var(--flow-ink-soft);
}

.dash-kv dd {
    margin: 0;
    text-align: right;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.dash-bar {
    display: flex;
    height: 8px;
    border-radius: 4px;
    overflow: hidden;
    background: var(--flow-track);
}

.dash-bar.tall {
    height: 12px;
}

.dash-bar span {
    display: block;
    height: 100%;
    transition: width 1s ease;
}

.dash-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin-top: 6px;
    font-size: 12px;
    color: var(--flow-ink-soft);
}

.dash-legend i {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 2px;
    margin-right: 5px;
    vertical-align: -1px;
}

.bg-sun { background: var(--flow-sun); }
.bg-grid { background: var(--flow-grid); }
.bg-export { background: var(--flow-export); }
.bg-house { background: var(--flow-house); }
.bg-car { background: var(--flow-car); }

/* a band of figures: one card, a hairline between the cells, no empty grey where a row ends */
.dash-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    background: var(--flow-card);
    border: 1px solid rgba(0, 0, 0, 0.06);
    border-radius: 6px;
    overflow: hidden;
    margin-bottom: 1.5rem;
}

.dash-tiles .fig {
    padding: 14px 16px;
    box-shadow: inset -1px -1px 0 var(--flow-rule);
}

.dash-card .dash-tiles {
    margin-bottom: 0;
}

.fig .v {
    display: block;
    font-size: 19px;
    font-weight: 600;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

.fig .l {
    display: block;
    font-size: 12.5px;
    color: var(--flow-ink-soft);
}

.c-sun { color: var(--flow-sun); }
.c-grid { color: var(--flow-grid); }
.c-export { color: var(--flow-export); }
.c-batt { color: var(--flow-batt); }
.c-house { color: var(--flow-house); }
.c-car { color: var(--flow-car); }
.c-heat { color: var(--flow-heat); }

/* ── charging now ────────────────────────────────────────────────────── */

.live-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
    gap: 16px;
    margin-bottom: 1.5rem;
}

.live-cards > .card {
    margin-bottom: 0;
}

.live-card {
    display: grid;
    grid-template-columns: 112px minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

@media (max-width: 459.98px) {
    .live-card {
        grid-template-columns: minmax(0, 1fr);
    }
}

.live-card .soc {
    width: 112px;
    height: 112px;
}

.live-card .soc .arc {
    fill: none;
    stroke: var(--flow-good);
    stroke-width: 9;
    stroke-linecap: round;
    animation: live-arc 2.4s ease-in-out infinite;
}

@keyframes live-arc {
    50% {
        opacity: 0.6;
    }
}

.live-card .soc text {
    fill: var(--flow-ink);
    text-anchor: middle;
}

.live-card .car-photo {
    width: 112px;
    height: auto;
    margin-top: 8px;
}

.live-card .figs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 22px;
}

/* ── the three charts, one card with tabs ───────────────────────────── */

.dash-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    border-bottom: 1px solid var(--flow-rule);
    margin-bottom: 12px;
}

.dash-tabs button {
    font: inherit;
    font-size: 13px;
    border: 0;
    background: none;
    color: var(--flow-ink-soft);
    padding: 7px 10px;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.dash-tabs button[aria-selected="true"] {
    color: var(--flow-ink);
    border-bottom-color: var(--flow-house);
    font-weight: 600;
}

.dash-tabs button:focus-visible {
    outline: 2px solid var(--flow-house);
    outline-offset: 2px;
}

.dash-pair {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
    gap: 16px;
    margin-bottom: 1.5rem;
}

.dash-pair > .card {
    margin-bottom: 0;
}

/* the poll ring beside the time of data: a lap is the minute to the next refresh */
.poll-ring {
    width: 22px;
    height: 22px;
    vertical-align: middle;
}

.poll-ring .lap {
    fill: none;
    stroke: var(--flow-house);
    stroke-width: 3;
    stroke-dasharray: 56.5;
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
    animation: poll-lap 60s linear forwards;
}

.poll-ring .base {
    fill: none;
    stroke: var(--flow-track);
    stroke-width: 3;
}

@keyframes poll-lap {
    from {
        stroke-dashoffset: 0;
    }
    to {
        stroke-dashoffset: 56.5;
    }
}

.dash-bar-info {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--flow-ink-soft);
    margin-right: 12px;
}

@media (max-width: 767.98px) {
    .energy-flow-card > .card-body {
        padding: 0.75rem 0.25rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .flow *,
    .dash-chip .dot,
    .live-card .soc .arc,
    .poll-ring .lap {
        animation: none !important;
        transition: none !important;
    }
}
