/* ==========================================================================
 HM Agri One €” design system
   Light + dark, Devanagari-safe type, dense data tables.
   ========================================================================== */

:root {
  color-scheme: light;

  --brand-50:  #ecfdf3;
  --brand-100: #d1fadf;
  --brand-200: #a6f4c5;
  --brand-500: #16a34a;
  --brand-600: #12894a;
  --brand-700: #0f6f3d;
  --brand-900: #08361e;

  --amber-50:  #fffbeb;
  --amber-100: #fef3c7;
  --amber-500: #d97706;
  --amber-600: #b45309;

  /* Khatabook convention: red = money we will GET, green = money we will GIVE */
  --get-50:  #fef2f2;
  --get-100: #fee2e2;
  --get:     #dc2626;
  --get-700: #b91c1c;
  --give-50: #ecfdf5;
  --give-100:#d1fae5;
  --give:    #059669;
  --give-700:#047857;

  --bg:        #f4f6f5;
  --surface:   #ffffff;
  --surface-2: #f8faf9;
  --surface-3: #eef2f0;
  --border:    #dfe5e2;
  --border-2:  #c9d3ce;

  --text:      #14201a;
  --text-2:    #4a5a52;
  --text-3:    #7b8a83;
  --on-brand:  #ffffff;

  --shadow-sm: 0 1px 2px rgba(16, 34, 24, .06);
  --shadow:    0 1px 3px rgba(16, 34, 24, .08), 0 4px 12px rgba(16, 34, 24, .05);
  --shadow-lg: 0 8px 28px rgba(16, 34, 24, .14);

  --r-sm: 8px;
  --r:    13px;
  --r-lg: 18px;
  /* A light tint that rings every card, so edges read softly rather than hard. */
  --ring: 0 0 0 1px rgba(22, 163, 74, .05);
  --sheen: inset 0 1px 0 rgba(255, 255, 255, .75);

  --sidebar-w: 252px;
  --topbar-h: 64px;

  /* Photo overlays share one deep moringa-green so text on them always reads. */
  --scrim: 6, 34, 20;
  --glass: rgba(255, 255, 255, .86);
  --glass-strong: rgba(255, 255, 255, .96);
  --glass-border: rgba(255, 255, 255, .7);

  --font: 'Segoe UI', 'Nirmala UI', system-ui, -apple-system, 'Noto Sans', 'Noto Sans Devanagari', Arial, sans-serif;
  --mono: 'Cascadia Mono', Consolas, 'SF Mono', Menlo, monospace;
}

html[data-theme='dark'] {
  color-scheme: dark;
  --brand-50:  #0d2a1a;
  --brand-100: #123b25;
  --brand-200: #175030;
  --brand-500: #34d07f;
  --brand-600: #22b96b;
  --brand-700: #1a9c58;
  --brand-900: #c8f5dc;

  --amber-50:  #2c2208;
  --amber-100: #3d300c;
  --amber-500: #fbbf24;
  --amber-600: #f59e0b;

  --get-50:  #3a1616;
  --get-100: #4d1d1d;
  --get:     #f87171;
  --get-700: #fca5a5;
  --give-50: #0d2b22;
  --give-100:#113a2e;
  --give:    #34d399;
  --give-700:#6ee7b7;

  --bg:        #0e1512;
  --surface:   #151d19;
  --surface-2: #1a231e;
  --surface-3: #212c26;
  --border:    #2a3630;
  --border-2:  #3a4842;

  --text:      #e8efeb;
  --text-2:    #a8b8b0;
  --text-3:    #7d8d85;
  --on-brand:  #07130c;

  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --shadow:    0 1px 3px rgba(0,0,0,.5), 0 4px 12px rgba(0,0,0,.35);
  --shadow-lg: 0 8px 28px rgba(0,0,0,.6);
  --ring: 0 0 0 1px rgba(255, 255, 255, .04);
  --sheen: inset 0 1px 0 rgba(255, 255, 255, .04);

  --glass: rgba(21, 29, 25, .84);
  --glass-strong: rgba(21, 29, 25, .93);
  --glass-border: rgba(255, 255, 255, .08);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; line-height: 1.25; letter-spacing: -.01em; }
h1 { font-size: 22px; }
h2 { font-size: 17px; }
h3 { font-size: 15px; }
p  { margin: 0 0 10px; }
a  { color: var(--brand-600); text-decoration: none; }
a:hover { text-decoration: underline; }

.num { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--mono); }

/* ---------------------------------------------------------------- app shell */

#app { min-height: 100vh; }

.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  /* A faint wash rather than flat white: it separates the sidebar from the
     page without needing a heavy rule down the side. */
  background: linear-gradient(180deg, #f6fbf8 0%, var(--surface) 220px);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 40;
  transition: transform .18s ease;
}
html[data-theme='dark'] .sidebar {
  background: linear-gradient(180deg, #141d18 0%, var(--surface) 220px);
}

.sidebar-brand {
  display: flex; align-items: center; gap: 11px;
  padding: 14px 16px;
  min-height: var(--topbar-h);
  /* No hard rule under the brand: the sidebar reads as one surface, and the
     nav below it is separated by space instead of a line. */
  flex: 0 0 auto;
}
.sidebar-brand .logo {
  width: 38px; height: 38px; flex: 0 0 38px;
  object-fit: contain;          /* the emblem is taller than it is wide */
}
.sidebar-brand .bt { font-weight: 700; font-size: 15.5px; letter-spacing: -.015em; }
.sidebar-brand .bs { font-size: 11px; color: var(--text-3); margin-top: 0; }

/*
 * The nav scrolls only when it has to, and its bar stays out of the way €”
 * a permanent scrollbar down a sidebar of ten items is noise, and it steals
 * width from the labels.
 */
.nav {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 6px 12px 20px;
  scrollbar-width: thin;
  scrollbar-color: var(--border-2) transparent;
}
.nav::-webkit-scrollbar { width: 6px; }
.nav::-webkit-scrollbar-track { background: transparent; }
.nav::-webkit-scrollbar-thumb { background: transparent; border-radius: 3px; }
.sidebar:hover .nav::-webkit-scrollbar-thumb { background: var(--border-2); }
.nav-group { margin-top: 18px; }
.nav-group:first-child { margin-top: 2px; }
.nav-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-3); padding: 0 12px 7px;
}

/*
 * Registration is one button that opens a list. Everything that brings a new
 * person into the system lives behind it, so the sidebar stays short and that
 * one job reads as one thing instead of five loose links.
 */
.nav-group.is-collapsible {
  margin-top: 18px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-2);
  padding: 5px;
  box-shadow: var(--sheen);
}

.nav-toggle {
  width: 100%;
  font-weight: 650;
  color: var(--text);
  cursor: pointer;
}
.nav-toggle:hover { background: var(--surface); }
.nav-toggle .badge { margin-left: auto; }
/* The chevron points right when closed, down when open. */
.nav-chev {
  margin-left: auto;
  display: inline-flex;
  transition: transform .18s ease;
  color: var(--text-3);
}
.nav-toggle .badge + .nav-chev { margin-left: 6px; }
.nav-group.is-open .nav-chev { transform: rotate(90deg); }

/* Closed by default; the open state sets a height generous enough for the list. */
.nav-sub {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .2s ease;
}
/* While closed the rows must be unreachable, not merely clipped €” otherwise Tab
   and screen readers still land on links nobody can see. The delay lets the
   closing animation finish before they disappear. */
.nav-sub > .nav-sub-inner {
  overflow: hidden;
  min-height: 0;
  visibility: hidden;
  transition: visibility 0s linear .2s;
}
.nav-group.is-open .nav-sub { grid-template-rows: 1fr; }
.nav-group.is-open .nav-sub-inner {
  visibility: visible;
  transition-delay: 0s;
}
/* Breathing room under the last row, only while open. */
.nav-group.is-open .nav-sub-inner { padding-bottom: 2px; }
/* Rows inside sit slightly indented, so the grouping reads at a glance. */
.nav-sub .nav-item { padding-left: 18px; }
.nav-sub .nav-item:hover { background: var(--surface); }
.nav-sub .nav-item.active { background: var(--brand-100); }
html[data-theme='dark'] .nav-sub .nav-item.active { background: var(--brand-50); }

/* Older browsers without grid-row animation still get a working toggle. */
@supports not (grid-template-rows: 1fr) {
  .nav-sub { display: none; }
  .nav-group.is-open .nav-sub { display: block; }
}
.nav-item {
  display: flex; align-items: center; gap: 12px;
  /* Roomier rows and a softer corner: the sidebar is read down the page, and
     tight rows make a long list hard to scan. */
  padding: 10px 12px; border-radius: 11px;
  color: var(--text-2); font-weight: 500; cursor: pointer;
  border: none; background: none; width: 100%; text-align: left;
  font-family: inherit; font-size: 13.5px;
  transition: background .13s ease, color .13s ease;
}
.nav-item:hover { background: var(--surface-3); color: var(--text); text-decoration: none; }
.nav-item.active {
  background: var(--brand-50);
  color: var(--brand-700);
  font-weight: 650;
}
html[data-theme='dark'] .nav-item.active { color: var(--brand-500); }
.nav-item .ico { width: 18px; height: 18px; flex: 0 0 18px; opacity: .85; }
.nav-item.active .ico { opacity: 1; }
.nav-item .badge { margin-left: auto; }

.sidebar-foot {
  padding: 12px;
  border-top: 1px solid var(--border);
  flex: 0 0 auto;
  background: var(--surface);
}

.main {
  flex: 1 1 auto;
  margin-left: var(--sidebar-w);
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.topbar {
  height: var(--topbar-h);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 12px;
  padding: 0 18px;
  position: sticky; top: 0; z-index: 30;
}
.topbar .spacer { flex: 1 1 auto; }
.hamburger { display: none; }

/*
 * Wider than before: on a 1920 screen the old 1500px cap left a broad empty
 * band down the right, while tables and the wider forms had room to spare.
 * Still capped, because a line of text running the full width of a large
 * monitor is hard to read.
 */
.page { padding: 22px 26px; max-width: 1680px; width: 100%; }
.page-head {
  display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 18px;
}
.page-head .ph-text { flex: 1 1 260px; min-width: 0; }
.page-head .sub { color: var(--text-3); font-size: 13px; margin-top: 3px; }
.page-head .ph-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------------------------------------------------------------- controls */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 8px 14px; border-radius: var(--r-sm);
  border: 1px solid var(--border-2); background: var(--surface); color: var(--text);
  font: inherit; font-size: 13.5px; font-weight: 550; cursor: pointer;
  white-space: nowrap; transition: background .12s, border-color .12s;
}
.btn:hover:not(:disabled) { background: var(--surface-3); text-decoration: none; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn:focus-visible, .input:focus-visible, .nav-item:focus-visible {
  outline: 2px solid var(--brand-500); outline-offset: 1px;
}
.btn-primary {
  background: var(--brand-600); border-color: var(--brand-600); color: var(--on-brand);
}
.btn-primary:hover:not(:disabled) { background: var(--brand-700); border-color: var(--brand-700); }
.btn-get { background: var(--get); border-color: var(--get); color: #fff; }
.btn-get:hover:not(:disabled) { background: var(--get-700); border-color: var(--get-700); }
.btn-give { background: var(--give); border-color: var(--give); color: #fff; }
.btn-give:hover:not(:disabled) { background: var(--give-700); border-color: var(--give-700); }
.btn-ghost { border-color: transparent; background: transparent; }
.btn-ghost:hover:not(:disabled) { background: var(--surface-3); }
.btn-danger { color: var(--get); border-color: var(--border-2); }
.btn-danger:hover:not(:disabled) { background: var(--get-50); border-color: var(--get); }
.btn-sm { padding: 5px 10px; font-size: 12.5px; }
.btn-icon { padding: 7px; }
.btn-block { width: 100%; }

.input, .select, .textarea {
  width: 100%; padding: 8px 11px;
  border: 1px solid var(--border-2); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text);
  font: inherit; font-size: 13.5px;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50);
}
.input::placeholder { color: var(--text-3); }
.textarea { min-height: 76px; resize: vertical; }
.select {
  appearance: none; padding-right: 30px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%237b8a83'%3E%3Cpath d='M4.5 6.5 8 10l3.5-3.5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center; background-size: 16px;
}
.input[type='date'] { min-height: 35px; }

.field { margin-bottom: 13px; }
.field > label {
  display: block; font-size: 12.5px; font-weight: 600; color: var(--text-2); margin-bottom: 5px;
}
.field .hint { font-size: 11.5px; color: var(--text-3); margin-top: 4px; }
.field .err { font-size: 12px; color: var(--get); margin-top: 4px; }
.field.invalid .input, .field.invalid .select { border-color: var(--get); }
.req::after { content: ' *'; color: var(--get); }

.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; }
.form-grid .span-2 { grid-column: 1 / -1; }
.form-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 14px; }

/*
 * Photo beside the details on a desktop; photo above them on a phone.
 *
 * Side by side, a 400px-wide screen leaves the fields around 180px €” too
 * narrow for a 10-digit mobile number or an Aadhaar, which then get clipped.
 * Stacking gives the fields the full width, which is what they need most.
 */
.photo-split {
  display: grid;
  grid-template-columns: minmax(0, 200px) minmax(0, 1fr);
  gap: 18px;
  /* stretch, not start: the photo panel then runs the full height of the
     fields beside it, as one block rather than a card that stops short. */
  align-items: stretch;
}

/* ==========================================================================
   Form sections
   Long forms read as one wall of boxes. Grouping related fields on their own
   tinted panel, each with a coloured mark, lets someone find "the money part"
   or "where they are posted" at a glance instead of reading every label.
   The tints are drawn from the palette so dark mode follows for free.
   ========================================================================== */

.f-sec {
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 14px 15px 3px;
  margin-bottom: 12px;
  background: var(--surface-2);
}
.f-sec-head {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 12px;
}
.f-sec-head .t { font-weight: 650; font-size: 14.5px; letter-spacing: -.01em; }
.f-sec-head .s { font-size: 12px; color: var(--text-3); margin-top: -1px; }

/* The round mark that carries each section's colour. */
.f-mark {
  width: 34px; height: 34px; flex: 0 0 34px;
  border-radius: 10px;
  display: grid; place-items: center;
  background: var(--brand-50); color: var(--brand-700);
  box-shadow: var(--ring);
}
html[data-theme='dark'] .f-mark { color: var(--brand-500); }

/* Section colours. Each is a tint of an existing token, never a new hex. */
.f-sec.tone-brand  { background: color-mix(in srgb, var(--brand-50) 55%, var(--surface)); }
.f-sec.tone-amber  { background: color-mix(in srgb, var(--amber-50) 55%, var(--surface)); }
.f-sec.tone-plain  { background: var(--surface-2); }

.f-mark.tone-amber { background: var(--amber-50); color: var(--amber-600); }
.f-mark.tone-give  { background: var(--give-50);  color: var(--give-700); }

/* Browsers without color-mix fall back to the flat surface, which still reads. */
@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .f-sec.tone-brand, .f-sec.tone-amber { background: var(--surface-2); }
}

/* ---- fields with a mark inside ---- */

.field-ico { position: relative; }
.field-ico > svg {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  color: var(--text-3); pointer-events: none;
}
.field-ico .input,
.field-ico .select { padding-left: 34px; }
/* The field turns brand-coloured while it is being filled in. */
.field-ico:focus-within > svg { color: var(--brand-600); }

/* ==========================================================================
   Tinted field panels
   Each field sits on its own faint panel, with a round coloured badge beside
   the label. On a screen of a dozen identical boxes this is what lets someone
 find "the phone one" without reading €” the colour and the mark carry the
   meaning, not just the words.
   Tints come from existing tokens, so dark mode follows without new colours.
   ========================================================================== */

.f-tile {
  border-radius: var(--r);
  padding: 11px 13px 3px;
  background: var(--surface-2);
  border: 1px solid transparent;
  transition: border-color .15s ease, background .15s ease;
}
/* The panel lifts while the field inside it has focus. */
.f-tile:focus-within { border-color: var(--brand-200); }

/* Label row: the badge, then the label text. */
.f-tile .field > label {
  display: flex; align-items: center; gap: 9px;
  margin-bottom: 7px;
  font-size: 13px;
  color: var(--text);
}
/* The input keeps its own white surface, so it stands out from the panel. */
.f-tile .input,
.f-tile .select,
.f-tile .textarea { background: var(--surface); }
.f-tile .field > label::before {
  content: '';
  width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: 50%;
 /* The badge is a filled circle in its tone, not an outline on white €”
     that is what makes it readable at a glance across a dozen fields. */
  background: var(--brand-100) center / 16px 16px no-repeat;
}
.f-tile .field { margin-bottom: 8px; }

/* Each tone: a panel wash and a matching filled badge. The badge picture is
   set by .f-tile[data-mark], below, so tone and mark stay independent. */
.f-tile.t-green  { background: #eefaf2; }
.f-tile.t-blue   { background: #eaf2fe; }
.f-tile.t-violet { background: #f2eefe; }
.f-tile.t-amber  { background: #fef7e8; }
.f-tile.t-plain  { background: var(--surface-2); }

.f-tile.t-green  .field > label::before { background-color: #cdefdb; }
.f-tile.t-blue   .field > label::before { background-color: #cfe0fb; }
.f-tile.t-violet .field > label::before { background-color: #ddd2fb; }
.f-tile.t-amber  .field > label::before { background-color: #fbe5b8; }
.f-tile.t-plain  .field > label::before { background-color: var(--surface-3); }

/* Dark mode: the same hues, dark enough to sit under light text. */
html[data-theme='dark'] .f-tile.t-green  { background: #10291c; }
html[data-theme='dark'] .f-tile.t-blue   { background: #14243c; }
html[data-theme='dark'] .f-tile.t-violet { background: #211a38; }
html[data-theme='dark'] .f-tile.t-amber  { background: #2e2410; }
html[data-theme='dark'] .f-tile.t-green  .field > label::before { background-color: #1b4630; }
html[data-theme='dark'] .f-tile.t-blue   .field > label::before { background-color: #1e3a5f; }
html[data-theme='dark'] .f-tile.t-violet .field > label::before { background-color: #33285a; }
html[data-theme='dark'] .f-tile.t-amber  .field > label::before { background-color: #4a3a15; }

/* The badge picture, one per kind of field. */
.f-tile[data-mark="user"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2312894a' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 21v-1a7 7 0 0 1 7-7h2a7 7 0 0 1 7 7v1'/%3E%3C/svg%3E");
}
.f-tile[data-mark="phone"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z'/%3E%3C/svg%3E");
}
.f-tile[data-mark="mail"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237c3aed' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m2 7 10 6 10-6'/%3E%3C/svg%3E");
}
.f-tile[data-mark="idcard"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b45309' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='5' width='20' height='14' rx='2'/%3E%3Ccircle cx='8' cy='11' r='2'/%3E%3Cpath d='M5 16c.6-1.3 1.7-2 3-2s2.4.7 3 2M14 10h5M14 14h3'/%3E%3C/svg%3E");
}
.f-tile[data-mark="pin"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2312894a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 22s7-6.6 7-12a7 7 0 1 0-14 0c0 5.4 7 12 7 12z'/%3E%3Ccircle cx='12' cy='10' r='2.6'/%3E%3C/svg%3E");
}
.f-tile[data-mark="lock"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='10' width='16' height='11' rx='2'/%3E%3Cpath d='M8 10V7a4 4 0 0 1 8 0v3'/%3E%3C/svg%3E");
}
.f-tile[data-mark="map"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237c3aed' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 3-6 3v15l6-3 6 3 6-3V3l-6 3z'/%3E%3Cpath d='M9 3v15M15 6v15'/%3E%3C/svg%3E");
}
.f-tile[data-mark="briefcase"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b45309' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='7' width='20' height='13' rx='2'/%3E%3Cpath d='M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M2 12h20'/%3E%3C/svg%3E");
}
.f-tile[data-mark="badge"] .field > label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2312894a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2 4 6v6c0 5 3.4 8.6 8 10 4.6-1.4 8-5 8-10V6z'/%3E%3C/svg%3E");
}

/* A row of tiles, side by side, wrapping when there is no room.
   align-items: start stops a tile with a hint under it from stretching its
   neighbour to match. */
.f-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 10px;
  margin-bottom: 10px;
  align-items: start;
}
/* A tile on its own takes the full width, like the rows above and below it. */
.f-tile { margin-bottom: 10px; }
.f-tiles > .f-tile { margin-bottom: 0; }

/* Show/hide button inside a password field. */
.pw-wrap { position: relative; }
.pw-wrap .input { padding-right: 38px; }
.pw-wrap .pw-eye {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  border: none; background: none; padding: 6px; cursor: pointer;
  color: var(--text-3); display: grid; place-items: center;
}
.pw-wrap .pw-eye:hover { color: var(--text-2); }

/* ---- the photo panel ---- */

.photo-panel {
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  /* A soft wash from the top, as in the mock-up, rather than a flat fill. */
  background: linear-gradient(170deg, #e8f7ee 0%, #f3fbf6 55%, var(--surface) 100%);
  padding: 18px 14px 16px;
  text-align: center;
}
html[data-theme='dark'] .photo-panel {
  background: linear-gradient(170deg, #10291c 0%, #12221a 55%, var(--surface) 100%);
}
.photo-panel .field { margin-bottom: 0; }
.photo-panel > .field > label {
  text-align: center;
  display: block;
  margin-bottom: 10px;
}

/* ---- page heading with a coloured mark, as the mock-up heads each step ---- */

.page-head.marked .ph-text { display: flex; align-items: center; gap: 13px; }
.page-head.marked .ph-mark {
  width: 52px; height: 52px; flex: 0 0 52px;
  border-radius: 15px;
  display: grid; place-items: center;
  background: linear-gradient(150deg, var(--brand-500), var(--brand-700));
  color: #fff;
  box-shadow: 0 4px 12px rgba(18, 137, 74, .28);
}

/* ---- the bar that ends a long form ---- */

.form-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 14px 16px;
  margin-top: 4px;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-sm), var(--sheen);
}
.form-foot .note { font-size: 12.5px; color: var(--text-3); }

/*
 * The circle on the photo panel: its own surface so it reads against the
 * wash, and a soft ring around it, as the mock-up draws it.
 */
.photo-panel .photo-circle {
  background-color: var(--surface) !important;
  border-color: var(--brand-200) !important;
  box-shadow: 0 0 0 6px rgba(22, 163, 74, .07);
}
html[data-theme='dark'] .photo-panel .photo-circle {
  box-shadow: 0 0 0 6px rgba(52, 208, 127, .08);
}

/*
 * A camera badge on the corner of the circle, as on a phone's profile photo.
 * It sits outside the circle's own overflow, so it is drawn on a wrapper
 * rather than the circle itself €” the circle clips its contents to show a
 * photo, and would clip the badge too.
 */
.photo-circle-wrap {
  position: relative;
  width: max-content;
  margin: 0 auto;
}
.photo-circle-wrap::after {
  content: '';
  position: absolute; right: 6px; bottom: 6px;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--brand-600) center / 16px 16px no-repeat
    url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8h3l2-2h6l2 2h3a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z'/%3E%3Ccircle cx='12' cy='13' r='3.5'/%3E%3C/svg%3E");
  border: 3px solid var(--surface);
  box-shadow: var(--shadow-sm);
  pointer-events: none;
}
html[data-theme='dark'] .photo-circle-wrap::after { border-color: var(--surface-2); }

.search-wrap { position: relative; flex: 1 1 260px; max-width: 420px; }
.search-wrap .input { padding-left: 38px; }
.search-wrap svg {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: var(--text-3); pointer-events: none;
}
/*
 * The search in the top bar is a rounded pill on a tinted ground €” it is the
 * one control on that bar, and this is what makes it read as a search rather
 * than another box.
 */
.topbar .search-wrap { max-width: 520px; }
.topbar .search-wrap .input {
  border-radius: 999px;
  padding-top: 9px; padding-bottom: 9px;
  background: var(--surface-2);
  border-color: transparent;
}
.topbar .search-wrap .input:focus {
  background: var(--surface);
  border-color: var(--brand-500);
}

.toolbar {
  display: flex; gap: 9px; flex-wrap: wrap; align-items: center;
  margin-bottom: 14px;
}
.toolbar .select, .toolbar .input { width: auto; min-width: 130px; }

.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 36px; height: 20px; border-radius: 10px; background: var(--border-2);
  position: relative; transition: background .15s; flex: 0 0 36px;
}
.switch .track::after {
  content: ''; position: absolute; left: 2px; top: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff; transition: transform .15s; box-shadow: var(--shadow-sm);
}
.switch input:checked + .track { background: var(--brand-600); }
.switch input:checked + .track::after { transform: translateX(16px); }

.seg {
  display: inline-flex; background: var(--surface-3); border-radius: var(--r-sm); padding: 2px; gap: 2px;
}
.seg button {
  border: none; background: none; font: inherit; font-size: 12.5px; font-weight: 550;
  padding: 5px 11px; border-radius: 5px; cursor: pointer; color: var(--text-2);
}
.seg button.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

/* ---------------------------------------------------------------- surfaces */

.card {
  background: var(--surface); border: 1px solid var(--border);
  /* A larger radius, matching the panels inside: the card and its contents
     should look like one family, not a soft panel in a sharp box. */
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm), var(--ring), var(--sheen);
  transition: box-shadow .18s ease;
}
.card:hover { box-shadow: var(--shadow), var(--ring), var(--sheen); }
.card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--border);
}
/*
 * A card that heads a form section carries a coloured mark instead of a bare
 * icon, so a long form reads as a few labelled steps rather than one wall.
 * Opt in with .card-head.marked €” it does not change the many cards that head
 * a table or a chart.
 */
.card-head.marked { gap: 12px; }
.card-head.marked > svg:first-child {
  width: 34px; height: 34px; flex: 0 0 34px;
  padding: 8px; border-radius: 10px;
  background: var(--brand-50); color: var(--brand-700);
  box-shadow: var(--ring);
  overflow: visible;
}
html[data-theme='dark'] .card-head.marked > svg:first-child { color: var(--brand-500); }
.card-head.marked.tone-amber > svg:first-child { background: var(--amber-50); color: var(--amber-600); }
.card-head.marked.tone-give  > svg:first-child { background: var(--give-50);  color: var(--give-700); }
/* A quiet second line under the heading, for a one-line explanation. */
.card-head .sub { font-size: 12px; font-weight: 500; color: var(--text-3); margin-top: -1px; }
.card-head h2, .card-head h3 { flex: 1 1 auto; min-width: 0; }
.card-body { padding: 16px; }
.card-body.tight { padding: 0; }

.grid { display: grid; gap: 14px; }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-auto { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }

/* KPI tiles */
.stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); padding: 14px 15px;
  box-shadow: var(--shadow-sm), var(--ring), var(--sheen);
  display: flex; flex-direction: column; gap: 3px; min-width: 0;
  transition: transform .18s cubic-bezier(.22, .61, .36, 1), box-shadow .18s ease;
}
/* A small lift on hover €” enough to feel alive, not enough to distract. */
.stat:hover { transform: translateY(-3px); box-shadow: var(--shadow), var(--ring), var(--sheen); }
.stat .k { font-size: 11.5px; font-weight: 650; color: var(--text-3); text-transform: uppercase; letter-spacing: .04em; }
.stat .v { font-size: 22px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; }
.stat .m { font-size: 12px; color: var(--text-3); }
.stat.get  { border-left: 3px solid var(--get); }
.stat.get .v  { color: var(--get); }
.stat.give { border-left: 3px solid var(--give); }
.stat.give .v { color: var(--give); }
.stat.brand { border-left: 3px solid var(--brand-600); }
.stat.amber { border-left: 3px solid var(--amber-500); }

/* ---------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.tbl { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.tbl th {
  text-align: left; font-weight: 650; font-size: 11.5px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-3);
  padding: 9px 12px; border-bottom: 1px solid var(--border);
  background: var(--surface-2); white-space: nowrap; position: sticky; top: 0; z-index: 1;
}
table.tbl td { padding: 9px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
table.tbl tbody tr:last-child td { border-bottom: none; }
table.tbl tbody tr.clickable { cursor: pointer; }
table.tbl tbody tr.clickable:hover { background: var(--surface-2); }
table.tbl .r { text-align: right; }
table.tbl .c { text-align: center; }
table.tbl .nowrap { white-space: nowrap; }
table.tbl td.amt { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }

.empty { padding: 44px 20px; text-align: center; color: var(--text-3); }
.empty .big { font-size: 30px; margin-bottom: 8px; opacity: .55; }
.empty h3 { color: var(--text-2); margin-bottom: 5px; }

.pager {
  display: flex; align-items: center; gap: 10px; justify-content: flex-end;
  padding: 11px 14px; border-top: 1px solid var(--border); font-size: 13px; color: var(--text-2);
  flex-wrap: wrap;
}

/* ---------------------------------------------------------------- bits */

.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 20px; font-size: 11.5px; font-weight: 600;
  background: var(--surface-3); color: var(--text-2); white-space: nowrap;
}
.badge-get   { background: var(--get-50); color: var(--get-700); }
.badge-give  { background: var(--give-50); color: var(--give-700); }
.badge-brand { background: var(--brand-50); color: var(--brand-700); }
.badge-amber { background: var(--amber-50); color: var(--amber-600); }
.badge-muted { background: var(--surface-3); color: var(--text-3); }

.avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: 0 0 34px;
  display: grid; place-items: center; font-weight: 700; font-size: 13px;
  background: var(--brand-100); color: var(--brand-700);
}
.avatar.lg { width: 52px; height: 52px; flex-basis: 52px; font-size: 19px; }

.money-get  { color: var(--get); font-weight: 650; }
.money-give { color: var(--give); font-weight: 650; }
.muted { color: var(--text-3); }
.small { font-size: 12.5px; }

.row { display: flex; align-items: center; gap: 10px; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.stack { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.kv { display: grid; grid-template-columns: minmax(110px, auto) 1fr; gap: 7px 14px; font-size: 13.5px; }
.kv dt { color: var(--text-3); font-weight: 500; }
.kv dd { margin: 0; font-weight: 550; }

.divider { height: 1px; background: var(--border); margin: 14px 0; }

/* balance hero on a farmer page */
.balance-hero {
  border-radius: var(--r); padding: 16px 18px; display: flex;
  align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
}
.balance-hero.get  { background: var(--get-50);  border: 1px solid var(--get-100); }
.balance-hero.give { background: var(--give-50); border: 1px solid var(--give-100); }
.balance-hero.zero { background: var(--surface-3); border: 1px solid var(--border); }
.balance-hero .lbl { font-size: 12.5px; font-weight: 650; text-transform: uppercase; letter-spacing: .04em; }
.balance-hero .amt { font-size: 29px; font-weight: 750; letter-spacing: -.02em; line-height: 1.1; }

/* ---------------------------------------------------------------- modal */

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(8, 18, 13, .5);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 5vh 16px; z-index: 100; overflow-y: auto;
  animation: fade .13s ease;
}
@keyframes fade { from { opacity: 0; } }
.modal {
  background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  width: 100%; max-width: 560px; animation: pop .15s ease;
  border: 1px solid var(--border);
}
.modal.wide { max-width: 900px; }
.modal.narrow { max-width: 420px; }
@keyframes pop { from { transform: translateY(-10px); opacity: 0; } }
.modal-head {
  display: flex; align-items: center; gap: 10px;
  padding: 15px 18px; border-bottom: 1px solid var(--border);
}
.modal-head h2 { flex: 1 1 auto; }
.modal-body { padding: 18px; }
.modal-foot {
  display: flex; gap: 9px; justify-content: flex-end;
  padding: 13px 18px; border-top: 1px solid var(--border); flex-wrap: wrap;
}

/* ---------------------------------------------------------------- toast */

.toasts {
  position: fixed; bottom: 18px; right: 18px; z-index: 200;
  display: flex; flex-direction: column; gap: 9px; max-width: min(390px, calc(100vw - 36px));
}
.toast {
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--brand-600);
  border-radius: var(--r); box-shadow: var(--shadow-lg); padding: 11px 14px;
  display: flex; gap: 10px; align-items: flex-start; animation: slide .18s ease;
  font-size: 13.5px;
}
@keyframes slide { from { transform: translateX(14px); opacity: 0; } }
.toast.err { border-left-color: var(--get); }
.toast.ok  { border-left-color: var(--give); }
.toast .tx { flex: 1 1 auto; min-width: 0; white-space: pre-wrap; word-break: break-word; }
.toast .tt { font-weight: 650; }

/* ---------------------------------------------------------------- login */

.login-wrap {
  min-height: 100vh; display: grid; place-items: center; padding: 24px 16px;
  background:
    radial-gradient(1100px 480px at 12% -8%, var(--brand-50), transparent 62%),
    radial-gradient(900px 420px at 105% 108%, var(--amber-50), transparent 58%),
    var(--bg);
}
.login-card { width: 100%; max-width: 400px; }
.login-logo {
  width: 76px; height: auto; margin: 0 auto 12px; display: block;
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, .35));
}

/* ---------------------------------------------------------------- charts */

.bars { display: flex; align-items: flex-end; gap: 5px; height: 148px; padding-top: 8px; }
.bars .col { flex: 1 1 0; display: flex; flex-direction: column; justify-content: flex-end;
             gap: 2px; height: 100%; min-width: 0; }
.bars .bar { border-radius: 3px 3px 0 0; min-height: 2px; transition: height .3s ease; }
.bars .bar.d { background: var(--get); opacity: .85; }
.bars .bar.c { background: var(--give); opacity: .85; }
.bars .lab { font-size: 10px; color: var(--text-3); text-align: center; margin-top: 5px;
             white-space: nowrap; overflow: hidden; }
.legend { display: flex; gap: 14px; font-size: 12px; color: var(--text-2); flex-wrap: wrap; }
.legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; margin-right: 5px; }

.meter { height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.meter > span { display: block; height: 100%; border-radius: 3px; background: var(--brand-600); }

/* ---------------------------------------------------------------- tree */

.tree { font-size: 13.5px; }
.tree ul { list-style: none; margin: 0; padding-left: 22px; border-left: 1px dashed var(--border-2); }
.tree > ul { padding-left: 0; border-left: none; }
.tree li { padding: 3px 0; position: relative; }
.tree .node {
  display: inline-flex; align-items: center; gap: 9px; padding: 6px 11px;
  border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface);
  cursor: pointer; max-width: 100%;
}
.tree .node:hover { border-color: var(--brand-500); background: var(--brand-50); }
.tree .lvl { font-size: 10.5px; font-weight: 700; color: var(--text-3); }

/* ---------------------------------------------------------------- misc */

.spinner {
  width: 17px; height: 17px; border: 2px solid var(--border-2);
  border-top-color: var(--brand-600); border-radius: 50%;
  animation: spin .6s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading { padding: 48px; display: grid; place-items: center; gap: 12px; color: var(--text-3); }

.scrim { display: none; }

.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 16px;
        overflow-x: auto; }
.tabs button {
  border: none; background: none; font: inherit; font-size: 13.5px; font-weight: 550;
  padding: 9px 14px; cursor: pointer; color: var(--text-2);
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap;
}
.tabs button.active { color: var(--brand-700); border-bottom-color: var(--brand-600); font-weight: 650; }
html[data-theme='dark'] .tabs button.active { color: var(--brand-500); }

.alert {
  padding: 11px 14px; border-radius: var(--r-sm); font-size: 13.5px;
  border: 1px solid var(--border); background: var(--surface-2);
}
.alert-warn { background: var(--amber-50); border-color: var(--amber-100); color: var(--amber-600); }
.alert-err  { background: var(--get-50);  border-color: var(--get-100);  color: var(--get-700); }
.alert-ok   { background: var(--give-50); border-color: var(--give-100); color: var(--give-700); }

/* ==========================================================================
   Sign-in / self-registration screen
   A light, airy page: photo on the right, drifting moringa leaves, and the
   form on a card that floats above it all.
   ========================================================================== */

.auth {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  background: #eef7f0;
  display: flex;
  flex-direction: column;
}

/*
 * The approved photograph, shown as-is €” no tint, no wash. Built from the
 * signed-off mock-up by scripts/make-login.ps1.
 */
.auth-photo {
  position: absolute;
  inset: 0;
  background: url("/img/login-bg.jpg") center / cover no-repeat;
  pointer-events: none;
}
html[data-theme='dark'] .auth-photo { filter: brightness(.62) saturate(.9); }

/*
 * Wind in the moringa branch.
 * The same picture, painted again over the tree only and warped by an animated
 * turbulence filter: the leaves themselves ripple, so there is no second copy
 * of the branch to give the trick away. The mask keeps it to the top-right and
 * fades out, so the movement dies away naturally towards the sky and the field.
 */
.auth-wind {
  position: absolute;
  inset: 0;
  /* Must match .auth-photo exactly, or the warp would shift the picture. */
  background: url("/img/login-bg.jpg") center / cover no-repeat;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(46% 48% at 88% 14%, #000 40%, rgba(0, 0, 0, .5) 68%, transparent 88%);
  mask-image: radial-gradient(46% 48% at 88% 14%, #000 40%, rgba(0, 0, 0, .5) 68%, transparent 88%);
  filter: url("#windFilter");
  will-change: filter;
}
/* The filter is costly; only run it where it is worth it. */
@media (max-width: 1079px), (prefers-reduced-motion: reduce) {
  .auth-wind { display: none; }
}

/* Soft brand-coloured sweep along the bottom-left, as on the artwork. */
.auth-glow {
  position: absolute;
  inset: auto -6% -18% -14%;
  height: 46%;
  background:
    radial-gradient(56% 100% at 20% 100%, rgba(233, 250, 205, .95) 0%, rgba(233, 250, 205, 0) 68%),
    radial-gradient(44% 88% at 4% 94%, rgba(120, 196, 74, .30) 0%, rgba(120, 196, 74, 0) 70%);
  pointer-events: none;
  filter: blur(3px);
}
html[data-theme='dark'] .auth-glow { opacity: .22; }

/* ---- layout ---- */
.auth-top {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  padding: 26px clamp(18px, 4vw, 56px) 0;
}
.auth-brand { display: flex; align-items: center; gap: 16px; min-width: 0; }
.auth-brand img { width: clamp(58px, 6vw, 78px); height: auto; flex: 0 0 auto; }
.auth-brand .rule {
  width: 2px; align-self: stretch; border-radius: 2px; margin: 4px 0;
  background: linear-gradient(180deg, var(--brand-500), rgba(22, 163, 74, .15));
}
.auth-name {
  font-size: clamp(26px, 3.2vw, 40px);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.05;
  color: var(--brand-900);
}
html[data-theme='dark'] .auth-name { color: #eaf7ef; }
.auth-sub {
  font-size: clamp(14px, 1.5vw, 19px);
  font-weight: 650;
  color: var(--brand-600);
  margin-top: 2px;
}
.auth-tags {
  display: flex; align-items: center; gap: 10px;
  margin-top: 6px; font-size: 13.5px; font-weight: 600; color: var(--text-2);
}
.auth-tags .sep { color: var(--border-2); }
/* Sits over the leaves, so it needs its own light pad to stay readable. */
.auth-slogan {
  text-align: right;
  font-size: clamp(15px, 1.7vw, 21px);
  font-weight: 700;
  line-height: 1.35;
  color: var(--brand-700);
  padding: 10px 18px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .82);
  box-shadow: 0 8px 24px -14px rgba(12, 60, 34, .6);
  backdrop-filter: blur(8px) saturate(1.1);
  -webkit-backdrop-filter: blur(8px) saturate(1.1);
}
html[data-theme='dark'] .auth-slogan { color: #bdf0cf; background: rgba(13, 21, 18, .72); }
.auth-slogan span { color: #8bbf25; }

.auth-body {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  padding: 22px clamp(18px, 4vw, 56px) 34px;
}

/* ---- the card ---- */
.auth-card {
  width: min(533px, 100%);
  border-radius: 28px;
  padding: 30px 32px 0;
  background: #fff;
  border: 1px solid rgba(255, 255, 255, .9);
  box-shadow:
    0 34px 64px -26px rgba(12, 60, 34, .4),
    0 2px 10px rgba(12, 60, 34, .07);
  animation: cardFloat 7s ease-in-out infinite alternate;
  overflow: hidden;
}
html[data-theme='dark'] .auth-card {
  background: #131c17;
  border-color: rgba(255, 255, 255, .07);
  box-shadow: 0 34px 64px -26px rgba(0, 0, 0, .75);
}
@keyframes cardFloat {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -10px, 0); }
}
.auth-card h1 {
  display: flex; align-items: center; gap: 12px;
  font-size: 27px; font-weight: 750; letter-spacing: -.02em;
  color: var(--brand-900);
}
html[data-theme='dark'] .auth-card h1 { color: #eaf7ef; }
.auth-card h1 svg { color: var(--brand-600); flex: 0 0 auto; }
.auth-card .lead {
  color: var(--text-2); font-size: 15px; line-height: 1.45;
  margin: 10px 0 22px; max-width: 34ch;
}

/* Field with a leading icon and the label inside the box. */
.auth-field {
  display: flex; align-items: center; gap: 14px;
  padding: 10px 16px;
  border: 1.5px solid var(--brand-200);
  border-radius: 14px;
  background: #fbfefc;
  margin-bottom: 14px;
  transition: border-color .16s, box-shadow .16s, background .16s;
}
html[data-theme='dark'] .auth-field { background: var(--surface-2); border-color: var(--border-2); }
.auth-field:focus-within {
  border-color: var(--brand-500);
  box-shadow: 0 0 0 4px rgba(22, 163, 74, .12);
}
.auth-field .fi { color: var(--brand-700); flex: 0 0 auto; display: grid; place-items: center; }
.auth-field .fb { flex: 1 1 auto; min-width: 0; }
.auth-field label {
  display: block; font-size: 13px; font-weight: 500; color: var(--text-3);
}
.auth-field label .req-star { color: #e11d48; font-weight: 700; }
.auth-field input {
  width: 100%; border: none; background: none; outline: none; padding: 2px 0 0;
  font: inherit; font-size: 16px; font-weight: 600; color: var(--text);
}
.auth-eye {
  border: none; background: none; cursor: pointer; color: var(--brand-700);
  padding: 6px; border-radius: 8px; flex: 0 0 auto;
}
.auth-eye:hover { background: var(--brand-50); }

.btn-hero {
  width: 100%;
  justify-content: center;
  gap: 12px;
  padding: 14px 18px;
  border-radius: 12px;
  font-size: 17px;
  font-weight: 650;
  background: var(--brand-700);
  border-color: var(--brand-700);
  color: #fff;
  box-shadow: 0 12px 22px -12px rgba(15, 111, 61, .9);
  transition: transform .14s ease, box-shadow .14s ease, filter .14s ease;
}
.btn-hero:hover:not(:disabled) { transform: translateY(-1px); filter: brightness(1.08); }
.btn-hero:active:not(:disabled) { transform: translateY(0); }

.auth-or {
  display: flex; align-items: center; gap: 14px;
  margin: 18px 0 14px; color: var(--text-3); font-size: 13px; font-weight: 500;
}
.auth-or::before, .auth-or::after {
  content: ''; flex: 1 1 auto; height: 1px; background: var(--border);
}
.auth-join { display: flex; gap: 12px; }
.auth-join .btn {
  flex: 1 1 0; justify-content: center; border-radius: 12px; padding: 11px 8px;
  font-size: 13.5px; font-weight: 550; border-color: var(--brand-200);
  background: #fff;
}
html[data-theme='dark'] .auth-join .btn { background: var(--surface-2); border-color: var(--border-2); }
.auth-join .btn:hover:not(:disabled) { background: var(--brand-50); border-color: var(--brand-500); }
.auth-join .btn svg { color: var(--brand-700); }
.auth-status {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-top: 16px; font-size: 15px; font-weight: 600; color: var(--brand-600);
}
.auth-status .dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--brand-600);
}
/* Sits on a faint strip along the bottom of the card, as on the artwork. */
.auth-help {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 20px -32px 0; padding: 12px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 13.5px; color: var(--text-2);
}
.auth-help svg { color: var(--brand-700); }
.auth-help b { color: var(--brand-900); font-weight: 650; }
html[data-theme='dark'] .auth-help b { color: #eaf7ef; }

/* ---- promo panel ---- */
.auth-promo {
  width: min(470px, 100%);
  align-self: flex-end;            /* sits low on the right, as on the artwork */
  margin-bottom: 6px;
  border-radius: 22px;
  padding: 20px 22px;
  color: #fff;
  background: linear-gradient(135deg, rgba(15, 111, 61, .94), rgba(10, 78, 44, .90));
  border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: 0 26px 50px -22px rgba(6, 45, 26, .8);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  animation: cardFloat 9s ease-in-out .6s infinite alternate;
}
.auth-promo h2 {
  display: flex; align-items: center; gap: 10px;
  font-size: 21px; font-weight: 750; letter-spacing: .01em;
}
.auth-promo .tag { font-size: 14px; color: rgba(255, 255, 255, .85); margin: 2px 0 16px 34px; }
.auth-feats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.auth-feat { text-align: center; }
.auth-feat .ring {
  width: 52px; height: 52px; margin: 0 auto 8px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1.5px solid rgba(255, 255, 255, .55);
  background: rgba(255, 255, 255, .10);
}
.auth-feat span { display: block; font-size: 12.5px; font-weight: 600; line-height: 1.3; }

.auth-lang { display: flex; justify-content: center; margin-top: 10px; }

@media (prefers-reduced-motion: reduce) {
  .leaf, .auth-card, .auth-promo { animation: none !important; }
  .leaf { transition: none; }
}

@media (max-width: 1080px) {
  .auth-photo {
    inset: 0;
    -webkit-mask-image: none;
    mask-image: none;
    opacity: .3;
  }
  .auth-body { justify-content: center; }
  .auth-promo { width: min(560px, 100%); }
}
@media (max-width: 720px) {
  .auth-top { padding-top: 18px; }
  .auth-slogan { text-align: left; }
  .auth-card { padding: 22px 18px 18px; border-radius: 22px; }
  .auth-card h1 { font-size: 21px; }
  .auth-join { flex-direction: column; }
  .auth-feats { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .leaf { display: none; }          /* keep small screens calm and fast */
}

/* ---------------------------------------------------------------- hero imagery */

/*
 * Dashboard hero. The picture sits behind the welcome only; the numbers float
 * over its lower edge in glass cards, so data never has a busy photo behind it.
 * Source: public/img/hero-banner.jpg (1743 x 340) €” see scripts/make-hero.ps1.
 */
.dash-hero {
  position: relative;
  isolation: isolate;
  /* Spans the whole main column even when .page is width-capped (1920px
     screens); only the text inside keeps to the page's content width. */
  margin: 0;
  padding: 34px 0 118px;
  min-height: 312px;
  color: #fff;
  overflow: hidden;
  background-color: rgb(var(--scrim));              /* shown while the image loads */
  background-image:
    linear-gradient(90deg,
      rgba(var(--scrim), .93) 0%,
      rgba(var(--scrim), .82) 26%,
      rgba(var(--scrim), .42) 52%,
      rgba(var(--scrim), .06) 76%,
      rgba(var(--scrim), 0) 100%),
    url("/img/hero-banner.jpg");
  background-size: cover;
  /* Right-anchored: when the band is cropped, the farmer, tractor and
     Moringa board stay; the leaves under the dark side go first. */
  background-position: right 28%;
  background-repeat: no-repeat;
  animation: heroIn .5s ease both;
}
/* Melt the bottom of the picture into the page so the cards can overlap it. */
.dash-hero::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  /* Tall and front-loaded: on wide screens the gutter right of the cards
     shows this edge, and the Moringa board lettering must not ghost through. */
  height: 130px;
  background: linear-gradient(180deg, rgba(var(--scrim), 0) 0%, var(--bg) 80%, var(--bg) 100%);
  z-index: -1;
  pointer-events: none;
}
/* Past ~1760px the page stops widening, leaving a gutter with no cards over
 the hero's lower edge €” fade higher there so no lettering shows through. */
@media (min-width: 1760px) {
  .dash-hero::after { height: 176px; }
}
/* Same box as .page, so the greeting lines up with the cards below it. */
.dash-hero-inner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  max-width: 1500px;
  padding-inline: 20px;
}
.dash-hero-text { max-width: 560px; min-width: 0; }
.dash-hero-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: rgba(255, 255, 255, .86);
  padding: 4px 10px; border-radius: 20px;
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .18);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.dash-hero h1 {
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 750;
  letter-spacing: -.02em;
  margin-top: 14px;
  color: #fff;
  text-shadow: 0 2px 18px rgba(0, 0, 0, .25);
}
.dash-hero p {
  margin: 8px 0 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: rgba(255, 255, 255, .88);
  max-width: 460px;
}
.dash-hero-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* A button that belongs on a photo. A dark tinted base (not white) keeps the
   white label readable over the bright sunlit part of the picture too. */
.btn-glass {
  background: rgba(var(--scrim), .52);
  border-color: rgba(255, 255, 255, .42);
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .25);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.btn-glass:hover:not(:disabled) { background: rgba(var(--scrim), .72); }

/* The headline numbers, lifted onto the hero's faded edge.
   -92px of overlap, plus the page's own 20px top padding. */
.hero-kpis {
  position: relative;
  z-index: 2;
  margin-top: -112px;
  margin-bottom: 14px;
}
.hero-kpis .stat {
  background: var(--glass);
  border-color: var(--glass-border);
  box-shadow: 0 12px 32px rgba(var(--scrim), .16), var(--shadow-sm);
  backdrop-filter: blur(14px) saturate(1.15);
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
  padding: 16px 18px;
}
.hero-kpis .stat .v { font-size: 26px; }

@keyframes heroIn { from { opacity: 0; transform: translateY(-4px); } }

/*
 * Login and self-registration. Source: public/img/login-bg.jpg.
 * That 1.93:1 shape sits close to a 16:9 screen, so the picture is shown near
 * native size. The scrim is darkest behind the form and lets the farmer,
 * field and Moringa board come through on the right.
 */
.login-wrap {
  position: relative;
  background-color: rgb(var(--scrim));
  background-image:
    linear-gradient(100deg,
      rgba(var(--scrim), .93) 0%,
      rgba(var(--scrim), .84) 24%,
      rgba(var(--scrim), .34) 42%,
      rgba(var(--scrim), .08) 64%,
      rgba(var(--scrim), .02) 100%),
    url("/img/login-bg.jpg");
  background-size: cover;
  /* Right-weighted so the Moringa board is not cut on 16:9 screens. */
  background-position: 78% 55%;
  background-repeat: no-repeat;
  justify-items: start;
  padding-inline: clamp(16px, 6vw, 96px);
}
.login-wrap .card {
  background: var(--glass-strong);
  border-color: var(--glass-border);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .32);
  backdrop-filter: blur(16px) saturate(1.15);
  -webkit-backdrop-filter: blur(16px) saturate(1.15);
}
/* Secondary panel under the form: see-through, so the form stays the focus. */
.login-wrap .card.login-alt {
  background: rgba(255, 255, 255, .10);
  border-color: rgba(255, 255, 255, .22);
  box-shadow: none;
  color: #fff;
}
.login-alt .muted { color: rgba(255, 255, 255, .82); }
.login-alt .btn {
  background: rgba(255, 255, 255, .14);
  border-color: rgba(255, 255, 255, .34);
  color: #fff;
}
.login-alt .btn:hover:not(:disabled) { background: rgba(255, 255, 255, .26); text-decoration: none; }
.login-alt a:not(.btn) { color: #c9f5d9; }
.login-brand, .login-brand h1 { color: #fff; }
.login-brand .muted { color: rgba(255, 255, 255, .82); }
.login-brand .btn-ghost { color: #fff; }
.login-brand .btn-ghost:hover { background: rgba(255, 255, 255, .14); }
.login-tagline {
  display: block;
  margin-top: 6px;
  font-size: 13px;
  color: rgba(255, 255, 255, .78);
}
.login-foot .btn-ghost { color: #fff; }
.login-foot .btn-ghost:hover { background: rgba(255, 255, 255, .14); }
.login-logo { box-shadow: 0 8px 24px rgba(0, 0, 0, .3); }

/* Self-registration form page: the same scene as a header band. */
.join-hero {
  margin: 0 0 22px;
  padding: 26px 16px 22px;
  color: #fff;
  background-color: rgb(var(--scrim));
  background-image:
    linear-gradient(180deg, rgba(var(--scrim), .78) 0%, rgba(var(--scrim), .70) 55%, rgba(var(--scrim), .93) 100%),
    url("/img/hero-banner.jpg");
  background-size: cover;
  /* Top-anchored keeps the turban whole; the darker foot hides the board
     lettering that the crop leaves half-visible. */
  background-position: 45% 0%;
}

@media (prefers-reduced-motion: reduce) {
  .dash-hero { animation: none; }
}

/* Browsers without backdrop-filter get solid panels instead of see-through ones. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero-kpis .stat, .login-wrap .card { background: var(--surface); }
}

/* ---------------------------------------------------------------- responsive */

@media (max-width: 1100px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Any grid given an explicit two-column template inline collapses here too. */
  .page .grid[style*='minmax'] { grid-template-columns: minmax(0, 1fr) !important; }
}

@media (max-width: 860px) {
  .sidebar { transform: translateX(-100%); box-shadow: var(--shadow-lg); }
  body.nav-open .sidebar { transform: translateX(0); }
  body.nav-open .scrim {
    display: block; position: fixed; inset: 0; background: rgba(8, 18, 13, .45); z-index: 35;
  }
  .main { margin-left: 0; }
  .hamburger { display: inline-flex; }
  .page { padding: 14px; }
  /* minmax(0, 1fr), never plain 1fr.
     A bare `1fr` track is min-content wide at minimum, so any wide child —
     a long unbroken string, a nested grid, a table — silently stretches the
     column past the screen and drags the page with it. Measured on a 390px
     phone: the dashboard's card came out 562px and settings' nested grid
     590px, both from `1fr`. minmax(0, …) lets the track actually shrink. */
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .form-grid, .form-grid-3 { grid-template-columns: minmax(0, 1fr); }
  /* Nested grids inherit the same fault; catch them wherever they appear. */
  .page .grid { grid-template-columns: minmax(0, 1fr); }
  /* And make sure grid/flex children are allowed to shrink at all. */
  .page .grid > *,
  .grid-2 > *, .grid-3 > *, .grid-4 > * { min-width: 0; }
  .kv { grid-template-columns: 1fr; gap: 2px 0; }

 /* Photo on top, full-width fields below €” see .photo-split above. */
  .photo-split {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  /* A smaller circle: here it is a thumbnail, not the point of the screen.
     !important because photoInput sets the size inline. */
  .photo-circle {
    width: 116px !important;
    height: 116px !important;
  }
  .kv dd { margin-bottom: 9px; }
  h1 { font-size: 19px; }
  .stat .v { font-size: 19px; }
  .balance-hero .amt { font-size: 24px; }

  /* On a phone the band is tall and narrow: centre on the farmer and darken
     top-to-bottom instead of left-to-right. */
  .dash-hero {
    padding: 22px 0 104px;
    min-height: 0;
    background-image:
      linear-gradient(180deg, rgba(var(--scrim), .80) 0%, rgba(var(--scrim), .55) 60%, rgba(var(--scrim), .32) 100%),
      url("/img/hero-banner.jpg");
    background-position: 44% 30%;
  }
  .dash-hero-inner { padding-inline: 14px; }
  .dash-hero::after { height: 70px; }
  .dash-hero h1 { font-size: 23px; margin-top: 12px; }
  .dash-hero p { font-size: 13.5px; }
  .dash-hero-actions { width: 100%; }
  .dash-hero-actions .btn { flex: 1 1 auto; }
  .hero-kpis { margin-top: -94px; }   /* 80px overlap + 14px page padding */
  .hero-kpis .stat .v { font-size: 22px; }

  .login-wrap {
    justify-items: center;
    background-image:
      linear-gradient(180deg, rgba(var(--scrim), .78) 0%, rgba(var(--scrim), .66) 42%, rgba(var(--scrim), .86) 100%),
      url("/img/login-bg.jpg");
    /* Portrait screens: centre on the farmer. */
    background-position: 42% center;
  }
}

@media print {
  .dash-hero { background: none !important; color: var(--text); margin: 0; padding: 0 0 12px; min-height: 0; }
  .dash-hero::after { display: none; }
  .dash-hero h1, .dash-hero p, .dash-hero-eyebrow { color: #000; text-shadow: none; background: none; border: none; }
  .hero-kpis { margin-top: 0; }
  .hero-kpis .stat { backdrop-filter: none; box-shadow: none; background: #fff; }
}

@media print {
  .sidebar, .topbar, .no-print, .toasts { display: none !important; }
  .main { margin-left: 0; }
  .page { padding: 0; max-width: none; }
  .card { box-shadow: none; border-color: #ccc; break-inside: avoid; }
  body { background: #fff; font-size: 11.5px; }
  table.tbl th { background: #f2f2f2 !important; }
  a { color: inherit; text-decoration: none; }
}

/* ==================================================================== */
/* APP INSTALL €” " ‡‚Ÿ‰ •‡‚" bar aur iPhone ki madad */
/* ==================================================================== */

/* Neeche se upar aati hui patti. Fixed rakhi hai taaki page scroll karne par
 bhi dikhe, lekin safe-area ka dhyan rakha hai €” iPhone ke home indicator ke
   peeche na chhupe. */
.install-bar {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 12px;
  border-radius: 16px;
  background: var(--card, #fff);
  border: 1px solid var(--line, #e3e8e5);
  box-shadow: 0 10px 32px rgba(8, 54, 30, .17), 0 2px 6px rgba(8, 54, 30, .07);
  /* Aane se pehle neeche chhupi rehti hai; .in lagte hi upar aati hai. */
  transform: translateY(140%);
  opacity: 0;
  transition: transform .42s cubic-bezier(.22, 1, .36, 1), opacity .3s ease;
}
.install-bar.in { transform: translateY(0); opacity: 1; }

.install-ico {
  width: 42px; height: 42px;
  border-radius: 10px;
  flex: 0 0 auto;
  border: 1px solid var(--line, #e3e8e5);
  background: #fff;
  object-fit: contain;
}
.install-ico.lg { width: 60px; height: 60px; border-radius: 14px; }

.install-txt { flex: 1 1 auto; min-width: 0; display: grid; gap: 1px; }
.install-txt strong { font-size: 14px; font-weight: 650; color: var(--text, #14201a); }
.install-txt span {
  font-size: 12px;
  line-height: 1.35;
  color: var(--text-3, #7b8a83);
  /* Chhoti screen par do line se zyada na ho. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

.install-go {
  flex: 0 0 auto;
  padding: 9px 17px;
  border: 0;
  border-radius: 10px;
  background: var(--brand-700, #0f6f3d);
  color: #fff;
  font-size: 13.5px;
  font-weight: 650;
  font-family: inherit;
  cursor: pointer;
  transition: background .15s ease, transform .12s ease;
}
.install-go:hover { background: var(--brand-600, #12894a); }
.install-go:active { transform: scale(.96); }

.install-x {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border: 0; border-radius: 8px;
  background: transparent;
  color: var(--text-3, #7b8a83);
  font-size: 21px; line-height: 1;
  cursor: pointer;
}
.install-x:hover { background: var(--bg, #f4f6f5); color: var(--text, #14201a); }

/* --- iPhone wali madad ---------------------------------------------- */
.install-sheet {
  position: fixed; inset: 0; z-index: 950;
  display: grid; place-items: end center;
  padding: 16px;
  background: rgba(8, 24, 16, .42);
  animation: inst-fade .2s ease;
}
@keyframes inst-fade { from { opacity: 0 } to { opacity: 1 } }

.install-sheet-card {
  width: 100%;
  max-width: 400px;
  margin-bottom: env(safe-area-inset-bottom, 0px);
  padding: 22px 20px 18px;
  border-radius: 20px;
  background: var(--card, #fff);
  box-shadow: 0 -8px 40px rgba(8, 54, 30, .25);
  text-align: center;
  animation: inst-up .34s cubic-bezier(.22, 1, .36, 1);
}
@keyframes inst-up { from { transform: translateY(22px); opacity: .6 } to { transform: none; opacity: 1 } }

.install-sheet-card h3 {
  margin: 12px 0 14px;
  font-size: 17px; font-weight: 680;
  color: var(--text, #14201a);
}
.install-sheet-card ol {
  margin: 0 0 18px;
  padding-left: 22px;
  text-align: right;
  direction: rtl;               /* Hindi list numbers sit with the text */
  font-size: 14px; line-height: 1.85;
  color: var(--text-2, #4a5a52);
}
.install-sheet-card ol li { direction: ltr; text-align: left; }
.install-sheet-card ol svg { vertical-align: -3px; color: var(--brand-700, #0f6f3d); }
.install-sheet-card strong { color: var(--text, #14201a); font-weight: 650; }

.install-ok {
  width: 100%;
  padding: 12px;
  border: 0; border-radius: 12px;
  background: var(--brand-700, #0f6f3d);
  color: #fff;
  font-size: 15px; font-weight: 650; font-family: inherit;
  cursor: pointer;
}
.install-ok:active { transform: scale(.98); }

/* Installed app: browser ki jagah nahi lagti, isliye thoda upar se jagah. */
@media (display-mode: standalone) {
  .topbar { padding-top: env(safe-area-inset-top, 0px); }
  .install-bar { display: none; }
}

/* Install bar page ke neeche wale hisse ko na dhake €” utni jagah chhod dein.
   Sirf tab jab bar sach mein dikh rahi ho. */
body:has(.install-bar) .login-wrap,
body:has(.install-bar) .page {
  padding-bottom: 104px;
}

/* ==================================================================== */
/* PHONE €” asli phone par naap kar theek kiya gaya */
/*                                                                       */
/*  Measured on a 390x844 device. What was wrong:                        */
/*    - sidebar took 252px of 390 (65% of the screen)                    */
/*    - the logo lived only in the sidebar, so the main screen had no    */
/*      branding at all once the menu was closed                         */
/*    - nav rows were 40px tall; 44px is the minimum a finger hits       */
/*      reliably (Apple HIG and Material both use 44-48px)               */
/*    - the search box was squeezed to about half its readable width     */
/*    - the install bar sat on top of the menu                           */
/* ==================================================================== */

@media (max-width: 860px) {

  /* --- Sidebar: narrower, and never more than ~78% of any screen ------
     252px on a 390px phone left only 138px of page showing, which reads
     as broken rather than as a drawer. 84vw capped at 310px keeps a real
     slice of the page visible behind the scrim, so it is obvious that the
     menu is a layer you can dismiss. */
  .sidebar {
    /* Half the screen. On a 390px phone that is ~195px, which still fits the
       longest Hindi label, and leaves as much page showing as menu - so the
       drawer reads as a layer over the app, not a screen of its own.
       The 300px ceiling stops it sprawling on a small tablet, where 50vw
       would be far more menu than anyone needs; the 190px floor keeps the
       icon tile plus label readable on a very narrow phone. */
    width: min(50vw, 300px);
    flex-basis: min(50vw, 300px);
    min-width: 190px;
    /* The drawer is above the page, so it needs its own shadow. */
    box-shadow: 6px 0 28px rgba(8, 40, 24, .18);
  }

  /* Drawer slides over the page; the page must not shift underneath. */
  .main { margin-left: 0; }

 /* Stop the page scrolling behind an open drawer €” on a phone that feels
     like the app has lost its place. */
  body.nav-open { overflow: hidden; }

  /* --- Top bar: brand on the left, controls compact ------------------- */
  .topbar {
    gap: 6px;
    padding-left: 6px;
    padding-right: 8px;
    /* Under the notch / status bar on an installed app. */
    padding-top: env(safe-area-inset-top, 0px);
    height: auto;
    min-height: var(--topbar-h);
  }

  .topbar-brand {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    flex: 0 1 auto;
  }
  .topbar-brand img {
    width: 30px; height: 30px;
    flex: 0 0 30px;
    object-fit: contain;
  }
  .topbar-brand span {
    font-size: 14.5px;
    font-weight: 680;
    letter-spacing: -.2px;
    color: var(--text);
    white-space: nowrap;
  }

  /* The language switch is the least-used control on a phone. Trim its
     padding rather than scale it: transform shrank the real tap area to
     31px while the pixels still looked fine, which is the worst kind of
 small target €” it looks tappable and misses. */
  .topbar .seg button {
    padding-left: 10px;
    padding-right: 10px;
    font-size: 12.5px;
    min-height: 40px;
  }

  /* --- Tap targets: 44px minimum -------------------------------------- */
  .nav-item {
    min-height: 46px;
    padding-top: 11px;
    padding-bottom: 11px;
    font-size: 14.5px;
  }
  .nav-group > .nav-head { min-height: 44px; }
  .sidebar-foot .btn-icon,
  .topbar .btn-icon {
    min-width: 42px;
    min-height: 42px;
  }

  /* --- Install bar must not cover the menu ---------------------------- */
  body.nav-open .install-bar { display: none; }
}

/* --- Narrow phones (<= 400px): hide the brand text, keep the mark ------
   Below this the brand word and the search box start fighting for the
   same row. The logo alone still identifies the app. */
@media (max-width: 400px) {
  .topbar-brand span { display: none; }
  .topbar .seg button { padding-left: 8px; padding-right: 8px; font-size: 12px; }
}

/* On a wide screen the sidebar already carries the brand €” no duplicate. */
@media (min-width: 861px) {
  .topbar-brand { display: none; }
}

/* --- Phone: search becomes an icon that expands ----------------------
   At 390px the pill was asking for 260px it could not get, so its
 placeholder was clipped mid-word ("•, —‚"). Collapsed to a round
   button it costs 42px; tapping it gives search the whole row, where the
   placeholder and the typed query both fit. */
@media (max-width: 860px) {
  .topbar .search-wrap {
    flex: 0 0 42px;
    width: 42px;
    max-width: 42px;
    transition: flex-basis .22s ease, width .22s ease, max-width .22s ease;
  }
  .topbar .search-wrap .input {
    padding-left: 38px;
    padding-right: 0;
    width: 42px;
    cursor: pointer;
    /* Hide the placeholder while collapsed: a clipped half-word looks
       broken, an icon alone does not. */
    color: transparent;
  }
  .topbar .search-wrap .input::placeholder { color: transparent; }

  /* Expanded: search owns the row, everything else steps aside. */
  .topbar .search-wrap:focus-within {
    flex: 1 1 auto;
    width: auto;
    max-width: none;
  }
  .topbar .search-wrap:focus-within .input {
    width: 100%;
    padding-right: 12px;
    cursor: text;
    color: var(--text);
  }
  .topbar .search-wrap:focus-within .input::placeholder { color: var(--text-3); }

  /* While searching, the brand and language switch give up their space. */
  .topbar:has(.search-wrap:focus-within) .topbar-brand,
  .topbar:has(.search-wrap:focus-within) .seg { display: none; }
}

/* --- Install bar page ke aakhri card ko na dhake ---------------------
   Measured: the bar is 78px tall and sits 12px from the bottom, so the
   page needs ~102px of clearance. The earlier :has() rule only covered
   .page and .login-wrap; the dashboard's own scroll container needs it
   too, or the last card is clipped mid-number. */
@media (max-width: 860px) {
  body:has(.install-bar) #pageHost,
  body:has(.install-bar) .main {
    padding-bottom: 102px;
  }
}

/* Thoda saans lene ki jagah €” logo aur menu button chipke nahi rahne
   chahiye. */
@media (max-width: 860px) {
  .topbar .hamburger { margin-right: 2px; }
  .topbar-brand { margin-right: 4px; }
}

/* ==================================================================== */
/* PHONE €” har page par naapi gayi dikkatein */
/*                                                                       */
/*  Swept dashboard, farmers, register, staff, applications, deals,      */
/*  ledger, team and settings at 390px. Three faults repeated on almost  */
/*  every page, so they are fixed once here rather than page by page.    */
/* ==================================================================== */

@media (max-width: 860px) {

  /* --- 1. Tap targets ------------------------------------------------
     Buttons and form controls measured 38px, small ones 25-31px. Apple
     and Google both put the reliable minimum at 44px; below that a
     fingertip hits the wrong control often enough to matter when a field
     officer is entering a farmer's money. */
 /* height:auto first €” several of these carry a fixed height from the
     desktop rules, and a min-height cannot grow an element that has been
     given an explicit height. */
  .btn,
  .input,
  select,
  input[type="text"], input[type="tel"], input[type="number"],
  input[type="date"], input[type="password"], input[type="search"],
  textarea.input,
  .field input,
  .field select {
    height: auto;
    min-height: 44px;
  }
  .btn-sm {
    height: auto;
    min-height: 40px;      /* secondary actions may be smaller, not tiny */
    padding-left: 12px;
    padding-right: 12px;
  }
  .btn-icon,
  .btn-sm.btn-icon {
    min-width: 40px;
    min-height: 40px;
  }
 /* Segmented controls (‚€/EN, filter pills) were 29px. */
  .seg button,
  .tabs button,
  .chip {
    min-height: 38px;
  }

  /* --- 2. Tables must not push the page sideways ---------------------
     The staff table ran 612px past a 390px screen, which drags the whole
     layout with it. Wrapping each table in its own scroller keeps the
     page itself fixed while the table scrolls under the finger. */
  .table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* The scroller itself must never be wider than the screen, or the page
       goes sideways with it. */
    max-width: 100%;
  }
  /* min-width ONLY inside a scroller. Applied to every .tbl it also hit
 tables that have no wrapper €” those then dragged the whole page
     sideways (measured: dashboard 574px, settings 602px on a 390px
     screen), which is worse than slightly narrow columns. */
  .table-wrap > .tbl {
    min-width: 560px;
  }
  /* A table with no scroller must fit, whatever that costs its columns. */
  .tbl {
    max-width: 100%;
  }

  /* --- 3. Headings and labels must not be clipped --------------------
 "•‡ ” Ÿ€" and "• •€ œ•€" were cut mid-word by a
     truncate meant for a desktop column. On a phone there is room to
     wrap, and a wrapped heading is always better than a cut one. */
  .card-head .ch-text,
  .card-head h3,
  .page-head h1,
  .f-tile label,
  .field label {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }

  /* Page padding: a little tighter so content gets the width. */
  .page { padding: 12px; }
  .card-body { padding: 14px; }
}

/* --- Phone: stepper dikhaye sirf abhi wala kadam --------------------
   Four Hindi step titles sharing 390px gave every one of them about 60px,
 so all four were cut mid-word ("•‡ ” Ÿ€" -> "•‡ ” Ÿ€").
   On a phone only the current step needs its name; the rest stay as
   numbered dots, which also makes the position in the flow clearer. */
@media (max-width: 860px) {
  .stepper { gap: 4px !important; }
  .stepper .step-item { flex: 0 0 auto !important; }
  /* The active step keeps its label and takes the leftover room. */
  .stepper .step-item.is-active { flex: 1 1 auto !important; }
  .stepper .step-item:not(.is-active) > .truncate { display: none; }
  .stepper .step-item.is-active > .truncate {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
  /* Connector lines shrink; the dots carry the meaning. */
  .stepper .step-item > div:last-child { min-width: 8px !important; }
}

/* Password ka aankh wala button bhi ungli se dabne layak ho. */
@media (max-width: 860px) {
  .pw-wrap .pw-eye {
    min-width: 40px;
    min-height: 40px;
    padding: 8px;
  }
}

/* ==================================================================== */
/*  SIDEBAR  —  approved design (mockup ke hisaab se)                    */
/*                                                                       */
/*  Differences the mockup asked for, measured against what was there:   */
/*    - a farm banner behind the brand instead of a bare white head      */
/*    - a coloured icon tile per row (scan by colour, not by reading)    */
/*    - the active row as a filled green pill, not a pale tint           */
/*    - a chevron on every row                                           */
/*    - an icon beside each section heading, with a green bar            */
/*    - more air between rows                                            */
/* ==================================================================== */

/* --- Brand head with the farm banner -------------------------------- */
.sidebar-brand.has-banner {
  position: relative;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 16px 18px;
  min-height: 0;
  overflow: hidden;
  /* The photo sits under a green wash so white text stays readable
     whatever part of the image shows through. */
  background:
    linear-gradient(180deg, rgba(236, 253, 243, .92) 0%, rgba(255, 255, 255, .97) 78%),
    url("/img/hero-banner.jpg") center 62% / cover no-repeat;
  border-bottom: 1px solid var(--border);
}
html[data-theme='dark'] .sidebar-brand.has-banner {
  background:
    linear-gradient(180deg, rgba(13, 42, 26, .93) 0%, rgba(20, 29, 24, .97) 78%),
    url("/img/hero-banner.jpg") center 62% / cover no-repeat;
}
.sidebar-brand.has-banner .logo {
  width: 46px; height: 46px; flex: 0 0 46px;
  filter: drop-shadow(0 2px 6px rgba(8, 54, 30, .18));
}
.sidebar-brand.has-banner .bt {
  font-size: 15px; font-weight: 800; letter-spacing: -.2px;
  color: var(--brand-900);
  line-height: 1.2;
}
html[data-theme='dark'] .sidebar-brand.has-banner .bt { color: #eaf6ef; }
.sidebar-brand.has-banner .bs {
  font-size: 12px; color: var(--text-2); margin-top: 1px;
}
.sidebar-brand.has-banner .btag {
  margin-top: 5px;
  font-size: 10.5px;
  font-style: italic;
  color: var(--brand-700);
  line-height: 1.3;
}
html[data-theme='dark'] .sidebar-brand.has-banner .btag { color: var(--brand-200); }

/* --- Section headings: green bar + icon + label ---------------------- */
.nav-label {
  display: flex; align-items: center; gap: 8px;
  padding: 0 12px 8px;
  position: relative;
}
.nav-label::before {
  content: '';
  width: 3px; height: 14px;
  border-radius: 2px;
  background: var(--brand-600);
  flex: 0 0 3px;
}
.nav-label .nl-ico {
  display: grid; place-items: center;
  color: var(--brand-700);
}
html[data-theme='dark'] .nav-label .nl-ico { color: var(--brand-200); }

/* --- Rows: icon tile, label, chevron --------------------------------- */
.nav-item {
  gap: 11px;
  padding: 7px 10px;
  border-radius: 13px;
}
/* Long Hindi labels ("फील्ड ऑफिसर पंजीकरण") wrapped to two lines and made the
   row twice as tall, which broke the even rhythm of the list. One line, with
   an ellipsis if it truly cannot fit. */
.nav-txt {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The coloured tile. Each tone is written out rather than generated so the
   palette stays deliberate — these are the colours from the design. */
.nav-ico {
  display: grid; place-items: center;
  width: 36px; height: 36px; flex: 0 0 36px;
  border-radius: 10px;
  transition: transform .14s ease;
}
.nav-item:hover .nav-ico { transform: scale(1.05); }

.nav-ico[data-tone='green']  { background: #dcfce7; color: #15803d; }
.nav-ico[data-tone='leaf']   { background: #e6f7dd; color: #3f7d20; }
.nav-ico[data-tone='amber']  { background: #fef3c7; color: #b45309; }
.nav-ico[data-tone='blue']   { background: #dbeafe; color: #1d4ed8; }
.nav-ico[data-tone='violet'] { background: #ede9fe; color: #6d28d9; }
.nav-ico[data-tone='teal']   { background: #ccfbf1; color: #0f766e; }
.nav-ico[data-tone='red']    { background: #fee2e2; color: #b91c1c; }
.nav-ico[data-tone='slate']  { background: #e2e8f0; color: #334155; }

html[data-theme='dark'] .nav-ico[data-tone='green']  { background: #16341f; color: #86efac; }
html[data-theme='dark'] .nav-ico[data-tone='leaf']   { background: #1c3315; color: #a3e07a; }
html[data-theme='dark'] .nav-ico[data-tone='amber']  { background: #3a2a0c; color: #fcd34d; }
html[data-theme='dark'] .nav-ico[data-tone='blue']   { background: #14264a; color: #93c5fd; }
html[data-theme='dark'] .nav-ico[data-tone='violet'] { background: #2a1f47; color: #c4b5fd; }
html[data-theme='dark'] .nav-ico[data-tone='teal']   { background: #0e3330; color: #5eead4; }
html[data-theme='dark'] .nav-ico[data-tone='red']    { background: #3d1717; color: #fca5a5; }
html[data-theme='dark'] .nav-ico[data-tone='slate']  { background: #26303b; color: #cbd5e1; }

/* The go-arrow. Only a down-chevron exists in the icon set, so rotate it. */
.nav-go {
  display: grid; place-items: center;
  flex: 0 0 auto;
  color: var(--text-3);
  opacity: .5;
  transition: opacity .14s ease, transform .14s ease;
}
/* No rotation: the `chevron` glyph in ui.js already points right
   (m9 18 6-6-6-6). Rotating it turned the arrow upward. */
.nav-item:hover .nav-go { opacity: 1; transform: translateX(2px); }

/* --- Active row: a filled pill, as in the design --------------------- */
.nav-item.active {
  background: linear-gradient(135deg, var(--brand-700) 0%, var(--brand-600) 100%);
  color: #fff;
  font-weight: 700;
  box-shadow: 0 4px 14px rgba(15, 111, 61, .28);
}
.nav-item.active .nav-ico {
  /* A translucent white tile reads as "lit" against the green pill without
     needing a second colour. */
  background: rgba(255, 255, 255, .22) !important;
  color: #fff !important;
}
.nav-item.active .nav-go { color: #fff; opacity: .9; }
.nav-item.active:hover { color: #fff; }

/* The pill inside the Registration group keeps the same treatment. */
.nav-sub .nav-item.active {
  background: linear-gradient(135deg, var(--brand-700) 0%, var(--brand-600) 100%);
  color: #fff;
}
html[data-theme='dark'] .nav-sub .nav-item.active {
  background: linear-gradient(135deg, var(--brand-600) 0%, var(--brand-500) 100%);
}

/* The Registration toggle's own chevron is handled by .nav-chev above — it
   points right when closed and rotates down when open. Nothing to override
   here; an earlier `transform: none` broke that open/close animation. */

/* --- A little more air between rows ---------------------------------- */
.nav-group { margin-bottom: 14px; }
.nav-group .nav-item + .nav-item { margin-top: 3px; }

/* --- Half-width drawer: make the labels fit ---------------------------
   At 50% the drawer is ~195px on a 390px phone, and measurement showed
   8 of the Hindi labels being cut by the ellipsis ("जिला प्रबंधक पंजीकरण",
   "एफिलिएट नेटवर्क" and so on). A menu whose words are cut off is not a
   menu, so the row is made to give the text more of the width: a smaller
   icon tile, tighter gaps, and a slightly smaller type size. */
@media (max-width: 860px) {
  .nav-item {
    gap: 8px;
    padding-left: 8px;
    padding-right: 6px;
  }
  .nav-ico {
    width: 30px; height: 30px; flex-basis: 30px;
    border-radius: 8px;
  }
  .nav-ico svg { width: 16px; height: 16px; }
  .nav-txt {
    font-size: 13px;
    letter-spacing: -.1px;
  }
  /* The go-arrow is decoration next to a full-width tap target; at this
     width its 15px is better spent on the label. */
  .nav-go { display: none; }

  /* The nested Registration list is indented, which costs it width twice
     over - trim its own padding so its labels get the same chance. */
  .nav-sub .nav-item { padding-left: 6px; }
  .nav-sub-inner { padding-left: 4px; padding-right: 4px; }
}

/* --- Half-width drawer: brand and user name must not be cut -----------
   At 50% the brand read "HM AGRI O..." and the footer "Administrat...".
   Both have room to wrap onto a second line here, and a wrapped name is
   always better than a cut one. */
@media (max-width: 860px) {
  .sidebar-brand.has-banner .bt {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    font-size: 13.5px;
    line-height: 1.25;
  }
  .sidebar-brand.has-banner .bs  { font-size: 11.5px; }
  .sidebar-brand.has-banner .btag { font-size: 10px; }
  .sidebar-brand.has-banner .logo { width: 38px; height: 38px; flex-basis: 38px; }

  /* The signed-in name in the footer. */
  .sidebar-foot .truncate {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    line-height: 1.25;
  }
  .sidebar-foot .row { gap: 8px; }
}

/* ==================================================================== */
/*  PHONE FORMS & FILTERS  -  ek seedha, saaf grid                       */
/*                                                                       */
/*  Measured on the farmers screen at 390px: 15 controls starting from   */
/*  7 different left edges (12, 119, 151, 161, 167, 171, 175), in 10     */
/*  different widths from 73px to 261px, 13 of them stopping short of    */
/*  the right gutter. That is what reads as "scattered" - not any one    */
/*  control, but the absence of a shared edge.                           */
/*                                                                       */
/*  The fix is a two-column grid: every control starts on one of two     */
/*  lines, ends on one of two, and anything that deserves the full width */
/*  spans both. Nothing is left to flex-wrap's discretion.               */
/* ==================================================================== */

@media (max-width: 860px) {

  /* --- Filter bar ---------------------------------------------------- */
  .toolbar {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    align-items: stretch;
    margin-bottom: 16px;
  }
  /* min-width:130px was letting each control pick its own size; in a grid
     the track decides, and the control fills it. */
  .toolbar .select,
  .toolbar .input,
  .toolbar select,
  .toolbar .btn {
    width: 100%;
    min-width: 0;
  }
  /* Search reads across the whole width - it is the primary control and
     its placeholder needs the room. */
  .toolbar .search-wrap {
    grid-column: 1 / -1;
    width: 100%;
    max-width: none;
    flex: none;
  }
  .toolbar .search-wrap .input { width: 100%; }
  /* "Clear" is an action among filters. It keeps one column so it reads as
     secondary; spanning both made it look like a primary action. */
  .toolbar > .btn:last-child {
    grid-column: 1;
    justify-content: center;
  }

  /* --- Page header actions ------------------------------------------- */
  /* Two equal buttons per row, so "Register farmer" and "Add farmer" line
     up instead of sizing themselves to their text. */
  /* `.page-head .ph-actions` (two selectors) sets display:flex earlier in
     this file and outranks a bare `.ph-actions`, so the grid never applied
     and every button stretched to the full width. Matching that specificity
     is what makes the two-column layout stick. */
  .page-head .ph-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    width: 100%;
    margin-top: 4px;
  }
  .ph-actions > .btn,
  .ph-actions > a.btn {
    width: 100%;
    justify-content: center;
  }
  /* A lone trailing button spans both columns only when the total count is
     odd. `:last-child:nth-child(odd)` matched whenever the last item sat in
     an odd position, which with four buttons stretched every one of them to
     full width and cost most of the screen. These two rules match only a
     genuine odd total (3 or 5 items). */
  .ph-actions > :last-child:nth-child(3),
  .ph-actions > :last-child:nth-child(5) { grid-column: 1 / -1; }

  .page-head { display: block; }
  .page-head h1 { margin-bottom: 2px; }
  .page-head .sub { margin-bottom: 12px; }

  /* --- Cards: a calmer, Apple-like surface ---------------------------- */
  .card {
    border-radius: 16px;
  }
  .card + .card { margin-top: 12px; }

  /* --- Forms --------------------------------------------------------- */
  /* Labels and fields share the same left edge as everything else, and
     every field runs the full width - no half-width strays. */
  .form-grid,
  .form-grid-3,
  .f-tiles {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
  }
  .field,
  .f-tile {
    width: 100%;
    min-width: 0;
  }
  .field .input,
  .field select,
  .f-tile .input,
  .f-tile select {
    width: 100%;
  }
  /* Two short fields side by side read better than one per line when they
     are obviously a pair (from/to dates, PIN + state). */
  .form-row-2 {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }

  /* --- The closing action bar of a form ------------------------------- */
  .form-foot {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  .form-foot > .btn { width: 100%; justify-content: center; }
  .form-foot > :last-child:nth-child(3),
  .form-foot > :last-child:nth-child(5) { grid-column: 1 / -1; }
}

/* ==================================================================== */
/*  FLOATING CARDS  -  Apple jaisa look, saare pages par                 */
/*                                                                       */
/*  The cards were sitting flat on the page: --shadow-sm is 0 1px 2px at */
/*  6% opacity, which on a light background is very nearly invisible. A  */
/*  surface reads as lifted only when there are two shadows at once -    */
/*  a tight dark one right under the edge that defines the shape, and a  */
/*  much wider, softer one further down that suggests the distance to    */
/*  the page. Apple's surfaces are built exactly this way; a single      */
/*  blurred shadow always looks like a smudge instead of height.         */
/* ==================================================================== */

:root {
  /* Two-layer lift. The contact shadow is small and slightly stronger;
     the ambient one is large, soft and very light. */
  --lift:
    0 1px 2px rgba(16, 34, 24, .05),
    0 4px 10px -2px rgba(16, 34, 24, .07),
    0 12px 28px -8px rgba(16, 34, 24, .09);
  --lift-hover:
    0 2px 4px rgba(16, 34, 24, .06),
    0 8px 18px -4px rgba(16, 34, 24, .10),
    0 20px 44px -12px rgba(16, 34, 24, .13);
  /* A hairline of the brand colour around the card. Not a border: a ring
     sits outside the radius and keeps the corners perfectly round. */
  --halo: 0 0 0 1px rgba(22, 163, 74, .07);
  --halo-hover: 0 0 0 1px rgba(22, 163, 74, .16);
}

html[data-theme='dark'] {
  --lift:
    0 1px 2px rgba(0, 0, 0, .35),
    0 4px 10px -2px rgba(0, 0, 0, .40),
    0 12px 28px -8px rgba(0, 0, 0, .45);
  --lift-hover:
    0 2px 4px rgba(0, 0, 0, .40),
    0 8px 18px -4px rgba(0, 0, 0, .48),
    0 20px 44px -12px rgba(0, 0, 0, .55);
  --halo: 0 0 0 1px rgba(255, 255, 255, .06);
  --halo-hover: 0 0 0 1px rgba(134, 239, 172, .18);
}

/* --- Every card floats ------------------------------------------------ */
.card {
  box-shadow: var(--lift), var(--halo), var(--sheen);
  /* The border is replaced by the halo ring, which follows the radius
     exactly - a 1px border on a rounded corner always looks slightly
     squared off where it meets the curve. */
  border-color: transparent;
  transition: box-shadow .24s cubic-bezier(.22, .61, .36, 1),
              transform .24s cubic-bezier(.22, .61, .36, 1);
}
.card:hover {
  box-shadow: var(--lift-hover), var(--halo-hover), var(--sheen);
}

/* --- Stat tiles: the same lift, and they rise on hover ---------------- */
.stat {
  box-shadow: var(--lift), var(--halo), var(--sheen);
  border-color: transparent;
}
.stat:hover {
  transform: translateY(-3px);
  box-shadow: var(--lift-hover), var(--halo-hover), var(--sheen);
}

/* --- The tinted field panels inside forms ----------------------------- */
/* These are already coloured, so they get a lighter lift - enough to sit
   above the card, not so much that they compete with it. */
.f-tile {
  box-shadow:
    0 1px 2px rgba(16, 34, 24, .04),
    0 3px 8px -2px rgba(16, 34, 24, .06);
}

/* --- Modals sit highest of all ---------------------------------------- */
.modal-card,
.install-sheet-card {
  box-shadow:
    0 2px 6px rgba(16, 34, 24, .08),
    0 12px 28px -6px rgba(16, 34, 24, .16),
    0 32px 64px -16px rgba(16, 34, 24, .22),
    var(--halo);
}

/* --- Phone: a touch less lift ----------------------------------------- */
/* On a small screen the cards are close together and near the edges, so a
   desktop-sized shadow reads as muddy rather than elegant. */
@media (max-width: 860px) {
  :root {
    --lift:
      0 1px 2px rgba(16, 34, 24, .05),
      0 3px 8px -2px rgba(16, 34, 24, .06),
      0 8px 20px -6px rgba(16, 34, 24, .08);
  }
  /* Nothing hovers on a phone; the hover lift would only ever fire as a
     sticky state after a tap. */
  .card:hover, .stat:hover {
    transform: none;
    box-shadow: var(--lift), var(--halo), var(--sheen);
  }
  /* A little more air between floating cards so the shadows do not touch. */
  .stat + .stat,
  .card + .card { margin-top: 14px; }
  .grid > .stat { margin-top: 0; }
  .page .grid { gap: 14px; }
}

/* --- The three hero tiles ---------------------------------------------
   These float on the hero photograph as frosted glass. At 86% opacity the
   photo shows through, which on a phone - where the tiles are wide and the
   photo is busy - made the first tiles look dull and greyish next to the
   solid white ones below them. On a small screen they are made almost
   solid: the glass effect stays, the numbers stop competing with a field
   of wheat behind them. */
@media (max-width: 860px) {
  .hero-kpis .stat {
    background: rgba(255, 255, 255, .97);
    box-shadow: var(--lift), var(--halo), var(--sheen);
  }
  html[data-theme='dark'] .hero-kpis .stat {
    background: rgba(22, 30, 26, .97);
  }
}

/* On a wide screen the glass reads well, but it should lift like every
   other surface now does. */
@media (min-width: 861px) {
  .hero-kpis .stat {
    box-shadow:
      0 2px 6px rgba(var(--scrim), .10),
      0 10px 26px -6px rgba(var(--scrim), .18),
      var(--sheen);
  }
}

/* ==================================================================== */
/*  CARDS: asli float aur halka rang                                     */
/*                                                                       */
/*  Measured on the phone: the deepest shadow layer was only 8% opaque,  */
/*  which is present in the computed style but invisible to the eye on a */
/*  light page; and the tiles had bgImage "none", so no tint at all.     */
/*  An older rule was also zeroing the hero tiles' shadow outright       */
/*  (.hero-kpis .stat { box-shadow: none }) and repainting their         */
/*  coloured left border white.                                          */
/*                                                                       */
/*  So: a genuinely visible two-layer lift, and a soft wash of each      */
/*  tile's own colour from the left edge inward.                         */
/* ==================================================================== */

:root {
  --lift:
    0 1px 2px rgba(16, 34, 24, .07),
    0 6px 14px -3px rgba(16, 34, 24, .13),
    0 16px 34px -10px rgba(16, 34, 24, .16);
  --lift-hover:
    0 2px 5px rgba(16, 34, 24, .09),
    0 12px 24px -6px rgba(16, 34, 24, .17),
    0 26px 52px -14px rgba(16, 34, 24, .22);
}
html[data-theme='dark'] {
  --lift:
    0 1px 2px rgba(0, 0, 0, .45),
    0 6px 14px -3px rgba(0, 0, 0, .55),
    0 16px 34px -10px rgba(0, 0, 0, .60);
  --lift-hover:
    0 2px 5px rgba(0, 0, 0, .50),
    0 12px 24px -6px rgba(0, 0, 0, .62),
    0 26px 52px -14px rgba(0, 0, 0, .70);
}

/* --- A soft wash of the tile's own colour ------------------------------
   The tint fades in from the coloured left edge and is gone by ~55%, so
   the number sits on clean white and the colour reads as a hint, not a
   fill. Painted with a gradient rather than a flat background so the two
   never fight. */
.stat.brand {
  background-image: linear-gradient(100deg,
    rgba(22, 163, 74, .085) 0%, rgba(22, 163, 74, .028) 32%, rgba(22, 163, 74, 0) 58%);
}
.stat.give {
  background-image: linear-gradient(100deg,
    rgba(5, 150, 105, .085) 0%, rgba(5, 150, 105, .028) 32%, rgba(5, 150, 105, 0) 58%);
}
.stat.get {
  background-image: linear-gradient(100deg,
    rgba(220, 38, 38, .075) 0%, rgba(220, 38, 38, .025) 32%, rgba(220, 38, 38, 0) 58%);
}
html[data-theme='dark'] .stat.brand {
  background-image: linear-gradient(100deg,
    rgba(134, 239, 172, .10) 0%, rgba(134, 239, 172, .03) 32%, rgba(134, 239, 172, 0) 58%);
}
html[data-theme='dark'] .stat.give {
  background-image: linear-gradient(100deg,
    rgba(110, 231, 183, .10) 0%, rgba(110, 231, 183, .03) 32%, rgba(110, 231, 183, 0) 58%);
}
html[data-theme='dark'] .stat.get {
  background-image: linear-gradient(100deg,
    rgba(252, 165, 165, .10) 0%, rgba(252, 165, 165, .03) 32%, rgba(252, 165, 165, 0) 58%);
}

/* --- The hero tiles keep their colour and their lift -------------------
   An earlier rule set box-shadow:none here and let --glass-border repaint
   the coloured edge white; both are undone. */
.hero-kpis .stat {
  box-shadow: var(--lift), var(--halo), var(--sheen) !important;
  border-color: transparent;
}
.hero-kpis .stat.brand { border-left-color: var(--brand-600); }
.hero-kpis .stat.give  { border-left-color: var(--give); }
.hero-kpis .stat.get   { border-left-color: var(--get); }

/* Plain cards get a whisper of brand colour from the top edge, which is
   what stops a large white panel looking flat. */
.card {
  background-image: linear-gradient(180deg,
    rgba(22, 163, 74, .035) 0%, rgba(22, 163, 74, 0) 92px);
}
html[data-theme='dark'] .card {
  background-image: linear-gradient(180deg,
    rgba(134, 239, 172, .045) 0%, rgba(134, 239, 172, 0) 92px);
}

/* ==================================================================== */
/*  FLOAT: page ko peechhe le jaao, card ko aage                         */
/*                                                                       */
/*  Measured with real pixels: the shadow IS painted (RGB 203 under the  */
/*  card against 253 nearby). The reason it does not read as "floating"  */
/*  is contrast, not the shadow - the page was #f4f6f5 (244) and the     */
/*  card #ffffff (255), eleven levels apart. At that distance a white    */
/*  card on a near-white page is one flat surface whatever shadow it     */
/*  carries.                                                             */
/*                                                                       */
/*  Apple's surfaces work because the ground is clearly grey and the     */
/*  card is clearly white. So the page steps back, and the cards get a   */
/*  tint on all four sides instead of only the left edge.                */
/* ==================================================================== */

:root {
  /* A real grey ground, with the faintest green cast so it belongs to the
     brand rather than looking like unpainted chrome.
     Measured: at #e9eeeb the card-to-page step was 19 levels, still too
     close to read as separation. #dfe6e2 puts it near 30, which is where
     a white card starts to look genuinely lifted off the page. */
  --bg: #dfe6e2;
}
html[data-theme='dark'] {
  --bg: #080d0a;
}

/* --- Tint on all four sides ------------------------------------------
   The colour was a left-to-right wash, so it only ever showed down one
   edge. A radial tint anchored just outside the top-left corner reaches
   every side: strongest at the corner, fading out across the card, with
   the ring picking the colour up again all the way round. */
.stat.brand {
  background-image:
    radial-gradient(120% 130% at 0% 0%,
      rgba(22, 163, 74, .13) 0%, rgba(22, 163, 74, .05) 42%, rgba(22, 163, 74, 0) 78%);
  box-shadow: var(--lift), 0 0 0 1px rgba(22, 163, 74, .15), var(--sheen);
}
.stat.give {
  background-image:
    radial-gradient(120% 130% at 0% 0%,
      rgba(5, 150, 105, .13) 0%, rgba(5, 150, 105, .05) 42%, rgba(5, 150, 105, 0) 78%);
  box-shadow: var(--lift), 0 0 0 1px rgba(5, 150, 105, .15), var(--sheen);
}
.stat.get {
  background-image:
    radial-gradient(120% 130% at 0% 0%,
      rgba(220, 38, 38, .11) 0%, rgba(220, 38, 38, .04) 42%, rgba(220, 38, 38, 0) 78%);
  box-shadow: var(--lift), 0 0 0 1px rgba(220, 38, 38, .14), var(--sheen);
}
html[data-theme='dark'] .stat.brand {
  background-image: radial-gradient(120% 130% at 0% 0%,
    rgba(134, 239, 172, .14) 0%, rgba(134, 239, 172, .05) 42%, rgba(134, 239, 172, 0) 78%);
}
html[data-theme='dark'] .stat.give {
  background-image: radial-gradient(120% 130% at 0% 0%,
    rgba(110, 231, 183, .14) 0%, rgba(110, 231, 183, .05) 42%, rgba(110, 231, 183, 0) 78%);
}
html[data-theme='dark'] .stat.get {
  background-image: radial-gradient(120% 130% at 0% 0%,
    rgba(252, 165, 165, .14) 0%, rgba(252, 165, 165, .05) 42%, rgba(252, 165, 165, 0) 78%);
}

/* The same idea for plain cards: a soft corner tint rather than a band. */
.card {
  background-image:
    radial-gradient(110% 120% at 0% 0%,
      rgba(22, 163, 74, .055) 0%, rgba(22, 163, 74, .018) 40%, rgba(22, 163, 74, 0) 74%);
}
html[data-theme='dark'] .card {
  background-image:
    radial-gradient(110% 120% at 0% 0%,
      rgba(134, 239, 172, .06) 0%, rgba(134, 239, 172, .02) 40%, rgba(134, 239, 172, 0) 74%);
}

/* --- Room for the shadows to land ------------------------------------
   With cards 14px apart the next card started before the shadow had
   finished, so the gaps read as seams. */
@media (max-width: 860px) {
  .page .grid { gap: 18px; }
  .stat + .stat, .card + .card { margin-top: 18px; }
}

/* ==================================================================== */
/*  STAT TILES: chaaron taraf rang, har tone ke liye                     */
/*                                                                       */
/*  Earlier passes left this in three places and covered only three of   */
/*  the four tones - `.stat.amber` had a coloured left border but no     */
/*  tint at all, which is exactly the tile the owner pointed at. This    */
/*  block replaces all of it: one definition per tone, driven by a       */
/*  single custom property, so a new tone needs one line and can never   */
/*  again get a border without a tint.                                   */
/*                                                                       */
/*  The colour reaches all four sides three ways at once:                */
/*    - a hairline ring of the tone around the whole card                */
/*    - a soft radial wash from the top-left corner                      */
/*    - a gentle bottom-edge glow, so the lower half is not bare         */
/*  Each is deliberately faint; together they tint the card rather than  */
/*  colour it.                                                           */
/* ==================================================================== */

.stat {
  /* Every tone sets --tone; the rules below never name a colour again. */
  --tone: 22, 163, 74;            /* default: brand green, as RGB parts */
  position: relative;
  border-left: 0;                  /* the ring carries the colour now */
  background-color: var(--surface);
  background-image:
    radial-gradient(135% 120% at 0% 0%,
      rgba(var(--tone), .12) 0%,
      rgba(var(--tone), .045) 38%,
      rgba(var(--tone), 0) 72%),
    linear-gradient(0deg,
      rgba(var(--tone), .05) 0%,
      rgba(var(--tone), 0) 46%);
  box-shadow:
    var(--lift),
    0 0 0 1px rgba(var(--tone), .18),
    var(--sheen);
}

.stat.brand { --tone: 22, 163, 74; }    /* green   - totals */
.stat.give  { --tone: 5, 150, 105; }    /* teal    - money received */
.stat.get   { --tone: 220, 38, 38; }    /* red     - money outstanding */
.stat.amber { --tone: 217, 119, 6; }    /* amber   - pending / awaiting */

html[data-theme='dark'] .stat.brand { --tone: 134, 239, 172; }
html[data-theme='dark'] .stat.give  { --tone: 110, 231, 183; }
html[data-theme='dark'] .stat.get   { --tone: 252, 165, 165; }
html[data-theme='dark'] .stat.amber { --tone: 251, 191, 36; }

html[data-theme='dark'] .stat {
  background-image:
    radial-gradient(135% 120% at 0% 0%,
      rgba(var(--tone), .13) 0%,
      rgba(var(--tone), .05) 38%,
      rgba(var(--tone), 0) 72%),
    linear-gradient(0deg,
      rgba(var(--tone), .055) 0%,
      rgba(var(--tone), 0) 46%);
  box-shadow: var(--lift), 0 0 0 1px rgba(var(--tone), .22), var(--sheen);
}

/* The number keeps the tone's own colour where it carries meaning. */
.stat.amber .v { color: var(--amber-500); }

.stat:hover {
  box-shadow:
    var(--lift-hover),
    0 0 0 1px rgba(var(--tone), .32),
    var(--sheen);
}

/* Hero tiles sit on the photograph; same treatment, same tones. */
.hero-kpis .stat {
  border-left: 0;
  box-shadow:
    var(--lift),
    0 0 0 1px rgba(var(--tone), .20),
    var(--sheen) !important;
}

/* Plain cards get the brand tone, at half the strength - they are large
   surfaces and a tint that reads well on a small tile becomes a colour
   cast on a full-width card. */
.card {
  --tone: 22, 163, 74;
  background-image:
    radial-gradient(110% 115% at 0% 0%,
      rgba(var(--tone), .055) 0%,
      rgba(var(--tone), .02) 40%,
      rgba(var(--tone), 0) 72%),
    linear-gradient(0deg,
      rgba(var(--tone), .022) 0%,
      rgba(var(--tone), 0) 40%);
  box-shadow: var(--lift), 0 0 0 1px rgba(var(--tone), .10), var(--sheen);
}
html[data-theme='dark'] .card { --tone: 134, 239, 172; }

/* The old 3px left border is fully replaced by the ring, which reaches all
   four sides. A few tiles still had it because the earlier `.stat.get`,
   `.stat.give` and `.stat.amber` border rules sit later in this file than
   the `.stat { border-left: 0 }` above; naming them explicitly settles it. */
.stat.brand,
.stat.give,
.stat.get,
.stat.amber,
.hero-kpis .stat {
  border-left-width: 0;
  border-left-style: none;
}

/* --- Border ko dikhne layak banaya ------------------------------------
   The tone ring was at 18% on stat tiles and only 10% on plain cards. On
   a light page a 1px line at that strength is below the threshold where
   the eye registers an edge at all - the owner could not see it. Raised
   to 38% / 22%, and to 1.5px on the tiles so the colour has enough area
   to read. Still a hairline, just an honest one. */
.stat {
  box-shadow:
    var(--lift),
    0 0 0 1.5px rgba(var(--tone), .38),
    var(--sheen);
}
.stat:hover {
  box-shadow:
    var(--lift-hover),
    0 0 0 1.5px rgba(var(--tone), .52),
    var(--sheen);
}
html[data-theme='dark'] .stat {
  box-shadow:
    var(--lift),
    0 0 0 1.5px rgba(var(--tone), .42),
    var(--sheen);
}

.hero-kpis .stat {
  box-shadow:
    var(--lift),
    0 0 0 1.5px rgba(var(--tone), .38),
    var(--sheen) !important;
}

/* Plain cards are far larger, so their ring stays finer - a 1.5px coloured
   edge around a full-width panel would read as a box, not a card. */
.card {
  box-shadow:
    var(--lift),
    0 0 0 1px rgba(var(--tone), .22),
    var(--sheen);
}
.card:hover {
  box-shadow:
    var(--lift-hover),
    0 0 0 1px rgba(var(--tone), .34),
    var(--sheen);
}

/* ==================================================================== */
/*  DASHBOARD: approved mockup ke hisaab se                              */
/*                                                                       */
/*  Differences measured against the design:                             */
/*    - the sidebar is a deep green panel with foliage, not a white one  */
/*    - each stat carries a round icon badge in its own tone             */
/*    - each stat has a go-arrow and is a link                           */
/*    - the hero carries a date panel and three "pillars"                */
/* ==================================================================== */

/* --- Sidebar: deep green, with foliage at the foot ---------------------
   Applied at every width. This was written as a desktop-only block, which
   left the phone drawer white while the desktop rail was dark green — the
   same menu looking like two different products depending on the device. */
@media (min-width: 0px) {
  .sidebar {
    background:
      radial-gradient(150% 60% at 0% 100%, rgba(22, 163, 74, .30) 0%, rgba(22, 163, 74, 0) 62%),
      linear-gradient(168deg, #0d4a2a 0%, #0a3b21 46%, #07301b 100%);
    border-right: 0;
    box-shadow: 1px 0 0 rgba(255, 255, 255, .05);
  }

  /* Leaves along the bottom edge, drawn rather than loaded: an image here
     would be one more request for pure decoration. */
  .sidebar::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 190px;
    pointer-events: none;
    opacity: .5;
    background-repeat: no-repeat;
    background-position: -10px bottom, right -20px bottom, 40% bottom;
    background-size: 150px 150px, 130px 130px, 90px 90px;
    background-image:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M12 92C12 52 40 26 86 20 82 62 54 88 12 92Z' fill='%2334d399' opacity='.35'/%3E%3Cpath d='M14 90C34 62 54 44 84 26' stroke='%2386efac' stroke-width='2' fill='none' opacity='.5'/%3E%3C/svg%3E"),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M88 94C88 56 62 30 18 22 22 62 48 90 88 94Z' fill='%2322c55e' opacity='.28'/%3E%3C/svg%3E"),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M50 96C50 64 66 40 94 32 90 66 76 90 50 96Z' fill='%2386efac' opacity='.22'/%3E%3C/svg%3E");
  }

  /* Everything in the sidebar now sits on dark green. */
  .sidebar-brand.has-banner {
    background: rgba(255, 255, 255, .06);
    border-bottom: 1px solid rgba(255, 255, 255, .08);
  }
  .sidebar-brand.has-banner .bt   { color: #ffffff; }
  .sidebar-brand.has-banner .bs   { color: rgba(255, 255, 255, .72); }
  .sidebar-brand.has-banner .btag { color: #86efac; }

  .sidebar .nav-label        { color: rgba(255, 255, 255, .55); }
  .sidebar .nav-label::before { background: #4ade80; }
  .sidebar .nav-label .nl-ico { color: #86efac; }

  .sidebar .nav-item  { color: rgba(255, 255, 255, .82); }
  .sidebar .nav-item:hover {
    background: rgba(255, 255, 255, .08);
    color: #ffffff;
  }
  .sidebar .nav-item.active {
    background: linear-gradient(135deg, #16a34a 0%, #15803d 100%);
    color: #ffffff;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
  }
  .sidebar .nav-go { color: rgba(255, 255, 255, .5); }
  .sidebar .nav-item.active .nav-go { color: #ffffff; }

  /* The coloured tiles keep their hue but need a darker seat to read
     against the green panel. */
  .sidebar .nav-ico { background: rgba(255, 255, 255, .13) !important; color: #ffffff !important; }
  .sidebar .nav-ico[data-tone='green']  { color: #86efac !important; }
  .sidebar .nav-ico[data-tone='leaf']   { color: #bbf7d0 !important; }
  .sidebar .nav-ico[data-tone='amber']  { color: #fcd34d !important; }
  .sidebar .nav-ico[data-tone='blue']   { color: #93c5fd !important; }
  .sidebar .nav-ico[data-tone='violet'] { color: #c4b5fd !important; }
  .sidebar .nav-ico[data-tone='teal']   { color: #5eead4 !important; }
  .sidebar .nav-ico[data-tone='red']    { color: #fca5a5 !important; }
  .sidebar .nav-ico[data-tone='slate']  { color: #cbd5e1 !important; }
  .sidebar .nav-item.active .nav-ico {
    background: rgba(255, 255, 255, .22) !important;
    color: #ffffff !important;
  }

  /* The Registration group's own panel. */
  .sidebar .nav-group.is-boxed,
  .sidebar .nav-group.is-collapsible {
    background: rgba(255, 255, 255, .05);
    border-color: rgba(255, 255, 255, .09);
  }

  .sidebar-foot {
    background: rgba(0, 0, 0, .22);
    border-top: 1px solid rgba(255, 255, 255, .08);
  }
  .sidebar-foot .truncate { color: #ffffff; }
  .sidebar-foot .small.muted { color: rgba(255, 255, 255, .6); }
  .sidebar-foot .avatar {
    background: rgba(255, 255, 255, .15);
    color: #ffffff;
  }
  .sidebar-foot .btn-icon { color: rgba(255, 255, 255, .75); }
  .sidebar-foot .btn-icon:hover { background: rgba(255, 255, 255, .12); color: #fff; }

  .sidebar .nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .18); }
}

/* --- Stat tiles: icon badge, arrow, link ------------------------------- */
.stat {
  display: flex;
  /* The original .stat is a column of label/value/meta. Now that the tile
     has an icon on the left and an arrow on the right, the tile itself is
     a row and .stat-body is the column — without naming the direction here
     the earlier `flex-direction: column` kept winning and stacked the icon
     above the text. */
  flex-direction: row;
  align-items: center;
  gap: 13px;
}
.stat-body { flex: 1 1 auto; min-width: 0; display: grid; gap: 3px; }

.stat-ico {
  flex: 0 0 auto;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(var(--tone), .14);
  color: rgb(var(--tone));
  box-shadow: inset 0 0 0 1px rgba(var(--tone), .18);
  transition: transform .18s cubic-bezier(.22, .61, .36, 1);
}
.stat:hover .stat-ico { transform: scale(1.06); }

.stat-go {
  flex: 0 0 auto;
  display: grid; place-items: center;
  color: rgba(var(--tone), .55);
  transition: transform .18s ease, color .18s ease;
}
.stat.is-link:hover .stat-go { transform: translateX(3px); color: rgb(var(--tone)); }

.stat.is-link { text-decoration: none; color: inherit; cursor: pointer; }
.stat.is-link:hover { text-decoration: none; }

/* --- Hero: date panel and the three pillars ---------------------------- */
.hero-date {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .90);
  box-shadow: 0 4px 14px rgba(var(--scrim), .18);
  color: var(--text);
}
.hero-date .stack { display: grid; gap: 0; line-height: 1.25; }
.hero-date strong { font-size: 13.5px; font-weight: 700; }
.hero-date span   { font-size: 11.5px; color: var(--text-3); }
.hero-date svg    { color: var(--brand-600); flex: 0 0 auto; }

.hero-pillars {
  display: flex; flex-wrap: wrap;
  gap: 8px 22px;
  margin-top: 14px;
}
.hero-pillars span {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13.5px; font-weight: 600;
  color: rgba(255, 255, 255, .92);
}
.hero-pillars svg { color: #86efac; }

.dash-hero .hi-name { color: #86efac; }

/* Phone: the pillars wrap to two lines and the date panel goes first. */
@media (max-width: 860px) {
  .hero-pillars { gap: 6px 16px; margin-top: 12px; }
  .hero-pillars span { font-size: 12.5px; }
  .hero-date { grid-column: 1 / -1; justify-content: center; }
  .stat-ico { width: 38px; height: 38px; }
  .stat { gap: 11px; }
}

/* --- Sparkline: a sense of direction behind the number ----------------- */
.stat-spark {
  flex: 0 0 auto;
  width: 78px; height: 34px;
  align-self: center;
  overflow: visible;
}
.stat-spark .sp-line {
  fill: none;
  stroke: rgb(var(--tone));
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .85;
}
.stat-spark .sp-area {
  fill: rgba(var(--tone), .14);
  stroke: none;
}

/* On a phone the tile is already tight; the number and its label matter
   more than the trend, so the line steps aside. */
@media (max-width: 720px) {
  .stat-spark { display: none; }
}

/* ==================================================================== */
/*  MOCKUP KE HISAAB SE: bhare hue icons, rangin cards                   */
/*                                                                       */
/*  Three differences measured against the approved design:              */
/*    - icon badges are solid colour with a white glyph, not a pale      */
/*      tint with a coloured glyph                                       */
/*    - the three headline cards carry a full-card wash, and the middle  */
/*      one is BLUE, not green                                           */
/*    - the sidebar tiles are dark green, and only the glyph is tinted   */
/* ==================================================================== */

/* --- Icon badges: solid, white glyph ----------------------------------- */
.stat-ico {
  background: linear-gradient(140deg,
    rgb(var(--tone)) 0%,
    rgba(var(--tone), .82) 100%);
  color: #ffffff;
  box-shadow:
    0 2px 6px rgba(var(--tone), .34),
    inset 0 1px 0 rgba(255, 255, 255, .28);
}
.stat-ico svg { stroke-width: 2.1; }

/* --- A blue tone, for money that has arrived --------------------------- */
/* The design uses blue for "received": it separates money in from money
   committed, which two greens could not do. */
.stat.info { --tone: 37, 99, 235; }
.stat.info .v { color: #1d4ed8; }
html[data-theme='dark'] .stat.info { --tone: 147, 197, 253; }
html[data-theme='dark'] .stat.info .v { color: #93c5fd; }

/* --- Headline cards: a full wash, as in the design --------------------- */
/* The three top tiles are tinted across the whole card rather than only
   at one corner — they are the loudest numbers on the page and the design
   gives them that weight. */
.grid-3 > .stat {
  background-image:
    linear-gradient(135deg,
      rgba(var(--tone), .10) 0%,
      rgba(var(--tone), .045) 52%,
      rgba(var(--tone), .02) 100%);
}

/* --- Sparkline: filled, reaching the card's edge ------------------------ */
.stat-spark {
  width: 104px; height: 44px;
  margin-right: -6px;
}
.stat-spark .sp-area { fill: rgba(var(--tone), .22); }
.stat-spark .sp-line { stroke-width: 2.2; opacity: .95; }

/* --- Sidebar tiles: dark green seat, tinted glyph ----------------------- */
@media (min-width: 0px) {
  .sidebar .nav-ico {
    background: rgba(255, 255, 255, .07) !important;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .09);
  }
  .sidebar .nav-txt {
    color: #ffffff;
    font-weight: 600;
  }
  .sidebar .nav-item.active .nav-txt { font-weight: 700; }

  /* The Registration group reads as an outlined panel. */
  .sidebar .nav-group.is-collapsible {
    border: 1px solid rgba(134, 239, 172, .28);
    background: rgba(255, 255, 255, .04);
    border-radius: 14px;
  }
  .sidebar .nav-toggle .nav-txt,
  .sidebar .nav-toggle > span { color: #ffffff; font-weight: 650; }
}

/* --- Commission card: the seedling, as in the design -------------------
   Drawn as an inline SVG background rather than loaded: it is decoration,
   and one more network request for decoration is not worth it on a 2G
   connection. Sits behind the content, fading out to the left so the
   number is never competing with it. */
.stat.is-commission {
  position: relative;
  overflow: hidden;
}
.stat.is-commission::after {
  content: '';
  position: absolute;
  right: 0; bottom: 0;
  width: 132px; height: 100%;
  pointer-events: none;
  opacity: .92;
  background-repeat: no-repeat;
  background-position: right bottom;
  background-size: 128px auto;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 96'%3E%3Cellipse cx='84' cy='86' rx='42' ry='9' fill='%23a16207' opacity='.22'/%3E%3Cg%3E%3Ccircle cx='58' cy='84' r='7' fill='%23fbbf24' stroke='%23d97706' stroke-width='1.2'/%3E%3Ccircle cx='72' cy='86' r='7' fill='%23fcd34d' stroke='%23d97706' stroke-width='1.2'/%3E%3Ccircle cx='65' cy='76' r='7' fill='%23fde68a' stroke='%23d97706' stroke-width='1.2'/%3E%3C/g%3E%3Cpath d='M92 88V52' stroke='%2315803d' stroke-width='3' stroke-linecap='round'/%3E%3Cpath d='M92 62C92 62 78 60 74 46 88 44 92 54 92 62Z' fill='%2322c55e'/%3E%3Cpath d='M92 56C92 56 104 52 106 38 94 38 90 48 92 56Z' fill='%234ade80'/%3E%3Cpath d='M92 46C92 46 84 38 88 26 98 32 96 40 92 46Z' fill='%2386efac'/%3E%3C/svg%3E");
}
/* The tint stops before the artwork so the two never overlap awkwardly. */
.stat.is-commission .stat-body { position: relative; z-index: 1; }

@media (max-width: 860px) {
  /* On a phone the tile is narrow; the seedling shrinks rather than
     crowding the number. */
  .stat.is-commission::after { width: 92px; background-size: 88px auto; opacity: .8; }
}

/* --- Tables must never widen the page ---------------------------------
   Measured on the dashboard at 390px: a 560px table inside a .table-wrap
   still dragged the page to 510px. The scroller was capped at 100%, but
   its grid parent sizes to min-content by default, so "100%" resolved to
   the table's own width rather than the screen's. The tracks and the flex
   children have to be allowed to shrink first.

   This is the same `minmax(0, 1fr)` fault fixed earlier for cards — it
   reappears wherever a new wide child lands in a grid. */
/* No column override here. An earlier attempt set `.page .grid` to a single
   column to stop a wide table pushing the page sideways — but `.page .grid`
   is two selectors and outranks the `.grid-3` that restores three columns on
   a desktop, so every dashboard grid collapsed to one card per row.
   The overflow is already handled by the min-width:0 rules below, which is
   the correct fix: let the tracks shrink, do not change how many there are. */

/* Every card and its body must be allowed to be narrower than its content;
   without this a wide table inside keeps the card wide. */
.page .grid > *,
.card,
.card-body,
.table-wrap {
  min-width: 0;
  max-width: 100%;
}

/* The scroller owns the overflow at every width, not just on a phone. */
.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}

/* ==================================================================== */
/*  TOP BAR: approved design                                             */
/*                                                                       */
/*  The bar was a plain white strip with a hamburger and two toggles.    */
/*  The design asks for a floating rounded panel on a soft green ground  */
/*  with foliage at both ends, the brand at the left, and grouped        */
/*  controls at the right: language, notifications, theme, settings and  */
/*  the signed-in user.                                                  */
/* ==================================================================== */

.topbar {
  /* A floating panel, not a full-width strip: it sits inside the page
     with air around it, which is what makes it read as a surface. */
  height: auto;
  min-height: 58px;
  margin: 12px 14px 0;
  padding: 8px 12px;
  border-radius: 18px;
  border-bottom: 0;
  gap: 10px;

  background:
    linear-gradient(180deg, rgba(255, 255, 255, .96) 0%, rgba(247, 252, 249, .96) 100%);
  box-shadow:
    0 1px 2px rgba(16, 34, 24, .05),
    0 6px 16px -4px rgba(16, 34, 24, .10),
    0 18px 38px -12px rgba(16, 34, 24, .13),
    0 0 0 1px rgba(22, 163, 74, .10);

  position: sticky;
  top: 12px;
  z-index: 30;
  overflow: hidden;
}
html[data-theme='dark'] .topbar {
  background: linear-gradient(180deg, rgba(26, 35, 30, .96) 0%, rgba(21, 29, 25, .96) 100%);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, .40),
    0 6px 16px -4px rgba(0, 0, 0, .50),
    0 18px 38px -12px rgba(0, 0, 0, .55),
    0 0 0 1px rgba(255, 255, 255, .06);
}

/* Foliage at both ends, drawn rather than loaded — decoration is not
   worth a network request on a village connection. */
.topbar::before,
.topbar::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 108px;
  pointer-events: none;
  opacity: .5;
  background-repeat: no-repeat;
  background-size: 104px auto;
}
.topbar::before {
  left: 0;
  background-position: left center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 104 60'%3E%3Cpath d='M2 12C2 12 26 6 38 20 24 30 8 24 2 12Z' fill='%2334d399' opacity='.5'/%3E%3Cpath d='M10 44C10 44 30 34 44 44 32 54 16 52 10 44Z' fill='%2322c55e' opacity='.42'/%3E%3Cpath d='M0 30C0 30 16 24 26 32 16 40 4 38 0 30Z' fill='%2386efac' opacity='.5'/%3E%3C/svg%3E");
}
.topbar::after {
  right: 0;
  background-position: right center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 104 60'%3E%3Cpath d='M102 12C102 12 78 6 66 20 80 30 96 24 102 12Z' fill='%2334d399' opacity='.5'/%3E%3Cpath d='M94 44C94 44 74 34 60 44 72 54 88 52 94 44Z' fill='%2322c55e' opacity='.42'/%3E%3Cpath d='M104 30C104 30 88 24 78 32 88 40 100 38 104 30Z' fill='%2386efac' opacity='.5'/%3E%3C/svg%3E");
}
/* Everything real sits above the leaves. */
.topbar > * { position: relative; z-index: 1; }

/* --- Brand: shown at every width now ----------------------------------- */
.topbar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 0 1 auto;
  padding-right: 12px;
  border-right: 1px solid var(--border);
}
.topbar-brand img {
  width: 36px; height: 36px; flex: 0 0 36px;
  object-fit: contain;
}
.topbar-brand .tb-text { display: grid; gap: 0; line-height: 1.2; min-width: 0; }
.topbar-brand .tb-text strong {
  font-size: 14.5px; font-weight: 800; letter-spacing: -.2px;
  color: var(--brand-900);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-brand .tb-text span {
  font-size: 11.5px; color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
html[data-theme='dark'] .topbar-brand .tb-text strong { color: #eaf6ef; }

/* --- Language: one control that states the current language ------------- */
.tb-lang {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 12px;
  border-radius: 11px;
  font-size: 13.5px; font-weight: 600;
  color: var(--brand-700);
  background: rgba(22, 163, 74, .07);
}
.tb-lang:hover { background: rgba(22, 163, 74, .13); }
.tb-lang svg:last-child { opacity: .6; }
html[data-theme='dark'] .tb-lang { color: var(--brand-200); background: rgba(134, 239, 172, .10); }

/* --- Notification bell and its dot -------------------------------------- */
.tb-bell { position: relative; }
.tb-dot {
  position: absolute;
  top: 7px; right: 7px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--get);
  box-shadow: 0 0 0 2px var(--surface);
  font-size: 0;            /* the count is for the sidebar badges, not here */
}
html[data-theme='dark'] .tb-dot { box-shadow: 0 0 0 2px #1a231e; }

/* --- Divider and the signed-in user ------------------------------------- */
.tb-sep {
  width: 1px; height: 26px;
  background: var(--border);
  flex: 0 0 auto;
  margin: 0 2px;
}
.tb-user {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px 5px 5px;
  border-radius: 999px;
}
.tb-avatar {
  width: 32px; height: 32px;
  flex: 0 0 32px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(140deg, var(--brand-600) 0%, var(--brand-700) 100%);
  color: #fff;
  font-size: 12.5px; font-weight: 700;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22);
}
.tb-user svg { opacity: .55; }

/* The page starts under the floating bar, not against it. */
.topbar + #pageHost > .page { padding-top: 16px; }

/* --- Phone: keep the brand, trim the rest ------------------------------- */
@media (max-width: 860px) {
  .topbar {
    margin: 8px 10px 0;
    padding: 7px 9px;
    border-radius: 15px;
    gap: 7px;
    top: 8px;
  }
  /* The leaves need width the phone does not have. */
  .topbar::before, .topbar::after { display: none; }

  .topbar-brand { padding-right: 8px; gap: 7px; }
  .topbar-brand img { width: 30px; height: 30px; flex-basis: 30px; }
  .topbar-brand .tb-text strong { font-size: 13px; }
  .topbar-brand .tb-text span { display: none; }

  /* Language collapses to the globe; the word costs room the brand needs. */
  .tb-lang { padding: 8px; gap: 0; }
  .tb-lang span, .tb-lang svg:last-child { display: none; }

  .tb-sep { display: none; }
  .tb-user { padding: 4px; }
  .tb-user svg { display: none; }
  .tb-avatar { width: 30px; height: 30px; flex-basis: 30px; }
}

/* Superseded by the 360px rule further down — 420px also caught the common
   390px phone, where the name does fit and the bar needs it. */

/* --- Phone: the brand name earns its place back ------------------------
   Measured at 390px: hiding the brand text left the bar as a row of six
   anonymous icons, which tells a user nothing about where they are. The
   search pill is already collapsed to an icon here, so there IS room —
   the settings gear is the one control that can wait behind the sidebar,
   and dropping it buys the brand its name. */
@media (max-width: 860px) {
  .topbar-brand .tb-text { display: grid; }
  .topbar-brand .tb-text strong {
    font-size: 12.5px;
    max-width: 128px;
  }
}
@media (max-width: 360px) {
  /* Only on the narrowest phones does the name have to go. At 390px —
     the most common size — there is room, and an earlier 420px breakpoint
     was hiding it there too, leaving a row of anonymous icons. */
  .topbar-brand .tb-text { display: none; }
  .topbar-brand { border-right: 0; padding-right: 0; }
}

/* --- Phone: fewer controls, so the brand has room ----------------------
   Measured at 390px: six icon buttons plus search left the brand exactly
   0px. Both of these live elsewhere already — settings is in the sidebar,
   and the theme toggle is a preference set once — so on a phone they step
   aside and the app finally says its own name. */
@media (max-width: 860px) {
  .topbar #themeBtn { display: none; }
  .topbar > .btn-ghost.btn-icon[title]:not(.hamburger):not(.tb-bell) { display: none; }

  /* Brand takes what the removed controls gave back. */
  .topbar-brand { flex: 1 1 auto; min-width: 0; }
  .topbar-brand .tb-text strong { max-width: none; }
  /* Search keeps its collapsed icon and only expands when tapped. */
  .topbar .search-wrap { flex: 0 0 40px; }
}

/* --- Phone: the short name, not the legal one --------------------------
   "HM AGRI ONE INDIA LLP" needs ~150px and the bar can spare ~104px, so
   it came out as "HM AG…". A truncated name is worse than a shorter one,
   so the phone shows the app's own short name instead. The full legal
   name is still in the sidebar, where there is room for it. */
@media (max-width: 860px) {
  /* Measured: the brand gets ~104px on a 390px phone. "HM Agri One" needs
     more than that and came out as "HM Agri", so the name is set on two
     lines, which fits and stays whole. */
  /* The short name replaces the registered one; both are in the markup and
     CSS picks. Generated content was tried first and mangled the Hindi and
     the escaped space — real elements are simply more reliable. */
  .topbar-brand .tb-full  { display: none; }
  .topbar-brand .tb-short { display: block; font-size: 13px; }
}

/* On a wide screen the registered name is shown and the short one hides. */
@media (min-width: 861px) {
  .topbar-brand .tb-short { display: none; }
  .topbar-brand .tb-full  { display: block; }
}

/* --- Sidebar icons: the tone fills the tile, not just the glyph ---------
   Measured: the glyph colours were correct (green, amber, violet) but the
   tile behind them was rgba(255,255,255,.07) — so faint on dark green that
   the colour never registered. The design fills each tile with its own
   tone and puts a white glyph on top, which is what makes the list
   scannable by colour. Every width: the phone drawer is the same panel. */
@media (min-width: 0px) {
  .sidebar .nav-ico {
    background: rgba(var(--ico-tone), .92) !important;
    color: #ffffff !important;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .22),
      0 2px 6px rgba(0, 0, 0, .28);
  }
  .sidebar .nav-ico svg { stroke-width: 2.1; }

  /* One variable per tone; the rule above never names a colour.
     `color: #fff` is repeated on each because the pale-tile rules earlier
     in this file are `.nav-ico[data-tone=…]` — the same specificity as a
     bare `.sidebar .nav-ico` — and being later in the file they won, which
     left dark glyphs on the now-saturated tiles. */
  .sidebar .nav-ico[data-tone='green']  { --ico-tone: 22, 163, 74;  color: #fff !important; }
  .sidebar .nav-ico[data-tone='leaf']   { --ico-tone: 77, 152, 44;  color: #fff !important; }
  .sidebar .nav-ico[data-tone='amber']  { --ico-tone: 217, 119, 6;  color: #fff !important; }
  .sidebar .nav-ico[data-tone='blue']   { --ico-tone: 37, 99, 235;  color: #fff !important; }
  .sidebar .nav-ico[data-tone='violet'] { --ico-tone: 109, 40, 217; color: #fff !important; }
  .sidebar .nav-ico[data-tone='teal']   { --ico-tone: 13, 148, 136; color: #fff !important; }
  .sidebar .nav-ico[data-tone='red']    { --ico-tone: 220, 38, 38;  color: #fff !important; }
  .sidebar .nav-ico[data-tone='slate']  { --ico-tone: 71, 85, 105;  color: #fff !important; }

  /* The active row already sits on a green pill; a second filled tile on
     top of it would be one green too many. */
  .sidebar .nav-item.active .nav-ico {
    background: rgba(255, 255, 255, .24) !important;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3);
  }
}

/* The phone drawer is the same dark panel, so it gets the same treatment. */
@media (max-width: 860px) {
  .sidebar .nav-ico svg { stroke-width: 2.05; }
}

/* ==================================================================== */
/*  QUICK ADD FARMER: the RTO code field                                 */
/*                                                                       */
/*  The code is the one thing typed before anything else works, so it is */
/*  given the weight of a headline field: wide letter spacing, uppercase */
/*  and a monospaced feel, so "UP72" reads as a code rather than a word. */
/* ==================================================================== */

.rto-row {
  display: flex;
  align-items: flex-end;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.rto-row > .field { flex: 0 0 auto; min-width: 190px; }

.rto-input {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  text-align: center;
  min-height: 52px;
}

.rto-result {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 14px;
}
.rto-hit {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 14px;
  border-radius: 11px;
  background: rgba(22, 163, 74, .10);
  color: var(--brand-700);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px rgba(22, 163, 74, .22);
}
.rto-hit strong { font-weight: 750; }
.rto-miss {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 14px;
  border-radius: 11px;
  background: rgba(217, 119, 6, .10);
  color: var(--amber-500);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px rgba(217, 119, 6, .22);
}
.rto-wait { color: var(--text-3); font-size: 13px; }

html[data-theme='dark'] .rto-hit  { color: var(--brand-200); }
html[data-theme='dark'] .rto-miss { color: #fcd34d; }

@media (max-width: 860px) {
  /* The code field takes the whole row on a phone; the result sits under it
     rather than beside, where it would be squeezed to two words. */
  .rto-row { gap: 10px; }
  .rto-row > .field { flex: 1 1 100%; min-width: 0; }
  .rto-result { flex: 1 1 100%; }
  .rto-input { font-size: 18px; min-height: 48px; }
}
