﻿/* KFC-aligned palette. Brand red drives chrome and single-series data.
   Status stays green/amber/red and is always paired with a number or label,
   never colour alone, so it cannot be confused with the brand red. */
:root {
    --bg: #f5f2f1;
    --surface: #ffffff;
    --surface2: #faf7f6;
    --border: #ece7e5;
    --text: #1a1210;
    --text-2: #3d302c;
    --muted: #7b6e6b;
    /* darkened from #9e918d: the card qualifiers shrank to .72em this round and
       at the old tone they measured 3.05:1 on white, which is thin for a screen
       read from several metres. This lands near 4:1 without becoming a second
       body colour. */
    --muted-2: #8b7d79;
    --brand: #e4002b;
    --brand-soft: #fdecef;
    --icon: #8c2a1e;
    --primary: #e4002b;
    --primary-soft: #fdecef;
    --good: #0e9f6e;
    --good-soft: #e3f7ef;
    --warn: #d97706;
    --warn-soft: #fdf0dd;
    --bad: #d92d20;
    --bad-soft: #fdeae8;
    --accent: #b45309;
    --accent-soft: #fbf0e4;
    --map-dot: #b8adaa;
    /* yesterday's reference line. Deliberately neutral: KFC's system is red,
       black and white, so the comparison line is the black end of it and the
       red is never competed with. */
    --line-yd: #7a6f6c;
    --shadow: 0 6px 24px rgba(26, 18, 16, .07);
    --fs-display: clamp(30px, 2.85vw, 58px);
    --fs-h1: clamp(21px, 1.92vw, 39px);
    --fs-h2: clamp(17px, 1.32vw, 27px);
    --fs-title: clamp(13px, .90vw, 18px);
    --fs-body: clamp(12.5px, .93vw, 19px);
    --fs-num: clamp(12px, .87vw, 17px);
    --fs-label: clamp(10.5px, .71vw, 14px);
    --fs-micro: clamp(9.5px, .64vw, 12.5px);
}
    /* Dark theme on the KFC system: red, black and white. The earlier dark palette
   was built on warm browns, which read as sepia on a large panel and pulled the
   brand red towards orange. These greys are neutral so #e4002b stays red. */
    :root[data-theme="dark"] {
        --bg: #0e0f12;
        --surface: #17181c;
        --surface2: #1f2026;
        --border: #2c2e35;
        --text: #f7f7f9;
        --text-2: #d9dae0;
        --muted: #9b9da6;
        --muted-2: #7b7d86;
        --brand: #ff2a4d;
        --brand-soft: #2c0d15;
        --icon: #ff6076;
        --primary: #ff2a4d;
        --primary-soft: #2c0d15;
        --good: #34d399;
        --good-soft: #0d2e24;
        --warn: #fbbf24;
        --warn-soft: #33260c;
        --bad: #ff5a6e;
        --bad-soft: #35151b;
        --accent: #fb923c;
        --accent-soft: #33210f;
        --map-dot: #3f424b;
        --line-yd: #8b8e97;
        --shadow: 0 6px 24px rgba(0, 0, 0, .55);
    }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg: #0e0f12;
        --surface: #17181c;
        --surface2: #1f2026;
        --border: #2c2e35;
        --text: #f7f7f9;
        --text-2: #d9dae0;
        --muted: #9b9da6;
        --muted-2: #7b7d86;
        --brand: #ff2a4d;
        --brand-soft: #2c0d15;
        --icon: #ff6076;
        --primary: #ff2a4d;
        --primary-soft: #2c0d15;
        --good: #34d399;
        --good-soft: #0d2e24;
        --warn: #fbbf24;
        --warn-soft: #33260c;
        --bad: #ff5a6e;
        --bad-soft: #35151b;
        --accent: #fb923c;
        --accent-soft: #33210f;
        --map-dot: #3f424b;
        --line-yd: #8b8e97;
        --shadow: 0 6px 24px rgba(0, 0, 0, .55);
    }
}

* {
    box-sizing: border-box;
    margin: 0;
}

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

body {
    background: var(--bg);
    color: var(--text);
    font-family: Calibri, "Leelawadee UI", "Segoe UI Variable Text", "Segoe UI", Tahoma, Arial, sans-serif;
    font-variant-numeric: tabular-nums;
    font-synthesis: none;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

.hdr-title, .card h2, .kpi-value, .map-hero .v, .zr-sales, .prod-val {
    font-family: Calibri, "Leelawadee UI", "Segoe UI Variable Display", "Segoe UI", sans-serif;
}

.board {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    gap: clamp(8px, 1.1vh, 16px);
    width: 100vw;
    height: 100vh;
    padding: clamp(12px, 1.1vw, 26px);
}

.hdr {
    display: flex;
    align-items: center;
    gap: clamp(12px, 1.3vw, 26px);
}

.hdr-brand {
    display: flex;
    align-items: center;
    gap: clamp(9px, .8vw, 16px);
}

.hdr-logo {
    width: clamp(38px, 3vw, 62px);
    height: clamp(38px, 3vw, 62px);
    object-fit: contain;
    flex: 0 0 auto;
}

.hdr-rule {
    width: 2px;
    align-self: stretch;
    margin: 2px 0;
    border-radius: 2px;
    background: var(--brand);
}

.hdr-title {
    font-size: clamp(17px, 1.32vw, 26px);
    font-weight: 600;
    letter-spacing: -.01em;
}

.hdr-sub {
    color: var(--muted-2);
    font-size: var(--fs-label);
    font-weight: 500;
    margin-top: 1px;
}

.hdr-spacer {
    flex: 1;
}

.pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: clamp(6px, .55vw, 11px) clamp(11px, .9vw, 18px);
    border-radius: 999px;
    font-weight: 700;
    font-size: var(--fs-label);
    letter-spacing: .02em;
}

.pill-good {
    background: var(--good-soft);
    color: var(--good);
}

.pill-warn {
    background: var(--warn-soft);
    color: var(--warn);
}

.pill-bad {
    background: var(--bad-soft);
    color: var(--bad);
}

.dot {
    width: .6em;
    height: .6em;
    border-radius: 50%;
    background: currentColor;
}

.hdr-meta {
    text-align: right;
    color: var(--muted-2);
    font-size: var(--fs-label);
    font-weight: 500;
    line-height: 1.55;
}

    .hdr-meta strong {
        color: var(--text-2);
        font-weight: 600;
    }

.fresh-ok {
    color: var(--muted-2);
    font-weight: 500;
}

.fresh-stale {
    color: var(--warn);
    font-weight: 600;
}

.ic-svg {
    width: 100%;
    height: 100%;
    display: block;
}

.h-ic {
    display: inline-flex;
    width: 1.22em;
    height: 1.22em;
    vertical-align: -.24em;
    margin-right: .42em;
    color: var(--icon);
}

.kpi-ic svg, .insight .ic svg, .alert-ic svg {
    width: 58%;
    height: 58%;
}

.pager {
    display: flex;
    align-items: center;
    gap: clamp(6px, .5vw, 10px);
}

.pager-dots {
    display: flex;
    align-items: center;
    gap: 7px;
}

.pager-dot {
    width: clamp(8px, .55vw, 11px);
    height: clamp(8px, .55vw, 11px);
    border-radius: 50%;
    background: var(--border);
    transition: all .3s;
    padding: 0;
    border: none;
    cursor: pointer;
}

    .pager-dot.on {
        background: var(--primary);
        width: clamp(20px, 1.4vw, 28px);
        border-radius: 999px;
    }

.pager-btn {
    display: grid;
    place-items: center;
    padding: 0;
    cursor: pointer;
    width: clamp(24px, 1.85vw, 36px);
    height: clamp(24px, 1.85vw, 36px);
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
}

    .pager-btn svg {
        width: 62%;
        height: 62%;
    }

    .pager-btn:hover {
        color: var(--brand);
        border-color: var(--brand);
    }

    .pager-btn:focus-visible, .pager-dot:focus-visible, .tour-btn:focus-visible {
        outline: 3px solid var(--brand);
        outline-offset: 3px;
    }

.card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    padding: clamp(12px, 1vw, 22px);
    border-radius: clamp(14px, 1vw, 20px);
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow);
}

    .card h2 {
        font-size: var(--fs-title);
        font-weight: 550;
        margin-bottom: clamp(6px, .8vh, 12px);
        letter-spacing: -.005em;
    }
        /* the qualifier after the title is reference material, not a heading - it sits
   a clear step below the title in both size and weight */
        .card h2 small {
            color: var(--muted-2);
            font-weight: 400;
            font-size: .72em;
            letter-spacing: 0;
        }

.page {
    display: none;
    min-height: 0;
    height: 100%;
}

    .page.on {
        display: grid;
    }

.p1 {
    grid-template-rows: auto minmax(0, .9fr) minmax(0, 1.1fr);
    gap: clamp(8px, 1.1vh, 16px);
}

.kpis {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: clamp(8px, .8vw, 16px);
}

.kpi-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: clamp(4px, .7vh, 10px);
}

.kpi-ic {
    display: grid;
    place-items: center;
    width: clamp(24px, 1.9vw, 38px);
    height: clamp(24px, 1.9vw, 38px);
    border-radius: 30%;
    flex: 0 0 auto;
}

.ic-primary {
    background: var(--primary-soft);
    color: var(--primary);
}

.ic-good {
    background: var(--good-soft);
    color: var(--good);
}

.ic-warn {
    background: var(--warn-soft);
    color: var(--warn);
}

.ic-accent {
    background: var(--accent-soft);
    color: var(--accent);
}

.kpi-label {
    color: var(--muted);
    font-size: var(--fs-label);
    font-weight: 500;
}
/* period badge + the rule that produced the figure, so nobody has to guess
   whether a number covers today, the month so far, or a projection */
.kpi-tag {
    margin-left: auto;
    flex: 0 0 auto;
    padding: 2px 7px;
    border-radius: 6px;
    background: var(--surface2);
    color: var(--muted);
    letter-spacing: .06em;
    font-size: var(--fs-micro);
    font-weight: 700;
}

.kpi-rule {
    margin-top: clamp(4px, .55vh, 8px);
    padding-top: clamp(4px, .55vh, 8px);
    border-top: 1px dashed var(--border);
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    line-height: 1.35;
}

.kpi-value {
    font-size: var(--fs-h1);
    font-weight: 700;
    letter-spacing: -.022em;
    line-height: 1.08;
    white-space: nowrap;
}

    .kpi-value small {
        font-size: .40em;
        color: var(--muted-2);
        font-weight: 500;
        letter-spacing: 0;
    }

.kpi-hero .kpi-value {
    font-size: var(--fs-display);
    font-weight: 700;
}

.kpi-hero .kpi-label {
    color: var(--text-2);
    font-weight: 600;
}

.kpi-sub {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: clamp(4px, .7vh, 9px);
    font-size: var(--fs-micro);
    color: var(--muted-2);
    font-weight: 500;
    white-space: nowrap;
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2.5px 9px;
    border-radius: 999px;
    font-size: var(--fs-micro);
    font-weight: 700;
}

.chip-good {
    background: var(--good-soft);
    color: var(--good);
}

.chip-warn {
    background: var(--warn-soft);
    color: var(--warn);
}

.chip-bad {
    background: var(--bad-soft);
    color: var(--bad);
}

.p1-mid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
    gap: clamp(8px, .8vw, 16px);
}

.p1-bot {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: clamp(8px, .8vw, 16px);
}

.prog-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-bottom: clamp(8px, 1.2vh, 18px);
}

.prog-stat .v {
    font-size: var(--fs-h2);
    font-weight: 700;
    letter-spacing: -.015em;
}

.prog-stat .l {
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    margin-top: 1px;
}

.prog-track {
    position: relative;
    height: clamp(24px, 3vh, 40px);
    border-radius: 999px;
    background: var(--surface2);
    border: 1px solid var(--border);
    margin-top: auto;
}

.prog-fill {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--primary), #ff6b7f);
}

.prog-marker {
    position: absolute;
    top: -6px;
    bottom: -6px;
    width: 3px;
    border-radius: 2px;
}

    .prog-marker span {
        position: absolute;
        top: -1.6em;
        left: 50%;
        transform: translateX(-50%);
        font-size: var(--fs-micro);
        font-weight: 600;
        white-space: nowrap;
    }

.prog-legend {
    display: flex;
    gap: clamp(10px, 1.2vw, 24px);
    margin-top: clamp(22px, 2.8vh, 32px);
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    flex-wrap: wrap;
}

.lg {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

    .lg i {
        width: 11px;
        height: 11px;
        border-radius: 4px;
        display: inline-block;
    }

.chart-wrap {
    flex: 1;
    min-height: 0;
    position: relative;
}

    .chart-wrap svg {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        overflow: visible;
    }

.chart-legend {
    display: flex;
    gap: clamp(9px, 1vw, 18px);
    margin-bottom: 2px;
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
}

    .chart-legend .lg i {
        width: 15px;
        height: 3px;
        border-radius: 2px;
    }

    .chart-legend .lg.yd i {
        background: var(--line-yd);
    }

.axis-text {
    fill: var(--muted-2);
    font-size: 15px;
    font-weight: 500;
    font-family: inherit;
}

.grid-line {
    stroke: var(--border);
    stroke-width: 1;
}

.chart-note {
    color: var(--muted-2);
    font-size: var(--fs-micro);
    margin-top: 5px;
}

.insights {
    gap: clamp(4px, .65vh, 9px);
    overflow: hidden;
}

.insight {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 11px;
    flex: 1 1 0;
    min-height: 0;
    padding: clamp(6px, .65vh, 10px) clamp(10px, .9vw, 16px);
    border-radius: 14px;
    background: var(--surface2);
}

    .insight .ic {
        display: grid;
        place-items: center;
        width: clamp(26px, 2vw, 40px);
        height: clamp(26px, 2vw, 40px);
        border-radius: 30%;
    }

    .insight .tx {
        font-size: var(--fs-num);
        font-weight: 400;
        line-height: 1.32;
        color: var(--text-2);
    }

        .insight .tx b {
            font-weight: 700;
            color: var(--text);
        }

.p2 {
    grid-template-columns: minmax(0, .92fr) minmax(0, 1.45fr);
    grid-template-rows: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: clamp(8px, .8vw, 16px);
}

    .p2 > .map-card {
        grid-column: 1;
        grid-row: 1 / span 2;
    }

    .p2 > .zones-card {
        grid-column: 2;
        grid-row: 1;
    }

    .p2 > .p2-bot {
        grid-column: 2;
        grid-row: 2;
    }

.map-hero {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: clamp(2px, .4vh, 6px);
}

    .map-hero .v {
        font-size: var(--fs-h2);
        font-weight: 700;
        letter-spacing: -.02em;
        color: var(--text);
    }

    .map-hero .u {
        color: var(--muted-2);
        font-size: var(--fs-micro);
        font-weight: 500;
    }

.map-wrap {
    flex: 1;
    min-height: 0;
    display: grid;
    place-items: center;
}

    .map-wrap svg {
        height: 100%;
        max-width: 100%;
    }

.map-legend {
    display: flex;
    justify-content: center;
    gap: clamp(10px, 1.2vw, 24px);
    flex-wrap: wrap;
    margin-top: clamp(4px, .6vh, 9px);
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
}

    .map-legend .lg i {
        width: 10px;
        height: 10px;
        border-radius: 50%;
    }

.zone-list {
    display: grid;
    grid-auto-rows: minmax(0, 1fr);
    gap: clamp(4px, .6vh, 10px);
    flex: 1;
    min-height: 0;
}

.zone-row {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1.5fr) minmax(0, 1fr) auto auto;
    align-items: center;
    gap: clamp(10px, 1vw, 20px);
    padding: 0 clamp(10px, .9vw, 18px);
    border-radius: 14px;
}

    .zone-row:nth-child(odd) {
        background: var(--surface2);
    }

.zr-rank {
    color: var(--muted-2);
    font-weight: 600;
    font-size: var(--fs-micro);
    width: 1.4em;
}
/* Big enough to recognise a face from across the room - at the old 52px cap the
   coaches were unidentifiable on a 50" screen. */
.avatar {
    display: grid;
    place-items: center;
    width: clamp(38px, 3.9vw, 78px);
    height: clamp(38px, 3.9vw, 78px);
    border-radius: 50%;
    color: #fff;
    font-weight: 700;
    font-size: clamp(13px, 1.2vw, 24px);
    background-size: cover;
    background-position: center;
    border: 3px solid var(--surface);
    box-shadow: 0 3px 12px rgba(26, 18, 16, .18);
}

.zr-name {
    font-size: var(--fs-body);
    font-weight: 600;
    line-height: 1.2;
    color: var(--text-2);
}

.zr-mgr {
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.zr-sales {
    font-size: var(--fs-h2);
    font-weight: 700;
    text-align: right;
    white-space: nowrap;
    letter-spacing: -.015em;
}

    .zr-sales small {
        color: var(--muted-2);
        font-size: .55em;
        font-weight: 500;
        letter-spacing: 0;
    }

.zr-tgt {
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    margin-top: 3px;
}

.bar-track {
    position: relative;
    height: clamp(8px, .95vh, 13px);
    border-radius: 999px;
    background: var(--surface2);
    border: 1px solid var(--border);
    min-width: 0;
}

.zone-row .bar-track {
    background: var(--bg);
}

.bar-fill {
    height: 100%;
    border-radius: 999px;
}

.f-good {
    background: var(--good);
}

.f-warn {
    background: var(--warn);
}

.f-bad {
    background: var(--bad);
}

.pct {
    font-size: var(--fs-num);
    font-weight: 700;
    white-space: nowrap;
}

.t-good {
    color: var(--good);
}

.t-warn {
    color: var(--warn);
}

.t-bad {
    color: var(--bad);
}
/* One bar: today's fill against a notch marking the same point yesterday.
   The notch carries NO white casing. It used to have a 2px ring, which punched
   a hole through the fill on either side of it - on the live board a zone 104%
   UP on yesterday read as behind, because the ring erased the last 7px of red
   and left the notch looking like it sat past the end of the bar. The overhang
   top and bottom is what makes it legible instead. */
.bar-col {
    min-width: 0;
}

.bar-tick {
    position: absolute;
    top: -5px;
    bottom: -5px;
    width: 3px;
    margin-left: -1.5px;
    border-radius: 2px;
    background: var(--text);
}

.yd-note {
    font-size: var(--fs-micro);
    font-weight: 600;
    white-space: nowrap;
}

.p2-bot {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: clamp(8px, .8vw, 16px);
}

.tbl {
    display: grid;
    grid-auto-rows: minmax(0, 1fr);
    flex: 1;
    min-height: 0;
    gap: 4px;
}
/* the name column gets the widest share so long branch names fit on two lines */
.tr {
    display: grid;
    grid-template-columns: auto minmax(0, 2.7fr) minmax(0, 1fr) auto auto;
    align-items: center;
    gap: clamp(8px, .9vw, 16px);
    padding: 0 clamp(8px, .8vw, 14px);
    border-radius: 12px;
}

    .tr:nth-child(odd) {
        background: var(--surface2);
    }

    .tr .rk {
        color: var(--muted-2);
        font-weight: 600;
        font-size: var(--fs-micro);
        width: 1.5em;
    }
    /* names were being cut mid-word behind an ellipsis; wrapping beats losing
   half the branch name on a screen read from metres away. A step below the
   zone names on page 2: these are a list to scan, not the headline. */
    .tr .nm {
        font-size: var(--fs-num);
        font-weight: 600;
        color: var(--text-2);
        overflow: hidden;
        line-height: 1.2;
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
    }

    .tr .amt {
        font-size: var(--fs-num);
        font-weight: 600;
        color: var(--text-2);
        text-align: right;
        white-space: nowrap;
    }

        .tr .amt .yd-note {
            margin-top: 1px;
        }

    .tr .pct {
        min-width: 3.3em;
        text-align: right;
    }

.p3 {
    grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
    gap: clamp(8px, .8vw, 16px);
}
/* two panels share this column; the channel list is the taller of them
   because every row carries a second line of per-bill detail */
.p3-right {
    display: grid;
    grid-template-rows: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: clamp(8px, 1.1vh, 16px);
    min-height: 0;
}
    /* the product tile is sized for a full-width list; in this narrow column the
   full-size thumbnail alone is taller than the row it has to sit in */
    .p3-right .prod-thumb {
        width: clamp(28px, 2.3vw, 46px);
        height: clamp(28px, 2.3vw, 46px);
        border-radius: clamp(8px, .65vw, 12px);
    }

/* menu quadrants - names every bubble, including the unlabelled grey ones.
   They live inside the matrix card, two-up, so the chart keeps its height
   and the reading order is graph first, roster directly beneath it. */
.quads {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(4px, .6vh, 9px);
    flex: 0 0 auto;
    margin-top: clamp(6px, .8vh, 11px);
}

.quad {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 0;
    padding: clamp(5px, .7vh, 10px) clamp(8px, .8vw, 14px);
    border-radius: 12px;
    background: var(--surface2);
}

.quad-head {
    display: flex;
    align-items: center;
    gap: 8px;
}

.quad-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}

.quad-title {
    font-size: var(--fs-label);
    font-weight: 700;
    letter-spacing: .06em;
}

.quad-classic {
    font-size: var(--fs-micro);
    font-weight: 600;
    color: var(--muted-2);
}

.quad-count {
    margin-left: auto;
    font-size: var(--fs-micro);
    font-weight: 700;
    color: var(--muted);
}

.quad-items {
    margin-top: 2px;
    font-size: var(--fs-micro);
    font-weight: 500;
    color: var(--text-2);
    line-height: 1.35;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.quad-empty {
    color: var(--muted-2);
    font-style: italic;
}

.quad-act {
    margin-top: 1px;
    font-size: var(--fs-micro);
    font-weight: 500;
    color: var(--muted-2);
    font-style: italic;
}

/* channel mix */
.channels {
    display: grid;
    grid-auto-rows: minmax(0, 1fr);
    gap: clamp(3px, .45vh, 7px);
    flex: 1;
    min-height: 0;
}

.ch-row {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.5fr) auto auto;
    grid-template-areas: "name bar share amt" "sub sub sub sub";
    align-items: center;
    gap: 3px clamp(7px, .8vw, 14px);
    padding: 0 clamp(6px, .6vw, 12px);
    border-radius: 11px;
}

    .ch-row:nth-child(odd) {
        background: var(--surface2);
    }

.ch-name {
    grid-area: name;
    font-size: var(--fs-num);
    font-weight: 600;
    color: var(--text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ch-row .bar-track {
    grid-area: bar;
}

.f-brand {
    background: linear-gradient(90deg, var(--primary), #ff6b7f);
}

.ch-share {
    grid-area: share;
    font-size: var(--fs-num);
    font-weight: 700;
    color: var(--primary);
}

.ch-amt {
    grid-area: amt;
    font-size: var(--fs-num);
    font-weight: 700;
    white-space: nowrap;
}

    .ch-amt small {
        color: var(--muted-2);
        font-size: .68em;
        font-weight: 500;
    }

.ch-sub {
    grid-area: sub;
    font-size: var(--fs-micro);
    font-weight: 500;
    color: var(--muted-2);
}

.items {
    display: grid;
    grid-auto-rows: minmax(0, 1fr);
    flex: 1;
    min-height: 0;
    gap: clamp(3px, .45vh, 7px);
}

.prod-row {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    align-items: center;
    gap: clamp(9px, .9vw, 18px);
    padding: 0 clamp(6px, .6vw, 12px);
    border-radius: 14px;
    min-height: 0;
}

    .prod-row:nth-child(odd) {
        background: var(--surface2);
    }

.prod-rank {
    color: var(--muted-2);
    font-weight: 600;
    font-size: var(--fs-micro);
    width: 1.5em;
    text-align: center;
}

.prod-thumb {
    display: grid;
    place-items: center;
    overflow: hidden;
    flex: 0 0 auto;
    width: clamp(34px, 3.1vw, 62px);
    height: clamp(34px, 3.1vw, 62px);
    border-radius: clamp(10px, .9vw, 16px);
    background: var(--surface);
    border: 1px solid var(--border);
}

    .prod-thumb img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

    .prod-thumb.is-icon {
        background: var(--brand-soft);
        border-color: transparent;
        color: var(--icon);
    }

        .prod-thumb.is-icon svg {
            width: 52%;
            height: 52%;
        }

.prod-meta {
    min-width: 0;
}

.prod-name {
    font-size: var(--fs-body);
    font-weight: 600;
    color: var(--text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prod-sub {
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prod-right {
    text-align: right;
}

.prod-val {
    font-size: var(--fs-num);
    font-weight: 700;
    white-space: nowrap;
    letter-spacing: -.01em;
}

    .prod-val small {
        color: var(--muted-2);
        font-size: .66em;
        font-weight: 500;
        letter-spacing: 0;
    }

.prod-avg {
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    margin-top: 2px;
    white-space: nowrap;
}

.alerts {
    gap: clamp(6px, .9vh, 12px);
}

.alert {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 11px;
    padding: clamp(8px, 1vh, 14px) clamp(10px, .9vw, 16px);
    border-radius: 14px;
    font-size: var(--fs-num);
    font-weight: 600;
}

.alert-bad {
    background: var(--bad-soft);
    color: var(--bad);
}

.alert-warn {
    background: var(--warn-soft);
    color: var(--warn);
}

.alert-good {
    background: var(--good-soft);
    color: var(--good);
}

.alert time {
    font-size: .8em;
    font-weight: 500;
    opacity: .8;
}

.alert-ic {
    display: grid;
    place-items: center;
    width: clamp(22px, 1.7vw, 34px);
    height: clamp(22px, 1.7vw, 34px);
    flex: 0 0 auto;
}

    .alert-ic svg {
        width: 100%;
        height: 100%;
    }

.ops {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: clamp(6px, .7vw, 12px);
}

.op {
    border-radius: 14px;
    background: var(--surface2);
    padding: clamp(7px, .9vh, 13px);
    text-align: center;
}

    .op .v {
        font-size: var(--fs-h2);
        font-weight: 700;
        letter-spacing: -.015em;
    }

    .op .l {
        color: var(--muted-2);
        font-size: var(--fs-micro);
        font-weight: 500;
        margin-top: 2px;
    }

.empty {
    display: grid;
    place-items: center;
    flex: 1;
    color: var(--muted-2);
    font-size: var(--fs-num);
    font-weight: 500;
}

/* ================= entry motion =================
   Switching a page from display:none to display:grid restarts every CSS
   animation inside it, so each swipe replays the sequence on its own with
   no JavaScript and no timers to drift. Order of arrival tells the story:
   cards settle, then bars grow, then the numbers land.                     */
@keyframes rd-rise {
    from {
        opacity: 0;
        transform: translateY(16px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes rd-fade {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes rd-growx {
    from {
        transform: scaleX(0);
    }

    to {
        transform: scaleX(1);
    }
}

@keyframes rd-growy {
    from {
        transform: scaleY(0);
    }

    to {
        transform: scaleY(1);
    }
}

@keyframes rd-pop {
    from {
        opacity: 0;
        transform: scale(.35);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes rd-draw {
    to {
        stroke-dashoffset: 0;
    }
}

.page.on .card {
    animation: rd-rise .5s cubic-bezier(.22,.8,.3,1) both;
}

.page.on .kpis .card:nth-child(1) {
    animation-delay: .00s
}

.page.on .kpis .card:nth-child(2) {
    animation-delay: .05s
}

.page.on .kpis .card:nth-child(3) {
    animation-delay: .10s
}

.page.on .kpis .card:nth-child(4) {
    animation-delay: .15s
}

.page.on .kpis .card:nth-child(5) {
    animation-delay: .20s
}

.page.on .kpis .card:nth-child(6) {
    animation-delay: .25s
}

.page.on .p1-mid .card:nth-child(2),
.page.on .p1-bot .card:nth-child(2),
.page.on .p2-bot .card:nth-child(2) {
    animation-delay: .10s
}

.page.on .zones-card {
    animation-delay: .08s
}

.page.on .p2-bot {
    animation-delay: .14s
}

/* bars and progress fills sweep out from their baseline */
.bar-fill, .prog-fill {
    transform-origin: left center;
}

.page.on .bar-fill {
    animation: rd-growx .7s .3s cubic-bezier(.22,.8,.3,1) both;
}

.page.on .prog-fill {
    animation: rd-growx .9s .35s cubic-bezier(.22,.8,.3,1) both;
}

.page.on .prog-marker {
    animation: rd-fade .5s .9s both;
}

/* daily bars rise out of the axis, their labels arrive after */
#dailyChart rect {
    transform-box: fill-box;
    transform-origin: bottom;
}

.page.on #dailyChart rect {
    animation: rd-growy .75s .18s cubic-bezier(.22,.8,.3,1) both;
}

.page.on #dailyChart text, .page.on #dailyChart line {
    animation: rd-fade .5s .75s both;
}

/* the hourly line draws itself left to right, area and axis follow */
.page.on #hourlyChart polyline {
    animation: rd-draw 1.05s .12s ease-out both;
}

.page.on #hourlyChart polygon {
    animation: rd-fade .7s .55s both;
}

.page.on #hourlyChart text, .page.on #hourlyChart line {
    animation: rd-fade .5s .6s both;
}

/* map: the country appears, then the zone markers pop in */
.page.on #thMap .th-dots {
    animation: rd-fade .65s both;
}

.page.on #thMap .th-link {
    animation: rd-fade .6s .45s both;
}

.page.on #thMap line {
    animation: rd-fade .5s .55s both;
}

#thMap g {
    transform-box: fill-box;
    transform-origin: center;
}

.page.on #thMap g {
    animation: rd-pop .45s cubic-bezier(.34,1.42,.5,1) both;
}

    .page.on #thMap g:nth-of-type(odd) {
        animation-delay: .5s
    }

    .page.on #thMap g:nth-of-type(even) {
        animation-delay: .58s
    }

/* list rows cascade; --i is set per row when the row is built */
.zone-row, .tr, .prod-row, .insight, .quad {
    --i: 0;
}

.page.on .zone-row, .page.on .tr, .page.on .prod-row, .page.on .insight, .page.on .quad {
    animation: rd-rise .42s cubic-bezier(.22,.8,.3,1) both;
    animation-delay: calc(.26s + var(--i) * .05s);
}
/* the yesterday notch arrives after the fill has finished growing past it,
   so the eye sees the bar overtake the mark rather than start beyond it */
.page.on .bar-tick {
    animation: rd-fade .4s .95s both;
}

/* ---- entry motion for the two restored pages ----
   They arrived carrying none of it: the only rule that reached them was the
   generic .card lift, so the ranked lists, the bars and the two charts simply
   appeared. Everything below reuses the keyframes already defined above, so
   the restored pages now settle in the same order and at the same speed as
   p1/p2/p3 rather than reading as a different product.
   All of it is index-driven off --i, which is set inline per row in the markup;
   swapping a page from display:none to grid restarts the whole sequence, so
   there are no timers to drift. */
.legacy-rank-row, .legacy-item-row, .legacy-zone-store, .legacy-zone-card, .legacy-day-col {
    --i: 0;
}

.page.on .legacy-rank-row, .page.on .legacy-item-row {
    animation: rd-rise .4s cubic-bezier(.22,.8,.3,1) both;
    animation-delay: calc(.24s + var(--i) * .035s);
}
/* the fills sweep out after their row has landed */
.legacy-rank-fill {
    transform-origin: left center;
}

.page.on .legacy-rank-fill {
    animation: rd-growx .65s .42s cubic-bezier(.22,.8,.3,1) both;
}
/* daily bars grow out of the axis, their rotated value labels follow */
.legacy-day-bar {
    transform-origin: bottom center;
}

.page.on .legacy-day-bar {
    animation: rd-growy .6s cubic-bezier(.22,.8,.3,1) both;
    animation-delay: calc(.16s + var(--i) * .022s);
}

    .page.on .legacy-day-bar b, .page.on .legacy-day-col span {
        animation: rd-fade .45s .62s both;
    }
/* the hourly line draws itself, the shaded area arrives once it has */
.page.on .legacy-hour-svg .line {
    animation: rd-draw 1s .15s ease-out both;
}

.page.on .legacy-hour-svg .area {
    animation: rd-fade .6s .5s both;
}

.page.on .legacy-hour-svg .axis, .page.on .legacy-hour-axis {
    animation: rd-fade .5s .1s both;
}
/* the five zone cards deal out left to right, then their store lists fill in */
.page.on .legacy-zone-card {
    animation: rd-rise .5s cubic-bezier(.22,.8,.3,1) both;
    animation-delay: calc(var(--i) * .07s);
}

.page.on .legacy-zone-store {
    animation: rd-fade .34s both;
    animation-delay: calc(.42s + var(--i) * .018s);
}
/* The donut builds itself one wedge at a time, in the same order as the ranked
   list beside it, so the biggest seller is drawn first. The previous version
   masked the whole ring with a six-point clip-path polygon, which sweeps in
   straight chords rather than round an arc and clipped the centre hole with it.
   pathLength="100" makes each share its own dash length, so a single keyframe
   reading var(--len) grows every wedge correctly. */
@keyframes rd-arc {
    from {
        stroke-dasharray: 0 100;
    }

    to {
        stroke-dasharray: var(--len) 100;
    }
}

.page.on .legacy-donut-base {
    animation: rd-fade .4s both;
}

.page.on .legacy-donut-seg {
    animation: rd-arc .42s cubic-bezier(.35,.75,.4,1) both;
    animation-delay: calc(.18s + var(--i) * .055s);
}

.page.on .legacy-donut-copy {
    animation: rd-pop .45s 1.05s cubic-bezier(.34,1.42,.5,1) both;
}

.page.on .legacy-summary-value, .page.on .legacy-head-value {
    animation: rd-rise .5s .1s cubic-bezier(.22,.8,.3,1) both;
}

/* Menu matrix: the grid is laid down first, then the bubbles land biggest to
   smallest. Ordering by revenue means the items that matter arrive first and
   the long tail of grey fills in behind them, which is the reading order. */
@keyframes rd-drop {
    from {
        opacity: 0;
        transform: scale(.25);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

#menuMatrix circle {
    transform-box: fill-box;
    transform-origin: center;
}

.page.on #menuMatrix line {
    animation: rd-fade .5s .06s both;
}

.page.on #menuMatrix circle {
    animation: rd-drop .52s cubic-bezier(.34,1.4,.5,1) both;
    animation-delay: calc(.2s + var(--i) * .05s);
}

.page.on #menuMatrix text {
    animation: rd-fade .55s .7s both;
}

/* ---- the zone markers keep breathing so the eye is drawn to the map ---- */
@keyframes rd-ping {
    0% {
        transform: scale(.5);
        opacity: .55;
    }

    70%, 100% {
        transform: scale(1.85);
        opacity: 0;
    }
}

@keyframes rd-breathe {
    0%, 100% {
        opacity: .14;
    }

    50% {
        opacity: .46;
    }
}

@keyframes rd-corebeat {
    0%, 100% {
        opacity: 1;
    }

    50% {
        opacity: .5;
    }
}

#thMap .th-pulse, #thMap .th-halo {
    transform-box: fill-box;
    transform-origin: center;
}

#thMap .th-pulse {
    animation: rd-ping 2.6s cubic-bezier(.2,.6,.3,1) infinite;
}

#thMap .th-halo {
    animation: rd-breathe 2.6s ease-in-out infinite;
}

#thMap .th-core {
    animation: rd-corebeat 2.6s ease-in-out infinite;
}

/* Motion is on by default: this is a display board, and Windows Server ships
   with system animations switched off, which would silently freeze the whole
   dashboard. Anyone who needs it still can add ?motion=off to the URL. */
body.tour-open .page.on *,
body.motion-off .page.on *, body.motion-off #thMap * {
    animation: none !important;
}

.tour-hole {
    position: fixed;
    z-index: 91;
    border-radius: 20px;
    pointer-events: none;
    box-shadow: 0 0 0 9999px rgba(16, 10, 9, .68), 0 0 0 3px var(--brand);
    transition: top .3s cubic-bezier(.4,0,.2,1), left .3s cubic-bezier(.4,0,.2,1), width .3s cubic-bezier(.4,0,.2,1), height .3s cubic-bezier(.4,0,.2,1);
}

.tour-tip {
    position: fixed;
    z-index: 93;
    width: min(34vw, 520px);
    padding: clamp(14px, 1.1vw, 24px) clamp(16px, 1.25vw, 28px);
    border-radius: 20px;
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: 0 22px 60px rgba(16, 10, 9, .3);
    transition: top .3s cubic-bezier(.4,0,.2,1), left .3s cubic-bezier(.4,0,.2,1);
}

.tour-step {
    color: var(--brand);
    font-size: var(--fs-micro);
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
}

.tour-title {
    font-size: clamp(15px, 1.2vw, 24px);
    font-weight: 700;
    margin: 4px 0 6px;
    letter-spacing: -.01em;
}

.tour-desc {
    font-size: var(--fs-num);
    font-weight: 450;
    color: var(--text-2);
    line-height: 1.55;
}

.tour-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: clamp(10px, .9vw, 18px);
}

.tour-hint {
    flex: 1;
    color: var(--muted-2);
    font-size: var(--fs-micro);
    font-weight: 500;
    line-height: 1.4;
}

.tour-btn {
    padding: clamp(7px, .55vw, 12px) clamp(13px, 1vw, 22px);
    border-radius: 999px;
    font-size: var(--fs-label);
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
}

    .tour-btn.primary {
        background: var(--brand);
        border-color: var(--brand);
        color: #fff;
        font-weight: 700;
    }

/* Restored TV pages. These use the current dashboard tokens and typography;
   the existing p1/p2/p3 rules below are intentionally untouched. */
.legacy-overview {
    /* the two mini charts were squeezed into 180px while the rows underneath had
       space to spare, so the band takes a little more and the item card a little
       less - the item grid was already close to full */
    grid-template-rows: clamp(150px, 19vh, 208px) minmax(0, 1fr) minmax(0, .88fr);
    gap: clamp(8px, 1.1vh, 16px);
}

.legacy-summary {
    display: grid;
    grid-template-columns: 1.35fr 1fr 1fr;
    gap: clamp(8px, .8vw, 16px);
}

    .legacy-summary .card {
        justify-content: center;
        padding-block: clamp(10px, 1.1vh, 18px);
    }

.legacy-summary-label {
    color: var(--muted);
    font-size: var(--fs-label);
    font-weight: 500;
}

/* Type on the two restored pages, rebalanced. The headline totals were set
   larger than the hero figure on p1 while carrying twelve digits and two
   decimals, so they filled their card and still could not be read at a glance;
   the ranked lists underneath were the reverse - the numbers people actually
   scan sat at 11-14px, which is below what a 50" panel resolves at 3-5 m.
   Headlines come down a step, every list goes up one. */
.legacy-summary-value {
    margin-top: 2px;
    font-family: Calibri, "Leelawadee UI", "Segoe UI Variable Display", "Segoe UI", sans-serif;
    font-size: clamp(22px, 1.85vw, 38px);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.025em;
}

    .legacy-summary-value small {
        font-size: .38em;
        color: var(--muted);
        font-weight: 500;
    }

.legacy-summary-sub {
    margin-top: 5px;
    color: var(--muted-2);
    font-size: var(--fs-micro);
}

.legacy-store-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(8px, .8vw, 16px);
    min-height: 0;
}

.legacy-rank-list {
    display: grid;
    gap: clamp(2px, .35vh, 5px);
    min-height: 0;
}

.legacy-rank-row {
    display: grid;
    grid-template-columns: 24px minmax(145px, 1.2fr) minmax(90px, .75fr) 66px 96px 108px;
    align-items: center;
    gap: clamp(5px, .55vw, 11px);
    min-height: 0;
    /* the ten rows were leaving 92px empty at the bottom of a 407px card */
    min-height: clamp(22px, 2.55vh, 32px);
    padding: 2px 6px;
    border-radius: 9px;
    font-size: clamp(11px, .84vw, 16.5px);
}

    .legacy-rank-row:nth-child(odd) {
        background: var(--surface2);
    }

.legacy-rank-no {
    color: var(--muted-2);
    text-align: center;
    font-weight: 600;
}

.legacy-rank-name {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 550;
}

.legacy-rank-track {
    height: 7px;
    background: var(--track);
    border-radius: 99px;
    overflow: hidden;
}

.legacy-rank-fill {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--primary);
}

    .legacy-rank-fill.low {
        background: var(--bad);
    }

.legacy-rank-pct {
    text-align: right;
    font-weight: 650;
    color: var(--text);
}

    .legacy-rank-pct.low {
        color: var(--text);
    }

.legacy-rank-amount {
    text-align: right;
    font-weight: 650;
    white-space: nowrap;
}

.legacy-rank-target {
    color: var(--muted-2);
    text-align: right;
    font-weight: 500;
    white-space: nowrap;
}

.legacy-items-card {
    display: grid;
    grid-template-columns: minmax(190px, .58fr) minmax(0, 2.42fr);
    gap: clamp(12px, 1.4vw, 26px);
}

.legacy-donut-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(6px, 1vh, 14px);
    min-height: 0;
}

.legacy-donut-figure {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 0;
}
/* was min(17vh, 165px), which left the ring floating in a 314x326 column with
   roughly half of it empty - measured on the live board, not guessed */
.legacy-donut {
    width: min(25vh, 235px);
    aspect-ratio: 1;
}

.legacy-donut-base {
    stroke: var(--surface2);
}

.legacy-donut-seg {
    stroke-dasharray: var(--len) 100;
}
/* sits in the hole; the ring is stroked at 17 of a 100 unit box, so the clear
   circle is 53 units across and the figure below is sized to stay inside it */
.legacy-donut-copy {
    position: absolute;
    inset: 0;
    display: grid;
    place-content: center;
    text-align: center;
    pointer-events: none;
}

    .legacy-donut-copy b {
        display: block;
        font-size: clamp(19px, 1.5vw, 30px);
        line-height: 1.05;
        letter-spacing: -.02em;
    }

    .legacy-donut-copy span {
        color: var(--muted-2);
        font-size: var(--fs-micro);
        font-weight: 600;
    }

.legacy-item-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-flow: column;
    grid-template-rows: repeat(10, minmax(0, 1fr));
    gap: 2px clamp(14px, 1.5vw, 30px);
    min-height: 0;
}

.legacy-item-row {
    display: grid;
    grid-template-columns: 20px 10px minmax(0, 1fr) 78px 96px;
    align-items: center;
    gap: 7px;
    font-size: clamp(10px, .76vw, 14.5px);
}

.legacy-item-no {
    color: var(--muted-2);
    text-align: right;
}

.legacy-item-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.legacy-item-name {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 550;
}

    .legacy-item-name small {
        color: var(--muted-2);
        font-weight: 400;
    }

.legacy-item-qty {
    text-align: right;
    color: var(--text);
    font-weight: 650;
    white-space: nowrap;
}

.legacy-item-amt {
    text-align: right;
    font-weight: 650;
    white-space: nowrap;
}

.legacy-zones {
    min-height: 0;
    /* same band height as the overview page, so the two read as one pair when
       the board rotates between them */
    grid-template-rows: clamp(150px, 19vh, 208px) minmax(0, 1fr);
    gap: clamp(8px, 1.1vh, 16px);
}

.legacy-top-band {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(8px, .8vw, 16px);
    min-height: 0;
}

.legacy-top-panel {
    display: grid;
    grid-template-columns: minmax(260px, .86fr) minmax(0, 1.14fr);
    align-items: center;
    gap: clamp(12px, 1.2vw, 24px);
    padding: clamp(10px, .85vw, 18px);
    overflow: hidden;
}

    .legacy-top-panel.hourly {
        grid-template-columns: minmax(0, 1.35fr) minmax(280px, .72fr);
    }

.legacy-head-kpi {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
}

    .legacy-head-kpi.today {
        text-align: right;
        align-items: flex-end;
    }

.legacy-head-title {
    color: var(--muted);
    font-size: var(--fs-label);
    font-weight: 550;
}

.legacy-head-value {
    margin-top: 5px;
    max-width: 100%;
    color: var(--text);
    font-family: Calibri, "Leelawadee UI", "Segoe UI", sans-serif;
    font-size: clamp(21px, 1.42vw, 31px);
    line-height: 1;
    font-weight: 700;
    letter-spacing: -.015em;
    white-space: nowrap;
}

    .legacy-head-value small {
        color: var(--muted);
        font-size: .38em;
        font-weight: 500;
    }

.legacy-head-meta {
    margin-top: 6px;
    color: var(--muted-2);
    font-size: clamp(9px, .63vw, 12px);
    line-height: 1.4;
}

.legacy-mini-chart {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
    min-height: 0;
    height: 100%;
    overflow: hidden;
}

.legacy-mini-chart-title {
    color: var(--muted);
    font-size: var(--fs-label);
    font-weight: 600;
    margin-bottom: 4px;
}

.legacy-daily-bars {
    display: grid;
    grid-template-columns: repeat(15, minmax(5px, 1fr));
    align-items: end;
    gap: clamp(2px, .22vw, 5px);
    flex: 1;
    min-height: 0;
    padding-top: 15px;
    border-bottom: 1px solid var(--border);
}

.legacy-day-col {
    display: grid;
    grid-template-rows: 1fr 14px;
    align-items: end;
    height: 100%;
    min-width: 0;
}

.legacy-day-bar {
    position: relative;
    display: block;
    width: 72%;
    justify-self: center;
    min-height: 2px;
    border-radius: 4px 4px 0 0;
    background: linear-gradient(180deg, var(--accent), var(--primary));
}

    .legacy-day-bar b {
        position: absolute;
        top: -13px;
        left: 50%;
        transform: translateX(-50%) rotate(-35deg);
        transform-origin: center;
        color: var(--text);
        font-size: clamp(7px, .47vw, 9.5px);
        font-style: normal;
        font-weight: 650;
        line-height: 1;
        white-space: nowrap;
    }

.legacy-day-col span {
    color: var(--muted-2);
    text-align: center;
    font-size: clamp(8px, .53vw, 10.5px);
}

.legacy-hour-svg {
    width: 100%;
    height: 100%;
    min-height: 70px;
    overflow: visible;
}

    .legacy-hour-svg .axis {
        stroke: var(--border);
        stroke-width: 1;
    }

    .legacy-hour-svg .area {
        fill: var(--primary-soft);
        opacity: .75;
    }

    .legacy-hour-svg .line {
        fill: none;
        stroke: var(--primary);
        stroke-width: 3;
        stroke-linecap: round;
        stroke-linejoin: round;
        /* pathLength="100" on the polyline gives every chart the same
           animation distance, regardless of how many hourly points it has. */
        stroke-dasharray: 100;
        stroke-dashoffset: 100;
    }

.legacy-hour-axis {
    display: flex;
    justify-content: space-between;
    color: var(--muted-2);
    font-size: clamp(8px, .55vw, 11px);
    margin-top: -2px;
}

.legacy-zone-grid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: clamp(7px, .65vw, 13px);
    min-height: 0;
    height: 100%;
}

.legacy-zone-card {
    border-top: 3px solid var(--primary);
    overflow: hidden;
    padding: clamp(9px, .72vw, 15px);
}

.legacy-zone-head {
    display: grid;
    grid-template-columns: 22px 38px minmax(0, 1fr);
    gap: 7px;
    align-items: center;
}

.legacy-zone-rank {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 7px;
    background: var(--surface2);
    color: var(--muted);
    font-size: clamp(9px, .63vw, 12px);
    font-weight: 700;
}

.legacy-zone-photo {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    object-fit: cover;
    object-position: center top;
    border: 2px solid var(--surface);
    box-shadow: 0 0 0 1px var(--border);
}

.legacy-zone-name {
    font-size: clamp(12px, .9vw, 18px);
    font-weight: 650;
    line-height: 1.05;
}

.legacy-zone-owner {
    color: var(--muted-2);
    font-size: clamp(9px, .62vw, 12px);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.legacy-zone-sales {
    margin-top: 8px;
    font-size: clamp(17px, 1.24vw, 26px);
    font-weight: 700;
    line-height: 1;
}

    .legacy-zone-sales small {
        font-size: .42em;
        color: var(--muted);
        font-weight: 500;
    }

.legacy-zone-target {
    margin-top: 4px;
    color: var(--muted-2);
    font-size: clamp(9px, .6vw, 11.5px);
}

.legacy-zone-progress {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 6px;
    align-items: center;
    margin: 7px 0 8px;
}

    .legacy-zone-progress .legacy-rank-track {
        height: 8px;
    }

    .legacy-zone-progress b {
        font-size: clamp(9px, .64vw, 12px);
        color: var(--text);
    }

.legacy-zone-section {
    border-top: 1px solid var(--border);
    padding-top: 6px;
    margin-top: 5px;
    min-height: 0;
}

    .legacy-zone-section h3 {
        color: var(--primary);
        font-size: clamp(11px, .78vw, 15px);
        font-weight: 650;
        margin-bottom: 4px;
    }

    .legacy-zone-section.low h3 {
        color: var(--bad);
    }
/* These 100 rows were the least readable thing on the board at 10-11px, and the
   cards still had 183px of unused height below them after the first increase -
   measured on the live render, not guessed. The row height goes up with the
   type so the list uses that space instead of leaving it blank underneath. */
.legacy-zone-store {
    display: grid;
    grid-template-columns: 18px minmax(0, 1fr) 66px;
    gap: 6px;
    align-items: center;
    min-height: 24px;
    font-size: clamp(10.5px, .81vw, 15.5px);
}
/* The sizes above are set for the 1080p panel this board lives on. clamp() only
   tracks width, so on a short window - a laptop at 1600x900, say - the twenty
   store rows and the item grid overrun their cards by a few pixels. Measured, so
   this trims exactly the two things that overflow and nothing else. */
@media (max-height: 950px) {
    .legacy-zone-store {
        min-height: 17px;
        font-size: clamp(9px, .66vw, 12.5px);
    }

    .legacy-zone-section h3 {
        font-size: clamp(10px, .7vw, 13px);
    }

    .legacy-item-row {
        font-size: clamp(9px, .7vw, 13px);
    }
}

.legacy-zone-store span:nth-child(1) {
    color: var(--muted-2);
    text-align: right;
}

.legacy-zone-store span:nth-child(2) {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.legacy-zone-store strong {
    text-align: right;
    font-weight: 650;
    white-space: nowrap;
}

/* Responsive layout -------------------------------------------------------
   The wallboard layout above intentionally fills one fixed screen. On smaller
   devices the active page becomes a normal scrolling document and dense grids
   progressively collapse, while desktop/TV sizing remains unchanged. */
@media (max-width: 1200px) {
    :root {
        --fs-display: clamp(28px, 5vw, 48px);
        --fs-h1: clamp(21px, 3.2vw, 34px);
        --fs-h2: clamp(17px, 2.4vw, 25px);
        --fs-title: clamp(14px, 1.8vw, 18px);
        --fs-body: clamp(13px, 1.65vw, 17px);
        --fs-num: clamp(12px, 1.55vw, 16px);
        --fs-label: clamp(11px, 1.35vw, 14px);
        --fs-micro: clamp(10px, 1.2vw, 12.5px);
    }

    html, body {
        height: auto;
        min-height: 100%;
        overflow-x: hidden;
        overflow-y: auto;
    }

    .board {
        width: 100%;
        height: auto;
        min-height: 100vh;
        padding: clamp(10px, 2vw, 20px);
    }

    .hdr {
        flex-wrap: wrap;
    }

    .hdr-spacer {
        display: none;
    }

    .hdr-meta {
        margin-left: auto;
    }

    .page,
    .page.on {
        height: auto;
        min-height: 0;
    }

    .p1,
    .p2,
    .p3,
    .legacy-overview,
    .legacy-zones {
        grid-template-rows: none;
    }

    .kpis {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .p1-mid,
    .p1-bot,
    .p2,
    .p3,
    .p2-bot,
    .legacy-store-grid,
    .legacy-items-card,
    .legacy-top-band {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .p2 > .map-card,
    .p2 > .zones-card,
    .p2 > .p2-bot {
        grid-column: auto;
        grid-row: auto;
    }

    .p2 > .map-card,
    .p2 > .p2-bot {
        grid-column: 1 / -1;
    }

    .chart-wrap {
        min-height: 260px;
    }

    .map-wrap {
        min-height: 420px;
    }

    .zone-list,
    .tbl,
    .channels,
    .items {
        grid-auto-rows: minmax(58px, auto);
    }

    .legacy-zone-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        height: auto;
    }

    .legacy-zone-store {
        min-height: 24px;
        font-size: clamp(10px, 1.2vw, 14px);
    }

    .legacy-mini-chart,
    .legacy-donut-wrap {
        min-height: 260px;
    }
}

/* Tablet portrait: two outer columns leave too little room for the nested
   KPI/chart columns and for the regional cards. Give each major panel a full
   row; the content inside a top panel can still use its balanced two columns. */
@media (max-width: 900px) {
    .legacy-top-band {
        grid-template-columns: minmax(0, 1fr);
    }

    .legacy-store-grid,
    .legacy-items-card {
        grid-template-columns: minmax(0, 1fr);
    }

    .legacy-rank-row {
        grid-template-columns: 24px minmax(0, 1.5fr) minmax(80px, .8fr) 58px 88px 100px;
        gap: 7px;
    }

    .legacy-rank-name {
        white-space: normal;
        line-height: 1.15;
    }

    .legacy-donut-wrap {
        min-height: 250px;
    }

    .legacy-item-list {
        width: 100%;
    }

    .legacy-item-row {
        grid-template-columns: 20px 10px minmax(0, 1fr) 68px 88px;
        gap: 6px;
    }

    .legacy-top-panel,
    .legacy-top-panel.hourly {
        grid-template-columns: minmax(230px, .9fr) minmax(0, 1.1fr);
        min-height: 250px;
    }

    .p2 {
        grid-template-columns: minmax(0, 1fr);
    }

    .p2 > .map-card,
    .p2 > .zones-card,
    .p2 > .p2-bot {
        grid-column: 1;
        grid-row: auto;
    }

    .p2-bot {
        grid-template-columns: minmax(0, 1fr);
    }

    .zones-card,
    .p2-bot > .card {
        width: 100%;
    }
}

@media (max-width: 760px) {
    .board {
        gap: 12px;
        padding: 10px;
    }

    .hdr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 10px;
    }

    .hdr-brand {
        grid-column: 1 / -1;
        min-width: 0;
    }

    .hdr-title {
        font-size: 18px;
    }

    .hdr-sub {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .pill {
        grid-column: 1 / -1;
        justify-content: center;
    }

    .hdr-meta {
        grid-column: 1;
        margin-left: 0;
        text-align: left;
    }

    .pager {
        grid-column: 2;
        margin-left: auto;
    }

    .card {
        padding: 14px;
        border-radius: 14px;
    }

    .tour-tip {
        display: flex;
        flex-direction: column;
        width: min(360px, calc(100vw - 24px));
        max-height: min(78dvh, 560px);
        padding: 16px;
        border-radius: 16px;
        overflow: hidden;
    }

    .tour-desc {
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding-right: 3px;
    }

    .tour-actions {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto auto;
        align-items: end;
        gap: 8px;
        flex: 0 0 auto;
        padding-top: 12px;
        margin-top: 0;
        background: var(--surface);
    }

    .tour-hint {
        min-width: 0;
        line-height: 1.35;
    }

    .tour-btn {
        white-space: nowrap;
    }

    .kpis,
    .p1-mid,
    .p1-bot,
    .p2,
    .p3,
    .p2-bot,
    .legacy-store-grid,
    .legacy-items-card,
    .legacy-top-band,
    .legacy-zone-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .p2 > .map-card,
    .p2 > .zones-card,
    .p2 > .p2-bot {
        grid-column: auto;
    }

    .legacy-overview,
    .legacy-zones {
        grid-template-rows: auto;
    }

    .legacy-top-panel,
    .legacy-top-panel.hourly {
        grid-template-columns: minmax(0, 1fr);
        gap: 14px;
        overflow: visible;
    }

    .legacy-top-panel.hourly .legacy-head-kpi {
        order: -1;
    }

    .legacy-head-kpi.today {
        align-items: flex-start;
        text-align: left;
    }

    .legacy-head-value {
        font-size: clamp(24px, 7vw, 32px);
        white-space: normal;
    }

    .legacy-mini-chart {
        min-height: 190px;
    }

    .legacy-daily-bars {
        min-height: 150px;
    }

    .legacy-hour-svg {
        height: 150px;
        min-height: 150px;
    }

    .chart-wrap {
        min-height: 230px;
    }

    .map-wrap {
        min-height: 340px;
    }

    .zone-row {
        grid-template-columns: auto auto minmax(0, 1fr) auto;
        gap: 8px;
        padding: 9px;
    }

    .zone-row .bar-col {
        grid-column: 3 / -1;
    }

    .zone-row .yd-note {
        grid-column: 3;
    }

    .tr {
        grid-template-columns: auto minmax(0, 1fr) auto;
        padding: 8px;
    }

    .tr .bar-col {
        grid-column: 2 / -1;
    }

    .legacy-rank-row {
        grid-template-columns: 22px minmax(0, 1fr) auto;
        grid-template-areas:
            "rank name amount"
            ". track track"
            ". pct target";
        row-gap: 5px;
        min-height: 64px;
        padding: 7px 6px;
    }

    .legacy-rank-no { grid-area: rank; }
    .legacy-rank-name { grid-area: name; }
    .legacy-rank-track { grid-area: track; }
    .legacy-rank-pct { grid-area: pct; text-align: left; }
    .legacy-rank-amount { grid-area: amount; }
    .legacy-rank-target { grid-area: target; }

    .legacy-rank-row .legacy-rank-amount {
        font-size: 12px;
    }

    .legacy-item-row {
        grid-template-columns: 20px 8px minmax(0, 1fr) auto;
    }

    .legacy-item-row .legacy-item-amt {
        grid-column: 3 / -1;
        text-align: right;
    }
}

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

    .hdr-meta {
        flex-basis: 100%;
    }

    .prog-stats,
    .ops,
    .quads {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ch-row {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: "name share" "bar bar" "sub amt";
        padding: 8px;
    }

    .tour-actions {
        grid-template-columns: 1fr 1fr;
    }

    .tour-hint {
        grid-column: 1 / -1;
    }

    .tour-btn {
        width: 100%;
    }
}
