/* ==========================================================================
   00  FONTS — self-hosted, Latin subset only
   No Google Fonts request. This app runs on a NAS with no guaranteed
   connectivity at the chute; a blocking external font request is a blank
   screen. Files live in static/fonts/. font-display:swap avoids invisible
   text while they load. Inter Tight ships as one variable-weight file
   (wght axis 100–900) covering all four weights used here, so a single
   @font-face with a weight range replaces four static files.
   ========================================================================== */
@font-face{
  font-family:"Barlow Condensed";
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url("fonts/barlow-condensed-600.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"Barlow Condensed";
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url("fonts/barlow-condensed-700.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"Inter Tight";
  font-style:normal;
  font-weight:400 700;
  font-display:swap;
  src:url("fonts/inter-tight-variable.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"IBM Plex Mono";
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-500.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"IBM Plex Mono";
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-600.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}


/* ==========================================================================
   HEADGATE DESIGN SYSTEM — v3.0
   Replaces static/style.css in full. Do not append to this file.

   RULES FOR ANYONE EDITING THIS FILE, INCLUDING FUTURE CLAUDE:

   1. No version-dated layers. The old file grew to 2,832 lines across 32
      appended blocks (v1.0.2 … v2.19.2c), each patching the last.
      That is how .hero-command ended up defined eight times. If a rule is
      wrong, change the rule. Do not add a later one that wins.

   2. No hardcoded colour. Every colour is a token in :root. The old file had
      381 unique hex values against 60 token uses. If you need a colour that
      is not here, add a token and say what it means.

   3. No !important. The old file had 178. Every one of them is a specificity
      argument that was lost. If you need !important, the selector above it is
      wrong. The single exception is the reduced-motion block at the bottom,
      where overriding author styles is the entire point.

   4. Section order is load-bearing. Tokens, then base, then components, then
      layout, then responsive, then the legacy shim. The shim is last on
      purpose and is the only place allowed to reference dead class names.

   ORGANISATION
     01  Tokens
     02  Base and reset
     03  Typography
     04  Ear tag chip (signature element)
     05  Buttons
     06  Forms
     07  Tables
     08  Cards and panels
     09  Status pills, badges, flashes
     10  App shell — sidebar, topbar, footer
     11  Dashboard — today band, stats, charts
     12  Phone and PWA
     13  Chute mode
     14  Utilities
     15  Responsive
     16  Legacy compatibility shim
     17  Print and accessibility

   Sections 18+ are per-feature additions made after the v3.0 rewrite, in
   the order each feature shipped. Same rules apply: tokens, not hex; no
   !important; reuse .pill/.card/.btn/--warn-tint etc. before inventing a
   new pattern. Add a new numbered section for a genuinely new feature
   area; do not append loose rules after the legacy shim.
     18  Working cattle session
     19  Animal profile
     20  Admin portal (2.29.4c)
     21  Settings
     22  Calving
     23  Vaccines & medications
     24  Calendar
     25  Pastures
     26  Hay inventory
     27  Purchasing
     28  Sales
     29  Reports
     30  Business hub
   ========================================================================== */


/* ==========================================================================
   01  TOKENS
   ========================================================================== */
:root{
  /* --- surface ------------------------------------------------------- */
  --ink:#141A17;
  --ink-2:#3A443E;
  /* #69726C on --paper was 4.49:1 — a hair under the 4.5:1 floor. Darkened
     to #69716B (imperceptible) so it clears on both --card and --paper. */
  --muted:#69716B;
  --paper:#F2F4EF;
  --card:#FFFFFF;
  /* V-03. Was #DEE3DA -- 1.18:1 against --paper, which is decoration indoors
     and gone in direct sun. These lines separate one animal's row from the
     next, so they have to survive being read in a chute.
     #AEB7A8 is 1.87:1. WCAG 1.4.11 asks 3:1 for UI boundaries and #848E7D
     would meet it, but 3:1 on every hairline rules the whole interface like
     a ledger. Row dividers are not required to understand the content -- the
     rows are also separated by spacing -- so the stronger value is held back
     for borders that carry state. */
  --line:#AEB7A8;
  --line-2:#EDF0EA;

  /* --- brand --------------------------------------------------------- */
  /* base.html sets --brand-primary / --brand-accent inline per tenant.
     These fall back to Headgate's own palette when a ranch has not set
     its own, so a white-label deploy needs no stylesheet change. */
  --brand:var(--brand-primary,#0E5240);
  --brand-2:#0A3E30;
  --brand-tint:#E7F0EC;
  --brand-on:#FFFFFF;

  /* --- ear tag colours ----------------------------------------------- */
  /* These are data, not theme. A tag colour identifies a herd group in the
     pen; the interface uses the same colours so the screen matches the
     animal. Do not repurpose them for decoration. */
  --tag-yellow:#F2C230;  --tag-yellow-ink:#3B2E00;
  --tag-green:#4F9A3F;   --tag-green-ink:#0E2A0A;
  --tag-orange:#E0651B;  --tag-orange-ink:#3A1500;
  --tag-blue:#2F6FB0;    --tag-blue-ink:#08203A;
  --tag-red:#C0392B;     --tag-red-ink:#340B07;
  --tag-white:#FFFFFF;   --tag-white-ink:#2A2A2A;

  /* --- state --------------------------------------------------------- */
  /* alert = money at risk right now (withdrawal active, overdue step)
     warn  = money at risk soon    (withdrawal closing, due today)
     ok    = clear                                                        */
  --alert:#B3261E;  --alert-2:#8E1E17;  --alert-tint:#FBEBEA;  --alert-edge:#F0CDCA;
  --warn:#8A6100;   --warn-tint:#FDF5DF;  --warn-edge:#F2C230;  --warn-edge-soft:#EEDCA8;
  --ok:#2E6B3E;     --ok-tint:#E9F3EA;    --ok-edge:#C7E0CC;
  --info:#1F5C8B;   --info-tint:#E8F1F8;  --info-edge:#C7DCEC;

  /* --- interactive ----------------------------------------------------- */
  /* Hover border on inputs/choices/chips, and placeholder text. Not a
     semantic state colour, just a step darker than --line for hover. */
  --line-hover:#C6CEC2;
  --placeholder:#9BA39D;

  /* --- sidebar (dark surface) ------------------------------------------ */
  /* Text and accent colours for the sidebar's own dark-green surface. Not
     usable on --paper or --card; they only have contrast against --brand-2. */
  --sidebar-text:#EAF1EE;
  --sidebar-text-dim:#D3E2DC;
  --sidebar-muted:#8FB3A6;
  /* #6F978A on --brand-2 was 3.71:1, below the 4.5:1 floor for the nav-group
     labels it's used on. Lightened to #83A69A to clear it. */
  --sidebar-muted-2:#83A69A;
  --sidebar-avatar-bg:#1C6A54;
  --sidebar-avatar-ink:#CFE6DD;

  /* --- chute mode (dark surface) ----------------------------------------- */
  /* Its own dark-ground micro-palette per section 13. Not usable on
     --paper or --card. */
  --chute-muted:#8B958F;
  --chute-card:#1E2723;
  --chute-card-line:#2E3833;
  --chute-chip-bg:#2A342F;
  --chute-chip-line:#3A453F;
  --chute-chip-ink:#D6DEDA;
  --chute-chip-hover:#354039;
  --chute-go-hover:#E5B520;
  --chute-ok:#4CAF6B;
  --chute-alert:#E2685B;

  /* --- calendar event categories --------------------------------------- */
  /* Task/AI/Health/Maintenance dots reuse --brand/--info/--warn-edge/--muted
     since they already carry the right meaning; Calving and Preg Check are
     their own event types with no existing semantic token to borrow, so
     they each get one named colour rather than a bare hex sitting in the
     component rule. */
  --cal-calving:#C2568B;
  --cal-pregcheck:#5B7FC7;

  /* --- print ------------------------------------------------------------ */
  --print-border:#999999;
  --print-th-bg:#EEEEEE;
  --print-ink:#000000;

  /* --- type ---------------------------------------------------------- */
  --display:"Barlow Condensed","Arial Narrow",Impact,sans-serif;
  --ui:"Inter Tight",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,monospace;

  --t-xs:11px; --t-sm:12.5px; --t-md:13.5px; --t-lg:15px; --t-xl:18px;
  /* V-02: was 10.5px. Set through the `font` shorthand, so the first pass --
     which searched for font-size: -- missed it, and the Email/Password
     labels on the login screen stayed below the caption floor. Uppercase
     tracked text is the hardest thing on the page to read in sun. */
  --label:600 11px/1.2 var(--ui);   /* uppercase eyebrow label */
  --label-track:.11em;

  /* --- geometry ------------------------------------------------------ */
  --r-sm:6px; --r:10px; --r-lg:14px; --r-pill:99px;
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px;
  --shadow:0 1px 2px rgba(20,26,23,.05), 0 4px 16px rgba(20,26,23,.05);
  --shadow-lg:0 8px 32px -8px rgba(20,26,23,.18);

  /* --- ergonomics ---------------------------------------------------- */
  /* 44px is Apple's minimum. 54px is what a gloved thumb needs, and is used
     for anything tapped while an animal is in the chute. */
  --tap:44px;
  --tap-glove:54px;

  --sidebar-w:264px;
  --topbar-h:56px;
  --safe-top:env(safe-area-inset-top,0px);
  --safe-bottom:env(safe-area-inset-bottom,0px);

  /* --- hub hero band --------------------------------------------------- */
  /* One shared dark-surface treatment for every top-level hub's desktop
     header (Today/Work/Land/Business) so they read as one product instead
     of four independently hand-tuned gradients. Do not add a fifth. */
  --hero-grad:
    radial-gradient(circle at 82% 20%,rgba(205,174,104,.24),transparent 31%),
    linear-gradient(125deg,var(--brand-2),#123f34 72%,#183a32);
  --hero-shadow:0 16px 36px rgba(10,42,34,.16);
  --hero-eyebrow:#bcd0c8;
  --hero-body:#d9e6e1;
  --hero-glass-bg:rgba(255,255,255,.1);
  --hero-glass-border:rgba(255,255,255,.24);
  --hero-glass-bg-hover:rgba(255,255,255,.17);
}


/* ==========================================================================
   02  BASE AND RESET
   ========================================================================== */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--ui);font-size:var(--t-md);line-height:1.45;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
img,svg{max-width:100%}
button{font:inherit;color:inherit;cursor:pointer}
a{color:var(--brand);text-decoration:none}
a:hover{text-decoration:underline}
hr{border:0;border-top:1px solid var(--line-2);margin:var(--s4) 0}

:focus-visible{
  outline:2px solid var(--brand);outline-offset:2px;border-radius:var(--r-sm);
}
/* The default brand-green outline is close to invisible on the app's own
   brand-green surfaces -- confirmed by contrast ratio (~1.3:1 against the
   sidebar, an exact color match against the chute header), nowhere near
   WCAG's 3:1 minimum for a focus indicator. Every surface that's brand-
   green, brand-2, or the shared hero gradient gets a light outline
   instead, scoped locally so nothing else on the page is affected. */
.app-sidebar :focus-visible,
.chute-head :focus-visible,
.command-hero :focus-visible,
.field-hero :focus-visible,
.land-hero :focus-visible,
.business-hero :focus-visible{
  outline-color:var(--brand-on);
}
.visually-hidden{
  position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  white-space:nowrap;
}
.skip-link{
  position:fixed;left:var(--s3);top:0;z-index:100;transform:translateY(-160%);
  background:var(--card);padding:var(--s3) var(--s4);border-radius:var(--r-sm);
  box-shadow:var(--shadow-lg);font-weight:600;
}
.skip-link:focus{top:var(--s3);transform:none}


/* ==========================================================================
   03  TYPOGRAPHY
   ========================================================================== */
h1,h2,h3,h4,h5{margin:0;font-weight:600;letter-spacing:-.01em;line-height:1.2}
h1{font-size:24px}
h2{font-size:19px}
h3{font-size:15px}
h4{font-size:var(--t-md)}
p{margin:0 0 var(--s3)}
p:last-child{margin-bottom:0}

/* Big numerals — herd counts, weights, money. Condensed so a five-digit
   figure still fits a narrow card without shrinking the type. */
.figure{font-family:var(--display);font-weight:700;line-height:1;letter-spacing:.01em}
.figure-xl{font-size:38px}
.figure-lg{font-size:30px}
.figure-md{font-size:22px}

/* Anything that lines up in a column: weights, doses, dates, money. */
.num{font-family:var(--mono);font-weight:500;font-variant-numeric:tabular-nums}

.eyebrow{
  font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;
  color:var(--muted);
}
.muted{color:var(--muted)}
.section-title{
  font-family:var(--display);font-weight:700;font-size:26px;
  letter-spacing:.03em;text-transform:uppercase;
}


/* ==========================================================================
   04  EAR TAG CHIP — the signature element
   --------------------------------------------------------------------------
   An animal is never rendered as a database row. It is rendered as its tag:
   punch hole, rounded body, heavy condensed numerals, real tag colour. This
   is the one place the product spends its visual boldness, and it earns it
   by being functional — colour is the herd group, so the screen matches
   what is hanging in the animal's ear.

   Markup:
     <span class="tag tag--yellow"><i>DCE</i><b>233</b></span>
   ========================================================================== */
.tag{
  display:inline-flex;flex-direction:column;align-items:center;justify-content:flex-start;
  min-width:44px;padding:17px 8px 7px;border-radius:22px 22px 8px 8px;
  font-family:var(--display);font-weight:700;line-height:.94;letter-spacing:.01em;
  position:relative;flex:none;text-decoration:none;
  box-shadow:inset 0 -2px 0 rgba(0,0,0,.12);
}
/* The punched hole at the top where a real button tag's post goes through
   the ear -- a tall, rounded-top body with a dark hole near the peak is
   what actually reads as "livestock ear tag" rather than a generic chip. */
.tag::before{
  content:"";position:absolute;top:6px;left:50%;transform:translateX(-50%);
  width:9px;height:9px;border-radius:50%;
  background:rgba(0,0,0,.5);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.5);
}
.tag--white::before{background:rgba(0,0,0,.62)}
.tag b{display:block;font-size:19px;margin-top:3px}
.tag i{
  font-style:normal;font-family:var(--ui);font-weight:600;font-size:8.5px;
  letter-spacing:.09em;text-transform:uppercase;opacity:.72;
}
a.tag:hover{text-decoration:none;filter:brightness(1.06)}

.tag--yellow{background:var(--tag-yellow);color:var(--tag-yellow-ink)}
.tag--green {background:var(--tag-green); color:var(--tag-green-ink)}
.tag--orange{background:var(--tag-orange);color:var(--tag-orange-ink)}
.tag--blue  {background:var(--tag-blue);  color:var(--tag-blue-ink)}
.tag--red   {background:var(--tag-red);   color:var(--tag-red-ink)}
.tag--white {
  background:var(--tag-white);color:var(--tag-white-ink);
  box-shadow:inset 0 0 0 1px var(--line),inset 0 -2px 0 rgba(0,0,0,.07);
}

.tag--sm{min-width:34px;padding:13px 6px 5px;border-radius:16px 16px 6px 6px}
.tag--sm::before{top:4px;width:7px;height:7px}
.tag--sm b{font-size:15px;margin-top:2px}
/* V-02, KNOWINGLY LEFT: .tag i / .tag--sm i are uppercase tracked text at
   8.5px and 7.5px inside a fixed-width tag pill (min-width 34px). They are
   the least readable text in the app -- tiny, tracked, uppercase and at .72
   opacity -- but raising them overflows the pill, so the pill has to be
   redesigned rather than the type nudged. Left as a known item instead of
   silently breaking the tag or silently ignoring it. */
.tag--sm i{font-size:7.5px}

.tag--lg{min-width:60px;padding:22px 12px 11px;border-radius:30px 30px 10px 10px}
.tag--lg::before{top:9px;width:12px;height:12px}
.tag--lg b{font-size:30px;margin-top:4px}
.tag--lg i{font-size:var(--t-xs)}

/* An animal that no longer has a tag in its ear — sold, dead, culled. */
.tag--void{opacity:.45;filter:grayscale(1)}

/* Tag beside a name. The single most repeated pattern in the product. */
.identity{display:flex;align-items:center;gap:11px;min-width:0}
.identity .thumb{
  /* Width/height come from each usage's own HTML attributes (40px in
     ai.html's list rows, 64px in ai_detail.html's larger detail view) --
     this rule only handles shape, fit and the icon-fallback centering. */
  border-radius:50%;object-fit:cover;flex:none;
  background:var(--line-2);display:flex;align-items:center;justify-content:center;color:var(--placeholder);
}
/* Herd Inventory's desktop table photo column -- same rounded-square
   convention as .animal-mobile-card .thumb below, since it's the same
   photo at a different breakpoint. .placeholder is unscoped so it also
   covers the mobile card's no-photo state further down this file. */
.herd-table-card .thumb{width:40px;height:40px;border-radius:var(--r);object-fit:cover}
.thumb.placeholder{display:flex;align-items:center;justify-content:center;background:var(--line-2);color:var(--placeholder)}
.identity .name{min-width:0}
.identity .name b{display:block;font-weight:600;line-height:1.25}
.identity .name small{display:block;color:var(--muted);font-size:var(--t-xs)}


/* ==========================================================================
   05  BUTTONS
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  min-height:var(--tap);padding:9px 15px;
  background:var(--brand);color:var(--brand-on);border:1px solid transparent;
  border-radius:var(--r-sm);font-weight:600;font-size:var(--t-md);
  text-decoration:none;white-space:nowrap;
  transition:background .12s ease,border-color .12s ease;
}
.btn:hover{background:var(--brand-2);color:var(--brand-on);text-decoration:none}
.btn:disabled,.btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
/* Still fully clickable -- just visually de-prioritized on a ranch with no
   herd yet, where "work cattle" and "record birth" have nothing to act on. */
.btn.is-dim{opacity:.5}
.btn.is-dim:hover{opacity:.75}
.quick-btn.is-dim{opacity:.5}

.btn--secondary{background:var(--card);color:var(--brand);border-color:var(--line)}
.btn--secondary:hover{background:var(--brand-tint);color:var(--brand)}

.btn--quiet{background:transparent;color:var(--brand);border-color:transparent}
.btn--quiet:hover{background:var(--brand-tint);color:var(--brand)}

.btn--danger{background:var(--alert);border-color:var(--alert)}
.btn--danger:hover{background:var(--alert-2)}

.btn--danger-quiet{background:transparent;color:var(--alert);border-color:var(--line)}
.btn--danger-quiet:hover{background:var(--alert-tint);color:var(--alert)}

.btn--sm{min-height:34px;padding:6px 12px;font-size:var(--t-sm)}
.btn--lg{min-height:var(--tap-glove);padding:14px 22px;font-size:var(--t-lg)}
.btn--block{width:100%}

.btn-row{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.btn-row form{margin:0;display:inline-flex}

/* Edit/Delete row pinned to the bottom of a record card -- pastures.html,
   contacts.html, hay.html, poultry.html. */
.card-actions{display:flex;gap:var(--s2);align-items:center;margin-top:var(--s3)}
.card-actions form{margin:0;display:inline-flex}

/* Save/Cancel row at the foot of a .form -- ai_inventory_edit.html,
   ai_event_edit.html, ai_sync_edit.html, parent_profile_edit.html,
   animal_edit.html. */
.form-action-row{display:flex;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s2)}

/* Back-link row above the form on animal_edit.html -- same shape as
   .btn-row, plus the margin-bottom .btn-row alone doesn't carry. */
.animal-edit-nav{display:flex;gap:var(--s2);flex-wrap:wrap;margin-bottom:var(--s4)}


/* ==========================================================================
   06  FORMS
   ========================================================================== */
.form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4)}
.form--1{grid-template-columns:minmax(0,1fr)}
.form--3{grid-template-columns:repeat(3,minmax(0,1fr))}
.form .full{grid-column:1/-1}

.field{display:grid;gap:5px;min-width:0}
.field > span,.field > label{
  font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;
  color:var(--ink-2);
}
/* `.form label` sets text-transform:uppercase, and resets it only on the
   input/select/textarea inside. A <small class="hint"> inside a label
   therefore inherited it, rendering whole sentences of guidance in spaced
   all-caps -- "A ROUGH NUMBER IS FINE. TWENTY OR MORE AND WE WILL START YOU
   WITH THE SPREADSHEET IMPORTER". Fine for a two-word field label, hard work
   for a sentence. Scoped to .field before v2.41.0c, so every hint outside a
   .field wrapper was affected: login, genetics, health, inventory, the AI
   screens, and both new onboarding forms. */
.hint,.field .hint{font-size:var(--t-xs);color:var(--muted);text-transform:none;letter-spacing:0;font-weight:400}
.field-help{font-size:var(--t-xs);color:var(--muted)}
.field .error{font-size:var(--t-xs);color:var(--alert);font-weight:600}

input[type=text],input[type=number],input[type=date],input[type=time],
input[type=datetime-local],
input[type=email],input[type=password],input[type=search],input[type=tel],
select,textarea{
  width:100%;min-height:var(--tap);padding:10px 12px;
  background:var(--card);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r-sm);
  font:inherit;
}
textarea{min-height:88px;resize:vertical}
input:hover,select:hover,textarea:hover{border-color:var(--line-hover)}
input:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-tint);
}
input[aria-invalid="true"],select[aria-invalid="true"]{border-color:var(--alert)}
input::placeholder,textarea::placeholder{color:var(--placeholder)}
/* A readonly field (e.g. an auto-assigned ID preview) looks identical to a
   real editable field otherwise -- nothing distinguishes it, so typing into
   one silently does nothing with no visual cue why. Applies everywhere a
   readonly input is used, not just one form. */
input[readonly]{background:var(--paper);color:var(--muted);cursor:not-allowed}
input[readonly]:focus{box-shadow:none;border-color:var(--line)}
input[type=checkbox],input[type=radio]{
  width:20px;height:20px;min-height:0;accent-color:var(--brand);margin:0;
}

.password-field{position:relative}
.password-field input[type=password],.password-field input[type=text]{padding-right:40px}
.password-toggle{
  position:absolute;right:4px;top:50%;transform:translateY(-50%);
  display:grid;place-items:center;width:32px;height:32px;
  background:transparent;border:0;border-radius:var(--r-sm);
  color:var(--muted);cursor:pointer;
}
.password-toggle:hover{color:var(--ink);background:var(--paper)}
.password-toggle svg{width:18px;height:18px;display:block}
.password-toggle .icon-eye-off{display:none}
.password-toggle[aria-pressed="true"] .icon-eye{display:none}
.password-toggle[aria-pressed="true"] .icon-eye-off{display:block}

/* Checkbox or radio with its label, sized as one tap target. */
.choice{
  display:flex;align-items:center;gap:var(--s2);min-height:var(--tap);
  padding:8px 11px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-sm);cursor:pointer;
}
.choice[hidden]{display:none}
.choice:hover{border-color:var(--line-hover)}
.choice input{flex:none}
.choice .name{min-width:0}
.choice .name b{display:block;font-weight:600;font-size:var(--t-md)}
.choice .name small{display:block;color:var(--muted);font-size:var(--t-xs)}
.choice:has(input:checked){border-color:var(--brand);background:var(--brand-tint)}
.choice-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:var(--s2)}

/* Per-animal card in the sale-editing grid (sale_edit.html) -- same
   selected-state language as .choice, plus a price/notes sub-section
   .choice alone doesn't need. */
.sale-animal-card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--s3);display:flex;flex-direction:column;gap:var(--s2);
}
.sale-animal-card.selected{border-color:var(--brand);background:var(--brand-tint)}
.sale-animal-select{display:flex;align-items:center;gap:var(--s2);cursor:pointer;min-height:var(--tap)}
.sale-animal-select input{flex:none}
.sale-animal-select span{min-width:0}
.sale-animal-select b{display:block;font-weight:600}
.sale-animal-select small{display:block;color:var(--muted);font-size:var(--t-xs)}
.sale-animal-fields{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}

/* sales.html: saving immediately, irreversibly marks every selected animal
   Sold -- same weight as .dose-warning's safety-critical language. */
.sale-save-warning{
  display:flex;align-items:flex-start;gap:var(--s2);
  background:var(--warn-tint);border-left:3px solid var(--warn-edge);
  border-radius:var(--r-sm);padding:var(--s3) var(--s4);font-size:var(--t-sm);color:var(--warn);
}

/* Three mini counts (Males/Females/Total) inside a poultry group card. */
.record-counts{display:flex;gap:var(--s3);margin:var(--s2) 0}
.record-counts>div{flex:1;text-align:center;background:var(--paper);border-radius:var(--r-sm);padding:8px}
.record-counts b{display:block;font-size:var(--t-lg);font-family:var(--mono)}
.record-counts span{display:block;color:var(--muted);font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.05em}

/* Sire photo + name header at the top of the semen-lot edit form -- same
   shape/fit convention as .identity .thumb and .parent-card .ph, just
   bigger since this is a profile header, not a list row. */
.sire-edit-header{display:flex;align-items:center;gap:var(--s3);margin-bottom:var(--s2)}
.sire-edit-photo{
  width:64px;height:64px;border-radius:50%;object-fit:cover;flex:none;
  background:var(--line-2);display:flex;align-items:center;justify-content:center;
  color:var(--placeholder);font-size:22px;
}
.sire-edit-header h3{margin:0}
.sire-edit-header p{margin:2px 0 4px;color:var(--muted);font-size:var(--t-sm)}

/* Migrated/duplicate/skipped/warning tiles on the import report. */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--s3)}

/* Tap-to-select chips — body condition, sex, category. Faster than a select
   on a phone and readable at arm's length. */
.chip-set{display:flex;flex-wrap:wrap;gap:var(--s2)}
.chip{
  display:inline-flex;align-items:center;min-height:44px;padding:9px 14px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-pill);
  font-weight:600;font-size:var(--t-md);
}
.chip:hover{border-color:var(--line-hover)}
.chip.is-on{background:var(--tag-yellow);border-color:var(--tag-yellow);color:var(--tag-yellow-ink)}

fieldset{border:0;margin:0;padding:0;min-width:0}
legend{font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;color:var(--ink-2);padding:0 0 var(--s2)}

/* Parentage links, nested inside a larger animal-edit .form -- a bordered
   box makes the boundary of the sub-section obvious. Shared by
   animal_edit.html, animal_form.html, breeding.html, record_edit.html. */
.parent-link-fieldset{
  border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--s4);background:var(--paper);
}
.nested-form{margin-top:var(--s2)}


/* ==========================================================================
   07  TABLES
   --------------------------------------------------------------------------
   Every table is wrapped by base.html's auto-responsive script. Keep that.
   ========================================================================== */
.responsive-table,.auto-responsive-table{
  overflow-x:auto;-webkit-overflow-scrolling:touch;min-width:0;
}
/* Right-edge fade, only once base.html's script confirms the table
   actually overflows -- see the comment there for why this can't be
   unconditional the way it is on chip rows (no trailing whitespace to
   safely eat into on a dense data table). */
.responsive-table.is-scrollable,.auto-responsive-table.is-scrollable{
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);
  mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);
}
table{width:100%;border-collapse:collapse}
th{
  text-align:left;padding:10px var(--s5);
  background:var(--paper);border-bottom:1px solid var(--line-2);
  font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;
  color:var(--muted);white-space:nowrap;
}
td{
  padding:11px var(--s5);border-bottom:1px solid var(--line-2);
  font-size:var(--t-md);vertical-align:middle;
}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover{background:var(--brand-tint)}
td.right,th.right{text-align:right}
.table-compact th,.table-compact td{padding:8px var(--s4)}

/* Flags a row (or a single spanning cell, as kpi_report.html's caveat row
   does) that deserves a second look -- an inactive user, a KPI caveat. */
.row-caution{background:var(--warn-tint);color:var(--warn)}
.row-critical{background:var(--alert-tint);color:var(--alert)}
tbody tr.row-caution:hover{background:var(--warn-tint)}
tbody tr.row-critical:hover{background:var(--alert-tint)}
.restriction-badge{color:var(--alert);margin-left:5px;font-size:var(--t-sm)}


/* --------------------------------------------------------------------------
   B-071  Record tables become one card per record on a phone
   --------------------------------------------------------------------------
   These tables are all wrapped and scrollable, so nothing was unreachable --
   but at 375px the wrapper is ~309px and the tables want 520-970px, so the
   columns falling off the right edge were the ones you came to use. Measured:
   /health 968px, /weaning 891, /expenses 799, /equipment 696, /preg-check 624
   (Days bred AND BCS off-screen), /sales 597 (Amount and Actions).

   base.html copies each column's header into its cells as data-label and adds
   .table-cards to the wrapper, so this is the Feed Board's card pattern
   applied to every record table at once rather than fifteen template edits.

   767px, not the 900px the .phone-only switch uses: between the two there is
   still ~740px of wrapper, which fits most of these tables, and carding a
   tablet would waste the width it has.
   ------------------------------------------------------------------------ */
@media (max-width:767px){
  .table-cards > table,
  .table-cards > table > tbody,
  .table-cards > table > tbody > tr,
  .table-cards > table > tbody > tr > td,
  .table-cards > table > tr,
  .table-cards > table > tr > td{ display:block; width:auto }

  /* The column names now live in each cell. */
  .table-cards > table > thead,
  .table-cards tr.row-headers{ display:none }

  .table-cards{ overflow-x:visible }
  .table-cards.is-scrollable{ -webkit-mask-image:none; mask-image:none }

  .table-cards > table > tbody > tr,
  .table-cards > table > tr{
    background:var(--card);border:1px solid var(--line-2);
    border-radius:var(--r);padding:var(--s2) var(--s4);margin-bottom:var(--s3);
  }
  .table-cards > table > tbody > tr:last-child,
  .table-cards > table > tr:last-child{ margin-bottom:0 }
  /* The hover tint reads as a selected state on a card. */
  .table-cards > table > tbody > tr:hover,
  .table-cards > table > tr:hover{ background:var(--card) }

  .table-cards td{
    display:flex !important;gap:var(--s4);align-items:baseline;
    justify-content:space-between;
    /* A long value -- a combination product name, a note -- drops onto its own
       line under the label instead of being squeezed against the card edge.
       Short values stay on the label's line, which is most of them. */
    flex-wrap:wrap;overflow-wrap:anywhere;
    padding:8px 0;border-bottom:1px dashed var(--line-2);
    font-size:var(--t-md);text-align:left;
  }
  .table-cards tr > td:last-child{ border-bottom:0 }

  .table-cards td[data-label]::before{
    content:attr(data-label);
    font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;
    color:var(--muted);flex:none;max-width:45%;
  }
  /* The first field anchors the card, so give it weight -- but keep its label,
     because "which field is this" must not become a guess. */
  .table-cards tr > td:first-child{ font-weight:600 }

  /* An input is the reason the rancher opened this screen: full width, on its
     own line, never sharing a row with its own label. */
  .table-cards td.cell-input{ display:block !important }
  .table-cards td.cell-input::before{ display:block;margin-bottom:var(--s1) }
  .table-cards td.cell-input input,
  .table-cards td.cell-input select,
  .table-cards td.cell-input textarea{ width:100% !important;min-height:var(--tap) }

  .table-cards td.cell-actions{ display:block !important }
  .table-cards td.cell-actions::before{ display:block;margin-bottom:var(--s2) }
  .table-cards td.cell-actions .inline-form{ display:inline-block }
  .table-cards td.cell-actions > *{ margin-right:var(--s2) }

  /* A spanning cell is a full-width statement, almost always an empty state.
     B-081: on /ai this was a 738px cell in a 341px wrapper, so a rancher read
     roughly the first half of a message whose whole job is to orient someone
     who has nothing yet. */
  .table-cards td.cell-full{
    display:block !important;border-bottom:0;
    color:var(--muted);text-align:center;padding:var(--s3) 0;
  }
  .table-cards td.cell-full::before{ content:none }
}


/* ==========================================================================
   08  CARDS AND PANELS
   ========================================================================== */
.panel{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow);overflow:hidden;min-width:0;
}
.panel-head{
  display:flex;align-items:center;gap:var(--s3);
  padding:var(--s4) var(--s5);border-bottom:1px solid var(--line-2);
}
.panel-head h3,.panel-head h2,.panel-head b{font-size:var(--t-lg)}
.panel-head .sub{font-size:var(--t-sm);color:var(--muted)}
.panel-head .go{margin-left:auto;font-size:var(--t-sm);font-weight:600;white-space:nowrap}
.panel-body{padding:var(--s4) var(--s5)}
.panel-foot{padding:var(--s3) var(--s5);border-top:1px solid var(--line-2);background:var(--paper)}
.panel > table:first-child th{border-top:0}

.card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow);padding:var(--s4);min-width:0;
}

/* Page header. Replaces .module-heading. */
.page-head{
  display:flex;align-items:flex-end;gap:var(--s4);flex-wrap:wrap;
  margin-bottom:var(--s4);
}
.page-head .titles{min-width:0}
.page-head h1{font-size:23px}
.page-head p{margin:3px 0 0;color:var(--muted);font-size:var(--t-sm)}
.page-head .actions{margin-left:auto;display:flex;gap:var(--s2);flex-wrap:wrap}

/* Empty state. An empty screen is an invitation to act, not an apology. */
.empty{
  display:grid;justify-items:center;gap:var(--s3);text-align:center;
  padding:var(--s7) var(--s5);color:var(--muted);
}
.empty h3{color:var(--ink);font-size:var(--t-lg)}
.empty p{max-width:46ch;font-size:var(--t-sm)}


/* ==========================================================================
   09  PILLS, BADGES, FLASHES
   ========================================================================== */
.pill{
  display:inline-flex;align-items:center;gap:5px;
  padding:3px 9px;border-radius:var(--r-pill);
  font-size:var(--t-xs);font-weight:600;white-space:nowrap;
}
.pill--alert{background:var(--alert-tint);color:var(--alert)}
.pill--warn {background:var(--warn-tint); color:var(--warn)}
.pill--ok   {background:var(--ok-tint);   color:var(--ok)}
.pill--info {background:var(--info-tint); color:var(--info)}
.pill--quiet{background:var(--line-2);    color:var(--ink-2)}

/* Same shape as .pill, bare modifier names (not --dashed) since that's the
   convention already hardcoded in ai_presets.html/parent_profiles.html. */
.status-pill{
  display:inline-flex;align-items:center;padding:3px 9px;border-radius:var(--r-pill);
  font-size:var(--t-xs);font-weight:600;white-space:nowrap;
  background:var(--info-tint);color:var(--info);
}
.status-pill.active{background:var(--ok-tint);color:var(--ok)}
.status-pill.muted{background:var(--line-2);color:var(--ink-2)}

/* Medication-row flags (working_session_detail.html's batch product picker).
   Same visual language as .pill, kept as their own class names since a
   product row can carry more than one at once (recent + Rx together). */
.chip-recent,.chip-rx{
  display:inline-flex;align-items:center;padding:2px 9px;border-radius:var(--r-pill);
  font-size:var(--t-xs);font-weight:600;
}
.chip-recent{background:var(--info-tint);color:var(--info)}
.chip-rx{background:var(--warn-tint);color:var(--warn)}
/* Longer than a flag word -- a full handler-safety sentence, so it reads as
   an inline warning line rather than a pill. */
.chip-danger{display:flex;align-items:flex-start;gap:6px;margin-top:4px;color:var(--alert);font-weight:600}

.dot{width:9px;height:9px;border-radius:50%;flex:none;display:inline-block}
.dot--alert{background:var(--alert)}
.dot--warn{background:var(--warn-edge)}
.dot--ok{background:var(--ok)}

.count{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:19px;height:19px;padding:0 6px;border-radius:var(--r-pill);
  background:var(--alert);color:var(--brand-on);font-size:var(--t-xs);font-weight:600;
}

.flash{
  display:flex;align-items:flex-start;gap:var(--s3);
  padding:var(--s3) var(--s4);border-radius:var(--r-sm);
  margin-bottom:var(--s3);font-size:var(--t-md);border-left:3px solid transparent;
}
.flash.success{background:var(--ok-tint);   border-left-color:var(--ok);   color:var(--ok)}
.flash.error  {background:var(--alert-tint);border-left-color:var(--alert);color:var(--alert)}
.flash.warning{background:var(--warn-tint); border-left-color:var(--warn-edge);color:var(--warn)}
.flash.info   {background:var(--info-tint); border-left-color:var(--info); color:var(--info)}

.notice{
  background:var(--brand-tint);border-left:3px solid var(--brand);
  padding:var(--s3) var(--s4);border-radius:var(--r-sm);font-size:var(--t-sm);
}
.notice h2{font-size:var(--t-lg)}
/* ai_schedule.js toggles this onto #schedule-preview-status's own .notice
   once any calculated step lands on a warning (a rest day, a Sunday, etc). */
.notice.warning-notice{background:var(--warn-tint);border-left-color:var(--warn-edge);color:var(--warn)}
/* Same JS renders one of these per calculated schedule step -- same visual
   language as .pill--ok/.pill--warn, kept separate since the class names
   are hardcoded in ai_schedule.js and out of this fix's scope to rename. */
.schedule-ok,.schedule-warning{
  display:inline-flex;align-items:center;gap:5px;padding:3px 9px;
  border-radius:var(--r-pill);font-size:var(--t-xs);font-weight:600;white-space:nowrap;
}
.schedule-ok{background:var(--ok-tint);color:var(--ok)}
.schedule-warning{background:var(--warn-tint);color:var(--warn)}

/* Withdrawal banner — the single most consequential warning in the product.
   Shown on an animal that cannot legally be sold or milked right now. */
.restriction{
  display:flex;align-items:center;gap:var(--s3);
  background:var(--alert-tint);border:1px solid var(--alert-edge);border-left:4px solid var(--alert);
  border-radius:var(--r-sm);padding:var(--s3) var(--s4);
}
.restriction b{color:var(--alert)}
.restriction small{display:block;color:var(--ink-2);font-size:var(--t-xs)}
.restriction--soon{background:var(--warn-tint);border-color:var(--warn-edge-soft);border-left-color:var(--warn-edge)}
.restriction--soon b{color:var(--warn)}


/* ==========================================================================
   10  APP SHELL
   ========================================================================== */
.app-shell{
  display:grid;grid-template-columns:var(--sidebar-w) minmax(0,1fr);
  min-height:100vh;min-height:100dvh;
}

.app-sidebar{
  position:sticky;top:0;height:100vh;height:100dvh;z-index:30;
  background:var(--brand-2);color:var(--sidebar-text);
  padding:var(--s4) var(--s3);
  display:flex;flex-direction:column;gap:var(--s4);
}
.sidebar-brand{
  display:flex;align-items:center;gap:10px;
  padding:2px 6px var(--s4);border-bottom:1px solid rgba(255,255,255,.1);
}
.sidebar-brand img{width:34px;height:34px;border-radius:var(--r-sm);object-fit:contain;background:var(--card);flex:none}
/* The default mark (v2.48.0c: Headgate's own white mark, previously one
   ranch's registered brand) is white on transparent and sits directly on
   the dark sidebar. The white .sidebar-brand img background above exists
   for arbitrary uploaded ranch logos, and would make this one vanish
   white-on-white for every ranch that has not uploaded its own. */
.sidebar-brand img.is-default-mark{background:none;border-radius:0}
.sidebar-brand-copy{display:flex;flex-direction:column;min-width:0}
.sidebar-brand h2{font-size:15px;color:var(--sidebar-text);letter-spacing:.01em;line-height:1.15}
.sidebar-brand p{
  margin:4px 0 0;font-size:11px;line-height:1.25;letter-spacing:.06em;color:var(--sidebar-muted);
}

.app-nav{display:flex;flex-direction:column;gap:6px;flex:1;overflow-y:auto;margin:0 -4px;padding:2px}
.app-nav .nav-group{
  font:var(--label);letter-spacing:.15em;text-transform:uppercase;
  color:var(--sidebar-muted-2);padding:var(--s4) 10px var(--s1);
}
.app-nav a{
  display:flex;align-items:center;gap:10px;
  padding:8px 10px;border-radius:var(--r-sm);
  color:var(--sidebar-text-dim);font-size:var(--t-sm);font-weight:500;text-decoration:none;
}
.app-nav a:hover{background:rgba(255,255,255,.07);color:var(--brand-on);text-decoration:none}
.app-nav a.active{background:var(--card);color:var(--brand-2);font-weight:600}
.app-nav .nav-icon{width:16px;text-align:center;font-size:13px;opacity:.85;flex:none}
.app-nav a.active .nav-icon{opacity:1}
.app-nav .count{margin-left:auto}
.workspace-home,.nav-workspace summary{
  min-height:54px;display:flex;align-items:center;gap:11px;padding:9px 11px;
  border-radius:var(--r);color:var(--sidebar-text-dim);cursor:pointer;list-style:none;
}
.workspace-home > span:last-child,.nav-workspace summary > span:nth-child(2){display:flex;flex-direction:column;min-width:0}
.workspace-home b,.nav-workspace summary b{font-size:14px;line-height:1.2;color:inherit}
.workspace-home small,.nav-workspace summary small{font-size:11.5px;color:var(--sidebar-muted);line-height:1.35;margin-top:2px}
.nav-workspace summary::-webkit-details-marker{display:none}
.nav-workspace summary:hover{background:rgba(255,255,255,.07);color:var(--brand-on)}
.nav-workspace summary.active,.workspace-home.active{background:rgba(255,255,255,.12);color:var(--brand-on)}
.nav-workspace .chevron{margin-left:auto;font-size:var(--t-xs);color:var(--sidebar-muted);transition:transform .16s ease}
.nav-workspace[open] .chevron{transform:rotate(180deg)}
.workspace-links{display:grid;gap:2px;margin:3px 0 5px 37px;padding-left:8px;border-left:1px solid rgba(255,255,255,.13)}
.app-nav .workspace-links a{padding:8px 9px;font-size:13px;border-radius:var(--r-sm)}
.app-nav .workspace-links a.active{background:var(--card);color:var(--brand-2)}
.sidebar-install-app{
  display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;text-align:left;
  border:1px solid rgba(255,255,255,.14);border-radius:var(--r-sm);
  background:rgba(255,255,255,.07);color:var(--sidebar-text-dim);
}
.sidebar-install-app[hidden]{display:none!important}
.sidebar-install-app span{display:flex;flex-direction:column}
.sidebar-install-app small{font-size:var(--t-xs);color:var(--sidebar-muted)}
.farm-switcher{display:flex;align-items:center;gap:9px;padding:9px 7px;color:var(--sidebar-text-dim);font-size:12px}
.farm-symbol{
  width:28px;height:28px;border-radius:50%;background:var(--sidebar-avatar-bg);flex:none;
  display:grid;place-items:center;font-size:var(--t-xs);color:var(--sidebar-avatar-ink);
}
.farm-switcher div{display:flex;flex:1;min-width:0;flex-direction:column}
.farm-switcher small{color:var(--sidebar-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.sidebar-foot{
  border-top:1px solid rgba(255,255,255,.1);padding-top:var(--s3);
  display:flex;align-items:center;gap:9px;font-size:var(--t-sm);
}
.sidebar-foot .avatar{
  width:28px;height:28px;border-radius:50%;background:var(--sidebar-avatar-bg);flex:none;
  display:grid;place-items:center;font-size:var(--t-xs);font-weight:600;color:var(--sidebar-avatar-ink);
}
.sidebar-foot small{display:block;color:var(--sidebar-muted);font-size:var(--t-xs)}
.sidebar-session-actions{display:none}
.sidebar-session-actions form{margin:0}
.sidebar-session-actions > * + *{margin-top:8px}
.sidebar-session-actions button,.sidebar-session-actions a{
  width:100%;display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid rgba(255,255,255,.12);
  border-radius:var(--r-sm);background:rgba(255,255,255,.06);color:var(--sidebar-text-dim);font-weight:600;
}

.app-main{min-width:0;display:flex;flex-direction:column}
.utility-bar{
  position:sticky;top:0;z-index:20;
  min-height:var(--topbar-h);
  display:flex;align-items:center;gap:var(--s3);
  padding:var(--s2) var(--s5);padding-top:calc(var(--s2) + var(--safe-top));
  background:var(--card);border-bottom:1px solid var(--line);
}
.utility-bar h2{font-size:var(--t-xl)}
.utility-bar .date{font-family:var(--mono);font-size:var(--t-sm);color:var(--muted)}
.utility-spacer{flex:1}
.utility-actions{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-left:auto;color:var(--muted);font-size:var(--t-sm)}
.utility-actions form{margin:0}
.utility-button{
  min-height:36px;padding:7px 12px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--card);color:var(--ink-2);font-size:var(--t-sm);font-weight:600;
  box-shadow:0 1px 2px rgba(18,38,31,.04);
}
.utility-button:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-tint)}
.search-box{
  display:flex;align-items:center;gap:var(--s2);min-height:var(--tap);
  padding:7px 11px;width:240px;
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);
  color:var(--muted);font-size:var(--t-sm);
}
.weather-strip{
  display:flex;align-items:center;gap:7px;font-size:var(--t-sm);color:var(--ink-2);
  padding-right:var(--s3);border-right:1px solid var(--line);
}
.weather-strip b{font-family:var(--mono);font-weight:600}

.app-content{padding:var(--s5);display:flex;flex-direction:column;gap:var(--s4);flex:1}

.app-footer{
  display:flex;align-items:center;justify-content:center;gap:var(--s3);
  padding:var(--s4) var(--s5);margin-top:auto;
  border-top:1px solid var(--line);color:var(--muted);font-size:var(--t-xs);
}
.app-footer a{color:var(--muted);text-decoration:underline}


/* ==========================================================================
   11  DASHBOARD
   --------------------------------------------------------------------------
   The decorative hero is gone. It occupied 315px of the highest-value screen
   real estate to display the ranch's own name, which the owner already knows.
   That space now answers: what costs me money if I do not do it today.
   ========================================================================== */
.command-hero{
  display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s5);
  padding:var(--s5) var(--s6);border-radius:calc(var(--r-lg) + 2px);
  color:#fff;background:var(--hero-grad);
  box-shadow:var(--hero-shadow);overflow:hidden;
}
.command-hero .eyebrow{color:var(--hero-eyebrow);letter-spacing:.13em}
.command-hero h1{font-family:var(--display);font-size:clamp(30px,3.2vw,46px);line-height:1.04;color:#fff;margin:5px 0 7px}
.command-hero p{max-width:630px;color:var(--hero-body);font-size:var(--t-md);margin:0}
.command-actions{display:flex;align-items:center;justify-content:flex-end;gap:9px;flex-wrap:wrap;min-width:390px}
.command-hero .btn--secondary{background:var(--hero-glass-bg);border-color:var(--hero-glass-border);color:#fff}
.command-hero .btn--secondary:hover{background:var(--hero-glass-bg-hover)}
.desktop-all-clear{display:flex;align-items:center;gap:13px;padding:18px var(--s5);border-top:1px solid var(--line-2);background:var(--ok-tint)}
.desktop-all-clear > i{font-size:23px;color:var(--ok)}
.desktop-all-clear div{display:flex;flex-direction:column;gap:2px}
.desktop-all-clear span{font-size:var(--t-sm);color:var(--muted)}
.today{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow);overflow:hidden;
}
.today-head{
  display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap;
  padding:var(--s4) var(--s5) var(--s3);
}
.today-head h2{
  font-family:var(--display);font-size:26px;font-weight:700;
  letter-spacing:.03em;text-transform:uppercase;
}
.today-head .summary{font-size:var(--t-sm);color:var(--muted)}
.today-head .go{margin-left:auto;font-size:var(--t-sm);font-weight:600}

.today-grid{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  border-top:1px solid var(--line-2);
}
.today-cell{
  padding:var(--s4) var(--s5);border-right:1px solid var(--line-2);
  display:flex;flex-direction:column;gap:var(--s3);min-width:0;
}
.today-cell:last-child{border-right:0}
.today-cell-head{display:flex;align-items:center;gap:9px}
.today-cell-head b,
.today-cell-head h2{
  font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;color:var(--ink-2);
  margin:0;
}
.today-cell-head .n{
  margin-left:auto;font-family:var(--display);font-weight:700;font-size:30px;line-height:.8;
}
.today-cell-head .n.is-alert{color:var(--alert)}
.today-cell-head .n.is-warn{color:var(--warn)}

.task-row{display:flex;align-items:center;gap:10px;font-size:var(--t-md);min-width:0}
.task-row .text{min-width:0;flex:1}
.task-row .text b{
  display:block;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.task-row .text small{display:block;color:var(--muted);font-size:var(--t-xs)}
.task-row .when{
  margin-left:auto;font-family:var(--mono);font-size:var(--t-xs);
  color:var(--muted);white-space:nowrap;
}
.task-row .when.is-late{color:var(--alert);font-weight:600}

.stat-row{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--s3)}
.stat{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow);padding:var(--s4);min-width:0;
}
.stat small{
  font:var(--label);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
}
.stat b{
  display:block;font-family:var(--display);font-weight:700;font-size:38px;
  line-height:1;margin:7px 0 3px;
}
.stat .delta{font-size:var(--t-xs);font-weight:600}
.delta--up{color:var(--ok)}
.delta--down{color:var(--alert)}
.delta--flat{color:var(--muted)}

.split{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);gap:var(--s4)}
.stack{display:flex;flex-direction:column;gap:var(--s4);min-width:0}

/* Composition bars. Replaces the CSS conic-gradient donut, which could not
   be labelled, read by a screen reader, or changed without editing CSS. */
.bar-list{padding:var(--s4) var(--s5);display:flex;flex-direction:column;gap:var(--s3)}
.bar-row{
  display:grid;grid-template-columns:96px minmax(0,1fr) 46px;
  align-items:center;gap:var(--s3);font-size:var(--t-sm);
}
.bar{height:9px;border-radius:var(--r-pill);background:var(--line-2);overflow:hidden}
.bar > span{display:block;height:100%;border-radius:var(--r-pill);background:var(--brand)}
.bar-row .value{text-align:right;font-family:var(--mono);font-weight:600;font-size:var(--t-sm)}

.ledger{padding:var(--s4) var(--s5);display:grid;gap:var(--s4)}
.ledger-row{display:flex;align-items:baseline;gap:var(--s3)}
.ledger-row small{
  font:var(--label);letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
}
.ledger-row b{margin-left:auto;font-family:var(--mono);font-weight:600;font-size:var(--t-lg)}
.ledger-row b.is-negative{color:var(--alert)}
.ledger-net{border-top:1px solid var(--line-2);padding-top:var(--s3)}
.ledger-net b{font-family:var(--display);font-size:29px;font-weight:700;color:var(--ok)}


/* ==========================================================================
   12  PHONE AND PWA
   --------------------------------------------------------------------------
   Not the desktop squeezed down. Different information order: what needs
   doing, then what is restricted, then the four things worth one tap.
   ========================================================================== */
.mobile-bottom-nav{display:none}
.mobile-menu-button{display:none}
.mobile-sidebar-close{display:none}
.mobile-sidebar-backdrop{display:none}
.mobile-title{display:none}

/* Phone home screen (dashboard.html) vs the desktop Today band / split
   panel. Same today_band data, two different layouts — see section 15 for
   the breakpoint that swaps which one is visible. */
.phone-only{display:none}

.phone-greeting{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:var(--s2) 0 var(--s1)}
.phone-greeting .eyebrow{display:block}
.phone-greeting h1{
  font-family:var(--display);font-size:32px;font-weight:700;
  letter-spacing:.01em;margin-top:2px;
}
.phone-greeting-calendar{
  display:flex;align-items:center;justify-content:center;flex:none;
  width:40px;height:40px;margin-top:2px;border-radius:50%;
  border:1px solid var(--line);background:var(--card);color:var(--brand);font-size:16px;
  text-decoration:none;box-shadow:var(--shadow);
}
.phone-greeting-calendar:hover,.phone-greeting-calendar:active{border-color:var(--brand);background:var(--brand-tint)}

.phone-card{margin-top:var(--s4)}
.phone-card:first-of-type{margin-top:0}
.phone-card .today-cell-head{padding:var(--s4) var(--s5) var(--s3)}
.all-clear-card{display:flex;align-items:center;gap:13px;padding:var(--s4);background:var(--ok-tint);border-color:rgba(31,112,74,.2)}
.all-clear-card > i{font-size:24px;color:var(--ok)}
.all-clear-card h2{font-size:16px}.all-clear-card p{margin:2px 0 0;color:var(--muted);font-size:13px}
.phone-herd-list{display:none}

.onboarding-card{border-color:var(--ok-edge);margin-bottom:var(--s4)}
.onboarding-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3)}
.onboarding-head h2{font-size:18px;margin:0}
.onboarding-progress{font-size:13px;color:var(--muted);white-space:nowrap}
.onboarding-sub{margin:2px 0 var(--s3);color:var(--muted);font-size:13px}
.onboarding-steps{display:flex;flex-direction:column;gap:8px}
.onboarding-step{
  display:flex;align-items:center;gap:var(--s3);padding:10px 14px;
  border:1px solid var(--line-2);border-radius:9px;background:var(--paper);
}
.onboarding-step.is-done{opacity:.6}
.onboarding-dot{
  width:22px;height:22px;border-radius:50%;border:2px solid var(--line);flex:none;
  display:grid;place-items:center;font-size:11px;color:#fff;
}
.onboarding-step.is-done .onboarding-dot{background:var(--ok);border-color:var(--ok)}
.onboarding-body{flex:1;min-width:0;display:flex;flex-direction:column}
.onboarding-body b{font-size:14px}
.onboarding-body small{color:var(--muted);font-size:12px;margin-top:1px}
.onboarding-cta{white-space:nowrap}
/* I-001: the herd step carries two routes (import / add one). Wrapping is
   deliberate -- at 375px two buttons do not fit beside a step label, and
   stacking them beats shrinking either below a glove target. */
.onboarding-cta-group{display:flex;flex-wrap:wrap;gap:var(--s2);justify-content:flex-end}
.onboarding-foot{display:flex;justify-content:flex-end;margin-top:var(--s3)}
/* Some controls SHOULD stay visually small -- a tag number inside a dense
   card, a "powered by" credit, a quiet dismiss. Making them 44px tall would
   make the page look clumsy, which is the wrong trade. Instead the visible
   control keeps its size and an invisible ::after extends the finger target
   to the minimum. The design stays tight; the thumb still lands. */
.tap-target{position:relative}
.tap-target::after{
  content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:100%;height:100%;min-width:var(--tap);min-height:var(--tap);
}
.link-quiet{border:0;background:none;color:var(--muted);text-decoration:underline;padding:0;cursor:pointer;font:inherit;font-size:13px}
.phone-card .task-row,.phone-card .empty{padding-left:var(--s5);padding-right:var(--s5)}
.phone-card .task-row{padding-bottom:var(--s3)}
.phone-card .task-row:last-of-type{padding-bottom:var(--s4)}
.phone-card > .go{display:block;padding:0 var(--s5) var(--s4);font-size:var(--t-sm);font-weight:600}

.quick-grid{margin-top:var(--s4);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.quick-btn{
  display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  min-height:72px;padding:var(--s4) var(--s3);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow);text-align:left;text-decoration:none;color:var(--ink);
}
.quick-btn:hover{border-color:var(--brand);text-decoration:none}
.quick-btn .nav-icon{font-size:17px;color:var(--brand)}
.quick-btn b{font-size:var(--t-md);font-weight:600}
.quick-btn small{color:var(--muted);font-size:var(--t-xs)}

/* Sticky save bar on long phone forms. base.html adds .has-save-bar to body. */
.mobile-save-bar{
  position:fixed;left:0;right:0;bottom:0;z-index:40;display:none;
  gap:var(--s2);padding:var(--s3) var(--s4);
  padding-bottom:calc(var(--s3) + var(--safe-bottom));
  background:var(--card);border-top:1px solid var(--line);
  box-shadow:0 -4px 16px rgba(20,26,23,.07);
}


/* ==========================================================================
   13  CHUTE MODE
   --------------------------------------------------------------------------
   The screen used with gloves on, in direct sun, with an animal restrained
   and a queue behind it. Dark ground because the phone is held at an angle
   under glare; 54px targets because the thumb is in a glove; one decision
   per screen because the animal does not wait.

   This is the differentiator. CattleMax, Ranch Manager and Cattlytics are
   record-keepers you visit after the work. Nothing here is a visit.
   ========================================================================== */
/* Field Mode (v2.30.9c): the chute screen used to swap to a dark, near-
   black surface -- good contrast, but read as a different app bolted onto
   an otherwise light product. Same layout and interaction, re-themed onto
   the app's normal light surface instead. The --chute-* tokens (section 13)
   are redefined here rather than at every individual selector, so every
   card/chip/choice on this screen re-themes from this one place. */
.chute{
  background:var(--paper);color:var(--ink);min-height:100vh;min-height:100dvh;display:flex;flex-direction:column;
  --chute-muted:var(--muted);
  --chute-card:var(--card);
  --chute-card-line:var(--line);
  --chute-chip-bg:var(--paper);
  --chute-chip-line:var(--line);
  --chute-chip-ink:var(--ink);
  --chute-chip-hover:var(--line-2);
  --chute-ok:var(--ok);
  --chute-alert:var(--alert);
}
.chute[hidden]{display:none}
/* The header keeps a bold brand-green band -- the one deliberate holdover
   from the dark theme, so there's still a clear "you're at the chute now"
   signal even though the rest of the screen matches the app. Its own
   --chute-muted override keeps the subtitle/counter light against this
   green band regardless of the light body tokens set just above. */
.chute-head{
  display:flex;align-items:center;gap:var(--s3);
  padding:var(--s4);padding-top:calc(var(--s4) + var(--safe-top));flex:none;
  background:var(--brand);
  --chute-muted:rgba(255,255,255,.75);
}
/* B-067. The only way out of full-screen chute mode was a bare <a> wrapping a
   Font Awesome arrow, which measured 12 x 20 px -- roughly a quarter of the
   44px touch minimum, aimed at with gloves, on a screen that deliberately
   hides the sidebar and offers no other exit. Give it a real target the same
   size as everything else on this screen. */
.chute-head > a[aria-label="Back to session"]{
  flex:none;display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;margin:calc(var(--s2) * -1);
  border-radius:var(--r-sm);color:var(--brand-on);
}
.chute-head > a[aria-label="Back to session"]:hover{background:rgba(255,255,255,.14)}
.chute-head .text{min-width:0}
.chute-head .text b{display:block;color:var(--brand-on);font-size:var(--t-lg);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chute-head .text small{display:block;color:var(--chute-muted);font-size:var(--t-sm);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chute-head .progress{
  margin-left:auto;font-family:var(--mono);font-size:var(--t-sm);color:var(--chute-muted);
}
.chute-body{flex:1;overflow-y:auto;padding:0 var(--s4) var(--s4);display:flex;flex-direction:column;gap:var(--s3)}

.chute-field{background:var(--chute-card);border:1px solid var(--chute-card-line);border-radius:var(--r);padding:var(--s4)}
.chute-field > small{
  font:var(--label);letter-spacing:.12em;text-transform:uppercase;color:var(--chute-muted);
}
.chute-value{
  font-family:var(--display);font-weight:700;font-size:44px;line-height:1;
  color:var(--ink);margin-top:6px;
}
.chute-value u{text-decoration:none;font-size:var(--t-xl);color:var(--chute-muted);margin-left:6px}
.chute-field .chip-set{margin-top:var(--s3)}
/* Any chip anywhere on the chute surface (Give, Procedures, gate chips,
   Classification, category picker) -- broader than .chute-field alone so
   chips inside .chute-more-fields (not itself a .chute-field) still pick
   up the same treatment instead of the global light .chip default. */
.chute .chip{background:var(--chute-chip-bg);border-color:var(--chute-chip-line);color:var(--chute-chip-ink)}
.chute .chip.is-on{background:var(--tag-yellow);border-color:var(--tag-yellow);color:var(--tag-yellow-ink)}
.chute .chip.ghost{background:transparent;color:var(--chute-muted)}
.chute .chip.sm{padding:7px 14px;font-size:var(--t-sm);min-height:var(--tap-glove)}
.chute .chip.gate-chip{border-style:dashed}
.chute .chip.gate-chip.is-on{border-style:solid}
@keyframes chuteChipFlash{0%{box-shadow:0 0 0 3px var(--tag-yellow)}100%{box-shadow:0 0 0 0 transparent}}
.chute .chip.chip-flash{animation:chuteChipFlash .7s ease}
@media (prefers-reduced-motion: reduce){ .chute .chip.chip-flash{animation:none} }

/* Route/medication-flag badges (route-pill, med-tag) keep a neutral chip
   treatment here rather than the light surface's default tinted pills, for
   visual consistency with the rest of the chute's chip language. Rx/VFD
   stays a dedicated warning color (not the neutral chip ink) since it's a
   legibility-first safety flag, not decoration -- kept dark enough for
   contrast on the now-light chip background (was bright tag-yellow, which
   only worked against the old dark ground). */
.chute .route-pill{background:var(--chute-chip-bg);color:var(--chute-chip-ink)}
.chute .med-tag{background:var(--chute-chip-bg);color:var(--chute-chip-ink)}
.chute .med-tag-warn{background:var(--chute-chip-bg);color:var(--warn)}

/* Computed dose. The number the operator acts on, plus the withdrawal date
   it creates — written before the gun is put down, not after. */
.dose-callout{
  background:var(--warn-tint);border-left:3px solid var(--warn-edge);
  border-radius:var(--r-sm);padding:var(--s3) var(--s4);margin-top:var(--s3);
}
.dose-callout b{
  display:block;font-family:var(--mono);font-weight:600;font-size:var(--t-xl);
  color:var(--tag-yellow-ink);
}
.dose-callout small{display:block;font-size:var(--t-sm);color:var(--warn)}

.chute-foot{
  position:sticky;bottom:0;z-index:5;
  flex:none;display:grid;grid-template-columns:1fr 1.7fr;gap:var(--s5);
  padding:var(--s4);padding-bottom:calc(var(--s4) + var(--safe-bottom));
  background:var(--card);border-top:1px solid var(--line);box-shadow:0 -8px 16px -8px rgba(20,26,23,.12);
}
.chute-foot .btn{min-height:var(--tap-glove);font-size:var(--t-lg)}
/* B-036. Skip used to be --chute-chip-bg on the --card foot bar: a 1.11:1
   fill defined only by a 1.30:1 hairline. In glare it was effectively not
   there, while sitting 12px from a 54px Save button under the same thumb.
   A 2px --muted outline is 5.03:1 against the bar -- a real silhouette --
   and the foot's gap went 12px -> 24px so reaching for Save cannot graze it.
   Deliberately still quiet: this is the secondary control, and Save keeps
   the only filled treatment on the screen. */
.btn--chute-skip{background:var(--chute-chip-bg);color:var(--chute-chip-ink);border:2px solid var(--muted)}
.btn--chute-skip:hover{background:var(--chute-chip-hover);color:var(--ink);border-color:var(--ink)}
.btn--chute-go{background:var(--tag-yellow);color:var(--tag-yellow-ink);border-color:var(--tag-yellow)}
.btn--chute-go:hover{background:var(--chute-go-hover);color:var(--tag-yellow-ink)}

/* Shell escape: chute.html and its .chute sections replace the whole app
   frame (sidebar, topbar, footer, bottom nav) rather than sitting inside
   .app-content's light, padded, nav-reserving layout. */
/* .app-shell's grid-template-columns still defines a 264px first track
   even with .app-sidebar display:none -- CSS grid auto-placement then
   slides .app-main (the next real item) into that leftover 264px track
   instead of the wide second one, squeezing the whole chute screen into a
   264px column with the rest of the viewport blank. Collapse to a single
   full-width track whenever chute-mode hides the sidebar, same as the
   existing mobile-breakpoint override just below. */
body.chute-mode .app-shell{grid-template-columns:1fr}
body.chute-mode .app-content{padding:0;max-width:none;gap:0}
body.chute-mode .app-sidebar,
body.chute-mode .utility-bar,
body.chute-mode .app-footer,
body.chute-mode .mobile-bottom-nav,
body.chute-mode .mobile-menu-button{display:none}

.chute-product{margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--chute-card-line)}
.chute-recent-weight{display:block;margin-top:var(--s2);color:var(--chute-muted);font-size:var(--t-xs)}

/* Live scale (v2.70.0c). Sits inside the Weight card, under the manual input,
   because that is the thing it fills in -- a reading that appears anywhere
   else on this screen invites the operator to read it and type it by hand.
   Both buttons are --tap-glove tall: this is aimed at with gloves on. */
.chute-scale{margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--chute-card-line)}
.chute-scale .btn--scale,
.chute-scale .btn--scale-use{
  min-height:var(--tap-glove);
  background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);color:var(--chute-chip-ink);
}
.chute-scale .btn--scale:hover,
.chute-scale .btn--scale-use:hover:not(:disabled){background:var(--chute-chip-hover)}
.chute-scale .btn--scale-use:not(:disabled){
  background:var(--brand);border-color:var(--brand);color:var(--brand-on);
}
.chute-scale .btn--scale-use:disabled{opacity:.5;cursor:not-allowed}
.chute-scale-note{display:block;color:var(--chute-muted);font-size:var(--t-xs)}
.chute-scale-live{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
/* An author display: rule outranks the UA's [hidden]{display:none}, so the
   live readout showed its "— lb" and a dead Use button before anything was
   connected, and .btn's display:inline-flex left "Connect scale" on screen
   next to the live reading after connecting. Same trap as .gate-panel and
   .qp-chip above, and it bit all three of these elements. */
.chute-scale[hidden],
.chute-scale-live[hidden],
.chute-scale .btn[hidden]{display:none}
.chute-scale-reading{font-family:var(--display);font-weight:700;font-size:var(--t-xl);color:var(--ink);line-height:1}
.chute-scale-reading u{text-decoration:none;font-size:var(--t-sm);color:var(--chute-muted);margin-left:4px}
/* The status line is the only thing telling the operator whether the number
   beside it may be trusted, so it never inherits a muted-on-muted treatment. */
.chute-scale-status{flex:1;min-width:120px;font-size:var(--t-sm);color:var(--chute-muted)}
.chute-scale-status.is-good{color:var(--chute-ok);font-weight:600}
.chute-scale-status.is-warn{color:var(--warn);font-weight:600}
.chute-scale-status.is-bad{color:var(--chute-alert);font-weight:600}

/* Reused from the per-product dose fields (work_animal.html) — never had
   CSS anywhere, so warnings and the pregnancy-approval gate were rendering
   invisibly. These are safety-critical displays, not decoration. */
.dose-warning{
  display:flex;align-items:flex-start;gap:var(--s2);margin-top:var(--s3);
  font-size:var(--t-sm);color:var(--warn);
}
.dose-warning.level-warn{color:var(--warn)}
/* Same row shape as .dose-warning, muted instead of warn-toned -- mixing
   instructions, needle size, species notes: informational, not a warning. */
.dose-note{
  display:flex;align-items:flex-start;gap:var(--s2);margin-top:var(--s3);
  font-size:var(--t-sm);color:var(--muted);
}
.pregnancy-safety-warning{
  margin-top:var(--s3);padding:var(--s3);border-radius:var(--r-sm);
  background:rgba(179,38,30,.15);border-left:3px solid var(--alert);
}
.pregnancy-safety-warning b{display:flex;align-items:center;gap:var(--s2);color:var(--alert-2)}
.pregnancy-safety-warning p{margin:var(--s2) 0;font-size:var(--t-sm);color:var(--chute-chip-ink)}
.pregnancy-safety-warning label{display:block;margin-top:var(--s2);font-size:var(--t-sm)}
.pregnancy-safety-warning input[type=text],
.pregnancy-safety-warning input:not([type=checkbox]){width:100%;margin-top:4px}

.chute-adjust{margin-top:var(--s3)}
.chute-adjust summary{
  cursor:pointer;font-size:var(--t-sm);color:var(--chute-muted);font-weight:600;
}
.chute-adjust[open] summary{color:var(--brand)}
.chute-adjust label{display:block;margin-top:var(--s3);font-size:var(--t-sm);color:var(--chute-muted)}
.chute-adjust label > input,.chute-adjust label > select{margin-top:4px}

.chute-more summary{
  cursor:pointer;padding:var(--s4);font-weight:600;color:var(--ink);
  background:var(--chute-card);border:1px solid var(--chute-card-line);border-radius:var(--r);
}
.chute-more[open] summary{border-radius:var(--r) var(--r) 0 0}
.chute-more-fields{
  padding:var(--s4);background:var(--chute-card);border:1px solid var(--chute-card-line);
  border-top:0;border-radius:0 0 var(--r) var(--r);display:flex;flex-direction:column;gap:var(--s3);
}
.chute-more-fields label{font-size:var(--t-sm);color:var(--chute-muted)}
.chute-more-fields label > input,.chute-more-fields label > select,.chute-more-fields label > textarea{margin-top:4px}
.chute-more-fields .choice-grid{margin-bottom:var(--s2)}

/* .choice's light-mode default (line ~494) now matches the chute's own
   surface exactly -- no override needed here. (Previously this repainted
   .choice for a dark chute ground; keep this comment as a marker in case
   the chute theme ever changes again -- a hardcoded color here bit us
   once already when the surrounding theme flipped.) */
.chute .choice:hover{border-color:var(--brand)}
.chute .choice:has(input:checked){border-color:var(--brand);background:var(--brand-tint)}

/* Identify-first redesign (v2.29.0): restructured "More" section --
   Procedures as a chip multi-select (was a checkbox list), Change Tag /
   Reclassify folded in as gate chips whose panels stay closed until tapped
   (a scroll can't brush them by accident), Classification/Status/BCS as
   chip rows instead of <select>s. Presentation only -- same underlying
   form fields post to the same work_animal() handler. */
.more-block{display:flex;flex-direction:column;gap:var(--s2);padding-bottom:var(--s3);border-bottom:1px solid var(--chute-card-line)}
/* An author display: rule beats the UA's [hidden] -- .gate-panel below
   already needs the same guard for exactly this reason. Without it the
   quick-add sheet shows its "is this a bull or heifer calf?" row for
   every category, including the ones that state the sex themselves. */
.more-block[hidden]{display:none}
.more-block:last-child{border-bottom:0;padding-bottom:0}
.more-block > small{font:var(--label);letter-spacing:.1em;text-transform:uppercase;color:var(--chute-muted)}
.choice-chip-grid{display:flex;flex-wrap:wrap;gap:6px}

.hint-note{color:var(--chute-muted);font-size:var(--t-xs);line-height:1.5}
.hint-note b{color:var(--ink);font-weight:600}

.gate-panel{margin-top:var(--s2);padding-top:var(--s3);border-top:1px dashed var(--chute-card-line);display:flex;flex-direction:column;gap:var(--s3)}
.gate-panel[hidden]{display:none}
.gate-panel > small{font:var(--label);letter-spacing:.1em;text-transform:uppercase;color:var(--chute-muted)}

.swatch-row{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}
.swatch{width:100%;aspect-ratio:1;min-height:44px;max-height:var(--tap-glove);border-radius:50%;border:3px solid transparent;cursor:pointer;padding:0}
.swatch.is-on{border-color:var(--brand-on);box-shadow:0 0 0 3px var(--ink)}
.swatch-yellow{background:var(--tag-yellow)}
.swatch-red{background:var(--tag-red)}
.swatch-blue{background:var(--tag-blue)}
.swatch-green{background:var(--tag-green)}
.swatch-orange{background:var(--tag-orange)}
.swatch-white{background:var(--tag-white)}
.swatch.swatch-light{border-color:var(--chute-chip-line)}
.tag-other-color select{margin-top:4px}
.mini-input{
  width:100%;background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);
  border-radius:var(--r-sm);color:var(--ink);font-family:var(--ui);font-size:var(--t-md);padding:11px 12px;
}

.bcs-scale{display:flex;flex-wrap:wrap;gap:5px;padding-bottom:2px}
.bcs-chip{
  flex:none;width:44px;height:44px;border-radius:50%;background:var(--chute-chip-bg);
  border:1px solid var(--chute-chip-line);color:var(--chute-chip-ink);font-family:var(--mono);
  font-size:12.5px;cursor:pointer;display:flex;align-items:center;justify-content:center;
}
.bcs-chip.is-on{background:var(--tag-yellow);border-color:var(--tag-yellow);color:var(--tag-yellow-ink);font-weight:700}

/* ---- identify panel: default screen, search-first ---- */
.status-strip{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2);text-align:center}
.status-strip > div{background:var(--chute-card);border:1px solid var(--chute-card-line);border-radius:var(--r);padding:var(--s3)}
.status-strip b{display:block;font-family:var(--mono);font-size:var(--t-xl);font-weight:600;color:var(--ink)}
.status-strip small{display:block;font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--chute-muted);margin-top:2px}

.identify-search input{
  width:100%;min-height:52px;background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);
  border-radius:var(--r);color:var(--ink);font-family:var(--ui);font-size:16px;padding:0 var(--s4);
}
.identify-search input::placeholder{color:var(--chute-muted)}
.identify-search input:focus{outline:2px solid var(--tag-yellow);outline-offset:1px}

.quickpick-label{display:flex;align-items:baseline;justify-content:space-between}
.quickpick-label small{font:600 11px/1.2 var(--ui);letter-spacing:.1em;text-transform:uppercase;color:var(--chute-muted)}
.quickpick-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2)}
.qp-chip{min-width:0}
.qp-chip{
  display:flex;align-items:center;gap:10px;text-align:left;
  background:var(--chute-card);border:1px solid var(--chute-card-line);border-radius:var(--r);
  padding:10px 12px;cursor:pointer;min-height:56px;
}
/* The chute identify-search filter sets the native `hidden` attribute on
   non-matching chips (chute.js applyIdentifyFilter), but the unqualified
   `display:flex` above outranks the UA default [hidden]{display:none} --
   so every chip stayed visually shown regardless of what was typed, even
   though the underlying filter state was correct. Search looked completely
   broken to the rancher despite working logic underneath. */
.qp-chip[hidden]{display:none}
.qp-chip:hover{border-color:var(--chute-chip-line);background:var(--chute-chip-bg)}
.qp-chip .qn{display:flex;flex-direction:column;min-width:0}
.qp-chip .qn b{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qp-chip .qn small{font-size:11px;color:var(--chute-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qp-empty{grid-column:1/-1;text-align:center;color:var(--chute-muted);font-size:13px;padding:var(--s5) 0}

.back-to-search{
  background:none;border:0;color:var(--chute-muted);font-family:var(--ui);font-size:12.5px;font-weight:600;
  display:flex;align-items:center;gap:4px;padding:0 var(--s2);cursor:pointer;flex:none;
}
.back-to-search:hover{color:var(--brand)}

/* ---- "+ Other" product-picker bottom sheet ---- */
.sheet-backdrop{
  position:fixed;inset:0;background:rgba(10,13,11,.55);z-index:60;
  opacity:0;transition:opacity .2s ease;pointer-events:none;
}
.sheet-backdrop.show{opacity:1;pointer-events:auto}
/* v2.35.0c -- these sheets are SIBLINGS of .chute, not children, so the
   light re-theme v2.30.9c applied to the chute surface never reached them:
   they kept rendering on the retired dark ground, over a light screen. Both
   the product sheet and the new quick-add sheet redefine the same --chute-*
   tokens .chute does, from one place, so a sheet matches the screen it
   slides up over. */
.sheet{
  position:fixed;left:0;right:0;bottom:0;z-index:61;max-height:82vh;display:flex;flex-direction:column;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg) var(--r-lg) 0 0;
  padding:var(--s3) var(--s4) calc(var(--s4) + var(--safe-bottom));
  transform:translateY(100%);transition:transform .22s ease;
  color:var(--ink);
  --chute-muted:var(--muted);
  --chute-card:var(--card);
  --chute-card-line:var(--line);
  --chute-chip-bg:var(--paper);
  --chute-chip-line:var(--line);
  --chute-chip-ink:var(--ink);
  --chute-chip-hover:var(--line-2);
}
.sheet .chip{background:var(--chute-chip-bg);border-color:var(--chute-chip-line);color:var(--chute-chip-ink)}
.sheet .chip.is-on{background:var(--tag-yellow);border-color:var(--tag-yellow);color:var(--tag-yellow-ink)}
.sheet.show{transform:translateY(0)}
.sheet-grip{width:36px;height:4px;border-radius:2px;background:var(--chute-chip-line);margin:0 auto var(--s3)}
.sheet-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s3)}
.sheet-head b{font-family:var(--display);font-weight:700;font-size:18px;color:var(--ink)}
.sheet-close{background:none;border:0;color:var(--chute-muted);font-size:18px;cursor:pointer;padding:var(--s2)}
.sheet-search{
  width:100%;min-height:44px;background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);
  border-radius:var(--r-sm);color:var(--ink);font-family:var(--ui);font-size:15px;padding:0 var(--s3);
  margin-bottom:var(--s3);
}
.sheet-cats{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:var(--s3)}
.cat-chip{
  font-family:var(--ui);font-size:12px;font-weight:600;padding:8px 13px;border-radius:var(--r-pill);
  background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);color:var(--chute-chip-ink);cursor:pointer;
}
.cat-chip.is-on{background:var(--tag-yellow);border-color:var(--tag-yellow);color:var(--tag-yellow-ink)}
.sheet-list{overflow-y:auto;display:flex;flex-direction:column;gap:6px}
.product-row{
  text-align:left;background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);border-radius:var(--r-sm);
  padding:var(--s3);cursor:pointer;color:var(--ink);
}
.product-row:hover{background:var(--chute-chip-hover)}
.product-row b{display:block;font-size:13.5px;font-weight:600}
.product-row .p-recent{color:var(--chute-ok);font-weight:600}
.product-row .p-meta{display:block;margin-top:2px;font-size:11.5px;color:var(--chute-muted)}
.sheet-empty{text-align:center;color:var(--chute-muted);font-size:13px;padding:var(--s5) 0}

/* ---- chute-side intake (v2.35.0c) ----
   A rancher unloading a bought trailer has no CSV and no tag list, only the
   animal in the headgate. Every target here is --tap-glove. */
.btn--chute-new{
  width:100%;min-height:var(--tap-glove);font-size:var(--t-lg);
  background:var(--brand);color:var(--brand-on);border-color:var(--brand);
}
.btn--chute-new:hover{background:var(--brand-2);color:var(--brand-on)}

/* Replaces the old full-screen "Nothing pending" dead end: the identify
   panel now always renders (so quick add is reachable on an empty session)
   and this carries the completion signal that card used to. */
.qp-all-done{
  text-align:center;padding:var(--s5) var(--s4);color:var(--chute-muted);
  display:flex;flex-direction:column;align-items:center;gap:var(--s2);
}
.qp-all-done[hidden]{display:none}
.qp-all-done i{font-size:26px;color:var(--ok)}
.qp-all-done b{color:var(--ink);font-size:var(--t-lg)}
.qp-all-done p{margin:0;font-size:var(--t-sm);max-width:34ch}
.qp-all-done .btn{margin-top:var(--s2);min-height:var(--tap-glove)}

.qp-empty .linkish{
  background:none;border:0;padding:0;font:inherit;font-weight:600;
  color:var(--brand);text-decoration:underline;cursor:pointer;
}

.quick-add-sheet{gap:0}
.quick-add-body{overflow-y:auto;display:flex;flex-direction:column;gap:var(--s3);padding:0 var(--s1) var(--s3) 0}
.quick-add-foot{flex:none;padding-top:var(--s3)}
.quick-add-foot .btn{width:100%;min-height:var(--tap-glove);font-size:var(--t-lg)}

/* The load's shared facts, learned from the first animal rather than
   configured up front -- there is no setup screen to get through with
   gloves on. */
.lotbar{
  display:flex;align-items:center;gap:var(--s3);
  background:var(--brand-tint);border-left:3px solid var(--brand);
  border-radius:var(--r-sm);padding:var(--s2) var(--s3);
}
.lotbar .txt{min-width:0;flex:1}
.lotbar b{display:block;font-size:var(--t-sm);font-weight:600;color:var(--brand)}
.lotbar small{
  display:block;font-size:var(--t-xs);color:var(--ink-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.lotbar-edit{
  flex:none;background:none;border:0;padding:var(--s2);cursor:pointer;
  font-size:var(--t-xs);font-weight:600;color:var(--brand);text-decoration:underline;
  min-height:var(--tap);
}

/* Pre-advanced from the last animal of this load, so the common animal never
   opens a keyboard -- which matters more than any button size, because the
   numeric keypad is what covers the button a gloved thumb is reaching for. */
.tag-number-row{display:flex;align-items:center;gap:var(--s3);margin-top:var(--s2)}
.tag-number-input{
  flex:1;min-width:0;min-height:62px;
  background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);
  border-radius:var(--r);color:var(--ink);
  font-family:var(--mono);font-size:30px;font-weight:600;padding:0 var(--s4);
}
.tag-number-input:focus{
  outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-tint);
}
.tag-auto-note{
  flex:none;font-size:var(--t-xs);font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ok);
}
.tag-auto-note[hidden]{display:none}

.quick-add-error{
  background:var(--warn-tint);border-left:3px solid var(--warn-edge);
  border-radius:var(--r-sm);padding:var(--s3);
  display:flex;flex-direction:column;gap:var(--s2);
}
.quick-add-error[hidden]{display:none}
.quick-add-error b{font-size:var(--t-sm);color:var(--warn)}
.quick-add-error p{margin:0;font-size:var(--t-xs);color:var(--ink-2)}
/* Stacked, not side by side: "Add anyway -- different animal" has a
   min-content width wider than half this sheet, so a two-column grid
   overflowed it. Full-width targets are the better answer with gloves
   on regardless. */
.quick-add-dup-opts{display:grid;grid-template-columns:1fr;gap:var(--s2);margin-top:var(--s1)}
.quick-add-dup-opts .btn{min-width:0;min-height:var(--tap-glove);font-size:var(--t-sm);text-align:center}

.quick-add-more summary{padding:var(--s3) var(--s4);min-height:var(--tap-glove);display:flex;align-items:center}

/* Session rollback now has livestock consequences -- name the animals. */
.undo-created-animals p{margin:var(--s2) 0 0}
.created-animal-list{font-family:var(--mono);font-size:var(--t-sm);color:var(--ink-2)}

/* ---- pasture moisture (v2.36.0c) ----
   Advisory only. The band colours read as information, not as alarm: a dry
   pasture is not an emergency, it is a longer rest than the target assumed. */
.grazing-notes-good{list-style:none;margin:var(--s2) 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.grazing-notes-good li{display:flex;gap:8px;align-items:flex-start;font-size:var(--t-sm);color:var(--ok)}

.grazing-moisture{margin-top:var(--s3);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper)}
.grazing-moisture summary{
  cursor:pointer;padding:10px 12px;font-size:var(--t-sm);font-weight:600;color:var(--ink);
  display:flex;gap:8px;align-items:baseline;min-height:var(--tap);
}
.grazing-moisture summary i{color:var(--info)}
.grazing-moisture.band-slower{border-left:3px solid var(--warn-edge);background:var(--warn-tint)}
.grazing-moisture.band-slower summary i{color:var(--warn)}
.grazing-moisture.band-faster{border-left:3px solid var(--ok-edge);background:var(--ok-tint)}
.grazing-moisture.band-faster summary i{color:var(--ok)}
.moisture-body{padding:0 12px 12px;display:flex;flex-direction:column;gap:var(--s2)}
.moisture-lede{margin:0;font-size:var(--t-sm);color:var(--ink-2)}
.moisture-lede b{color:var(--ink)}
.moisture-caveat,.moisture-source{margin:0;font-size:var(--t-xs);color:var(--muted)}
.moisture-windows{display:flex;flex-wrap:wrap;gap:8px}
.moisture-windows > div{
  flex:1 1 120px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:8px 10px;
}
.moisture-windows span{display:block;font-size:var(--t-xs);letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.moisture-windows b{
  display:block;font-family:var(--mono);font-size:var(--t-lg);font-weight:600;
  font-variant-numeric:tabular-nums;margin-top:2px;
}
.moisture-windows small{display:block;font-size:var(--t-xs);color:var(--muted)}
.moisture-setup{
  margin:var(--s3) 0 0;font-size:var(--t-sm);color:var(--muted);
  display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;
}
.field-hint{display:block;margin-top:4px;font-size:var(--t-xs);color:var(--muted)}
.plain-list{margin:0 0 var(--s3);padding-left:18px;display:flex;flex-direction:column;gap:6px;font-size:var(--t-md)}




.chute-empty{align-items:center;justify-content:center}
.chute-empty .chute-body{align-items:center;justify-content:center;flex:none;padding:var(--s5)}
.chute-empty p{color:var(--chute-muted);margin:var(--s3) 0}

/* Offline sync status (v2.24.0c). .chute-head is a flex row ending in
   .progress, which already claims margin-left:auto to sit flush right --
   this sits between the animal's name and .progress in normal flow, no
   margin of its own, so it never fights that rule for the same space. */
.chute-offline-btn{
  flex:none;width:36px;height:36px;display:flex;align-items:center;justify-content:center;
  background:var(--chute-chip-bg);border:1px solid var(--chute-chip-line);border-radius:var(--r-sm);
  color:var(--chute-chip-ink);
}
.chute-offline-btn:hover{background:var(--chute-chip-hover);color:var(--ink)}
.chute-sync-status{
  flex:none;font-family:var(--mono);font-size:var(--t-xs);color:var(--chute-muted);
  white-space:nowrap;
}
.chute-sync-status.is-ok{color:var(--chute-ok)}
.chute-sync-status.is-alert{color:var(--chute-alert);font-weight:600}
.chute-sync-detail{margin:0 var(--s4) var(--s3)}

/* Global "still queued" pill (static/chute-sync.js) — shown on every page
   EXCEPT chute mode itself, which renders its own in-head status above.
   Reuses .mobile-save-bar's fixed/safe-area pattern; overridden in the
   ≤900px query below to clear .mobile-bottom-nav, which sits at the same
   bottom:0 edge only at that width. */
.chute-outbox-pill{
  position:fixed;left:0;right:0;bottom:0;z-index:40;
  padding:var(--s3) var(--s4);padding-bottom:calc(var(--s3) + var(--safe-bottom));
  background:var(--ink);color:var(--brand-on);font-size:var(--t-sm);font-weight:600;
  text-align:center;box-shadow:0 -4px 16px rgba(20,26,23,.15);
}
.chute-outbox-pill.is-alert{background:var(--chute-alert)}

.offline-ready-note{display:block;margin-top:var(--s2);color:var(--muted);font-size:var(--t-xs)}


/* ==========================================================================
   14  UTILITIES
   ========================================================================== */
.row{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;min-width:0}
.row-tight{gap:var(--s2)}
.push{margin-left:auto}
.grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4)}
.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4)}
.grid-4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s4)}
.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.is-done{opacity:.5}
.nowrap{white-space:nowrap}
.mt-0{margin-top:0}
.mb-0{margin-bottom:0}


/* ==========================================================================
   15  RESPONSIVE
   --------------------------------------------------------------------------
   Two breakpoints, not seven. 1100px collapses the sidebar and the multi-
   column grids. 900px is the phone: bottom nav, single column, safe areas.
   ========================================================================== */
@media (max-width:1100px){
  .app-shell{grid-template-columns:1fr}
  .app-sidebar{
    position:fixed;top:0;left:0;bottom:0;width:280px;z-index:60;
    transform:translateX(-100%);transition:transform .18s ease;
  }
  .app-sidebar.is-open{transform:translateX(0)}
  /* The sidebar goes off-canvas at this width, so the trigger that brings
     it back needs to exist here too -- previously it only appeared at
     900px, leaving 901-1100px with the sidebar hidden and no way to open
     it. This duplicates just the button (not the full phone-width
     rearrangement below, which stays gated at 900px). */
  .utility-bar{padding-left:68px}
  .mobile-menu-button{
    display:inline-flex;align-items:center;justify-content:center;position:fixed;
    top:calc(8px + var(--safe-top));left:12px;z-index:46;
    width:var(--tap);height:var(--tap);flex:none;
    background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);box-shadow:var(--shadow);
  }
  .mobile-sidebar-close{
    position:absolute;top:12px;right:12px;z-index:2;display:grid;place-items:center;
    width:44px;height:44px;padding:0;border:1px solid rgba(255,255,255,.18);
    border-radius:50%;background:rgba(255,255,255,.09);color:#fff;font-size:18px;
  }
  .mobile-sidebar-backdrop{
    display:block;position:fixed;inset:0;z-index:50;
    background:rgba(11,15,13,.45);opacity:0;pointer-events:none;transition:opacity .18s ease;
  }
  .mobile-sidebar-backdrop.is-open{opacity:1;pointer-events:auto}
  .stat-row{grid-template-columns:repeat(3,minmax(0,1fr))}
  .split,.grid-3,.grid-4{grid-template-columns:minmax(0,1fr)}
  .today-grid{grid-template-columns:minmax(0,1fr)}
  .today-cell{border-right:0;border-bottom:1px solid var(--line-2)}
  .today-cell:last-child{border-bottom:0}
}

@media (max-width:900px){
  /* Everything in the chain must be allowed to shrink, or auto-fill grids
     compute a second column that does not fit. This is the fix; the rest of
     this block only matters once it is right. */
  .app-shell,.app-shell > *,.app-main,.app-main > *,
  .panel,.card,form,fieldset{min-width:0}

  h1,h2,h3,.page-head,.section-title{overflow-wrap:anywhere}

  .app-content{padding:var(--s4);gap:var(--s3);padding-bottom:calc(78px + var(--safe-bottom))}
  body.has-save-bar .app-content{padding-bottom:calc(140px + var(--safe-bottom))}

  /* dashboard.html only: phone-native home screen instead of the desktop
     Today band and split panel. */
  .phone-only{display:block}
  .desk-only{display:none}

  .mobile-title{display:block;flex:1;min-width:0;font-weight:600}
  .mobile-title b{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mobile-title small{display:flex;align-items:center;gap:4px;margin-top:2px;color:var(--muted);font-size:var(--t-xs);font-weight:500;white-space:nowrap}
  .online-dot{width:6px;height:6px;border-radius:50%;background:var(--ok);flex:none}
  #mobile-sync-state.is-alert{color:var(--alert);font-weight:700}
  .search-box,.weather-strip{display:none}
  .utility-bar{min-height:60px;padding:calc(10px + var(--safe-top)) var(--s4) 10px 68px;flex-wrap:nowrap;gap:var(--s2)}
  .utility-actions{display:none}

  .mobile-menu-button{
    display:inline-flex;align-items:center;justify-content:center;position:fixed;
    top:calc(8px + var(--safe-top));left:12px;z-index:46;
    width:var(--tap);height:var(--tap);flex:none;
    background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);box-shadow:var(--shadow);
  }
  .sidebar-session-actions{display:block}

  .stat-row{grid-template-columns:repeat(2,minmax(0,1fr))}
  .stat b{font-size:31px}
  .form,.form--3,.grid-2,.choice-grid{grid-template-columns:minmax(0,1fr)}
  .form .full{grid-column:auto}
  .module-heading{align-items:flex-start;gap:var(--s3)}
  .herd-inventory-actions{display:grid;grid-template-columns:1fr;gap:8px;width:100%}
  .herd-status-summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .herd-status-summary > div{display:flex;align-items:center;justify-content:space-between;padding:11px 12px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--card)}
  .herd-status-summary span{font-size:12px;color:var(--muted)}
  .herd-status-summary b{font-size:20px}
  .herd-search{display:grid!important;grid-template-columns:1fr;gap:10px;padding:var(--s4)}
  .herd-search label,.herd-search input,.herd-search .btn{width:100%;min-width:0}
  .herd-search input{display:block;margin-top:6px;min-height:48px;padding:11px 12px;text-overflow:ellipsis;font-size:16px}
  .herd-table-card{display:none}
  .phone-herd-list{display:grid;gap:9px}
  .animal-mobile-card{display:grid;grid-template-columns:44px auto minmax(0,1fr) auto 12px;align-items:center;gap:10px;padding:12px;border:1px solid var(--line);border-radius:var(--r);background:var(--card);box-shadow:var(--shadow);color:var(--ink);text-decoration:none}
  .animal-mobile-card .thumb{width:44px;height:44px;border-radius:var(--r);object-fit:cover}
  .animal-mobile-identity{display:flex;flex-direction:column;min-width:0}
  .animal-mobile-identity b,.animal-mobile-identity small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .animal-mobile-identity b{font-size:15px}.animal-mobile-identity small{color:var(--muted);font-size:11px}
  .animal-mobile-status{padding:4px 7px;border-radius:var(--r-pill);background:var(--ok-tint);color:var(--ok);font-size:var(--t-xs);font-weight:700}

  th,td{padding:10px var(--s4)}
  .panel-head,.panel-body,.bar-list,.ledger,.today-head,.today-cell{padding-left:var(--s4);padding-right:var(--s4)}

  .mobile-bottom-nav{
    display:grid;grid-template-columns:repeat(5,1fr);
    position:fixed;left:0;right:0;bottom:0;z-index:45;
    min-height:64px;padding-bottom:var(--safe-bottom);
    background:var(--card);border-top:1px solid var(--line);
  }
  /* F-003. The bar above is fixed at bottom:0 and NOTHING reserved space for
     it, so the last 64px of a page scrolled to its end sat underneath the nav.
     The footer was the visible casualty -- measured on a 375x812 phone, it
     rendered at y=766-812 against a nav starting at y=748, so the credit link
     could not be tapped at all and elementFromPoint returned the nav instead.

     Worth being precise about what the original finding got wrong: it reported
     this as an 11px tap target. The link IS 11px tall, but `.app-footer a` is
     already covered by the "small by design -- expanded, not enlarged" rule
     further down, which gives it a 44x44 ::after. A pseudo-element does not
     change its parent's getBoundingClientRect(), which is what was measured.
     The target was never too small; it was underneath something. */
  .app-footer{padding-bottom:calc(64px + var(--safe-bottom) + var(--s4))}

  .mobile-bottom-nav a,.mobile-bottom-nav button{
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    background:none;border:0;color:var(--muted);
    font-size:var(--t-xs);font-weight:600;text-decoration:none;
  }
  .mobile-bottom-nav a.active,.mobile-bottom-nav button.active{color:var(--brand)}
  .mobile-bottom-nav i{font-size:16px}

  body.has-save-bar .mobile-save-bar{display:grid;grid-template-columns:1fr 1.4fr}
  body.has-save-bar .mobile-bottom-nav{display:none}

  /* .mobile-bottom-nav only becomes fixed/bottom:0 at this width -- clear
     it here so the pill stacks above it instead of sitting underneath. */
  .chute-outbox-pill{bottom:calc(64px + var(--safe-bottom))}
}


/* ==========================================================================
   16  LEGACY COMPATIBILITY SHIM
   --------------------------------------------------------------------------
   The 83 templates in this repo use class names from the old stylesheet.
   Rewriting all of them in one change would be a diff nobody can review, so
   this section maps the old names onto the new system. Every page therefore
   improves the moment this file lands, and templates migrate one at a time.

   THIS SECTION IS TEMPORARY. It shrinks as templates are ported. When a
   template is migrated to the new class names, delete the rules it was the
   last user of. Track progress in HANDOFF; the target is deleting this
   section entirely, at which point the stylesheet is roughly 40% smaller.

   Nothing new may be added here. New markup uses the names above.
   ========================================================================== */

/* --- buttons --------------------------------------------------------- */
.btn.secondary{background:var(--card);color:var(--brand);border-color:var(--line)}
.btn.secondary:hover{background:var(--brand-tint)}
.btn.small{min-height:34px;padding:6px 12px;font-size:var(--t-sm)}
.btn.full{width:100%}
.btn.danger{background:var(--alert);border-color:var(--alert)}
.danger-button{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:var(--tap);padding:9px 15px;
  background:transparent;color:var(--alert);border:1px solid var(--line);
  border-radius:var(--r-sm);font-weight:600;font-size:var(--t-md);
}
.danger-button:hover{background:var(--alert-tint)}
.danger-button.large{min-height:var(--tap-glove);padding:14px 22px;font-size:var(--t-lg)}
/* Delete sat as a bare underlined text link -- 20x37px -- immediately beside
   Edit, which is a bordered 34px button. Two controls doing the same job in a
   row, styled as if they came from different applications, with the
   DESTRUCTIVE one the smaller and flimsier of the pair. On /calving that is a
   2am-in-a-barn control at under half the touch minimum.

   Given a quiet outline rather than a fill: it now reads as deliberate and
   sits with Edit as a pair, without shouting louder than the safe action
   beside it. */
.link-danger{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:var(--tap);padding:6px 12px;
  border:1px solid var(--alert);border-radius:var(--r-sm);
  background:none;color:var(--alert);text-decoration:none;
  font-weight:600;font-size:var(--t-sm);cursor:pointer;
}
.link-danger:hover{background:var(--alert);color:#fff}
/* Edit sat beside Delete as a bare text link, so the pair read as one button
   and one afterthought -- and on a phone it was a small target next to a
   full-size one (reported from an iPhone against Breeding Records, v3.0.2c).
   Health & Vaccinations already looked right because it writes the .btn
   classes directly; everywhere else uses these containers.
   Every anchor inside .row-actions / .table-actions across all twelve
   templates that use them is an "Edit" -- enumerated, not assumed -- so
   styling them here matches the pair everywhere at once instead of editing
   twelve templates and missing one. Box metrics deliberately mirror
   .link-danger above so Edit and Delete come out the same size and shape. */
.row-actions > a,
.table-actions > a{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:var(--tap);padding:6px 12px;
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--card);color:var(--brand);
  font-weight:600;font-size:var(--t-sm);text-decoration:none;
}
.row-actions > a:hover,
.table-actions > a:hover{background:var(--brand-tint);border-color:var(--brand)}
.link-button{border:0;background:none;color:var(--brand);text-decoration:underline;padding:0;cursor:pointer;font:inherit}
.inactive-row{opacity:.6}
.line-number{color:var(--muted)}
.calving-checks{display:flex;gap:var(--s4);flex-wrap:wrap}
.attention-card{border-left:3px solid var(--warn);background:var(--warn-tint)}
.legacy-rollback-note{border-left:3px solid var(--warn);background:var(--warn-tint)}
.undo-warning-card,.destructive-confirmation{border-left:3px solid var(--alert);background:var(--alert-tint)}
.order-buttons form{display:flex;gap:4px}
.text-button{border:0;background:none;color:var(--brand);font-weight:600;padding:0}

/* --- layout ---------------------------------------------------------- */
.module-heading{
  display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s4);
  flex-wrap:wrap;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:var(--s4) var(--s5);margin-bottom:var(--s4);
  box-shadow:var(--shadow);
}
.module-heading h2{font-size:23px;margin:2px 0}
.module-heading p{margin:0;color:var(--muted);font-size:var(--t-sm)}
.module-actions{display:flex;gap:var(--s2);flex-wrap:wrap}
/* livestock.html's Current Herd/Sold/Deceased/Archived counts -- previously
   had a mobile-only rule (see Responsive) and no desktop styling at all,
   so on desktop it rendered as raw, unstyled text with the label and
   number touching. Same "strip with dividers" language as
   .land-ranch-strip/.today-grid for consistency rather than a new pattern. */
.herd-status-summary{
  display:flex;flex-wrap:wrap;margin-bottom:var(--s4);
  border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);
  box-shadow:var(--shadow);overflow:hidden;
}
.herd-status-summary>div{
  display:flex;align-items:center;gap:var(--s2);flex:1;min-width:130px;
  padding:var(--s3) var(--s4);border-right:1px solid var(--line-2);
}
.herd-status-summary>div:last-child{border-right:0}
.herd-status-summary span{font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;color:var(--muted)}
.herd-status-summary b{font-family:var(--display);font-size:22px;font-weight:700;margin-left:auto;color:var(--ink)}
.heading-fa{color:var(--brand);margin-right:var(--s2)}
.card-title-row{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
/* v2.48.0c -- a settings card whose control is a checkbox + Save rather than
   a link out to another page. Keeps the two on one baseline and stops the
   checkbox stretching across the card on a wide monitor. */
.settings-inline-form{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}

/* v2.52.0c -- B-061. An answer the herd's records did not support. Warn, not
   alert: the answer may still be perfectly good general guidance, and dressing
   it in danger red would train the rancher to ignore the colour that means a
   withdrawal violation. */
.ai-ungrounded{
  margin:var(--s2) 0 0;padding:9px 11px;border-radius:var(--r-sm);
  background:var(--warn-tint);border:1px solid var(--warn-edge-soft);
  font-size:var(--t-sm);color:var(--ink-2);line-height:1.5}
.ai-ungrounded b{color:var(--ink)}
.settings-inline-form .check{margin:0;white-space:nowrap}
.row-actions,.page-actions{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
.row-actions form,.inline-form{display:inline-flex;gap:var(--s2);margin:0}
.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4);margin:var(--s4) 0}
@media (max-width:640px){ .two{grid-template-columns:minmax(0,1fr)} }
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:var(--s3)}
.summary{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s3);margin-bottom:var(--s4)}
.summary > div{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s4);text-align:center;
}
.summary span{display:block;font-size:var(--t-xs);color:var(--muted)}
.summary b{font-family:var(--display);font-size:29px;font-weight:700}
.summary details{margin-top:6px}
.summary summary{font-size:var(--t-xs);font-weight:800;color:var(--brand);cursor:pointer;list-style:none}
.summary summary::-webkit-details-marker{display:none}
.summary details p{margin:6px 0 0;font-size:11px;color:var(--muted)}

/* --- forms ----------------------------------------------------------- */
.form label{display:grid;gap:5px;font:var(--label);letter-spacing:var(--label-track);
  text-transform:uppercase;color:var(--ink-2);min-width:0}
.form label input,.form label select,.form label textarea{
  font:400 var(--t-md)/1.45 var(--ui);text-transform:none;letter-spacing:0;color:var(--ink);
}
.wide,.wide-field{grid-column:1/-1}
.compact{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:640px){ .compact{grid-template-columns:minmax(0,1fr)} }
.check{display:flex;align-items:center;gap:var(--s2);min-height:var(--tap)}
.check input{width:20px;height:20px;flex:none}
.choices{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:var(--s2)}
.choices label{
  display:flex;align-items:center;gap:var(--s2);min-height:var(--tap);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 11px;
}

/* --- dashboard widgets (dashboard_customizer.js depends on these) ----- */
.dashboard-widget{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow);overflow:hidden;min-width:0;display:flex;flex-direction:column;
}
.dashboard-widget-header{
  display:flex;align-items:center;gap:var(--s2);
  padding:var(--s3) var(--s4);border-bottom:1px solid var(--line-2);
}
.dashboard-widget-header h3{font-size:var(--t-md)}
.widget-drag-handle{color:var(--muted);cursor:grab;background:none;border:0;padding:2px}
.widget-drag-handle:active{cursor:grabbing}
.widget-resize-control{margin-left:auto;color:var(--muted);background:none;border:0;padding:2px}
.dash-card,.report-card,.mini-card,.dash-mini{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow);padding:var(--s4);min-width:0;
}
.dash-card h3,.report-card h3{font-size:var(--t-md);margin-bottom:var(--s3)}
.dash-list,.dense-list,.summary-lines{list-style:none;margin:0;padding:0}
.dash-list li,.dense-list li,.summary-lines li{
  display:flex;justify-content:space-between;gap:var(--s3);
  padding:9px 0;border-bottom:1px solid var(--line-2);font-size:var(--t-sm);
}
.dash-list li:last-child,.dense-list li:last-child,.summary-lines li:last-child{border-bottom:0}

/* --- retired -------------------------------------------------------- */
/* The hero occupied the top third of the dashboard to show the ranch its
   own name. Hidden rather than deleted so the markup can come out of
   dashboard.html in its own commit. */
.hero,.hero-command,.command-header,.hero-heading{display:none}
/* The conic-gradient donut could not be labelled or read aloud. .bar-list
   replaces it. */
.donut{display:none}

/* ========================================================================== 
   16.5 FIELD MODE — fast, glove-friendly capture launch point
   ========================================================================== */
.smart-selector{display:flex;flex-direction:column;gap:var(--s3);min-width:0}
.smart-selector-header{display:flex;align-items:center;justify-content:space-between;gap:var(--s3)}
.smart-selector-header h3{font-size:17px}.smart-selector-header p{margin:3px 0 0;color:var(--muted);font-size:12px}
.selected-animal-count{display:flex;align-items:baseline;gap:5px;padding:8px 12px;border-radius:var(--r-pill);background:var(--brand-tint);color:var(--brand);white-space:nowrap}.selected-animal-count b{font-size:20px}.selected-animal-count span{font-size:11px;font-weight:700}
.smart-group-buttons,.pasture-group-buttons{display:flex;align-items:center;gap:7px;flex-wrap:wrap}.pasture-group-buttons > span{font-size:11px;font-weight:700;color:var(--muted)}
.smart-group-buttons button,.pasture-group-buttons button{min-height:var(--tap);padding:7px 14px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--card);color:var(--ink-2);font-size:11px;font-weight:700}.smart-group-buttons button:hover,.pasture-group-buttons button:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-tint)}.smart-group-buttons .clear-group{color:var(--alert)}
.animal-selector{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.animal-choice{display:grid;grid-template-columns:22px minmax(0,1fr);align-items:center;gap:10px;min-height:58px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--card);cursor:pointer}.animal-choice:has(input:checked){border-color:var(--brand);background:var(--brand-tint);box-shadow:inset 0 0 0 1px var(--brand)}
.animal-choice > input{width:20px;height:20px;accent-color:var(--brand)}.animal-choice > span{display:flex;flex-direction:column;min-width:0}.animal-choice b,.animal-choice small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.animal-choice b{font-size:13px}.animal-choice small{color:var(--muted);font-size:var(--t-xs)}
.selector-extra-fields{grid-column:1/-1;display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:4px}
.selector-show-all{align-self:flex-start;min-height:40px;padding:8px 12px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--card);color:var(--brand);font-weight:700}
.smart-selector.preselected-mode .smart-group-buttons,.smart-selector.preselected-mode .pasture-group-buttons{display:none}
.smart-selector.preselected-mode .animal-choice:not(:has(input:checked)){display:none}
.pasture-move-card form{display:flex;flex-direction:column;gap:var(--s4)}
.pasture-move-controls{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s3)}.pasture-move-controls label{display:flex;flex-direction:column;gap:6px;color:var(--ink-2);font-size:12px;font-weight:700}.pasture-move-controls input,.pasture-move-controls select{min-height:44px;width:100%}
.pasture-move-button{align-self:flex-start;min-height:48px}
.quick-birth{scroll-margin-top:72px}.quick-birth-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s3);margin-bottom:var(--s4)}.quick-birth-head h2{font-size:24px;margin:3px 0}.quick-birth-head p{margin:0;color:var(--muted)}
.quick-birth-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}.quick-birth-form label{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:700;color:var(--ink-2)}.quick-birth-form input,.quick-birth-form select{min-height:46px}.quick-birth-form .wide{grid-column:1/-1}.quick-birth-actions{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}.quick-birth-actions .btn{min-height:48px}.quick-birth-actions a{font-size:12px;font-weight:700}
.field-hero{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s5);padding:var(--s5);border-radius:var(--r-lg);background:var(--hero-grad);color:#fff;box-shadow:var(--hero-shadow)}
.field-hero h1{font-family:var(--display);font-size:36px;color:#fff;margin:4px 0 6px}.field-hero p{margin:0;color:var(--hero-body)}
.field-connection{display:grid;grid-template-columns:auto auto;align-items:center;gap:2px 7px;padding:10px 13px;border:1px solid var(--hero-glass-border);border-radius:var(--r-pill);background:var(--hero-glass-bg)}
.field-connection small{grid-column:2;color:var(--hero-eyebrow)}.field-connection .online-dot{background:#8fe0b1}
.field-actions{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s3)}
.field-actions a{display:flex;align-items:center;gap:12px;min-height:76px;padding:14px 16px;border:1px solid var(--line);border-radius:var(--r);background:var(--card);box-shadow:var(--shadow);color:var(--ink);text-decoration:none}
.field-actions i{display:grid;place-items:center;width:38px;height:38px;border-radius:var(--r);background:var(--brand-tint);color:var(--brand);font-size:17px}.field-actions span{display:flex;flex-direction:column}.field-actions small{color:var(--muted);font-size:11px}
.field-search{padding:var(--s4) var(--s5);border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);box-shadow:var(--shadow)}
.field-search > label{display:block;margin-bottom:7px;font:var(--label);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.field-search > div{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;border:2px solid var(--brand);border-radius:var(--r);overflow:hidden;background:#fff}
.field-search > div > i{padding-left:15px;color:var(--brand)}.field-search input{height:52px;border:0!important;box-shadow:none!important;padding:0 12px;font-size:17px}.field-search button{align-self:stretch;min-width:92px;border:0;background:var(--brand);color:#fff;font-weight:700}.field-search > small{display:block;margin-top:7px;color:var(--muted)}
.field-results{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.field-animal-card{border:1px solid var(--line);border-radius:var(--r);background:var(--card);box-shadow:var(--shadow);overflow:hidden}
.field-animal-main{display:grid;grid-template-columns:58px minmax(0,1fr) auto;align-items:center;gap:12px;padding:14px;color:var(--ink);text-decoration:none}.field-animal-main > span:nth-child(2){display:flex;flex-direction:column;min-width:0}.field-animal-main b,.field-animal-main small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.field-animal-main small{color:var(--muted);font-size:11px}
.field-tag{display:grid;place-items:center;min-height:42px;padding:4px;border:1px solid var(--line);border-radius:var(--r);background:var(--paper);font:600 11px var(--mono);text-align:center}
.field-animal-actions{display:grid;grid-template-columns:repeat(3,1fr);border-top:1px solid var(--line-2)}.field-animal-actions a{display:flex;align-items:center;justify-content:center;gap:6px;min-height:46px;border-right:1px solid var(--line-2);color:var(--brand);font-size:12px;font-weight:700;text-decoration:none}.field-animal-actions a:last-child{border-right:0}
.field-empty{grid-column:1/-1;text-align:center;padding:var(--s7);border:1px dashed var(--line);border-radius:var(--r-lg);background:var(--card)}.field-empty > i{font-size:28px;color:var(--muted)}.field-empty h2{margin:10px 0 4px}.field-empty p{color:var(--muted)}

@media(max-width:900px){
  .smart-selector-header{align-items:flex-start}.smart-selector-header p{max-width:220px}.selected-animal-count{padding:6px 10px}
  .smart-group-buttons,.pasture-group-buttons{
    flex-wrap:nowrap;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin;
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);
    mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);
  }
  .smart-group-buttons button,.pasture-group-buttons button{flex:none;min-height:var(--tap)}
  .animal-selector{grid-template-columns:1fr}.animal-choice{min-height:60px}.selector-extra-fields{grid-template-columns:1fr}
  .pasture-move-controls{grid-template-columns:1fr;gap:10px}.pasture-move-card{scroll-margin-top:70px}.pasture-move-button{width:100%}
  .quick-birth{padding:var(--s4)}.quick-birth-head h2{font-size:21px}.quick-birth-head p{font-size:12px}.quick-birth-form{grid-template-columns:1fr;gap:10px}.quick-birth-form .wide{grid-column:auto}.quick-birth-actions{align-items:stretch;flex-direction:column}.quick-birth-actions .btn{width:100%}.quick-birth-actions a{text-align:center}
  .field-hero{align-items:flex-start;padding:var(--s4);gap:var(--s3)}.field-hero h1{font-size:27px}.field-hero p{font-size:12px}.field-connection{display:none}
  .field-actions{grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}.field-actions a{min-height:68px;padding:11px}.field-actions i{width:34px;height:34px}.field-actions small{font-size:var(--t-xs)}
  .field-search{padding:var(--s4)}.field-search input{height:50px;font-size:16px}.field-search button{min-width:72px}
  .field-results{grid-template-columns:1fr}.field-animal-main{grid-template-columns:52px minmax(0,1fr) auto;padding:12px}.field-animal-actions a{min-height:48px}
}

/* v2.28 — Grazing Board / explainable land intelligence */
.land-hero{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s5);padding:var(--s5);border-radius:var(--r-lg);background:var(--hero-grad);color:#fff;box-shadow:var(--hero-shadow)}
.land-hero h1{margin:4px 0 6px;color:#fff;font:700 36px var(--display)}.land-hero p{max-width:720px;margin:0;color:var(--hero-body)}.land-hero-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.land-hero-actions .btn.secondary{border-color:var(--hero-glass-border);background:var(--hero-glass-bg);color:#fff}.sync-chip{display:flex;align-items:center;gap:7px;min-height:40px;padding:0 12px;border:1px solid var(--hero-glass-border);border-radius:var(--r-pill);font-size:12px;font-weight:700;white-space:nowrap}.sync-chip .online-dot{background:#8fe0b1}
.land-ranch-strip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);box-shadow:var(--shadow);overflow:hidden}.land-ranch-strip>div{display:flex;flex-direction:column;gap:2px;padding:15px 18px;border-right:1px solid var(--line-2)}.land-ranch-strip>div:last-child{border-right:0}.land-ranch-strip span{font:var(--label);color:var(--muted);text-transform:uppercase}.land-ranch-strip b{font:700 26px var(--display);color:var(--ink)}.land-ranch-strip small{color:var(--muted)}
.land-alert{display:flex;align-items:center;gap:12px;padding:13px 16px;border:1px solid var(--warn-edge);border-radius:var(--r);background:var(--warn-tint);color:var(--warn)}.land-alert>i{font-size:20px}.land-alert>div{display:flex;flex:1;flex-direction:column}.land-alert span{font-size:12px}.land-alert a{min-height:42px;display:flex;align-items:center;font-weight:800;color:var(--brand)}
.grazing-lanes{display:grid;gap:var(--s4)}.grazing-lane{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--paper);overflow:hidden}.grazing-lane>header{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);padding:14px 17px;border-bottom:1px solid var(--line);background:var(--card)}.grazing-lane>header h2{margin:0;font-size:20px}.grazing-lane>header p{margin:2px 0 0;color:var(--muted);font-size:12px}.grazing-lane>header>span{display:grid;place-items:center;min-width:34px;height:34px;border-radius:50%;background:var(--brand-tint);font-weight:800;color:var(--brand)}.lane-attention>header{border-left:5px solid var(--warn-edge)}.lane-grazing>header{border-left:5px solid var(--brand)}.lane-ready>header{border-left:5px solid var(--ok)}.lane-resting>header{border-left:5px solid var(--muted)}
.grazing-card-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;gap:var(--s3);padding:var(--s3)}.grazing-card{min-width:0;border:1px solid var(--line);border-radius:var(--r);background:var(--card);box-shadow:var(--shadow);overflow:hidden}.grazing-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;padding:15px 16px 10px}.grazing-card-head h3{margin:2px 0 0;font-size:21px}.grazing-state{padding:5px 9px;border-radius:var(--r-pill);background:var(--paper);font-size:var(--t-xs);font-weight:800;text-transform:uppercase;color:var(--ink-2)}.state-attention{background:var(--warn-tint);color:var(--warn)}.state-grazing{background:var(--brand-tint);color:var(--brand)}.state-ready{background:var(--ok-tint);color:var(--ok)}
.grazing-primary-metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));padding:0 16px 13px}.grazing-primary-metrics>div{display:flex;min-width:0;flex-direction:column;padding:8px 9px;border-left:1px solid var(--line-2)}.grazing-primary-metrics>div:first-child{border-left:0;padding-left:0}.grazing-primary-metrics span,.grazing-time-row span{font:var(--label);color:var(--muted);text-transform:uppercase}.grazing-primary-metrics b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:18px}.grazing-primary-metrics small{font-size:11px;color:var(--warn)}
.grazing-time-row{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:0 16px 12px;padding:10px 12px;border-radius:var(--r);background:var(--paper)}.grazing-time-row>div{display:flex;flex-direction:column}.grazing-time-row b{font-size:13px}
.forage-answer{margin:0 16px 12px;padding:12px;border:1px solid var(--line);border-radius:var(--r)}.forage-answer.is-ready{border-color:var(--ok-edge);background:var(--ok-tint)}.forage-answer.needs-data{border-style:dashed;background:var(--paper)}.forage-answer>div{display:flex;flex-direction:column}.forage-answer>div>span{font:var(--label);color:var(--muted);text-transform:uppercase}.forage-answer>div>b{font:700 20px var(--display)}.forage-answer small{color:var(--muted)}.forage-answer details{margin-top:8px}.forage-answer summary{font-size:11px;font-weight:800;color:var(--brand);cursor:pointer}.forage-answer p{margin:8px 0;font-size:11px;color:var(--muted)}.forage-answer dl{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:8px 0}.forage-answer dl div{display:flex;justify-content:space-between;gap:7px;font-size:var(--t-xs)}.forage-answer dd{margin:0;font-weight:700}.estimate-note{font-style:italic}
.grazing-warnings{display:flex;gap:6px;flex-wrap:wrap;margin:0 16px 12px;padding:0;list-style:none}.grazing-warnings li{display:flex;align-items:center;gap:5px;padding:5px 8px;border-radius:var(--r-pill);background:var(--warn-tint);color:var(--warn);font-size:var(--t-xs);font-weight:700}.grazing-animal-row{display:flex;gap:5px;overflow-x:auto;margin:0 16px 12px;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 24px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 24px),transparent 100%)}.grazing-animal-row span{flex:none;padding:4px 8px;border:1px solid var(--line);border-radius:var(--r-pill);font-size:var(--t-xs);font-weight:700}
.grazing-card.is-empty-attention .grazing-primary-metrics,.grazing-card.is-empty-attention .grazing-time-row,.grazing-card.is-empty-attention .forage-answer{display:none}.grazing-card.is-empty-attention .grazing-warnings{margin-top:2px}.lane-attention .grazing-card-list{grid-template-columns:repeat(2,minmax(0,1fr))}
.assumption-list{display:grid;gap:4px;margin:8px 0 0;padding:8px 0 0;border-top:1px solid var(--line-2);list-style:none}.assumption-list li{display:flex;justify-content:space-between;gap:10px;font-size:var(--t-xs)}.assumption-list span{color:var(--muted);text-align:right}
.grazing-history{margin:0 16px 12px;border:1px solid var(--line-2);border-radius:10px;background:var(--paper)}.grazing-history>summary{display:flex;align-items:center;gap:7px;min-height:42px;padding:7px 10px;list-style:none;cursor:pointer;color:var(--ink-2);font-size:11px;font-weight:800}.grazing-history>summary::-webkit-details-marker{display:none}.grazing-history>summary>span{margin-left:auto;display:grid;place-items:center;min-width:22px;height:22px;border-radius:50%;background:var(--card);color:var(--brand)}.grazing-history ol{display:grid;gap:0;margin:0;padding:0 10px 10px;list-style:none}.grazing-history li{display:grid;grid-template-columns:12px 1fr;gap:7px;position:relative;padding:7px 0}.grazing-history li>i{width:8px;height:8px;margin-top:4px;border:2px solid var(--brand);border-radius:50%;background:var(--card)}.grazing-history li:not(:last-child)>i:after{content:"";position:absolute;top:20px;bottom:-7px;left:3px;border-left:1px solid var(--line)}.grazing-history li div{display:flex;flex-wrap:wrap;gap:2px 7px}.grazing-history li b{font-size:11px}.grazing-history li span{color:var(--ink-2);font-size:var(--t-xs)}.grazing-history li small{flex-basis:100%;color:var(--muted);font-size:11px}.grazing-history>p{margin:0;padding:0 10px 10px;color:var(--muted);font-size:var(--t-xs)}
.grazing-actions{display:grid;grid-template-columns:repeat(3,1fr);border-top:1px solid var(--line-2)}.grazing-action{position:relative}.grazing-action>summary{display:flex;align-items:center;justify-content:center;gap:6px;min-height:48px;padding:7px;border-right:1px solid var(--line-2);list-style:none;cursor:pointer;color:var(--brand);font-size:11px;font-weight:800}.grazing-action:last-child>summary{border-right:0}.grazing-action[open]{grid-column:1/-1}.grazing-action[open]>summary{justify-content:flex-start;border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2);background:var(--brand-tint)}.grazing-action>summary::-webkit-details-marker{display:none}.grazing-mini-form{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:14px;background:#fbfcfa}.grazing-mini-form label{display:flex;flex-direction:column;gap:5px;font-size:11px;font-weight:700;color:var(--ink-2)}.grazing-mini-form input,.grazing-mini-form select{min-height:44px}.grazing-mini-form .wide{grid-column:1/-1}.grazing-mini-form button.wide{width:100%;min-height:48px}.move-preview{grid-column:1/-1;display:flex;justify-content:space-between;gap:10px;margin:0;padding:10px;border-radius:9px;background:var(--brand-tint);font-size:12px}.move-preview span{color:var(--muted)}.grazing-lane-empty{grid-column:1/-1;display:flex;align-items:center;justify-content:center;gap:8px;min-height:72px;color:var(--muted)}
.plan-preview{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;margin:0;padding:10px;border:1px solid var(--line);border-radius:var(--r);background:var(--card)}.plan-preview span{display:flex;min-width:0;flex-direction:column}.plan-preview small,.move-impact small{font:var(--label);color:var(--muted);text-transform:uppercase}.plan-preview b{font-size:11px}.plan-preview>i{color:var(--brand)}.move-impact{padding:11px;border:1px solid var(--ok-edge);border-radius:var(--r);background:var(--ok-tint)}.move-impact>p{margin:0;color:var(--muted);font-size:11px}.move-impact-metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}.move-impact-metrics>span{display:flex;min-width:0;flex-direction:column}.move-impact-metrics b{font-size:12px}.move-impact ul{display:flex;gap:5px;flex-wrap:wrap;margin:9px 0 0;padding:0;list-style:none}.move-impact li{padding:4px 7px;border-radius:var(--r-pill);background:var(--warn-tint);color:var(--warn);font-size:11px;font-weight:700}.task-row-link{text-decoration:none;color:inherit}.task-row-link:hover{background:var(--brand-tint)}

@media(max-width:900px){
  .land-hero{align-items:flex-start;padding:var(--s4)}.land-hero h1{font-size:27px}.land-hero p{font-size:12px}.land-hero-actions .btn{display:none}.land-hero .sync-chip{display:none}.land-ranch-strip{grid-template-columns:repeat(2,1fr)}.land-ranch-strip>div{padding:11px 13px;border-bottom:1px solid var(--line-2)}.land-ranch-strip>div:nth-child(2){border-right:0}.land-ranch-strip>div:nth-child(n+3){border-bottom:0}.land-ranch-strip b{font-size:22px}.land-ranch-strip small{font-size:11px}.land-alert{align-items:flex-start}.land-alert a{display:none}
  .grazing-lane>header{padding:12px 13px}.grazing-lane>header h2{font-size:18px}.grazing-lane>header p{font-size:var(--t-xs)}.grazing-card-list,.lane-attention .grazing-card-list{grid-template-columns:1fr;padding:9px}.grazing-card-head{padding:13px 13px 9px}.grazing-primary-metrics{padding:0 13px 11px}.grazing-primary-metrics>div{padding:6px}.grazing-primary-metrics b{font-size:15px}.grazing-time-row,.forage-answer,.grazing-warnings,.grazing-animal-row,.grazing-history{margin-left:13px;margin-right:13px}.forage-answer>div>b{font-size:19px}.grazing-actions{grid-template-columns:repeat(3,1fr)}.grazing-action>summary{min-height:50px;font-size:var(--t-xs)}.grazing-mini-form{grid-template-columns:1fr;padding:12px}.grazing-mini-form .wide,.move-preview{grid-column:auto}.move-preview{flex-direction:column}.move-impact-metrics{grid-template-columns:1fr 1fr}.plan-preview{grid-template-columns:1fr}.plan-preview>i{transform:rotate(90deg);justify-self:center}.grazing-mini-form input,.grazing-mini-form select{min-height:48px;font-size:16px}
}


/* A printed hand-to-buyer document (bill_of_sale.html) needs to hide its
   own app chrome -- the outer page-head, action cards, status buttons --
   without hiding the document body itself. .page-head already disappears
   on print via the rule below; .no-print marks the other on-screen-only
   pieces nested inside the document card that .page-head doesn't reach. */
.bos-signatures{display:grid;grid-template-columns:2fr 1fr;gap:28px var(--s5);margin-top:var(--s5)}
.bos-signatures>div{display:flex;flex-direction:column}
.sig-line{display:block;height:40px;border-bottom:1.5px solid var(--ink-2)}
.bos-signatures small{display:block;margin-top:6px;color:var(--muted);font-size:11px;
  text-transform:uppercase;letter-spacing:.05em}
.bos-signatures small+small{text-transform:none;letter-spacing:0;color:var(--ink-2);
  font-size:12.5px;margin-top:2px}

/* ==========================================================================
   17  PRINT AND ACCESSIBILITY
   ========================================================================== */
@media print{
  .app-sidebar,.utility-bar,.mobile-bottom-nav,.mobile-menu-button,
  .app-footer,.btn,.btn-row,.page-head .actions,.no-print{display:none}
  .app-shell{grid-template-columns:1fr}
  .panel,.card{border-color:var(--print-border);box-shadow:none;break-inside:avoid}
  body{background:var(--card);font-size:11pt}
  th{background:var(--print-th-bg)}
  a{text-decoration:none;color:var(--print-ink)}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important;
  }
}

@media (prefers-contrast:more){
  :root{--line:#9AA69E;--line-2:#C4CDC5;--muted:#4A534E}
}

/* ==========================================================================
   18  WORKING CATTLE SESSION
   --------------------------------------------------------------------------
   working_sessions.html (session list + creation) and
   working_session_detail.html (one session's Pending/Processed/Skipped
   lists, chute search, batch treatment). Light theme -- .card/.form/--brand
   tokens throughout, same as the rest of the (already-good) app; chute mode
   itself stays on the dark --chute-* tokens, untouched here.
   ========================================================================== */

/* --- session creation form (working_sessions.html) --- */
.working-session-header-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--s3);margin-bottom:var(--s3);
}
.working-session-header-grid label{display:grid;gap:5px;font:var(--label);letter-spacing:var(--label-track);
  text-transform:uppercase;color:var(--ink-2);min-width:0}
.working-session-header-grid label.wide{grid-column:1/-1}
.working-session-header-grid input,.working-session-header-grid select,.working-session-header-grid textarea{
  font:400 var(--t-md)/1.45 var(--ui);text-transform:none;letter-spacing:0;color:var(--ink);
}
.working-start-button{margin-top:var(--s3)}

.working-session-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:var(--s3);margin-top:var(--s4)}
.working-session-card p{margin:4px 0 var(--s3);color:var(--muted);font-size:var(--t-sm)}
.working-session-counts{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:var(--s3);text-align:center}
.working-session-counts > div{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px}
.working-session-counts b{display:block;font-family:var(--display);font-size:20px}
.working-session-counts span{font-size:11px;color:var(--muted)}
.working-session-actions{display:flex;gap:var(--s2);flex-wrap:wrap}
.session-status{font-size:var(--t-xs);font-weight:700;padding:3px 9px;border-radius:var(--r-pill);background:var(--brand-tint);color:var(--brand)}
.session-status.status-completed{background:var(--ok-tint,var(--brand-tint));color:var(--ok,var(--brand))}

/* --- session detail: summary strip, search, columns --- */
.working-session-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s3);margin-bottom:var(--s4)}
.working-session-summary .card{text-align:center;padding:var(--s3)}
.working-session-summary .card span{display:block;font-size:var(--t-xs);color:var(--muted)}
.working-session-summary .card b{display:block;font-family:var(--display);font-size:26px;font-weight:700;margin-top:2px}

.chute-search-card{margin-bottom:var(--s4)}
.chute-search.herd-search{margin-bottom:0}
.chute-search-results{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s3)}
.chute-search-results article{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);
}
.chute-search-results article > div{display:flex;align-items:center;gap:var(--s3);min-width:0}
.chute-search-results article b{display:block}
.chute-search-results article small{display:block;color:var(--muted);font-size:var(--t-xs)}
.chute-search-empty{margin-top:var(--s3);color:var(--muted);font-size:var(--t-sm)}

.working-columns{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--s4);margin-bottom:var(--s4);align-items:start}
.work-animal-list{display:flex;flex-direction:column;gap:6px;margin-top:var(--s3)}
.work-animal-list a,.work-animal-list .skipped-row{
  display:flex;align-items:center;gap:var(--s3);padding:var(--s2) var(--s3);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);color:var(--ink);
}
.work-animal-list a:hover{border-color:var(--brand);background:var(--brand-tint)}
.work-animal-list a span,.work-animal-list .skipped-row span{flex:1;min-width:0}
.work-animal-list a b,.work-animal-list .skipped-row b{display:block}
.work-animal-list a small,.work-animal-list .skipped-row small{display:block;color:var(--muted);font-size:var(--t-xs)}
.work-animal-list a i{color:var(--muted);flex:none}
.work-animal-list p{color:var(--muted);font-size:var(--t-sm);margin-top:var(--s3)}
.work-empty{display:flex;flex-direction:column;align-items:center;gap:var(--s2);text-align:center;padding:var(--s5) var(--s3);color:var(--muted)}
.work-empty i{font-size:22px;color:var(--line)}
.work-empty p{margin:0;font-size:var(--t-sm)}

/* S3 scale-file import history, same file. */
.import-log-list{list-style:none;margin:var(--s3) 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.import-log-list li{
  display:flex;justify-content:space-between;gap:var(--s3);
  padding:8px 11px;background:var(--paper);border-radius:var(--r-sm);font-size:var(--t-sm);
}
.import-log-list li span{color:var(--muted);font-size:var(--t-xs);text-align:right}

/* --- batch treatment card: outer structure only -- the animal-selection
   grid above reuses ._smart_animal_selector.html's already-styled
   .smart-selector/.smart-group-buttons/.selected-animal-count classes. --- */
.batch-treatment-card{margin-bottom:var(--s4)}
.batch-treatment-card > summary{cursor:pointer;font-weight:600;font-size:var(--t-lg)}
.batch-treatment-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s3);flex-wrap:wrap;margin:var(--s3) 0}
.batch-treatment-heading p{margin:3px 0 0;color:var(--muted);font-size:var(--t-sm)}
.batch-treatment-animal-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:8px;margin-bottom:var(--s4)}
.batch-treatment-animal-grid label{
  display:flex;align-items:center;gap:var(--s2);padding:var(--s2) var(--s3);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);cursor:pointer;
}
.batch-treatment-animal-grid label.selected{border-color:var(--brand);background:var(--brand-tint)}
.batch-treatment-animal-grid label b{display:block}
.batch-treatment-animal-grid label small{display:block;color:var(--muted);font-size:var(--t-xs)}

.chute-med-toolbar{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin:var(--s3) 0}
.chute-med-toolbar input[type=search]{flex:1;min-width:200px}
.chute-med-chips{display:flex;gap:6px;flex-wrap:wrap}
.chute-med-count{color:var(--muted);font-size:var(--t-xs);white-space:nowrap}

.batch-product-list{display:flex;flex-direction:column;gap:8px}
.batch-product-card{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);padding:var(--s3)}
.batch-product-selector{display:flex;align-items:flex-start;gap:var(--s3);cursor:pointer}
.batch-product-selector b{display:block}
.batch-product-selector small{display:block;color:var(--muted);font-size:var(--t-xs);margin-top:2px}
.batch-product-details{margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--line-2);display:flex;flex-direction:column;gap:var(--s3)}
.batch-product-common{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--s3)}
.batch-draw{display:block;margin-top:6px;font-size:var(--t-xs);color:var(--brand)}
.batch-draw.batch-draw-missing{color:var(--alert)}

.custom-batch-treatment{margin-top:var(--s4)}
.custom-batch-treatment summary{cursor:pointer;font-weight:600}
.batch-treatment-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--s3);margin-top:var(--s3)}
.batch-dose-table td,.batch-dose-table th{white-space:nowrap}
.table-sub{display:block;color:var(--muted);font-size:var(--t-xs)}

@media (max-width:900px){
  .working-session-summary{grid-template-columns:repeat(2,minmax(0,1fr))}
  .working-columns{grid-template-columns:1fr}
}

/* ==========================================================================
   19  ANIMAL PROFILE
   --------------------------------------------------------------------------
   One page, not two: consolidates the two previously-unstyled animal pages
   (animal_profiles.html + the legacy animal_detail.html) into a single
   profile with real design-system styling. Light theme -- .card/--brand/
   --ink tokens, same as the rest of the app; the tag() ear-tag chip is the
   one borrowed piece from chute mode's design language (it already lived
   in _animal_identity.html, section 04).
   ========================================================================== */

.profile-search{display:flex;align-items:flex-end;gap:var(--s3);flex-wrap:wrap;margin-bottom:var(--s4)}
.profile-search label{flex:1;min-width:200px;display:grid;gap:5px;font:var(--label);
  letter-spacing:var(--label-track);text-transform:uppercase;color:var(--ink-2)}
.profile-search label input{font:400 var(--t-md)/1.45 var(--ui);text-transform:none;letter-spacing:0;color:var(--ink)}
.profile-search select{min-width:220px;flex:1}

.profile-hero{margin-bottom:var(--s3)}
.profile-hero-top{display:flex;align-items:flex-start;gap:var(--s4)}
.profile-photo{
  width:76px;height:76px;border-radius:var(--r);flex:none;overflow:hidden;
  background:var(--line-2);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;
}
.profile-photo img{width:100%;height:100%;object-fit:cover}
.profile-photo-placeholder{color:var(--placeholder);font-size:26px}
.profile-id{flex:1;min-width:0}
.profile-id-row{display:flex;align-items:center;gap:8px}
.profile-id-row h1{font-family:var(--display);font-weight:700;font-size:28px;margin:0;color:var(--ink)}
.profile-star{color:var(--tag-yellow);font-size:16px}
.favorite-toggle-form{display:inline-flex;line-height:0}
.favorite-toggle{
  appearance:none;border:0;background:none;padding:6px;margin:0;cursor:pointer;
  color:var(--muted);font-size:16px;line-height:1;border-radius:var(--r-pill);
  min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center;
}
.favorite-toggle:hover{background:var(--surface)}
.favorite-toggle.is-favorite{color:var(--tag-yellow)}
.favorite-toggle--sm{min-width:32px;min-height:32px;padding:2px;font-size:14px}
.profile-id-sub{margin:3px 0 0;color:var(--muted);font-size:var(--t-sm)}
.profile-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:var(--s3)}
.profile-chips .chip{
  font:600 11px/1 var(--ui);padding:6px 10px;border-radius:var(--r-pill);background:var(--paper);
  border:1px solid var(--line);color:var(--ink-2);display:inline-flex;align-items:center;gap:5px;
}
.profile-chips .chip b{font-weight:700;color:var(--ink)}

.profile-banner{
  margin-bottom:var(--s3);padding:12px 14px;border-radius:var(--r-sm);display:flex;gap:10px;
  align-items:flex-start;font-size:var(--t-sm);line-height:1.5;
}
.profile-banner.alert{background:var(--alert-tint);border-left:3px solid var(--alert);color:var(--alert-2)}
.profile-banner.deceased{background:var(--line-2);border-left:3px solid var(--ink-2);color:var(--ink-2)}
.profile-banner i{flex:none;margin-top:2px}
.profile-banner b{display:block;font-size:var(--t-md);margin-bottom:3px;color:inherit}
.profile-banner-line{display:block;margin-top:2px}
.profile-banner a{color:inherit;font-weight:600;text-decoration:underline}

.profile-quick-actions{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:var(--s4)}
/* F-007. These are the five primary actions on an animal's page -- Edit
   Profile, + Health Event, + Breeding, Record Calving, Record Death -- and
   they measured 33px against the product's own --tap standard of 44px.
   The rule is otherwise a copy of .btn, padding and all; it simply dropped
   .btn's `min-height:var(--tap)` line. Restored, so a gloved thumb gets the
   same target here as everywhere else. */
.qa-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:var(--tap);padding:9px 15px;border-radius:var(--r-pill);
  background:var(--brand);color:var(--brand-on);font:600 var(--t-sm)/1 var(--ui);
  border:1px solid var(--brand);text-decoration:none;
}
.qa-btn:hover{background:var(--brand-2);border-color:var(--brand-2)}
.qa-btn.secondary{background:var(--card);color:var(--ink-2);border-color:var(--line)}
.qa-btn.secondary:hover{background:var(--paper);color:var(--ink)}
.qa-btn.danger{color:var(--alert);border-color:var(--alert-edge)}
.qa-btn.danger:hover{background:var(--alert-tint)}

.profile-section-nav{
  position:sticky;top:0;z-index:5;display:flex;gap:2px;background:var(--paper);
  border-bottom:1px solid var(--line);margin-bottom:var(--s4);overflow-x:auto;
  /* On a phone this strip usually has more tabs than fit (Genetics, Photos &
     Docs, History often sit off-screen) -- without a hint, a hard-cut right
     edge looks like the tab list simply ends there. A right-edge fade says
     "more this way" without needing JS scroll-position tracking. Harmless
     when every tab already fits: the mask still applies, but there is
     nothing past the edge to fade. */
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);
  mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);
}
.profile-section-nav button{
  flex:none;border:0;background:none;padding:11px 14px;font:600 var(--t-sm)/1 var(--ui);
  color:var(--muted);border-bottom:2.5px solid transparent;cursor:pointer;white-space:nowrap;
}
.profile-section-nav button.is-on{color:var(--brand);border-bottom-color:var(--brand)}
.profile-section-nav button .n{opacity:.6;font-weight:600;margin-left:2px}

.profile-section[hidden]{display:none}
.profile-block{margin-bottom:var(--s3)}
.profile-block-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s3);gap:var(--s3)}
.profile-block-head h3{margin:0;font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;color:var(--ink-2)}
.profile-block-head a{font-size:var(--t-sm);font-weight:600;color:var(--brand);text-decoration:none}

.profile-stat-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2)}
.profile-stat{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 11px}
.profile-stat small{display:block;font:600 11px/1.2 var(--ui);letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.profile-stat .val{display:flex;align-items:baseline;gap:4px;margin-top:3px}
.profile-stat .val b{font-family:var(--mono);font-size:20px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.profile-stat .val u{text-decoration:none;font-size:var(--t-xs);color:var(--muted)}
.profile-stat .trend{font-size:var(--t-xs);font-weight:700;margin-top:3px}
.profile-stat .trend.up{color:var(--ok)}
.profile-stat .trend.down{color:var(--alert)}
.profile-stat .trend.flat{color:var(--muted);font-weight:600}

.profile-link{
  display:inline-block;margin-top:var(--s3);font-size:var(--t-sm);font-weight:600;color:var(--brand);
  background:none;border:0;padding:0;cursor:pointer;text-align:left;
}

.profile-dl{display:flex;flex-direction:column}
.profile-dl > div{display:flex;justify-content:space-between;gap:var(--s3);padding:7px 0;border-bottom:1px solid var(--line-2)}
.profile-dl > div:last-child{border-bottom:0}
.profile-dl dt{margin:0;font-size:var(--t-sm);color:var(--muted);flex:none}
.profile-dl dd{margin:0;font-size:var(--t-sm);color:var(--ink);font-weight:600;text-align:right;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:60%}

/* --- Cost & Return (v2.47.0c) -------------------------------------------
   A cost stack reads top-down and lands on one number, so the total and the
   net are the only two lines given weight. An absent figure is deliberately
   QUIETER than a real one -- "No prices on file" is not a result, and setting
   it in the same bold as a dollar amount would make an absence look like a
   finding. Tabular figures so the column of money lines up. */
.cost-stack dd{font-variant-numeric:tabular-nums;max-width:65%}
.cost-none{font-weight:400;color:var(--muted);white-space:normal;display:inline-block}
.cost-stack .cost-line-total{border-top:2px solid var(--line);border-bottom:0;margin-top:2px;padding-top:10px}
.cost-stack .cost-line-total dt{color:var(--ink);font-weight:600}
.cost-stack .cost-line-total dd{font-size:var(--t-lg)}
.cost-stack .cost-line-net{border-bottom:0;padding-top:2px}
.cost-stack .cost-line-net dt{font-weight:600}
.cost-stack .cost-line-net dd{font-size:var(--t-lg)}
.cost-stack .cost-line-net.is-up dt,.cost-stack .cost-line-net.is-up dd{color:var(--ok)}
.cost-stack .cost-line-net.is-down dt,.cost-stack .cost-line-net.is-down dd{color:var(--alert)}

.cost-caveat{
  margin:var(--s3) 0 0;padding:8px 10px;border-radius:var(--r-sm);
  background:var(--warn-tint);border:1px solid var(--warn-edge-soft);
  font-size:var(--t-xs);color:var(--ink-2);line-height:1.5}

.cost-method{margin-top:var(--s3);border-top:1px solid var(--line-2);padding-top:var(--s2)}
.cost-method > summary{
  font-size:var(--t-sm);color:var(--brand);font-weight:600;cursor:pointer;
  list-style:none;display:flex;align-items:center;gap:6px}
.cost-method > summary::-webkit-details-marker{display:none}
.cost-method > summary::before{content:"›";font-size:16px;line-height:1;transition:transform .15s ease}
.cost-method[open] > summary::before{transform:rotate(90deg)}
.cost-method p{margin:var(--s2) 0 0;font-size:var(--t-sm);color:var(--ink-2);line-height:1.55}
.cost-method p.hint{line-height:1.5}

.profile-record-chips{display:flex;flex-wrap:wrap;gap:7px}
.rec-chip{
  display:flex;align-items:center;gap:6px;padding:8px 12px;border-radius:var(--r-pill);
  background:var(--paper);border:1px solid var(--line);font-size:var(--t-sm);color:var(--ink-2);
  font-weight:600;cursor:pointer;
}
.rec-chip:hover{border-color:var(--brand);color:var(--brand)}
.rec-chip b{font-family:var(--mono);color:var(--ink);font-weight:700}

.profile-activity{display:flex;flex-direction:column}
.profile-activity .a-row{
  display:flex;gap:10px;padding:9px 0;border-bottom:1px solid var(--line-2);
  text-decoration:none;color:inherit;
}
.profile-activity .a-row:last-child{border-bottom:0}
.profile-activity .a-row:hover .a-body b{color:var(--brand)}
.a-icon{
  width:26px;height:26px;border-radius:50%;flex:none;display:flex;align-items:center;
  justify-content:center;font-size:11px;margin-top:1px;background:var(--brand-tint);color:var(--brand);
}
.a-body{flex:1;min-width:0}
.a-body b{display:block;font-size:var(--t-sm);color:var(--ink)}
.a-body small{display:block;font-size:11.5px;color:var(--muted);margin-top:1px}
.a-time{flex:none;font-size:var(--t-xs);color:var(--placeholder);margin-top:2px;font-variant-numeric:tabular-nums}

.wh-chart{height:56px;display:flex;align-items:flex-end;gap:4px;margin-bottom:var(--s3)}
.wh-bar{flex:1;background:var(--brand-tint);border-radius:3px 3px 0 0;min-height:4px}
.wh-bar.is-latest{background:var(--brand)}

.wrap-table{overflow-x:auto}
table.data{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
table.data th{text-align:left;padding:7px 8px;font:600 11px/1.2 var(--ui);letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--line)}
table.data td{padding:8px 8px;border-bottom:1px solid var(--line-2);color:var(--ink)}
table.data td.num{font-family:var(--mono);font-variant-numeric:tabular-nums}

/* Sire/dam library card (parent_profiles.html) -- photo, details, then an
   Edit/Archived footer row. */
.parent-library-card{display:flex;flex-direction:column;gap:var(--s3)}
.parent-library-card.inactive-card{opacity:.6}
.parent-library-photo{
  display:block;width:100%;aspect-ratio:1/1;border-radius:var(--r-sm);overflow:hidden;
  background:var(--line-2);color:var(--placeholder);
}
.parent-library-photo img{width:100%;height:100%;object-fit:cover;display:block}
.parent-library-photo span{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:28px}
.parent-card-actions{display:flex;align-items:center;justify-content:space-between;gap:var(--s2)}

.parent-pair{display:flex;gap:var(--s3);flex-wrap:wrap}
.parent-card{
  flex:1;min-width:160px;background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:10px;display:flex;gap:9px;align-items:center;
}
.parent-card .ph{width:38px;height:38px;border-radius:50%;object-fit:cover;flex:none;
  background:var(--line-2);display:flex;align-items:center;justify-content:center;color:var(--placeholder)}
.parent-card small{display:block;color:var(--muted);font-size:var(--t-xs);text-transform:uppercase;
  letter-spacing:.06em;font-weight:600}
.parent-card b{display:block;font-size:var(--t-sm);margin-top:1px}
.parent-card span{display:block;font-size:11.5px;color:var(--muted)}

.genetics-strip{display:flex;gap:var(--s2);flex-wrap:wrap}
.gene-chip{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:9px 11px;flex:1;min-width:130px}
.gene-chip small{display:block;color:var(--muted);font-size:var(--t-xs);text-transform:uppercase}
.gene-chip b{display:block;font-size:var(--t-md);margin-top:2px}

.gallery{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:var(--s2)}
.gallery .g-item{margin:0;background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden}
.gallery .g-item img{width:100%;aspect-ratio:1;object-fit:cover;display:block}
.gallery .g-item figcaption{padding:6px 8px;font-size:11px;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.media-actions{margin-top:2px}
.media-actions summary{cursor:pointer;padding:6px 8px;font-size:11px;color:var(--muted);font-weight:600}
.media-actions form{display:flex;flex-wrap:wrap;gap:6px;padding:6px 8px}
.media-actions form input:not([type=checkbox]){flex:1;min-width:100px}

.profile-document-list .doc-row{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:8px 0;border-bottom:1px solid var(--line-2);
}
.profile-document-list .doc-row:last-child{border-bottom:0}

.profile-inline-form{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s3);align-items:flex-end;margin-top:var(--s3)}
.profile-inline-form label{display:grid;gap:5px;font:var(--label);letter-spacing:var(--label-track);
  text-transform:uppercase;color:var(--ink-2);min-width:120px;flex:1}
.profile-inline-form label input,.profile-inline-form label select{
  font:400 var(--t-md)/1.45 var(--ui);text-transform:none;letter-spacing:0;color:var(--ink);
}
.profile-inline-form label.check{display:flex;flex-direction:row;align-items:center;gap:6px;
  text-transform:none;font:400 var(--t-sm)/1.4 var(--ui);color:var(--ink-2);flex:none}

.profile-note{font-size:var(--t-sm);color:var(--ink-2);margin:0 0 var(--s2)}
.profile-empty-note{color:var(--muted);font-size:var(--t-sm)}
.profile-block-label{font-size:11px;text-transform:uppercase;letter-spacing:.04em;
  color:var(--muted);margin:var(--s3) 0 var(--s2);font-weight:600}
.profile-block-label:first-of-type{margin-top:0}

@media (max-width:900px){
  .profile-hero-top{flex-wrap:wrap}
  .profile-stat-row{grid-template-columns:repeat(3,minmax(0,1fr))}
  .parent-pair{flex-direction:column}
}

/* ==========================================================================
   20  ADMIN PORTAL (2.29.4c)
   --------------------------------------------------------------------------
   Platform-level pages (templates/admin_*.html) — reachable with no ranch
   bound at all, so these never reference {{ brand.* }}. Light theme, same
   .card/--brand/--ink tokens as the rest of the app; visually distinct only
   by the dark topbar, which reads as "not a ranch page" at a glance.
   ========================================================================== */

body.admin-portal-page{background:var(--paper);min-height:100vh;min-height:100dvh}

.admin-portal-topbar{
  display:flex;align-items:center;gap:var(--s3);padding:14px 22px;
  background:var(--ink);color:#fff;
}
.admin-portal-mark{
  width:30px;height:30px;border-radius:var(--r-sm);background:rgba(255,255,255,.14);
  display:flex;align-items:center;justify-content:center;font:800 14px/1 var(--display);flex:none;
}
.admin-portal-topbar b{font-family:var(--display);font-weight:700;font-size:16px}
.admin-portal-logout{margin-left:auto}
.admin-portal-logout .btn--secondary{background:transparent;color:#fff;border-color:rgba(255,255,255,.28)}
.admin-portal-logout .btn--secondary:hover{background:rgba(255,255,255,.1)}

.admin-portal-body{max-width:880px;margin:0 auto;padding:var(--s5) var(--s4) var(--s7)}

.admin-portal-back{
  display:inline-flex;align-items:center;gap:5px;font:600 var(--t-sm)/1 var(--ui);
  color:var(--brand);text-decoration:none;margin-bottom:var(--s4);
}
.admin-portal-back:hover{color:var(--brand-2)}

.admin-portal-head{
  display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--s3);
  margin-bottom:var(--s4);
}
.admin-portal-head h2{font-family:var(--display);font-weight:700;font-size:24px;margin:0}
.admin-portal-head .sub{margin:2px 0 0;color:var(--muted);font-size:var(--t-sm)}

.admin-portal-panel{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s4) var(--s5);margin-bottom:var(--s4);
}
.admin-portal-panel h2,.admin-portal-panel h3{font-family:var(--display);font-weight:700;margin:0 0 4px}
.admin-portal-panel .sub{margin:0 0 var(--s3);color:var(--muted);font-size:var(--t-sm)}
.admin-portal-panel--form{max-width:460px}
.admin-portal-panel--form .field{margin-bottom:var(--s3)}
.admin-portal-panel--form form>.btn{margin-top:var(--s2)}
.hint-inline{text-transform:none;font-weight:400;color:var(--muted);letter-spacing:0}

.admin-portal-filters{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center;margin-bottom:var(--s4)}
.admin-portal-filters input[type=search]{flex:1;min-width:220px}
.admin-portal-pager{
  display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--s3);
  margin-top:var(--s4);color:var(--muted);font-size:var(--t-sm);
}
.admin-portal-pager-links{display:flex;gap:var(--s2)}

.admin-portal-table{width:100%;border-collapse:collapse;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.admin-portal-table th{text-align:left;padding:10px 14px;font:600 11px/1.2 var(--ui);
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);background:var(--paper);
  border-bottom:1px solid var(--line)}
.admin-portal-table td{padding:12px 14px;border-bottom:1px solid var(--line-2);font-size:var(--t-sm)}
.admin-portal-table tr:last-child td{border-bottom:0}
.admin-portal-row{cursor:pointer}
.admin-portal-row:hover{background:var(--paper)}
.admin-portal-row:hover .admin-portal-name{color:var(--brand-2)}
.admin-portal-name{font-weight:700;display:block}
.admin-portal-slug{color:var(--muted);font-family:var(--mono);font-size:11.5px;display:block}
.admin-portal-row-go{color:var(--muted);text-align:right}

.admin-portal-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);margin-bottom:var(--s4)}
.admin-portal-stat{background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:12px 14px}
.admin-portal-stat .k{display:block;font:600 11px/1.2 var(--ui);letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);margin-bottom:5px}
.admin-portal-stat .v{display:block;font:700 19px/1.1 var(--display);color:var(--ink);
  font-variant-numeric:tabular-nums}

.btn-caution{display:inline-flex;align-items:center;gap:6px;background:var(--warn-tint);
  color:var(--warn);border:1px solid var(--warn-edge);border-radius:var(--r-sm);
  padding:10px 15px;font:700 var(--t-sm)/1 var(--ui);cursor:pointer}
.btn-caution:hover{background:var(--warn-edge-soft)}

.admin-portal-success{background:var(--ok-tint);border:1px solid var(--ok);border-radius:var(--r);
  padding:var(--s4) var(--s5);margin-bottom:var(--s4)}
.admin-portal-success h2,.admin-portal-success h3{margin:0 0 var(--s3);font-size:var(--t-lg);
  color:var(--ok);display:flex;align-items:center;gap:7px}
.cred-row{display:flex;justify-content:space-between;align-items:center;gap:var(--s3);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:9px 12px;margin-bottom:8px;font-size:var(--t-sm)}
.cred-row b{font-family:var(--mono);word-break:break-all}
.admin-portal-smtp-note{font-size:var(--t-xs);color:var(--ink-2);margin:var(--s3) 0 0;
  line-height:1.5;padding-top:var(--s3);border-top:1px dashed var(--line)}
.admin-portal-smtp-note--ok{border-top-color:var(--ok)}
.admin-portal-smtp-note--ok strong{color:var(--ok)}

.radio-row{display:flex;gap:8px}
.radio-chip{flex:1;border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px;
  cursor:pointer;font-size:var(--t-sm);display:flex;align-items:flex-start;gap:8px}
.radio-chip:has(input:checked){border-color:var(--brand);background:var(--brand-tint);color:var(--brand-2)}
.radio-chip input{margin-top:3px}
.radio-chip small{display:block;font-weight:400;color:var(--muted);margin-top:2px;font-size:11px}

@media (max-width:640px){
  .admin-portal-stats{grid-template-columns:repeat(2,1fr)}
}

/* ==========================================================================
   21  SETTINGS
   --------------------------------------------------------------------------
   Functionally complete before this pass (forms posted correctly, the
   branding modal already opened/closed via JS) but almost entirely
   unstyled -- no size constraint on the logo/icon images (the "huge
   picture" complaint) and no positioning on the modal itself, which
   without CSS was just an inline block, not an overlay.
   ========================================================================== */

.pwa-settings-card{display:grid;gap:var(--s3)}
.pwa-settings-heading{display:flex;align-items:center;gap:var(--s3)}
.pwa-settings-heading img{
  width:56px;height:56px;border-radius:var(--r-sm);object-fit:contain;flex:none;
  background:var(--paper);border:1px solid var(--line);
}
.pwa-settings-card-title{margin:2px 0 2px;font-size:var(--t-lg)}
.settings-card-title{font-size:var(--t-lg)}
.card-title{font-size:var(--t-lg)}
.pwa-settings-heading p{margin:0;color:var(--muted);font-size:var(--t-sm)}
.pwa-capability-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--s2)}
.pwa-capability-grid span{
  display:flex;flex-direction:column;gap:2px;background:var(--paper);
  border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px;
}
.pwa-capability-grid b{font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.pwa-settings-note{font-size:var(--t-sm);color:var(--muted);margin:0}

.install-steps{display:grid;gap:var(--s3)}
.install-steps[hidden]{display:none}
.install-step{
  display:grid;grid-template-columns:24px 24px 1fr;align-items:start;gap:var(--s2);
  padding:10px 12px;background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);
}
.install-step-num{
  display:flex;align-items:center;justify-content:center;width:24px;height:24px;
  border-radius:50%;background:var(--brand-primary,#0b4b32);color:#fff;
  font-size:var(--t-sm);font-weight:700;flex:none;
}
.install-step > i{
  display:flex;align-items:center;justify-content:center;width:24px;height:24px;
  font-size:var(--t-lg);color:var(--brand-primary,#0b4b32);flex:none;
}
.install-step div{display:grid;gap:2px}
.install-step b{font-size:var(--t-sm)}
.install-step small{color:var(--muted);font-size:12px;line-height:1.4}

.settings-launcher-preview{display:flex;align-items:center;gap:var(--s3);margin-top:var(--s3);flex-wrap:wrap}
.settings-launcher-preview b{display:block}
.settings-launcher-preview span{display:block;font-size:var(--t-sm);color:var(--muted)}
.settings-launcher-preview small{display:block;font-size:var(--t-xs);color:var(--muted)}
.branding-launcher-preview img{
  width:48px;height:48px;border-radius:var(--r-sm);object-fit:contain;flex:none;
  background:var(--paper);border:1px solid var(--line);
}
.branding-swatches{display:flex;gap:6px;margin-left:auto}
.branding-swatches span{width:22px;height:22px;border-radius:50%;border:1px solid var(--line);display:block}

/* Shared modal chrome -- reused by Seller Identity and White-Label Branding */
.settings-modal{position:fixed;inset:0;z-index:70;display:flex;align-items:center;justify-content:center;padding:var(--s4)}
.settings-modal[hidden]{display:none}
.settings-modal-backdrop{position:fixed;inset:0;background:rgba(10,13,11,.55)}
.settings-modal-panel{
  position:relative;background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow-lg);
  max-width:640px;width:100%;max-height:88vh;display:flex;flex-direction:column;overflow:hidden;
}
.settings-modal-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s3);
  padding:var(--s4) var(--s5);border-bottom:1px solid var(--line);flex:none;
}
.settings-modal-head h2{margin:2px 0 4px;font-size:var(--t-xl)}
.settings-modal-head p{margin:0;color:var(--muted);font-size:var(--t-sm)}
.settings-modal-close{border:0;background:none;color:var(--muted);font-size:18px;cursor:pointer;padding:4px;line-height:1}
.settings-modal-close:hover{color:var(--ink)}
.settings-modal-body{padding:var(--s4) var(--s5);overflow-y:auto}
.settings-modal-body .form{margin-top:0}
.settings-modal-body form + form{margin-top:var(--s3);padding-top:var(--s3);border-top:1px dashed var(--line);text-align:right}
body.modal-open{overflow:hidden}

.branding-preview{
  display:flex;align-items:center;gap:var(--s3);padding-top:var(--s3);
  border-top:1px dashed var(--line);margin-top:var(--s2);
}
.branding-preview img{
  width:48px;height:48px;border-radius:var(--r-sm);object-fit:contain;flex:none;
  background:var(--paper);border:1px solid var(--line);
}
.branding-preview span{display:block;font-size:var(--t-sm);color:var(--muted)}
.branding-preview small{display:block;font-size:var(--t-xs);color:var(--muted)}

@media (max-width:640px){
  .settings-modal{padding:0}
  .settings-modal-panel{max-width:none;max-height:100vh;height:100vh;max-height:100dvh;height:100dvh;border-radius:0}
}

/* ==========================================================================
   22  CALVING
   --------------------------------------------------------------------------
   Was a single 176-line <details> form -- dam/breeding-record/sire selects,
   six pre-rendered calf cards all visible at once regardless of count. This
   pass makes the dam a searchable tag-picker (mirrors chute mode's identify
   panel, light-themed), splits entry into an Event step then a Calves step,
   and turns count/assistance into tap chips. Sire defaults to literal
   "unknown" -- _calving_sire_from_form() falls back to the breeding record's
   sire on any empty/missing selection, so the default has to be explicit.
   ========================================================================== */

.calving-alert-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4);margin-bottom:var(--s4)}
.calving-watch h3,.overdue-watch h3{margin:0 0 var(--s3);font-size:var(--t-lg)}
.overdue-watch{border-color:var(--alert-edge);background:var(--alert-tint)}
.calving-watch-list{display:grid;gap:var(--s2)}
.calving-watch-list li{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);padding:9px 12px;
}
.overdue-watch .calving-watch-list li{border-color:var(--alert-edge)}
.calving-watch-list li div{display:flex;flex-direction:column;min-width:0}
.calving-watch-list li b{font-size:var(--t-md);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.calving-watch-list li small{color:var(--muted);font-size:var(--t-xs)}
.calving-watch-list li strong{flex:none;font-family:var(--mono);font-size:var(--t-sm)}
.calving-watch-list li.muted{justify-content:center;color:var(--muted);background:transparent;border-style:dashed}

.calving-step-tabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2);margin:var(--s4) 0}
.calving-step-tab{
  display:flex;flex-direction:column;gap:2px;padding:10px 14px;border:1px solid var(--line);
  border-radius:var(--r-sm);background:var(--paper);font-weight:700;font-size:var(--t-md);cursor:pointer;
}
.calving-step-tab .n{font-weight:400;font-size:var(--t-xs);color:var(--muted);text-transform:none;letter-spacing:0}
.calving-step-tab.is-on{background:var(--brand);color:var(--brand-on);border-color:var(--brand)}
.calving-step-tab.is-on .n{color:var(--brand-on);opacity:.8}

.calving-step-pane[hidden]{display:none}
.calving-form .field{margin-bottom:var(--s3)}
.field-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.field-hint{font-size:var(--t-xs);color:var(--muted);margin-top:2px}

/* Dam picker -- search-first, mirrors chute mode's identify panel on light tokens */
.dam-picker-selected{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:10px 12px;border:1px solid var(--brand);border-radius:var(--r-sm);background:var(--brand-tint);
}
.dam-picker-selected[hidden]{display:none}
.dam-picker-change{border:0;background:none;color:var(--brand);font-weight:700;font-size:var(--t-sm);cursor:pointer;padding:4px 6px}
.dam-picker-search[hidden]{display:none}
.dam-picker-input{min-height:48px;font-size:16px}
.dam-picker-grid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2);
  max-height:340px;overflow-y:auto;margin-top:var(--s2);padding-right:2px;
}
.dam-chip{
  display:flex;align-items:center;gap:10px;text-align:left;min-width:0;min-height:56px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 10px;cursor:pointer;
}
.dam-chip[hidden]{display:none}
.dam-chip:hover{border-color:var(--brand);background:var(--brand-tint)}
.dam-chip .dn{display:flex;flex-direction:column;min-width:0}
.dam-chip .dn b{font-size:var(--t-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dam-chip .dn small{color:var(--muted);font-size:var(--t-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dam-picker-empty{grid-column:1/-1;text-align:center;color:var(--muted);font-size:var(--t-sm);padding:var(--s4) 0}
.dam-picker-empty[hidden]{display:none}

#calving-sire-other[hidden]{display:none}

/* Tap chips for count and assistance -- :has(input:checked) syncs state, no JS bookkeeping */
.calving-count-stepper{display:flex;flex-wrap:wrap;gap:var(--s2)}
.calving-count-chip{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
  min-width:56px;min-height:52px;padding:6px 10px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--card);font-weight:700;font-size:var(--t-lg);cursor:pointer;
}
.calving-count-chip small{font-weight:400;font-size:var(--t-xs);letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.calving-count-chip:has(input:checked){background:var(--tag-yellow);border-color:var(--tag-yellow);color:var(--tag-yellow-ink)}
.calving-count-chip:has(input:checked) small{color:var(--tag-yellow-ink);opacity:.75}

.calving-assist-chips{display:flex;flex-wrap:wrap;gap:var(--s2)}
.calving-assist-chip{
  display:inline-flex;align-items:center;min-height:40px;padding:9px 14px;border:1px solid var(--line);
  border-radius:var(--r-pill);background:var(--card);font-weight:600;font-size:var(--t-sm);cursor:pointer;
}
.calving-assist-chip:has(input:checked){background:var(--warn-edge);border-color:var(--warn-edge);color:var(--warn)}
.calving-assist-detail{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3);
  margin-top:var(--s3);padding-top:var(--s3);border-top:1px dashed var(--line);
}
.calving-assist-detail[hidden]{display:none}

.calving-continue-btn{
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:52px;
  margin-top:var(--s4);background:var(--brand);color:var(--brand-on);border:0;border-radius:var(--r-sm);
  font-weight:700;font-size:var(--t-md);cursor:pointer;
}
.calving-continue-btn:hover{background:var(--brand-2)}

/* Calf tabs -- generated one-per-count by calving.js, mirror calving-step-tab visually */
.calf-tabs{display:flex;flex-wrap:wrap;gap:var(--s2);margin-bottom:var(--s3)}
.calf-tab{
  min-height:var(--tap);padding:7px 16px;border:1px solid var(--line);border-radius:var(--r-pill);
  background:var(--paper);font-weight:700;font-size:var(--t-sm);cursor:pointer;
}
.calf-tab.is-on{background:var(--brand);color:var(--brand-on);border-color:var(--brand)}
.calf-tab.has-data::after{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--ok);margin-left:6px;vertical-align:middle}

.calf-intake-card{background:var(--paper);border:1px solid var(--line);border-radius:var(--r);padding:var(--s4);margin-bottom:var(--s3)}
.calf-intake-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s3)}
.calf-intake-grid .wide{grid-column:1/-1}
.calf-check-grid{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s4)}

.calving-save-bar{display:flex;justify-content:flex-end;margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--line)}
.calving-save-bar .btn{min-height:48px;padding:0 28px}

.table-actions{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.tiny-check{display:flex;align-items:center;gap:5px;font-size:var(--t-xs);color:var(--muted);white-space:nowrap}
.tiny-check input{width:14px;height:14px;min-height:0}

@media (max-width:640px){
  .calving-alert-grid,.field-row,.calf-intake-grid,.calving-assist-detail{grid-template-columns:minmax(0,1fr)}
  .dam-picker-grid{grid-template-columns:minmax(0,1fr);max-height:280px}
  .calving-step-tabs{gap:6px}
}

/* ==========================================================================
   23  VACCINES & MEDICATIONS
   --------------------------------------------------------------------------
   Was 101 native <details> elements, each holding an ~44-field form inline
   -- zero CSS existed for any of it (.library-item, .protocol-grid, the
   per-class dose fieldsets), so an open card was raw unstyled form soup, and
   every closed one still cost a full render tree. Rows are now a flat list;
   opening one clones its <template> into a single shared modal, so only the
   product actually being edited is ever live DOM.
   ========================================================================== */

.med-summary{grid-template-columns:repeat(4,minmax(0,1fr))}
.med-summary .stat-warn{color:var(--warn)}

.med-verify-note{background:var(--warn-tint);border-color:var(--warn-edge)}
.med-verify-note p{margin:0;display:flex;align-items:flex-start;gap:10px}
.med-verify-note i{color:var(--warn);margin-top:3px;flex:none}

.med-filter-card{padding:var(--s3) var(--s4)}
.med-filters{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}
.med-filters input[type=search]{flex:1 1 240px;min-width:0}
.med-filters select{flex:0 0 auto;width:auto;min-width:170px}
.med-count{flex:none;margin-left:auto;font-size:var(--t-sm);color:var(--muted);white-space:nowrap}

.med-list{display:flex;flex-direction:column;gap:var(--s2);margin-bottom:var(--s4)}
.med-row-main{
  display:flex;align-items:center;gap:var(--s3);width:100%;text-align:left;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s3) var(--s4);cursor:pointer;
}
.med-row-main:hover{border-color:var(--brand);background:var(--brand-tint)}
.med-row.is-disabled .med-row-main{opacity:.55}
.med-row-info{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}
.med-row-info b{font-size:var(--t-md);font-weight:700}
.med-row-info small{color:var(--muted);font-size:var(--t-xs)}
.route-pill{
  display:inline-block;padding:1px 7px;border-radius:var(--r-pill);
  background:var(--info-tint);color:var(--info);font-weight:600;font-size:var(--t-xs);
  text-transform:uppercase;letter-spacing:.03em;
}
.med-flags{display:flex;flex-wrap:wrap;gap:6px}
.med-tag{
  display:inline-flex;align-items:center;padding:2px 9px;border-radius:var(--r-pill);
  background:var(--line-2);color:var(--ink-2);font-size:var(--t-xs);font-weight:600;
}
.med-tag-ok{background:var(--ok-tint);color:var(--ok)}
.med-tag-warn{background:var(--warn-tint);color:var(--warn)}
.med-row-status{flex:none;font-size:var(--t-sm);font-weight:600;color:var(--muted)}
.med-row-edit-icon{flex:none;color:var(--muted);font-size:13px}
.med-row-main:hover .med-row-edit-icon{color:var(--brand)}
.med-empty{text-align:center;padding:var(--s5) 0}

.med-modal-panel{max-width:760px}

/* The protocol_fields macro's own nested grids -- .form's grid only reaches
   its direct children, so each <details> section needs its own layout. */
.protocol-section{
  grid-column:1/-1;background:var(--paper);border:1px solid var(--line);
  border-radius:var(--r);padding:var(--s3) var(--s4);margin-top:var(--s2);
}
.protocol-section summary{
  cursor:pointer;font-weight:700;font-size:var(--t-md);color:var(--ink);
  list-style:none;display:flex;align-items:center;gap:8px;
}
.protocol-section summary::-webkit-details-marker{display:none}
.protocol-section summary::before{content:"\25B8";color:var(--muted);font-size:11px;transition:transform .15s ease}
.protocol-section[open] summary::before{transform:rotate(90deg)}
.protocol-section .protocol-grid{margin-top:var(--s3)}
.protocol-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--s3)}
.medication-dose-rule-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s3);margin-top:var(--s3);
}
.medication-dose-rule-grid fieldset{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--s3);display:grid;gap:5px;
}

.med-verify-form{
  grid-column:1/-1;background:var(--warn-tint);border:1px solid var(--warn-edge);
  border-radius:var(--r);padding:var(--s3) var(--s4);margin-top:var(--s3);
  display:flex;flex-direction:column;gap:var(--s2);
}
.med-verify-form > b{font-size:var(--t-md)}
.med-verify-form > span{color:var(--ink-2);font-size:var(--t-sm)}
.med-verify-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--s3)}
.med-verify-fields label{display:grid;gap:4px;font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;color:var(--ink-2)}
.med-modal-delete{margin-top:var(--s4);padding-top:var(--s3);border-top:1px dashed var(--line);text-align:right}
.save-row{grid-column:1/-1;display:flex;justify-content:flex-end;margin-top:var(--s2)}

.protocol-template-card .protocol-template-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--s3);margin-top:var(--s3);
}
.protocol-template-grid form{
  display:flex;flex-direction:column;gap:8px;background:var(--paper);border:1px solid var(--line);
  border-radius:var(--r);padding:var(--s4);
}
.protocol-template-grid b{font-size:var(--t-md)}
.protocol-template-grid span{color:var(--muted);font-size:var(--t-sm)}
.protocol-template-grid .btn{align-self:flex-start;margin-top:4px}
.label-disclaimer{font-size:var(--t-xs);line-height:1.5;margin-top:var(--s4)}

@media (max-width:640px){
  .med-summary{grid-template-columns:repeat(2,minmax(0,1fr))}
  .med-count{margin-left:0;flex-basis:100%}
  .med-row-main{flex-wrap:wrap}
  .med-row-status{order:3}
}

/* ==========================================================================
   24  CALENDAR
   --------------------------------------------------------------------------
   Was a flat, unstyled <a> list of every task/AI-step/calving/health/service
   date ever entered, in one long sorted column -- no sense of this week vs.
   next month. Now a real Sunday-first month grid; the day cell markup uses
   display:flex, so [hidden] needs the same explicit override this codebase
   keeps re-learning for any custom element that sets its own display.
   ========================================================================== */

.cal-toolbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:var(--s4)}
.cal-nav{display:flex;align-items:center;gap:4px}
.cal-nav-btn{
  width:34px;height:34px;border-radius:var(--r-sm);border:1px solid var(--line);background:var(--card);
  color:var(--ink-2);font-size:15px;cursor:pointer;display:flex;align-items:center;justify-content:center;
  text-decoration:none;
}
.cal-nav-btn:hover{border-color:var(--brand);color:var(--brand)}
.cal-month-title{font-family:var(--display);font-weight:700;font-size:22px;min-width:170px;text-align:center}
.cal-today-btn{
  height:34px;padding:0 13px;border-radius:var(--r-sm);border:1px solid var(--line);background:var(--card);
  font:600 12px var(--ui);color:var(--ink-2);cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;
}
.cal-today-btn:hover{border-color:var(--brand);color:var(--brand)}
.cal-legend{display:flex;flex-wrap:wrap;gap:12px;margin-left:auto;font-size:11.5px;color:var(--muted)}
.cal-legend span{display:inline-flex;align-items:center;gap:5px}
.cal-legend i{width:8px;height:8px;border-radius:50%;display:inline-block}

.cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px}
.cal-weekday{
  text-align:center;font:700 11px/1.2 var(--ui);letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);padding:4px 0 8px;
}
.cal-day{
  min-height:96px;background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:6px;display:flex;flex-direction:column;gap:4px;cursor:pointer;text-align:left;
}
.cal-day[hidden]{display:none}
.cal-day:hover{border-color:var(--brand);background:var(--brand-tint)}
.cal-day.is-other-month{background:var(--paper);opacity:.55}
.cal-day.is-other-month:hover{opacity:.85}
.cal-day.is-today{outline:2px solid var(--brand);outline-offset:-2px;border-color:var(--brand)}
.cal-day-num{font:700 13px/1 var(--mono);color:var(--ink-2)}
.cal-day.is-today .cal-day-num{color:var(--brand)}
.cal-day-events{display:flex;flex-direction:column;gap:2px;min-width:0}
.cal-chip{display:flex;align-items:center;gap:4px;font-size:var(--t-xs);line-height:1.3;color:var(--ink-2);min-width:0}
.cal-chip i{width:6px;height:6px;border-radius:50%;flex:none}
.cal-chip span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.cal-more{font:600 11px var(--ui);color:var(--muted);margin-top:1px}
.cal-day-dots{display:none}

.dot-task{background:var(--brand)}
.dot-ai{background:var(--info)}
.dot-calving{background:var(--cal-calving)}
.dot-health{background:var(--warn-edge);border:1px solid var(--warn)}
.dot-maint{background:var(--muted)}
.dot-pregcheck{background:var(--cal-pregcheck)}

/* Dashboard mini-calendar -- the full Calendar page was hard to discover
   (buried three sidebar levels deep), so a compact live preview sits on
   the dashboard itself, one click from the real thing. */
.mini-cal{display:block;text-decoration:none;color:inherit;transition:border-color .15s,box-shadow .15s}
.mini-cal:hover{border-color:var(--brand);box-shadow:var(--shadow-lg)}
.mini-cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px;margin-top:10px}
.mini-cal-weekday{text-align:center;font:700 11px/1.2 var(--ui);letter-spacing:.04em;text-transform:uppercase;color:var(--muted);padding-bottom:4px}
.mini-cal-day{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
  height:26px;border-radius:var(--r-sm);font:600 11px var(--mono);color:var(--ink-2);
}
.mini-cal-day.is-other-month{color:var(--muted);opacity:.35}
.mini-cal-day.is-today{background:var(--brand);color:#fff}
.mini-cal-day.is-today b{color:#fff}
.mini-cal-dot{width:3.5px;height:3.5px;border-radius:50%}
.mini-cal-go{display:block;margin-top:12px;font:700 12px var(--ui);color:var(--brand)}

.day-modal{position:fixed;inset:0;z-index:70;display:flex;align-items:center;justify-content:center;padding:16px}
.day-modal[hidden]{display:none}
.day-modal-backdrop{position:fixed;inset:0;background:rgba(10,13,11,.55)}
.day-modal-panel{
  position:relative;background:var(--card);border-radius:var(--r-lg);box-shadow:var(--shadow-lg);
  max-width:440px;width:100%;max-height:80vh;display:flex;flex-direction:column;overflow:hidden;
}
.day-modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:18px 20px;border-bottom:1px solid var(--line)}
.day-modal-head h3{font-family:var(--display);font-weight:700;font-size:19px;margin:2px 0}
.day-modal-close{border:0;background:none;color:var(--muted);font-size:17px;cursor:pointer;padding:4px}
.day-modal-body{padding:10px 14px;overflow-y:auto;display:flex;flex-direction:column;gap:6px}
.day-event-row{display:flex;align-items:center;gap:10px;padding:10px 8px;border-radius:var(--r-sm);text-decoration:none;color:var(--ink)}
.day-event-row:hover{background:var(--paper)}
.day-event-row i{width:9px;height:9px;border-radius:50%;flex:none}
.day-event-row b{display:block;font-size:13px;font-weight:600}
.day-event-row small{display:block;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.04em}
.day-modal-empty{padding:24px;text-align:center;color:var(--muted);font-size:13px}

@media (max-width:640px){
  .cal-day{min-height:64px;padding:4px}
  .cal-day-events{display:none}
  .cal-day-dots{display:flex;gap:3px;flex-wrap:wrap}
  .cal-day-dots i{width:6px;height:6px;border-radius:50%;display:inline-block}
  .cal-legend{width:100%;margin-left:0}
  .cal-weekday{font-size:var(--t-xs)}
  .cal-month-title{min-width:0;flex:1}
}

/* ==========================================================================
   25  PASTURES
   --------------------------------------------------------------------------
   The card grid, the <dl> detail rows and the per-pasture history/activity
   panel had zero CSS -- a bare <dl> stacks dt/dd with no relationship at
   all, which was the actual source of the "clutter" complaint. Add Pasture
   moves off the same-page <details> soup into the shared .settings-modal;
   Move Animals and pasture_edit.html were already styled and are untouched.
   ========================================================================== */

.pasture-summary{grid-template-columns:repeat(4,minmax(0,1fr))}

.pasture-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:var(--s4);margin-top:var(--s4)}
.pasture-card{display:flex;flex-direction:column;gap:var(--s3)}
.pasture-status{background:var(--line-2);color:var(--ink-2)}
.pasture-status--active-grazing{background:var(--ok-tint);color:var(--ok)}
.pasture-status--quarantine,.pasture-status--closed{background:var(--alert-tint);color:var(--alert)}
.pasture-status--resting,.pasture-status--winter-stockpile{background:var(--info-tint);color:var(--info)}

.pasture-metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s2)}
.pasture-metrics > div{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 6px;text-align:center}
.pasture-metrics span{display:block;font-size:var(--t-xs);letter-spacing:.03em;text-transform:uppercase;color:var(--muted);margin-bottom:2px}
.pasture-metrics b{font-family:var(--mono);font-size:var(--t-md);font-weight:600}

.pasture-details{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px var(--s3);margin:0}
.pasture-details div{display:flex;justify-content:space-between;gap:8px;padding-bottom:6px;border-bottom:1px dashed var(--line-2)}
.pasture-details dt{color:var(--muted);font-size:var(--t-xs)}
.pasture-details dd{margin:0;font-weight:600;font-size:var(--t-sm);text-align:right}

.pasture-animal-chips{display:flex;flex-wrap:wrap;gap:6px}
.pasture-chip{
  display:inline-flex;padding:3px 10px;border-radius:var(--r-pill);background:var(--brand-tint);
  color:var(--brand);font-size:11px;font-weight:600;text-decoration:none;
}
.pasture-chip:hover{background:var(--brand);color:var(--brand-on)}

.pasture-history-list{list-style:none;margin:var(--s3) 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.pasture-history-list li{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 10px;
}
.pasture-history-list li.muted{justify-content:center;border-style:dashed}
.pasture-history-list b{display:block;font-size:var(--t-sm)}
.pasture-history-list span{display:block;color:var(--muted);font-size:var(--t-xs)}
.pasture-history-list time{flex:none;font-family:var(--mono);font-size:11px;color:var(--ink-2)}
.pasture-activity-form{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1.4fr) auto;gap:var(--s2);
  align-items:end;margin-top:var(--s3);padding-top:var(--s3);border-top:1px dashed var(--line);
}
.pasture-activity-form label{display:grid;gap:4px;font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;color:var(--ink-2)}
.pasture-activity-form .btn{height:var(--tap)}

.pasture-edit-actions{display:flex;gap:var(--s2)}

@media (max-width:640px){
  .pasture-summary{grid-template-columns:repeat(2,minmax(0,1fr))}
  .pasture-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}
  .pasture-details{grid-template-columns:minmax(0,1fr)}
  .pasture-activity-form{grid-template-columns:minmax(0,1fr)}
}

/* ==========================================================================
   26  HAY INVENTORY
   --------------------------------------------------------------------------
   Already the right shape (a plain add-form, a simple card grid) -- this is
   a visual pass only, not a restructure: the banner, cards and +/-1 buttons
   had no CSS at all and were riding on unstyled defaults.
   ========================================================================== */

.inventory-engine-banner{
  display:flex;align-items:flex-start;gap:var(--s3);background:var(--info-tint);
  border:1px solid var(--line);border-radius:var(--r);padding:var(--s3) var(--s4);margin-bottom:var(--s4);
}
.inventory-engine-banner i{color:var(--info);font-size:16px;margin-top:2px;flex:none}
.inventory-engine-banner b{display:block;font-size:var(--t-sm)}
.inventory-engine-banner span{display:block;color:var(--muted);font-size:var(--t-xs)}

.hay-summary{grid-template-columns:repeat(4,minmax(0,1fr))}
.hay-add-card{margin-bottom:var(--s4)}
.hay-add-card > summary{cursor:pointer;font-weight:700;font-size:var(--t-lg);color:var(--ink)}

.hay-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--s3)}
.inventory-card{display:flex;flex-direction:column;gap:4px}
.inventory-card h3{margin:0;font-size:var(--t-lg)}
.inventory-card-meta{color:var(--muted);font-size:var(--t-xs)}
.inventory-card strong{font-family:var(--mono);font-size:22px;margin-top:4px}
.inventory-card small{color:var(--muted);font-size:var(--t-xs);margin-bottom:6px}

.quick-adjust{display:flex;gap:6px;margin-bottom:8px}
.quick-adjust button{
  flex:1;min-height:36px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--paper);color:var(--ink-2);font-family:var(--mono);font-size:14px;font-weight:600;cursor:pointer;
}
.quick-adjust button:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-tint)}

@media (max-width:640px){
  .hay-summary{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ==========================================================================
   27  PURCHASING
   --------------------------------------------------------------------------
   The line-item form and the dynamically cloned .purchase-line-card already
   had solid structure and JS (purchasing.js) -- this is styling only.
   .purchase-header-grid / .purchase-line-grid / .hay-purchase-fields reuse
   .form's label treatment by carrying the "form" class in the template;
   only their column counts and the line-card chrome are new here.
   ========================================================================== */

.purchase-form-card > summary{cursor:pointer;font-weight:700;font-size:var(--t-lg);color:var(--ink)}
.purchase-header-grid{grid-template-columns:repeat(3,minmax(0,1fr));margin-top:var(--s3)}

.purchase-lines-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s3);margin:var(--s5) 0 var(--s3)}
.purchase-lines-heading h3{margin:0 0 2px}
.purchase-lines-heading p{margin:0;color:var(--muted);font-size:var(--t-sm)}

.purchase-lines{display:flex;flex-direction:column;gap:var(--s3)}
.purchase-line-card{background:var(--paper);border:1px solid var(--line);border-radius:var(--r);padding:var(--s3) var(--s4)}
.purchase-line-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s3)}
.purchase-line-top b{font-size:var(--t-sm);color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.purchase-line-grid{grid-template-columns:repeat(3,minmax(0,1fr))}

.hay-purchase-fields{display:none;grid-template-columns:repeat(3,minmax(0,1fr));margin-top:var(--s3);padding-top:var(--s3);border-top:1px dashed var(--line)}
.hay-purchase-fields.show{display:grid}

.purchase-submit-row{display:flex;align-items:center;gap:var(--s3);margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--line)}
.purchase-submit-row span{color:var(--muted);font-size:var(--t-sm)}

.purchase-summary{grid-template-columns:repeat(4,minmax(0,1fr))}

.purchase-status{display:inline-flex;padding:3px 10px;border-radius:var(--r-pill);font-size:11px;font-weight:700;background:var(--line-2);color:var(--ink-2)}
.purchase-status.status-posted{background:var(--ok-tint);color:var(--ok)}
.purchase-status.status-void{background:var(--alert-tint);color:var(--alert);text-decoration:line-through}
.purchase-status.status-draft{background:var(--warn-tint);color:var(--warn)}

.danger-zone{background:var(--alert-tint);border-color:var(--alert-edge)}
.danger-zone h3{color:var(--alert);margin-top:0}
.danger-zone p{color:var(--ink-2);font-size:var(--t-sm)}

@media (max-width:640px){
  .purchase-header-grid,.purchase-line-grid,.hay-purchase-fields{grid-template-columns:minmax(0,1fr)}
  .purchase-summary{grid-template-columns:repeat(2,minmax(0,1fr))}
  .purchase-lines-heading{flex-direction:column;align-items:flex-start}
  .purchase-submit-row{flex-direction:column;align-items:flex-start}
}

/* ==========================================================================
   28  SALES
   --------------------------------------------------------------------------
   Was every eligible animal rendered as a checkbox card, all at once, with
   per-animal price/weight/note fields inline on every one of them -- fine
   for a handful of head, unusable once a herd gets big. The picker now
   stays empty until a search or group narrows it (search text reuses the
   chute/calving shorthand-token matcher), and only SELECTED animals get
   the price/weight/note row, in a separate list below the picker.
   ========================================================================== */

.sale-picker{background:var(--paper);border:1px solid var(--line);border-radius:var(--r);padding:var(--s4)}
.sale-picker-search{min-height:48px;font-size:16px;margin-bottom:var(--s3)}
.sale-group-chips{display:flex;flex-wrap:wrap;gap:var(--s2);margin-bottom:var(--s3)}
.sale-group-chip{
  display:inline-flex;align-items:center;min-height:36px;padding:7px 13px;border:1px solid var(--line);
  border-radius:var(--r-pill);background:var(--card);font-weight:600;font-size:var(--t-sm);cursor:pointer;
}
.sale-group-chip:hover{border-color:var(--brand)}
.sale-group-chip.is-on{background:var(--brand);border-color:var(--brand);color:var(--brand-on)}

.sale-picker-prompt{text-align:center;color:var(--muted);font-size:var(--t-sm);padding:var(--s5) 0}
.sale-picker-grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:var(--s2);
  max-height:360px;overflow-y:auto;padding-right:2px;
}
.sale-picker-grid[hidden]{display:none}
.sale-pick-chip{
  display:flex;align-items:center;gap:10px;text-align:left;min-width:0;min-height:56px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 10px;cursor:pointer;
}
.sale-pick-chip[hidden]{display:none}
.sale-pick-chip:hover{border-color:var(--brand);background:var(--brand-tint)}
.sale-pick-chip.is-selected{border-color:var(--ok);background:var(--ok-tint)}
.sale-pick-chip .dn{display:flex;flex-direction:column;min-width:0}
.sale-pick-chip .dn b{font-size:var(--t-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sale-pick-chip .dn small{color:var(--muted);font-size:var(--t-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sale-picker-empty{grid-column:1/-1;text-align:center;color:var(--muted);font-size:var(--t-sm);padding:var(--s4) 0}
.sale-picker-empty[hidden]{display:none}

.sale-selected{margin-top:var(--s4)}
.sale-selected-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:var(--s2)}
.sale-selected-head h4{margin:0;font-size:var(--t-md)}
.sale-selected-head span{color:var(--muted);font-size:var(--t-sm)}
.sale-selected-empty{color:var(--muted);font-size:var(--t-sm);text-align:center;padding:var(--s4);border:1px dashed var(--line);border-radius:var(--r-sm);margin:0}
.sale-selected-list{display:flex;flex-direction:column;gap:var(--s2)}
.sale-selected-row{
  display:grid;grid-template-columns:auto minmax(0,1fr) repeat(3,minmax(0,120px)) auto;gap:var(--s3);
  align-items:end;background:var(--card);border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s3);
}
.sale-selected-row[hidden]{display:none}
.sale-selected-name{grid-column:2;display:flex;flex-direction:column;justify-content:center;min-width:0}
.sale-selected-row label{display:grid;gap:4px;font:var(--label);letter-spacing:var(--label-track);text-transform:uppercase;color:var(--ink-2)}
.sale-row-remove{
  align-self:center;width:32px;height:32px;border:0;border-radius:50%;background:var(--alert-tint);
  color:var(--alert);cursor:pointer;font-size:13px;
}
.sale-row-remove:hover{background:var(--alert);color:#fff}

@media (max-width:640px){
  .sale-picker-grid{grid-template-columns:minmax(0,1fr);max-height:300px}
  .sale-selected-row{grid-template-columns:auto minmax(0,1fr) auto}
  .sale-selected-row label{grid-column:1/-1}
}

/* Both in-page animal pickers are max-height + overflow-y lists, and neither
   had an edge. On a phone that reads as a fault rather than a feature: the
   last card is sliced through the middle and the next form label starts
   immediately under the cut, so the calving picker looked like it had
   failed to render rather than like a list you can scroll (reported from an
   iPhone, v3.0.2c).
   Giving them a real well fixes it without changing the behaviour the
   operator actually liked. The border says where the list stops; the tinted
   ground -- paper inside a white card -- makes the chips read as contents of
   a container rather than as more page. Defined after both pickers so this
   wins the padding, and outside the media query because the ambiguity is
   worse on a phone but present at every width.
   The scroll behaviour itself is deliberately untouched. */
.dam-picker-grid,
.sale-picker-grid{
  border:1px solid var(--line);
  border-radius:var(--r-sm);
  background:var(--paper);
  padding:var(--s2);
}

/* ==========================================================================
   29  REPORTS
   --------------------------------------------------------------------------
   .report-grid and .report-card were referenced everywhere but never
   styled -- .report-card sat on a bare <a> with no display rule, so ten of
   them just ran together as inline text. .report-critical (also used on
   Sales/Users/Restrictions/etc. as a shared "make this card read urgent"
   modifier) had the same gap; fixed once here, benefits every page that
   already references it.
   ========================================================================== */

.report-critical{background:var(--alert-tint);border-color:var(--alert-edge)}
.report-critical h3{color:var(--alert)}

.report-summary-grid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
/* F-001. These stat tiles use the same <div class="card"><span>label</span><b>value</b></div>
   shape as the working-session summary strip, but only that strip ever got the rule that makes
   the label and the value stack. Here both stayed inline and ran together, so the Death Loss
   screen read "Deaths in 20261" -- the year fused to its own count -- and the repro board's
   status tiles fused the same way ("Open5"). Same declarations as
   .working-session-summary .card, applied to the container that was missing them. */
.report-summary-grid .card{text-align:center;padding:var(--s3)}
.report-summary-grid .card span{display:block;font-size:var(--t-xs);color:var(--muted)}
.report-summary-grid .card b{display:block;font-family:var(--display);font-size:26px;font-weight:700;margin-top:2px}

.report-section{margin-top:var(--s5)}
.report-section-title{
  font:700 11px/1.2 var(--ui);letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);margin:0 0 var(--s3);
}

.report-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:var(--s3)}
.report-card{
  display:flex;flex-direction:column;gap:6px;text-decoration:none;color:var(--ink);
}
.report-card:hover{border-color:var(--brand);box-shadow:var(--shadow-lg)}
.report-card i{
  display:flex;align-items:center;justify-content:center;width:36px;height:36px;
  border-radius:var(--r-sm);background:var(--brand-tint);color:var(--brand);font-size:15px;margin-bottom:2px;
}
.report-card b{font-size:var(--t-md)}
.report-card span{color:var(--muted);font-size:var(--t-xs);line-height:1.45}

/* ==========================================================================
   30  BUSINESS HUB
   --------------------------------------------------------------------------
   New /business landing page for the PWA bottom-nav "Business" button --
   previously that button only opened the sidebar, unlike the real
   Today/Herd/Work/Land pages. Hero + strip now share the same --hero-grad
   treatment as Today/Work/Land (a v2.30.4c consistency fix -- this used to
   carry its own slate/navy gradient "so it reads as its own destination,"
   but that made it the one hub of four that broke from the rest of the
   product's colour language, which reads as inconsistency rather than
   intentional differentiation). The quick-link tiles below still reuse
   .report-section/.report-grid/.report-card verbatim rather than
   inventing a fourth card style.
   ========================================================================== */
.business-hero{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s5);padding:var(--s5);border-radius:var(--r-lg);background:var(--hero-grad);color:#fff;box-shadow:var(--hero-shadow)}
.business-hero h1{margin:4px 0 6px;color:#fff;font:700 36px var(--display)}
.business-hero p{max-width:640px;margin:0;color:var(--hero-body)}
.business-hero-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}

.business-strip{grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}
.business-strip>div{display:flex;flex-direction:column;gap:2px}
.business-strip small{color:var(--muted);font-size:11px}

@media(max-width:900px){
  .business-hero{align-items:flex-start;padding:var(--s4);gap:var(--s3)}
  .business-hero h1{font-size:27px}
  .business-hero p{font-size:12px}
}

/* Shown in place when a save could not go out. Deliberately warm rather than
   alarming: nothing has been lost, and the rancher is standing in a pasture
   with a cow in a chute. */
.offline-notice{
  margin:0 0 var(--s3);padding:12px 14px;
  border:1px solid var(--warn-edge);border-radius:var(--r-sm);
  background:var(--warn-tint);color:var(--warn);
  font-size:var(--t-sm);font-weight:600;line-height:1.5;
}

/* ==========================================================================
   GLOVE PASS -- override layer, deliberately LAST in this file.
   --------------------------------------------------------------------------
   This first lived inside the main phone breakpoint and silently lost:
   `.grazing-history>summary{min-height:42px}` has identical specificity to
   `.grazing-history > summary` here, so whichever comes later wins -- and at
   ~1500 lines earlier, this one did not. Same trap for the sale and inventory
   chips. Keeping the whole pass at the end makes it an override layer rather
   than a hopeful suggestion.
   ========================================================================== */
@media (max-width:767px){
  /* ====================================================================
     GLOVE PASS (Rancher-10, criterion 1) -- phone only.
     --------------------------------------------------------------------
     --tap is already declared 44px at the top of this file and .btn already
     honours it. The failures were six rules that override it DOWNWARD, and
     on a phone that was 36-41 of every screen's tappable controls: the whole
     sidebar nav at 35px, small buttons at 34px, a dismiss link at 19px.
     Meanwhile the chute has used 54px throughout. The app owned the right
     standard and applied it on one screen.

     Two different tools on purpose, because "make everything 44px" would
     look like a kiosk:
       - Controls that look BETTER larger simply grow. A 35px nav row is
         cramped; at 44px the sidebar gains proper vertical rhythm.
       - Controls that should stay visually small keep their size and get an
         invisible hit area instead (.tap-target above).
     Desktop keeps its denser controls -- this is scoped to the phone, where
     the finger is. ==================================================== */
  .btn--sm{min-height:var(--tap)}

  .app-nav .workspace-links a{
    min-height:var(--tap);display:flex;align-items:center;
  }

  .sidebar-session-actions button,
  .sidebar-session-actions a{min-height:var(--tap)}

  /* Row/table actions are the Edit-and-Delete pairs. Both are real controls
     and both should be reachable without aiming. */
  .row-actions a,.row-actions button,
  .table-actions a,.table-actions button{
    min-height:var(--tap);display:inline-flex;align-items:center;justify-content:center;
  }

  /* <summary> is a real control -- it is how "Add Expense", "Add Breeding" and
     "Show the math" open. They were 15-20px. Grown rather than given an
     invisible hit area, because nine "Show the math" toggles stacked down the
     Reports page would otherwise have overlapping 44px phantom areas stealing
     each other's taps -- and at 15px they were cramped anyway, so the height
     is a visual improvement as well as a reachable one. */
  summary{min-height:var(--tap);display:flex;align-items:center}

  /* 40x40 -- four pixels short. */
  .phone-greeting-calendar{min-width:var(--tap);min-height:var(--tap)}

  /* Controls carrying a hardcoded sub-44px minimum of their own, which beat
     the generic rules above on specificity. Every one is a real control:
       .calving-assist-chip  the calving-ease scale -- Unassisted / Hard Pull /
                             C-Section -- tapped at 2am in a barn, at 40px
       .quick-adjust button  the dose and weight nudges
       .favorite-toggle--sm  32px, the smallest control in the product
       .grazing-history>summary, .land-alert a, .selector-show-all,
       .utility-button, .btn.small, .sale-group-chip
     Listed explicitly rather than raised with a blanket !important, so a
     future control that wants to be small has to say so on purpose. */
  .calving-assist-chip,
  .quick-adjust button,
  .favorite-toggle--sm,
  .grazing-history > summary,
  .land-alert a,
  .selector-show-all,
  .utility-button,
  .btn.small,
  .sale-group-chip{min-height:var(--tap)}
  .favorite-toggle--sm{min-width:var(--tap)}

  /* Deliberately NOT touched: links inside prose ("Use Bull Turnouts",
     "Working Cattle"). They sit mid-sentence, so a 44px hit area would
     overlap the lines above and below and start stealing taps from other
     text. They are cross-references, not primary controls -- every one of
     them has a full-size button or nav entry reaching the same place. */

  /* A checkbox in a table cell with no label around it has only its own 20px
     box as a target. Wrapping it in a label (see weaning.html) makes the whole
     cell toggle it, which is both the accessible markup and the reachable one. */
  .cell-check{
    display:flex;align-items:center;justify-content:flex-start;
    min-width:var(--tap);min-height:var(--tap);cursor:pointer;
  }
  .cell-check input[type=checkbox]{width:22px;height:22px}

  /* The drawer's close button is absolutely positioned over the header, so a
     ranch name longer than a couple of words runs underneath it -- "DIAMOND
     CROSS E RANCH" rendered as "DIAMOND CROSS E RANC[x]", 29px of the name
     hidden behind the control. Reserve the button's width, and ellipsis
     anything still too long rather than letting it collide. */
  .sidebar-brand-copy{padding-right:52px;min-width:0}
  .sidebar-brand-copy h2{
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }

  /* The show/hide eye on the sign-in form: 32x32, and the first control a
     rancher ever touches in this product. */
  .password-toggle{min-width:var(--tap);min-height:var(--tap)}

  /* Small by design -- expanded, not enlarged. */
  .link-quiet,
  .app-footer a,
  .table-cards td a,
  td a{position:relative}
  .link-quiet::after,
  .app-footer a::after,
  .table-cards td a::after,
  td a::after{
    content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    width:100%;height:100%;min-width:var(--tap);min-height:var(--tap);
  }

}

/* v2.58.0c — pre-chute supply forecast. A shortfall is the whole point of the
   panel, so it reads as an alert rather than another table row. */
.supply-forecast tr.is-short td{background:var(--alert-tint)}
.supply-forecast tr.is-short b{color:var(--alert-2)}
.supply-forecast small{display:block;color:var(--muted);font-size:var(--t-xs)}

/* M-02 — withdrawal provenance on the compliance screen. Quiet when the operator
   has checked the bottle, visible when nobody has. Not an alarm: an unchecked
   label is the honest default for all 95 shipped products, and shouting about it
   on every row would train people to ignore the row. */
.verified-label{display:block;color:var(--ok);font-size:var(--t-xs)}
.unverified-label{display:block;color:var(--warn);font-size:var(--t-xs);font-weight:600}

/* --- v2.67.0c: import column mapping ------------------------------------
   The panel that tells a rancher which of his spreadsheet columns we could
   not read, and offers a suggested home for each one.

   Sizes are tokens only. v2.62-2.65 established a hard floor at --t-xs (11px)
   after a legibility pass found text down at 7.5px; sample values and reasons
   are the kind of secondary text that invites a 10px "just this once".        */
.import-columns h3{margin:0 0 var(--s2);font-size:var(--t-lg)}
.import-columns>p{font-size:var(--t-sm);margin:0 0 var(--s3)}

/* icon + one span, and nothing else: a flex container turns every inline
   child into its own column, so a <b> inside the sentence would break the
   sentence into pieces. Caught by looking at the page, not by a test. */
.import-blocker{
  display:flex;gap:var(--s2);align-items:flex-start;
  background:var(--alert-tint);border:1px solid var(--alert-edge);
  border-radius:var(--r);padding:var(--s3);color:var(--alert-2);
}

/* A "we did read these" line, so the panel is not purely a list of failures
   and the rancher can tell at a glance that the rest of the file landed. */
.import-read-ok{color:var(--muted)}
.import-read-ok .chip{margin:0 var(--s1) var(--s1) 0;font-size:var(--t-xs)}

/* Model output is labelled as model output. v2.52.0c settled that a prompt
   rule is a request and only a retrieval-derived flag is a fact -- a column
   suggestion is neither, so it is badged and it arrives unticked. */
.ai-badge{
  display:flex;gap:var(--s2);align-items:flex-start;
  background:var(--warn-tint);border:1px solid var(--warn-edge-soft);
  border-radius:var(--r);padding:var(--s2) var(--s3);
  color:var(--warn);font-size:var(--t-xs);font-weight:600;
}

.import-suggestions,.import-unused{list-style:none;margin:var(--s3) 0;padding:0}
.import-suggestions li,.import-unused li{
  border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s3);margin-bottom:var(--s2);
}
/* The whole label is the hit area: this is ticked in a farm office on a
   phone, and a 13px checkbox on its own is not a tap target. */
.import-suggestions label{
  display:flex;align-items:center;gap:var(--s2);
  min-height:var(--tap);font-size:var(--t-md);cursor:pointer;
}
.import-suggestions input[type=checkbox]{width:20px;height:20px;flex:none}

.import-samples{display:block;color:var(--muted);font-size:var(--t-xs)}
.import-reason{color:var(--ink-2);font-size:var(--t-xs);margin-top:var(--s1)}
.import-ai-note{color:var(--warn);font-size:var(--t-sm);font-weight:600}

/* The columns with no suggestion are NOT part of the form above them, and at
   phone width they otherwise sit 8px under its button and read as if they
   were. Seen on a 375px screen, not in a test. */
.import-columns form + .import-unused{
  margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--line-2);
}

/* --- v2.68.0c: reading a photographed receipt ---------------------------- */
.receipt-read h3{margin:0 0 var(--s2);font-size:var(--t-lg)}
.receipt-read p{font-size:var(--t-sm);color:var(--muted);margin:0 0 var(--s3)}

.receipt-proposal .ai-badge{margin-bottom:var(--s3)}
.receipt-lines{width:100%;font-size:var(--t-sm)}
.receipt-lines td:last-child,.receipt-lines th:last-child{text-align:right;white-space:nowrap}
.receipt-lines-total b,.receipt-lines-total td{font-weight:700}
.receipt-lines-total td{border-top:1px solid var(--line)}

.receipt-agrees{display:flex;gap:var(--s2);align-items:flex-start;
  color:var(--ok);font-size:var(--t-sm);font-weight:600}
/* --warn, not --alert: most of these notes are "I left this blank for you",
   which is the system behaving correctly, not an emergency. The v2.66.0c
   lesson holds -- red on every receipt teaches people to ignore red. */
.receipt-note{display:flex;gap:var(--s2);align-items:flex-start;
  color:var(--warn);font-size:var(--t-sm);font-weight:600}
.receipt-note-quiet{color:var(--muted);font-size:var(--t-xs);margin-top:var(--s3)}

/* A machine-filled field has to LOOK machine-filled, or it gets scrolled past
   like anything else already on the form. This is the money field. */
.was-read input,.was-read select{
  background:var(--warn-tint);border-color:var(--warn-edge-soft);
}
.read-flag{
  display:inline-block;margin-left:var(--s2);padding:1px 6px;border-radius:var(--r-pill);
  background:var(--warn-tint);color:var(--warn);
  font-size:var(--t-xs);font-weight:700;text-transform:uppercase;letter-spacing:.04em;
}
.receipt-attached{display:flex;gap:var(--s2);align-items:center;
  color:var(--muted);font-size:var(--t-sm);margin:0 0 var(--s3)}
