/* Auto-specific overrides layered on top of bootstrap.min.css, tabler.min.css,
   and tabler-overrides.css (ported from pool_tracker for a consistent look and
   feel). Only rules with no Tabler/Bootstrap equivalent live here. */

.inline-form { display: inline; margin: 0; }

/* Dynamic textarea min-height applied via a class (instead of an inline
   style) so the CSS language service never has to parse a Jinja2 expression
   inside a style attribute. The class name encodes the pixel value, e.g.
   min-height-250 -> min-height: 250px. */
.min-height-250 { min-height: 250px; }


/* Small default-car thumbnail on Fuel Records / New Fill-Up card-headers and
   the Fuel Records Report heading. 58px image + 1px top/bottom padding = 60px
   total, matching the existing card-header height so it doesn't grow. */
.card-header-car-thumbnail {
    height: 58px;
    width: auto;
    padding-top: 1px;
    padding-bottom: 1px;
    display: block;
}

/* The thumbnail's own 1px+1px padding already accounts for the header's
   vertical spacing, so zero the header's own padding wherever one appears. */
.card-header:has(.card-header-car-thumbnail) {
    padding-top: 0;
    padding-bottom: 0;
}

/* Select2 hides the native <select>, so an .is-invalid class on it alone has
   no visible effect -- mirror the red outline onto the rendered container. */
.form-select.is-invalid + .select2-container .select2-selection,
.form-select.is-invalid + .select2-container--default .select2-selection--single,
.form-select.is-invalid + .select2-container--default .select2-selection--multiple {
    border-color: var(--bs-danger) !important;
    box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25);
}

/* Live data-integrity field highlighting (Fuel Records entry/edit form) --
   orange when a field is named by a currently-active integrity warning,
   green when it holds a value and isn't flagged. Never applied alongside a
   real .is-invalid error (that always takes priority -- see
   applyIntegrityFieldHighlights in static/js/fuel_records_controller.js).
   Colors match the integrity-warning-gauge gradient's green/orange stops. */
.form-control.integrity-field-warning,
.form-select.integrity-field-warning,
.form-check-input.integrity-field-warning {
    border-color: #f76707;
    box-shadow: 0 0 0 .2rem rgba(247, 103, 7, .25);
}
.form-control.integrity-field-ok,
.form-select.integrity-field-ok,
.form-check-input.integrity-field-ok {
    border-color: #2fb344;
    box-shadow: 0 0 0 .2rem rgba(47, 179, 68, .25);
}

/* Same Select2 sibling-selector need as the .is-invalid rule above. */
.form-select.integrity-field-warning + .select2-container .select2-selection,
.form-select.integrity-field-warning + .select2-container--default .select2-selection--single,
.form-select.integrity-field-warning + .select2-container--default .select2-selection--multiple {
    border-color: #f76707 !important;
    box-shadow: 0 0 0 .2rem rgba(247, 103, 7, .25);
}
.form-select.integrity-field-ok + .select2-container .select2-selection,
.form-select.integrity-field-ok + .select2-container--default .select2-selection--single,
.form-select.integrity-field-ok + .select2-container--default .select2-selection--multiple {
    border-color: #2fb344 !important;
    box-shadow: 0 0 0 .2rem rgba(47, 179, 68, .25);
}

/* Message printed beneath a field flagged by a Mileage Check-In field value
   logic check -- matches the orange outline above it so the border and the
   text read as one warning (the red .invalid-feedback stays red). */
.field-error.integrity-field-message {
    color: #f76707;
}

/* Info-circle icon used by render_info_tooltip() -- sized down so it doesn't
   inherit the bold/large font-size of surrounding measure values. Spacing
   around it is left to the call site (e.g. me-2/ms-2) since it can sit on
   either side of its labeled value. */
.info-tooltip-icon {
    font-size: 0.85rem;
    color: var(--bs-secondary);
    cursor: help;
}

dialog {
    border: none;
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
    padding: 1.25rem;
    max-width: 600px;
    width: 90%;
    position: relative;
}
dialog::backdrop { background: rgba(0, 0, 0, 0.4); }

.dialog-close-x {
    position: absolute;
    top: 0.5rem;
    right: 0.75rem;
    background: none;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    color: var(--tblr-text-muted);
}
.dialog-close-x:hover { color: var(--tblr-text); }

.history-modal-table td, .history-modal-table th {
    white-space: normal;
    overflow-wrap: break-word;
    word-break: break-word;
}

.reason-row { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; }
.reason-row-field { flex: 0 0 140px; font-weight: 600; }
.reason-select, .reason-comment { flex: 1; padding: 0.35rem; }
.dialog-actions { margin-top: 1rem; display: flex; gap: 0.75rem; }

.photo-upload-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.photo-upload-slot { flex: 0 1 30%; box-sizing: border-box; padding: 0.75rem; }
@media (max-width: 700px) {
    .photo-upload-slot { flex-basis: 100%; }
}
.photo-status-success { color: #166534; font-weight: 600; }
.photo-status-error { color: #991b1b; font-weight: 600; }
.highlight-row { background: #fef9c3; }

.auth-card { max-width: 380px; margin: 3rem auto; }

.fuel-record-photo-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
}
.fuel-record-photo-thumb {
    width: 250px;
    text-align: center;
    position: relative;
}
.fuel-record-photo-thumb img {
    width: 250px;
    height: auto;
    border-radius: 4px;
    border: 1px solid #dce1e7;
    display: block;
}
.fuel-record-photo-caption {
    margin-top: 0.35rem;
    font-size: 0.85rem;
    color: #495057;
    word-break: break-word;
}
.fuel-record-photo-meta {
    margin-top: 0.1rem;
    font-size: 0.78rem;
    color: #6c757d;
    word-break: break-word;
}
.fuel-record-photo-map {
    width: 100%;
    height: 180px;
    margin-top: 0.5rem;
    border-radius: 4px;
    border: 1px solid #dce1e7;
}
.integrity-check-alert {
    margin-bottom: 0.75rem;
}
.integrity-check-title {
    font-weight: 600;
}
.integrity-check-message {
    margin-top: 0.15rem;
}
.integrity-check-fields {
    margin-top: 0.35rem;
}
.file-delete-form {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 2;
}
.file-delete-button {
    background: #dc3545;
    color: #fff;
    border: none;
    border-radius: 50%;
    width: 24px;
    height: 24px;
    line-height: 1;
    font-size: 1rem;
    cursor: pointer;
}
.file-delete-button:hover {
    background: #b02a37;
}

/* "Reasons For Change" modal's copy-to-all-rows buttons -- larger circular
   touch target (44px meets the WCAG 2.5.5 minimum) so they're easy to press
   on a small screen despite sitting in a compact input-group. */
.reason-header-apply-btn {
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 50%;
    font-size: 1.1rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}

.upload-attempt-photo-thumb-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}
.upload-attempt-photo-thumb {
    height: 40px;
    width: auto;
    border-radius: 4px;
    border: 1px solid #dce1e7;
    display: block;
}

/* Fuelometry brand logo: the first item in the top header, to the left of the
   hamburger "Menu" button. 50px tall so it fits comfortably inside the fixed
   56px `.custom-navbar`; the whole logo is a link back to the home page ("/").
   The image is streamed by the public /media/Fuelometry_Logo.svg route
   (app/routes/media_routes.py). */
.navbar-logo-link {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    margin-right: 12px;
    text-decoration: none;
}

.navbar-logo {
    height: 50px;
    width: auto;
    display: block;
}

/* Fuelometry wordmark: replaces the old "Fuelometry" title text after the
   hamburger "Menu" button. Same 50px height as the emblem logo so the two read
   as one brand lockup; streamed by the public /media/Fuelometry_word.svg route
   (app/routes/media_routes.py). */
.navbar-wordmark {
    height: 50px;
    width: auto;
    display: block;
}

/* Top-header "AI" server-status badge (templates/base.html, left of the Sign
   Out control). The navbar's own `.custom-navbar .text-white` rule would force
   dark text on a `text-white` utility here, so the badge's white text comes
   from its own rule instead. The base `.ai-status-badge` neutral-gray
   background shows from page load until the first ping answers; the JS in
   static/js/ai_status_badge.js then flips the badge to `.ai-status-online`
   (solid green) or `.ai-status-offline` (solid red + pulse). */
.ai-status-badge {
    color: #fff;
    background-color: #6c757d; /* pending */
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1;
    vertical-align: middle;
    white-space: nowrap;
    border-radius: 0.5rem;
    transition: background-color 0.25s ease;
}

.ai-status-badge-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
}

/* Hover tooltip under the "AI" badge: shows a live countdown to the next ping
   ("Next AI ping in Ns"), swapped for "Pinging AI server..." while a ping is
   in flight and then the ping's outcome for a few seconds afterwards. Hidden
   until the wrapper is hovered/focused; its text is refreshed every 250 ms by
   static/js/ai_status_badge.js, so it is always current when revealed. */
.ai-status-tooltip {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 1080;
    padding: 4px 8px;
    font-size: 0.72rem;
    font-weight: 400;
    line-height: 1.25;
    color: #fff;
    background-color: #212529;
    border-radius: 4px;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

.ai-status-badge-wrap:hover .ai-status-tooltip,
.ai-status-badge-wrap:focus-within .ai-status-tooltip {
    display: block;
}

.ai-status-badge.ai-status-online {
    background-color: #198754; /* green */
}

.ai-status-badge.ai-status-offline {
    background-color: #dc3545; /* red */
    animation: ai-status-pulse 1.5s ease-in-out infinite;
}

@keyframes ai-status-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}

/* ----------------------------------------------------------------------------
   Responsive "statistics band" above the Fuel Fill-Up Records listing (see
   templates/macros/statistics_band.html). Seven at-a-glance columns on ONE row
   at every width, from a wide desktop down to the narrowest phone: a shared
   label column on the far left -- the chevron toggle beside the trend icon in
   that column's header band, then the "Est. Next" badge, then a collapsible
   block holding a blue "Recent" badge and a green "Average" badge -- beside the
   six metric columns (MPG, price per mile, miles between fill-ups, days between
   fill-ups, fill-up cost, price per gallon), each of which repeats the same
   bands: header, estimate badge, then its own collapsible block carrying the
   Recent and Average badges.

   Those bands are declared once, as shared row heights on this band, so every
   column's estimate sits on one line across the whole band and the Recent and
   Average badges on the two lines beneath it once the rows are expanded (see
   .statistics-band__card and .statistics-band__recent-average). The rows start
   HIDDEN -- the block's markup carries the `hidden` attribute, so the band opens
   showing only the estimates -- and the chevron toggle in the label column (or
   the trend icon beside it) shows and hides them. The dividers are drawn by 1px
   grid GAPS over a divider-colored grid background rather than per-card borders:
   that way the same rules produce correct vertical hairlines between the columns
   without any :nth-child juggling.

   NOTHING WRAPS: the grid's column count is fixed (the label column plus the six
   metrics), so the band can never re-flow into a second row of cards however
   narrow the viewport gets -- at every width it is the columns' own TEXT that
   wraps inside its column, never the band that stacks. All that changes below
   the wide layout is how much side padding a card may spend (see the 1199.98px
   and 575.98px blocks), which is what gives the narrow columns' text the width
   it needs; the phone block additionally drops PRICE / GALLON, whose width its
   five remaining columns can use, and the subgrid rules at the foot of this
   section keep every badge row lined up across the cramped phone columns.
   ---------------------------------------------------------------------------- */
.statistics-band {
    /* The header band has to clear a title that wraps to two lines (as the
       narrowest desktop column can force) and each badge band holds one badge;
       sharing those heights across all seven columns is what lines the badges up
       from column to column. */
    --statistics-band-header-row: 1.9rem;
    --statistics-band-badge-row: 1.7rem;
    background-color: #f7f5ee;
    border: 1px solid #e6e2d4;
    border-radius: 12px;
    /* Inset from the card edges so the band reads as its own rounded panel. */
    margin: 0.75rem 1rem;
    overflow: hidden;
}

.statistics-band__grid {
    display: grid;
    /* The label column, a little narrower than the six metric columns. This is
       the ONLY rule that sets the column count: no media query below changes it,
       which is what keeps the band on one row at every width instead of
       re-flowing into a second row of cards. */
    grid-template-columns: minmax(6.75rem, 0.8fr) repeat(6, minmax(0, 1fr));
    /* The hairline dividers between the columns are the 1px COLUMN gaps. The ROW
       gap instead matches the cards' own row gap (see .statistics-band__card and
       the two blocks below, which trim it in step): where subgrid is available the
       cards take their rows' spacing from the tracks they span, so the two have to
       agree or the shared rows are stretched taller than their content. The row
       gaps themselves sit behind the cards -- every one of them spans every row --
       so only the column gaps are ever seen. */
    column-gap: 1px;
    row-gap: 0.3rem;
    background-color: #e6e2d4;
}

.statistics-band__card {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(var(--statistics-band-header-row), auto) repeat(3, minmax(var(--statistics-band-badge-row), auto));
    align-content: start;
    gap: 0.3rem;
    min-width: 0;
    padding: 0.85rem 0.9rem;
    background-color: #f7f5ee;
}

/* The label column's own mark AND the band's one control: the trend icon, with
   the chevron that shows and hides the two measured rows immediately to its
   LEFT, both glyphs inside one <button>. The button fills the header band the
   metric columns fill with their titles -- across that band and down it, so the
   mark reads as the band's own rather than a corner ornament. The flex centring
   is what puts the glyphs themselves on that centre: their line boxes are taller
   than the glyphs. It is a chrome-less button -- no background, no border, no
   padding of its own -- so the two glyphs are the whole of it, and its
   accessible name (its aria-label) says which way a click will take the rows. */
.statistics-band__toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    align-self: center;
    justify-self: center;
    padding: 0;
    border: 0;
    background: none;
    color: #6c757d;
    font: inherit;
    line-height: 1.1;
    cursor: pointer;
}

/* Two classes so these beat the page's own `[data-testid="page-container"] .ti`
   icon-size rule regardless of source order: the trend icon keeps the size it
   had (sized to the band's text) and the chevron beside it reads one size down,
   so the pair still fits the label column's narrowest track (3rem on a phone:
   the base rule below). */
.statistics-band .statistics-band__toggle .ti {
    font-size: 1.25rem;
}

.statistics-band .statistics-band__toggle .statistics-band__toggle-chevron {
    font-size: 1rem;
}

/* The header row: the column's own icon beside its title, both centred. */
.statistics-band__title {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    color: #6c757d;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    line-height: 1.2;
    text-align: center;
    text-transform: uppercase;
    /* A title that cannot fit the column the grid gave it breaks INSIDE a word
       ("FILL-UP", "GALLON") rather than forcing that column wider than its share
       of the row -- which is what keeps the band's content inside the band at
       the widths where seven columns share the narrowest space. */
    overflow-wrap: anywhere;
}

/* The icon is sized to the title text it sits beside: 1em of the title's
   0.75rem is 12px, the same as the pill text, and the icon font's square glyphs
   (line-height: 1) keep its width proportionate to its height. Two classes so
   this beats any page-level `.ti` size rule, like the label column's own icon
   rule above. */
.statistics-band .statistics-band__title .ti {
    font-size: 1em;
    line-height: 1;
}

/* The value pills: one per column in the blue "Recent" band, one in the green
   "Average" band beneath it and one in the "Est. Next" band on the third line,
   each filling the width of its column's padding and taking the shared badge
   height so the whole band reads as three straight rows. */
.stat-badge {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    min-height: var(--statistics-band-badge-row);
    padding: 0.15rem 0.5rem;
    /* The text colour comes from the row's own modifier below (black on the
       "Recent" row, #505962 on the "Average", #545d65 on the "Est. Next"), and
       the size is pinned in px rather than rem so the pill text is exactly 12px
       whatever the root font size -- matching the 12px column titles above it. */
    font-size: 12px;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
    font-variant-numeric: tabular-nums;
    border-radius: 7px;
    overflow-wrap: anywhere;
}

/* The three rows' own text colours: the "Recent" row reads in black on its
   pill, the "Average" row in the #505962 slate the design asks for and the
   "Est. Next" row in its own #545d65 slate on the band's lightest pill. The
   label column's "Recent"/"Average"/"Est. Next" pills wear these same three
   modifiers, so the row labels and the rows' values are always coloured
   together. */
.stat-badge--recent {
    color: #000000;
    background-color: #dcd2dd;
}

.stat-badge--average {
    color: #505962;
    background-color: #d5d3c3;
}

/* ... and the estimate row's own, for the estimates: the lightest of the three
   pills, so the row reads as the band's projection rather than as another
   measured figure, while its slate text keeps it legible. The label column's
   "Est. Next" pill wears this same modifier, so the row label and that row's
   six values are always coloured together. */
.stat-badge--estimate {
    color: #545d65;
    background-color: #e4e3d9;
}

/* The word naming the band a badge belongs to. The shared label column on the
   left says it beside all three rows at EVERY width (the band never stacks, so
   that column never steps aside), which is why the tag stays out of sight here
   while remaining in the accessibility tree. */
.stat-badge__tag {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* The collapsible block the two MEASURED rows live in, one per column: the blue
   "Recent" pill above the green "Average" one. It spans the card's last two
   shared badge bands (`grid-row: span 2`, i.e. the two rows the card reserves
   beneath its header and estimate rows) and takes its two row heights straight
   from them where the browser supports subgrid, so its two rows are band-wide
   rows: every column's "Recent" pill sits on ONE straight line, below the bottom
   of the column with the lowest (tallest) "Est. Next" value, and every column's
   "Average" pill on the line beneath it. Its row gap matches the card's own, so
   the spacing between the rows reads the same as everywhere else in the band. */
.statistics-band__recent-average {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: repeat(2, minmax(var(--statistics-band-badge-row), auto));
    grid-row: span 2;
    gap: 0.3rem;
    min-width: 0;
}

/* The rows start hidden (the markup carries the `hidden` attribute) and the
   chevron shows and hides them. This rule is not optional: an author `display`
   declaration beats the user agent's own `display: none` for `[hidden]`, so
   without it the block's `display: grid` would keep the rows on screen. */
.statistics-band__recent-average[hidden] {
    display: none;
}

/* ... and while the rows are hidden the card gives up the two badge rows it
   reserves for them, so a collapsed band is as short as the header and estimate
   rows it still shows rather than trailing two empty bands. This is the FALLBACK
   half of the sharing rule below: where subgrid is available the card's rows are
   the band's own tracks, and the two the hidden blocks leave empty collapse to
   nothing by themselves. `:where()` keeps this rule at the card's own
   specificity, so it cannot outrank the rules that share the tracks below. */
:where(.statistics-band--rows-hidden) .statistics-band__card {
    grid-template-rows: minmax(var(--statistics-band-header-row), auto) minmax(var(--statistics-band-badge-row), auto);
}

/* Every column shares the band's five row tracks where the browser supports
   subgrid -- the header band, the estimate band, the two measured bands the
   "Recent"/"Average" block spans and the "why this figure is missing" line (which
   only the columns carrying a note fill, so it collapses to nothing when every
   column has a figure). Sharing them is what lines each ROW up across the band:
   the estimate badges all sit in ONE band, so a column whose estimate text wraps
   to more lines than its neighbours' -- the miles column's "Odo:" reading, the
   days column's weekday'd date -- cannot push its own measured rows down out of
   line. The "Recent" row therefore starts below the bottom of the LOWEST estimate
   value in the band, on one straight line, with the "Average" row on the line
   beneath it, whatever each column's text wraps to. Every card spans all five
   tracks, so neither a wrapped title nor a wrapped value can stagger a column's
   rows either. Browsers without subgrid size each card's rows to its own content
   instead (the fallback above and in .statistics-band__card): the rows still sit
   in the right order, just not on one straight line. Subgrid itself is Baseline
   widely available -- Chrome/Edge 117+, Firefox 71+ and Safari 16+. */
@supports (grid-template-rows: subgrid) {
    .statistics-band__grid {
        grid-template-rows: repeat(5, auto);
    }

    .statistics-band__card {
        grid-row: span 5;
        grid-template-rows: subgrid;
    }

    /* ... and the "Recent"/"Average" block takes its two rows from the same tracks
       (the two it spans), so the two measured rows are band-wide rows too. */
    .statistics-band__recent-average {
        grid-template-rows: subgrid;
    }
}

.statistics-band__note {
    color: #6c757d;
    font-size: 0.75rem;
    line-height: 1.25;
}

/* The band never re-wraps: the grid's seven-column row above is the only column
   count at any width, so this block trims what the cards may spend on their own
   side padding and nothing more. Every pixel taken back here goes straight to
   the columns' TEXT, which is what has to fit now that seven columns share a
   tablet's width -- the titles and values wrap inside their own column rather
   than the band wrapping into a second row of cards. The phone block below trims
   the same padding further still and drops PRICE / GALLON for the width its five
   remaining columns can use. */
@media (max-width: 1199.98px) {
    .statistics-band__card {
        padding: 0.6rem 0.2rem;
        gap: 0.25rem;
    }

    /* The band's own row gap follows the cards' trimmed gap, so the shared row
       tracks are sized for the spacing the cards actually use (see
       .statistics-band__grid). */
    .statistics-band__grid {
        row-gap: 0.25rem;
    }

    .stat-badge {
        padding: 0.15rem 0.2rem;
    }
}

/* Phones: the band still holds its single row rather than stacking -- seven
   columns is already one too many for a phone's width, so PRICE / GALLON is not
   shown at all and its width goes to the five metric columns that remain, with
   the label column at the far left beside them (as it is at every width). Every
   side padding is cut to the bone so a value has as much of its column as
   possible; the narrow columns' titles wrap as they must. */
@media (max-width: 575.98px) {
    .statistics-band {
        margin: 0.5rem 0.25rem 0.75rem;
    }

    /* The label column's track is sized to the widest pill it has to hold (its
       "Average" / "Est. Next" labels), never wider than that minimum needs, so
       all the remaining width goes to the five metrics -- and the band's row gap
       follows the cards' trimmed gap, so the shared row tracks are sized for the
       spacing the cards actually use (0.2rem here). */
    .statistics-band__grid {
        grid-template-columns: minmax(3rem, auto) repeat(5, minmax(0, 1fr));
        row-gap: 0.2rem;
    }

    .statistics-band__card--labels {
        display: grid;
    }

    /* PRICE / GALLON is not displayed on phones at all. */
    .statistics-band__card[data-testid="statistics-band-price-per-gallon-card"] {
        display: none;
    }

    /* Bare-minimum side padding: the columns are as wide as the phone allows. */
    .statistics-band__card {
        padding: 0.5rem 0.05rem;
        gap: 0.2rem;
    }

    .statistics-band__title {
        gap: 0.1rem;
    }

    /* The measured rows' block and the chevron pair keep this width's own tight
       spacing: the block's two rows take the same 0.2rem the card's rows take
       above, and the chevron sits close to the trend icon so the two glyphs still
       fit the label column's 3rem track. */
    .statistics-band__recent-average {
        gap: 0.2rem;
    }

    .statistics-band__toggle {
        gap: 0.1rem;
    }

    /* The clipped, screen-reader-only form the base rule gives this tag, restated
       here so the phone layout pins it explicitly: with the label column on
       screen at this width too, the band names are said once beside the badges,
       so repeating them inside every pill would only take width from the value.
       (The 1199.98px block above deliberately does NOT turn the tags back into
       visible text -- that block used to, back when the columns wrapped and the
       label column stepped aside; the band now holds its one row at every width,
       so the tags stay clipped at every width.) */
    .stat-badge__tag {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    .stat-badge {
        padding: 0.15rem 0.05rem;
        overflow-wrap: anywhere;
    }

    /* The "Est. Next" row's own label and its six values read one size down
       (10px) on phones ONLY: that row carries the longest text in the band --
       the weekday'd date beside the days gap, the "Odo:" reading beside the
       miles -- and 10px is what keeps those readings inside their column at a
       phone's width. The two measured rows above ("Recent" and "Average") keep
       the 12px every other pill in the app uses. */
    .stat-badge--estimate {
        font-size: 10px;
    }

    .statistics-band__note {
        overflow-wrap: anywhere;
    }

    /* Where the browser supports it the label column and the five cramped metric
       columns already share the band's five row tracks through subgrid, so each
       row is one straight line across the band -- the sharing rules are at the foot
       of this section's wide-layout half, NOT duplicated here, since the band holds
       the same five tracks (header, estimate, Recent, Average, note) at every width
       and all this block changes is the cards' padding and gap. */
}
/* ----------------------------------------------------------------------------
   The Planned Mileage Milestones rail (templates/macros/
   planned_mileage_milestones.html). The engine writes the canvas' own width,
   height and viewBox onto the <svg> as it draws, and these rules draw that canvas
   at exactly that size -- the rule names no width of its own, so the canvas is
   NEVER scaled and every word on it keeps the size the layout drew it at (11px or
   larger) on a phone and on a desktop alike. A card wider than the phone breakpoint
   gets a canvas exactly its own width (the rail, the line itself, is what shrinks);
   a phone-sized screen may get a wider canvas, and the card is what scrolls
   sideways to show the rest of it -- never a scaled-down rail with unreadable
   words and never a label cut off. The `--scroll` class is what the engine sets for
   exactly that case; the media query below is the same Bootstrap `md` breakpoint,
   covering the moment before the payload arrives. */
.planned-mileage-milestones { overflow-x: hidden; }
.planned-mileage-milestones--scroll { overflow-x: auto; }
.planned-mileage-milestones__svg { display: block; height: auto; max-width: none; }

/* Phone-sized screens (Bootstrap's md breakpoint and down): the rail the engine
   draws may be wider than the card, so the card scrolls sideways to show all of it
   rather than shrinking any word below its own size. */
@media (max-width: 767.98px) {
  .planned-mileage-milestones { overflow-x: auto; }
}

/* The spec's own rules for the callout text the engine writes as SVG <text>:
   an estimated date is one unbroken line (SVG text only wraps when it is styled
   to, so nothing here ever asks it to) and reads bold and dark; a milestone name
   is the callout's accent, bold; the 95% range and the day count stay small and
   muted. */
.planned-mileage-milestones__date { white-space: nowrap; font-weight: 600; }
.planned-mileage-milestones__title { font-weight: 600; }

/* The stems joining each callout to its own mark on the rail, and the light
   guide line under the rail's left end. */
.planned-mileage-milestones__stem,
.planned-mileage-milestones__guide { shape-rendering: crispEdges; }

