html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

/* ══════════════════════════════════════════════════════════════════════
   ACRES DESIGN TOKENS — flat, editorial, low-chrome. See docs/STYLE_GUIDE.md.
   Aesthetic: ink + gray on paper; accent color ONLY signals a data state;
   hairline borders, no shadows, small radii, type carries the hierarchy.
   ══════════════════════════════════════════════════════════════════════ */
:root {
    /* color roles.
       --acres-ink is taken from the official logo file, wwwroot/acres_full_logo.svg,
       which is a monochrome #003761. It read #1e365e here until 2026-08-11, so every
       surface in the app had been slightly off-brand since the beginning. MudTheme
       in Layout/MainLayout.razor carried the same wrong value and was corrected in
       the same pass — those are the only two places the brand navy is defined. */
    --acres-ink:      #003761;  /* brand navy — titles, primary text          */
    --acres-ink-deep: #10233b;  /* heavy rules, the report's structural lines  */
    --acres-ink-2:    #47576b;  /* secondary text                             */
    /* #7d8a99 measured ~3.3:1 on white and failed the 4.5:1 floor for small
       text, which is most of what this token is used for — labels, dates and
       acreage. #64707e is ~4.7:1 and reads at arm's length outdoors. Keep
       FieldConditions.Neutral in step: it is the same role in inline styles. */
    --acres-gray:     #64707e;  /* labels, muted, and "we do not know"        */
    --acres-line:     #dde2e7;  /* hairline borders / dividers                */
    --acres-surface:  #ffffff;  /* sheets and cards                           */
    /* The white panel a map screen floats over satellite imagery. Not quite
       opaque, so a farmer keeps some sense of the ground beneath the controls.
       Map and Forecast between them used FOUR alphas for this one surface
       (0.97, 0.95, 0.93, 0.92) on rows that sit directly against each other,
       which reads as a rendering fault rather than a hierarchy. One value. */
    --acres-overlay:  rgba(255, 255, 255, 0.97);
    /* The ground the white sheets sit on. Briefly #ffffff during the 2026-08-11
       rebuild, which removed the figure/ground relationship entirely: white
       content on a white page has no edges, so a 600px column in a 1440px window
       read as an unbounded field of empty space rather than a document. Cool
       rather than the previous warm #f6f6f3, which tinted toward cream. */
    --acres-bg:       #eef0f2;  /* page ground                                */
    /* accents — used ONLY to signal state, never decoration.
       Kept in step with the FieldConditions.Good/Watch/Bad/Neutral constants,
       which are what the field rows read for their inline colors. */
    --acres-green:   #2f6b34;   /* good / crop / NDVI                        */
    --acres-blue:    #2f6f96;   /* water / moisture / rain                   */
    --acres-amber:   #b8791d;   /* watch / caution                           */
    --acres-red:     #a8342f;   /* stress / alert / frost                    */
    /* shape + spacing — flat: small radii, no shadow */
    --r-card: 6px;
    --r-pill: 6px;
    --s-1: 4px;  --s-2: 8px;  --s-3: 14px;  --s-4: 20px;
    --hair: 1px solid var(--acres-line);
    /* Height of the fixed bottom tab bar, excluding the device's safe area.
       Must stay in step with .tb-item's height in Layout/TabBar.razor.css. */
    --acres-tabbar: 54px;
    /* Space to leave below the tab bar for the system's own bottom furniture.
       In a browser env() is the whole story. The MAUI host overrides this with a
       floor, because Android's WebView reports 0 here even under viewport-fit=cover
       and its gesture pill then draws straight over the tabs. */
    --acres-safe-bottom: env(safe-area-inset-bottom, 0px);
    /* Height of the app bar, owned by THIS app rather than read from MudBlazor.
       Both the pinned page header's sticky offset and the main content's padding
       derive from it, and they must agree exactly — when they were both computed
       from var(--mud-appbar-height, 64px) they disagreed by 16px, because the bar
       MudBlazor actually rendered was 48px tall. Measured off an Android
       screenshot 2026-08-12: a 16px strip of scrolling rows showed through
       between the app bar and the pinned header. Setting the height here means
       nothing has to guess it. */
    --acres-appbar-h: 56px;
    /* Total height the app bar occupies, including any system inset above it. A page
       that wants to fill the screen exactly (the map) sizes itself from this rather
       than hardcoding an offset — which is what left FieldCurrent's first row under
       the logo when the bar's height changed. */
    --acres-appbar-total: var(--acres-appbar-h);
    /* Viewport offset of the app bar's bottom edge — where a pinned page header
       sticks to. The browser's app bar starts at 0; the MAUI host shifts it down by
       the status bar and overrides this. */
    /* Viewport offset of the app bar's bottom edge: where a pinned page header
       sticks, and how much top padding the content reserves. The MAUI host adds its
       status bar to this. */
    --acres-header-top: var(--acres-appbar-h);

    /* legacy aliases (existing rules below still reference these) */
    --brand-navy: var(--acres-ink);
    --brand-green: var(--acres-green);
}

/* The document does not scroll; the content pane does. A fixed bar over a scrolling
   document lags the scroll in Android's WebView, and neither translateZ(0) nor
   overscroll-behavior stopped it. If the document never scrolls there is nothing for
   a fixed element to lag behind.
   This is deliberately NOT the flex-column shell that was tried and reverted: no
   height maths, no viewport units, no per-page sizing. The content pane is pinned
   between the two bars using the same two tokens they are positioned with. */
html, body {
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
}

/* ── Browser surfaces. These ship with defaults that belong to no design
   system, so they are themed explicitly rather than left to the UA. ────── */
::selection { background: var(--acres-ink); color: #fff; }
:focus-visible {
    outline: 2px solid var(--acres-ink);
    outline-offset: 2px;
}

/* Content must clear the fixed tab bar, or the last field row sits under it.
   MAUI adds its own padding-top to this same element for the status bar; these
   are different properties and do not fight. */
/* The app bar and the tab bar are both position:fixed, so content reserves space
   for each. Two values, both tokens — this replaced a non-scrolling flex shell whose
   six interlocking variables caused four consecutive layout regressions. */
.mud-main-content {
    position: fixed;
    top: var(--acres-header-top);
    left: 0;
    right: 0;
    bottom: calc(var(--acres-tabbar) + var(--acres-safe-bottom));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    /* No padding-top: the pane already begins below the app bar, and a padding-top
       here would offset every position:sticky page header, which pins to a scroll
       container's PADDING box rather than its top edge. */
    padding-top: 0;
    padding-bottom: var(--s-4);
}

/* These two are still viewport-fixed, so they must clear the tab bar the shell now
   reserves at the bottom. A snackbar behind the tabs is a message never received. */
#blazor-error-ui {
    bottom: calc(var(--acres-tabbar) + var(--acres-safe-bottom)) !important;
}

.mud-snackbar-location-bottom-left,
.mud-snackbar-location-bottom-center,
.mud-snackbar-location-bottom-right {
    padding-bottom: calc(var(--acres-tabbar) + var(--acres-safe-bottom));
}

/* ── Shared flat components — one definition, used across pages ──────────
   Pages opt in with these classes; page-scoped CSS handles only layout.   */

.acres-card {
    background: var(--acres-surface);
    border: var(--hair);
    border-radius: var(--r-card);
    padding: var(--s-3);
    /* no box-shadow — flatness is the point */
}

.acres-pill {                    /* tabs, toggles, steppers, chips */
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    padding: 5px 12px;
    border: var(--hair);
    border-radius: var(--r-pill);
    background: var(--acres-surface);
    font-size: 12px;
    font-weight: 600;
    color: var(--acres-ink-2);
    cursor: pointer;
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
    transition: background .12s, border-color .12s, color .12s;
}
.acres-pill--on {                /* selected — flat fill, no gradient */
    background: var(--acres-ink);
    border-color: var(--acres-ink);
    color: #fff;
}

.acres-label  { font-size: 10px; font-weight: 600; letter-spacing: .05em;
                text-transform: uppercase; color: var(--acres-gray); }
.acres-title  { font-size: 16px; font-weight: 700; color: var(--acres-ink); }
.acres-value  { font-size: 20px; font-weight: 700; color: var(--acres-ink); line-height: 1.15; }
.acres-detail { font-size: 11px; color: var(--acres-gray); line-height: 1.35; }

a, .btn-link {
    color: var(--brand-navy);
}

.btn-primary {
    color: #fff;
    background-color: var(--brand-navy);
    border-color: var(--brand-navy);
}

.btn-primary:hover, .btn-primary:active, .btn-primary:focus {
    background-color: #162848;
    border-color: #162848;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem var(--acres-ink);
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}
