/* ============================================================================
 * bitting.css
 *
 * Visual design tokens + utility classes for the Bitting package.
 *
 * Consumers link this once from their host page:
 *   <link rel="stylesheet" href="_content/Bitting/bitting.css" />
 *
 * Override the CSS variables in your own :root to re-skin without forking:
 *   :root {
 *       --bitting-md: clamp(0.875rem, 0.831rem + 0.1878vw, 1rem);
 *         (interpolates 0.875rem -> 1rem over a 375px -> 1440px viewport. The
 *          rem bounds and intercept keep browser zoom and a raised default
 *          font size effective; the vw slope supplies fluid scaling.)
 *       --bitting-positive: #2ecc71;
 *       --bitting-negative: #e74c3c;
 *       (and so on for any token declared in :root below)
 *   }
 *
 * Accessibility note: every default text-and-fill palette role clears WCAG AA
 * (4.5:1) against each light surface shipped below. When you re-theme via
 * --bitting-*, verify the same role/surface combinations in the host palette.
 * ============================================================================ */

:root {
    /* -- Size scale --------------------------------------------------------
     * Phi-stepped scale anchored on --bitting-md. Everything else (sizes, icon
     * sizes, line heights) derives from it via calc(). Override md to scale
     * the whole design system.
     */
    --bitting-phi: calc(1.6180339887 * 0.8);

    /* The preferred term interpolates 0.875rem -> 1rem across a 375px -> 1440px
     * viewport, which is the range the product is actually read at. The
     * earlier `1vw` reached 14px only at a 1400px viewport and 16px at
     * 1600px, so every phone, tablet, and laptop resolved to a flat 14px and
     * the scale was fluid in name only. Endpoints are unchanged; only the
     * band they interpolate over moved. Slope is 2px / 1065px = 0.1878vw.
     *
     * Both fixed terms are rem, so the ruler answers to the reader as well as
     * to the viewport. It did not: the terms were px, and doubling the browser
     * font size moved no role by a pixel -- a resize failure no automated scan
     * can see, because the page is perfectly styled at the wrong size.
     *
     * rem is only safe here because the host anchors `body`, not `html`. Sizing
     * html from this token would make it resolve against a root font-size it
     * had just set; that circularity is what the px terms were working around.
     * If you move the anchor back onto html, this must become px again. */
    --bitting-md: clamp(0.875rem, 0.831rem + 0.1878vw, 1rem);

    /* Paper is another state of the same scale, not a second component theme.
       Letter width and A4 height define one stable landscape layout box so
       preparation on screen and the browser's print pipeline agree. */
    --bitting-paper-md: 12pt;
    --bitting-paper-min-text: 6pt;
    --bitting-paper-margin-block: 14mm;
    --bitting-paper-margin-inline: 12mm;
    --bitting-paper-box-width: 255mm;
    --bitting-paper-box-height: 182mm;
    --bitting-paper-rule: color-mix(in srgb, var(--bitting-secondary) 22%, transparent);
    --bitting-paper-fit-floor: 0.838;
    --bitting-print-label-printed: "Printed";
    --bitting-print-label-page: "Page";
    --bitting-print-label-of: "of";

    --bitting-half-md: calc(var(--bitting-md) / 2);
    --bitting-qtr-md: calc(var(--bitting-md) / 4);

    --bitting-xs: calc(var(--bitting-md) / (var(--bitting-phi) * var(--bitting-phi)));
    --bitting-sm: calc(var(--bitting-md) / var(--bitting-phi));
    --bitting-lg: calc(var(--bitting-md) * var(--bitting-phi));
    --bitting-xl: calc(var(--bitting-md) * (var(--bitting-phi) * var(--bitting-phi)));

    /* One Extra-small semantic inset on every edge of an ordinary tile. Tile
       variants may opt out when their own composition owns the edge; headed
       tile call sites never select a raw scale step. */
    --bitting-tile-padding: var(--bitting-xs);
    --bitting-tile-aspect: auto;

    --bitting-icon-multiplier: 2;
    --bitting-icon-xs: calc(var(--bitting-xs) * var(--bitting-icon-multiplier));
    --bitting-icon-sm: calc(var(--bitting-sm) * var(--bitting-icon-multiplier));
    --bitting-icon-md: calc(var(--bitting-md) * var(--bitting-icon-multiplier));
    --bitting-icon-lg: calc(var(--bitting-lg) * var(--bitting-icon-multiplier));
    --bitting-icon-xl: calc(var(--bitting-xl) * var(--bitting-icon-multiplier));

    /* Weight of a data mark, and the diameter of a point marker, as fractions
     * of the text beside them. Mirrors ChartVisualMetrics.DataStrokeRatio and
     * MarkerRatio, which the charts computing geometry in C# read; these are
     * for components that size strokes through calc() instead.
     * DesignTokenDisciplineTests holds the two sides together. */
    --bitting-stroke-multiplier: 0.1875;
    /* The width of a Bitting chart content line — a trend line, a line-chart
       segment, a bubble outline, a sparkline. One width, taken off the system
       anchor rather than off each component's own step: the multiplier alone is
       a shared ratio, and a shared ratio is not a shared width unless every
       consumer feeds it the same base. A sparkline sized ExtraLarge and a chart
       trend line both "on the scale" drew 2.6x apart until this existed. */
    --bitting-chart-line-width: calc(var(--bitting-md) * var(--bitting-stroke-multiplier));
    --bitting-marker-multiplier: 0.3333333333;

    /* Chart grid lines and axis rules. Named so a client theme can re-point
     * chart chrome without editing chart internals — it was the literal
     * `lightgray` in three components, which no theme could reach. */
    --bitting-chart-grid: #d3d3d3;

    /* The halo on whichever chart mark the reader is on. Points at the text
     * role so it contrasts with the surface in either theme -- a fixed white
     * ring disappears the moment a client themes the chart light. */
    --bitting-chart-mark-focus: var(--bitting-secondary);

    /* -- Cartesian chart spacing ----------------------------------------- */
    --bitting-chart-entry-breadth: calc(var(--bitting-md) * 3);
    --bitting-dialog-max-width: calc(var(--bitting-md) * 36);
    --bitting-overlay-content-max-width: calc(var(--bitting-md) * 36);
    --bitting-viewport-width: 100vw;
    --bitting-viewport-height: 100dvh;
    --bitting-overlay-viewport-width: 90vw;
    --bitting-intrinsic-icon-size: 1em;
    --bitting-intrinsic-spinner-border: 0.15em;
    --bitting-visually-hidden-size: 1px;
    --bitting-visually-hidden-offset: -1px;

    /* -- Neutral background tint ----------------------------------------- */
    --bitting-muted-gray: rgba(233, 236, 239, 0.6);

    /* -- Bitting Map ------------------------------------------------------
     * Sequential data roles are deliberately separate from categorical chart
     * colors: the order is part of their meaning. Missing data is a neutral
     * role, not the first step of the ramp. Boundary and focus remain separate
     * channels so interaction never rewrites a country's bucket fill. */
    --bitting-data-lowest: color-mix(in srgb, var(--bitting-info) 18%, var(--bitting-surface));
    --bitting-data-low: color-mix(in srgb, var(--bitting-info) 38%, var(--bitting-surface));
    --bitting-data-middle: color-mix(in srgb, var(--bitting-info) 58%, var(--bitting-surface));
    --bitting-data-high: color-mix(in srgb, var(--bitting-info) 78%, var(--bitting-surface));
    --bitting-data-highest: var(--bitting-info);
    --bitting-data-missing: var(--bitting-light);
    --bitting-map-boundary: var(--bitting-surface);
    --bitting-map-overlay-surface: color-mix(in srgb, var(--bitting-surface) 92%, transparent);
    --bitting-map-empty-overlay-surface: color-mix(in srgb, var(--bitting-map-overlay-surface) 72%, transparent);
    --bitting-map-boundary-width: var(--bitting-border-width);
    --bitting-map-focus-stroke-width: calc(var(--bitting-focus-width) * 2);
    --bitting-map-height: calc(var(--bitting-md) * 28);
    --bitting-chart-tooltip-surface: var(--bitting-secondary);
    --bitting-chart-tooltip-text: var(--bitting-on-accent);
    --bitting-chart-tooltip-accent-width: var(--bitting-border-width);

    /* -- Named colour palette (consumed by BittingColors) ----------------
     * The named slots in the BittingColors static palette resolve to these.
     * Defaults are a neutral, self-contained set so components render out of
     * the box. Override any of them in your own :root to re-theme — e.g.
     *   :root { --bitting-primary: #6c5ce7; }
     */
    /* Defaults are the Unlocked Data brand wherever a role clears the text
       floor: primary is Intuitive, secondary and dark are Expert, light is
       Canvas. Every role paints text as well as fills, so the remaining roles
       sit at the brightest value in their UnlockedData hue family that still
       clears WCAG AA 4.5:1 on white, Canvas, Light, and the translucent table
       tint -- enforced by PaletteContrastTests. That floor is why success is a
       darker member of the Bespoke family (Bespoke itself is 2.7:1 on white)
       and why a warning cannot be pure amber (#ffc107 is only 1.9:1); the
       burnt orange below is as warm as the contract allows while staying
       separable from danger red. Consumers re-theme by overriding any token. */
    --bitting-primary:   #055f58;
    --bitting-secondary: #053741;
    --bitting-info:      #0b6db5;
    --bitting-warning:   #b64607;
    --bitting-success:   #357612;
    --bitting-danger:    #cc2823;
    --bitting-light:     #f1f0ec;
    --bitting-dark:      #053741;
    --bitting-gray:      #5c6f74;
    --bitting-muted:     var(--bitting-gray);
    --bitting-white:     #fff;
    --bitting-black:     #000;

    /* Graphic tier. The same four status hues, for marks: shapes whose
       geometry carries data, such as bars, lines, points, cells, and gauge
       arcs. WCAG 2.2 holds a mark to 3:1 against its surroundings rather than
       the 4.5:1 text needs, so each is tuned to the 3:1 limit on the
       lowest-contrast light surface, the tinted table row. Words, symbols, and
       labeled fills keep the text tokens above. BittingColor finds a mark's
       token by appending its GraphicTokenSuffix, and falls back to the text
       token when no graphic token exists. */
    --bitting-info-graphic:    #3c8dd6;
    --bitting-warning-graphic: #d66a3d;
    --bitting-success-graphic: #569936;
    --bitting-danger-graphic:  #f34e43;

    /* The strength of secondary in a track behind a mark, such as a gauge's
       range arc or the gap in a percentage bar, over the tile surface. Faint
       enough that every graphic token still clears 3:1 against the track. */
    --bitting-track-tint: 6%;
    /* Adaptive foreground/surface roles. Unlike the literal white/black
       foundations, these are safe for host themes to remap between light and
       dark schemes without changing component markup. */
    --bitting-on-accent: var(--bitting-light);
    /* Brand mark colours for BittingUnlockedDataLockup: the Expert-to-Intuitive
       pill with a Canvas glyph. Hosts remap these on dark surfaces; the
       component sets the Canvas-pill / Expert-glyph pairing for its Inverse
       variant. */
    --bitting-lockup-pill-start: #053741;
    --bitting-lockup-pill-end: #055f58;
    --bitting-lockup-glyph: #f1f0ec;
    --bitting-white-50:  rgba(255, 255, 255, 0.5);
    --bitting-black-50:  rgba(0, 0, 0, 0.5);
    --bitting-white-98:  rgba(255, 255, 255, 0.98);
    --bitting-white-85:  rgba(255, 255, 255, 0.85);
    --bitting-white-70:  rgba(255, 255, 255, 0.7);
    --bitting-white-45:  rgba(255, 255, 255, 0.45);
    --bitting-black-53:  rgba(0, 0, 0, 0.53);
    --bitting-black-35:  rgba(0, 0, 0, 0.35);
    --bitting-black-10:  rgba(0, 0, 0, 0.1);

    /* -- Surface, border, and elevation roles --------------------------- */
    --bitting-surface: var(--bitting-white);
    /* Brand Canvas, the Unlocked Data ground every pairing is approved on. */
    --bitting-canvas: #f1f0ec;
    --bitting-border-subtle: rgba(16, 24, 40, 0.08);
    --bitting-border-soft: rgba(16, 24, 40, 0.06);
    --bitting-shadow-soft: rgba(16, 24, 40, 0.10);
    --bitting-shadow: rgba(16, 24, 40, 0.25);
    --bitting-shadow-strong: rgba(16, 24, 40, 0.40);
    --bitting-muted-gray-80: rgba(233, 236, 239, 0.8);
    --bitting-muted-gray-40: rgba(233, 236, 239, 0.4);
    --bitting-scroll-fade: rgba(0, 0, 0, 0.05);
    --bitting-attention-80: rgba(255, 165, 0, 0.8);
    --bitting-attention-60: rgba(255, 165, 0, 0.6);
    --bitting-attention-40: rgba(255, 165, 0, 0.4);
    --bitting-attention-30: rgba(255, 165, 0, 0.3);
    --bitting-attention-20: rgba(255, 165, 0, 0.2);
    --bitting-border-width: max(1px, 0.0625rem);
    --bitting-border-width-strong: max(2px, 0.125rem);
    --bitting-focus-width: max(2px, 0.125rem);
    --bitting-focus-offset: max(2px, 0.125rem);
    --bitting-focus-ring: var(--bitting-primary);
    /* WCAG 2.2 (2.5.8) target-size floor: exactly the 24px the success
       criterion asks for. This is a *floor*, so an icon control whose glyph is
       larger still sizes to its content -- tying the floor itself to
       --bitting-icon-md instead pushed every text pill to 28-32px and made
       dense toolbars far chunkier than the criterion requires. */
    --bitting-target-min: 24px;
    --bitting-layer-sticky: 10;
    --bitting-layer-base: 0;
    --bitting-layer-content: 1;
    --bitting-layer-affordance: 2;
    --bitting-layer-raised: 50;
    --bitting-layer-dropdown: 1000;
    --bitting-layer-popover: 1100;
    --bitting-layer-tooltip: 1150;
    /* A modal takes the whole surface, so it sits above every transient layer.
       The backdrop sits directly beneath its own dialog. */
    --bitting-layer-modal-backdrop: 1200;
    --bitting-layer-modal: 1210;
    --bitting-content-max-width: 80rem;
    --bitting-readable-measure: 72ch;
    --bitting-grid-min-rainbow: 10.5rem;
    --bitting-grid-min-kpi: 13.125rem;
    --bitting-grid-min-two-column: 21.25rem;
    --bitting-grid-min-three-column: 16.25rem;
    --bitting-label-column-min: 6rem;
    --bitting-label-column-max: 11.25rem;

    /* -- Semantic colour tokens (consumed by BittingSemanticColor) -------
     * BittingSemanticColor.{Positive,Negative,Neutral,Muted} resolve to these.
     * Default to the palette slots above; override independently if you want
     * semantic colours to diverge from the named palette.
     */
    --bitting-positive: var(--bitting-success);
    --bitting-negative: var(--bitting-danger);
    --bitting-positive-graphic: var(--bitting-success-graphic);
    --bitting-negative-graphic: var(--bitting-danger-graphic);
    --bitting-neutral:  var(--bitting-secondary);

    /* -- Typography ------------------------------------------------------
     * Font sizes live on the phi scale above (xs..xl). These carry the rest
     * of the type system: one family, three weights, line-heights, and the
     * heading tracking. Apply the family to your host body so every component
     * inherits it. */
    /* DM Sans is named first but deliberately not shipped: the package stays
       self-contained and fetches nothing at runtime. Hosts that want it load it
       themselves (one Google Fonts link, or self-hosted @font-face); everyone
       else falls through to the system stack with no missing-font flash. */
    --bitting-font-family: "DM Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --bitting-font-weight: 400;
    --bitting-font-weight-medium: 500;
    --bitting-font-weight-bold: 700;
    --bitting-font-weight-heavy: 800;
    --bitting-line-height: 1.4;
    --bitting-line-height-tight: 1;
    --bitting-line-height-heading: 1.15;
    --bitting-line-height-relaxed: 1.55;
    --bitting-letter-spacing-tight: -0.02em;
    --bitting-letter-spacing-heading: -0.01em;
    --bitting-letter-spacing-normal: 0;

    /* -- Semantic text roles ----------------------------------------------
     * Roles add meaning, weight, rhythm, and tracking to the five-step scale.
     * They do not create a second size scale: their classes below select
     * xs..xl directly.
     */
    --bitting-text-display-weight: var(--bitting-font-weight-heavy);
    --bitting-text-heading-weight: var(--bitting-font-weight-bold);
    --bitting-text-compact-heading-weight: var(--bitting-font-weight-bold);
    --bitting-text-body-weight: var(--bitting-font-weight);
    --bitting-text-supporting-weight: var(--bitting-font-weight);
    --bitting-text-micro-weight: var(--bitting-font-weight-medium);
    --bitting-text-display-line-height: var(--bitting-line-height-tight);
    --bitting-text-heading-line-height: var(--bitting-line-height-heading);
    --bitting-text-compact-heading-line-height: var(--bitting-line-height-heading);
    --bitting-text-body-line-height: var(--bitting-line-height-relaxed);
    --bitting-text-supporting-line-height: var(--bitting-line-height);
    --bitting-text-micro-line-height: var(--bitting-line-height);
    --bitting-text-display-tracking: var(--bitting-letter-spacing-tight);
    --bitting-text-heading-tracking: var(--bitting-letter-spacing-heading);
    --bitting-text-compact-heading-tracking: var(--bitting-letter-spacing-heading);
    --bitting-text-body-tracking: var(--bitting-letter-spacing-normal);
    --bitting-text-supporting-tracking: var(--bitting-letter-spacing-normal);
    --bitting-text-micro-tracking: var(--bitting-letter-spacing-normal);

    /* -- Radius ----------------------------------------------------------
     * Corner rounding, tracking the size scale so radius scales with density.
     * Elevation is the .bitting-solid-shadow / .bitting-solid-drop-shadow
     * classes further down. */
    --bitting-radius-sm: var(--bitting-sm);
    --bitting-radius:    var(--bitting-md);
    --bitting-radius-pill: 100vmax;

    /* -- Motion ----------------------------------------------------------
     * Duration + easing tokens for the transitions below. Keyframe animations
     * keep their tuned per-animation timing. All motion is suppressed under
     * prefers-reduced-motion (see the media query further down). */
    --bitting-duration-fast: 0.15s;
    --bitting-duration:      0.3s;
    --bitting-duration-slow: 0.5s;
    --bitting-duration-spinner: 0.75s;
    --bitting-duration-spinner-reduced: 2s;
    --bitting-ease:          ease;
    --bitting-ease-out:      ease-out;
    --bitting-ease-in-out:   ease-in-out;
    --bitting-motion-lift: calc(var(--bitting-qtr-md) * -1);
    --bitting-motion-lift-subtle: calc(var(--bitting-border-width) * -1);
    --bitting-motion-scale: 1.02;
    --bitting-motion-scale-emphasis: 1.06;
    --bitting-motion-scale-dismissed: 0.9;
    --bitting-opacity-hidden: 0;
    --bitting-opacity-disabled: 0.25;
    --bitting-opacity-subtle: 0.75;
    --bitting-opacity-graphic: 0.9;
    --bitting-opacity-visible: 1;
    --bitting-opacity-faint: 0.1;
    --bitting-opacity-scrim: 0.5;
    --bitting-opacity-dim: var(--bitting-opacity-disabled);

    /* Solid-shadow recipe. Every raised, pressed, and inset shadow is built from
       these five terms, so the slider and the tile utilities share one recipe. */
    --bitting-shadow-ring: calc(var(--bitting-md) * 0.15);
    --bitting-shadow-lift: calc(var(--bitting-md) * 0.2);
    --bitting-shadow-drop: calc(var(--bitting-md) * 0.4);
    --bitting-shadow-spread: calc(var(--bitting-md) * 0.1);
    --bitting-shadow-blur: calc(var(--bitting-md) * 0.25);

    /* Slider geometry: sub-step sizes the range control needs, named once. */
    --bitting-slider-thumb-border: calc(var(--bitting-qtr-md) * 0.65);
    --bitting-slider-thumb-gap: calc(var(--bitting-qtr-md) * 0.9);
    --bitting-slider-focus-inset: calc(var(--bitting-qtr-md) * -0.9);
    --bitting-slider-focus-ring: calc(var(--bitting-qtr-md) * 0.8);
    --bitting-slider-tick-width: calc(var(--bitting-qtr-md) * 0.5);
    --bitting-slider-tick-height: calc(var(--bitting-md) * 1.5);
    --bitting-slider-minor-tick-width: calc(var(--bitting-qtr-md) * 0.45);
    --bitting-slider-tick-radius: calc(var(--bitting-qtr-md) * 0.3);
    --bitting-slider-minor-tick-height: calc(var(--bitting-sm) * 0.7);

    /* -- Tooltip --------------------------------------------------------- */
    --bitting-tooltip-max-width: calc(var(--bitting-md) * 16);
    --bitting-tooltip-offset: var(--bitting-sm);
    --bitting-tooltip-opacity: 0.9;
}

/* ============================================================================
 * BITTING - LATCH: BASE FRAMEWORK
 * ============================================================================ */

.bitting-font-xs { font-size: var(--bitting-xs); }
.bitting-font-sm { font-size: var(--bitting-sm); }
.bitting-font-md { font-size: var(--bitting-md); }
.bitting-font-lg { font-size: var(--bitting-lg); }
.bitting-font-xl { font-size: var(--bitting-xl); }

/* Semantic text roles. All six share the package family and reset browser
   margins; recurring compositions own the gaps around them. */
.bitting-text-display,
.bitting-text-heading,
.bitting-text-compact-heading,
.bitting-text-body,
.bitting-text-supporting,
.bitting-text-micro {
    margin: 0;
    font-family: var(--bitting-font-family);
}

.bitting-text-display {
    font-size: var(--bitting-xl);
    font-weight: var(--bitting-text-display-weight);
    line-height: var(--bitting-text-display-line-height);
    letter-spacing: var(--bitting-text-display-tracking);
}

.bitting-text-heading {
    font-size: var(--bitting-lg);
    font-weight: var(--bitting-text-heading-weight);
    line-height: var(--bitting-text-heading-line-height);
    letter-spacing: var(--bitting-text-heading-tracking);
}

.bitting-text-compact-heading {
    font-size: var(--bitting-md);
    font-weight: var(--bitting-text-compact-heading-weight);
    line-height: var(--bitting-text-compact-heading-line-height);
    letter-spacing: var(--bitting-text-compact-heading-tracking);
}

.bitting-text-body {
    font-size: var(--bitting-md);
    font-weight: var(--bitting-text-body-weight);
    line-height: var(--bitting-text-body-line-height);
    letter-spacing: var(--bitting-text-body-tracking);
}

.bitting-text-supporting {
    font-size: var(--bitting-sm);
    font-weight: var(--bitting-text-supporting-weight);
    line-height: var(--bitting-text-supporting-line-height);
    letter-spacing: var(--bitting-text-supporting-tracking);
}

.bitting-text-micro {
    font-size: var(--bitting-sm);
    font-weight: var(--bitting-text-micro-weight);
    line-height: var(--bitting-text-micro-line-height);
    letter-spacing: var(--bitting-text-micro-tracking);
}

/* Emphasis within a role: the bold weight token, never an inline font-weight. */
.bitting-text-strong {
    font-weight: var(--bitting-font-weight-bold);
}

/* Page-title lockup: one title, optional lead/supporting copy, then optional
   actions. This is the sole page-heading composition used by the demo routes. */
.bitting-page-header {
    width: min(100%, 72ch);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--bitting-sm);
    padding: var(--bitting-lg) 0 var(--bitting-md);
}

.bitting-page-header__title {
    color: var(--bitting-primary);
}

.bitting-page-header__lead {
    color: var(--bitting-secondary);
}

.bitting-page-header__description {
    color: var(--bitting-gray);
    max-width: 68ch;
}

.bitting-page-header__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bitting-sm);
    padding-top: var(--bitting-xs);
}

/* Section headings share one structural treatment so pages can establish
   consistent rhythm around them without depending on inline declarations. */
.bitting-section-header {
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    margin-bottom: var(--bitting-md);
    font-size: var(--bitting-lg);
    font-weight: var(--bitting-text-heading-weight);
}

.bitting-section-header__title {
    display: block;
    padding-bottom: calc(var(--bitting-md) / 4);
}

.paper-only {
    display: none;
}

/* One switch owns every prepared-paper rule. Component styles refine their
   own layout under the same attribute; these are the shared palette, page,
   interaction, and data-mark contracts. */
:root[data-bitting-paper] {
    color-scheme: light;
    --bitting-md: var(--bitting-paper-md);
    --bitting-surface: var(--bitting-white);
    --bitting-canvas: var(--bitting-white);
}

:root[data-bitting-paper],
:root[data-bitting-paper] body {
    background: var(--bitting-white) !important;
    color: var(--bitting-secondary);
}

:root[data-bitting-paper] *,
:root[data-bitting-paper] *::before,
:root[data-bitting-paper] *::after {
    animation: none !important;
    transition: none !important;
}

:root[data-bitting-paper] .paper-only {
    display: block;
}

:root[data-bitting-paper] .no-print,
:root[data-bitting-paper] .print-none {
    display: none !important;
}

:root[data-bitting-paper] .bitting-solid-shadow,
:root[data-bitting-paper] .bitting-solid-drop-shadow,
:root[data-bitting-paper] .bitting-traditional-shadow {
    box-shadow: inset 0 0 0 var(--bitting-border-width) var(--bitting-paper-rule) !important;
}

:root[data-bitting-paper] .bitting-section-header {
    break-before: page;
    break-after: avoid;
    break-inside: avoid;
}

:root[data-bitting-paper] .bitting-section-header + .bitting-slide {
    break-before: auto;
}

:root[data-bitting-paper] .bitting-slide {
    width: var(--bitting-paper-box-width);
    max-width: 100%;
    min-height: 0;
    margin-inline: auto;
    break-before: page;
    transform-origin: top center;
}

:root[data-bitting-paper] .bitting-slide__panels {
    flex-direction: column;
    align-items: stretch !important;
    margin: 0;
}

:root[data-bitting-paper] .bitting-slide__panel {
    width: 100%;
    max-width: 100%;
    flex: 0 0 auto;
    padding: 0;
}

:root[data-bitting-paper] .bitting-slide[data-bitting-paper-continuing] {
    break-inside: auto;
}

:root[data-bitting-paper] .bitting-tile {
    width: 100%;
    height: auto !important;
    min-height: 0;
    aspect-ratio: var(--bitting-tile-aspect);
    break-inside: avoid;
    overflow: visible;
    background: var(--bitting-surface) !important;
    box-shadow: inset 0 0 0 var(--bitting-border-width) var(--bitting-paper-rule) !important;
}

:root[data-bitting-paper] .bitting-summary-table {
    overflow: visible !important;
    max-height: none !important;
}

:root[data-bitting-paper] .bitting-summary-table thead,
:root[data-bitting-paper] .bitting-summary-table th,
:root[data-bitting-paper] .bitting-summary-table td {
    position: static !important;
}

:root[data-bitting-paper] .bitting-summary-table thead {
    display: table-header-group;
}

:root[data-bitting-paper] .bitting-pill-button[aria-pressed="false"],
:root[data-bitting-paper] .bitting-drop-menu,
:root[data-bitting-paper] .bitting-tooltip,
:root[data-bitting-paper] .bitting-tooltip-fixed,
:root[data-bitting-paper] .bitting-chart-hover-tooltip {
    display: none !important;
}

:root[data-bitting-paper] .bitting-pill-button[aria-pressed="true"] {
    border-radius: var(--bitting-pill-radius) !important;
}

:root[data-bitting-paper] [aria-pressed="true"] {
    outline: var(--bitting-focus-width) solid var(--bitting-focus-ring);
    outline-offset: calc(-1 * var(--bitting-focus-width));
}

:root[data-bitting-paper] .bitting-pill-button[aria-pressed="true"],
:root[data-bitting-paper] .bitting-slider-fill,
:root[data-bitting-paper] .bitting-sparkline-dot,
:root[data-bitting-paper] .bitting-pip,
:root[data-bitting-paper] .bitting-underline,
:root[data-bitting-paper] [class*="table-pct"],
:root[data-bitting-paper] [class*="value-bar"] {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}

@page {
    size: landscape;
    margin: var(--bitting-paper-margin-block) var(--bitting-paper-margin-inline);

    @top-left {
        content: var(--bitting-print-title, "");
    }

    @top-right {
        content: var(--bitting-print-period, "");
    }

    @bottom-left {
        content: var(--bitting-print-label-printed) " " var(--bitting-print-date, "");
    }

    @bottom-right {
        content: var(--bitting-print-label-page) " " counter(page) " " var(--bitting-print-label-of) " " counter(pages);
    }
}

@page :first {
    @top-left { content: none; }
    @top-right { content: none; }
}

.bitting-solid-shadow {
    box-shadow: 0 0 0 var(--bitting-shadow-ring) var(--bitting-muted-gray-80);
}

.bitting-solid-drop-shadow {
    box-shadow:
        0 0 0 var(--bitting-shadow-ring) var(--bitting-muted-gray-80),
        0 var(--bitting-shadow-lift) 0 var(--bitting-shadow-ring) var(--bitting-muted-gray),
        0 var(--bitting-shadow-drop) 0 var(--bitting-shadow-spread) var(--bitting-muted-gray-40);
}

.bitting-traditional-shadow {
    box-shadow:
        0 var(--bitting-shadow-lift) var(--bitting-shadow-blur)
        var(--bitting-black-10);
}

.bitting-solid-inset-shadow {
    box-shadow:
        inset 0 0 0 var(--bitting-shadow-ring) var(--bitting-muted-gray-80),
        inset 0 var(--bitting-shadow-lift) 0 var(--bitting-shadow-ring) var(--bitting-muted-gray),
        inset 0 var(--bitting-shadow-drop) 0 var(--bitting-shadow-spread) var(--bitting-muted-gray-40);
}

.bitting-hover {
    transition: background-color var(--bitting-duration-fast) var(--bitting-ease);
}

.bitting-hover:hover {
    cursor: pointer;
    background-color: var(--bitting-muted-gray) !important;
}

/* -- Hover-opacity utilities --------------------------------------------
 * Backing classes for the BittingHoverOpacityStyle enum, applied by every
 * interactive Bitting component (PillButton, ArrowBookends, SelectableIcon,
 * DropDownMenu, etc.). At rest the element renders at partial opacity;
 * hovering lifts it to fully opaque.
 *   Subtle  → default for pill buttons (gentle dim at rest).
 *   Normal  → stronger affordance for icons + bookends.
 *
 * These classes were previously declared in
 * a host stylesheet and did not ship to
 * consumers of just this package, leaving the hover effect dead. Moved
 * here so the Bitting package is self-contained.
 */
.opacity-hover {
    opacity: var(--bitting-opacity-subtle);
    transition: opacity var(--bitting-duration) var(--bitting-ease);
}

.opacity-hover:hover {
    opacity: var(--bitting-opacity-visible);
}

/* Dims non-hovered *graphics* (chart marks, icons) so the hovered one leads.
   Never put this on a control that carries text: a resting fade composites the
   fill toward the page and drops label contrast below the AA the palette is
   tuned for. Text-bearing controls use .subtle-contrast-hover below. */
.subtle-opacity-hover {
    opacity: var(--bitting-opacity-graphic);
    transition: opacity var(--bitting-duration) var(--bitting-ease);
}

.subtle-opacity-hover:hover {
    opacity: var(--bitting-opacity-visible);
}

/* The hover affordance for text-bearing controls. Full opacity at rest keeps
   the label's contrast intact; hover darkens the fill, which only ever raises
   contrast against light label text. */
.subtle-contrast-hover {
    transition: filter var(--bitting-duration) var(--bitting-ease);
}

.subtle-contrast-hover:hover {
    filter: brightness(0.92);
}

/* -- flex-centered: micro-utility used throughout Bitting markup --------- */
.flex-centered {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Small composition vocabulary shared by pages and component internals. */
.bitting-stack {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--bitting-md);
}

.bitting-stack--compact { gap: var(--bitting-xs); }
.bitting-stack--cozy { gap: var(--bitting-sm); }
.bitting-stack--relaxed { gap: var(--bitting-lg); }
.bitting-stack--spread { justify-content: space-between; }

.bitting-cluster {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bitting-sm);
}

.bitting-cluster--center { justify-content: center; }
.bitting-cluster--spread { justify-content: space-between; }
.bitting-cluster--relaxed { gap: var(--bitting-lg); }
.bitting-cluster--spacious { gap: var(--bitting-xl); }

.bitting-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--bitting-sm);
    text-align: center;
    width: 100%;
}

/* Caps prose at a readable line length without coupling that decision to a
   particular page. Pair with a stack and the semantic text-role classes. */
.bitting-readable-measure {
    width: min(100%, var(--bitting-readable-measure));
}

.bitting-grid {
    display: grid;
    gap: var(--bitting-md);
    grid-template-columns: repeat(
        auto-fit,
        minmax(min(100%, var(--bitting-grid-min-kpi)), 1fr));
}

.bitting-grid--compact {
    grid-template-columns: repeat(
        auto-fit,
        minmax(min(100%, var(--bitting-grid-min-rainbow)), 1fr));
}

.bitting-grid--two {
    grid-template-columns: repeat(
        auto-fit,
        minmax(min(100%, var(--bitting-grid-min-two-column)), 1fr));
}

.bitting-grid--three {
    grid-template-columns: repeat(
        auto-fit,
        minmax(min(100%, var(--bitting-grid-min-three-column)), 1fr));
}

/* Focus halo for a hovered line mark.

   The filled marks — a bubble, a bar, a waffle cell — wear the ring emitted by
   ChartVisualMetrics.FocusRingStyle, which works by stroking a shape that
   already has a fill. A line has no fill, so the same declaration would repaint
   the line instead of haloing it; the line equivalent is a wider line of the
   focus colour drawn underneath, revealed on hover.

   Only lines that carry a tooltip get this class. A focus state promises a
   readout, so the segments between plotted dots — which have no tooltip, because
   the dots are the marks that carry the values — deliberately do not have it.

   visibility rather than opacity: the halo already carries the line's own
   opacity inline, so a hover rule on opacity would fight it. */
.bitting-chart-line-focus {
    stroke: var(--bitting-chart-mark-focus);
    visibility: hidden;
}

.bitting-chart-line-focusable:hover .bitting-chart-line-focus {
    visibility: visible;
}

.bitting-fill { width: 100%; height: 100%; }
.bitting-chart-stage {
    display: flex;
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    align-items: center;
    justify-content: center;
}
/* Bitting Map is one responsive composition: the SVG owns geography while
   package filter and legend sit in named overlay regions that the viewport
   math reserves. The overlays use the same surface and text roles as the host
   instead of creating map-only chrome. */
.bitting-map {
    position: relative;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.bitting-map-canvas {
    display: block;
    width: 100%;
    height: 100%;
}

.bitting-map-geography {
    transform-origin: 0 0;
    transition: transform var(--bitting-duration) var(--bitting-ease-in-out);
}

.bitting-map[data-bitting-map-view="country"] .bitting-map-canvas {
    cursor: grab;
    touch-action: none;
}

.bitting-map--dragging .bitting-map-canvas {
    cursor: grabbing;
}

.bitting-map--manipulating .bitting-map-geography {
    transition: none;
}

.bitting-map-region {
    stroke: var(--bitting-map-boundary);
    stroke-width: var(--bitting-map-boundary-width);
}

.bitting-map-canvas[role="group"] .bitting-map-region {
    cursor: pointer;
}

/* The browser outline traces SVG compound-path internals and becomes long bars
   at country-context scale. Suppress only that malformed geometry, then draw a
   token-owned focus boundary on the country path itself. */
.bitting-map-canvas[role="group"] .bitting-map-region:focus {
    outline: var(--bitting-focus-width) none var(--bitting-focus-ring);
    opacity: var(--bitting-opacity-visible);
}

.bitting-map-canvas[role="group"] .bitting-map-region:focus-visible {
    stroke: var(--bitting-focus-ring);
    stroke-width: var(--bitting-map-focus-stroke-width);
    paint-order: stroke fill;
}

.bitting-map-region--selected {
    opacity: var(--bitting-opacity-visible);
}

.bitting-map-toolbar,
.bitting-map-legend,
.bitting-map-empty {
    position: absolute;
    z-index: var(--bitting-layer-affordance);
}

.bitting-map-toolbar {
    inset-block-end: var(--bitting-xs);
    inset-inline-start: var(--bitting-xs);
    inset-inline-end: var(--bitting-xs);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: var(--bitting-xs);
}

.bitting-map-selection-filter {
    min-width: 0;
}

.bitting-map-legend {
    inset-inline: var(--bitting-xs);
    inset-block-start: var(--bitting-xs);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--bitting-xs) var(--bitting-sm);
    padding: var(--bitting-xs);
    border-radius: var(--bitting-radius-sm);
    background: var(--bitting-map-overlay-surface);
}

.bitting-map-legend-item {
    display: inline-flex;
    align-items: center;
    gap: var(--bitting-xs);
}

/* The marker is the shared BittingBubble inside a marker-sized inline SVG;
   size and stroke come from the chart metrics, not from a map token. */
.bitting-map-legend-marker {
    display: block;
    flex: 0 0 auto;
}

.bitting-map-empty {
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    background: var(--bitting-map-empty-overlay-surface);
}

.bitting-map-empty .bitting-empty-state {
    padding: var(--bitting-md);
}

.bitting-map-fault-list {
    margin: 0;
    padding-inline-start: var(--bitting-lg);
}

.bitting-fill { width: 100%; height: 100%; }
.bitting-chart-stage {
    display: flex;
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    align-items: center;
    justify-content: center;
}



.bitting-key-value-text {
    line-height: var(--bitting-line-height);
    letter-spacing: var(--bitting-letter-spacing-normal);
}

.bitting-key-value-text--stacked {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: var(--bitting-line-height-tight);
}

.bitting-key-value-text__key {
    font-weight: var(--bitting-font-weight);
}

.bitting-key-value-text__value {
    margin-inline-start: var(--bitting-qtr-md);
    font-weight: var(--bitting-font-weight-bold);
}

.bitting-key-value-text--stacked .bitting-key-value-text__value {
    margin-inline-start: 0;
}


.bitting-pad-tile { padding: var(--bitting-tile-padding); }
.bitting-pad-md { padding: var(--bitting-md); }
.bitting-pad-lg { padding: var(--bitting-lg); }
.bitting-tile--flush { padding: 0; }
.bitting-flush { margin: 0; }

/* -- bitting-spinner: dependency-free loading spinner --------------------
 * Replaces the Font Awesome <i class="fas fa-spin fa-spinner"> pattern so
 * the package has no icon-font requirement on the consumer. Sizes from the
 * current text font-size; inherits currentColor.
 */
.bitting-spinner {
    display: inline-block;
    width: var(--bitting-intrinsic-icon-size);
    height: var(--bitting-intrinsic-icon-size);
    border: var(--bitting-intrinsic-spinner-border) solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: bitting-spinner-rotate var(--bitting-duration-spinner) linear infinite;
}

@keyframes bitting-spinner-rotate {
    to { transform: rotate(360deg); }
}

/* ============================================================================
 * BITTING - LATCH: MISC UTILITIES + ANIMATIONS
 *
 * Self-contained replacements for the handful of Bootstrap/unlocked.css
 * utility classes the components reference, so the package needs no external
 * stylesheet.
 * ============================================================================ */

/* Screen-reader-only text (Bootstrap's .visually-hidden equivalent). */
.visually-hidden {
    position: absolute !important;
    width: var(--bitting-visually-hidden-size);
    height: var(--bitting-visually-hidden-size);
    padding: 0;
    margin: var(--bitting-visually-hidden-offset);
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.opacity-25 { opacity: var(--bitting-opacity-disabled) !important; }

/* Pill add/enter animation (BittingPillButton FadeIn). */
.fade-grow-in {
    animation: bitting-fade-grow-in var(--bitting-duration-fast) var(--bitting-ease-out);
}

@keyframes bitting-fade-grow-in {
    from { opacity: var(--bitting-opacity-hidden); transform: scale(var(--bitting-motion-scale-dismissed)); }
    to   { opacity: var(--bitting-opacity-visible); transform: scale(1); }
}

.fade-shrink-out {
    animation: bitting-fade-shrink-out var(--bitting-duration-fast) var(--bitting-ease-out) forwards;
}

@keyframes bitting-fade-shrink-out {
    from { opacity: var(--bitting-opacity-visible); transform: scale(1); }
    to   { opacity: var(--bitting-opacity-hidden); transform: scale(var(--bitting-motion-scale-dismissed)); }
}

/* Attention pulses (BittingTile Wobble / PulseGlow). */
.pulse-wobble {
    animation: bitting-pulse-wobble var(--bitting-duration-slow) var(--bitting-ease-in-out);
}

@keyframes bitting-pulse-wobble {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(-1.5deg); }
    75%      { transform: rotate(1.5deg); }
}

.pulse-glow {
    animation: bitting-pulse-glow calc(var(--bitting-duration-slow) * 3) var(--bitting-ease-in-out) infinite;
}

@keyframes bitting-pulse-glow {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--bitting-primary) 40%, transparent); }
    50%      { box-shadow: 0 0 0 var(--bitting-shadow-drop) transparent; }
}

/* ============================================================================
 * BITTING - LATCH: PRINT UTILITIES
 *
 * Bitting components reference these classes (BittingTile's screenshot button,
 * BittingHorizontalNavigation, BittingVerticalNavigation, BittingRenderVeil,
 * BittingQuestionTooltip, BittingSlide). Before this block they were defined
 * only in a host stylesheet and so did not ship
 * to consumers of just this package, leaving the print behavior silently dead.
 *
 *   .no-print / .print-none — hide chrome that doesn't belong in a printout
 *                              (capture buttons, nav, loading overlays).
 *   .print-dont-break       — keep a tile or row intact across a page break.
 * ============================================================================ */
@media print {
    .no-print,
    .print-none {
        display: none !important;
    }

    .print-dont-break {
        break-inside: avoid;
        page-break-inside: avoid !important;
    }

    /* Safe no-script fallback. Rich paper preparation is keyed on the root
       attribute; these minimums keep ordinary Ctrl+P output usable even when
       the host forgot to load bitting.js. */
    .bitting-tile {
        break-inside: avoid;
        page-break-inside: avoid;
    }
}

/* ============================================================================
 * REDUCED MOTION (WCAG 2.3.3)
 *
 * Honour the user's OS "reduce motion" setting: drop the decorative entrance
 * and attention animations entirely, and gentle the loading spinner to a slow
 * turn so it still reads as "busy" without a fast, vestibular-triggering spin.
 * The default (no-preference) look is unchanged.
 * ============================================================================ */
@media (prefers-reduced-motion: reduce) {
    .bitting-map-geography {
        transition: none;
    }
    .fade-grow-in,
    .fade-shrink-out,
    .pulse-wobble,
    .pulse-glow {
        animation: none;
    }

    .bitting-hover,
    .opacity-hover,
    .subtle-opacity-hover,
    .subtle-contrast-hover {
        transition: none;
    }

    .bitting-spinner {
        animation-duration: var(--bitting-duration-spinner-reduced);
    }
}

/* ============================================================================
 * KEYBOARD FOCUS (WCAG 2.4.7)
 *
 * :focus-visible fires for keyboard navigation only, so mouse users see the
 * resting look unchanged. A conventional outline (what users expect) sits
 * outside the shadow language, in the brand colour.
 * ============================================================================ */
[role="button"]:focus-visible,
.bitting-pill-button:focus-visible,
.subtle-opacity-hover:focus-visible,
.subtle-contrast-hover:focus-visible,
.opacity-hover:focus-visible {
    outline: var(--bitting-focus-width) solid var(--bitting-focus-ring);
    outline-offset: var(--bitting-focus-offset);
    opacity: 1;
}

/* Shared hit-area contract for icon-only controls. The glyph can stay on the
   five-step visual scale while its operable area remains at least 24 CSS px. */
.bitting-icon-target {
    min-width: var(--bitting-target-min);
    min-height: var(--bitting-target-min);
}

/* ============================================================================
 * REQUIRED HOST GRID
 *
 * BittingSlide and selectable tile rows currently consume Bootstrap's grid and
 * flex utilities. Keep this dependency explicit until Bitting owns the narrow
 * set of layout primitives tracked in ROADMAP.md.
 * ============================================================================ */
/* The Bitting components use the Bootstrap 5 grid (row / col-*, with gutters)
 * and Bootstrap utilities (flex-grow-1, text-center, align-items-center,
 * p-*/m-*, and the global box-sizing: border-box reset). The host page must
 * load Bootstrap — the same setup Unlock8s ships. We deliberately do NOT
 * redefine .row/.col here: a stub copy without Bootstrap's gutter system is
 * exactly what collapsed the spacing between tiles. */
