/**
 * output-style/ansi.mjs — C22 primitive layer.
 *
 * Pure-Node ANSI escape helpers. No external dependencies. All rendering is
 * gated through `supportsColor({ stream, env })` so callers can pass explicit
 * streams/env stubs in tests — we never mutate process globals.
 *
 * See docs/frameworks/spec-gaps.md#c22 and packages/framework/docs/output-style.md.
 */
const RESET = '\x1b[0m';
/**
 * SGR codes used by the helper set. Exported so the test suite can assert on
 * the exact escape sequences without hard-coding magic numbers.
 */
export const SGR = Object.freeze({
    bold: '\x1b[1m',
    dim: '\x1b[2m',
    italic: '\x1b[3m',
    underline: '\x1b[4m',
    reset: RESET,
    // 8-color palette — 30-37 foreground. 256-color / truecolor would give us
    // nicer accents but breaks in plain xterms and stack-traces harder to read.
    red: '\x1b[31m',
    green: '\x1b[32m',
    yellow: '\x1b[33m',
    blue: '\x1b[34m',
    magenta: '\x1b[35m',
    cyan: '\x1b[36m',
    gray: '\x1b[90m',
});
/**
 * Does the runtime support ANSI color on this stream?
 *
 *   - NO_COLOR (any non-empty value) → always false (https://no-color.org/).
 *   - FORCE_COLOR (any non-empty value other than "0") → always true.
 *   - Otherwise: true iff `stream.isTTY`.
 *
 * Pure function; takes explicit stream + env so tests can stub without
 * touching process globals.
 */
export function supportsColor({ stream, env } = {}) {
    const e = env || process.env;
    const noColor = e.NO_COLOR;
    if (noColor !== undefined && noColor !== '')
        return false;
    const force = e.FORCE_COLOR;
    if (force !== undefined && force !== '' && force !== '0')
        return true;
    const s = stream || process.stdout;
    return Boolean(s && s.isTTY);
}
/**
 * Wrap `text` in one or more SGR codes. When `color` is false, returns `text`
 * unchanged — this keeps snapshot tests deterministic and lets consumers pipe
 * into `jq` without stripping escapes.
 *
 * Accepts either a single code string or an array of codes (concatenated).
 */
export function style(text, codes, { color = true } = {}) {
    if (!color)
        return String(text);
    const open = Array.isArray(codes) ? codes.join('') : String(codes || '');
    if (!open)
        return String(text);
    return `${open}${text}${RESET}`;
}
/** Convenience wrappers — all take `(text, { color })`. */
export function bold(text, opts) {
    return style(text, SGR.bold, opts);
}
export function dim(text, opts) {
    return style(text, SGR.dim, opts);
}
export function red(text, opts) {
    return style(text, SGR.red, opts);
}
export function green(text, opts) {
    return style(text, SGR.green, opts);
}
export function yellow(text, opts) {
    return style(text, SGR.yellow, opts);
}
export function cyan(text, opts) {
    return style(text, SGR.cyan, opts);
}
export function gray(text, opts) {
    return style(text, SGR.gray, opts);
}
//# sourceMappingURL=ansi.mjs.map