/* ==========================================================================
   AgryOS design system
   Premium farm-management UI: deep forest greens, warm harvest amber,
   paper-warm neutrals. All class names are stable — every view in the app
   builds on this vocabulary.
   ========================================================================== */

/* ---------- Fonts (self-hosted Inter, OFL — see wwwroot/fonts/inter/LICENSE.txt) ---------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter/inter-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/inter/inter-latin-500-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter/inter-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter/inter-latin-700-normal.woff2") format("woff2");
}

:root {
  /* Forest green scale */
  --g-950: #062015;
  --g-900: #0a2f1e;
  --g-800: #10402a;
  --g-700: #165236;
  --g-600: #1c6642;
  --g-500: #26794f;
  --g-400: #439465;
  --g-300: #7ab894;
  --g-200: #b8dbc4;
  --g-100: #e0f0e6;
  --g-50: #f1f8f3;

  /* Harvest amber scale */
  --a-700: #975a0d;
  --a-600: #b87514;
  --a-500: #d99a2b;
  --a-400: #ecb64d;
  --a-200: #f6d997;
  --a-100: #fdf1d7;
  --a-50: #fef9ec;

  /* Warm paper neutrals (slightly warm so the app feels earthy, not clinical) */
  --n-900: #181c1a;
  --n-800: #272c29;
  --n-700: #3d4340;
  --n-600: #59605b;
  --n-500: #6e756f;
  --n-400: #98a09a;
  --n-300: #d3d8d4;
  --n-200: #e5e8e5;
  --n-100: #f0f2f0;
  --n-50: #f7f8f7;

  /* Semantic */
  --success-600: var(--g-600);
  --success-100: var(--g-100);
  --warning-600: var(--a-600);
  --warning-100: var(--a-100);
  --danger-600: #c2402f;
  --danger-100: #fce9e6;
  --info-600: #2e6e8e;
  --info-100: #e3f0f6;

  /* ---------- Data colour: charts, land use, grazing status ----------
     One source of truth for every colour that encodes *meaning* rather than chrome.
     Before this block the app carried six different greens all claiming to be the brand
     (#1c6642, #1f6b3a, #2e7d32, #059669, #064e3b, #1a5430), two different chart palettes on
     the dashboard alone, and a Material-palette grazing legend that shared no family with the
     land-use colours on the farm map. Charts and Leaflet need real hex at runtime, so JS reads
     these through agryColour() rather than keeping a second copy - see agry-map.js.

     Pinned literals, not theme tokens: these sit on satellite imagery and in printed reports,
     where the meaning must not invert with the light/dark toggle. */
  --chart-1: #1c6642;   /* brand green - first series, revenue */
  --chart-2: #c2402f;   /* clay red - second series, cost */
  --chart-3: #2e6e8e;   /* slate blue - third series */
  --chart-4: #b87514;   /* ochre */
  --chart-5: #6b4d8a;   /* heather */

  /* Land use, keyed to what the ground actually is. Read at a glance: grass, crop, trees. */
  --land-grazing: #2e7d32;
  --land-crop: #c8952b;
  --land-wood: #5d4037;
  --land-none: #546e7a;

  /* Grazing rotation state. Deliberately the same family as land use above - a paddock being
     grazed and a paddock of grass should not look like they came from different products. */
  --graze-active: #1c6642;
  --graze-ready: #2e7d32;
  --graze-resting: #b87514;
  --graze-empty: #546e7a;

  --agry-primary: var(--g-600);
  --agry-primary-dark: var(--g-800);
  --agry-bg: var(--n-50);
  --agry-surface: #ffffff;
  --agry-border: var(--n-200);
  --agry-text: var(--n-900);
  /* Muted text is read outdoors, on a phone, in direct sun, often through a smeared screen
     protector. The 500 step measured 4.44:1 against the page - which fails WCAG AA for body
     text (4.5:1) before you even leave the office. The 700 step measures 9.49:1: comfortably
     AAA, and still visibly lighter than body text (16.2:1) so the hierarchy survives.
     This single token feeds .text-muted, .form-hint, .page-lede, .stat-label, .stat-cap,
     .empty-state and the sparkline legend, so it is the highest-leverage contrast fix here. */
  --agry-text-muted: var(--n-700);
  --agry-sidebar-width: 16.5rem;

  --radius-sm: 0.5rem;
  --radius-md: 0.75rem;
  --radius-lg: 1rem;
  --radius-xl: 1.25rem;

  /* Layered, low-elevation shadows with a warm base */
  --shadow-xs: 0 1px 2px rgba(18, 26, 21, 0.06);
  --shadow-sm: 0 1px 2px rgba(18, 26, 21, 0.05), 0 2px 6px -1px rgba(18, 26, 21, 0.06);
  --shadow-md: 0 2px 4px -1px rgba(18, 26, 21, 0.05), 0 10px 24px -6px rgba(18, 26, 21, 0.10);
  --shadow-lg: 0 4px 8px -2px rgba(18, 26, 21, 0.06), 0 24px 48px -12px rgba(18, 26, 21, 0.18);

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Type scale */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 1.875rem;

  /* Retint Bootstrap's own palette so every built-in component picks up the brand for free. */
  --bs-primary: var(--agry-primary);
  --bs-primary-rgb: 28, 102, 66;
  --bs-link-color: var(--agry-primary);
  --bs-link-hover-color: var(--agry-primary-dark);
  --bs-body-color: var(--agry-text);
  --bs-body-bg: var(--agry-bg);
  --bs-border-color: var(--agry-border);
  --bs-border-radius: var(--radius-sm);
  --bs-body-font-family: var(--font-sans);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--agry-bg);
  color: var(--agry-text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: 1.55;
  font-feature-settings: "cv11", "ss01", "tnum" 0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
  letter-spacing: -0.02em;
  font-weight: 650;
  line-height: 1.25;
  color: var(--n-900);
}

a { transition: color 0.15s ease; }

::selection { background: var(--g-200); color: var(--g-900); }

/* Consistent, visible keyboard focus everywhere */
:focus-visible {
  outline: 2px solid var(--g-500);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Quiet scrollbars that match the theme (webkit) */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--n-300); border-radius: 999px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--n-400); border: 2px solid transparent; background-clip: content-box; }

.text-tabular, .stat-value, td .text-end, .table-agry td { font-variant-numeric: tabular-nums; }

.text-muted { color: var(--agry-text-muted) !important; }

/* Small muted helper line beneath a form input — explains what to enter. */
.form-hint {
  font-size: var(--text-xs);
  color: var(--agry-text-muted);
  margin-top: 0.3rem;
  line-height: 1.45;
}

/* Muted one-liner under a page heading that says what the page is for. */
.page-lede {
  color: var(--agry-text-muted);
  font-size: var(--text-sm);
  margin: -0.35rem 0 1.25rem;
  max-width: 70ch;
}

/* ---------- Buttons ---------- */
.btn {
  border-radius: var(--radius-sm);
  font-weight: 550;
  letter-spacing: -0.005em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  min-height: 2.375rem;
  transition: transform 0.12s ease, box-shadow 0.12s ease, background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  box-shadow: var(--shadow-xs);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(0.99); }
.btn-sm { border-radius: var(--radius-sm); min-height: 2rem; }

.btn-primary {
  --bs-btn-bg: var(--g-600);
  --bs-btn-border-color: var(--g-600);
  --bs-btn-hover-bg: var(--g-700);
  --bs-btn-hover-border-color: var(--g-700);
  --bs-btn-active-bg: var(--g-800);
  --bs-btn-active-border-color: var(--g-800);
  --bs-btn-disabled-bg: var(--g-400);
  --bs-btn-disabled-border-color: var(--g-400);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 45%);
  box-shadow: var(--shadow-xs), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
.btn-primary:hover { box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.12); }

.btn-success {
  --bs-btn-bg: var(--g-600);
  --bs-btn-border-color: var(--g-600);
  --bs-btn-hover-bg: var(--g-700);
  --bs-btn-hover-border-color: var(--g-700);
  --bs-btn-active-bg: var(--g-800);
  --bs-btn-active-border-color: var(--g-800);
}

.btn-danger {
  --bs-btn-bg: var(--danger-600);
  --bs-btn-border-color: var(--danger-600);
  --bs-btn-hover-bg: #a93525;
  --bs-btn-hover-border-color: #a93525;
  --bs-btn-active-bg: #932d1f;
  --bs-btn-active-border-color: #932d1f;
}

.btn-outline-secondary {
  --bs-btn-color: var(--n-700);
  --bs-btn-border-color: var(--n-300);
  --bs-btn-hover-bg: var(--n-100);
  --bs-btn-hover-border-color: var(--n-300);
  --bs-btn-hover-color: var(--n-900);
  --bs-btn-active-bg: var(--n-200);
  --bs-btn-active-border-color: var(--n-300);
  --bs-btn-active-color: var(--n-900);
  background: var(--agry-surface);
}

.btn-outline-danger {
  --bs-btn-color: var(--danger-600);
  --bs-btn-border-color: var(--n-300);
  --bs-btn-hover-bg: var(--danger-100);
  --bs-btn-hover-border-color: var(--danger-600);
  --bs-btn-hover-color: var(--danger-600);
  --bs-btn-active-bg: var(--danger-100);
  --bs-btn-active-border-color: var(--danger-600);
  --bs-btn-active-color: var(--danger-600);
  background: var(--agry-surface);
}

.btn-outline-primary {
  --bs-btn-color: var(--g-700);
  --bs-btn-border-color: var(--g-300);
  --bs-btn-hover-bg: var(--g-50);
  --bs-btn-hover-border-color: var(--g-500);
  --bs-btn-hover-color: var(--g-800);
  --bs-btn-active-bg: var(--g-100);
  --bs-btn-active-border-color: var(--g-500);
  --bs-btn-active-color: var(--g-800);
  background: var(--agry-surface);
}

.btn-link {
  text-decoration: none;
  box-shadow: none;
  min-height: 0;
}
.btn-link:hover { text-decoration: underline; transform: none; }

/* Quiet icon-only action button (table rows, card headers) */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  min-height: 0;
  padding: 0;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: transparent;
  /* Icon-only buttons carry no label to fall back on, so the glyph itself has to be legible
     at arm's length in a shed - the 500 step was 4.44:1, below AA. */
  color: var(--n-600);
  box-shadow: none;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.btn-icon:hover { background: var(--n-100); color: var(--n-800); transform: none; }
.btn-icon.danger:hover { background: var(--danger-100); color: var(--danger-600); }

/* ---------- Forms ---------- */
.form-control, .form-select {
  border-radius: var(--radius-sm);
  border-color: var(--n-300);
  background-color: var(--n-50);
  padding: 0.5rem 0.75rem;
  min-height: 2.625rem; /* 42px touch-friendly */
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}
textarea.form-control { min-height: 0; }
.form-control:focus, .form-select:focus {
  background-color: var(--agry-surface);
  border-color: var(--g-500);
  box-shadow: 0 0 0 3px var(--g-100);
}
/* Placeholders here are worked examples ("e.g. Aberdeen Angus"), not decoration - they earn
   being readable. The 400 step measured 2.52:1, which is invisible outdoors. */
.form-control::placeholder { color: var(--n-600); }
.form-control:disabled, .form-select:disabled { background-color: var(--n-100); color: var(--n-500); }

.form-label {
  font-weight: 550;
  font-size: var(--text-sm);
  color: var(--n-800);
  margin-bottom: 0.35rem;
  letter-spacing: -0.005em;
}

.form-check-input:checked { background-color: var(--g-600); border-color: var(--g-600); }
.form-check-input:focus { border-color: var(--g-500); box-shadow: 0 0 0 3px var(--g-100); }

.input-group-text {
  background: var(--n-100);
  border-color: var(--n-300);
  color: var(--n-600);
  border-radius: var(--radius-sm);
}

/* Validation states keep brand colours */
.valid-feedback { color: var(--g-600); }
.invalid-feedback { color: var(--danger-600); }
.was-validated .form-control:valid, .form-control.is-valid { border-color: var(--g-500); }
.was-validated .form-control:invalid, .form-control.is-invalid { border-color: var(--danger-600); }
.field-validation-error { color: var(--danger-600); font-size: var(--text-xs); margin-top: 0.3rem; display: block; }

/* ---------- App shell ---------- */
.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: var(--agry-sidebar-width);
  flex-shrink: 0;
  background:
    radial-gradient(120% 60% at 0% 0%, rgba(122, 184, 148, 0.14), transparent 55%),
    radial-gradient(90% 45% at 100% 100%, rgba(236, 182, 77, 0.07), transparent 60%),
    linear-gradient(185deg, var(--g-800) 0%, var(--g-900) 55%, var(--g-950) 100%);
  color: #e9f1ea;
  display: flex;
  flex-direction: column;
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 1040;
  transition: transform 0.22s ease;
  box-shadow: var(--shadow-lg);
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 1.4rem 1.5rem 1.15rem;
  font-weight: 700;
  font-size: 1.22rem;
  letter-spacing: -0.02em;
  color: #fff;
  text-decoration: none;
}

.sidebar-brand svg {
  flex-shrink: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.06));
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0.6rem;
  padding: 5px;
  width: 32px;
  height: 32px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 0.35rem 0.85rem 1rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.18); border: none; }

.sidebar-section-label {
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.62);
  padding: 1.15rem 0.65rem 0.4rem;
}

.sidebar-nav .nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  color: rgba(255, 255, 255, 0.76);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.65rem 0.5rem 0.8rem;
  font-size: 0.89rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  margin-bottom: 0.1rem;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.sidebar-nav .nav-link svg { flex-shrink: 0; opacity: 0.8; transition: opacity 0.15s ease; }

/* Sub-pages of the entry above them - a batch's welfare, its individuals, its incubation.
   Indented and iconless so the group reads as one section rather than as separate
   destinations, with a hairline connecting them back to the parent. */
.sidebar-nav .nav-sublink {
  display: block;
  position: relative;
  margin-left: 1.55rem;
  padding: 0.32rem 0.65rem 0.32rem 0.75rem;
  border-left: 1px solid rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.62);
  font-size: 0.83rem;
  font-weight: 500;
  text-decoration: none;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.sidebar-nav .nav-sublink:hover {
  color: #fff;
  border-left-color: rgba(255, 255, 255, 0.5);
}
.sidebar-nav .nav-sublink.active {
  color: #fff;
  font-weight: 600;
  border-left-color: var(--a-400);
}

.sidebar-nav .nav-link:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}
.sidebar-nav .nav-link:hover svg { opacity: 1; }

.sidebar-nav .nav-link.active {
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.08));
  color: #fff;
  font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}
.sidebar-nav .nav-link.active svg { opacity: 1; color: var(--a-400); }
.sidebar-nav .nav-link.active::before {
  content: "";
  position: absolute;
  left: -0.85rem;
  top: 0.35rem;
  bottom: 0.35rem;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--a-400), var(--a-500));
  box-shadow: 0 0 8px rgba(236, 182, 77, 0.55);
}

.sidebar-footer {
  padding: 0.95rem 1.5rem;
  font-size: 0.72rem;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.60);
  border-top: 1px solid rgba(255, 255, 255, 0.09);
}

.app-main {
  flex: 1;
  margin-left: var(--agry-sidebar-width);
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.topbar {
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(12px) saturate(1.4);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  border-bottom: 1px solid var(--agry-border);
  padding: 0.95rem 1.75rem;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  position: sticky;
  top: 0;
  z-index: 1020;
}

.topbar .page-title {
  font-size: 1.28rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  margin: 0;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* Topbar "Guide" button — launches the interactive tour for the current page */
.guide-launch {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--n-200);
  background: var(--agry-surface);
  color: var(--n-600);
  font-size: var(--text-sm);
  font-weight: 550;
  border-radius: 999px;
  padding: 0.32rem 0.85rem;
  box-shadow: var(--shadow-xs);
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.12s ease;
}
.guide-launch svg { color: var(--g-600); }
.guide-launch:hover {
  background: var(--g-50);
  border-color: var(--g-300);
  color: var(--g-800);
  transform: translateY(-1px);
}
.guide-launch:hover svg { color: var(--g-700); }

.sidebar-toggle {
  display: none;
  border: none;
  background: none;
  padding: 0.25rem;
  color: var(--agry-text);
}

.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(10, 15, 12, 0.45);
  backdrop-filter: blur(2px);
  z-index: 1030;
}

.content {
  padding: 1.75rem;
  flex: 1;
  max-width: 1400px;
  width: 100%;
  background-image: radial-gradient(60rem 30rem at 100% -10%, rgba(28, 102, 66, 0.06), transparent 60%);
  background-repeat: no-repeat;
  animation: content-fade-in 0.22s ease;
}

@keyframes content-fade-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.topbar-user { display: flex; align-items: center; gap: 0.6rem; }
.topbar-user-avatar {
  width: 2.05rem;
  height: 2.05rem;
  border-radius: 50%;
  background: linear-gradient(160deg, var(--g-200), var(--g-100));
  border: 1px solid var(--g-200);
  color: var(--g-800);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.8rem;
  flex-shrink: 0;
}
.topbar-user-email { font-size: var(--text-sm); color: var(--n-700); }

@media (max-width: 991.98px) {
  .sidebar { transform: translateX(-100%); }
  .app-shell.sidebar-open .sidebar { transform: translateX(0); }
  .app-shell.sidebar-open .sidebar-backdrop { display: block; }
  .app-main { margin-left: 0; }
  .sidebar-toggle { display: inline-flex; }
  .content { padding: 1.1rem; }
  .topbar { padding: 0.8rem 1.1rem; gap: 0.6rem; }
  .topbar .page-title { font-size: 1.1rem; }
  .guide-launch .guide-launch-text { display: none; }
  .guide-launch { padding: 0.32rem 0.55rem; }
}

@media (max-width: 575.98px) {
  .topbar-user-email { display: none; }
  .section-heading { flex-wrap: wrap; row-gap: 0.65rem; }
  .section-heading > .ms-auto {
    margin-left: 0 !important;
    width: 100%;
    display: flex;
    gap: 0.5rem;
  }
  .section-heading > .ms-auto > .btn,
  .section-heading > .ms-auto > a.btn { flex: 1 1 0; }
  .stat-tile { padding: 1rem 1.1rem; }
  .stat-tile .stat-value { font-size: 1.55rem; }
  .agry-card { padding: 1.1rem; }
}

/* ---------- Reusable surfaces ---------- */
.agry-card {
  background: var(--agry-surface);
  border: 1px solid var(--agry-border);
  border-radius: var(--radius-lg);
  padding: 1.45rem;
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.7);
  transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}

a.agry-card { display: block; text-decoration: none; color: inherit; }
a.agry-card:hover, .agry-card-hover:hover {
  box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255, 255, 255, 0.7);
  transform: translateY(-2px);
  border-color: var(--n-300);
}

.stat-tile {
  background: var(--agry-surface);
  border: 1px solid var(--agry-border);
  border-radius: var(--radius-lg);
  padding: 1.25rem 1.35rem;
  height: 100%;
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.7);
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.stat-tile:hover { box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255, 255, 255, 0.7); }

.stat-tile-icon {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.65rem;
  background: linear-gradient(160deg, var(--g-100), var(--g-50));
  border: 1px solid var(--g-100);
  color: var(--g-700);
}
.stat-tile.warn .stat-tile-icon { background: var(--a-100); border-color: var(--a-100); color: var(--a-700); }
.stat-tile.danger .stat-tile-icon { background: var(--danger-100); border-color: var(--danger-100); color: var(--danger-600); }
.stat-tile.ok .stat-tile-icon { background: linear-gradient(160deg, var(--g-100), var(--g-50)); border-color: var(--g-100); color: var(--g-700); }

.stat-tile .stat-label {
  font-size: 0.74rem;
  font-weight: 650;
  color: var(--agry-text-muted);
  display: flex;
  align-items: center;
  gap: 0.35rem;
  text-transform: uppercase;
  letter-spacing: 0.045em;
}

.stat-tile .stat-value {
  font-size: 1.95rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  margin-top: 0.1rem;
  line-height: 1.12;
}

.stat-tile .stat-cap { font-size: 0.8rem; color: var(--agry-text-muted); }

.stat-tile.danger { box-shadow: var(--shadow-sm), inset 3px 0 0 var(--danger-600); }
.stat-tile.warn { box-shadow: var(--shadow-sm), inset 3px 0 0 var(--a-500); }

.section-heading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.section-heading h2 { font-size: var(--text-2xl); letter-spacing: -0.025em; }
.section-heading h5 { font-size: 1.05rem; font-weight: 650; }
.section-heading h2, .section-heading h5, .section-heading h6 { margin: 0; }

/* ---------- Badges ---------- */
/* Soft pill badges: tinted background + matching dark text. */
.badge {
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.01em;
  padding: 0.35em 0.7em;
  align-self: center;
  flex-shrink: 0;
}

.badge.text-bg-success { background-color: var(--success-100) !important; color: var(--g-800) !important; }
.badge.text-bg-warning { background-color: var(--warning-100) !important; color: var(--a-700) !important; }
.badge.text-bg-danger { background-color: var(--danger-100) !important; color: var(--danger-600) !important; }
.badge.text-bg-info { background-color: var(--info-100) !important; color: var(--info-600) !important; }
.badge.text-bg-secondary { background-color: var(--n-100) !important; color: var(--n-700) !important; }
.badge.text-bg-light { background-color: var(--n-100) !important; color: var(--n-700) !important; border-color: var(--n-200) !important; }

/* Lifecycle status.
   Active and Harvested are the normal run of things and stay as soft tints - they are the
   background hum of a batch list and shouldn't shout.

   Quarantined and Culled are the two states a vet, an inspector or a recall actually hunts for,
   and they were the two that read weakest: Culled was pixel-identical to the generic
   .text-bg-secondary pill, and Quarantined was indistinguishable from any .text-bg-warning
   badge elsewhere on the same row. Both are now SOLID rather than tinted, which is a difference
   in kind rather than degree - scanning a table from a few feet away, a filled pill separates
   from a page of soft ones instantly, without relying on hue discrimination (~8% of male
   farmers are red-green colour deficient, so shape and fill weight carry the signal, not colour
   alone). Measured 7.06:1 (quarantined) and 10.1:1 (culled).

   The two solid pills are pinned to literals, not tokens: --n-900 and --n-700 invert between
   themes, which would turn the amber pill into amber-on-white and the culled pill into
   white-on-pale-grey the moment someone switched to dark. A compliance signal must not change
   meaning with a theme toggle. */
.badge-status-active { background: var(--success-100); color: var(--g-800); }
.badge-status-harvested { background: var(--info-100); color: var(--info-600); }
.badge-status-quarantined {
  background: #d99a2b;
  color: #181c1a;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.14);
}
.badge-status-culled {
  background: #3d4340;
  color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
}

/* ---------- Help icon + branded popover ---------- */
.help-icon {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  background: var(--g-100);
  color: var(--g-700);
  cursor: help;
  margin-left: 0.35rem;
  vertical-align: middle;
  border: 1px solid var(--g-200);
  flex-shrink: 0;
  transition: all 0.15s ease;
}
.help-icon svg {
  width: 12px;
  height: 12px;
  display: block;
}
.badge .help-icon { background: transparent; border-color: transparent; color: var(--n-400); }
.stat-tile .help-icon {
  background: var(--g-100);
  color: var(--g-800);
  border: 1px solid var(--g-200);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.help-icon:hover, .help-icon:focus,
.stat-tile .help-icon:hover, .stat-tile .help-icon:focus {
  background: var(--g-600);
  color: #fff;
  border-color: var(--g-600);
  outline: none;
  transform: scale(1.12);
}

.popover {
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--n-200);
  max-width: 300px;
  --bs-popover-header-bg: var(--g-50);
  --bs-popover-header-color: var(--g-800);
}
.popover-header {
  font-size: 0.82rem;
  font-weight: 650;
  letter-spacing: -0.005em;
  border-bottom: 1px solid var(--n-200);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  padding: 0.55rem 0.9rem;
}
.popover-body { font-size: 0.85rem; padding: 0.7rem 0.9rem; color: var(--n-700); line-height: 1.5; }
.popover-body ul, .popover-body ol { padding-left: 1.1rem; margin: 0.35rem 0 0; }
.popover-body li + li { margin-top: 0.2rem; }
.popover-body .popover-example {
  display: block;
  margin-top: 0.45rem;
  padding: 0.4rem 0.55rem;
  background: var(--n-50);
  border: 1px solid var(--n-200);
  border-radius: var(--radius-sm);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.76rem;
  color: var(--g-800);
}

/* ---------- Empty states ---------- */
.empty-state {
  text-align: center;
  padding: 3rem 1.5rem;
  color: var(--agry-text-muted);
  border: 1.5px dashed var(--n-300);
  border-radius: var(--radius-md);
  font-size: 0.92rem;
  background: var(--n-50);
}
.empty-state-icon {
  width: 3rem;
  height: 3rem;
  margin: 0 auto 0.9rem;
  border-radius: 50%;
  background: var(--agry-surface);
  border: 1px solid var(--n-200);
  box-shadow: var(--shadow-xs);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--g-500);
}
.empty-state-title {
  font-weight: 650;
  font-size: 1.02rem;
  color: var(--n-800);
  letter-spacing: -0.01em;
  margin-bottom: 0.3rem;
}
.empty-state-text { max-width: 46ch; margin: 0 auto 1.1rem; line-height: 1.55; }
.empty-state .btn { margin-top: 0.15rem; }

/* ---------- Tables ---------- */
/* overflow-x:auto so wide tables scroll horizontally on narrow screens instead of
   squashing columns illegibly, while overflow-y:hidden still clips to the rounded card. */
.agry-card.p-0 { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }

.table-agry {
  margin-bottom: 0;
  min-width: 560px;
  --bs-table-bg: transparent;
}
.table-agry thead th {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--n-700);
  border-bottom: 1px solid var(--agry-border);
  padding: 0.8rem 1rem;
  background: var(--n-50);
}
.table-agry th, .table-agry td { white-space: nowrap; }
.table-agry td.wrap { white-space: normal; }
.table-agry tbody td {
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--n-100);
  vertical-align: middle;
  font-size: 0.9rem;
}
.table-agry tbody tr:last-child td { border-bottom: none; }
.table-agry tbody tr { transition: background-color 0.12s ease; }
.table-agry tbody tr:hover { background: var(--g-50); }
.table-agry a { text-decoration: none; font-weight: 600; }
.table-agry a:hover { text-decoration: underline; }

.list-group-item { border-color: var(--n-100); background: transparent; }

/* ---------- Sparkline chart ---------- */
.sparkline-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  margin-top: 0.75rem;
  font-size: var(--text-xs);
  color: var(--agry-text-muted);
}
.sparkline-legend .dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

/* ---------- SOP / markdown content ---------- */
.sop-content { line-height: 1.7; }
.sop-content h2 { font-size: 1.15rem; margin-top: 1.5rem; font-weight: 650; }
.sop-content h3 { font-size: 1.02rem; font-weight: 650; }
.sop-content ol, .sop-content ul { padding-left: 1.3rem; }

/* ---------- Alerts (soft tint + left accent) ---------- */
.alert {
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  border-left-width: 3px;
  font-size: var(--text-sm);
  box-shadow: var(--shadow-xs);
}
.alert-success { background: var(--success-100); color: var(--g-800); border-color: var(--g-200); border-left-color: var(--g-500); }
.alert-danger { background: var(--danger-100); color: #8f2b1c; border-color: #f2c9c2; border-left-color: var(--danger-600); }
.alert-warning { background: var(--warning-100); color: var(--a-700); border-color: var(--a-200); border-left-color: var(--a-500); }
.alert-info { background: var(--info-100); color: var(--info-600); border-color: #c2dcea; border-left-color: var(--info-600); }
.alert .btn-close { font-size: 0.7rem; }

/* Clickable alert rows that jump to the page where the issue is fixed (dashboard). */
.alert a.alert-jump {
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius-sm);
  margin: -0.15rem -0.35rem;
  padding: 0.15rem 0.35rem;
  transition: background-color 0.12s ease;
}
.alert a.alert-jump:hover {
  color: inherit;
  background: rgba(255, 255, 255, 0.45);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---------- Modals / dropdowns / pills ---------- */
.modal-content {
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.modal-header { border-bottom: 1px solid var(--n-100); padding: 1.15rem 1.4rem; }
.modal-title { font-weight: 650; letter-spacing: -0.015em; font-size: 1.1rem; }
.modal-body { padding: 1.4rem; }
.modal-footer { border-top: 1px solid var(--n-100); padding: 1rem 1.4rem; }
.modal-backdrop.show { opacity: 0.45; }

.dropdown-menu {
  border: 1px solid var(--n-200);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 0.4rem;
  font-size: var(--text-sm);
}
.dropdown-item { border-radius: var(--radius-sm); padding: 0.45rem 0.7rem; }
.dropdown-item:hover, .dropdown-item:focus { background: var(--g-50); color: var(--g-800); }
.dropdown-item:active { background: var(--g-100); color: var(--g-900); }

.nav-pills {
  gap: 0.35rem;
  background: var(--n-100);
  padding: 0.3rem;
  border-radius: 999px;
  display: inline-flex;
  flex-wrap: wrap;
}
.nav-pills .nav-link {
  border-radius: 999px;
  color: var(--n-600);
  font-weight: 550;
  font-size: var(--text-sm);
  padding: 0.35rem 0.95rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.nav-pills .nav-link:hover { color: var(--n-900); }
.nav-pills .nav-link.active {
  background: var(--agry-surface);
  color: var(--g-800);
  box-shadow: var(--shadow-sm);
}

/* ---------- Auth pages (login/register/forgot password) ---------- */
.auth-body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(50rem 30rem at 15% 0%, rgba(28, 102, 66, 0.12), transparent 60%),
    radial-gradient(40rem 24rem at 100% 100%, rgba(217, 154, 43, 0.10), transparent 55%),
    linear-gradient(180deg, var(--g-50), var(--n-50));
  padding: 1.5rem;
}
.auth-shell { width: 100%; max-width: 440px; }
.auth-shell.wide { max-width: 660px; }
.auth-shell.wide .auth-card { padding: 2.25rem 2.5rem; }
.auth-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  margin-bottom: 1.5rem;
  font-weight: 700;
  font-size: 1.35rem;
  letter-spacing: -0.02em;
  color: var(--g-800);
}
.auth-brand svg {
  background: linear-gradient(160deg, var(--g-600), var(--g-800));
  border-radius: 0.65rem;
  padding: 6px;
  color: #fff;
  box-shadow: var(--shadow-md);
}
.auth-card {
  background: var(--agry-surface);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--agry-border);
  padding: 2.25rem 2rem;
}
.auth-card > h1:first-child {
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 1.5rem;
}
.auth-card h2, .auth-card h3 { display: none; }
.auth-card hr { display: none; }
.auth-card .row { margin: 0; }
.auth-card .row > [class*="col-"] { padding: 0; width: 100%; max-width: 100%; flex: 0 0 100%; }
.auth-card .col-lg-4.col-lg-offset-2 { display: none; } /* no external auth providers configured */
.auth-card .form-floating > label { color: var(--agry-text-muted); }
.auth-card .form-floating > .form-control { min-height: 3.5rem; }
.auth-card .checkbox { margin-bottom: 1.1rem; }
.auth-card .checkbox label { display: flex; align-items: center; gap: 0.5rem; font-weight: 500; cursor: pointer; margin: 0; }
.auth-card .checkbox .form-check-input { margin: 0; }
.auth-card button[type="submit"] { margin-top: 0.25rem; }
.auth-card #account > div:last-of-type {
  margin-top: 1.25rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--n-100);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.auth-card #account > div:last-of-type p { margin: 0; font-size: 0.85rem; }
.auth-footer { text-align: center; margin-top: 1.5rem; font-size: 0.78rem; color: var(--agry-text-muted); }

/* Self-registration is disabled (accounts come from the setup wizard); hide the default Identity
   UI's register links rather than scaffolding the whole page just to remove one line. */
.auth-card a[href*="/Account/Register"] { display: none; }

@media (max-width: 480px) {
  .auth-card { padding: 1.75rem 1.35rem; }
}

/* ---------- Setup wizard step indicator ---------- */
.wizard-steps {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.75rem;
}
.wizard-step {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.wizard-step-circle {
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.82rem;
  background: var(--n-100);
  color: var(--n-500);
  border: 2px solid var(--n-200);
  flex-shrink: 0;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.wizard-step-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--n-500);
  white-space: nowrap;
}
.wizard-step.done .wizard-step-circle { background: var(--g-600); border-color: var(--g-600); color: #fff; }
.wizard-step.done .wizard-step-label { color: var(--g-700); }
.wizard-step.active .wizard-step-circle { background: var(--agry-surface); border-color: var(--g-600); color: var(--g-600); box-shadow: 0 0 0 3px var(--g-100); }
.wizard-step.active .wizard-step-label { color: var(--n-900); }
.wizard-step-line {
  width: 2.25rem;
  height: 2px;
  background: var(--n-200);
  margin: 0 0.5rem;
  flex-shrink: 0;
}
.wizard-step-line.done { background: var(--g-600); }

@media (max-width: 480px) {
  .wizard-step-label { display: none; }
  .wizard-step-line { width: 1.25rem; }
}

/* ==========================================================================
   Interactive guide engine (agry-guide.js)
   Spotlight tour: dimmed overlay + highlighted target + step tooltip.
   ========================================================================== */
.agry-guide-overlay {
  position: fixed;
  inset: 0;
  background: rgba(6, 20, 13, 0.55);
  backdrop-filter: blur(1.5px);
  -webkit-backdrop-filter: blur(1.5px);
  z-index: 10000;
  animation: guide-fade 0.18s ease;
}
@keyframes guide-fade { from { opacity: 0; } to { opacity: 1; } }

/* The element being explained is lifted above the overlay and ringed. */
.agry-guide-target {
  position: relative;
  z-index: 10001 !important;
  border-radius: var(--radius-sm);
  box-shadow:
    0 0 0 3px var(--a-400),
    0 0 0 7px rgba(236, 182, 77, 0.28),
    0 12px 32px -8px rgba(0, 0, 0, 0.45);
  animation: guide-pulse 1.8s ease-in-out infinite;
}
@keyframes guide-pulse {
  0%, 100% { box-shadow: 0 0 0 3px var(--a-400), 0 0 0 7px rgba(236, 182, 77, 0.28), 0 12px 32px -8px rgba(0, 0, 0, 0.45); }
  50% { box-shadow: 0 0 0 3px var(--a-400), 0 0 0 11px rgba(236, 182, 77, 0.14), 0 12px 32px -8px rgba(0, 0, 0, 0.45); }
}

.agry-guide-tooltip {
  position: fixed;
  z-index: 10002;
  width: min(350px, calc(100vw - 2rem));
  background: var(--agry-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(18, 26, 21, 0.04);
  padding: 1.1rem 1.2rem 0.95rem;
  animation: guide-tip-in 0.2s ease;
}
@keyframes guide-tip-in { from { opacity: 0; transform: translateY(6px) scale(0.98); } to { opacity: 1; transform: none; } }

.agry-guide-step-label {
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--a-600);
  margin-bottom: 0.3rem;
}
.agry-guide-title {
  font-weight: 700;
  font-size: 1.02rem;
  letter-spacing: -0.015em;
  color: var(--n-900);
  margin-bottom: 0.4rem;
  padding-right: 1.5rem;
}
.agry-guide-body {
  font-size: var(--text-sm);
  color: var(--n-700);
  line-height: 1.55;
}
.agry-guide-body ul { padding-left: 1.1rem; margin: 0.4rem 0 0; }
.agry-guide-body li + li { margin-top: 0.2rem; }
.agry-guide-body code {
  background: var(--n-100);
  border-radius: 0.3rem;
  padding: 0.05rem 0.35rem;
  font-size: 0.82em;
  color: var(--g-800);
}
.agry-guide-footer {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.95rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--n-100);
}
.agry-guide-dots { display: flex; gap: 0.3rem; flex: 1; }
.agry-guide-dots .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--n-200);
  transition: background-color 0.15s ease, transform 0.15s ease;
}
.agry-guide-dots .dot.active { background: var(--g-600); transform: scale(1.25); }
.agry-guide-dots .dot.done { background: var(--g-300); }
.agry-guide-skip {
  border: none;
  background: none;
  color: var(--n-400);
  font-size: var(--text-xs);
  font-weight: 550;
  padding: 0.25rem 0.4rem;
}
.agry-guide-skip:hover { color: var(--n-700); }
.agry-guide-close {
  position: absolute;
  top: 0.65rem;
  right: 0.65rem;
  width: 1.6rem;
  height: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--n-400);
  font-size: 1rem;
  line-height: 1;
}
.agry-guide-close:hover { background: var(--n-100); color: var(--n-700); }
.agry-guide-audio-toggle {
  position: absolute;
  top: 0.65rem;
  right: 2.5rem;
  width: 1.6rem;
  height: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--n-400);
  transition: all 0.15s ease;
  cursor: pointer;
}
.agry-guide-audio-toggle:hover { background: var(--n-100); color: var(--n-700); }
.agry-guide-audio-toggle.is-enabled {
  color: var(--g-600);
  background: rgba(34, 197, 94, 0.1);
}
.agry-guide-audio-toggle.is-enabled:hover {
  background: rgba(34, 197, 94, 0.2);
  color: var(--g-800);
}
.agry-guide-audio-toggle.is-playing {
  animation: guide-audio-pulse 1.2s ease-in-out infinite;
}
@keyframes guide-audio-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.3); }
  50% { transform: scale(1.08); box-shadow: 0 0 0 4px rgba(34, 197, 94, 0); }
}
.agry-guide-nav { display: flex; gap: 0.4rem; }
.agry-guide-nav .btn { min-height: 2rem; font-size: var(--text-sm); padding: 0.2rem 0.8rem; }

/* First-visit prompt toast (bottom-right): offers the page tour once per page. */
.agry-guide-prompt {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 9990;
  width: min(340px, calc(100vw - 2.5rem));
  background: var(--agry-surface);
  border: 1px solid var(--n-200);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 1rem 1.15rem;
  display: flex;
  gap: 0.8rem;
  align-items: flex-start;
  animation: guide-prompt-in 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
@keyframes guide-prompt-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.agry-guide-prompt-icon {
  width: 2.3rem;
  height: 2.3rem;
  flex-shrink: 0;
  border-radius: var(--radius-md);
  background: linear-gradient(160deg, var(--g-100), var(--g-50));
  border: 1px solid var(--g-100);
  color: var(--g-700);
  display: flex;
  align-items: center;
  justify-content: center;
}
.agry-guide-prompt-title { font-weight: 650; font-size: 0.92rem; color: var(--n-900); margin-bottom: 0.15rem; }
.agry-guide-prompt-text { font-size: var(--text-xs); color: var(--n-500); line-height: 1.5; margin-bottom: 0.55rem; }
.agry-guide-prompt-actions { display: flex; gap: 0.45rem; }
.agry-guide-prompt-actions .btn { min-height: 1.9rem; font-size: var(--text-xs); padding: 0.15rem 0.7rem; }

/* ---------- Skeleton shimmer (loading placeholders) ---------- */
.skeleton {
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--n-100) 25%, var(--n-50) 50%, var(--n-100) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s linear infinite;
}
@keyframes skeleton-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ---------- Print ---------- */
@media print {
  .sidebar, .topbar, .guide-launch, .agry-guide-overlay, .agry-guide-tooltip, .agry-guide-prompt, .btn, .help-icon { display: none !important; }
  .app-main { margin-left: 0; }
  .content { padding: 0; max-width: none; animation: none; background: none; }
  .agry-card, .stat-tile { box-shadow: none; border-color: var(--n-300); }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Customisable dashboard grid (agry-dashboard.js) ---------- */
.dash-item { position: relative; transition: width 0.25s ease; }

/* Customise mode: dashed outlines hint that the cards are movable. */
#dashboard-grid.dash-customize .dash-item {
  outline: 1.5px dashed var(--n-300);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* Overlay control bar, top-right of each card — only shown while customising. */
.dash-item-tools { display: none; }
#dashboard-grid.dash-customize .dash-item-tools {
  position: absolute;
  top: 0.45rem;
  right: 1.1rem; /* clears the column gutter padding */
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 0.15rem;
  padding: 0.2rem;
  background: var(--agry-surface);
  border: 1px solid var(--n-200);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}
.dash-item-tools .btn-icon { width: 1.7rem; height: 1.7rem; }
.dash-item-tools .dash-size-btn { width: auto; min-width: 2.1rem; padding: 0 0.3rem; font-size: var(--text-xs); font-weight: 650; }
.dash-item-tools .dash-drag-handle { cursor: grab; }
.dash-item-tools .dash-drag-handle:active { cursor: grabbing; }

/* Drag ghost and insertion indicator. */
.dash-item.dash-dragging { opacity: 0.5; }
#dashboard-grid.dash-customize .dash-item.dash-drop-before,
#dashboard-grid.dash-customize .dash-item.dash-drop-after {
  outline: 2px solid var(--a-500);
  outline-offset: 3px;
}
#dashboard-grid.dash-customize .dash-item.dash-drop-before { box-shadow: inset 3px 0 0 var(--a-500); }
#dashboard-grid.dash-customize .dash-item.dash-drop-after { box-shadow: inset -3px 0 0 var(--a-500); }

@media print {
  .dash-item-tools, #dash-customize-btn, #dash-reset-btn { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .dash-item { transition: none; }
}

/* Plaintext (non-HTTPS, non-loopback) connection warning banner - see
   _PlaintextConnectionWarning.cshtml. */
.plaintext-warning {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 1rem;
  background: var(--warning-100);
  color: var(--warning-600);
  font-size: 0.85rem;
  border-bottom: 1px solid var(--warning-600);
}
.plaintext-warning .alert-link { color: inherit; text-decoration: underline; font-weight: 600; }
.plaintext-warning-close {
  margin-left: auto;
  background: none;
  border: none;
  font-size: 1.2rem;
  line-height: 1;
  color: inherit;
  cursor: pointer;
  padding: 0 0.25rem;
}

/* ==========================================================================
   Dark theme
   Night use on a farm is normal - lambing checks, late paperwork, a phone in
   the yard after dark - so this is a real first-class theme, not a filter.

   Implemented by re-pointing the design tokens rather than restyling
   components: every rule above already reads --agry-* or the --n-* neutral
   scale, so inverting those flips the whole app. Bootstrap 5.3 brings its own
   [data-bs-theme=dark] palette along for the ride, which is why the attribute
   is data-bs-theme rather than a bespoke one.
   ========================================================================== */
[data-bs-theme="dark"] {
  /* Neutral scale inverted. 900 stays "the strongest text colour" and 50 stays
     "the faintest background", so existing rules keep meaning what they meant.
     Kept slightly green-warm rather than pure grey to match the brand. */
  --n-900: #eef2ef;
  --n-800: #dde3df;
  --n-700: #c3ccc6;
  --n-600: #a4aea8;
  --n-500: #8d968f;
  --n-400: #6e7871;
  --n-300: #3c443f;
  --n-200: #2c332f;
  --n-100: #242a27;
  --n-50:  #1c211e;

  /* Greens lifted: the 600-700 range is rich on paper but muddy on a dark
     background, so text-weight greens move up the scale while solid buttons
     keep enough depth to carry white text. */
  --g-900: #d9ecdf;
  --g-800: #bcdcc7;
  --g-700: #93c9a8;
  --g-600: #2f8d5c;
  --g-500: #35a06a;
  --g-400: #55b381;
  --g-300: #7cc79c;
  --g-200: #2a4d39;
  --g-100: #1e3a2a;
  --g-50:  #172c20;

  /* Amber: same idea - readable highlight tones, muted fills. */
  --a-700: #f0c274;
  --a-600: #e3a84a;
  --a-500: #d99a2b;
  --a-400: #b8801f;
  --a-200: #4a3818;
  --a-100: #33280f;
  --a-50:  #2a2110;

  /* Semantic pairs: the 100s become dark tints (a pale wash would glare), the
     600s become the readable foreground on top of them. */
  --success-600: #5fbd85;
  --success-100: #16301f;
  --warning-600: #e0a53f;
  --warning-100: #33260f;
  --danger-600:  #ea7b68;
  --danger-100:  #3a1c17;
  --info-600:    #74b4d3;
  --info-100:    #17303c;

  --agry-bg: #131715;
  --agry-surface: #1c211e;
  --agry-border: #2e352f;
  --agry-text: #e8eee9;
  /* 7.15:1 on the dark surface (the old #98a29b measured 6.20:1). Light-on-dark reads bolder
     than dark-on-light at the same ratio, so this sits a step lighter than the light theme's
     muted token and still lands AAA. */
  --agry-text-muted: var(--n-600);
  --agry-primary: #35a06a;
  --agry-primary-dark: #7cc79c;

  /* Shadows need to be near-black to read at all against a dark surface. */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35), 0 2px 6px -1px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 2px 4px -1px rgba(0, 0, 0, 0.4), 0 10px 24px -6px rgba(0, 0, 0, 0.55);
  --shadow-lg: 0 4px 8px -2px rgba(0, 0, 0, 0.45), 0 24px 48px -12px rgba(0, 0, 0, 0.7);

  --bs-primary-rgb: 53, 160, 106;
}

/* The glossy top highlight on cards reads as a bright seam on dark - keep the
   lift, drop the shine. */
[data-bs-theme="dark"] .agry-card,
[data-bs-theme="dark"] .stat-tile {
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

/* Frosted topbar: same effect, dark base. */
[data-bs-theme="dark"] .topbar { background: rgba(28, 33, 30, 0.88); }

/* Bootstrap deliberately keeps "light" light in dark mode (it's a fixed colour
   name, not a role), but these are used across the app as neutral surfaces -
   left alone they punch bright holes in every page. */
[data-bs-theme="dark"] .bg-light,
[data-bs-theme="dark"] .bg-white { background-color: var(--n-100) !important; }
[data-bs-theme="dark"] .text-bg-light { background-color: var(--n-100) !important; color: var(--n-800) !important; }
[data-bs-theme="dark"] .text-dark { color: var(--n-800) !important; }
[data-bs-theme="dark"] .table-light > * { --bs-table-bg: var(--n-100); --bs-table-color: var(--n-800); }
[data-bs-theme="dark"] .border { border-color: var(--agry-border) !important; }

/* Ctrl+K search results. The rows are built in JS, so they get a class rather than an inline
   colour - a hardcoded surface here is invisible to the theme and was rendering pale text on a
   pale row in dark mode. Both the surface and the text come off the neutral scale, which flips. */
.agry-search-result {
  background: var(--n-100);
  color: var(--n-900);
}
.agry-search-result:hover,
.agry-search-result:focus {
  background: var(--n-200);
  color: var(--n-900);
}
.agry-search-result .agry-search-title { color: var(--n-900); font-weight: 600; }
/* --n-600 not --n-500: the subtitle is small text and needs 4.5:1 against the row in both
   themes. The 500 step measured 4.21:1 in light mode, which fails. */
.agry-search-result .agry-search-sub { color: var(--n-600); }

/* Contextual table rows: Bootstrap's tints assume dark text on a pale wash. */
[data-bs-theme="dark"] .table-danger > *  { --bs-table-bg: var(--danger-100);  --bs-table-color: var(--danger-600); }
[data-bs-theme="dark"] .table-warning > * { --bs-table-bg: var(--warning-100); --bs-table-color: var(--warning-600); }
[data-bs-theme="dark"] .table-success > * { --bs-table-bg: var(--success-100); --bs-table-color: var(--success-600); }

/* Alerts carry hardcoded light-mode borders/text in the light theme above. */
[data-bs-theme="dark"] .alert-danger { color: var(--danger-600); border-color: #5c2b23; }
[data-bs-theme="dark"] .alert-info   { border-color: #234a5c; }

/* Inputs: dark field, and the focus state must not flash back to white. */
[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select {
  background-color: var(--n-100);
  border-color: var(--agry-border);
  color: var(--agry-text);
}
[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-select:focus { background-color: var(--n-100); }
[data-bs-theme="dark"] .form-control::placeholder { color: var(--n-400); }
/* ...but not in a floating-label field, where Bootstrap deliberately keeps the placeholder
   transparent because the label itself sits over it until it floats. That rule
   (.form-floating > .form-control::placeholder) has the same specificity as the dark one
   above, so the later of the two wins - ours, printing "Email" on top of "name@example.com".
   Restated here, after, so floating fields stay transparent in dark mode too. */
.form-floating > .form-control::placeholder { color: transparent; }

/* Leaflet ships a white attribution strip and light controls. */
/* Hybrid satellite: OpenStreetMap's road rendering composited onto the aerial imagery beneath
   it, rather than laid over it as a sheet. Multiply keeps OSM's near-white background
   effectively invisible while road casings and label text (both dark) come through, so you get
   road lines and names without losing the photograph. Paired with agry-map.js's `satellite`
   layer group - the class is applied to that tile layer's container. */
.agry-hybrid-roads { mix-blend-mode: multiply; }

[data-bs-theme="dark"] .leaflet-control-attribution,
[data-bs-theme="dark"] .leaflet-bar a {
  background: var(--n-100) !important;
  color: var(--n-700) !important;
}

/* Printing is always on white paper, whatever the screen is set to. */
@media print {
  [data-bs-theme="dark"] {
    --agry-bg: #ffffff;
    --agry-surface: #ffffff;
    --agry-text: #181c1a;
    --n-900: #181c1a; --n-800: #272c29; --n-700: #3d4340; --n-600: #59605b;
    --n-500: #6e756f; --n-400: #98a09a; --n-300: #d3d8d4; --n-200: #e5e8e5;
    --n-100: #f0f2f0; --n-50: #f7f8f7;
  }
}

/* Theme toggle button in the topbar. Only one of the two icons is ever shown. */
.theme-toggle { display: inline-flex; align-items: center; justify-content: center; }
.theme-toggle .theme-icon-dark { display: none; }
[data-bs-theme="dark"] .theme-toggle .theme-icon-light { display: none; }
[data-bs-theme="dark"] .theme-toggle .theme-icon-dark { display: inline-flex; }

/* --------------------------------------------------------------------------
   Dark theme: brand chrome
   The green scale above is inverted in dark mode because most of it is used
   for tints and text. But a handful of surfaces are solid brand chrome that
   carries white text - the sidebar, the auth mark, the chat launcher. Those
   have to STAY dark or the white text sits on pale green and disappears.
   They're pinned to literals here rather than scale tokens for that reason.
   -------------------------------------------------------------------------- */
[data-bs-theme="dark"] .sidebar {
  background:
    radial-gradient(120% 60% at 0% 0%, rgba(122, 184, 148, 0.10), transparent 55%),
    radial-gradient(90% 45% at 100% 100%, rgba(236, 182, 77, 0.05), transparent 60%),
    linear-gradient(185deg, #10402a 0%, #0a2f1e 55%, #051a11 100%);
}
[data-bs-theme="dark"] .auth-brand svg { background: linear-gradient(160deg, #1c6642, #10402a); }

/* Guide-prompt toggle: mirrors the theme toggle - one icon at a time, keyed off a class the
   button sets from the stored preference. */
.guide-prompt-toggle .gp-off { display: none; }
.guide-prompt-toggle.prompts-off .gp-on { display: none; }
.guide-prompt-toggle.prompts-off .gp-off { display: inline-flex; }
.guide-prompt-toggle.prompts-off { opacity: 0.6; }

/* ---------------------------------------------------------------------------
   Sign-up: choosing hosted or local, and the product key that follows.

   The deployment choice is rendered as two large cards rather than a dropdown
   because it is the one decision on the form a customer cannot change later by
   editing a field, and because it is answered by a fact about their farm - the
   connection in the shed - rather than a preference. It deserves the room.
   --------------------------------------------------------------------------- */

.deploy-choice { display: grid; gap: 0.75rem; }
@media (min-width: 576px) { .deploy-choice { grid-template-columns: 1fr 1fr; } }

/* Visually hidden, not display:none - the radio stays focusable and reachable by
   keyboard and screen reader, and the card is its label. */
.deploy-radio {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.deploy-card {
    display: flex; flex-direction: column; gap: 0.35rem;
    /* Generous target: this gets tapped on a phone, often outdoors. */
    padding: 1rem;
    border: 2px solid var(--agry-border, #d4d8d2);
    border-radius: 0.6rem;
    cursor: pointer;
    background: var(--agry-surface, #fff);
    transition: border-color 0.12s ease, background-color 0.12s ease;
}

.deploy-card:hover { border-color: var(--agry-accent, #2f7d4f); }

.deploy-radio:checked + .deploy-card {
    border-color: var(--agry-accent, #2f7d4f);
    background: var(--agry-accent-soft, #eef6f0);
}

/* Focus must be visible on the CARD, since the input itself is off-screen -
   without this a keyboard user tabs into nothing they can see. */
.deploy-radio:focus-visible + .deploy-card {
    outline: 3px solid var(--agry-accent, #2f7d4f);
    outline-offset: 2px;
}

.deploy-title { font-weight: 600; }
.deploy-body { font-size: 0.875rem; color: var(--agry-muted, #5b6459); line-height: 1.4; }

/* The key is copied by hand onto paper as often as it is copied to a clipboard,
   so it is set large, monospaced and letter-spaced: 0/O and 1/I have to be
   distinguishable at arm's length under a work light. */
.licence-key {
    font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
    font-size: 1.35rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    word-break: break-all;
    margin: 0;
}

.setup-steps { padding-left: 1.25rem; }
.setup-steps li { margin-bottom: 1rem; }
.setup-steps li::marker { font-weight: 600; color: var(--agry-accent, #2f7d4f); }
