#!/usr/bin/env bash
#
# ▌ benchmark — a modern VPS benchmark
# ▌
# ▌ System info · CPU · Memory · Disk · Network — zero dependencies, one file.
# ▌ Inspired by yabs.sh (Mason Rowe) and bench.sh (Teddysun).
#
# Usage:
#   curl -sL benchmarki.ng | bash
#   ./benchmark.sh [flags]
#
# Flags:
#   -q            quick mode (shorter tests)
#   -c            skip CPU benchmark
#   -d            skip disk benchmark
#   -n            skip network tests
#   -r            reduce global network test to 3 regions
#   -g            skip the Geekbench test
#   -j            print JSON results at the end
#   -w <file>     write JSON results to file
#   -h            show help
#   --no-color    disable colors (also respects NO_COLOR env)
#   --no-tui      disable motion (spinners, animations, live HUD)
#   --ascii       plain ASCII glyphs

# Everything below is bash — arrays, [[ ]], local. If we were started by sh,
# dash or ksh, hand over to bash rather than failing one line at a time.
# Keep this block POSIX-clean: it has to parse in whatever shell got here.
if [ -z "${BASH_VERSION-}" ]; then
    if command -v bash >/dev/null 2>&1; then
        case "$0" in
            sh | dash | ksh | zsh | busybox | -* | */sh | */dash | */ksh | */zsh)
                : ;; # piped into a shell — there is no file to re-exec
            *)
                [ -r "$0" ] && exec bash "$0" "$@" ;;
        esac
    fi
    echo "benchmark: this script requires bash (you are running $0)." >&2
    echo "  curl -sL benchmarki.ng | bash" >&2
    echo "  wget -qO- benchmarki.ng | bash" >&2
    exit 1
fi

set -u

BENCHMARK_VERSION="1.0.0"
START_TIME=$(date +%s)

# ───────────────────────────── terminal & colors ─────────────────────────────

TERM_WIDTH=$( (command -v tput >/dev/null 2>&1 && tput cols) 2>/dev/null || echo 80)
[[ -z "$TERM_WIDTH" || "$TERM_WIDTH" -lt 60 ]] && TERM_WIDTH=80
[[ "$TERM_WIDTH" -gt 100 ]] && TERM_WIDTH=100
BOX_W=$((TERM_WIDTH - 2))

# --no-color kills colors only; --no-tui kills motion (spinners, animated
# meters, the HUD, in-place redraws) only. Non-tty output disables both.
USE_COLOR=true
USE_TUI=true
TRUECOLOR=false
[[ -n "${NO_COLOR:-}" ]] && USE_COLOR=false
[[ ! -t 1 ]] && USE_COLOR=false && USE_TUI=false
[[ "${COLORTERM:-}" == *truecolor* || "${COLORTERM:-}" == *24bit* ]] && TRUECOLOR=true

# remember the launch locale before we force LC_ALL=C for parsing — it decides
# whether the terminal can be trusted with non-ASCII glyphs
ORIG_LOCALE="${LC_ALL:-${LC_CTYPE:-${LANG:-}}}"
FORCE_ASCII=false

for arg in "$@"; do
    case "$arg" in
        --no-color) USE_COLOR=false ;;
        --no-tui) USE_TUI=false ;;
        --ascii) FORCE_ASCII=true ;;
    esac
done

# glyph set: unicode on UTF-8 terminals, pure ASCII otherwise (or via --ascii)
if $FORCE_ASCII || [[ "$ORIG_LOCALE" != *[Uu][Tt][Ff]* ]]; then
    G_BAR="|" G_RULE="-" G_FILL="#" G_EMPTY="-"
    G_OK="+" G_BAD="x" G_DOT="*" G_DN="v" G_UP="^"
    G_SEP="-" G_ARR="->" G_PM="+-" G_X="x" G_MD="-" G_CLK=""
    SPARK_CHARS=("_" "." ":" "-" "=" "+" "*" "#")
    SPIN_FRAMES=("|" "/" "-" "\\")
else
    G_BAR="▍" G_RULE="─" G_FILL="━" G_EMPTY="╌"
    G_OK="✓" G_BAD="✗" G_DOT="●" G_DN="↓" G_UP="↑"
    G_SEP="·" G_ARR="→" G_PM="±" G_X="×" G_MD="—" G_CLK="⏱"
    SPARK_CHARS=("▁" "▂" "▃" "▄" "▅" "▆" "▇" "█")
    SPIN_FRAMES=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏")
fi

c() { # c <r> <g> <b> <fallback-256>
    if ! $USE_COLOR; then return; fi
    if $TRUECOLOR; then
        printf '\033[38;2;%d;%d;%dm' "$1" "$2" "$3"
    else
        printf '\033[38;5;%dm' "$4"
    fi
}

if $USE_COLOR; then
    RST=$'\033[0m'; BOLD=$'\033[1m'; DIM=$'\033[2m'
else
    RST=""; BOLD=""; DIM=""
fi

# palette
C_ACCENT=$(c 129 140 248 105)   # indigo
C_ACCENT2=$(c 192 132 252 141)  # purple
C_OK=$(c 52 211 153 42)         # emerald
C_WARN=$(c 251 191 36 214)      # amber
C_BAD=$(c 248 113 113 203)      # red
C_INFO=$(c 96 165 250 75)       # blue
C_MUTE=$(c 113 113 122 244)     # zinc
C_TEXT=$(c 228 228 231 253)     # near-white
C_CYAN=$(c 34 211 238 51)       # cyan

# ─────────────────────────────── ui primitives ───────────────────────────────

repeat_char() { local out="" i; for ((i = 0; i < $2; i++)); do out+="$1"; done; printf '%s' "$out"; }

hr() { printf '%s%s%s\n' "$C_MUTE" "$(repeat_char "$G_EMPTY" "$TERM_WIDTH")" "$RST"; }

# gradient horizontal rule (indigo → purple → pink)
grad_hr() {
    if ! $USE_COLOR || ! $TRUECOLOR; then
        printf '%s%s%s\n' "$C_ACCENT" "$(repeat_char "$G_RULE" "$TERM_WIDTH")" "$RST"
        return
    fi
    local i r g b n=$TERM_WIDTH
    for ((i = 0; i < n; i++)); do
        r=$((129 + (244 - 129) * i / n))
        g=$((140 - (140 - 114) * i / n))
        b=$((248 - (248 - 182) * i / n))
        printf '\033[38;2;%d;%d;%dm%s' "$r" "$g" "$b" "$G_RULE"
    done
    printf '%s\n' "$RST"
}

set_title() { # set terminal tab title
    $USE_TUI && printf '\033]0;%s\007' "$1"
    return 0
}

SECTION_NUM=0
STEP_TOTAL=0
section() { # section <title> [subtitle] — left-accent header with step/elapsed
    local title=$1 subtitle=${2:-}
    set_title "benchmark · $title"
    local right=""
    if [[ "$title" != "Summary" && "$STEP_TOTAL" -gt 0 ]]; then
        SECTION_NUM=$((SECTION_NUM + 1))
        local n=$SECTION_NUM el
        ((n > STEP_TOTAL)) && n=$STEP_TOTAL
        el=$(($(date +%s) - START_TIME))
        right=$(printf '%d/%d %s %d:%02d' "$n" "$STEP_TOTAL" "$G_SEP" $((el / 60)) $((el % 60)))
    fi
    local left_len=$((4 + ${#title}))
    [[ -n "$subtitle" ]] && left_len=$((left_len + 3 + ${#subtitle}))
    local pad=$((TERM_WIDTH - left_len - ${#right} - 2))
    ((pad < 1)) && pad=1
    printf '\n  %s%s%s %s%s%s' "$C_ACCENT" "$G_BAR" "$RST" "$BOLD$C_TEXT" "$title" "$RST"
    [[ -n "$subtitle" ]] && printf ' %s%s %s%s' "$DIM" "$G_SEP" "$subtitle" "$RST"
    printf '%*s%s%s%s\n' "$pad" "" "$C_MUTE$DIM" "$right" "$RST"
}

row() { # row <label> <value>  — aligned key/value line
    printf '  %s%-22s%s %s\n' "$C_MUTE" "$1" "$RST" "$2"
}

ok()   { printf '%s%s%s' "$C_OK" "$G_OK" "$RST"; }
bad()  { printf '%s%s%s' "$C_BAD" "$G_BAD" "$RST"; }

# meter <value> <max> <width> — colored bar, green→amber→red by fill is inverted
# for latency (lower better) callers pass pre-picked color
meter() { # meter <fraction 0-100> <width> <color>
    local pct=$1 width=$2 color=$3
    ((pct > 100)) && pct=100
    ((pct < 0)) && pct=0
    local filled=$((pct * width / 100))
    printf '%s%s%s%s%s' "$color" "$(repeat_char "$G_FILL" "$filled")" \
        "$C_MUTE$DIM" "$(repeat_char "$G_EMPTY" $((width - filled)))" "$RST"
}

spark() { # spark <v1> <v2> ... → sparkline scaled to min..max
    local vals=("$@") min max v out="" idx
    [[ ${#vals[@]} -eq 0 ]] && return
    min=${vals[0]} max=${vals[0]}
    for v in "${vals[@]}"; do
        awk -v a="$v" -v b="$min" 'BEGIN {exit !(a<b)}' && min=$v
        awk -v a="$v" -v b="$max" 'BEGIN {exit !(a>b)}' && max=$v
    done
    for v in "${vals[@]}"; do
        idx=$(awk -v v="$v" -v mn="$min" -v mx="$max" \
            'BEGIN {r=mx-mn; if (r<=0) print 4; else printf "%d", (v-mn)/r*7+0.5}')
        out+="${SPARK_CHARS[$idx]}"
    done
    printf '%s' "$out"
}

# determinate progress bar, redrawn in place; call pbar_done when finished
pbar() { # pbar <pct 0-100> <message>
    $USE_TUI || return 0
    local pct=$1 msg=$2 width=26 filled
    ((pct > 100)) && pct=100
    ((pct < 0)) && pct=0
    filled=$((pct * width / 100))
    printf '\r\033[2K  %s%s%s%s%s %s%3d%%%s  %s%s%s' \
        "$C_ACCENT" "$(repeat_char "$G_FILL" "$filled")" \
        "$C_MUTE$DIM" "$(repeat_char "$G_EMPTY" $((width - filled)))" "$RST" \
        "$C_TEXT$BOLD" "$pct" "$RST" "$DIM" "$msg" "$RST"
}
pbar_done() { $USE_TUI && printf '\r\033[2K' || true; }

# ─────────────────────────── live system HUD ─────────────────────────────────
# Pins a two-row dashboard to the bottom of the terminal while the benchmark
# runs: a gradient rule, then live CPU / memory / disk I/O / network rates
# sampled from /proc once a second. Implemented with a DECSTBM scroll region —
# the benchmark output scrolls above, the HUD stays put. Linux + tty only.

HUD_PID="" HUD_ROWS=0 HUD_ON=false

hud_size() { # → "rows cols" from the real tty (tput lies inside pipes/ssh)
    local sz=""
    sz=$(stty size </dev/tty 2>/dev/null)
    if [[ "$sz" =~ ^[0-9]+\ [0-9]+$ ]]; then
        printf '%s' "$sz"
        return 0
    fi
    local r c
    r=$(tput lines 2>/dev/null) c=$(tput cols 2>/dev/null)
    [[ -n "$r" && -n "$c" ]] && { printf '%s %s' "$r" "$c"; return 0; }
    printf '%s %s' "${LINES:-24}" "${COLUMNS:-80}"
}

hud_rate() { # bytes/sec → compact human rate
    awk -v b="$1" 'BEGIN {
        if (b >= 1073741824) printf "%.1fG/s", b/1073741824
        else if (b >= 1048576) printf "%.0fM/s", b/1048576
        else if (b >= 1024) printf "%.0fK/s", b/1024
        else printf "%dB/s", b }'
}

hud_load_color() { # pct → green/amber/red
    if (($1 < 60)); then printf '%s' "$C_OK"
    elif (($1 < 85)); then printf '%s' "$C_WARN"
    else printf '%s' "$C_BAD"; fi
}

hud_rule() { # gradient rule sized to the live terminal width
    local n=$1 i r g b out=""
    if $TRUECOLOR; then
        for ((i = 0; i < n; i++)); do
            r=$((129 + (244 - 129) * i / n))
            g=$((140 - (140 - 114) * i / n))
            b=$((248 - (248 - 182) * i / n))
            out+=$(printf '\033[38;2;%d;%d;%dm─' "$r" "$g" "$b")
        done
        printf '%s%s' "$out" "$RST"
    else
        printf '%s%s%s' "$C_ACCENT" "$(repeat_char '─' "$n")" "$RST"
    fi
}

hud_loop() {
    local pb=0 pt=0 pdr=0 pdw=0 prx=0 ptx=0 first=true
    local rows=$HUD_ROWS cols rule_cols=0 rule=""
    while :; do
        local nrows region=""
        read -r nrows cols <<<"$(hud_size)"
        if ((nrows != rows)); then # terminal was resized — re-pin the HUD
            rows=$nrows
            region=$(printf '\033[1;%dr' $((rows - 2)))
        fi
        if ((cols != rule_cols)); then
            rule=$(hud_rule "$cols")
            rule_cols=$cols
        fi

        # cpu: busy/total delta over the last tick
        local _ u n s idle iw irq sirq st busy total cpu=0
        read -r _ u n s idle iw irq sirq st _ < /proc/stat
        busy=$((u + n + s + irq + sirq + st))
        total=$((busy + idle + iw))
        if ! $first && ((total > pt)); then
            cpu=$(((busy - pb) * 100 / (total - pt)))
        fi
        pb=$busy pt=$total

        # memory
        local mt ma mu mem_pct
        mt=$(awk '/^MemTotal/ {print $2}' /proc/meminfo)
        ma=$(awk '/^MemAvailable/ {print $2}' /proc/meminfo)
        mu=$((mt - ma))
        mem_pct=$((mu * 100 / (mt > 0 ? mt : 1)))

        # disk io: whole physical devices only, sectors → bytes
        local dr dw rrate=0 wrate=0
        read -r dr dw <<<"$(awk '$3 ~ /^(sd[a-z]+|vd[a-z]+|xvd[a-z]+|hd[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+)$/ {r+=$6; w+=$10} END {printf "%.0f %.0f", r*512, w*512}' /proc/diskstats)"
        if ! $first; then
            rrate=$((dr - pdr)); wrate=$((dw - pdw))
            ((rrate < 0)) && rrate=0
            ((wrate < 0)) && wrate=0
        fi
        pdr=$dr pdw=$dw

        # network: everything except loopback
        local rx tx rxr=0 txr=0
        read -r rx tx <<<"$(awk 'NR>2 {gsub(/:/," "); if ($1 != "lo") {rx+=$2; tx+=$10}} END {printf "%.0f %.0f", rx, tx}' /proc/net/dev)"
        if ! $first; then
            rxr=$((rx - prx)); txr=$((tx - ptx))
            ((rxr < 0)) && rxr=0
            ((txr < 0)) && txr=0
        fi
        prx=$rx ptx=$tx
        first=false

        # elapsed
        local el line
        el=$(($(date +%s) - START_TIME))

        local ccol mcol
        ccol=$(hud_load_color "$cpu")
        mcol=$(hud_load_color "$mem_pct")
        if ((cols >= 96)); then
            printf -v line ' %s%s%s %d:%02d  %sCPU%s %s %s%3d%%%s  %sMEM%s %s %s%s%s%s/%s%s  %sDISK%s %s%s%s%s %s%s%s%s  %sNET%s %s%s%s%s %s%s%s%s' \
                "$C_MUTE" "$G_CLK" "$RST" $((el / 60)) $((el % 60)) \
                "$C_MUTE" "$RST" "$(meter "$cpu" 12 "$ccol")" "$BOLD" "$cpu" "$RST" \
                "$C_MUTE" "$RST" "$(meter "$mem_pct" 12 "$mcol")" \
                "$BOLD" "$(fmt_kib "$mu")" "$RST" "$C_MUTE" "$(fmt_kib "$mt")" "$RST" \
                "$C_MUTE" "$RST" "$C_CYAN" "$G_DN" "$RST" "$(hud_rate "$rrate")" "$C_CYAN" "$G_UP" "$RST" "$(hud_rate "$wrate")" \
                "$C_MUTE" "$RST" "$C_ACCENT" "$G_DN" "$RST" "$(hud_rate "$rxr")" "$C_ACCENT" "$G_UP" "$RST" "$(hud_rate "$txr")"
        else
            printf -v line ' %s%s%s %d:%02d  %sCPU%s %s%3d%%%s  %sMEM%s %s%d%%%s  %sD%s %s%s %s%s  %sN%s %s%s %s%s' \
                "$C_MUTE" "$G_CLK" "$RST" $((el / 60)) $((el % 60)) \
                "$C_MUTE" "$RST" "$ccol$BOLD" "$cpu" "$RST" \
                "$C_MUTE" "$RST" "$mcol$BOLD" "$mem_pct" "$RST" \
                "$C_MUTE" "$RST" "$G_DN" "$(hud_rate "$rrate")" "$G_UP" "$(hud_rate "$wrate")" \
                "$C_MUTE" "$RST" "$G_DN" "$(hud_rate "$rxr")" "$G_UP" "$(hud_rate "$txr")"
        fi

        # one atomic write: save cursor, paint both rows, restore
        printf '\0337%s\033[%d;1H\033[2K%s\033[%d;1H\033[2K%s\0338' \
            "$region" $((rows - 1)) "$rule" "$rows" "$line"
        sleep 1
    done
}

hud_start() {
    $USE_TUI || return 0
    [[ "$OS_KIND" == "linux" ]] || return 0
    local rows _cols
    read -r rows _cols <<<"$(hud_size)"
    [[ -z "$rows" || "$rows" -lt 12 ]] && return 0
    HUD_ROWS=$rows
    # start from a clean screen, then fence off the bottom two rows
    printf '\033[2J\033[H'
    printf '\033[1;%dr' $((rows - 2))
    printf '\033[1;1H'
    hud_loop &
    HUD_PID=$!
    disown "$HUD_PID" 2>/dev/null
    HUD_ON=true
}

hud_stop() {
    [[ -n "$HUD_PID" ]] && kill "$HUD_PID" 2>/dev/null && wait "$HUD_PID" 2>/dev/null
    HUD_PID=""
    $HUD_ON || return 0
    # release the scroll region and wipe the HUD rows
    local rows _cols
    read -r rows _cols <<<"$(hud_size)"
    [[ -z "$rows" ]] && rows=$HUD_ROWS
    printf '\0337\033[r\033[%d;1H\033[2K\033[%d;1H\033[2K\0338' $((rows - 1)) "$rows"
    HUD_ON=false
}

SPINNER_PID=""
spin_start() { # spin_start <message>
    $USE_TUI || { printf '  %s ...\n' "$1"; return; }
    local msg=$1
    (
        local i=0 nf=${#SPIN_FRAMES[@]}
        printf '\033[?25l'
        while :; do
            printf '\r  %s%s%s %s%s%s ' "$C_ACCENT2" "${SPIN_FRAMES[i % nf]}" "$RST" "$DIM" "$msg" "$RST"
            i=$((i + 1))
            sleep 0.09
        done
    ) &
    SPINNER_PID=$!
    disown "$SPINNER_PID" 2>/dev/null
}

spin_stop() {
    [[ -n "$SPINNER_PID" ]] && kill "$SPINNER_PID" 2>/dev/null && wait "$SPINNER_PID" 2>/dev/null
    SPINNER_PID=""
    $USE_TUI && printf '\r\033[2K\033[?25h'
    return 0
}

# slow pulse with elapsed timer — for minutes-long external runs where a
# fast spinner would feel frantic and a stuck one would look hung
pulse_start() { # pulse_start <message>
    $USE_TUI || { printf '  %s ...\n' "$1"; return; }
    local msg=$1
    (
        local start i=0 el
        start=$(date +%s)
        local s1 s2 s3
        s1=$(c 165 180 252 147) s2=$(c 129 140 248 105) s3=$(c 79 70 229 62)
        local shades=("$s1" "$s2" "$s3" "$s2")
        printf '\033[?25l'
        while :; do
            el=$(($(date +%s) - start))
            printf '\r\033[2K  %s%s%s %s%s%s %s%s %d:%02d elapsed%s ' \
                "${shades[i % 4]}" "$G_DOT" "$RST" "$DIM" "$msg" "$RST" \
                "$C_MUTE" "$G_SEP" $((el / 60)) $((el % 60)) "$RST"
            i=$((i + 1))
            sleep 0.5
        done
    ) &
    SPINNER_PID=$!
    disown "$SPINNER_PID" 2>/dev/null
}

banner() {
    echo
    # gradient wordmark: each letter sweeps indigo → pink
    local word="benchmark"
    local mark="" i n=${#word} r g b
    if $TRUECOLOR && $USE_COLOR; then
        for ((i = 0; i < n; i++)); do
            r=$((129 + (244 - 129) * i / (n - 1)))
            g=$((140 - (140 - 114) * i / (n - 1)))
            b=$((248 - (248 - 182) * i / (n - 1)))
            mark+=$(printf '\033[38;2;%d;%d;%dm%s' "$r" "$g" "$b" "${word:i:1}")
        done
    else
        mark="$C_ACCENT$word"
    fi
    local tagline="the modern VPS benchmark"
    local ver="v$BENCHMARK_VERSION"
    local pad=$((TERM_WIDTH - 4 - ${#word} - 3 - ${#tagline} - ${#ver} - 2))
    ((pad < 1)) && pad=1
    printf '  %s%s%s %s%s%s %s%s %s%s%*s%s%s%s\n' \
        "$C_ACCENT" "$G_BAR" "$RST" "$BOLD" "$mark" "$RST" "$DIM" "$G_SEP" "$tagline" "$RST" \
        "$pad" "" "$C_MUTE" "$ver" "$RST"
    # context strip: what we're running on, at a glance
    local ctx="${R_OS:-$(uname -s)}"
    [[ -n "${R_CPU_CORES:-}" ]] && ctx+=" $G_SEP ${R_CPU_CORES} cores"
    [[ -n "${R_ARCH:-}" ]] && ctx+=" $G_SEP ${R_ARCH}"
    ctx+=" $G_SEP $(date '+%Y-%m-%d %H:%M %Z')"
    printf '    %s%s%s\n\n' "$C_MUTE" "$ctx" "$RST"
    grad_hr
}

# animated meter row: the bar sweeps from zero to its value, then the line
# settles — value bold, unit dimmed, all values right-aligned in one column
meter_row() { # meter_row <label> <pct> <color> <value> <unit> [suffix]
    local label=$1 pct=$2 color=$3 value=$4 unit=$5 suffix=${6:-}
    if $USE_TUI; then
        local frames=6 f p
        for ((f = 1; f <= frames; f++)); do
            p=$((pct * f / frames))
            printf '\r\033[2K  %s%-14s%s %s %s%9s%s %s%-5s%s%s' \
                "$C_MUTE" "$label" "$RST" "$(meter "$p" 30 "$color")" \
                "$BOLD$C_TEXT" "$value" "$RST" "$DIM" "$unit" "$RST" "$suffix"
            sleep 0.02
        done
        printf '\n'
    else
        printf '  %-14s %s %9s %-5s%s\n' \
            "$label" "$(meter "$pct" 30 "$color")" "$value" "$unit" "$suffix"
    fi
}

speed_row() { # speed_row <label> <pct> <color> <mbs> [suffix] — MB/s → value+unit
    local human
    human=$(fmt_speed "$4")
    meter_row "$1" "$2" "$3" "${human% *}" "${human##* }" "${5:-}"
}

# ────────────────────────────────── helpers ──────────────────────────────────

exists() { command -v "$1" >/dev/null 2>&1; }

OS_KIND="linux"
[[ "$(uname -s)" == "Darwin" ]] && OS_KIND="darwin"

cleanup() {
    spin_stop
    hud_stop
    rm -f "${DISK_TEST_DIR:-/nonexistent}"/benchmark_test_* 2>/dev/null
    [[ -n "${SCRATCH_DIR:-}" && "$SCRATCH_DIR" == */benchmark* ]] && rm -rf "$SCRATCH_DIR" 2>/dev/null
    $USE_COLOR && printf '\033[?25h'
}
trap 'cleanup; printf "\n%sInterrupted — cleaned up.%s\n" "$C_BAD" "$RST"; exit 130' INT TERM
trap cleanup EXIT

fmt_kib() { # kibibytes → human
    awk -v k="$1" 'BEGIN {
        if (k >= 1073741824) printf "%.1f TiB", k/1073741824
        else if (k >= 1048576) printf "%.1f GiB", k/1048576
        else if (k >= 1024) printf "%.1f MiB", k/1024
        else printf "%d KiB", k
    }'
}

fmt_speed() { # MB/s → human (keeps MB/s or GB/s)
    awk -v s="$1" 'BEGIN {
        if (s >= 1024) printf "%.2f GB/s", s/1024
        else printf "%.1f MB/s", s
    }'
}

json_escape() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }

# ─────────────────────────────────── flags ───────────────────────────────────

QUICK=false SKIP_CPU=false SKIP_DISK=false SKIP_NET=false REDUCE_NET=false SKIP_GB=false
JSON_PRINT=false JSON_FILE=""

print_help() {
    banner
    cat <<EOF

  ${BOLD}Usage:${RST} curl -sL benchmarki.ng | bash -s -- [flags]
         ./benchmark.sh [flags]

  ${C_ACCENT}-q${RST}            quick mode — shorter CPU/disk/network tests
  ${C_ACCENT}-c${RST}            skip CPU benchmark
  ${C_ACCENT}-d${RST}            skip disk benchmark
  ${C_ACCENT}-n${RST}            skip network tests
  ${C_ACCENT}-r${RST}            reduce global network test to 3 regions (save bandwidth)
  ${C_ACCENT}-g${RST}            skip the Geekbench test
  ${C_ACCENT}-j${RST}            print JSON results when finished
  ${C_ACCENT}-w${RST} <file>     write JSON results to <file>
  ${C_ACCENT}--no-color${RST}    disable colors (NO_COLOR env also respected)
  ${C_ACCENT}--no-tui${RST}      disable motion — spinners, animations, live HUD (colors stay)
  ${C_ACCENT}--ascii${RST}       plain ASCII glyphs (auto when the locale isn't UTF-8)
  ${C_ACCENT}-h${RST}            this help

EOF
    exit 0
}

while getopts 'qcdnrgjw:h-:' flag 2>/dev/null; do
    case "$flag" in
        q) QUICK=true ;;
        c) SKIP_CPU=true ;;
        d) SKIP_DISK=true ;;
        n) SKIP_NET=true ;;
        r) REDUCE_NET=true ;;
        g) SKIP_GB=true ;;
        j) JSON_PRINT=true ;;
        w) JSON_FILE=$OPTARG ;;
        h) print_help ;;
        -) case "${OPTARG:-}" in
               help) print_help ;;
               no-color | no-tui | ascii) ;; # handled in the pre-scan
           esac ;;
        *) ;;
    esac
done

export LC_ALL=C 2>/dev/null || true

# section count for the n/total progress indicator in headers
STEP_TOTAL=1 # System
$SKIP_NET || STEP_TOTAL=$((STEP_TOTAL + 3))  # network info, latency, global
$SKIP_CPU || STEP_TOTAL=$((STEP_TOTAL + 2))  # cpu, memory
$SKIP_DISK || STEP_TOTAL=$((STEP_TOTAL + 1))
$SKIP_GB || STEP_TOTAL=$((STEP_TOTAL + 1))

# ────────────────────────────── system information ───────────────────────────

R_CPU_MODEL="" R_CPU_CORES="" R_CPU_FREQ="" R_RAM="" R_DISK="" R_OS="" R_KERNEL=""
R_VIRT="" R_ARCH="" R_AES=false R_UPTIME="" R_LOAD="" R_CPU_ISA="" R_RAM_MB=0

# turn a space-separated CPU flag list into a readable ISA-extension string,
# best first. Covers x86 (avx512/avx2/…) and ARM (sve/asimd/…).
isa_from_flags() { # isa_from_flags "<flags>" → "AVX-512 · AVX2 · FMA"
    local f=" $1 " out="" x
    add() { [[ -n "$out" ]] && out+=" $G_SEP "; out+="$1"; }
    [[ "$f" == *" avx512f "* ]] && add "AVX-512"
    [[ "$f" == *" avx2 "* ]] && add "AVX2"
    [[ "$f" == *" avx2 "* || "$f" == *" avx512f "* || "$f" != *" avx "* ]] || add "AVX"
    [[ "$f" == *" fma "* ]] && add "FMA"
    [[ "$f" == *" sve "* ]] && add "SVE"
    [[ "$f" == *" asimd "* || "$f" == *" neon "* ]] && add "NEON"
    unset -f add
    printf '%s' "$out"
}

collect_sysinfo() {
    R_ARCH=$(uname -m)
    R_KERNEL=$(uname -r)

    if [[ "$OS_KIND" == "darwin" ]]; then
        R_CPU_MODEL=$(sysctl -n machdep.cpu.brand_string 2>/dev/null)
        R_CPU_CORES=$(sysctl -n hw.ncpu 2>/dev/null)
        R_OS="macOS $(sw_vers -productVersion 2>/dev/null)"
        local mem_bytes
        mem_bytes=$(sysctl -n hw.memsize 2>/dev/null || echo 0)
        R_RAM=$(fmt_kib $((mem_bytes / 1024)))
        R_UPTIME=$(uptime | sed -E 's/.*up ([^,]+(, *[0-9]+:[0-9]+)?).*/\1/' | head -1)
        R_LOAD=$(uptime | awk -F'load averages?: ' '{print $2}')
        R_VIRT=$([[ "$R_CPU_MODEL" == *Apple* ]] && echo "Bare metal (Apple Silicon)" || echo "Unknown")
        R_RAM_MB=$((mem_bytes / 1024 / 1024))
        local mfeat
        mfeat=$(sysctl -n machdep.cpu.features machdep.cpu.leaf7_features 2>/dev/null | tr 'A-Z. ' 'a-z__' | tr '\n' ' ')
        [[ "$mfeat" == *aes* ]] && R_AES=true
        [[ "$R_CPU_MODEL" == *Apple* ]] && R_CPU_ISA="NEON" || R_CPU_ISA=$(isa_from_flags "$mfeat")
        local disk_line
        disk_line=$(df -k / | awk 'NR==2 {print $2, $3}')
        R_DISK="$(fmt_kib "$(echo "$disk_line" | awk '{print $2}')") used / $(fmt_kib "$(echo "$disk_line" | awk '{print $1}')")"
    else
        R_CPU_MODEL=$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo 2>/dev/null | sed 's/^[ \t]*//')
        [[ -z "$R_CPU_MODEL" ]] && exists lscpu && \
            R_CPU_MODEL=$(lscpu | awk -F: '/Model name/ {print $2; exit}' | sed 's/^[ \t]*//')
        R_CPU_CORES=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo 2>/dev/null)
        R_CPU_FREQ=$(awk -F'[ :]+' '/cpu MHz/ {printf "%.0f", $4; exit}' /proc/cpuinfo 2>/dev/null)
        if [[ -z "$R_CPU_FREQ" || "$R_CPU_FREQ" == "0" ]] && exists lscpu; then
            R_CPU_FREQ=$(lscpu 2>/dev/null | awk -F: '/CPU max MHz/ {gsub(/ /,"",$2); printf "%.0f", $2; exit}')
        fi
        [[ "$R_CPU_FREQ" == "0" ]] && R_CPU_FREQ=""
        [[ -n "$R_CPU_FREQ" ]] && R_CPU_FREQ="$R_CPU_FREQ MHz"
        local cflags
        cflags=$(awk -F: '/^flags|^Features/ {print $2; exit}' /proc/cpuinfo 2>/dev/null)
        [[ " $cflags " == *" aes "* ]] && R_AES=true
        R_CPU_ISA=$(isa_from_flags "$cflags")
        if [[ -f /etc/os-release ]]; then
            R_OS=$(awk -F= '/^PRETTY_NAME=/{gsub(/"/, "", $2); print $2}' /etc/os-release)
        fi
        local tram uram
        tram=$(free -k 2>/dev/null | awk '/^Mem/ {print $2}')
        uram=$(free -k 2>/dev/null | awk '/^Mem/ {print $3}')
        [[ -n "$tram" ]] && R_RAM="$(fmt_kib "${uram:-0}") used / $(fmt_kib "$tram")"
        [[ -n "$tram" ]] && R_RAM_MB=$((tram / 1024))
        R_UPTIME=$(awk '{d=int($1/86400); h=int(($1%86400)/3600); m=int(($1%3600)/60);
            printf "%dd %dh %dm", d, h, m}' /proc/uptime 2>/dev/null)
        R_LOAD=$(awk '{printf "%s %s %s", $1, $2, $3}' /proc/loadavg 2>/dev/null)
        local dtot dused
        dtot=$(df -k --total -x tmpfs -x devtmpfs -x overlay -x squashfs 2>/dev/null | awk '/^total/ {print $2}')
        dused=$(df -k --total -x tmpfs -x devtmpfs -x overlay -x squashfs 2>/dev/null | awk '/^total/ {print $3}')
        [[ -n "$dtot" ]] && R_DISK="$(fmt_kib "${dused:-0}") used / $(fmt_kib "$dtot")"
        # virtualization
        if exists systemd-detect-virt; then
            local v
            v=$(systemd-detect-virt 2>/dev/null)
            case "$v" in
                none) R_VIRT="Dedicated / Bare metal" ;;
                "")   R_VIRT="Unknown" ;;
                *)    R_VIRT=$(echo "$v" | tr '[:lower:]' '[:upper:]') ;;
            esac
        elif [[ -f /proc/user_beancounters ]]; then R_VIRT="OpenVZ"
        elif grep -qa docker /proc/1/cgroup 2>/dev/null; then R_VIRT="Docker"
        elif grep -qa lxc /proc/1/cgroup 2>/dev/null; then R_VIRT="LXC"
        elif grep -qi hypervisor /proc/cpuinfo 2>/dev/null; then R_VIRT="VM (hypervisor flag)"
        else R_VIRT="Dedicated / Bare metal"
        fi
    fi
    [[ -z "$R_OS" ]] && R_OS="$(uname -s)"
    [[ -z "$R_CPU_MODEL" ]] && R_CPU_MODEL="Unknown CPU"
}

print_sysinfo() {
    section "System"
    local cpu_line="$C_TEXT$R_CPU_MODEL$RST"
    row "CPU" "$cpu_line"
    local core_line="$C_TEXT$R_CPU_CORES cores$RST"
    [[ -n "$R_CPU_FREQ" ]] && core_line+=" $C_MUTE@ $R_CPU_FREQ$RST"
    if $R_AES; then core_line+="  $(ok) ${C_MUTE}AES-NI$RST"; else core_line+="  $(bad) ${C_MUTE}AES-NI$RST"; fi
    row "Cores" "$core_line"
    [[ -n "$R_CPU_ISA" ]] && row "Instructions" "$C_TEXT$R_CPU_ISA$RST"
    row "Memory" "$C_TEXT$R_RAM$RST"
    row "Disk" "$C_TEXT$R_DISK$RST"
    row "OS" "$C_TEXT$R_OS$RST $C_MUTE($R_ARCH)$RST"
    row "Kernel" "$C_TEXT$R_KERNEL$RST"
    row "Virtualization" "$C_TEXT$R_VIRT$RST"
    row "Uptime" "$C_TEXT$R_UPTIME$RST  ${C_MUTE}load:$RST $C_TEXT$R_LOAD$RST"
}

# ─────────────────────────────── network info ────────────────────────────────

R_IPV4=false R_IPV6=false R_ISP="" R_LOC=""

collect_netinfo() {
    exists curl || return
    spin_start "Detecting public network..."
    local info
    R_IPV4=$(curl -s -4 -m 4 https://icanhazip.com >/dev/null 2>&1 && echo true || echo false)
    R_IPV6=$(curl -s -6 -m 4 https://icanhazip.com >/dev/null 2>&1 && echo true || echo false)
    info=$(curl -s -m 6 "https://ipinfo.io/json" 2>/dev/null)
    R_ISP=$(printf '%s' "$info" | sed -n 's/.*"org": *"\([^"]*\)".*/\1/p')
    local city country
    city=$(printf '%s' "$info" | sed -n 's/.*"city": *"\([^"]*\)".*/\1/p')
    country=$(printf '%s' "$info" | sed -n 's/.*"country": *"\([^"]*\)".*/\1/p')
    [[ -n "$city" ]] && R_LOC="$city, $country"
    spin_stop
}

print_netinfo() {
    section "Network"
    local conn=""
    [[ "$R_IPV4" == true ]] && conn+="$(ok) ${C_TEXT}IPv4$RST   " || conn+="$(bad) ${C_MUTE}IPv4$RST   "
    [[ "$R_IPV6" == true ]] && conn+="$(ok) ${C_TEXT}IPv6$RST" || conn+="$(bad) ${C_MUTE}IPv6$RST"
    row "Connectivity" "$conn"
    [[ -n "$R_ISP" ]] && row "Provider" "$C_TEXT$R_ISP$RST"
    [[ -n "$R_LOC" ]] && row "Location" "$C_TEXT$R_LOC$RST"
}

# ─────────────────────────────── cpu benchmark ───────────────────────────────

R_CPU_SINGLE="" R_CPU_MULTI="" R_CPU_CV="" R_CPU_STEAL="" R_CPU_ENGINE="" R_CPU_UNIT=""

cpu_hash_run() { # cpu_hash_run <seconds> <jobs> → total MB hashed
    local secs=$1 jobs=$2 dir="$SCRATCH_DIR" i
    local hasher="sha256sum"
    exists sha256sum || hasher="shasum -a 256"
    for ((i = 0; i < jobs; i++)); do
        (
            local end=$(($(date +%s) + secs)) mb=0
            while (($(date +%s) < end)); do
                dd if=/dev/zero bs=1m count=32 2>/dev/null | $hasher >/dev/null 2>&1 ||
                    dd if=/dev/zero bs=1M count=32 2>/dev/null | $hasher >/dev/null
                mb=$((mb + 32))
            done
            echo "$mb" >"$dir/cpu_$i"
        ) &
    done
    wait
    local total=0
    for ((i = 0; i < jobs; i++)); do
        total=$((total + $(cat "$dir/cpu_$i" 2>/dev/null || echo 0)))
        rm -f "$dir/cpu_$i"
    done
    echo "$total"
}

read_cpu_stat() { # → "steal_ticks total_ticks" (linux only)
    awk '/^cpu / {t=0; for (i=2; i<=NF; i++) t+=$i; print $9+0, t}' /proc/stat 2>/dev/null
}

# ── on-the-fly native micro-probe ────────────────────────────────────────────
# A tiny C program (real memory bandwidth + integer/FP CPU work) compiled here,
# run once, deleted. This is the only honest way to measure these in a shell
# script: sha256 throughput tracks SHA-NI, not general CPU (off by up to ~50x),
# and dd measures VFS/syscall overhead, not the memory subsystem. Source is
# inline so it stays fully auditable.
PROBE_BIN="" # "" = not tried yet, "none" = tried and failed, else = binary path

compile_probe() {
    [[ "$PROBE_BIN" == none ]] && return 1
    [[ -n "$PROBE_BIN" ]] && return 0
    local cc="" c
    for c in cc gcc clang; do command -v "$c" >/dev/null 2>&1 && { cc=$c; break; }; done
    [[ -z "$cc" ]] && { PROBE_BIN=none; return 1; }
    local src="$SCRATCH_DIR/probe.c" bin="$SCRATCH_DIR/probe"
    cat >"$src" <<'PROBE_EOF'
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include <pthread.h>

static double now(void) {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec + ts.tv_nsec / 1e9;
}

/* memory bandwidth: buffer sized to blow past LLC; touch defeats dead-store elim */
static double mem_bw(size_t bytes, int op, double secs) {
    char *a = malloc(bytes), *b = malloc(bytes);
    if (!a || !b) { free(a); free(b); return 0; }
    memset(a, 1, bytes); memset(b, 2, bytes);
    volatile uint64_t sink = 0;
    double t0 = now(); size_t moved = 0;
    while (now() - t0 < secs) {
        if (op == 0) { memcpy(b, a, bytes); sink += (uint64_t)b[bytes-1]; }
        else if (op == 1) {
            uint64_t s = 0; uint64_t *p = (uint64_t *)a;
            for (size_t i = 0; i < bytes/8; i++) s += p[i];
            sink += s;
        } else { memset(a, (int)(moved & 0xff), bytes); sink += (uint64_t)a[bytes-1]; }
        moved += bytes;
    }
    double dt = now() - t0;
    free(a); free(b);
    (void)sink;
    return moved / dt / 1e9;
}

/* CPU: mixed integer + floating point loop, iterations per second */
typedef struct { double secs; volatile uint64_t iters; } cpu_arg;
static void *cpu_worker(void *v) {
    cpu_arg *c = v;
    uint64_t x = 0x9e3779b97f4a7c15ULL; double f = 1.0;
    uint64_t n = 0; double t0 = now();
    while (now() - t0 < c->secs) {
        for (int i = 0; i < 100000; i++) {
            x ^= x << 13; x ^= x >> 7; x ^= x << 17;
            f = f * 1.0000001 + (double)(x & 0xffff);
            if (f > 1e9) f = 1.0;
        }
        n += 100000;
    }
    volatile double keep = f; (void)keep;
    c->iters = n;
    return NULL;
}
static double cpu_run(int threads, double secs) {
    pthread_t th[256]; cpu_arg args[256];
    if (threads > 256) threads = 256;
    for (int i = 0; i < threads; i++) { args[i].secs = secs; args[i].iters = 0; }
    double t0 = now();
    for (int i = 0; i < threads; i++) pthread_create(&th[i], NULL, cpu_worker, &args[i]);
    for (int i = 0; i < threads; i++) pthread_join(th[i], NULL);
    double dt = now() - t0;
    uint64_t total = 0;
    for (int i = 0; i < threads; i++) total += args[i].iters;
    return total / dt / 1e6;
}

int main(int argc, char **argv) {
    const char *mode = argc > 1 ? argv[1] : "all";
    double secs = argc > 2 ? atof(argv[2]) : 1.0;
    int cores = argc > 3 ? atoi(argv[3]) : 1;
    size_t mb = argc > 4 ? (size_t)atoi(argv[4]) : 128;
    size_t bytes = mb * 1024 * 1024;
    int do_mem = strcmp(mode, "cpu") != 0;
    int do_cpu = strcmp(mode, "mem") != 0;
    if (do_mem) {
        printf("MEM_COPY %.2f\n", mem_bw(bytes, 0, secs));
        printf("MEM_READ %.2f\n", mem_bw(bytes, 1, secs));
        printf("MEM_WRITE %.2f\n", mem_bw(bytes, 2, secs));
    }
    if (do_cpu) {
        printf("CPU1 %.1f\n", cpu_run(1, secs));
        if (cores > 1) printf("CPUN %.1f\n", cpu_run(cores, secs));
    }
    return 0;
}
PROBE_EOF
    if ! "$cc" -O2 -pthread "$src" -o "$bin" 2>/dev/null || [[ ! -x "$bin" ]]; then
        PROBE_BIN=none
        return 1
    fi
    PROBE_BIN=$bin
    return 0
}

probe_mem_mb() { # buffer size in MiB — big enough to defeat cache, small enough for tiny RAM
    local mb=128 tk
    if [[ -r /proc/meminfo ]]; then
        tk=$(awk '/^MemTotal/ {print $2; exit}' /proc/meminfo)
        [[ -n "$tk" ]] && ((tk / 1024 / 16 < mb)) && mb=$((tk / 1024 / 16))
    fi
    ((mb < 16)) && mb=16
    printf '%d' "$mb"
}

probe_cpu_val() { # probe_cpu_val <secs> <threads> → CPUN if threads>1 else CPU1
    local out
    out=$("$PROBE_BIN" cpu "$1" "$2" 2>/dev/null) || return 1
    if (($2 > 1)); then printf '%s' "${out##*CPUN }"; else
        out=${out#CPU1 }
        printf '%s' "${out%%$'\n'*}"
    fi
}

# openssl fallback: in-process sha256 (SHA-NI where present). Crypto throughput,
# not general CPU — only used when no compiler is available.
TASKSET=()
command -v taskset >/dev/null 2>&1 && TASKSET=(taskset -c 0)

openssl_sha_mbps() { # openssl_sha_mbps <seconds> <multi> <pin> → integer MB/s
    local secs=$1 multi=$2 pin=$3
    local -a cmd=(openssl speed -mr -seconds "$secs" -bytes 1048576)
    ((multi > 1)) && cmd+=(-multi "$multi")
    [[ "$pin" == pin && ${#TASKSET[@]} -gt 0 ]] && cmd=("${TASKSET[@]}" "${cmd[@]}")
    local out line bps=""
    out=$("${cmd[@]}" sha256 2>/dev/null) || return 1
    while IFS= read -r line; do
        [[ "$line" == +F:* ]] && bps=${line##*:}
    done <<<"$out"
    bps=${bps%%.*}
    [[ "$bps" =~ ^[0-9]+$ ]] || return 1
    printf '%d' $((bps / 1000000))
}

bench_cpu() {
    local cores=${R_CPU_CORES:-1}
    local secs=1 bursts=10
    $QUICK && bursts=5

    local stat0=""
    [[ "$OS_KIND" == "linux" ]] && stat0=$(read_cpu_stat)

    local i speeds=() v ref
    if compile_probe; then
        # primary: native integer + floating-point workload. Same code path for
        # every burst so the consistency trace reflects real compute, not the
        # SHA-NI pipeline whose behaviour under load differs from general CPU.
        section "CPU" "integer + floating point"
        R_CPU_ENGINE="native"
        R_CPU_UNIT="Mit/s"
        local pin_note=""
        [[ ${#TASKSET[@]} -gt 0 ]] && pin_note=", single-core pinned to cpu0"
        printf '  %s(engine: compiled native probe%s)%s\n' "$DIM" "$pin_note" "$RST"
        local -a probe1=("$PROBE_BIN" cpu 0.5 1)
        [[ ${#TASKSET[@]} -gt 0 ]] && probe1=("${TASKSET[@]}" "${probe1[@]}")
        for ((i = 1; i <= bursts; i++)); do
            pbar $(((i - 1) * 100 / bursts)) "Single-core burst $i/$bursts"
            v=$("${probe1[@]}" 2>/dev/null)
            v=${v#CPU1 }
            [[ -n "$v" ]] && speeds+=("$v")
        done
        pbar_done
        if ((cores > 1)); then
            spin_start "Multi-core run (${cores} threads)..."
            R_CPU_MULTI=$(probe_cpu_val "$secs" "$cores")
            spin_stop
        fi
        ref=400
    elif exists openssl && v=$(openssl_sha_mbps 1 1 pin) && [[ -n "$v" ]]; then
        # fallback: sha256 crypto throughput. Honest label — this is SHA-NI
        # crypto speed, not general CPU performance.
        section "CPU" "sha256 crypto throughput"
        printf '  %s(no C compiler — showing SHA-256 crypto throughput, which%s\n' "$DIM" "$RST"
        printf '  %s tracks SHA-NI, not general CPU; install gcc/clang for that)%s\n' "$DIM" "$RST"
        R_CPU_ENGINE="openssl"
        R_CPU_UNIT="MB/s"
        speeds+=("$v")
        for ((i = ${#speeds[@]} + 1; i <= bursts; i++)); do
            pbar $(((i - 1) * 100 / bursts)) "Single-core burst $i/$bursts"
            v=$(openssl_sha_mbps 1 1 pin) || break
            speeds+=("$v")
        done
        pbar_done
        if ((cores > 1)); then
            spin_start "Multi-core run (openssl -multi ${cores})..."
            R_CPU_MULTI=$(openssl_sha_mbps 2 "$cores" nopin) || R_CPU_MULTI=""
            spin_stop
        fi
        ref=2000
    else
        # last resort: dd | sha256sum. Slow, noisy, crypto-bound — indicative only.
        section "CPU" "sha256 crypto throughput"
        printf '  %s(no compiler or openssl — dd | sha256sum, indicative only)%s\n' "$DIM" "$RST"
        R_CPU_ENGINE="sha256sum"
        R_CPU_UNIT="MB/s"
        local hasher="sha256sum" burst_mb=64
        exists sha256sum || hasher="shasum -a 256"
        local t0 t1 dt
        t0=$(date +%s.%N 2>/dev/null || date +%s)
        dd if=/dev/zero bs=1M count="$burst_mb" 2>/dev/null | $hasher >/dev/null 2>&1 ||
            dd if=/dev/zero bs=1m count="$burst_mb" 2>/dev/null | $hasher >/dev/null
        t1=$(date +%s.%N 2>/dev/null || date +%s)
        dt=$(awk -v a="$t0" -v b="$t1" 'BEGIN {d=b-a; if (d<=0.001) d=0.001; print d}')
        burst_mb=$(awk -v d="$dt" -v m="$burst_mb" 'BEGIN {
            f = int(0.4 / d) + 1; if (f < 1) f = 1; if (f > 32) f = 32; print m * f }')
        for ((i = 1; i <= bursts; i++)); do
            pbar $(((i - 1) * 100 / bursts)) "Single-core burst $i/$bursts"
            t0=$(date +%s.%N 2>/dev/null || date +%s)
            dd if=/dev/zero bs=1M count="$burst_mb" 2>/dev/null | $hasher >/dev/null 2>&1 ||
                dd if=/dev/zero bs=1m count="$burst_mb" 2>/dev/null | $hasher >/dev/null
            t1=$(date +%s.%N 2>/dev/null || date +%s)
            dt=$(awk -v a="$t0" -v b="$t1" 'BEGIN {d=b-a; if (d<=0.001) d=0.001; print d}')
            speeds+=("$(awk -v m="$burst_mb" -v d="$dt" 'BEGIN {printf "%.1f", m/d}')")
        done
        pbar_done
        if ((cores > 1)); then
            spin_start "Multi-core hash run (${cores} threads)..."
            local mbN
            mbN=$(cpu_hash_run 2 "$cores")
            spin_stop
            R_CPU_MULTI=$(awk -v m="$mbN" 'BEGIN {printf "%.0f", m/2}')
        fi
        ref=2000
    fi

    [[ ${#speeds[@]} -eq 0 ]] && { printf '  %sCPU benchmark failed.%s\n' "$C_BAD" "$RST"; return; }

    local stats
    stats=$(printf '%s\n' "${speeds[@]}" | awk '
        {s+=$1; ss+=$1*$1; n++}
        END {m=s/n; sd=sqrt(ss/n-m*m); printf "%.0f %.1f", m, (m>0)? sd/m*100 : 0}')
    R_CPU_SINGLE=${stats%% *}
    R_CPU_CV=${stats##* }

    # steal% across the whole CPU benchmark window
    if [[ -n "$stat0" ]]; then
        local stat1
        stat1=$(read_cpu_stat)
        R_CPU_STEAL=$(awk -v a="$stat0" -v b="$stat1" 'BEGIN {
            split(a, x, " "); split(b, y, " ")
            dt = y[2] - x[2]
            printf "%.1f", (dt > 0) ? (y[1] - x[1]) / dt * 100 : 0}')
    fi

    local pct1
    pct1=$(awk -v v="$R_CPU_SINGLE" -v r="$ref" 'BEGIN {printf "%.0f", v/r*100}')
    meter_row "Single-core" "$pct1" "$C_CYAN" "$R_CPU_SINGLE" "$R_CPU_UNIT"
    if [[ -n "$R_CPU_MULTI" ]]; then
        local pctN scaling
        pctN=$(awk -v v="$R_CPU_MULTI" -v s="$((ref * cores))" 'BEGIN {printf "%.0f", v/s*100}')
        scaling=$(awk -v a="$R_CPU_SINGLE" -v b="$R_CPU_MULTI" 'BEGIN {printf "%.1f", (a>0)? b/a : 0}')
        meter_row "All cores" "$pctN" "$C_ACCENT" "$R_CPU_MULTI" "$R_CPU_UNIT" " ${C_MUTE}${G_X}${scaling} scaling$RST"
    fi
    printf '  %s%-14s%s %s%s%s  %s%s%s%% variance%s\n' "$C_MUTE" "Burst trace" "$RST" \
        "$C_CYAN" "$(spark "${speeds[@]}")" "$RST" "$C_MUTE" "$G_PM" "$R_CPU_CV" "$RST"
    local steal_line="${C_MUTE}n/a$RST"
    if [[ -n "${R_CPU_STEAL:-}" ]]; then
        local scolor=$C_OK
        awk -v s="$R_CPU_STEAL" 'BEGIN {exit !(s >= 2)}' && scolor=$C_WARN
        awk -v s="$R_CPU_STEAL" 'BEGIN {exit !(s >= 10)}' && scolor=$C_BAD
        steal_line="$scolor$R_CPU_STEAL%$RST"
    fi
    printf '  %s%-14s%s %s\n' "$C_MUTE" "CPU steal" "$RST" "$steal_line"
}

# ─────────────────────────────── disk benchmark ──────────────────────────────

DISK_TEST_DIR="."
R_DISK_ENGINE="" R_FIO_RESULTS=() R_DD_WRITE=""
FIO_BIN=""

# use local fio if present; otherwise fetch the static binary yabs.sh publishes
install_fio() {
    if exists fio; then
        FIO_BIN="fio"
        return 0
    fi
    [[ "$OS_KIND" != "linux" ]] && return 1
    exists curl || return 1
    local arch_tag=""
    case "$(uname -m)" in
        x86_64 | amd64) arch_tag="x64" ;;
        i?86) arch_tag="x86" ;;
        aarch64 | arm64) arch_tag="aarch64" ;;
        arm*) arch_tag="arm" ;;
        *) return 1 ;;
    esac
    local bin="$SCRATCH_DIR/fio"
    spin_start "Fetching static fio binary (${arch_tag})..."
    curl -sL -m 30 --retry 2 -o "$bin" \
        "https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/fio/fio_${arch_tag}" 2>/dev/null
    chmod +x "$bin" 2>/dev/null
    if ! "$bin" --version >/dev/null 2>&1; then
        spin_stop
        rm -f "$bin"
        return 1
    fi
    spin_stop
    FIO_BIN="$bin"
    printf '  %s(fio not installed — using downloaded static binary)%s\n' "$DIM" "$RST"
}

# Parse fio's default human output — the "(NNNunit B/s)" decimal token and
# IOPS= are stable across every fio version, unlike terse column offsets or the
# static binary's JSON support. Portable: sed + awk BEGIN, no gawk match().
fio_line_mbs() { # <read:/write: line> → MB/s
    local val unit
    val=$(sed -n 's/.*(\([0-9.]*\)[kMGT]B\/s).*/\1/p' <<<"$1")
    unit=$(sed -n 's/.*([0-9.]*\([kMGT]\)B\/s).*/\1/p' <<<"$1")
    [[ -z "$val" ]] && { printf '0.0'; return; }
    awk -v v="$val" -v u="$unit" 'BEGIN {
        if (u == "k") v /= 1000; else if (u == "G") v *= 1000; else if (u == "T") v *= 1000000
        printf "%.1f", v}'
}
fio_line_iops() { sed -n 's/.*IOPS=\([0-9.]*[kMG]*\).*/\1/p' <<<"$1"; }

FIO_ENGINE="" FIO_DIRECT=""

# The static binary may lack libaio, and some filesystems reject O_DIRECT —
# either yields all-zero rows. Probe once for a combo that actually moves data.
fio_probe() {
    local eng dir out mbs
    for eng in libaio psync sync; do
        for dir in 1 0; do
            out=$("$FIO_BIN" --name=probe --ioengine="$eng" --rw=randwrite --bs=64k \
                --size=32m --runtime=2 --direct="$dir" --numjobs=1 \
                --filename="$DISK_TEST_DIR/benchmark_test_fio" 2>/dev/null | grep -E '^ *write:' | head -1)
            rm -f "$DISK_TEST_DIR"/benchmark_test_fio* 2>/dev/null
            mbs=$(fio_line_mbs "$out")
            if [[ -n "$out" ]] && awk -v x="$mbs" 'BEGIN {exit !(x > 0)}'; then
                FIO_ENGINE=$eng
                FIO_DIRECT=$dir
                return 0
            fi
        done
    done
    return 1
}

bench_disk_fio() {
    R_DISK_ENGINE="fio"
    if ! fio_probe; then
        printf '  %sfio found no working ioengine on this host — falling back to dd.%s\n' "$DIM" "$RST"
        return 1
    fi
    local dnote="direct I/O"
    [[ "$FIO_DIRECT" == 0 ]] && dnote="buffered (O_DIRECT unavailable)"
    printf '  %s(engine: %s, %s)%s\n' "$DIM" "$FIO_ENGINE" "$dnote" "$RST"

    # A single fixed 2 GiB test file, created once and reused for every block
    # size — exactly what yabs does. Recreating it per block leaves the just-
    # written data in the *host* page cache (direct=1 only bypasses the guest),
    # which inflates reads to absurd cache-speed numbers.
    local fio_size="2G"
    [[ "$R_ARCH" == aarch64 || "$R_ARCH" == arm* ]] && fio_size="512M"
    $QUICK && fio_size="512M"
    local testfile="$DISK_TEST_DIR/benchmark_test_fio"
    local runtime=20
    $QUICK && runtime=8

    spin_start "Generating fio test file..."
    "$FIO_BIN" --name=setup --ioengine="$FIO_ENGINE" --rw=read --bs=64k --iodepth=64 \
        --numjobs=2 --size="$fio_size" --runtime=1 --gtod_reduce=1 --direct="$FIO_DIRECT" \
        --filename="$testfile" >/dev/null 2>&1
    spin_stop

    printf '  %s%-8s %12s %12s %10s %10s%s\n' "$C_MUTE" "Block" "Read" "Write" "R IOPS" "W IOPS" "$RST"
    local bs
    for bs in 4k 64k 512k 1m; do
        spin_start "fio ${bs} random read/write"
        local out
        out=$("$FIO_BIN" --name=test --ioengine="$FIO_ENGINE" --rw=randrw --rwmixread=50 \
            --bs="$bs" --iodepth=64 --numjobs=2 --size="$fio_size" --runtime="$runtime" \
            --gtod_reduce=1 --direct="$FIO_DIRECT" --filename="$testfile" --group_reporting 2>/dev/null)
        spin_stop
        local rl wl rspeed wspeed riops wiops
        rl=$(grep -E '^ *read:' <<<"$out" | head -1)
        wl=$(grep -E '^ *write:' <<<"$out" | head -1)
        if [[ -z "$rl$wl" ]]; then
            printf '  %s%-8s %s(test failed)%s\n' "$C_TEXT" "$bs" "$C_BAD" "$RST"
            continue
        fi
        rspeed=$(fio_line_mbs "$rl")
        wspeed=$(fio_line_mbs "$wl")
        riops=$(fio_line_iops "$rl")
        wiops=$(fio_line_iops "$wl")
        R_FIO_RESULTS+=("$bs:$rspeed:$wspeed")
        printf '  %s%-8s%s %s%12s%s %s%12s%s %s%10s%s %s%10s%s\n' \
            "$C_TEXT" "$bs" "$RST" \
            "$C_OK" "$(fmt_speed "$rspeed")" "$RST" \
            "$C_INFO" "$(fmt_speed "$wspeed")" "$RST" \
            "$C_MUTE" "${riops:-$G_MD}" "$RST" "$C_MUTE" "${wiops:-$G_MD}" "$RST"
    done
    rm -f "$testfile" 2>/dev/null
}

# sustained write: keep writing fdatasync'd chunks for <duration> seconds.
# This is deliberately BUFFERED — its job is to watch the write cache fill and
# drain: the peak is the cache-absorb rate, the tail is what the disk actually
# sustains once the cache is full. (fio above is the direct-I/O measurement;
# dd at queue-depth 1 can't do direct I/O well.) Chunks start small so even a
# slow disk yields many samples, and grow so fast disks get pushed too.
R_DISK_BURST="" R_DISK_SUSTAIN=""

bench_disk_sustained() {
    local duration=$1
    local chunk_kb=$((64 * 1024)) max_chunk_kb=$((1024 * 1024))
    local written_kb=0 cap_kb=$((16 * 1024 * 1024)) # never write more than 16 GiB
    local start now elapsed speeds=() t0 t1 dt mb
    start=$(date +%s)
    while :; do
        now=$(date +%s)
        elapsed=$((now - start))
        ((elapsed >= duration)) && break
        ((written_kb >= cap_kb)) && break
        pbar $((elapsed * 100 / duration)) "Sustained write ${elapsed}s/${duration}s"
        t0=$(date +%s.%N 2>/dev/null || date +%s)
        if [[ "$OS_KIND" == "darwin" ]]; then
            dd if=/dev/zero of="$DISK_TEST_DIR/benchmark_test_dd" bs=512k \
                count=$((chunk_kb / 512)) 2>/dev/null
            sync
        else
            dd if=/dev/zero of="$DISK_TEST_DIR/benchmark_test_dd" bs=512k \
                count=$((chunk_kb / 512)) conv=fdatasync 2>/dev/null
        fi
        t1=$(date +%s.%N 2>/dev/null || date +%s)
        dt=$(awk -v a="$t0" -v b="$t1" 'BEGIN {d=b-a; if (d<=0.01) d=0.01; print d}')
        mb=$(awk -v k="$chunk_kb" -v d="$dt" 'BEGIN {printf "%.1f", k/1024/d}')
        speeds+=("$mb")
        written_kb=$((written_kb + chunk_kb))
        # grow chunks so fast disks still get pushed for the full window
        if awk -v d="$dt" 'BEGIN {exit !(d < 2)}' && ((chunk_kb < max_chunk_kb)); then
            chunk_kb=$((chunk_kb * 2))
        fi
    done
    pbar_done
    rm -f "$DISK_TEST_DIR/benchmark_test_dd"
    [[ ${#speeds[@]} -eq 0 ]] && return 1

    R_DISK_BURST=$(printf '%s\n' "${speeds[@]}" | sort -rn | head -1)
    # steady state: average of the last half of the samples
    R_DISK_SUSTAIN=$(printf '%s\n' "${speeds[@]}" | awk -v n="${#speeds[@]}" \
        'NR > n/2 {s+=$1; c++} END {printf "%.1f", (c>0)? s/c : 0}')
    R_DD_WRITE=$R_DISK_SUSTAIN

    local pct_b pct_s
    pct_b=$(awk -v v="$R_DISK_BURST" 'BEGIN {printf "%.0f", v/3000*100}')
    pct_s=$(awk -v v="$R_DISK_SUSTAIN" 'BEGIN {printf "%.0f", v/3000*100}')
    printf '  %s(buffered sequential write — peak is cache, sustained is the disk)%s\n' "$DIM" "$RST"
    speed_row "Cache peak" "$pct_b" "$C_CYAN" "$R_DISK_BURST"
    speed_row "Sustained" "$pct_s" "$C_OK" "$R_DISK_SUSTAIN"
    local drop
    drop=$(awk -v b="$R_DISK_BURST" -v s="$R_DISK_SUSTAIN" \
        'BEGIN {printf "%.0f", (b>0)? (1-s/b)*100 : 0}')
    printf '  %s%-14s%s %s%s%s  %s%s samples %s -%s%% off peak%s\n' "$C_MUTE" "Write trace" "$RST" \
        "$C_OK" "$(spark "${speeds[@]}")" "$RST" "$C_MUTE" "${#speeds[@]}" "$G_SEP" "$drop" "$RST"
}

bench_disk_dd() {
    R_DISK_ENGINE="dd"
    local duration=30
    $QUICK && duration=10
    printf '  %s(fio unavailable — sustained sequential write via dd)%s\n' "$DIM" "$RST"
    bench_disk_sustained "$duration" ||
        printf '  %sDisk write test failed.%s\n' "$C_BAD" "$RST"
}

bench_disk() {
    section "Disk"
    # pick a writable directory
    if ! touch "./benchmark_test_w" 2>/dev/null; then
        DISK_TEST_DIR="${TMPDIR:-/tmp}"
        if ! touch "$DISK_TEST_DIR/benchmark_test_w" 2>/dev/null; then
            printf '  %sNo writable directory found — skipping disk test.%s\n' "$C_BAD" "$RST"
            return
        fi
    fi
    rm -f "./benchmark_test_w" "$DISK_TEST_DIR/benchmark_test_w" 2>/dev/null
    if [[ "$OS_KIND" == "linux" ]] && install_fio && bench_disk_fio; then
        echo
        local sdur=15
        $QUICK && sdur=8
        bench_disk_sustained "$sdur" || true
    else
        bench_disk_dd
    fi
}

# ────────────────────────────── memory benchmark ─────────────────────────────

R_MEM_ENGINE="" R_MEM_READ="" R_MEM_WRITE="" R_MEM_COPY="" R_MEM_UNIT=""

# sysbench reports MiB/s; the native probe reports GB/s. Normalize both to GB/s.
mem_gbs_row() { # mem_gbs_row <label> <gbs> <color>
    local pct
    pct=$(awk -v v="$2" 'BEGIN {printf "%.0f", v/50*100}')
    meter_row "$1" "$pct" "$3" "$2" "GB/s"
}

bench_mem() {
    section "Memory" "bandwidth"
    local total_gb=8
    $QUICK && total_gb=3
    if exists sysbench; then
        R_MEM_ENGINE="sysbench"
        local r w
        spin_start "sysbench memory read (${total_gb} GiB)..."
        r=$(sysbench memory --memory-block-size=1M \
            --memory-total-size="${total_gb}G" --memory-oper=read run 2>/dev/null |
            sed -n 's/.*(\([0-9.]*\) MiB\/sec).*/\1/p' | head -1)
        spin_stop
        spin_start "sysbench memory write (${total_gb} GiB)..."
        w=$(sysbench memory --memory-block-size=1M \
            --memory-total-size="${total_gb}G" --memory-oper=write run 2>/dev/null |
            sed -n 's/.*(\([0-9.]*\) MiB\/sec).*/\1/p' | head -1)
        spin_stop
        # MiB/s → GB/s
        [[ -n "$r" ]] && R_MEM_READ=$(awk -v v="$r" 'BEGIN {printf "%.2f", v*1.048576/1000}')
        [[ -n "$w" ]] && R_MEM_WRITE=$(awk -v v="$w" 'BEGIN {printf "%.2f", v*1.048576/1000}')
        R_MEM_UNIT="GB/s"
        [[ -n "$R_MEM_READ" ]] && mem_gbs_row "Read" "$R_MEM_READ" "$C_CYAN"
        [[ -n "$R_MEM_WRITE" ]] && mem_gbs_row "Write" "$R_MEM_WRITE" "$C_ACCENT"
        [[ -z "$R_MEM_READ$R_MEM_WRITE" ]] &&
            printf '  %ssysbench failed to report bandwidth.%s\n' "$C_BAD" "$RST"
    elif compile_probe; then
        R_MEM_ENGINE="native"
        R_MEM_UNIT="GB/s"
        printf '  %s(engine: compiled native probe)%s\n' "$DIM" "$RST"
        local mb out
        mb=$(probe_mem_mb)
        spin_start "Measuring bandwidth (${mb} MiB buffer)..."
        out=$("$PROBE_BIN" mem 1 1 "$mb" 2>/dev/null)
        spin_stop
        R_MEM_READ=$(awk '/^MEM_READ/ {print $2}' <<<"$out")
        R_MEM_COPY=$(awk '/^MEM_COPY/ {print $2}' <<<"$out")
        R_MEM_WRITE=$(awk '/^MEM_WRITE/ {print $2}' <<<"$out")
        if [[ -n "$R_MEM_READ$R_MEM_COPY$R_MEM_WRITE" ]]; then
            [[ -n "$R_MEM_READ" ]] && mem_gbs_row "Read" "$R_MEM_READ" "$C_CYAN"
            [[ -n "$R_MEM_COPY" ]] && mem_gbs_row "Copy" "$R_MEM_COPY" "$C_ACCENT2"
            [[ -n "$R_MEM_WRITE" ]] && mem_gbs_row "Write" "$R_MEM_WRITE" "$C_ACCENT"
        else
            printf '  %sMemory probe failed to report bandwidth.%s\n' "$C_BAD" "$RST"
        fi
    else
        R_MEM_ENGINE="none"
        printf '  %sNo memory benchmark available — install sysbench or a C compiler (gcc/clang).%s\n' "$DIM" "$RST"
    fi
}

# ────────────────────────────── network benchmark ────────────────────────────

R_NET_DOWN="" R_NET_UP="" R_LAT_RESULTS=()

lat_color() { # ms → color
    awk -v m="$1" 'BEGIN {exit !(m < 30)}' && { printf '%s' "$C_OK"; return; }
    awk -v m="$1" 'BEGIN {exit !(m < 90)}' && { printf '%s' "$C_WARN"; return; }
    printf '%s' "$C_BAD"
}

bench_latency() {
    exists ping || return
    printf '  %s%-24s %10s %10s %7s%s\n' "$C_MUTE" "Endpoint" "Latency" "Jitter" "Loss" "$RST"
    local targets=(
        "1.1.1.1|Cloudflare (anycast)"
        "8.8.8.8|Google DNS (anycast)"
        "9.9.9.9|Quad9 (anycast)"
    )
    local count=5
    $QUICK && count=3
    local t host name out ms jit loss
    for t in "${targets[@]}"; do
        host=${t%%|*}; name=${t##*|}
        spin_start "$name"
        out=$(ping -c "$count" -W 2 "$host" 2>/dev/null)
        spin_stop
        ms=$(echo "$out" | awk -F'/' '/^(rtt|round-trip)/ {printf "%.1f", $5}')
        jit=$(echo "$out" | awk -F'/' '/^(rtt|round-trip)/ {printf "%.1f", $7}')
        loss=$(echo "$out" | awk '/packet loss/ {for (i=1; i<=NF; i++)
            if ($i ~ /%/) {gsub(/%.*/, "", $i); printf "%.0f", $i}}')
        if [[ -n "$ms" ]]; then
            local color lcolor
            color=$(lat_color "$ms")
            lcolor=$C_OK
            [[ "${loss:-0}" != "0" ]] && lcolor=$C_BAD
            R_LAT_RESULTS+=("$name:$ms:${jit:-0}:${loss:-0}")
            printf '  %s%-24s%s %s%7s ms%s %s%7s ms%s %s%5s%%%s  %s\n' \
                "$C_TEXT" "$name" "$RST" "$color" "$ms" "$RST" \
                "$C_MUTE" "${jit:-—}" "$RST" "$lcolor" "${loss:-0}" "$RST" \
                "$(meter "$(awk -v m="$ms" 'BEGIN {p=100-m/2; if (p<4) p=4; printf "%.0f", p}')" 16 "$color")"
        else
            printf '  %s%-24s%s %s   timeout%s\n' "$C_TEXT" "$name" "$RST" "$C_BAD" "$RST"
        fi
    done
}

# ───────────────────────────────── bufferbloat ───────────────────────────────
# ping under a saturating download vs. idle — latency growth under load is
# what makes a link feel slow regardless of Mbps

R_BB_IDLE="" R_BB_LOADED="" R_BB_DELTA=""

bench_bufferbloat() {
    exists ping || return
    exists curl || return
    local target="1.1.1.1"

    # idle baseline — reuse the Cloudflare row from the latency table if we have it
    local item
    for item in "${R_LAT_RESULTS[@]:-}"; do
        [[ "$item" == "Cloudflare (anycast):"* ]] &&
            R_BB_IDLE=$(echo "$item" | cut -d: -f2)
    done
    if [[ -z "$R_BB_IDLE" ]]; then
        spin_start "Bufferbloat — idle baseline..."
        R_BB_IDLE=$(ping -c 5 -W 2 "$target" 2>/dev/null |
            awk -F'/' '/^(rtt|round-trip)/ {printf "%.1f", $5}')
        spin_stop
    fi
    [[ -z "$R_BB_IDLE" ]] && return

    # saturate the downlink from two sources while sampling latency
    curl -s -o /dev/null -m 30 "https://speed.cloudflare.com/__down?bytes=1000000000" >/dev/null 2>&1 &
    local p1=$!
    curl -sL -o /dev/null -m 30 "https://nj-us-ping.vultr.com/vultr.com.100MB.bin" >/dev/null 2>&1 &
    local p2=$!
    sleep 2

    local n=10 i s samples=()
    $QUICK && n=6
    for ((i = 1; i <= n; i++)); do
        pbar $((i * 100 / n)) "Bufferbloat — latency under load $i/$n"
        s=$(ping -c 1 -W 2 "$target" 2>/dev/null | awk -F'time=' '/time=/ {printf "%.1f", $2+0}')
        [[ -n "$s" ]] && samples+=("$s")
    done
    pbar_done
    kill "$p1" "$p2" 2>/dev/null
    wait "$p1" "$p2" 2>/dev/null

    [[ ${#samples[@]} -eq 0 ]] && return
    R_BB_LOADED=$(printf '%s\n' "${samples[@]}" | awk '{s+=$1; c++} END {printf "%.1f", s/c}')
    R_BB_DELTA=$(awk -v l="$R_BB_LOADED" -v i="$R_BB_IDLE" 'BEGIN {printf "%.1f", l-i}')

    echo
    local dcolor=$C_OK
    awk -v d="$R_BB_DELTA" 'BEGIN {exit !(d >= 15)}' && dcolor=$C_WARN
    awk -v d="$R_BB_DELTA" 'BEGIN {exit !(d >= 100)}' && dcolor=$C_BAD
    printf '  %s%-24s%s %s%7s ms%s idle  %s%s%s  %s%s ms%s loaded  %s+%s ms bufferbloat%s\n' \
        "$C_MUTE" "Latency under load" "$RST" "$C_OK" "$R_BB_IDLE" "$RST" \
        "$C_MUTE" "$G_ARR" "$RST" "$(lat_color "$R_BB_LOADED")" "$R_BB_LOADED" "$RST" \
        "$dcolor" "$R_BB_DELTA" "$RST"
    printf '  %s%-24s%s %s%s%s\n' "$C_MUTE" "Load trace" "$RST" \
        "$C_CYAN" "$(spark "${samples[@]}")" "$RST"
}

curl_download_mbps() { # curl_download_mbps <url> <cap-seconds> → "mbps connect_ms" (empty on failure)
    local out size secs conn
    out=$(curl -sL -o /dev/null -m "$2" \
        -w '%{size_download} %{time_total} %{time_connect}' "$1" 2>/dev/null)
    size=$(echo "$out" | awk '{print $1}')
    secs=$(echo "$out" | awk '{print $2}')
    conn=$(echo "$out" | awk '{print $3}')
    # need at least 1 MB transferred to call it a valid measurement
    awk -v s="${size:-0}" 'BEGIN {exit !(s >= 1048576)}' || return 1
    awk -v s="$size" -v t="$secs" -v c="$conn" \
        'BEGIN {printf "%.1f %.1f", s*8/t/1000000, c*1000}'
}

bench_speed() {
    exists curl || { printf '  %scurl not found — skipping speed test.%s\n' "$C_BAD" "$RST"; return; }
    local dl_bytes=$((200 * 1000 * 1000)) up_mb=25 cap=40
    $QUICK && dl_bytes=$((50 * 1000 * 1000)) && up_mb=8 && cap=20

    spin_start "Download — Cloudflare edge ($((dl_bytes / 1000000)) MB)..."
    local dl try
    for try in 1 2; do
        dl=$(curl_download_mbps "https://speed.cloudflare.com/__down?bytes=${dl_bytes}" "$cap") && break
        dl=""
    done
    spin_stop
    [[ -n "$dl" ]] && R_NET_DOWN=$(echo "$dl" | awk '{print $1}')

    spin_start "Upload — Cloudflare edge (${up_mb} MB)..."
    local up_out up_size up_secs
    for try in 1 2; do
        up_out=$(dd if=/dev/zero bs=1048576 count="$up_mb" 2>/dev/null |
            curl -s -o /dev/null -m "$cap" -X POST --data-binary @- \
                -w '%{size_upload} %{time_total}' "https://speed.cloudflare.com/__up" 2>/dev/null)
        up_size=$(echo "$up_out" | awk '{print $1}')
        up_secs=$(echo "$up_out" | awk '{print $2}')
        awk -v s="${up_size:-0}" 'BEGIN {exit !(s >= 1048576)}' && break
        up_out=""
    done
    spin_stop
    [[ -n "$up_out" ]] && R_NET_UP=$(awk -v s="$up_size" -v t="$up_secs" \
        'BEGIN {printf "%.1f", s*8/t/1000000}')

    echo
    local pct
    if [[ -n "$R_NET_DOWN" ]]; then
        pct=$(awk -v v="$R_NET_DOWN" 'BEGIN {printf "%.0f", v/1000*100}')
        meter_row "Download" "$pct" "$C_OK" "$R_NET_DOWN" "Mbps" " $G_DN"
    else
        printf '  %s%-14s%s %s(test failed)%s\n' "$C_MUTE" "Download" "$RST" "$C_BAD" "$RST"
    fi
    if [[ -n "$R_NET_UP" ]]; then
        pct=$(awk -v v="$R_NET_UP" 'BEGIN {printf "%.0f", v/1000*100}')
        meter_row "Upload" "$pct" "$C_INFO" "$R_NET_UP" "Mbps" " $G_UP"
    else
        printf '  %s%-14s%s %s(test failed)%s\n' "$C_MUTE" "Upload" "$RST" "$C_BAD" "$RST"
    fi
}

# ─────────────────────────── global network testing ──────────────────────────
#
# Primary engine: the official Ookla speedtest CLI, installed on the fly into
# the scratch directory (same approach as bench.sh / nws.sh) — it saturates the
# link with parallel connections and measures download AND upload per location.
# Fallback engine: single-connection curl downloads (less accurate on
# high-latency paths, download only).

R_GLOBAL_RESULTS=()
R_GLOBAL_ENGINE=""
SPEEDTEST_BIN=""

install_speedtest() {
    [[ "$OS_KIND" != "linux" ]] && return 1
    local dir="$SCRATCH_DIR/speedtest-cli"
    [[ -x "$dir/speedtest" ]] && { SPEEDTEST_BIN="$dir/speedtest"; return 0; }
    local sys_bit=""
    case "$(uname -m)" in
        x86_64 | amd64) sys_bit="x86_64" ;;
        i386 | i686) sys_bit="i386" ;;
        aarch64 | arm64 | armv8*) sys_bit="aarch64" ;;
        armv7*) sys_bit="armhf" ;;
        armv6*) sys_bit="armel" ;;
        *) return 1 ;;
    esac
    spin_start "Fetching Ookla speedtest CLI (${sys_bit})..."
    local tgz="$SCRATCH_DIR/speedtest.tgz"
    local url1="https://install.speedtest.net/app/cli/ookla-speedtest-1.2.0-linux-${sys_bit}.tgz"
    local url2="https://dl.lamp.sh/files/ookla-speedtest-1.2.0-linux-${sys_bit}.tgz"
    if ! curl -sL -m 20 -o "$tgz" "$url1" 2>/dev/null; then
        curl -sL -m 20 -o "$tgz" "$url2" 2>/dev/null || { spin_stop; return 1; }
    fi
    mkdir -p "$dir"
    if ! tar zxf "$tgz" -C "$dir" 2>/dev/null || [[ ! -f "$dir/speedtest" ]]; then
        spin_stop
        rm -f "$tgz"
        return 1
    fi
    chmod +x "$dir/speedtest"
    rm -f "$tgz"
    spin_stop
    SPEEDTEST_BIN="$dir/speedtest"
}

ookla_row() { # ookla_row <server-id or ''> <name> <region>
    local id=$1 name=$2 region=$3
    local log="$SCRATCH_DIR/speedtest.log"
    spin_start "$name"
    if [[ -z "$id" ]]; then
        "$SPEEDTEST_BIN" --progress=no --accept-license --accept-gdpr >"$log" 2>&1
    else
        "$SPEEDTEST_BIN" --progress=no --server-id="$id" --accept-license --accept-gdpr >"$log" 2>&1
    fi
    spin_stop
    local ms dl ul
    ms=$(awk '/Latency/{printf "%.1f", $3; exit}' "$log")
    dl=$(awk '/Download/{printf "%.1f", $3; exit}' "$log")
    ul=$(awk '/Upload/{printf "%.1f", $3; exit}' "$log")
    if grep -q "Limit reached" "$log" 2>/dev/null; then
        printf '  %s%-18s %s%-9s%s %srate limited — retry in ~1h%s\n' \
            "$C_TEXT" "$name" "$C_MUTE" "$region" "$RST" "$C_BAD" "$RST"
        return 1
    fi
    if [[ -z "$ms" || -z "$dl" || -z "$ul" ]]; then
        printf '  %s%-18s %s%-9s%s %s     test failed%s\n' \
            "$C_TEXT" "$name" "$C_MUTE" "$region" "$RST" "$C_BAD" "$RST"
        return 1
    fi
    R_GLOBAL_RESULTS+=("$name:$ms:$dl:$ul")
    if [[ -z "$id" ]]; then
        R_NET_DOWN=$dl
        R_NET_UP=$ul
    fi
    local lcolor pct
    lcolor=$(lat_color "$ms")
    pct=$(awk -v v="$dl" 'BEGIN {printf "%.0f", v/1000*100}')
    printf '  %s%-18s%s %s%-9s%s %s%8s ms%s %s%9s%s %s %s%9s%s %s  %s\n' \
        "$C_TEXT" "$name" "$RST" "$C_MUTE" "$region" "$RST" \
        "$lcolor" "$ms" "$RST" "$BOLD$C_TEXT" "$dl" "$RST" "$G_DN" \
        "$C_INFO" "$ul" "$RST" "$G_UP" "$(meter "$pct" 12 "$C_ACCENT")"
}

bench_global_ookla() {
    R_GLOBAL_ENGINE="ookla"
    section "Global network" "Ookla speedtest, Mbps"
    # server IDs from teddysun's bench.sh (maintained upstream)
    local servers=(
        "|Nearest|-"
        "7190|Los Angeles, US|America"
        "22288|Dallas, US|America"
        "64420|Montreal, CA|America"
        "61933|Paris, FR|Europe"
        "41423|Amsterdam, NL|Europe"
        "13623|Singapore, SG|Asia"
        "32155|Hong Kong, HK|Asia"
        "48463|Tokyo, JP|Asia"
    )
    if $REDUCE_NET || $QUICK; then
        servers=(
            "|Nearest|-"
            "22288|Dallas, US|America"
            "61933|Paris, FR|Europe"
            "13623|Singapore, SG|Asia"
        )
    fi
    printf '  %s%-18s %-9s %11s %11s %11s%s\n' "$C_MUTE" \
        "Location" "Region" "Latency" "Download" "Upload" "$RST"
    local s
    for s in "${servers[@]}"; do
        ookla_row "$(echo "$s" | cut -d'|' -f1)" \
            "$(echo "$s" | cut -d'|' -f2)" \
            "$(echo "$s" | cut -d'|' -f3)"
    done
}

# ── iperf3: real network path, not a CDN edge ────────────────────────────────
# iperf3 shows the actual network to each provider (unlike a speedtest CDN),
# and reports which network/provider is being reached. Static binary + server
# list are the ones the yabs project maintains.
IPERF_BIN=""

install_iperf3() {
    exists iperf3 && { IPERF_BIN="iperf3"; return 0; }
    [[ "$OS_KIND" != "linux" ]] && return 1
    exists curl || return 1
    local arch_tag=""
    case "$(uname -m)" in
        x86_64 | amd64) arch_tag="x64" ;;
        i?86) arch_tag="x86" ;;
        aarch64 | arm64) arch_tag="aarch64" ;;
        arm*) arch_tag="arm" ;;
        *) return 1 ;;
    esac
    local bin="$SCRATCH_DIR/iperf3"
    spin_start "Fetching static iperf3 binary (${arch_tag})..."
    curl -sL -m 30 --retry 2 -o "$bin" \
        "https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/iperf/iperf3_${arch_tag}" 2>/dev/null
    chmod +x "$bin" 2>/dev/null
    spin_stop
    "$bin" --version >/dev/null 2>&1 || { rm -f "$bin"; return 1; }
    IPERF_BIN="$bin"
}

fmt_netspeed() { # Mbps → "9.42 Gbit/s" or "812 Mbit/s"
    awk -v m="${1:-0}" 'BEGIN {
        if (m >= 1000) printf "%.2f Gbit/s", m/1000
        else printf "%.0f Mbit/s", m }'
}

iperf_speed() { # iperf_speed <host> <port-range> <reverse: r|''> → Mbps (empty on fail)
    local host=$1 range=$2 rev=$3
    local lo=${range%-*} hi=${range#*-} p n=0 out val unit
    local -a args
    for ((p = lo; p <= hi && n < 3; p++, n++)); do
        args=(-c "$host" -p "$p" -P 8 -t 5 --connect-timeout 3000)
        [[ "$rev" == r ]] && args+=(-R)
        out=$(timeout 25 "$IPERF_BIN" "${args[@]}" 2>/dev/null)
        [[ "$out" == *receiver* && "$out" != *error* ]] || continue
        read -r val unit < <(awk '/SUM/ && /receiver/ {print $(NF-2), $(NF-1)}' <<<"$out" | tail -1)
        [[ -z "$val" ]] && continue
        case "$unit" in
            Gbits/sec) awk -v v="$val" 'BEGIN {printf "%.0f", v*1000}' ;;
            Kbits/sec) awk -v v="$val" 'BEGIN {printf "%.0f", v/1000}' ;;
            *)         awk -v v="$val" 'BEGIN {printf "%.0f", v}' ;;
        esac
        return 0
    done
    return 1
}

iperf_row() { # iperf_row <host> <port-range> <provider> <location>
    local host=$1 range=$2 prov=$3 loc=$4 dl ul
    spin_start "$loc ($prov)"
    ul=$(iperf_speed "$host" "$range" "") || ul=""
    dl=$(iperf_speed "$host" "$range" r) || dl=""
    spin_stop
    if [[ -z "$dl$ul" ]]; then
        printf '  %s%-20s%s %s%-11s%s %sunreachable%s\n' \
            "$C_TEXT" "$loc" "$RST" "$C_MUTE" "$prov" "$RST" "$C_BAD" "$RST"
        return 1
    fi
    R_GLOBAL_RESULTS+=("$loc:-:${dl:-0}:${ul:-0}")
    [[ -n "$dl" ]] && R_NET_DOWN=$(awk -v a="${R_NET_DOWN:-0}" -v b="$dl" 'BEGIN {print (b>a)?b:a}')
    [[ -n "$ul" ]] && R_NET_UP=$(awk -v a="${R_NET_UP:-0}" -v b="$ul" 'BEGIN {print (b>a)?b:a}')
    local pct
    pct=$(awk -v v="${dl:-0}" 'BEGIN {printf "%.0f", v/10000*100}')
    printf '  %s%-20s%s %s%-11s%s %s%12s%s %s %s%12s%s %s  %s\n' \
        "$C_TEXT" "$loc" "$RST" "$C_MUTE" "$prov" "$RST" \
        "$BOLD$C_TEXT" "$(fmt_netspeed "${dl:-0}")" "$RST" "$G_DN" \
        "$C_INFO" "$(fmt_netspeed "${ul:-0}")" "$RST" "$G_UP" "$(meter "$pct" 10 "$C_ACCENT")"
}

bench_global_iperf() {
    R_GLOBAL_ENGINE="iperf3"
    section "Global network" "iperf3 · parallel streams to each provider"
    local servers=(
        "lon.speedtest.clouvider.net|5200-5209|Clouvider|London, UK"
        "iperf-ams-nl.eranium.net|5201-5210|Eranium|Amsterdam, NL"
        "speedtest.uztelecom.uz|5200-5209|Uztelecom|Tashkent, UZ"
        "speedtest.sin1.sg.leaseweb.net|5201-5210|Leaseweb|Singapore, SG"
        "la.speedtest.clouvider.net|5200-5209|Clouvider|Los Angeles, US"
        "speedtest.nyc1.us.leaseweb.net|5201-5210|Leaseweb|NYC, US"
        "speedtest.sao1.edgoo.net|9204-9240|Edgoo|Sao Paulo, BR"
    )
    if $REDUCE_NET || $QUICK; then
        servers=(
            "lon.speedtest.clouvider.net|5200-5209|Clouvider|London, UK"
            "speedtest.sin1.sg.leaseweb.net|5201-5210|Leaseweb|Singapore, SG"
            "speedtest.nyc1.us.leaseweb.net|5201-5210|Leaseweb|NYC, US"
        )
    fi
    printf '  %s%-20s %-11s %12s %12s%s\n' "$C_MUTE" "Location" "Provider" "Download" "Upload" "$RST"
    local s host range prov loc
    for s in "${servers[@]}"; do
        IFS='|' read -r host range prov loc <<<"$s"
        iperf_row "$host" "$range" "$prov" "$loc"
    done
}

bench_global_curl() {
    R_GLOBAL_ENGINE="curl"
    section "Global network" "curl fallback, download only"
    printf '  %s(Ookla speedtest CLI unavailable — single-connection curl;%s\n' "$DIM" "$RST"
    printf '  %s high-latency routes will read low)%s\n' "$DIM" "$RST"
    local endpoints=(
        "New York, US|America|https://nj-us-ping.vultr.com/vultr.com.100MB.bin"
        "Los Angeles, US|America|https://lax-ca-us-ping.vultr.com/vultr.com.100MB.bin"
        "London, UK|Europe|https://lon-gb-ping.vultr.com/vultr.com.100MB.bin"
        "Frankfurt, DE|Europe|https://fra-de-ping.vultr.com/vultr.com.100MB.bin"
        "Singapore, SG|Asia|https://sgp-ping.vultr.com/vultr.com.100MB.bin"
        "Tokyo, JP|Asia|https://hnd-jp-ping.vultr.com/vultr.com.100MB.bin"
        "Sydney, AU|Oceania|https://syd-au-ping.vultr.com/vultr.com.100MB.bin"
    )
    if $REDUCE_NET; then
        endpoints=(
            "New York, US|America|https://nj-us-ping.vultr.com/vultr.com.100MB.bin"
            "Frankfurt, DE|Europe|https://fra-de-ping.vultr.com/vultr.com.100MB.bin"
            "Singapore, SG|Asia|https://sgp-ping.vultr.com/vultr.com.100MB.bin"
        )
    fi
    local cap=10
    $QUICK && cap=5
    printf '  %s%-18s %-9s %11s %14s%s\n' "$C_MUTE" "Location" "Region" "Latency" "Download" "$RST"
    local e name region url result mbps ms
    for e in "${endpoints[@]}"; do
        name=${e%%|*}
        region=$(echo "$e" | cut -d'|' -f2)
        url=${e##*|}
        spin_start "$name"
        result=$(curl_download_mbps "$url" "$cap") || result=""
        spin_stop
        if [[ -z "$result" ]]; then
            printf '  %s%-18s %s%-9s%s %s     unreachable%s\n' \
                "$C_TEXT" "$name" "$C_MUTE" "$region" "$RST" "$C_BAD" "$RST"
            continue
        fi
        mbps=$(echo "$result" | awk '{print $1}')
        ms=$(echo "$result" | awk '{print $2}')
        R_GLOBAL_RESULTS+=("$name:$ms:$mbps:")
        local lcolor pct
        lcolor=$(lat_color "$ms")
        pct=$(awk -v v="$mbps" 'BEGIN {printf "%.0f", v/1000*100}')
        printf '  %s%-18s%s %s%-9s%s %s%8s ms%s %s%9s Mbps%s  %s\n' \
            "$C_TEXT" "$name" "$RST" "$C_MUTE" "$region" "$RST" \
            "$lcolor" "$ms" "$RST" "$BOLD$C_TEXT" "$mbps" "$RST" \
            "$(meter "$pct" 18 "$C_ACCENT")"
    done
}

bench_net() {
    section "Network latency"
    bench_latency
    bench_bufferbloat
    # iperf3 (real network path, both directions) → Ookla → curl fallback
    if install_iperf3; then
        bench_global_iperf
    elif install_speedtest; then
        bench_global_ookla
    else
        section "Network speed" "speed.cloudflare.com"
        bench_speed
        bench_global_curl
    fi
}

# ─────────────────────────────── geekbench 7 ─────────────────────────────────

R_GB_SINGLE="" R_GB_MULTI="" R_GB_URL="" R_GB_VER=""

bench_geekbench() {
    [[ "$OS_KIND" != "linux" ]] && return
    exists curl || return

    # Geekbench's RAM appetite grows with each major version. Pick the newest
    # one this box can actually complete: GB7 needs ~4 GiB, GB6 ~2 GiB, GB4 less.
    local arm=false
    case "$(uname -m)" in
        x86_64 | amd64) ;;
        aarch64 | arm64) arm=true ;;
        *)
            section "Geekbench"
            printf '  %sGeekbench requires a 64-bit x86 or ARM system — skipping.%s\n' \
                "$C_MUTE" "$RST"
            return ;;
    esac

    local ver cmd url ram=${R_RAM_MB:-0}
    if ((ram >= 4096)); then
        ver=7 cmd=geekbench7
        $arm && url="https://cdn.geekbench.com/Geekbench-7.0.0-LinuxARMPreview.tar.gz" \
             || url="https://cdn.geekbench.com/Geekbench-7.0.0-Linux.tar.gz"
    elif ((ram >= 2048)); then
        ver=6 cmd=geekbench6
        $arm && url="https://cdn.geekbench.com/Geekbench-6.5.0-LinuxARMPreview.tar.gz" \
             || url="https://cdn.geekbench.com/Geekbench-6.5.0-Linux.tar.gz"
    else
        # GB4 is x86-only; on ARM there is no low-RAM option, so try GB6 anyway
        if $arm; then
            ver=6 cmd=geekbench6
            url="https://cdn.geekbench.com/Geekbench-6.5.0-LinuxARMPreview.tar.gz"
        else
            ver=4 cmd=geekbench4
            url="https://cdn.geekbench.com/Geekbench-4.4.4-Linux.tar.gz"
        fi
    fi
    R_GB_VER=$ver
    section "Geekbench $ver" "chosen for ${ram} MiB RAM $G_SEP takes a few minutes"

    local gb_cmd=""
    if command -v "$cmd" >/dev/null 2>&1; then
        gb_cmd="$cmd"
    else
        local gb_dir="$SCRATCH_DIR/geekbench$ver"
        mkdir -p "$gb_dir"
        spin_start "Downloading Geekbench $ver..."
        if ! curl -s -m 120 "$url" | tar xz --strip-components=1 -C "$gb_dir" 2>/dev/null ||
            [[ ! -f "$gb_dir/$cmd" ]]; then
            spin_stop
            printf '  %sGeekbench %s download failed — skipping.%s\n' "$C_BAD" "$ver" "$RST"
            return
        fi
        spin_stop
        gb_cmd="$gb_dir/$cmd"
    fi

    # unlock if a license file sits next to the script
    [[ -f "geekbench.license" ]] &&
        "$gb_cmd" --unlock "$(cat geekbench.license)" >/dev/null 2>&1

    pulse_start "Running Geekbench $ver"
    R_GB_URL=$("$gb_cmd" --upload 2>/dev/null | grep -o 'https://browser.geekbench.com[^ ]*' | head -1)
    spin_stop
    if [[ -z "$R_GB_URL" ]]; then
        printf '  %sGeekbench %s run failed (not enough free RAM, or no IPv4).%s\n' "$C_BAD" "$ver" "$RST"
        return
    fi

    # scores live on the public results page, not in the CLI output. GB4 wraps
    # them in <span class='score'>, GB5/6/7 in <div class='score'>. Give the
    # page a few seconds to publish, then take the first (single) and last
    # (multi) score. This is the parser the yabs project uses.
    sleep 8
    local pat="div class='score'"
    [[ "$ver" == 4 ]] && pat="span class='score'"
    local scores
    scores=$(curl -s -m 20 "$R_GB_URL" | grep "$pat")
    R_GB_SINGLE=$(echo "$scores" | awk -v FS='(>|<)' '{print $3}' | head -n1)
    R_GB_MULTI=$(echo "$scores" | awk -v FS='(>|<)' '{print $3}' | tail -n1)
    # keep only clean integers
    [[ "$R_GB_SINGLE" =~ ^[0-9]+$ ]] || R_GB_SINGLE=""
    [[ "$R_GB_MULTI" =~ ^[0-9]+$ ]] || R_GB_MULTI=""

    if [[ -n "$R_GB_SINGLE" && -n "$R_GB_MULTI" ]]; then
        local pct1 pctN
        pct1=$(awk -v v="$R_GB_SINGLE" 'BEGIN {printf "%.0f", v/3000*100}')
        pctN=$(awk -v v="$R_GB_MULTI" 'BEGIN {printf "%.0f", v/16000*100}')
        meter_row "Single-core" "$pct1" "$C_CYAN" "$R_GB_SINGLE" "pts"
        meter_row "Multi-core" "$pctN" "$C_ACCENT" "$R_GB_MULTI" "pts"
    else
        printf '  %sScores are on the results page (parsing was blocked).%s\n' "$DIM" "$RST"
    fi
    printf '  %s%-14s%s %s%s%s\n' "$C_MUTE" "Full results" "$RST" "$C_INFO" "$R_GB_URL" "$RST"
}

# ─────────────────────────────────── summary ─────────────────────────────────

print_summary() {
    section "Summary"
    local t_end elapsed
    t_end=$(date +%s)
    elapsed=$((t_end - START_TIME))
    local cpu_hi=${R_CPU_MULTI:-$R_CPU_SINGLE}
    [[ -n "$cpu_hi" ]] && row "CPU" "$BOLD$C_TEXT${cpu_hi} ${R_CPU_UNIT}$RST ${C_MUTE}${R_CPU_ENGINE}${R_CPU_MULTI:+, all cores}$RST"
    [[ -n "$R_CPU_CV" ]] && row "CPU consistency" "$C_TEXT${G_PM}${R_CPU_CV}% variance$RST${R_CPU_STEAL:+ $C_MUTE$G_SEP$RST $C_TEXT${R_CPU_STEAL}% steal$RST}"
    [[ -n "$R_MEM_READ$R_MEM_WRITE" ]] && row "Memory bandwidth" "$BOLD$C_TEXT${R_MEM_READ:-$R_MEM_WRITE} ${R_MEM_UNIT}$RST ${C_MUTE}read, ${R_MEM_ENGINE}$RST"
    if [[ "$R_DISK_ENGINE" == "fio" && ${#R_FIO_RESULTS[@]} -gt 0 ]]; then
        local mid=${R_FIO_RESULTS[0]}
        row "Disk 4k rand R/W" "$BOLD$C_TEXT$(fmt_speed "$(echo "$mid" | cut -d: -f2)")$RST / $BOLD$C_TEXT$(fmt_speed "$(echo "$mid" | cut -d: -f3)")$RST"
    fi
    [[ -n "$R_DISK_SUSTAIN" ]] && row "Disk write (seq)" "$BOLD$C_TEXT$(fmt_speed "$R_DISK_SUSTAIN")$RST ${C_MUTE}sustained ${G_SEP} $(fmt_speed "${R_DISK_BURST:-0}") cache peak$RST"
    [[ -n "$R_BB_DELTA" ]] && row "Bufferbloat" "$C_TEXT+${R_BB_DELTA} ms$RST ${C_MUTE}latency under load$RST"
    [[ -n "$R_GB_SINGLE" ]] && row "Geekbench ${R_GB_VER:-}" "$BOLD$C_TEXT$R_GB_SINGLE$RST ${C_MUTE}single $G_SEP$RST $BOLD$C_TEXT$R_GB_MULTI$RST ${C_MUTE}multi$RST"
    [[ -n "$R_NET_DOWN" ]] && row "Network (best)" "$BOLD$C_TEXT$(fmt_netspeed "$R_NET_DOWN")$RST $G_DN  $BOLD$C_TEXT$(fmt_netspeed "${R_NET_UP:-0}")$RST $G_UP"
    if [[ ${#R_GLOBAL_RESULTS[@]} -gt 0 ]]; then
        local gdl=0 gul=0 gulcount=0 gcount=0 gitem uval
        for gitem in "${R_GLOBAL_RESULTS[@]}"; do
            gdl=$(awk -v s="$gdl" -v v="$(echo "$gitem" | cut -d: -f3)" 'BEGIN {print s+v}')
            uval=$(echo "$gitem" | cut -d: -f4)
            if [[ -n "$uval" ]]; then
                gul=$(awk -v s="$gul" -v v="$uval" 'BEGIN {print s+v}')
                gulcount=$((gulcount + 1))
            fi
            gcount=$((gcount + 1))
        done
        local gline
        gline="$BOLD$C_TEXT$(fmt_netspeed "$(awk -v s="$gdl" -v c="$gcount" 'BEGIN {printf "%.1f", s/c}')")$RST $G_DN"
        [[ "$gulcount" -gt 0 ]] && gline+="  $BOLD$C_TEXT$(fmt_netspeed "$(awk -v s="$gul" -v c="$gulcount" 'BEGIN {printf "%.1f", s/c}')")$RST $G_UP"
        row "Global average" "$gline ${C_MUTE}($gcount locations)$RST"
    fi
    row "Completed in" "$C_TEXT$((elapsed / 60))m $((elapsed % 60))s$RST"
    echo
    grad_hr
    printf '  %sbenchmark v%s %s %s%s\n' \
        "$DIM" "$BENCHMARK_VERSION" "$G_SEP" "$(date '+%Y-%m-%d %H:%M %Z')" "$RST"
}

# ─────────────────────────────────── json ────────────────────────────────────

emit_json() {
    local lat_json="" fio_json="" global_json="" first=true item
    for item in "${R_GLOBAL_RESULTS[@]:-}"; do
        [[ -z "$item" ]] && continue
        $first || global_json+=","
        first=false
        local g_lat g_ul
        g_lat=$(echo "$item" | cut -d: -f2)
        [[ "$g_lat" =~ ^[0-9.]+$ ]] || g_lat=null
        g_ul=$(echo "$item" | cut -d: -f4)
        global_json+="{\"location\":\"$(json_escape "$(echo "$item" | cut -d: -f1)")\",\"latency_ms\":${g_lat},\"download_mbps\":$(echo "$item" | cut -d: -f3),\"upload_mbps\":${g_ul:-null}}"
    done
    first=true
    for item in "${R_LAT_RESULTS[@]:-}"; do
        [[ -z "$item" ]] && continue
        $first || lat_json+=","
        first=false
        lat_json+="{\"target\":\"$(json_escape "$(echo "$item" | cut -d: -f1)")\",\"ms\":$(echo "$item" | cut -d: -f2),\"jitter_ms\":$(echo "$item" | cut -d: -f3),\"loss_pct\":$(echo "$item" | cut -d: -f4)}"
    done
    first=true
    for item in "${R_FIO_RESULTS[@]:-}"; do
        [[ -z "$item" ]] && continue
        $first || fio_json+=","
        first=false
        fio_json+="{\"bs\":\"$(echo "$item" | cut -d: -f1)\",\"read_mbs\":$(echo "$item" | cut -d: -f2),\"write_mbs\":$(echo "$item" | cut -d: -f3)}"
    done
    cat <<EOF
{
  "version": "$BENCHMARK_VERSION",
  "timestamp": "$(date -u '+%Y-%m-%dT%H:%M:%SZ')",
  "system": {
    "cpu": "$(json_escape "$R_CPU_MODEL")",
    "cores": ${R_CPU_CORES:-null},
    "os": "$(json_escape "$R_OS")",
    "kernel": "$(json_escape "$R_KERNEL")",
    "arch": "$(json_escape "$R_ARCH")",
    "virtualization": "$(json_escape "$R_VIRT")",
    "aes_ni": $R_AES,
    "isa_extensions": "$(json_escape "$R_CPU_ISA")"
  },
  "network_info": {
    "ipv4": $R_IPV4,
    "ipv6": $R_IPV6,
    "provider": "$(json_escape "$R_ISP")",
    "location": "$(json_escape "$R_LOC")"
  },
  "cpu_bench": {
    "engine": "${R_CPU_ENGINE:-skipped}",
    "unit": "$(json_escape "$R_CPU_UNIT")",
    "single_core": ${R_CPU_SINGLE:-null},
    "multi_core": ${R_CPU_MULTI:-null},
    "burst_variance_pct": ${R_CPU_CV:-null},
    "steal_pct": ${R_CPU_STEAL:-null}
  },
  "memory_bench": {
    "engine": "${R_MEM_ENGINE:-skipped}",
    "unit": "$(json_escape "$R_MEM_UNIT")",
    "read": ${R_MEM_READ:-null},
    "copy": ${R_MEM_COPY:-null},
    "write": ${R_MEM_WRITE:-null}
  },
  "disk_bench": {
    "engine": "${R_DISK_ENGINE:-skipped}",
    "burst_write_mbs": ${R_DISK_BURST:-null},
    "sustained_write_mbs": ${R_DISK_SUSTAIN:-null},
    "fio": [${fio_json}]
  },
  "bufferbloat": {
    "idle_ms": ${R_BB_IDLE:-null},
    "loaded_ms": ${R_BB_LOADED:-null},
    "delta_ms": ${R_BB_DELTA:-null}
  },
  "geekbench": {
    "version": ${R_GB_VER:-null},
    "single_core": ${R_GB_SINGLE:-null},
    "multi_core": ${R_GB_MULTI:-null},
    "url": "$(json_escape "$R_GB_URL")"
  },
  "network_bench": {
    "engine": "${R_GLOBAL_ENGINE:-skipped}",
    "best_download_mbps": ${R_NET_DOWN:-null},
    "best_upload_mbps": ${R_NET_UP:-null},
    "latency": [${lat_json}],
    "global": [${global_json}]
  }
}
EOF
}

# ──────────────────────────────────── main ───────────────────────────────────

on_winch() {
    local _r c
    read -r _r c <<<"$(hud_size)"
    [[ "$c" =~ ^[0-9]+$ ]] || return 0
    TERM_WIDTH=$c
    ((TERM_WIDTH < 60)) && TERM_WIDTH=60
    ((TERM_WIDTH > 100)) && TERM_WIDTH=100
    BOX_W=$((TERM_WIDTH - 2))
}
trap on_winch WINCH

SCRATCH_DIR=$(mktemp -d "${TMPDIR:-/tmp}/benchmark.XXXXXX" 2>/dev/null || echo "${TMPDIR:-/tmp}/benchmark.$$")
mkdir -p "$SCRATCH_DIR"

collect_sysinfo
hud_start
banner
print_sysinfo
if ! $SKIP_NET; then
    collect_netinfo
    print_netinfo
fi
$SKIP_CPU || bench_cpu
$SKIP_CPU || bench_mem
$SKIP_DISK || bench_disk
$SKIP_NET || bench_net
$SKIP_GB || bench_geekbench
print_summary

if $JSON_PRINT; then
    echo
    emit_json
fi
if [[ -n "$JSON_FILE" ]]; then
    emit_json >"$JSON_FILE"
    printf '  %sJSON results written to %s%s\n' "$DIM" "$JSON_FILE" "$RST"
fi

set_title "benchmark · complete"
rm -rf "$SCRATCH_DIR" 2>/dev/null
exit 0
