import { Line, LineSegment, Run } from '../../../../contracts/src/index.js';
type UnderlinePaintRun = {
    underline?: {
        style?: string;
        color?: string;
    } | null;
    fontSize?: number;
    color?: string;
};
type UnderlineSource = Run | UnderlinePaintRun;
export declare const underlineStyleForRun: (run: UnderlineSource) => string | undefined;
export declare const canPaintUnderlineAsBorder: (run: UnderlineSource) => boolean;
/**
 * Whether the line-level underline overlay may own this run's underline (SD-3330).
 *
 * Scoped to the styles a single CSS `border-top` reproduces faithfully: `single`, `double`,
 * `dotted`, `dashed`. Everything else stays on its existing path on purpose, so the overlay
 * never silently flattens a distinct style into solid inside a "continuous" line:
 * - `none` paints nothing (rejected by canPaintUnderlineAsBorder);
 * - `wave`, `thick`, and the OOXML heavy/compound spellings (`dotDash`, `dashLongHeavy`, ...) a
 *   border-top cannot draw - they keep their current (degraded) per-run rendering.
 *
 * `words` is NOT solved end-to-end here. canPaintUnderlineAsBorder rejects a literal `words`, but
 * the v1 adapter's normalizeUnderlineStyle collapses OOXML `words` to `single` BEFORE paint, so a
 * `words` underline reaches this layer as `single` and gets overlaid - it does not reproduce Word's
 * "underline the words, not the tab whitespace". Fixing that needs an importer/adapter change and is
 * out of scope for the seam fix; the guard here is only defensive for a producer that passes `words` raw.
 *
 * Color is a separate axis: this gate is style-only, and underlineBorderForRun does not resolve
 * theme/`auto` underline colors (it uses the literal color string, as the prior border path did),
 * so theme-color fidelity is out of scope here too.
 *
 * Mixed lines stay per-run: a single-underlined tab can be overlaid while an adjacent wavy run
 * keeps its native text-decoration.
 */
export declare const canPaintUnderlineOverlay: (run: UnderlineSource) => boolean;
export declare const underlineBorderForRun: (run: UnderlineSource) => string | undefined;
export declare const renderInlineTabRun: (run: Extract<Run, {
    kind: "tab";
}>, line: Line, doc: Document, layoutEpoch: number, styleId?: string, paintUnderline?: boolean) => HTMLElement;
export declare const renderPositionedTabRun: (run: Extract<Run, {
    kind: "tab";
}>, line: Line, doc: Document, layoutEpoch: number, tabStartX: number, indentOffset: number, immediateNextSegment?: LineSegment, styleId?: string, paintUnderline?: boolean) => {
    element: HTMLElement;
    tabEndX: number;
    actualTabWidth: number;
};
/**
 * Distance, in pixels from the top of the line box, at which a tab's underline
 * (border-bottom) should be drawn so it lines up with the `text-decoration`
 * underline of adjacent text runs.
 *
 * The line box places the baseline at `half-leading + ascent` from its top
 * (the remaining `half-leading + descent` sits below). `text-decoration`
 * underlines render slightly below the baseline, so we add a small gap that
 * scales with font size (capped by the descent). This is geometry derived from
 * the resolved line metrics. The painter never measures the DOM (SD-2957).
 */
export declare const underlineOffsetFromLineTop: (line: Line) => number;
export {};
//# sourceMappingURL=tab-run.d.ts.map