/* /Components/Calendar/YearOverview.razor.rz.scp.css */
/* =============================================================================================
   Year at a glance.

   Scoped; every element is rendered by YearOverview itself. Tokens only, except the country
   colours, which come inline from CountryColours (one stable colour per country, readable on the
   light and the dark card alike).

   Five kinds of day, told apart by more than colour:
   a country      - its own solid colour
   travelling     - grey diagonal stripes ("--")
   missing        - amber cross-hatch ("??", "I don't know where I was")
   before the log - a faint filled square
   future         - an empty outline
   ============================================================================================= */

.ctt-year[b-7wsmbuhaah] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    min-width: 0;
    padding: var(--card-pad);
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
    color: var(--ink);
}

.ctt-year__head[b-7wsmbuhaah] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-4);
}

.ctt-year__title[b-7wsmbuhaah] {
    margin: 0;
    font-size: var(--text-lg);
    line-height: var(--leading-snug);
    font-weight: var(--weight-bold);
    letter-spacing: -0.01em;
}

/* ‹ 2026 › */
.ctt-year__switch[b-7wsmbuhaah] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}

.ctt-year__yr[b-7wsmbuhaah] {
    min-width: 3.5ch;
    text-align: center;
    font-size: var(--text-xl);
    font-weight: var(--weight-bold);
    line-height: var(--leading-tight);
    font-variant-numeric: tabular-nums;
}

.ctt-year__step[b-7wsmbuhaah] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border: 1px solid var(--rule);
    border-radius: var(--radius-sm);
    background-color: var(--surface);
    color: var(--accent);
    font-size: var(--text-xl);
    line-height: 1;
    cursor: pointer;
}

.ctt-year__step:hover:not(:disabled)[b-7wsmbuhaah] {
    background-color: var(--accent-wash);
}

.ctt-year__step:focus-visible[b-7wsmbuhaah] {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

.ctt-year__step:disabled[b-7wsmbuhaah] {
    color: var(--rule);
    cursor: default;
}

/* The year bar: one thick bar, split by country. */
.ctt-year__bar[b-7wsmbuhaah] {
    display: flex;
    height: 1.25rem;
    overflow: hidden;
    border-radius: var(--radius-pill);
    background-color: var(--sunken);
}

.ctt-year__seg[b-7wsmbuhaah] {
    display: block;
    height: 100%;
    min-width: 2px;
}

/* "Greece 109 · Spain 31 · ..." */
.ctt-year__legend[b-7wsmbuhaah] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-5);
    margin: 0;
    padding: 0;
    list-style: none;
}

.ctt-year__key[b-7wsmbuhaah] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-base);
    min-width: 0;
}

.ctt-year__swatch[b-7wsmbuhaah] {
    flex: none;
    width: 0.875rem;
    height: 0.875rem;
    border-radius: 3px;
}

.ctt-year__name[b-7wsmbuhaah] {
    overflow-wrap: anywhere;
}

.ctt-year__num[b-7wsmbuhaah] {
    font-weight: var(--weight-bold);
    font-variant-numeric: tabular-nums;
}

.ctt-year__none[b-7wsmbuhaah] {
    margin: 0;
    color: var(--muted);
}

/* Twelve small months: three across on a wide screen, two on a phone. */
.ctt-year__months[b-7wsmbuhaah] {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-5) var(--space-5);
}

@media (max-width: 599.98px) {
    .ctt-year__months[b-7wsmbuhaah] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--space-4) var(--space-4);
    }
}

.ctt-year__month[b-7wsmbuhaah] {
    min-width: 0;
}

.ctt-year__mname[b-7wsmbuhaah] {
    margin: 0 0 var(--space-1);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--muted);
}

.ctt-year__grid[b-7wsmbuhaah] {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 3px;
    max-width: 16rem;
}

.ctt-year__blank[b-7wsmbuhaah],
.ctt-year__day[b-7wsmbuhaah] {
    aspect-ratio: 1;
    border-radius: 3px;
}

.ctt-year__day[b-7wsmbuhaah] {
    cursor: pointer;
}

/* --- the kinds of day; also used by the bar and the legend swatches --- */

.ctt-year--travel[b-7wsmbuhaah] {
    background-color: var(--sunken);
    background-image: repeating-linear-gradient(
        45deg,
        var(--muted) 0 2px,
        transparent 2px 5px);
}

.ctt-year--missing[b-7wsmbuhaah] {
    background-color: var(--warn-wash);
    background-image:
        repeating-linear-gradient(45deg, var(--warn) 0 1.5px, transparent 1.5px 5px),
        repeating-linear-gradient(-45deg, var(--warn) 0 1.5px, transparent 1.5px 5px);
}

.ctt-year--before[b-7wsmbuhaah] {
    background-color: var(--sunken);
}

.ctt-year--future[b-7wsmbuhaah] {
    box-shadow: inset 0 0 0 1px var(--rule);
}

.ctt-year--today[b-7wsmbuhaah] {
    outline: 2px solid var(--ink);
    outline-offset: 1px;
}

.ctt-year--picked[b-7wsmbuhaah] {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

/* The tapped day, in words, under the grid. Reserved height so the page does not jump. */
.ctt-year__picked[b-7wsmbuhaah] {
    margin: 0;
    min-height: 1.6em;
    font-size: var(--text-sm);
    color: var(--muted);
}
/* /Components/Dashboard/CountryCards.razor.rz.scp.css */
/* =============================================================================================
   Country cards - the dashboard's middle band.

   Scoped. Every element below is rendered by CountryCards itself, so plain selectors match it. The
   chips, the info icons and the two US tracker tiles are CHILD components: only their position is
   set from here, and always with ::deep.

   ONE CARD, THREE STEPS. The country's name, then its number - big and heavy - then the bar and the
   period in small muted type. The eye lands on the number; nothing else on the card is the same size.

   COLOUR. Tokens only. --ok, --warn and --crit are semantic: under the limit = ok, close = warn,
   reached = crit, a broken rule = crit. A count with no verdict is --ink. --accent is structure (the section badge, the "you are in"
   line) and never means good. The "you are in" card sits on the teal wash: it says where you are,
   which is a fact about the page, not a verdict.

   LAYOUT (owner, 3 Oct 2026: "equal heights and distributed correctly - not 2 cards, then 1, then
   2"). One regular grid of same-width cells. The column count comes from the section's own width,
   by container query: 1 on a phone, 2 from 30rem, 3 from 46rem, 4 from 64rem - so a cell is never
   narrower than about 14.5rem. From two columns up every row is the same height
   (grid-auto-rows: 1fr), and each card's bottom row - chip and "Details" - sits on the card's floor,
   so those line up across the grid.

   NO LONELY CARD. How many cards there are depends on the record, so the last row would often be
   short. The "You are in" card - always the first child - absorbs the shortfall instead: with N
   columns and K cards, K mod N = r, it spans N - r + 1 cells, which fills every row. :has() counts
   the cards; nothing in the markup knows about it. On one column nothing spans.
   ============================================================================================= */

.ctt-cc[b-iwv5ytg3ca] {
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    min-width: 0;
}

.ctt-cc__grid[b-iwv5ytg3ca] {
    --cc-cols: 1;
    display: grid;
    grid-template-columns: repeat(var(--cc-cols), minmax(0, 1fr));
    gap: var(--space-4);
    min-width: 0;
}

@container (min-width: 30rem) {
    .ctt-cc__grid[b-iwv5ytg3ca] {
        --cc-cols: 2;
        grid-auto-rows: 1fr;
    }

    /* Two columns, an odd count: "You are in" takes the whole first row. */
    .ctt-cc__grid:has(> :nth-child(2n+1):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: span 2;
    }
}

@container (min-width: 46rem) {
    .ctt-cc__grid[b-iwv5ytg3ca] {
        --cc-cols: 3;
    }

    .ctt-cc__grid:has(> :nth-child(2n+1):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: auto;
    }

    .ctt-cc__grid:has(> :nth-child(3n+1):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: span 3;
    }

    .ctt-cc__grid:has(> :nth-child(3n+2):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: span 2;
    }
}

@container (min-width: 64rem) {
    .ctt-cc__grid[b-iwv5ytg3ca] {
        --cc-cols: 4;
    }

    .ctt-cc__grid:has(> :nth-child(2n+1):last-child) > :first-child[b-iwv5ytg3ca],
    .ctt-cc__grid:has(> :nth-child(3n+1):last-child) > :first-child[b-iwv5ytg3ca],
    .ctt-cc__grid:has(> :nth-child(3n+2):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: auto;
    }

    .ctt-cc__grid:has(> :nth-child(4n+1):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: span 4;
    }

    .ctt-cc__grid:has(> :nth-child(4n+2):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: span 3;
    }

    .ctt-cc__grid:has(> :nth-child(4n+3):last-child) > :first-child[b-iwv5ytg3ca] {
        grid-column: span 2;
    }
}

/* ---------------------------------------------------------------------------------------------
   One card
   --------------------------------------------------------------------------------------------- */

.ctt-cc__card[b-iwv5ytg3ca] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
    padding: var(--card-pad);
    border: 0;
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
}

/* The status is a thick leading edge, the same mark the kit's tiles use. Green under the limit,
   amber close, red over (owner, 3 Oct 2026: "a green check mark ... the broken terms in red"). */
.ctt-cc__card--ok[b-iwv5ytg3ca] {
    box-shadow: inset var(--edge) 0 0 0 var(--ok), var(--elev-card);
}

.ctt-cc__card--warn[b-iwv5ytg3ca] {
    box-shadow: inset var(--edge) 0 0 0 var(--warn), var(--elev-card);
}

.ctt-cc__card--crit[b-iwv5ytg3ca] {
    box-shadow: inset var(--edge) 0 0 0 var(--crit), var(--elev-card);
}

.ctt-cc__card--today[b-iwv5ytg3ca] {
    background-color: var(--accent-wash);
}

.ctt-cc__eyebrow[b-iwv5ytg3ca] {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--accent);
}

.ctt-cc__top[b-iwv5ytg3ca] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.ctt-cc__top[b-iwv5ytg3ca]  .ctt-hint {
    margin-left: auto;
}

.ctt-cc__name[b-iwv5ytg3ca] {
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
    font-size: var(--text-lg);
    line-height: var(--leading-snug);
    font-weight: var(--weight-bold);
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* Where you are today is the one name on the band that is the answer, so it is bigger. */
.ctt-cc__card--today .ctt-cc__name[b-iwv5ytg3ca] {
    font-size: var(--text-xl);
    line-height: var(--leading-tight);
}

.ctt-cc__figure[b-iwv5ytg3ca] {
    margin: 0;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-2);
    color: var(--ink);
}

.ctt-cc__figure--ok[b-iwv5ytg3ca] {
    color: var(--ok);
}

.ctt-cc__figure--warn[b-iwv5ytg3ca] {
    color: var(--warn);
}

.ctt-cc__figure--crit[b-iwv5ytg3ca] {
    color: var(--crit);
}

/* The verdict chip sits right under the number it judges. The figure's own gap is enough. */
.ctt-cc__verdict[b-iwv5ytg3ca] {
    display: flex;
    margin-top: calc(-1 * var(--space-1));
}

.ctt-cc__num[b-iwv5ytg3ca] {
    font-size: var(--text-figure);
    line-height: var(--leading-tight);
    font-weight: var(--weight-bold);
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.ctt-cc__of[b-iwv5ytg3ca] {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* Words in place of a number. Large enough to read as the answer, never styled as a figure. */
.ctt-cc__words[b-iwv5ytg3ca] {
    margin: 0;
    font-size: var(--text-md);
    line-height: var(--leading-snug);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

/* The bar. The solid part is the count; the hatched part is how far the dates with no record
   could carry it. Told apart by pattern as well as colour. No outline: the track is the well. */
.ctt-cc__bar[b-iwv5ytg3ca] {
    display: flex;
    width: 100%;
    height: var(--space-3);
    overflow: hidden;
    border-radius: var(--radius-pill);
    background-color: var(--sunken);
}

.ctt-cc__card--today .ctt-cc__bar[b-iwv5ytg3ca] {
    background-color: var(--surface);
}

.ctt-cc__fill[b-iwv5ytg3ca] {
    height: 100%;
    background-color: var(--ink);
}

.ctt-cc__fill--ok[b-iwv5ytg3ca] {
    background-color: var(--ok);
}

.ctt-cc__fill--warn[b-iwv5ytg3ca] {
    background-color: var(--warn);
}

.ctt-cc__fill--crit[b-iwv5ytg3ca] {
    background-color: var(--crit);
}

.ctt-cc__gapfill[b-iwv5ytg3ca] {
    height: 100%;
    background-image: repeating-linear-gradient(
        45deg,
        var(--warn) 0,
        var(--warn) 2px,
        transparent 2px,
        transparent 6px);
}

.ctt-cc__period[b-iwv5ytg3ca],
.ctt-cc__gapline[b-iwv5ytg3ca] {
    margin: 0;
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    color: var(--muted);
}

.ctt-cc__gapline[b-iwv5ytg3ca] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--ink);
}

.ctt-cc__gapline > i[b-iwv5ytg3ca] {
    color: var(--warn);
}

.ctt-cc__bottom[b-iwv5ytg3ca] {
    margin-top: auto;
    padding-top: var(--space-1);
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.ctt-cc__detail[b-iwv5ytg3ca] {
    margin-left: auto;
}

/* What the limit is for (owner, 3 Oct 2026). Small, muted, the card's last line; wraps on a phone. */
.ctt-cc__footer[b-iwv5ytg3ca] {
    margin: calc(-1 * var(--space-2)) 0 0;
    padding-top: var(--space-2);
    border-top: 1px solid var(--rule);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    color: var(--muted);
}

/* The US tracker tiles are the kit's StatTile; only their cell is set here. */
.ctt-cc__tile[b-iwv5ytg3ca] {
    min-width: 0;
}

/* The tile fills its cell, so it is as tall as the country cards beside it. */
.ctt-cc__tile[b-iwv5ytg3ca]  > .ctt-tile {
    height: 100%;
}

/* Its chips and buttons sit on the floor, level with the country cards' bottom row. Whichever comes
   first after the figure and caption takes the slack. */
.ctt-cc__tile[b-iwv5ytg3ca]  > .ctt-tile > .ctt-tile__chips,
.ctt-cc__tile[b-iwv5ytg3ca]  > .ctt-tile > .ctt-tile__caption + .ctt-more,
.ctt-cc__tile[b-iwv5ytg3ca]  > .ctt-tile > .ctt-tile__value + .ctt-more {
    margin-top: auto;
}

/* A chip longer than a narrow card wraps inside it instead of running out past the card's edge. */
.ctt-cc__grid[b-iwv5ytg3ca]  .ctt-chip-row {
    min-width: 0;
    max-width: 100%;
}

.ctt-cc__grid[b-iwv5ytg3ca]  .ctt-chip {
    white-space: normal;
}

.ctt-cc__none[b-iwv5ytg3ca] {
    margin: 0;
    font-size: var(--text-md);
    color: var(--muted);
}

/* ---------------------------------------------------------------------------------------------
   The whole card is the button (owner's review, 3 October 2026).

   The card's own "Details" button is stretched over the card with ::after, so a tap anywhere on it
   opens the details - one real <button>, so a keyboard and a screen reader still see exactly one
   control. The few controls drawn on top of it (chips, "Check a date", an info icon) are lifted
   above the stretch so they keep their own job. Every tap target is at least 44px.
   --------------------------------------------------------------------------------------------- */

.ctt-cc__card--tap[b-iwv5ytg3ca] {
    position: relative;
    cursor: pointer;
}

.ctt-cc__card--tap:hover[b-iwv5ytg3ca] {
    box-shadow: inset 0 0 0 2px var(--rule), var(--elev-card);
}

.ctt-cc__card--tap.ctt-cc__card--ok:hover[b-iwv5ytg3ca] {
    box-shadow: inset var(--edge) 0 0 0 var(--ok), inset 0 0 0 2px var(--rule), var(--elev-card);
}

.ctt-cc__card--tap.ctt-cc__card--warn:hover[b-iwv5ytg3ca] {
    box-shadow: inset var(--edge) 0 0 0 var(--warn), inset 0 0 0 2px var(--rule), var(--elev-card);
}

.ctt-cc__card--tap.ctt-cc__card--crit:hover[b-iwv5ytg3ca] {
    box-shadow: inset var(--edge) 0 0 0 var(--crit), inset 0 0 0 2px var(--rule), var(--elev-card);
}

.ctt-cc__card--tap .ctt-cc__detail[b-iwv5ytg3ca]::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--radius-md);
}

.ctt-cc__detail[b-iwv5ytg3ca],
.ctt-cc__check[b-iwv5ytg3ca] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

.ctt-cc__check[b-iwv5ytg3ca] {
    position: relative;
    z-index: 1;
}

.ctt-cc__card--tap[b-iwv5ytg3ca]  .ctt-chip-row,
.ctt-cc__card--tap[b-iwv5ytg3ca]  .ctt-chip,
.ctt-cc__card--tap[b-iwv5ytg3ca]  .ctt-hint {
    position: relative;
    z-index: 1;
}

/* The info icon's invisible hit area, grown to 44px. */
.ctt-cc[b-iwv5ytg3ca]  .ctt-hint::after {
    inset: -0.875rem;
}

/* A two-line title (the US card) keeps its info icon level with the first line. */
.ctt-cc__top[b-iwv5ytg3ca] {
    align-items: flex-start;
}

.ctt-cc__top[b-iwv5ytg3ca]  .ctt-hint {
    margin-top: 0.35rem;
}

/* "Also this year: Albania 30 · Georgia 50 · United Kingdom 90 days" - one plain line. */
.ctt-cc__also[b-iwv5ytg3ca] {
    margin: 0;
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.ctt-cc__also-item[b-iwv5ytg3ca] {
    white-space: nowrap;
}
/* /Components/Dashboard/FeieCardDateCheck.razor.rz.scp.css */
/* "Check a date" for the US foreign income rule. Colour comes from tokens only, and each outcome
   also has its own words, so colour is never the only signal. */

.ctt-feie-check[b-set4rw22ij] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
}

.ctt-feie-check__form[b-set4rw22ij] {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.ctt-feie-check__label[b-set4rw22ij] {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-feie-check__row[b-set4rw22ij] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* The date box: the native date input, its own text hidden, with "3 Oct 2026" drawn over it. */
.ctt-feie-check__date[b-set4rw22ij] {
    position: relative;
    flex: 1 1 10rem;
    max-width: 14rem;
}

.ctt-feie-check__date > input[b-set4rw22ij] {
    width: 100%;
    min-height: 44px;
    color: transparent;
    cursor: pointer;
}

/* The picker's own icon is stretched over the whole box, so a click anywhere opens the picker
   (Chromium and Edge; Firefox and phones open it on any tap already). */
.ctt-feie-check__date > input[b-set4rw22ij]::-webkit-calendar-picker-indicator {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    opacity: 0;
    cursor: pointer;
}

.ctt-feie-check__date > input[b-set4rw22ij]::-webkit-datetime-edit {
    color: transparent;
}

.ctt-feie-check__shown[b-set4rw22ij] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    padding: 0 0.75rem;
    pointer-events: none;
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-feie-check__row > .btn[b-set4rw22ij] {
    min-height: 44px;
}

.ctt-feie-check__answer[b-set4rw22ij] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--ink);
}

.ctt-feie-check__answer > p[b-set4rw22ij] {
    margin: 0;
}

.ctt-feie-check__answer--meets[b-set4rw22ij] {
    background-color: var(--ok-wash);
    box-shadow: inset 3px 0 0 0 var(--ok);
}

.ctt-feie-check__answer--short[b-set4rw22ij] {
    background-color: var(--warn-wash);
    box-shadow: inset 3px 0 0 0 var(--warn);
}

.ctt-feie-check__answer--none[b-set4rw22ij] {
    box-shadow: inset 3px 0 0 0 var(--rule);
}

.ctt-feie-check__headline[b-set4rw22ij] {
    font-size: var(--text-lg);
    line-height: var(--leading-snug);
    font-weight: var(--weight-semibold);
}

.ctt-feie-check__verdict[b-set4rw22ij] {
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
}

.ctt-feie-check__missing[b-set4rw22ij] {
    font-weight: var(--weight-semibold);
}

.ctt-feie-check__ending[b-set4rw22ij],
.ctt-feie-check__note[b-set4rw22ij] {
    font-size: var(--text-sm);
    color: var(--muted);
}

.ctt-feie-check__note[b-set4rw22ij] {
    margin: 0;
}
/* /Components/Dashboard/IncludePlannedTrips.razor.rz.scp.css */
/* The "Include planned trips" switch and its note. One quiet row above the counts: it changes
   what every number below means, so it sits above them, but it is not a card. Tokens only. */

.ctt-plans-switch[b-lg0u69a0i5] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    min-width: 0;
}

.ctt-plans-switch .ctt-switch[b-lg0u69a0i5] {
    margin: 0;
}

.ctt-plans-switch__note[b-lg0u69a0i5] {
    margin: 0;
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    background-color: var(--accent-wash);
    color: var(--ink);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
}

.ctt-plans-switch__note > i[b-lg0u69a0i5] {
    color: var(--accent);
}
/* /Components/Dashboard/NowLine.razor.rz.scp.css */
/*
    The line at the top of Home. Big and bold, one glance: the answer before any card.
    Every colour and size is a token, so dark theme follows on its own.
*/

.ctt-now[b-uzzwkliytt] {
    /* Tucked up under the heading: it belongs to it, not to the cards below. */
    margin: calc(-1 * var(--space-3)) 0 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--ink);
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
}

/* Not a sentence to read: words only, so the "No entry" line is quiet, not an alarm. */
.ctt-now--noentry[b-uzzwkliytt] {
    color: var(--muted);
}

/* Flex, not inline text: Razor drops the space between the two pieces, and a wrapping flex row
   gives the gap and the break point in one place. */
.ctt-now__text[b-uzzwkliytt] {
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    column-gap: 0.35em;
}

/* The count stays whole, so a narrow phone wraps between the two pieces. The place may wrap inside
   itself: a long country name must never push the page wider than the phone. */
.ctt-now__count[b-uzzwkliytt] {
    white-space: nowrap;
}

/* The count is the card's number, shown again below: here it is the quieter half of the line. */
.ctt-now__count[b-uzzwkliytt] {
    color: var(--muted);
    font-weight: var(--weight-medium);
}

.ctt-now__icon[b-uzzwkliytt] {
    flex: none;
    font-size: 1.25em;
    line-height: 1;
    color: var(--muted);
}

/* The flag is a picture, not text, so it never shrinks when the line wraps. */
.ctt-now[b-uzzwkliytt]  .ctt-flag {
    flex: none;
}

@media (min-width: 600px) {
    .ctt-now[b-uzzwkliytt] {
        font-size: var(--text-lg);
    }
}
/* /Components/Dashboard/RecentCrossings.razor.rz.scp.css */
/* =============================================================================================
   Recent crossings, on the dashboard.

   Scoped. Every element below is rendered by RecentCrossings itself, so plain selectors are right;
   the chips and the info icon are child components and are NOT styled from here - their look is
   the kit's, in wwwroot/css/app.css, and only their position is set (with ::deep).

   A gap and a transit are drawn differently, as on the Crossings page: a gap is amber, a transit
   is grey. Colour is never the only signal - each also has its own icon and its own label.
   Tokens only.
   ============================================================================================= */

.ctt-recent[b-uj9xhwrdki] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
}

.ctt-recent__head[b-uj9xhwrdki] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.ctt-recent__head[b-uj9xhwrdki]  .ctt-hint {
    margin-left: auto;
}

/* The same size as the map heading beside it, so the two halves of the bottom band line up. */
.ctt-recent__title[b-uj9xhwrdki] {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-lg);
    line-height: var(--leading-snug);
    font-weight: var(--weight-bold);
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* The section badge, the same one every dashboard section head carries. */
.ctt-recent__title > i[b-uj9xhwrdki] {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-sm);
    background-color: var(--accent-wash);
    color: var(--accent);
    font-size: var(--text-md);
    line-height: 1;
}

/* A card, like the rest of the dashboard: lifted, rounded, no hairline round the outside. The
   rules BETWEEN rows stay - a list needs them - and are the only lines on it. */
.ctt-recent__list[b-uj9xhwrdki] {
    margin: 0;
    padding: 0;
    list-style: none;
    border: 0;
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
    overflow: hidden;
}

/* One line per crossing where there is room; the date and the country wrap under each other where there is not, so a phone never scrolls sideways. */
.ctt-recent__item[b-uj9xhwrdki] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-3);
    min-height: 3.25rem;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--rule);
    font-size: var(--text-base);
    color: var(--ink);
}

.ctt-recent__item:last-child[b-uj9xhwrdki] {
    border-bottom: 0;
}

.ctt-recent__icon[b-uj9xhwrdki] {
    color: var(--muted);
    line-height: 1;
}

.ctt-recent__date[b-uj9xhwrdki] {
    min-width: 7.5rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ctt-recent__what[b-uj9xhwrdki] {
    flex: 1 1 10rem;
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
}

.ctt-recent__entered[b-uj9xhwrdki] {
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-recent__chips[b-uj9xhwrdki] {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--space-1);
}

/* ---- a gap: amber, because the record does not know. ---- */
.ctt-recent__item--gap[b-uj9xhwrdki] {
    background-color: var(--warn-wash);
    box-shadow: inset var(--edge) 0 0 0 var(--warn);
}

.ctt-recent__item--gap .ctt-recent__icon[b-uj9xhwrdki] {
    color: var(--warn);
}

/* ---- in transit: grey, because it is known. Never the gap's amber. ---- */
.ctt-recent__item--transit[b-uj9xhwrdki] {
    background-color: var(--sunken);
    box-shadow: inset var(--edge) 0 0 0 var(--muted);
}

/* The same height as the map's "List of places" toggle beside it (a Disclosure: 2.75rem), so the
   two cards above them end on one line. Also a full-size tap target. */
.ctt-recent__foot[b-uj9xhwrdki] {
    margin: 0;
    min-height: 2.75rem;
    display: flex;
    align-items: center;
    font-size: var(--text-sm);
}

.ctt-recent__foot > a[b-uj9xhwrdki] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--accent);
}

/* ---- beside the map: the list card fills the cell, so its bottom lines up with the map's. ----
   The page stretches the two cells to one height (Dashboard.razor.css); the list takes whatever
   the heading and the link leave. Lines stay at the top; spare room is plain card under them. */
.ctt-recent[b-uj9xhwrdki] {
    height: 100%;
}

.ctt-recent__list[b-uj9xhwrdki] {
    flex: 1 1 auto;
}

/* ---- a phone: the first RecentCrossingsModel.PhoneCount lines only; the model marks the rest. ---- */
@media (max-width: 575px) {
    .ctt-recent__item--wide[b-uj9xhwrdki] {
        display: none;
    }

    .ctt-recent__item:has(+ .ctt-recent__item--wide)[b-uj9xhwrdki] {
        border-bottom: 0;
    }
}
/* /Components/Dashboard/SchengenStrip.razor.rz.scp.css */
/* =============================================================================================
   The Schengen 180-day strip. THE HERO OF THE APP, and styled as one.

   It is the one place on the dashboard where the design spends its boldness: the biggest corner
   radius, the most room, and a figure at 80px in the heaviest weight the typeface has. Everything
   else on the page is quieter so that this is where the eye lands. The strip under it reads like
   the barcode on a boarding pass - 180 marks, one per date, solid where the day counts.

   SCOPED, AND NO ::deep. Every element styled here is rendered by SchengenStrip.razor itself, so it
   carries this component's scope attribute and a plain selector matches it. The two children it
   uses - InfoHint and StatusChip - are styled by the kit in wwwroot/css/app.css and are not touched
   from here. If a rule is ever added for markup a CHILD component renders, it must be written ::deep
   (see the comment at the top of Layout/MainLayout.razor.css), or it compiles to a selector that
   matches nothing.

   The card itself is the kit's .ctt-tile, which owns the surface, the shadow and the status edge.
   This sheet only gives it more room and rounder corners through .ctt-s180, and never restyles a
   kit class.

   COLOUR. Tokens only. --ok, --warn and --crit are semantic (safe / watch / breach) and a counted day
   is neither: it is a plain fact, so it is drawn in --ink. --accent is structure, used only for the
   title badge and the look-ahead marker, which is a pointer and not a verdict. Every state is also
   told apart by shape - a fill, an outline, hatching, a faded mark - so the strip reads without
   colour.

   LAYOUT. Laid out month by month. On a wide container all months sit in one row and each month's
   width follows its number of days, so the whole strip is one row of marks. On a narrower
   container the months wrap - three to a row, then one - with every month on a 31-column grid, so
   the squares stay a usable size and there is never a horizontal page scroll. A container query, not
   a media query: the strip is the same whatever column the page puts it in.
   ============================================================================================= */

.ctt-s180[b-cfgy19fenx] {
    container-type: inline-size;
    min-width: 0;
    gap: var(--space-5);
    border-radius: var(--radius-lg);
    padding: var(--space-5) var(--space-4);
}

@media (min-width: 40rem) {
    .ctt-s180[b-cfgy19fenx] {
        padding: var(--space-6);
    }
}

.ctt-s180__head[b-cfgy19fenx] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
}

.ctt-s180__title[b-cfgy19fenx] {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* The section badge: the icon in a teal wash. The same badge marks every section head on the
   dashboard, so the four sections read as one set. Structure, not a verdict. */
.ctt-s180__title > i[b-cfgy19fenx] {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-sm);
    background-color: var(--accent-wash);
    color: var(--accent);
    font-size: var(--text-md);
    line-height: 1;
}

/* ---------------------------------------------------------------------------------------------
   The hero: big numbers, then the next date and the warning chips beside them. Wraps on a phone,
   so nothing has a fixed width. The figure's COLOUR is the kit's (.ctt-tile__figure--warn and so on,
   in app.css); this sheet only sets its size, and never writes a semantic colour itself.
   --------------------------------------------------------------------------------------------- */

.ctt-s180__hero[b-cfgy19fenx] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-5) var(--space-7);
}

.ctt-s180__stat[b-cfgy19fenx] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* 80px on a laptop, never under 52px on the narrowest phone. Two-digit counts at this size still
   leave room for the unit beside them at 320px. */
.ctt-s180__figure[b-cfgy19fenx] {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    font-size: clamp(var(--text-figure), 15cqi, var(--text-figure-lg));
    font-weight: var(--weight-bold);
    line-height: 0.95;
    letter-spacing: -0.03em;
}

.ctt-s180__unit[b-cfgy19fenx] {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    letter-spacing: 0;
    color: var(--muted);
}

/* The label under the figure. Second in the order of reading, so ink, not muted. */
.ctt-s180__caption[b-cfgy19fenx] {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    color: var(--ink);
}

/* No figures: a few bold words where the number would be. */
.ctt-s180__short[b-cfgy19fenx] {
    margin: 0;
    font-size: var(--text-xl);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    letter-spacing: -0.01em;
    color: var(--ink);
}

.ctt-s180__aside[b-cfgy19fenx] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
    padding-bottom: var(--space-1);
}

.ctt-s180__next[b-cfgy19fenx] {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    color: var(--ink);
}

/* ---------------------------------------------------------------------------------------------
   The strip
   --------------------------------------------------------------------------------------------- */

.ctt-s180__frame[b-cfgy19fenx] {
    min-width: 0;
}

.ctt-s180__strip[b-cfgy19fenx] {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--space-2);
    min-width: 0;
}

/* One month. Its share of the row is its number of days, so a mark is the same width in every
   month. --days is set on the element by the component. */
.ctt-s180__group[b-cfgy19fenx] {
    flex: var(--days) 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.ctt-s180__cells[b-cfgy19fenx] {
    display: grid;
    grid-template-columns: repeat(var(--days), minmax(0, 1fr));
    gap: 1px;
}

.ctt-s180__month[b-cfgy19fenx] {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
}

/* A month with only a few days showing has no room for its label on the one-row strip. */
.ctt-s180__group--short .ctt-s180__month[b-cfgy19fenx] {
    visibility: hidden;
}

/* ---------------------------------------------------------------------------------------------
   The marks. On the one-row strip a mark is a few pixels wide, so it is drawn tall, like a bar of
   a barcode; on the wrapped strip it is a true square with softened corners.
   --------------------------------------------------------------------------------------------- */

.ctt-s180__cell[b-cfgy19fenx] {
    display: block;
    height: 2.75rem;
    min-width: 0;
    border-radius: 1.5px;
}

/* Counted: solid. */
.ctt-s180__cell--counted[b-cfgy19fenx] {
    background-color: var(--ink);
}

/* Not counted: pale, with an outline so it holds its shape against the card. */
.ctt-s180__cell--not-counted[b-cfgy19fenx] {
    background-color: var(--sunken);
    box-shadow: inset 0 0 0 1px var(--rule);
}

/* No record: empty and hatched. Never the same as "not counted". */
.ctt-s180__cell--gap[b-cfgy19fenx] {
    background-color: var(--surface);
    background-image: repeating-linear-gradient(
        45deg,
        var(--muted) 0,
        var(--muted) 1px,
        transparent 1px,
        transparent 4px
    );
    box-shadow: inset 0 0 0 1px var(--rule);
}

/* Ahead of today: faded, with a dotted outline. Not a record of anything. */
.ctt-s180__cell--ahead[b-cfgy19fenx] {
    background-color: var(--sunken);
    outline: 1px dotted var(--muted);
    outline-offset: -1px;
    opacity: 0.45;
}

/* The look-ahead date: a heavy outline, at full strength, on top of its neighbours - and a small
   accent pointer above it. The cell keeps its own fill, because the date may be a counted day, a
   missing day or a day ahead, and the marker must not hide which. */
.ctt-s180__cell--marker[b-cfgy19fenx] {
    position: relative;
    z-index: 1;
    opacity: 1;
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

/* THE POINTER. The legend's marker swatch and the swatch in front of "Days left run out after ..."
   are drawn as this same shape. An outlined square there read as a checkbox a person could tick;
   a solid pointer cannot be mistaken for a control. */
.ctt-s180__cell--marker[b-cfgy19fenx]::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: calc(100% + 0.25rem);
    width: 0.875rem;
    height: 0.625rem;
    transform: translateX(-50%);
    background-color: var(--accent);
    clip-path: polygon(0 0, 100% 0, 50% 100%);
    pointer-events: none;
}

/* ---------------------------------------------------------------------------------------------
   Under the strip
   --------------------------------------------------------------------------------------------- */

/* What the limit is for (owner, 3 Oct 2026). Small, muted, the band's last line. */
.ctt-s180__footer[b-cfgy19fenx] {
    margin: 0;
    padding-top: var(--space-2);
    border-top: 1px solid var(--rule);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    color: var(--muted);
}

.ctt-s180__legend[b-cfgy19fenx] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-5);
    font-size: var(--text-sm);
    color: var(--muted);
}

.ctt-s180__legend-item[b-cfgy19fenx] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* The legend swatches repeat the mark styles exactly, at a readable size. */
.ctt-s180__swatch[b-cfgy19fenx] {
    display: inline-block;
    flex: 0 0 auto;
    width: 1rem;
    height: 1rem;
    border-radius: 3px;
}

.ctt-s180__swatch--counted[b-cfgy19fenx] {
    background-color: var(--ink);
}

.ctt-s180__swatch--not-counted[b-cfgy19fenx] {
    background-color: var(--sunken);
    box-shadow: inset 0 0 0 1px var(--rule);
}

.ctt-s180__swatch--gap[b-cfgy19fenx] {
    background-color: var(--surface);
    background-image: repeating-linear-gradient(
        45deg,
        var(--muted) 0,
        var(--muted) 1px,
        transparent 1px,
        transparent 4px
    );
    box-shadow: inset 0 0 0 1px var(--rule);
}

.ctt-s180__swatch--ahead[b-cfgy19fenx] {
    background-color: var(--sunken);
    outline: 1px dotted var(--muted);
    outline-offset: -1px;
    opacity: 0.45;
}

/* The pointer that sits above the marked date on the strip, at the same size. A solid shape, not an
   outline: an outlined square here looked like a checkbox. */
.ctt-s180__swatch--marker[b-cfgy19fenx] {
    width: 0.875rem;
    height: 0.625rem;
    border-radius: 0;
    background-color: var(--accent);
    clip-path: polygon(0 0, 100% 0, 50% 100%);
}

/* In front of the "Days left run out after ..." line, the pointer sits on the FIRST line of text, so
   it still points at the sentence when a phone wraps it onto two. */
.ctt-s180__next .ctt-s180__swatch--marker[b-cfgy19fenx] {
    align-self: flex-start;
    margin-top: calc((1lh - 0.625rem) / 2);
}

/* ---------------------------------------------------------------------------------------------
   Narrower containers: wrap by month, every month on a 31-column grid, true squares.
   --------------------------------------------------------------------------------------------- */

@container (max-width: 60rem) {
    .ctt-s180__strip[b-cfgy19fenx] {
        flex-wrap: wrap;
        row-gap: var(--space-4);
        column-gap: var(--space-4);
    }

    .ctt-s180__group[b-cfgy19fenx] {
        flex: 0 0 calc((100% - 2 * var(--space-4)) / 3);
    }

    .ctt-s180__cells[b-cfgy19fenx] {
        grid-template-columns: repeat(31, minmax(0, 1fr));
        gap: 2px;
    }

    .ctt-s180__cell[b-cfgy19fenx] {
        height: auto;
        aspect-ratio: 1;
        border-radius: 2px;
    }

    .ctt-s180__group--short .ctt-s180__month[b-cfgy19fenx] {
        visibility: visible;
    }
}

@container (max-width: 36rem) {
    .ctt-s180__group[b-cfgy19fenx] {
        flex: 0 0 100%;
    }
}

/* ---------------------------------------------------------------------------------------------
   "Last day: 13 Oct" under the "Left" figure, and the phone fold for the 180 squares.
   --------------------------------------------------------------------------------------------- */

.ctt-s180__lastday[b-cfgy19fenx] {
    font-size: var(--text-md);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    color: var(--ink);
}

.ctt-s180__days[b-cfgy19fenx] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* The toggle exists only on phones. On wider screens the squares are always shown. */
.ctt-s180 button.ctt-s180__toggle[b-cfgy19fenx] {
    display: none;
    min-height: 44px;
    align-self: flex-start;
}

@media (max-width: 599.98px) {
    .ctt-s180 button.ctt-s180__toggle[b-cfgy19fenx] {
        display: inline-flex;
        align-items: center;
    }

    .ctt-s180__days:not(.ctt-s180__days--open)[b-cfgy19fenx] {
        display: none;
    }

    .ctt-s180__toggle[aria-expanded="true"] > i[b-cfgy19fenx] {
        transform: rotate(90deg);
    }
}
/* /Components/Dashboard/SpeedTestCard.razor.rz.scp.css */
/* =============================================================================================
   Internet speed, on the home screen.

   Scoped. The button is the kit's .btn. Numbers only - no verdict colours (owner, 3 Oct 2026).
   ============================================================================================= */

.ctt-speed[b-cuv9h70u26] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
    /* The same card as every other one on the dashboard: lifted, no hairline, the card padding.
       height: 100% so it matches the weather card beside it. */
    height: 100%;
    padding: var(--card-pad);
    border: 0;
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
}

.ctt-speed__head[b-cuv9h70u26] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.ctt-speed__title[b-cuv9h70u26] {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-lg);
    line-height: var(--leading-snug);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-speed__title > i[b-cuv9h70u26] {
    color: var(--accent);
}

.ctt-speed__body[b-cuv9h70u26] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.ctt-speed__body > p[b-cuv9h70u26] {
    margin: 0;
}

/* The big numbers. They wrap onto a second line on a phone rather than scrolling sideways. */
.ctt-speed__figures[b-cuv9h70u26],
.ctt-speed__live[b-cuv9h70u26] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1) var(--space-2);
    color: var(--ink);
}

.ctt-speed__figure[b-cuv9h70u26] {
    font-size: var(--text-figure);
    line-height: var(--leading-tight);
    font-weight: var(--weight-bold);
    font-variant-numeric: tabular-nums;
}

.ctt-speed__unit[b-cuv9h70u26],
.ctt-speed__sep[b-cuv9h70u26] {
    font-size: var(--text-sm);
    color: var(--muted);
}

.ctt-speed__when[b-cuv9h70u26] {
    font-size: var(--text-sm);
    color: var(--muted);
}

.ctt-speed__problem[b-cuv9h70u26] {
    font-size: var(--text-sm);
    color: var(--crit);
}

.ctt-speed__actions > .btn[b-cuv9h70u26] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}

.ctt-speed__credit[b-cuv9h70u26] {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--muted);
}

.ctt-speed__credit > a[b-cuv9h70u26] {
    color: var(--accent);
}
/* /Components/Dashboard/WeatherCard.razor.rz.scp.css */
/* =============================================================================================
   The weather card, on the home screen.

   Scoped; every element is rendered by WeatherCard itself. Tokens only - a raw colour here would
   be the one part of the card that stopped following the theme.
   ============================================================================================= */

.ctt-weather[b-koy9lgylnu] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
    /* The same card as every other one on the dashboard: lifted, no hairline, the card padding.
       height: 100% so it matches the speed card beside it. */
    height: 100%;
    padding: var(--card-pad);
    border: 0;
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
    color: var(--ink);
}

.ctt-weather__head[b-koy9lgylnu] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1) var(--space-3);
}

.ctt-weather__title[b-koy9lgylnu] {
    margin: 0;
    font-size: var(--text-md);
    line-height: var(--leading-snug);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-weather__place[b-koy9lgylnu] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-width: 0;
    font-size: var(--text-sm);
    color: var(--muted);
    overflow-wrap: anywhere;
}

.ctt-weather__now[b-koy9lgylnu] {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.ctt-weather__icon[b-koy9lgylnu] {
    font-size: var(--text-figure);
    line-height: var(--leading-tight);
    color: var(--accent);
}

.ctt-weather__temp[b-koy9lgylnu] {
    margin: 0;
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    font-size: var(--text-figure);
    line-height: var(--leading-tight);
    font-weight: var(--weight-semibold);
    font-variant-numeric: tabular-nums;
}

.ctt-weather__alt[b-koy9lgylnu] {
    font-size: var(--text-sm);
    font-weight: var(--weight-regular);
    color: var(--muted);
}

.ctt-weather__desc[b-koy9lgylnu] {
    margin: 0;
    font-size: var(--text-base);
    font-weight: var(--weight-medium);
}

.ctt-weather__facts[b-koy9lgylnu] {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-4);
    font-size: var(--text-sm);
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.ctt-weather__credit[b-koy9lgylnu] {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--muted);
}

.ctt-weather__credit > a[b-koy9lgylnu] {
    color: var(--accent);
}
/* /Components/Import/ImportFormatHelp.razor.rz.scp.css */
/*
    Scoped to ImportFormatHelp. Tokens only.
*/

/* Three short rules, tight, so the strip reads as a strip rather than as prose. */
.ctt-quickrules[b-0sdiho3hni] {
    margin: 0 0 var(--space-4) 0;
    padding-left: var(--space-4);
    color: var(--ink);
    font-size: var(--text-sm);
}

.ctt-quickrules li + li[b-0sdiho3hni] {
    margin-top: var(--space-1);
}

/*
    The example. A well inside the card, monospaced, with tabular figures so the dates line up under
    each other - a column of ragged dates is harder to copy correctly.
*/
.ctt-example[b-0sdiho3hni] {
    background-color: var(--sunken);
    border: 0;
    border-radius: var(--radius-sm);
    padding: var(--space-3);
    margin: 0 0 var(--space-3) 0;
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
    overflow-x: auto;
}

.ctt-example--sm[b-0sdiho3hni] {
    font-size: var(--text-xs);
    padding: var(--space-2) var(--space-3);
}

.ctt-example:focus-visible[b-0sdiho3hni] {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}
/* /Components/Import/ImportPreview.razor.rz.scp.css */
/*
    Scoped to ImportPreview. Tokens only.

    The head row puts the crossing count and its chips beside the dates and the countries, so the whole
    of level 1 fits above the disclosures with no scroll.
*/

.ctt-preview-head[b-lz0vw44rgl] {
    display: grid;
    grid-template-columns: minmax(14rem, 20rem) 1fr;
    gap: var(--space-4);
    align-items: start;
    margin-bottom: var(--space-4);
}

@media (max-width: 48rem) {
    .ctt-preview-head[b-lz0vw44rgl] {
        grid-template-columns: 1fr;
    }
}

/*
    The one sentence that disqualifies the figure above it. Full contrast ink on a faint wash, not
    muted and not a filled red block: it has to be read, and a card filled red is a card the reader
    learns to close.
*/
.ctt-preview-head__alarm[b-lz0vw44rgl] {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    margin: var(--space-2) 0 0;
    padding: var(--space-3) var(--space-4);
    box-shadow: inset var(--edge) 0 0 0 var(--crit);
    border-radius: var(--radius-sm);
    background: var(--crit-wash);
    color: var(--ink);
    font-size: var(--text-sm);
}

/* A short definition list: label on the left, value on the right, no table furniture. */
.ctt-facts[b-lz0vw44rgl] {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-1) var(--space-4);
    margin: 0;
}

.ctt-facts dt[b-lz0vw44rgl] {
    color: var(--muted);
    font-weight: var(--weight-regular);
    font-size: var(--text-sm);
    white-space: nowrap;
}

.ctt-facts dd[b-lz0vw44rgl] {
    color: var(--ink);
    margin: 0;
    font-size: var(--text-sm);
}

/* The crossings table can be long. It scrolls inside its own box, never the page. */
.ctt-preview-table[b-lz0vw44rgl] {
    max-height: 24rem;
    overflow-y: auto;
}
/* /Components/Import/ImportProblemList.razor.rz.scp.css */
/*
    Scoped to ImportProblemList. Tokens only.

    The washes are the faintest tint the palette has, on purpose. This list can be a hundred rows long
    and a saturated row colour repeated a hundred times is unreadable - and unreadable is the same as
    hidden for a list whose whole job is to be read.

    Colour is never the only signal here: every row carries its line number, the text as typed, and the
    reason in words.
*/

.ctt-problem-heading[b-bj7i2829dr] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}

.ctt-problem-heading--crit[b-bj7i2829dr] {
    color: var(--crit);
}

.ctt-problem-heading--warn[b-bj7i2829dr] {
    color: var(--warn);
}

.ctt-problem--crit[b-bj7i2829dr] {
    --bs-table-bg: var(--crit-wash);
    --bs-table-accent-bg: var(--crit-wash);
    color: var(--ink);
}

.ctt-problem--warn[b-bj7i2829dr] {
    --bs-table-bg: var(--warn-wash);
    --bs-table-accent-bg: var(--warn-wash);
    color: var(--ink);
}
/* /Components/Import/LedgerExportPanel.razor.rz.scp.css */
/*
    Scoped to LedgerExportPanel. Tokens only.

    The layout puts the tile and the two buttons side by side on a laptop and stacked on a phone, so
    the count, the browser-promise chip and both save buttons are on the first screen with no scroll.
    That is the point: §5 calls this the escape hatch.
*/

.ctt-export[b-07ldyzyp0a] {
    display: grid;
    grid-template-columns: minmax(14rem, 20rem) 1fr;
    gap: var(--space-4);
    align-items: start;
}

@media (max-width: 48rem) {
    .ctt-export[b-07ldyzyp0a] {
        grid-template-columns: 1fr;
    }
}

.ctt-export__actions[b-07ldyzyp0a] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.ctt-export__action[b-07ldyzyp0a] {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    align-items: flex-start;
}

.ctt-export__action p[b-07ldyzyp0a] {
    color: var(--ink);
    max-width: 52ch;
}
/* /Components/Ledger/CountryPicker.razor.rz.scp.css */
/*
    CountryPicker. Tokens only - see LedgerHeaderBar.razor.css for why.
*/

.ctt-cpick[b-5m4f9ikxcz] {
    position: relative;
    min-width: 0;
}

/* Looks like the select it replaced, so the form reads the same. Left-aligned text, 44px tall. */
.ctt-cpick__button[b-5m4f9ikxcz] {
    text-align: left;
    min-height: 2.75rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ctt-cpick__placeholder[b-5m4f9ikxcz] {
    color: var(--muted);
}

.ctt-cpick__panel[b-5m4f9ikxcz] {
    margin-top: var(--space-2);
    border: 1px solid var(--rule);
    border-radius: var(--radius-md);
    background-color: var(--surface);
    overflow: hidden;
}

.ctt-cpick__search[b-5m4f9ikxcz] {
    border: 0;
    border-bottom: 1px solid var(--rule);
    border-radius: 0;
    min-height: 2.75rem;
}

.ctt-cpick__list[b-5m4f9ikxcz] {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 16rem;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.ctt-cpick__group[b-5m4f9ikxcz] {
    padding: var(--space-2) var(--space-3) var(--space-1);
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    background-color: var(--sunken);
}

.ctt-cpick__option[b-5m4f9ikxcz] {
    appearance: none;
    -webkit-appearance: none;
    display: block;
    width: 100%;
    min-height: 2.75rem;
    padding: var(--space-2) var(--space-3);
    border: 0;
    background: none;
    color: var(--ink);
    text-align: left;
    cursor: pointer;
}

.ctt-cpick__option:hover[b-5m4f9ikxcz],
.ctt-cpick__option:focus-visible[b-5m4f9ikxcz] {
    background-color: var(--sunken);
}

.ctt-cpick__option.is-selected[b-5m4f9ikxcz] {
    font-weight: var(--weight-semibold);
}

.ctt-cpick__none[b-5m4f9ikxcz] {
    padding: var(--space-3);
    color: var(--muted);
}
/* /Components/Ledger/LedgerCountryBand.razor.rz.scp.css */
/*
    LedgerCountryBand. Tokens only - see LedgerHeaderBar.razor.css for why.

    Small tiles that wrap: a country name and its nights. Wrapping, never a sideways scroll, and
    never wider than the screen.
*/

.ctt-lband[b-xd6e8ay9l3] {
    margin-bottom: var(--space-5);
    min-width: 0;
}

/* A heading, not a shouted label: sentence case, ink, bold. */
.ctt-lband__heading[b-xd6e8ay9l3] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-2) 0;
    font-size: var(--text-md);
    font-weight: var(--weight-bold);
    color: var(--ink);
}

.ctt-lband__list[b-xd6e8ay9l3] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: var(--space-2);
}

.ctt-lband__item[b-xd6e8ay9l3] {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 3.25rem;
    min-width: 0;
    padding: var(--space-2) var(--space-3);
    background-color: var(--surface);
    border-radius: var(--radius-md);
    box-shadow: var(--elev-card);
}

.ctt-lband__name[b-xd6e8ay9l3] {
    color: var(--ink);
    font-weight: var(--weight-semibold);
    overflow-wrap: anywhere;
}

.ctt-lband__nights[b-xd6e8ay9l3] {
    color: var(--muted);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}
/* /Components/Ledger/LedgerHeaderBar.razor.rz.scp.css */
/*
    LedgerHeaderBar.

    Every value is a token from wwwroot/css/tokens.css, which is generated from design/tokens.json.
    No raw hex, no raw pixel size: a colour written here is a colour that exists on web and nowhere
    else, and this app also has a MAUI head coming.
*/

.ctt-lhead[b-rqlij0ij2v] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.ctt-lhead__what[b-rqlij0ij2v] {
    margin: 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

/* One primary action, then the rest. */
.ctt-lhead__actions[b-rqlij0ij2v] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
}

.ctt-lhead__actions .btn[b-rqlij0ij2v] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2.75rem;
}

/* "More" and its menu. The menu hangs under the button and never runs off the screen. */
.ctt-lhead__more[b-rqlij0ij2v] {
    position: relative;
}

.ctt-lhead__scrim[b-rqlij0ij2v] {
    position: fixed;
    inset: 0;
    z-index: 1000;
}

.ctt-lhead__menu[b-rqlij0ij2v] {
    position: absolute;
    top: calc(100% + var(--space-1));
    /* Hung from the button's RIGHT edge, so it opens back across the screen rather than off it. */
    right: 0;
    z-index: 1001;
    list-style: none;
    margin: 0;
    padding: var(--space-1) 0;
    min-width: 15rem;
    max-width: calc(100vw - 2rem);
    background-color: var(--surface);
    border-radius: var(--radius-md);
    box-shadow: var(--elev-pop);
}

.ctt-lhead__menu button[b-rqlij0ij2v] {
    appearance: none;
    -webkit-appearance: none;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: 2.75rem;
    padding: var(--space-2) var(--space-4);
    border: 0;
    background: none;
    color: var(--ink);
    text-align: left;
    cursor: pointer;
}

.ctt-lhead__menu button:hover[b-rqlij0ij2v],
.ctt-lhead__menu button:focus-visible[b-rqlij0ij2v] {
    background-color: var(--sunken);
}

.ctt-lhead__menu i[b-rqlij0ij2v] {
    color: var(--muted);
}

.ctt-lhead__totals[b-rqlij0ij2v] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
}

.ctt-lhead__stat[b-rqlij0ij2v] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--muted);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

/*
    The open-gap banner. Amber, not red: it is a state to act on, not a limit already passed, and the
    three semantic colours mean one thing each.
*/
.ctt-lbanner[b-rqlij0ij2v] {
    display: flex;
    gap: var(--space-3);
    align-items: flex-start;
    padding: var(--space-4) var(--card-pad);
    background-color: var(--warn-wash);
    border: 0;
    border-radius: var(--radius-md);
    box-shadow: inset var(--edge) 0 0 0 var(--warn), var(--elev-card);
}

.ctt-lbanner__icon[b-rqlij0ij2v] {
    color: var(--warn);
    font-size: var(--text-md);
    line-height: var(--leading-snug);
}

.ctt-lbanner__body[b-rqlij0ij2v] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
}

.ctt-lbanner__line[b-rqlij0ij2v] {
    margin: 0;
    color: var(--ink);
    font-weight: var(--weight-semibold);
}

.ctt-lbanner__body .btn[b-rqlij0ij2v] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}
/* /Components/Ledger/LedgerTable.razor.rz.scp.css */
/*
    LedgerTable. Tokens only - see LedgerHeaderBar.razor.css for why.

    The two rules this file exists to hold in CSS:
      1. A gap row is amber and unmistakable.
      2. A transit row is NOT amber. It is quiet grey, because it is known, and giving it the same
         colour as a gap would say the two are the same kind of fact.

    And the rule the phone review added: NOTHING HERE MAY BE WIDER THAN THE SCREEN. Under 600px the
    table is not drawn at all and the cards are; from 600px up it is the other way round. The table
    also sits in a box that scrolls on its own, so a long note can never push the page sideways.
*/

/* ---------------------------------------------------------------- phone: cards */

.ctt-lcards[b-rjrv9izgrv] {
    list-style: none;
    margin: 0 0 var(--space-4);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
}

.ctt-lcards__group[b-rjrv9izgrv] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-2);
    margin-top: var(--space-2);
    color: var(--muted);
    font-size: var(--text-sm);
}

.ctt-lcards__roundtrip[b-rjrv9izgrv] {
    font-style: italic;
}

.ctt-lcard[b-rjrv9izgrv] {
    background-color: var(--surface);
    border-radius: var(--radius-md);
    box-shadow: var(--elev-card);
    min-width: 0;
    overflow: hidden;
}

/* The whole card is the tap target: well over 44px tall, full width. */
.ctt-lcard__main[b-rjrv9izgrv] {
    appearance: none;
    -webkit-appearance: none;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: 3.5rem;
    padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
    border: 0;
    background: none;
    color: var(--ink);
    text-align: left;
    cursor: pointer;
}

.ctt-lcard__icon[b-rjrv9izgrv] {
    color: var(--muted);
    line-height: 1;
    flex: none;
}

.ctt-lcard__text[b-rjrv9izgrv] {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

.ctt-lcard__country[b-rjrv9izgrv] {
    font-weight: var(--weight-semibold);
    overflow-wrap: anywhere;
}

.ctt-lcard__date[b-rjrv9izgrv] {
    color: var(--muted);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

.ctt-lcard__nights[b-rjrv9izgrv] {
    flex: none;
    white-space: nowrap;
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-weight: var(--weight-medium);
}

.ctt-lcard__chevron[b-rjrv9izgrv] {
    flex: none;
    color: var(--muted);
    line-height: 1;
}

.ctt-lcard__chips[b-rjrv9izgrv] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    padding: 0 var(--space-3) var(--space-3) var(--space-4);
}

/* A gap card: amber edge and wash, amber icon, so colour is never the only signal. */
.ctt-lcard--gap[b-rjrv9izgrv] {
    background-color: var(--warn-wash);
    box-shadow: inset var(--edge) 0 0 0 var(--warn), var(--elev-card);
}

.ctt-lcard--gap .ctt-lcard__icon[b-rjrv9izgrv] {
    color: var(--warn);
}

/* A transit card: grey, never amber. */
.ctt-lcard--transit[b-rjrv9izgrv] {
    background-color: var(--sunken);
    box-shadow: inset var(--edge) 0 0 0 var(--muted), var(--elev-card);
}

/* ---------------------------------------------------------------- wider: the table */

/* The table is a card like every other surface: rounded, lifted, no outer hairline. The rules
   between rows stay - a table of dates needs them. border-collapse: separate is what lets the
   rounded corners clip the cells. */
.ctt-lt[b-rjrv9izgrv] {
    margin-bottom: var(--space-4);
    border-collapse: separate;
    border-spacing: 0;
    border-radius: var(--radius-md);
    box-shadow: var(--elev-card);
    overflow: hidden;
}

.ctt-lt__caption[b-rjrv9izgrv] {
    caption-side: top;
    padding: 0 0 var(--space-3) 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

/* Column heads are labels: sentence case, muted, never shouted in capitals. */
.ctt-lt thead th[b-rjrv9izgrv] {
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    vertical-align: bottom;
    white-space: nowrap;
}

.ctt-lt tbody tr:last-child > td[b-rjrv9izgrv] {
    border-bottom: 0;
}

.ctt-lt__nights-head[b-rjrv9izgrv] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

.ctt-lt__type[b-rjrv9izgrv] {
    width: 2rem;
    text-align: center;
    padding-right: 0;
}

.ctt-lt__date[b-rjrv9izgrv],
.ctt-lt__nights[b-rjrv9izgrv] {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Location checks: a number, right under its heading. */
.ctt-lt__seen[b-rjrv9izgrv] {
    text-align: center;
    width: 1%;
}

/* The note gets the room the trash column and the hours used to take. */
.ctt-lt__note[b-rjrv9izgrv] {
    color: var(--muted);
    font-size: var(--text-sm);
    min-width: 12rem;
    width: 35%;
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- rows */

.ctt-lrow > td[b-rjrv9izgrv] {
    border-color: var(--rule);
}

/* A row you can click to change. */
.ctt-lrow--tap[b-rjrv9izgrv] {
    cursor: pointer;
}

.ctt-lrow--tap:hover > td[b-rjrv9izgrv] {
    background-color: var(--sunken);
}

.ctt-lrow__icon[b-rjrv9izgrv] {
    color: var(--muted);
    line-height: 1;
}

/* The country name is also the row's button, for the keyboard. It looks like text. */
.ctt-lrow__open[b-rjrv9izgrv] {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: 0;
    padding: 0;
    min-height: 2.75rem;
    color: var(--ink);
    font-weight: var(--weight-medium);
    text-align: left;
    cursor: pointer;
}

.ctt-lrow__open:hover[b-rjrv9izgrv] {
    text-decoration: underline;
}

.ctt-lrow__chips[b-rjrv9izgrv] {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    margin-left: var(--space-2);
    vertical-align: middle;
}

.ctt-lrow__sub[b-rjrv9izgrv] {
    display: block;
    color: var(--muted);
    font-size: var(--text-sm);
}

/* ---- a gap. Amber, and the icon is amber too, so colour is never the only signal. ---- */
.ctt-lrow--gap > td[b-rjrv9izgrv] {
    background-color: var(--warn-wash);
    color: var(--ink);
}

.ctt-lrow--gap > td:first-child[b-rjrv9izgrv] {
    box-shadow: inset var(--edge) 0 0 0 var(--warn);
}

.ctt-lrow--gap .ctt-lrow__icon[b-rjrv9izgrv] {
    color: var(--warn);
}

/* ---- in transit. Deliberately different from a gap: grey, not amber. ---- */
.ctt-lrow--transit > td[b-rjrv9izgrv] {
    background-color: var(--sunken);
    color: var(--ink);
}

.ctt-lrow--transit > td:first-child[b-rjrv9izgrv] {
    box-shadow: inset var(--edge) 0 0 0 var(--muted);
}

.ctt-lrow--transit .ctt-lrow__icon[b-rjrv9izgrv] {
    color: var(--muted);
}

/* ---- the header row for a date carrying more than one crossing ---- */
.ctt-lrow--group > td[b-rjrv9izgrv] {
    background-color: var(--sunken);
    color: var(--ink);
    font-size: var(--text-sm);
    border-top: 1px solid var(--rule);
}

.ctt-lrow__group-icon[b-rjrv9izgrv] {
    color: var(--muted);
    margin-right: var(--space-1);
    line-height: 1;
}

.ctt-lrow__route[b-rjrv9izgrv] {
    color: var(--muted);
    margin-left: var(--space-2);
}

.ctt-lrow__roundtrip[b-rjrv9izgrv] {
    color: var(--muted);
    margin-left: var(--space-2);
    font-style: italic;
}

/* ---------------------------------------------------------------- sightings

   How many times the place was seen under a crossing. Just the number now; the hours are in its
   title.

   ONE SIGHTING AND FORTY MUST NOT LOOK THE SAME. That is what these four rungs are for. The weight
   grows with the strength, so the difference is readable without stopping to read the number.

   NO GROUND, NO PILL. The strongest rung used to sit on a filled pill, and on a list of plain
   numbers one filled pill read as a stuck hover or a selected row (the phone review, 3 Oct 2026).
   Weight and ink only.

   NO SEMANTIC COLOUR. Not ok, not warn: strong evidence is not an all-clear about a day count, and a
   single sighting is not a warning.

   A row with no sightings renders no element at all, so there is no rule here for "none".
*/
.ctt-ev[b-rjrv9izgrv] {
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Seen once. Faint on purpose: one instant is the weakest thing this column can say. */
.ctt-ev--once[b-rjrv9izgrv] {
    color: var(--muted);
    font-weight: var(--weight-regular);
}

/* Several sightings inside one hour. More than once, still one moment of the date. */
.ctt-ev--moment[b-rjrv9izgrv] {
    color: var(--muted);
    font-weight: var(--weight-medium);
}

/* An hour or more, less than half the date. */
.ctt-ev--part[b-rjrv9izgrv] {
    color: var(--ink);
    font-weight: var(--weight-medium);
}

/* Twelve hours or more - most of the date is covered. The heaviest weight, and nothing else. */
.ctt-ev--most[b-rjrv9izgrv] {
    color: var(--ink);
    font-weight: var(--weight-bold);
}

/* The heading the sightings hang their explanation on. */
.ctt-lt__know-head[b-rjrv9izgrv] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

/* ---------------------------------------------------------------- which shape

   LAST IN THE FILE ON PURPOSE. These rules hide one shape and show the other, and they have the
   same specificity as the display rules above, so they must come after them to win. */

.ctt-lt-wrap[b-rjrv9izgrv] {
    display: none;
}

@media (min-width: 600px) {
    .ctt-lcards[b-rjrv9izgrv] {
        display: none;
    }

    .ctt-lt-wrap[b-rjrv9izgrv] {
        display: block;
        max-width: 100%;
        overflow-x: auto;
    }
}
/* /Components/Ledger/PlannedTrips.razor.rz.scp.css */
/* Planned trips on the travel log page. Cards in the home screen's style: surface, card shadow, a
   thick leading edge in the verdict colour (ok / warn / crit), nothing coloured otherwise. Tokens
   only, so dark theme follows. One column on a phone, more as the section widens. */

.ctt-plans[b-x4tgbqk5fo] {
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
    margin-bottom: var(--space-5);
}

.ctt-plans__head[b-x4tgbqk5fo] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
}

.ctt-plans__title[b-x4tgbqk5fo] {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    color: var(--ink);
}

.ctt-plans__empty[b-x4tgbqk5fo] {
    margin: 0;
    color: var(--muted);
}

.ctt-plans__grid[b-x4tgbqk5fo] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-3);
}

@container (min-width: 34rem) {
    .ctt-plans__grid[b-x4tgbqk5fo] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@container (min-width: 56rem) {
    .ctt-plans__grid[b-x4tgbqk5fo] {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.ctt-plan[b-x4tgbqk5fo] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
    padding: var(--card-pad);
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
}

.ctt-plan--ok[b-x4tgbqk5fo] {
    box-shadow: inset var(--edge) 0 0 0 var(--ok), var(--elev-card);
}

.ctt-plan--warn[b-x4tgbqk5fo] {
    box-shadow: inset var(--edge) 0 0 0 var(--warn), var(--elev-card);
}

.ctt-plan--crit[b-x4tgbqk5fo] {
    box-shadow: inset var(--edge) 0 0 0 var(--crit), var(--elev-card);
}

.ctt-plan--ended[b-x4tgbqk5fo] {
    opacity: 0.7;
}

/* The whole top of the card is the tap target that opens the edit dialog. */
.ctt-plan__open[b-x4tgbqk5fo] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.ctt-plan__open:focus-visible[b-x4tgbqk5fo] {
    outline: 2px solid var(--accent);
    outline-offset: 4px;
    border-radius: var(--radius-sm);
}

.ctt-plan__name[b-x4tgbqk5fo] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
    overflow-wrap: anywhere;
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    color: var(--ink);
}

.ctt-plan__dates[b-x4tgbqk5fo] {
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-plan__length[b-x4tgbqk5fo] {
    font-size: var(--text-sm);
    color: var(--muted);
}

.ctt-plan__chip[b-x4tgbqk5fo] {
    display: flex;
}
/* /Components/Map/ReadingMap.razor.rz.scp.css */
/*
 * The reading map.
 *
 * TWO KINDS OF SELECTOR IN HERE, and the difference matters. The ctt-map ones style elements this
 * component renders, so Blazor scopes them on its own. Everything under ::deep styles elements
 * LEAFLET creates inside the container - Blazor never sees those, so they carry no scope attribute
 * and only ::deep reaches them.
 *
 * EVERY COLOUR IS A TOKEN. Leaflet ships its own palette, and it is a fixed light one: white
 * controls, white popups, a white-ish attribution strip. Left alone, all three glare on a dark
 * theme, so each is repainted from tokens/tokens.json below and follows the theme like the rest of
 * the app.
 *
 * THE TILE IMAGERY IS DARKENED IN THE DARK THEME, and only there (owner's review, 3 October 2026:
 * a bright white map in the middle of a dark page glares). This replaces the earlier rule that the
 * imagery is never recoloured. A dark tile style would be better, but every free one lives on a
 * host the Content-Security-Policy does not allow (img-src names tile.openstreetmap.org only), and
 * the CSP is not changed for this. So the tile PANE is inverted and turned back to its own hues -
 * land stays land-coloured, water stays blue-ish, only the lightness flips. The dots, popups and
 * controls are not in the tile pane and keep their token colours.
 */

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .ctt-map__frame[b-vpkoj2fzab]  .leaflet-tile-pane {
        filter: invert(1) hue-rotate(180deg) brightness(0.95) contrast(0.9);
    }
}

:root[data-theme="dark"] .ctt-map__frame[b-vpkoj2fzab]  .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) brightness(0.95) contrast(0.9);
}

.ctt-map[b-vpkoj2fzab] {
    margin-top: var(--space-6);
}

.ctt-map__h2[b-vpkoj2fzab] {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    letter-spacing: -0.01em;
    color: var(--ink);
    margin: 0 0 var(--space-2);
}

/* The section badge, the same one every dashboard section head carries. */
.ctt-map__h2 i[b-vpkoj2fzab] {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-sm);
    background-color: var(--accent-wash);
    color: var(--accent);
    font-size: var(--text-md);
    line-height: 1;
}

.ctt-map__lede[b-vpkoj2fzab] {
    font-size: var(--text-sm);
    color: var(--muted);
    margin: 0 0 var(--space-3);
}

/* The positioning context for the offline overlay. The overlay is inside this box and can never
   reach the rest of the page. A card like every other: rounded, lifted, no hairline. */
.ctt-map__frame[b-vpkoj2fzab] {
    position: relative;
    border-radius: var(--radius-md);
    box-shadow: var(--elev-card);
    overflow: hidden;
    background: var(--sunken);
}

.ctt-map__canvas[b-vpkoj2fzab] {
    /* A height is compulsory. Leaflet measures its container, and a container with no height
       measures as zero: the map draws one tile in a corner, or nothing at all. */
    height: 340px;
    width: 100%;

    /* Shows through wherever a tile has not arrived - which is the whole of it when the reader is
       offline. A token, so the blank state is the app's own colour rather than Leaflet's grey. */
    background: var(--sunken);
}

@media (max-width: 575px) {
    .ctt-map__canvas[b-vpkoj2fzab] {
        height: 240px;
    }
}

/*
 * One dot. Filled with accent and outlined with accent-ink, which is the pairing that survives BOTH
 * themes on top of light map imagery: a deep teal disc with a white edge in light, a pale cyan disc
 * with a near-black edge in dark. The outline is also what keeps two overlapping dots readable as
 * two.
 */
.ctt-map__frame[b-vpkoj2fzab]  .ctt-map__dot {
    fill: var(--accent);
    fill-opacity: 0.65;
    stroke: var(--accent-ink);
    stroke-width: 1.5;
    stroke-opacity: 0.9;
}

.ctt-map__frame[b-vpkoj2fzab]  .ctt-map__dot:hover {
    fill-opacity: 0.85;
}

/*
 * THE OFFLINE OVERLAY.
 *
 * pointer-events: none is the load-bearing line. Without it this box swallows every click and drag
 * over the middle of the map, so a reader who is offline - and whose dots are all still correct -
 * could not pan to look at them. It covers the picture, not the page: it is positioned inside the
 * frame above, so nothing outside the map is under it either way.
 */
.ctt-map__offline[b-vpkoj2fzab] {
    position: absolute;
    inset: 0;
    pointer-events: none;

    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-4);
    text-align: center;

    /* Not opaque. The dots stay visible through it, which is the message: the record is here and the
       picture is not.
       The solid declaration comes first as the fallback for an engine with no color-mix, the same way
       Layout/NavMenu.razor.css does it. An overlay with no background at all would put this text on
       top of map imagery, which is the one state it must never be in - the message would be the
       unreadable thing on screen. */
    background: var(--surface);
    background: color-mix(in srgb, var(--surface) 82%, transparent);
}

.ctt-map__offline-head[b-vpkoj2fzab] {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    color: var(--ink);
    margin: 0;
}

.ctt-map__offline-head i[b-vpkoj2fzab] {
    color: var(--warn);
    margin-right: var(--space-1);
}

.ctt-map__offline-body[b-vpkoj2fzab] {
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--ink);
    margin: 0 auto;
    max-width: 34rem;
}

.ctt-map__note[b-vpkoj2fzab] {
    font-size: var(--text-sm);
    color: var(--muted);
    margin: var(--space-2) 0 0;
}

.ctt-map__list[b-vpkoj2fzab] {
    margin: 0;
    padding-left: var(--space-5);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
}

.ctt-map__list-detail[b-vpkoj2fzab] {
    display: block;
    font-size: var(--text-sm);
    color: var(--muted);
}

/* ---- Leaflet's own furniture, repainted from tokens ---- */

/*
 * The attribution strip. REQUIRED by the OpenStreetMap tile usage policy, so it is styled to be
 * readable rather than styled away: a credit nobody can read is not a credit.
 */
.ctt-map__frame[b-vpkoj2fzab]  .leaflet-control-attribution {
    background: var(--surface);
    background: color-mix(in srgb, var(--surface) 85%, transparent);
    color: var(--muted);
    font-family: var(--font-ui);
    font-size: var(--text-xs);
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-control-attribution a {
    color: var(--accent);
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-bar {
    border: 1px solid var(--rule);
    box-shadow: none;
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-bar a {
    background: var(--surface);
    color: var(--ink);
    border-bottom-color: var(--rule);
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-bar a:hover,
.ctt-map__frame[b-vpkoj2fzab]  .leaflet-bar a:focus-visible {
    background: var(--sunken);
    color: var(--ink);
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-bar a:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-popup-content-wrapper,
.ctt-map__frame[b-vpkoj2fzab]  .leaflet-popup-tip {
    background: var(--surface);
    color: var(--ink);
    box-shadow: none;
    border: 1px solid var(--rule);
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-popup-content-wrapper {
    border-radius: var(--radius-md);
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-popup-content {
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    margin: var(--space-3);
}

.ctt-map__frame[b-vpkoj2fzab]  .leaflet-popup-close-button {
    color: var(--muted);
}

.ctt-map__frame[b-vpkoj2fzab]  .ctt-map__pop strong {
    display: block;
    color: var(--ink);
    font-weight: var(--weight-semibold);
}

.ctt-map__frame[b-vpkoj2fzab]  .ctt-map__pop span {
    display: block;
    color: var(--muted);
}
/* /Components/Settings/DeviceList.razor.rz.scp.css */
/*
    One rule. The network address a session was last seen from is raw machine text the reader is
    comparing character by character against something they half remember, so it is monospace - the
    same treatment country codes and imported values get in this app.

    Nothing here redefines a shared kit class. The chip on a row with no address is the kit's
    StatusChip, styled once in wwwroot/css/app.css.
*/
.ctt-devices__where[b-5ix0dbl7wc] {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    overflow-wrap: anywhere;
}

.ctt-devices__action[b-5ix0dbl7wc] {
    text-align: right;
}

/*
    ON A PHONE, NO TABLE. Five columns do not fit 360px, and a table that scrolls sideways hides the
    sign-out button off the edge. Each row becomes a block: the name on top, then one labelled line
    per fact (the label comes from data-label in the markup), then the button.
*/
@media (max-width: 599.98px) {
    .ctt-devices thead[b-5ix0dbl7wc] {
        display: none;
    }

    .ctt-devices table[b-5ix0dbl7wc],
    .ctt-devices tbody[b-5ix0dbl7wc],
    .ctt-devices tr[b-5ix0dbl7wc],
    .ctt-devices th[b-5ix0dbl7wc],
    .ctt-devices td[b-5ix0dbl7wc] {
        display: block;
        width: 100%;
    }

    .ctt-devices tr[b-5ix0dbl7wc] {
        padding: var(--space-3) 0;
        border-bottom: 1px solid var(--rule);
    }

    .ctt-devices tr:last-child[b-5ix0dbl7wc] {
        border-bottom: 0;
    }

    .ctt-devices th[b-5ix0dbl7wc],
    .ctt-devices td[b-5ix0dbl7wc] {
        border: 0;
        padding: 0.125rem 0;
        text-align: left;
    }

    .ctt-devices td[data-label][b-5ix0dbl7wc]::before {
        content: attr(data-label) ": ";
        color: var(--muted);
        font-size: var(--text-sm);
    }

    .ctt-devices .ctt-devices__action[b-5ix0dbl7wc] {
        padding-top: var(--space-2);
        text-align: left;
    }
}
/* /Components/Settings/ProfileSwitchRow.razor.rz.scp.css */
/*
    Scoped to ProfileSwitchRow.

    Deliberately NOT added to wwwroot/css/app.css. That file belongs to the shared UI kit and three
    other screens are being rebuilt against it at the same time; a class added there for one screen is
    a merge conflict and a class nobody else knows the rules for. Every value below is a token from
    css/tokens.css, so the switch still follows the theme.
*/

.ctt-switch[b-y7cn2cli6z] {
    padding: var(--space-3) 0 var(--space-3) 3.5rem;
    border-bottom: 1px solid var(--rule);
    margin: 0;
}

.ctt-switch:last-child[b-y7cn2cli6z] {
    border-bottom: none;
}

/* Bootstrap puts the switch track at the left edge; pull it into the padding we just added. */
.ctt-switch .form-check-input[b-y7cn2cli6z] {
    margin-left: -3.5rem;
    width: 2.75rem;
    height: 1.5rem;
    margin-top: 0.05rem;
    cursor: pointer;
}

.ctt-switch .form-check-input:checked[b-y7cn2cli6z] {
    background-color: var(--accent);
    border-color: var(--accent);
}

.ctt-switch .form-check-label[b-y7cn2cli6z] {
    cursor: pointer;
    display: block;
}

.ctt-switch__label[b-y7cn2cli6z] {
    display: block;
    color: var(--ink);
    font-weight: var(--weight-semibold);
}

/* ONE line. The consequence is the whole answer for a reader who never opens the popover, so it gets
   real contrast rather than the muted grey a caption would take. */
.ctt-switch__consequence[b-y7cn2cli6z] {
    display: block;
    color: var(--ink);
    font-size: var(--text-sm);
    margin-top: 0.05rem;
}
/* /Layout/MainLayout.razor.rz.scp.css */
/*
    The app frame: the title bar, the tab-bar-or-sidebar, the main column, and (signed out only) the
    footer.

    WHAT IS IN HERE, AND WHAT IS NOT
    Only the frame. The shared UI kit (StatusChip, StatTile, InfoHint, Disclosure, EmptyState) and the
    Bootstrap remap are in wwwroot/css/app.css, which is global and therefore the right place for an
    app-wide skin. This file once held a second copy of all of it, written when app.css was believed to
    be the untouched Blazor template; two owners of one rule meant two places for the app to disagree
    with itself about what amber is. Do not put a .ctt-* rule back in here.

    ::deep, AND WHEN IT IS REQUIRED
    Blazor stamps its scope attribute only on the elements a component renders ITSELF. MainLayout
    renders .shell, .shell-bar, .shell-body, .shell-navhost, .shell-main and .shell-foot, so those take
    a plain selector. Markup rendered by a CHILD component would need ::deep - without it the selector
    compiles to .x[b-xxx] and matches nothing at all. That bug happened here once, on the status bar,
    which has since been removed (owner, 3 Oct 2026: vlogger test - no tech status).

    SAFE AREAS. index.html sets viewport-fit=cover, so on a phone with a notch or a home indicator the
    page runs edge to edge and these insets are the only thing keeping the title bar and the tab bar
    out from under them. env() is 0 everywhere else, so the same rules are right on a laptop.

    Everything here is presentation. No selector encodes a rule, a threshold or a country.
*/
/* =========================================================================================
   THE FRAME
   ========================================================================================= */

.shell[b-vimflvta5v] {
    /* Restated on the frame rather than left to inherit, so the app column reads correctly even
       if a host page ever supplies a different body font. app.css sets the same values on body. */
    font-family: var(--font-ui);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    color: var(--ink);
    background: var(--ground);
    min-height: 100vh;
    display: flex;
    flex-direction: column;

    /* Digits line up in every column, table and figure in the app. */
    font-variant-numeric: tabular-nums;

    /* The title bar height, not counting the safe area above it. 56px: room for a 44px target. */
    --bar-h: 3.5rem;

    /* The tab bar's own height on a phone, not counting the safe area below it. */
    --tabs-h: 3.75rem;

    /* ---- Bootstrap, re-pointed at the design tokens ----
       Bootstrap 5.3 reads these at run time, so one block here makes its buttons, tables, forms,
       modals and popovers follow the skin - and follow it in dark theme too, because the tokens do.
       Custom properties inherit, so this reaches @Body as well. */
    --bs-body-font-family: var(--font-ui);
    --bs-body-font-size: var(--text-base);
    --bs-body-color: var(--ink);
    --bs-body-bg: var(--ground);
    --bs-emphasis-color: var(--ink);
    --bs-heading-color: var(--ink);
    --bs-secondary-color: var(--muted);
    --bs-tertiary-color: var(--muted);
    --bs-secondary-bg: var(--sunken);
    --bs-tertiary-bg: var(--sunken);
    --bs-border-color: var(--rule);
    --bs-border-radius: var(--radius-md);
    --bs-border-radius-sm: var(--radius-sm);
    --bs-border-radius-lg: var(--radius-lg);
    --bs-link-color: var(--accent);
    --bs-link-hover-color: var(--accent);
    --bs-code-color: var(--accent);
    --bs-primary: var(--accent);
}

/* ---- title bar ---- */

.shell-bar[b-vimflvta5v] {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    height: calc(var(--bar-h) + env(safe-area-inset-top, 0px));
    padding: env(safe-area-inset-top, 0px)
             calc(var(--space-3) + env(safe-area-inset-right, 0px))
             0
             calc(var(--space-3) + env(safe-area-inset-left, 0px));

    /*
        THE FRAME SITS ON THE SURFACE, in both themes. It used to be filled with the accent, which in
        dark theme is a bright cyan: a loud band across the top and down the side of a near-black page,
        louder than any number on it. The accent is structure, and structure should be quiet - so it
        now marks only the screen the reader is on (NavMenu.razor.css) and the mark beside the name.
        A hairline rule, not a fill, separates the bar from the page.
    */
    background: var(--surface);
    border-bottom: 1px solid var(--rule);
    color: var(--ink);
}

.shell-bar__brand[b-vimflvta5v] {
    color: var(--ink);
    font-size: var(--text-md);
    font-weight: var(--weight-bold);
    letter-spacing: -0.01em;
    text-decoration: none;
    white-space: nowrap;

    display: inline-flex;
    align-items: center;
    gap: var(--space-2);

    /*
        NEVER shrink, and no ellipsis.

        The bar holds this and nothing else - the mark plus "Country Time" is about 130px, which fits
        the narrowest phone in use. min-width 0 once removed the automatic minimum size a flex item
        gets from its own content, which let this collapse, and text-overflow then cut the name down
        to "Cou...". An app that cannot say its own name in its own title bar looks broken.
    */
    flex: none;

    /*
        The mark in the theme's own accent. Restated from tokens rather than left to BrandGlyph's
        built-in fallbacks, which are the LIGHT theme's hex values: on the dark surface the deep
        teal would all but vanish. The cut takes the bar's colour so it reads as a gap, not a stripe.
    */
    --brand-deep: var(--accent);
    --brand-soft: var(--accent-soft);
    --brand-cut: var(--surface);
}

/*
    ::deep is REQUIRED here, and its absence made the mark invisible once.

    MainLayout writes the class - <BrandGlyph Class="shell-bar__mark" /> - but BrandGlyph renders the
    <svg>. Blazor stamps the scope attribute only on elements a component renders ITSELF, so a plain
    selector compiled to .shell-bar__mark[b-xxx] and matched nothing. An <svg> carrying only a viewBox
    has no intrinsic size inside a flex row, so with no width it collapsed to zero and the logo simply
    was not there.

    Writing the class in this file is not the same as rendering the element. That is the trap.
*/
.shell-bar__brand[b-vimflvta5v]  .shell-bar__mark {
    width: 1.75rem;
    height: 1.75rem;
    flex: none;
}

.shell-bar__brand:focus-visible[b-vimflvta5v] {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

/* ---- body: tab bar or sidebar, plus the screen ---- */

.shell-body[b-vimflvta5v] {
    display: flex;
    align-items: stretch;
    flex: 1;
    min-height: 0;
}

.shell-main[b-vimflvta5v] {
    flex: 1;
    /* Without this a wide table inside @Body stretches the flex item and the whole page scrolls
       sideways. Level 1 has to be readable without that. */
    min-width: 0;
    padding: var(--space-5)
             calc(var(--space-4) + env(safe-area-inset-right, 0px))
             var(--space-7)
             calc(var(--space-4) + env(safe-area-inset-left, 0px));
}

/*
    THE TAB BAR, on a phone. Fixed to the bottom edge, above the home indicator.

    The main column is padded by the bar's full height plus the safe area, so the last line of every
    screen can still be scrolled clear of the bar - nothing hides behind it.
*/
.shell-navhost[b-vimflvta5v] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    padding: 0 env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
    background: var(--surface);
    border-top: 1px solid var(--rule);
}

.shell--tabs .shell-main[b-vimflvta5v] {
    padding-bottom: var(--space-6);
}

/* The footer is the last thing on the page, so it is what has to clear the fixed tab bar. */
.shell--tabs .shell-foot[b-vimflvta5v] {
    padding-bottom: calc(var(--tabs-h) + env(safe-area-inset-bottom, 0px) + var(--space-3));
}

/* ---- footer: the three public documents, signed out only ---- */

.shell-foot[b-vimflvta5v] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--rule);
    background: var(--surface);
    color: var(--muted);
    font-size: var(--text-sm);
}

.shell-foot__name[b-vimflvta5v] {
    font-weight: var(--weight-medium);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);

    /* The same token restatement as the title bar's mark, so it follows the dark theme too. */
    --brand-deep: var(--accent);
    --brand-soft: var(--accent-soft);
    --brand-cut: var(--surface);
}

/* The footer sits on the surface, so the mark takes the same colours as in the title bar.
   ::deep for the same reason as the bar's mark: BrandGlyph renders the svg, not MainLayout. */
.shell-foot__name[b-vimflvta5v]  .shell-foot__mark {
    width: 1.125rem;
    height: 1.125rem;
    flex: none;
}

.shell-foot a[b-vimflvta5v] {
    color: var(--accent);
}

/* ---- wide screen: the tab bar becomes a sidebar ---- */

@media (min-width: 900px) {
    .shell-navhost[b-vimflvta5v] {
        position: static;
        flex: 0 0 15rem;
        width: 15rem;
        padding: 0;
        border-top: 0;
        border-right: 1px solid var(--rule);
    }

    .shell-main[b-vimflvta5v],
    .shell--tabs .shell-main[b-vimflvta5v] {
        padding: var(--space-6) var(--space-6) var(--space-7);
    }

    .shell--tabs .shell-foot[b-vimflvta5v] {
        padding-bottom: var(--space-3);
    }
}

/* =========================================================================================
   THE GATE'S WAITING LINE.

   Shown for the few milliseconds between the page loading and the stored session token being read.
   Quiet on purpose: it is not a warning and it is not an error, and a loud panel here would flash on
   every single load. MainLayout renders this element itself, so no ::deep.
   ========================================================================================= */

.shell-gate[b-vimflvta5v] {
    color: var(--muted);
    font-size: var(--text-sm);
    margin: var(--space-4) 0 0;
}

/* ---- who is signed in: right end of the title bar, a dropdown with Settings and Sign out ----
   May shrink, unlike the brand: an address can be forty characters, so it gets what is left and
   trims with an ellipsis (full text in the title attribute). Quieter than the app's name. */
.shell-bar__account[b-vimflvta5v] {
    position: relative;
    margin-left: auto;
    min-width: 0;
}

.shell-bar__who[b-vimflvta5v] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    max-width: 100%;
    min-height: 44px;
    padding: 0 var(--space-2);
    border: 0;
    background: none;
    color: var(--muted);
    font-size: var(--text-sm);
}

.shell-bar__who-text[b-vimflvta5v] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.shell-bar__who:hover[b-vimflvta5v],
.shell-bar__who:focus-visible[b-vimflvta5v] {
    color: var(--ink);
}

/* Click anywhere else closes the menu. */
.shell-bar__scrim[b-vimflvta5v] {
    position: fixed;
    inset: 0;
    z-index: 40;
    border: 0;
    background: transparent;
}

.shell-bar__menu[b-vimflvta5v] {
    position: absolute;
    right: 0;
    top: 100%;
    z-index: 41;
}

.shell-bar__menu .dropdown-item[b-vimflvta5v] {
    min-height: 44px;
    display: flex;
    align-items: center;
}

.shell-visually-hidden[b-vimflvta5v] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* /Layout/NavMenu.razor.rz.scp.css */
/*
    The navigation, drawn once. MainLayout decides where it sits - a tab bar fixed to the bottom of a
    phone, a sidebar on a wide screen - so nothing here positions itself. This file only lays the
    items out: in a row, icon over label, on a phone; in a column, icon beside label, on a wide screen.

    The accent colour is the structure colour and means nothing else. A nav item is never green,
    amber or red: those three mean safe, watch and breach, and a menu has no verdict to give.

    THEME NOTE. The nav sits on --surface in both themes (see the title bar in MainLayout.razor.css).
    The items are plain --ink on the surface, and the accent appears in one place only: the screen the
    reader is on, as accent text on the faint --accent-wash. ContrastTests checks both pairs (ink on
    surface, accent on accent-wash) in both themes.
*/

/* ---- phone first: the tab bar ---- */

.shell-nav__list[b-rhu0hvrpeu] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: row;
}

.shell-nav__item[b-rhu0hvrpeu] {
    /* Five equal tabs: 72px each on a 360px phone, still wide enough for "Travel log". min-width 0
       lets a long label trim instead of pushing the bar wider than the phone. */
    flex: 1 1 0;
    min-width: 0;
}

/* ::deep, because NavLink renders the anchor itself and Blazor's scope attribute lands on this
   component's own elements only. */
.shell-nav__item[b-rhu0hvrpeu]  .shell-nav__link {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    padding: var(--space-1) var(--space-1);
    color: var(--muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    line-height: var(--leading-snug);
    text-align: center;
    text-decoration: none;

    /* A thumb target, comfortably above 44px. */
    min-height: 3.5rem;
}

.shell-nav__label[b-rhu0hvrpeu] {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The screen the reader is on: accent text, and a bar along the TOP edge of the tab, so the current
   tab is still obvious to someone who cannot separate two close colours. */
.shell-nav__item[b-rhu0hvrpeu]  .shell-nav__link.active {
    color: var(--accent);
    box-shadow: inset 0 0.1875rem 0 0 var(--accent);
    font-weight: var(--weight-semibold);
}

.shell-nav__item[b-rhu0hvrpeu]  .shell-nav__link:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: -2px;
}

.shell-nav__icon[b-rhu0hvrpeu] {
    font-size: 1.375rem;
    line-height: 1;
    color: inherit;
}

/* ---- wide screen: the same list is the sidebar ---- */

@media (min-width: 900px) {
    .shell-nav[b-rhu0hvrpeu] {
        padding: var(--space-4) var(--space-3);
    }

    .shell-nav__list[b-rhu0hvrpeu] {
        flex-direction: column;
        gap: var(--space-1);
    }

    .shell-nav__item[b-rhu0hvrpeu] {
        flex: none;
    }

    .shell-nav__item[b-rhu0hvrpeu]  .shell-nav__link {
        flex-direction: row;
        justify-content: flex-start;
        gap: var(--space-3);
        padding: var(--space-2) var(--space-3);
        border-radius: var(--radius-sm);
        color: var(--ink);
        font-size: var(--text-base);
        font-weight: var(--weight-regular);
        text-align: left;
        min-height: 2.75rem;
    }

    .shell-nav__item[b-rhu0hvrpeu]  .shell-nav__link:hover {
        background: var(--sunken);
    }

    .shell-nav__item[b-rhu0hvrpeu]  .shell-nav__link.active {
        background: var(--accent-wash);
        color: var(--accent);
        box-shadow: inset 0.1875rem 0 0 0 var(--accent);
        font-weight: var(--weight-semibold);
    }

    .shell-nav__icon[b-rhu0hvrpeu] {
        flex: 0 0 1.25rem;
        font-size: var(--text-md);
        text-align: center;
        color: var(--muted);
    }

    .shell-nav__item[b-rhu0hvrpeu]  .shell-nav__link.active .shell-nav__icon {
        color: var(--accent);
    }
}
/* /Layout/SignInLayout.razor.rz.scp.css */
/*
    The sign-in frame. One narrow column, centred, on the app's own ground colour.

    EVERY COLOUR AND EVERY SIZE IS A TOKEN. No literal hex anywhere, so the dark theme follows for
    free - the same rule the app frame is held to by a test.

    ::deep, AND WHERE IT IS REQUIRED
    Blazor stamps its scope attribute only on the elements THIS component renders. .plain-bar__mark
    names the <svg> that BrandGlyph renders, so it must be written ::deep or it compiles to
    .plain-bar__mark[b-xxx], matches nothing, and the mark renders at whatever size an unstyled inline
    svg happens to be. That exact bug made the logo disappear from the app bar once.
*/
.plain[b-lem99d3smi] {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    /* Safe areas: index.html sets viewport-fit=cover, so the notch and the home indicator are ours
       to keep clear of. env() is 0 everywhere else. */
    padding: calc(var(--space-5) + env(safe-area-inset-top, 0px))
             calc(var(--space-4) + env(safe-area-inset-right, 0px))
             calc(var(--space-6) + env(safe-area-inset-bottom, 0px))
             calc(var(--space-4) + env(safe-area-inset-left, 0px));
    background: var(--ground);
    color: var(--ink);
    font-family: var(--font-ui);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
}

.plain-bar[b-lem99d3smi] {
    display: flex;
    align-items: center;
    justify-content: center;

    /* The info icon sits right beside the name, on the same line. */
    gap: var(--space-1);
}

.plain-bar__brand[b-lem99d3smi] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);

    /* No min-width: 0 and no text-overflow. The app's name is the app's name; the bar holds nothing
       else, so there is never a shortage of room, and a rule that lets it collapse once printed
       "Cou..." in the app frame. */
    flex: none;
}

[b-lem99d3smi] .plain-bar__mark {
    width: 2.25rem;
    height: 2.25rem;
    flex: none;
}

.plain-main[b-lem99d3smi] {
    /* Phone first: full width, and a ceiling so the form does not stretch across a laptop. */
    width: 100%;
    max-width: 34rem;

    /* Lets a wide child - a long error message, a pasted address - shrink instead of pushing the
       page sideways. */
    min-width: 0;
}

.plain-foot[b-lem99d3smi] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-top: auto;
    padding-top: var(--space-5);
    font-size: var(--text-sm);
}

.plain-foot a[b-lem99d3smi] {
    color: var(--muted);
}
/* /Pages/Calendar.razor.rz.scp.css */
/* =============================================================================================
   The calendar. One month, Monday first, seven columns that fit a 360px phone with no sideways
   scroll.

   COLOUR. A country's fill is its colour from CountryColours (set as --c on the cell), mixed with
   the surface so the day number in --ink stays readable in light and dark. The small stay number
   uses the semantic tokens - --ok, --warn, --crit - by LimitTone's rule, exactly as Home does.
   Everything else is a token.

   BANDS. Days of one country side by side join into one band: the fill of a joined side runs out
   into the gap and loses its corner, so a week in France reads as one bar.

   CountryFlag is a child component, so rules that reach its <img> are written ::deep.
   ============================================================================================= */

.ctt-cal[b-9yopllz5tg] {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    min-width: 0;
}

.ctt-cal__head[b-9yopllz5tg] {
    margin-bottom: 0;
    flex-wrap: nowrap;
}

.ctt-cal__card[b-9yopllz5tg] {
    --cal-gap: 3px;
    gap: var(--space-4);
    min-width: 0;
    padding: var(--space-4) var(--space-3);
}

@media (min-width: 40rem) {
    .ctt-cal__card[b-9yopllz5tg] {
        --cal-gap: 6px;
        padding: var(--space-5);
    }
}

/* ---- the month bar: title, then previous / Today / next ---- */
.ctt-cal__bar[b-9yopllz5tg] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.ctt-cal__title[b-9yopllz5tg] {
    margin: 0;
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    color: var(--ink);
}

.ctt-cal__nav[b-9yopllz5tg] {
    display: flex;
    gap: var(--space-2);
}

.ctt-cal__step[b-9yopllz5tg] {
    min-width: 2.75rem;
}

/* The one chevron icon, turned round for "previous". */
.ctt-cal__back[b-9yopllz5tg] {
    display: inline-block;
    transform: scaleX(-1);
}

/* ---- the grid ---- */
.ctt-cal__grid[b-9yopllz5tg] {
    display: flex;
    flex-direction: column;
    gap: var(--cal-gap);
    min-width: 0;
}

.ctt-cal__row[b-9yopllz5tg] {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: var(--cal-gap);
}

.ctt-cal__name[b-9yopllz5tg] {
    text-align: center;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    color: var(--muted);
    padding-bottom: var(--space-1);
}

.ctt-cal__day[b-9yopllz5tg] {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: stretch;
    min-width: 0;
    min-height: 3.4rem;
    padding: 0.2rem 0.25rem;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
    isolation: isolate;
}

@media (min-width: 40rem) {
    .ctt-cal__day[b-9yopllz5tg] {
        min-height: 4.75rem;
        padding: var(--space-2);
    }
}

.ctt-cal__day--pad[b-9yopllz5tg] {
    cursor: default;
}

/* The fill sits behind the content and can run out into the gap to join a band. */
.ctt-cal__fill[b-9yopllz5tg] {
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: var(--radius-sm);
    background-color: var(--sunken);
}

.ctt-cal__day--country .ctt-cal__fill[b-9yopllz5tg] {
    background-color: color-mix(in srgb, var(--c) 55%, var(--surface));
}

.ctt-cal__day--join-before .ctt-cal__fill[b-9yopllz5tg] {
    left: calc(-1 * var(--cal-gap));
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.ctt-cal__day--join-after .ctt-cal__fill[b-9yopllz5tg] {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.ctt-cal__day--travelling .ctt-cal__fill[b-9yopllz5tg] {
    background-color: var(--accent-wash);
}

/* A missing day: hatched, so it never reads as a clean day outside. */
.ctt-cal__day--missing .ctt-cal__fill[b-9yopllz5tg] {
    background-color: var(--surface);
    background-image: repeating-linear-gradient(135deg, var(--rule) 0 2px, transparent 2px 6px);
}

/* Not in the log (the future, or before the log starts): a quiet outline only. */
.ctt-cal__day--notinlog .ctt-cal__fill[b-9yopllz5tg] {
    background-color: transparent;
    box-shadow: inset 0 0 0 1px var(--rule);
}

/* A planned trip (after today, inside a planned trip): dashed, so it never reads as a real day. */
.ctt-cal__day--planned .ctt-cal__fill[b-9yopllz5tg] {
    background-color: color-mix(in srgb, var(--c, var(--sunken)) 25%, var(--surface));
    box-shadow: inset 0 0 0 2px var(--muted);
    outline: 2px dashed var(--muted);
    outline-offset: -2px;
}

.ctt-cal__day--today[b-9yopllz5tg] {
    box-shadow: 0 0 0 2px var(--ink);
    z-index: 1;
}

.ctt-cal__day--picked .ctt-cal__fill[b-9yopllz5tg] {
    box-shadow: inset 0 0 0 2px var(--accent);
}

.ctt-cal__day:focus-visible[b-9yopllz5tg] {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
    z-index: 2;
}

.ctt-cal__top[b-9yopllz5tg] {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 3px;
    min-width: 0;
}

.ctt-cal__num[b-9yopllz5tg] {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    line-height: 1.1;
}

.ctt-cal__day--today .ctt-cal__num[b-9yopllz5tg] {
    font-weight: var(--weight-bold);
}

.ctt-cal__top[b-9yopllz5tg]  .ctt-flag {
    font-size: 0.8rem;
}

/* The stay number: small, bold, bottom right, in LimitTone's colour. */
.ctt-cal__stay[b-9yopllz5tg] {
    align-self: flex-end;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

@media (min-width: 40rem) {
    .ctt-cal__stay[b-9yopllz5tg] {
        font-size: var(--text-base);
    }
}

.ctt-cal__stay--ok[b-9yopllz5tg] { color: var(--ok); }
.ctt-cal__stay--warn[b-9yopllz5tg] { color: var(--warn); }
.ctt-cal__stay--crit[b-9yopllz5tg] { color: var(--crit); }
.ctt-cal__stay--none[b-9yopllz5tg] { color: var(--muted); }

/* ---- the tapped day ---- */
.ctt-cal__panel[b-9yopllz5tg] {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background-color: var(--sunken);
}

.ctt-cal__panel p[b-9yopllz5tg] {
    margin: 0;
}

.ctt-cal__panel-date[b-9yopllz5tg] {
    font-size: var(--text-md);
    font-weight: var(--weight-bold);
}

.ctt-cal__panel-where[b-9yopllz5tg] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-3);
    font-size: var(--text-base);
}

.ctt-cal__panel-country[b-9yopllz5tg] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

.ctt-cal__panel-stay[b-9yopllz5tg] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0 var(--space-3);
    margin-top: var(--space-2) !important;
    font-size: var(--text-base);
}

.ctt-cal__panel-stay--ok strong[b-9yopllz5tg] { color: var(--ok); }
.ctt-cal__panel-stay--warn strong[b-9yopllz5tg] { color: var(--warn); }
.ctt-cal__panel-stay--crit strong[b-9yopllz5tg] { color: var(--crit); }

.ctt-cal__panel-note[b-9yopllz5tg] {
    font-size: var(--text-sm);
    color: var(--muted);
}

/* ---- the key ---- */
.ctt-cal__legend[b-9yopllz5tg] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--text-sm);
    color: var(--muted);
}

.ctt-cal__legend li[b-9yopllz5tg] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

.ctt-cal__swatch[b-9yopllz5tg] {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    border-radius: 4px;
    background-color: color-mix(in srgb, var(--c) 55%, var(--surface));
}

.ctt-cal__swatch--today[b-9yopllz5tg] {
    background-color: transparent;
    box-shadow: inset 0 0 0 2px var(--ink);
}

.ctt-cal__swatch--planned[b-9yopllz5tg] {
    background-color: transparent;
    outline: 2px dashed var(--muted);
    outline-offset: -2px;
}

.ctt-cal__key-num[b-9yopllz5tg] {
    font-weight: var(--weight-bold);
    color: var(--ok);
}
/* /Pages/Dashboard.razor.rz.scp.css */
/* =============================================================================================
   Dashboard styles.

   Scoped to this page (Blazor CSS isolation), and every rule that reaches a child component uses
   ::deep on purpose. Nothing here is global: the shared classes - .ctt-tile, .ctt-chip, .ctt-hint,
   .ctt-disclosure, .ctt-empty, .ctt-tile-grid, .ctt-chip-row, .ctt-scroll-x - belong to the kit in
   wwwroot/css/app.css and are not touched from here. Three other screens share them.

   Every colour is a token from css/tokens.css, so dark theme comes for free and cannot drift from
   the rest of the app. No colour is written as a literal.

   Corner radii and spacing are tokens too. Radii are in px on purpose - a corner is physical
   geometry and should not grow with the reader's font size.
   ============================================================================================= */

.ctt-dash[b-3x74o3te3n] {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

/* More air between the bands where there is room for it. The bands are the structure of the page;
   the space between them is what makes them read as three things rather than one long list. */
@media (min-width: 40rem) {
    .ctt-dash[b-3x74o3te3n] {
        gap: var(--space-6);
    }
}

/* The empty state's two secondary links and their info icon, on one line, wrapping on a phone. */
.ctt-dash[b-3x74o3te3n]  .ctt-dash__empty-links {
    margin: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    font-size: var(--text-base);
}

/* The page heading is the shared .ctt-page-head (plain h1, info icon on the same line). Two
   things only: the page's own gap already spaces it from the first card, and on a 360px phone the
   title wraps INSIDE the h1 so the icon never drops to a line of its own. */
.ctt-dash__head[b-3x74o3te3n] {
    margin-bottom: 0;
    flex-wrap: nowrap;
}

.ctt-dash__head > h1[b-3x74o3te3n] {
    min-width: 0;
}

/* ---------------------------------------------------------------------------------------------
   3. One-line notices. A warning that changes a decision, with its explanation in a popover.
      Deliberately not Bootstrap's .alert: an alert is a block of prose, and a block of prose is
      what this page is removing.
   --------------------------------------------------------------------------------------------- */
.ctt-notice[b-3x74o3te3n] {
    margin: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    min-height: 3.5rem;
    padding: var(--space-3) var(--card-pad);
    border: 0;
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

/* The unreadable-record panel leads with a few large words; the explanation is behind its icon. */
.ctt-dash__alert .ctt-panel__head[b-3x74o3te3n] {
    align-items: center;
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
}

.ctt-notice--warn[b-3x74o3te3n] {
    background-color: var(--warn-wash);
    box-shadow: inset var(--edge) 0 0 0 var(--warn), var(--elev-card);
}

.ctt-notice--warn > i[b-3x74o3te3n] {
    color: var(--warn);
    font-size: var(--text-md);
}

/* ---------------------------------------------------------------------------------------------
   4. The three bands, the owner's desktop layout.

        1. Schengen, the full width.
        2. Tax residency and other limits: the table, with the US tiles beside it when they apply.
        3. The map of readings and the recent crossings, side by side.

      Below 60rem every band is one column, in the same order. Every column is minmax(0, ...) or
      min-width: 0, so a wide child - the residency table, the map - shrinks into its column and
      scrolls inside it rather than pushing the page sideways on a phone.
   --------------------------------------------------------------------------------------------- */

/* Band 1. The full width, and nothing beside it. */
.ctt-dash__schengen[b-3x74o3te3n] {
    min-width: 0;
}

/* Band 2. One column by default: the "US trackers are off" note above the table. */
.ctt-dash__limits[b-3x74o3te3n] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4);
    align-items: start;
}

/* With a US tile to show, the tiles take a narrow column beside the table. The table keeps most of
   the width because it is thirteen rows of figures and the tiles are one figure each. */
.ctt-dash__limits--side[b-3x74o3te3n] {
    grid-template-columns: minmax(0, 3fr) minmax(14rem, 1fr);
}

.ctt-dash__table[b-3x74o3te3n] {
    min-width: 0;
}

/* The US tiles stack in their column. On a narrow screen, where the column falls under the table,
   they sit side by side where there is room, so they do not cost two tile heights of scrolling. */
.ctt-dash__side[b-3x74o3te3n] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
    align-content: start;
    gap: var(--space-4);
    min-width: 0;
}

/* Band 3. Two halves that wrap: each half asks for at least 22rem, so on a narrow screen the
   crossings fall under the map rather than squeezing it. Flex rather than grid so that a hidden
   half (below) gives its room to the other one instead of leaving an empty column.
   The gutter is the country grid's, --space-4, so two equal halves split at exactly the line where
   that grid's second and third columns meet: the bands share one set of edges.
   STRETCH, so side by side the two cells are one height and the entries card fills its cell down to
   the map's bottom edge (RecentCrossings.razor.css). Stacked on a phone, each line is its own height
   and stretch changes nothing. */
.ctt-dash__pair[b-3x74o3te3n] {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: var(--space-4);
}

.ctt-dash__map[b-3x74o3te3n],
.ctt-dash__recent[b-3x74o3te3n] {
    flex: 1 1 min(100%, 22rem);
    min-width: 0;
}

.ctt-dash__weather[b-3x74o3te3n] {
    min-width: 0;
}

/* The speed card: last on the page and half width (owner's review, 3 October 2026 - kept, but the
   least important thing here). Full width on a phone, where half would be too narrow to read. */
.ctt-dash__speed[b-3x74o3te3n] {
    min-width: 0;
    width: 100%;
}

@media (min-width: 40rem) {
    .ctt-dash__speed[b-3x74o3te3n] {
        width: calc(50% - var(--space-4) / 2);
    }
}

/* The weather card draws nothing until there is a position; the speed card always draws. */
.ctt-dash__weather:empty[b-3x74o3te3n] {
    display: none;
}

/* The map renders nothing at all when there are no readings with a place. Its cell is then empty,
   and an empty cell beside the crossings would read as a map the app failed to draw. */
.ctt-dash__map:empty[b-3x74o3te3n],
.ctt-dash__recent:empty[b-3x74o3te3n] {
    display: none;
}

/* The map's own stylesheet spaces it away from whatever was above it, which was right when it was
   last on the page on its own. Beside the crossings that margin would drop it below their heading.
   The map's section is rendered by ReadingMap, so it needs ::deep. Width and height are left alone:
   the canvas is width 100% of this cell, and the map re-measures itself when the cell resizes. */
.ctt-dash__map[b-3x74o3te3n]  .ctt-map {
    margin-top: 0;
}

/* SIDE BY SIDE, THE MAP CARD AND THE ENTRIES CARD ARE ONE HEIGHT (owner, 3 October 2026). The cells
   are stretched to one height (above); here the map's frame takes whatever its cell has beyond the
   heading and the "List of places" toggle, so when the seven entries are taller than the 340px canvas
   the map grows to match. The heading and the toggle are the same heights as the entries' heading
   and link (RecentCrossings.razor.css), so the two card edges line up exactly. Leaflet re-measures
   when its box changes size. Stacked on a phone the cell is its content's height and none of this
   changes anything. */
.ctt-dash__map[b-3x74o3te3n]  .ctt-map {
    height: 100%;
    display: flex;
    flex-direction: column;
}

.ctt-dash__map[b-3x74o3te3n]  .ctt-map__frame {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}

.ctt-dash__map[b-3x74o3te3n]  .ctt-map__canvas {
    flex: 1 1 auto;
}

@media (max-width: 60rem) {
    .ctt-dash__limits--side[b-3x74o3te3n] {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ---------------------------------------------------------------------------------------------
   5. The Schengen tile. Same shape as the kit's StatTile - a status edge, not a fill - but with a
      bigger figure and room for the meter.
   --------------------------------------------------------------------------------------------- */
.ctt-dash[b-3x74o3te3n]  .ctt-big {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--card-pad);
    background-color: var(--surface);
    border: 0;
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-card);
    min-width: 0;
}

.ctt-dash[b-3x74o3te3n]  .ctt-big--ok { box-shadow: inset var(--edge) 0 0 0 var(--ok), var(--elev-card); }
.ctt-dash[b-3x74o3te3n]  .ctt-big--warn { box-shadow: inset var(--edge) 0 0 0 var(--warn), var(--elev-card); }
.ctt-dash[b-3x74o3te3n]  .ctt-big--crit { box-shadow: inset var(--edge) 0 0 0 var(--crit), var(--elev-card); }

.ctt-dash[b-3x74o3te3n]  .ctt-big__head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__title {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* The section badge: the icon in a teal wash, the same on every section head of the dashboard. */
.ctt-dash[b-3x74o3te3n]  .ctt-big__title > i,
.ctt-dash[b-3x74o3te3n]  .ctt-section__title > i {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-sm);
    background-color: var(--accent-wash);
    color: var(--accent);
    font-size: var(--text-md);
    line-height: 1;
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__head > .ctt-hint {
    margin-left: auto;
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__lead {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__label {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__value {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__figure {
    font-size: var(--text-figure);
    font-weight: var(--weight-bold);
    line-height: var(--leading-tight);
    letter-spacing: -0.02em;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__figure--ok { color: var(--ok); }
.ctt-dash[b-3x74o3te3n]  .ctt-big__figure--warn { color: var(--warn); }
.ctt-dash[b-3x74o3te3n]  .ctt-big__figure--crit { color: var(--crit); }

.ctt-dash[b-3x74o3te3n]  .ctt-big__unit {
    font-size: var(--text-md);
    font-weight: var(--weight-medium);
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* No answer is not a small number. It is a sentence, where the number would be, in muted type -
   never coloured, because there is no verdict to colour. */
.ctt-dash[b-3x74o3te3n]  .ctt-big__none {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    color: var(--muted);
}

/* The demoted figure. Small, but full contrast: it is not fine print and it is not hidden. */
.ctt-dash[b-3x74o3te3n]  .ctt-big__provisional {
    margin: 0;
    max-width: 60ch;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__caption {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    font-size: var(--text-sm);
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.ctt-dash[b-3x74o3te3n]  .ctt-big__sep {
    color: var(--rule);
}

/* ---------------------------------------------------------------------------------------------
   6. The meter.

      Two segments. Solid is what the record counts. Striped is how much further the count could
      reach if every date with no record turned out to be a day that counts - the gap made visible
      on the figure itself, not only in the words.

      The stripes are drawn with a gradient rather than an animation, so there is nothing to switch
      off under prefers-reduced-motion.
   --------------------------------------------------------------------------------------------- */
.ctt-dash[b-3x74o3te3n]  .ctt-meter {
    display: flex;
    height: var(--space-3);
    background-color: var(--sunken);
    border-radius: var(--radius-pill);
    overflow: hidden;
}

/* Inline, so the meter and the window it measures share one line inside a table cell. */
.ctt-dash[b-3x74o3te3n]  .ctt-meter--slim {
    display: inline-flex;
    width: 6rem;
    height: 0.5rem;
    margin-right: var(--space-2);
    vertical-align: middle;
}

.ctt-dash[b-3x74o3te3n]  .ctt-meter__solid {
    background-color: var(--accent);
    transition: none;
}

.ctt-dash[b-3x74o3te3n]  .ctt-meter__solid--ok { background-color: var(--ok); }
.ctt-dash[b-3x74o3te3n]  .ctt-meter__solid--warn { background-color: var(--warn); }
.ctt-dash[b-3x74o3te3n]  .ctt-meter__solid--crit { background-color: var(--crit); }

.ctt-dash[b-3x74o3te3n]  .ctt-meter__gap {
    background-image: repeating-linear-gradient(
        45deg,
        var(--muted) 0,
        var(--muted) 2px,
        transparent 2px,
        transparent 5px
    );
    opacity: 0.75;
}

/* No scale under the bar. The unit beside the figure already says "of 90", and a second copy of the
   ceiling costs a line of height on the one screen this page has to fit into. */

/* ---------------------------------------------------------------------------------------------
   7. Section heads, used by the residency table.
   --------------------------------------------------------------------------------------------- */
.ctt-dash[b-3x74o3te3n]  .ctt-section {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.ctt-dash[b-3x74o3te3n]  .ctt-section__head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.ctt-dash[b-3x74o3te3n]  .ctt-section__title {
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    letter-spacing: -0.01em;
    color: var(--ink);
}

.ctt-dash[b-3x74o3te3n]  .ctt-section__head > .ctt-hint {
    margin-left: auto;
}

/* ---------------------------------------------------------------------------------------------
   8. The residency table. Thirteen countries, one row each.

      Rows are tight on purpose: the whole point of this screen is that thirteen countries fit on
      one laptop screen without scrolling. The table scrolls inside .ctt-scroll-x when the viewport
      is too narrow, so the page body never scrolls sideways.
   --------------------------------------------------------------------------------------------- */
.ctt-dash[b-3x74o3te3n]  .ctt-rows {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: var(--text-sm);
    background-color: var(--surface);
    border-radius: var(--radius-md);
    box-shadow: var(--elev-card);
    overflow: hidden;
}

/* Column heads are labels: sentence case, muted, never shouted in capitals. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows thead th {
    padding: var(--space-3) var(--space-3) var(--space-2);
    text-align: left;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--muted);
    border-bottom: 1px solid var(--rule);
    white-space: nowrap;
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__band th {
    padding: var(--space-4) var(--space-3) var(--space-2);
    background-color: var(--sunken);
    text-align: left;
    font-weight: var(--weight-regular);
    border-bottom: 1px solid var(--rule);
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__bandname {
    display: inline-block;
    margin-right: var(--space-2);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

/* Tight rows on purpose. Thirteen countries have to fit on one laptop screen under the Schengen band,
   and every extra pixel per row costs thirteen of them. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows tbody tr:not(.ctt-rows__band) > * {
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--rule);
    vertical-align: middle;
}

/* The two rows that carry a demoted figure need the room, and only those. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows__row--thin > * {
    vertical-align: top;
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
}

/* The status colour is a left edge on the row, the same idea as the tiles. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows__row > :first-child {
    border-left: var(--edge) solid transparent;
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__row--ok > :first-child { border-left-color: var(--ok); }
.ctt-dash[b-3x74o3te3n]  .ctt-rows__row--warn > :first-child { border-left-color: var(--warn); }
.ctt-dash[b-3x74o3te3n]  .ctt-rows__row--crit > :first-child { border-left-color: var(--crit); }

/* The last row's rule would sit on the card's own rounded edge. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows tbody tr:last-child > * {
    border-bottom: 0;
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__country {
    font-weight: var(--weight-regular);
    text-align: left;
    min-width: 9rem;
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__code {
    display: inline-block;
    min-width: 2.2rem;
    font-weight: var(--weight-semibold);
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__name {
    color: var(--muted);
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__num {
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__figure {
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    color: var(--ink);
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__figure--ok { color: var(--ok); }
.ctt-dash[b-3x74o3te3n]  .ctt-rows__figure--warn { color: var(--warn); }
.ctt-dash[b-3x74o3te3n]  .ctt-rows__figure--crit { color: var(--crit); }

/* On the same line as the figure. A stacked unit costs a line on every one of thirteen rows. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows__unit {
    font-size: var(--text-sm);
    color: var(--muted);
}

/* Words where a figure would be. Left-aligned and wrapped: it is a phrase, not a number. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows__none {
    display: block;
    text-align: left;
    max-width: 12rem;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--muted);
    white-space: normal;
}

/* The demoted figure on a row. Full contrast, small type, never hidden. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows__prov {
    display: block;
    margin-top: var(--space-1);
    text-align: left;
    max-width: 26rem;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--ink);
    white-space: normal;
}

/* Beside the meter, not under it. Same reason: one line per row, thirteen rows. */
.ctt-dash[b-3x74o3te3n]  .ctt-rows__window {
    font-size: var(--text-sm);
    color: var(--muted);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    vertical-align: middle;
}

.ctt-dash[b-3x74o3te3n]  .ctt-rows__act {
    text-align: right;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------------------------
   9. The "more" button: opens a dialog, or reveals the rest of a tile. A quiet link, not a button
      that competes with the figure beside it.
   --------------------------------------------------------------------------------------------- */
.ctt-dash[b-3x74o3te3n]  .ctt-more {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-height: 2.75rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--accent);
    cursor: pointer;
    text-align: left;
}

.ctt-dash[b-3x74o3te3n]  .ctt-more:hover {
    text-decoration: underline;
}

/* ---------------------------------------------------------------------------------------------
   10. Level 2 and level 3 content: the definition rows inside a Disclosure, the gap panel, and the
       bare card that becomes a dialog body.
   --------------------------------------------------------------------------------------------- */
.ctt-dash[b-3x74o3te3n]  .ctt-defs {
    display: grid;
    grid-template-columns: minmax(8rem, max-content) minmax(0, 1fr);
    gap: var(--space-1) var(--space-3);
    margin: 0 0 var(--space-3);
    font-size: var(--text-sm);
}

.ctt-dash[b-3x74o3te3n]  .ctt-defs dt {
    font-weight: var(--weight-medium);
    color: var(--muted);
}

.ctt-dash[b-3x74o3te3n]  .ctt-defs dd {
    margin: 0;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.ctt-dash[b-3x74o3te3n]  .ctt-detail__headline {
    margin: 0 0 var(--space-2);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--ink);
}

.ctt-dash[b-3x74o3te3n]  .ctt-detail__p {
    margin: 0 0 var(--space-3);
    max-width: 68ch;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--ink);
}

.ctt-dash[b-3x74o3te3n]  .ctt-detail__source {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    font-size: var(--text-xs);
    color: var(--muted);
}

.ctt-panel[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-panel {
    padding: var(--space-4);
    border: 0;
    border-radius: var(--radius-md);
    background-color: var(--surface);
    box-shadow: var(--elev-card);
}

.ctt-panel--warn[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-panel--warn {
    box-shadow: inset var(--edge) 0 0 0 var(--warn), var(--elev-card);
    background-color: var(--warn-wash);
}

.ctt-panel--crit[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-panel--crit {
    box-shadow: inset var(--edge) 0 0 0 var(--crit), var(--elev-card);
    background-color: var(--crit-wash);
}

.ctt-panel__head[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-panel__head {
    margin: 0 0 var(--space-1);
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    font-size: var(--text-base);
    font-weight: var(--weight-bold);
    /* Text on a wash is always --ink, so the panel reads at full contrast whatever it means. */
    color: var(--ink);
}

.ctt-panel__body[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-panel__body {
    margin: 0;
    max-width: 72ch;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--ink);
}

/* A card used as a dialog body. No frame of its own - the dialog already has one. */
.ctt-dash[b-3x74o3te3n]  .ctt-bare {
    border: 0;
    background: none;
    box-shadow: none;
}

.ctt-dash[b-3x74o3te3n]  .ctt-bare__body {
    padding: 0;
}

.ctt-list[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-list {
    margin: 0 0 var(--space-2);
    padding-left: var(--space-4);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--ink);
}

.ctt-list > li[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-list > li {
    margin-bottom: var(--space-1);
}

.ctt-dim[b-3x74o3te3n],
.ctt-dash[b-3x74o3te3n]  .ctt-dim {
    color: var(--muted);
}
/* /Pages/Import.razor.rz.scp.css */
/*
    Scoped to the Import/Export page. Tokens only.

    Kept out of wwwroot/css/app.css on purpose: that stylesheet belongs to the shared kit and three
    other screens are being rebuilt against it right now.
*/

/*
    The replace card. The breach colour is a left edge and a heading, never a fill: a card filled red
    is a card the reader learns to close, and this is the one card on the page they must read.
*/
.ctt-danger-card[b-hou553jkx7] {
    box-shadow: inset var(--edge) 0 0 0 var(--crit), var(--elev-card);
}

.ctt-danger-card h3[b-hou553jkx7] {
    color: var(--crit);
}

/* The "I am still there today" switch. Same shape as the settings switches, for the same reason. */
.ctt-switch[b-hou553jkx7] {
    padding-left: 3.5rem;
    margin: 0;
}

.ctt-switch .form-check-input[b-hou553jkx7] {
    margin-left: -3.5rem;
    width: 2.75rem;
    height: 1.5rem;
    margin-top: 0.05rem;
    cursor: pointer;
}

.ctt-switch .form-check-input:checked[b-hou553jkx7] {
    background-color: var(--accent);
    border-color: var(--accent);
}

.ctt-switch .form-check-label[b-hou553jkx7] {
    cursor: pointer;
    display: block;
}

.ctt-switch__label[b-hou553jkx7] {
    display: block;
    color: var(--ink);
    font-weight: var(--weight-semibold);
}

.ctt-switch__consequence[b-hou553jkx7] {
    display: block;
    color: var(--ink);
    font-size: var(--text-sm);
    margin-top: 0.05rem;
}
/* /Pages/Ledger.razor.rz.scp.css */
/*
    The travel log page. Tokens only - see LedgerHeaderBar.razor.css for why.
*/

/* The heading and the §8 icon beside it, on one line. */
.ctt-ledger__title[b-uh868toium] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.ctt-ledger__title h1[b-uh868toium] {
    margin: 0;
}

/* "Show oldest first": a link, but a 44px tap target. */
.ctt-ledger__order[b-uh868toium] {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--space-1);
}

.ctt-ledger__order .btn[b-uh868toium] {
    min-height: 2.75rem;
    padding-left: var(--space-2);
    padding-right: var(--space-2);
}

.ctt-ledger__band[b-uh868toium] {
    margin-top: var(--space-5);
}

/* One column of fields in every form: on a phone that is the only shape that fits, and in the
   500px desktop dialog it is easier to read than two cramped columns. */
.ctt-lform[b-uh868toium] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
}

.ctt-lform .form-control[b-uh868toium],
.ctt-lform .form-select[b-uh868toium] {
    min-height: 2.75rem;
}

.ctt-lform__inline[b-uh868toium] {
    display: flex;
    gap: var(--space-2);
}

.ctt-lform__inline .form-control[b-uh868toium] {
    flex: 1 1 auto;
    min-width: 0;
}

.ctt-lform__inline .btn[b-uh868toium] {
    flex: none;
    min-height: 2.75rem;
}

/* The two sentinel choices: the whole label is the tap target. */
.ctt-lform__choice[b-uh868toium] {
    min-height: 2.75rem;
}

/* ---------------------------------------------------------------- the short message after a save */

.ctt-ltoast-region[b-uh868toium] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--space-5);
    z-index: 1090;
    display: flex;
    justify-content: center;
    padding: 0 var(--space-4);
    pointer-events: none;
}

.ctt-ltoast[b-uh868toium] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    max-width: 100%;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-pill);
    background-color: var(--ink);
    color: var(--surface);
    box-shadow: var(--elev-pop);
    font-weight: var(--weight-semibold);
}
/* /Pages/Settings.razor.rz.scp.css */
/*
    Scoped to the Settings page. Tokens only - no hex values, no font stacks.

    Everything here is for elements this page renders itself. The switch rows are ProfileSwitchRow's,
    styled in its own file.
*/

.ctt-page-lede[b-z1da8x6w98] {
    color: var(--ink);
    max-width: 68ch;
    margin: 0 0 var(--space-4);
}

.ctt-switches[b-z1da8x6w98] {
    border-top: 1px solid var(--rule);
}

/* The country picker and its Remove button on one line, wrapping on a narrow phone. */
.ctt-home[b-z1da8x6w98] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-2) var(--space-3);
}

.ctt-home__picker[b-z1da8x6w98] {
    flex: 1 1 14rem;
    min-width: 0;
    max-width: 24rem;
}

.ctt-home__since[b-z1da8x6w98] {
    max-width: 16rem;
    margin: var(--space-2) 0 0 3.5rem;
}

/* A long address wraps rather than pushing the card wider than the phone. */
.ctt-account__email[b-z1da8x6w98] {
    overflow-wrap: anywhere;
}

.ctt-account[b-z1da8x6w98] {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--space-2);
}

/* The paperwork, quiet, at the very bottom. */
.ctt-settings-links[b-z1da8x6w98] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin-top: var(--space-5);
    font-size: var(--text-sm);
}

.ctt-settings-links a[b-z1da8x6w98] {
    color: var(--muted);
}
/* /Pages/SignIn.razor.rz.scp.css */
/*
    The sign-in screen's own rules.

    SHAPE: one narrow centred panel, not two stacked cards. Two cards made the two ways in look like
    two separate features to choose between; they are one decision with two answers, so they share a
    panel and are separated by an "or" instead of by a card boundary.

    Everything here is a token. It redefines no .ctt-chip, .ctt-tile, .ctt-hint, .ctt-disclosure,
    .ctt-empty or .ctt-page-note rule - those live once, in wwwroot/css/app.css. A second copy here is
    how the same warning ends up looking different on two screens.

    NO ::deep IS NEEDED for any of these: every element they target is rendered by SignIn.razor
    itself, so Blazor stamps its scope attribute on all of them. The one child component on the screen
    is InfoHint, and only its wrapper is styled here, never its internals.
*/

.ctt-auth[b-bldpz0i4fj] {
    max-width: 26rem;   /* 416px - a form column, not a page width */
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);

    /* The one panel: a card on the ground, like every surface in the app. */
    padding: var(--space-5) var(--card-pad);
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-card);
}

.ctt-auth__head[b-bldpz0i4fj] {
    text-align: center;
    margin-bottom: var(--space-2);
}

.ctt-auth__title[b-bldpz0i4fj] {
    font-size: var(--text-xl);
    font-weight: var(--weight-bold);
    line-height: var(--leading-snug);
    margin: 0;
}

/* Reads as a continuation of the title, so it is a fragment rather than a sentence and takes no
   full stop: "Sign in / to keep your ledger on more than one device". */
.ctt-auth__sub[b-bldpz0i4fj] {
    font-size: var(--text-sm);
    color: var(--muted);
    margin: var(--space-1) 0 0;
}

/* ---------------------------------------------------------------- the provider button */

/*
    Deliberately NOT .btn-primary. The accent is this app's own colour and pressing this hands the
    reader to somebody else - a teal Google button reads as though Country Time were doing the
    authenticating. White with a quiet border is also what every other site's Google button looks
    like, and that familiarity is the whole point of a provider button.

    --rule is very close to the #dadce0 border Google's own guidance specifies, so no new token.
*/
.ctt-auth__google[b-bldpz0i4fj] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);

    min-height: 3rem;
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--rule);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--ink);

    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    text-decoration: none;
    cursor: pointer;
}

.ctt-auth__google:hover[b-bldpz0i4fj] {
    background: var(--sunken);
    color: var(--ink);
}

.ctt-auth__google:focus-visible[b-bldpz0i4fj] {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

/* Google's mark keeps its own four colours in both themes - it is somebody else's logo and recolouring
   it is both wrong and against their brand terms. flex: none so a long label cannot squash it. */
.ctt-auth__gmark[b-bldpz0i4fj] {
    width: 1.125rem;
    height: 1.125rem;
    flex: none;
}

/* The button and its info icon on one line. The button takes the width; the icon sits at its end. */
.ctt-auth__google-row[b-bldpz0i4fj] {
    display: flex;
    align-items: center;
    gap: var(--space-1);
}

.ctt-auth__google-row .ctt-auth__google[b-bldpz0i4fj] {
    flex: 1 1 auto;
    min-width: 0;
}

/* ::deep: InfoHint renders the button that carries this class, not this page. */
.ctt-auth__google-row[b-bldpz0i4fj]  .ctt-auth__hint {
    flex: none;
}

/* ---------------------------------------------------------------- the divider */

.ctt-auth__or[b-bldpz0i4fj] {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--muted);
}

.ctt-auth__or[b-bldpz0i4fj]::before,
.ctt-auth__or[b-bldpz0i4fj]::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--rule);
}

/* ---------------------------------------------------------------- the code step */

.ctt-auth__step[b-bldpz0i4fj] {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    margin: 0 0 var(--space-2);
}

.ctt-auth__status[b-bldpz0i4fj] {
    font-size: var(--text-sm);
    color: var(--muted);
    margin: 0;
    text-align: center;
}

/* The two warnings on the code step: nobody will ever ask you for this code, and the mail may be
   slow. Ink rather than muted, and marked with the warn rule - both change what the reader does
   next, so neither is a footnote. This is a semantic use of --warn, not decoration. */
.ctt-signin__warn[b-bldpz0i4fj] {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    color: var(--ink);
    border-left: 3px solid var(--warn);
    padding-left: var(--space-3);
    margin-bottom: var(--space-3);
    font-size: var(--text-sm);
}

/* The code field. Monospace and spaced out, because eight digits are read back digit by digit from a
   mail against the screen. */
.ctt-signin__code[b-bldpz0i4fj] {
    font-family: var(--font-mono);
    font-size: var(--text-md);
    letter-spacing: 0.25em;
    text-align: center;
}
