/* ═══════════════════════════════════════════════════════════════════════════
   newworld-wdp — the one stylesheet. Vanilla CSS, OKLCH tokens, semantic
   selectors, no build step (canon: .claude/canon/style.md). The foundation:
   the Irrigator look re-expressed in the canon register, contrast-verified.
   Spec: claude/releases/v0.2/sprints/v0.2.0/research_v0.2.0.md (§2.1 tokens,
   §3 components, §4 auth layout). v0.2.1.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: light;                       /* the canon is a light design — keep native controls light */

  /* ── LAYER 1 · Neutral architecture — CANON DEFAULTS (one fix: --text-muted). ── */
  --surface:        oklch(0.99 0.004 250);   /* app background — near-white  #FAFCFE */
  --surface-raised: oklch(1.00 0     0  );   /* cards, the auth panel        #FFFFFF */
  --surface-sunken: oklch(0.97 0.005 250);   /* inputs, wells, table stripes #F3F5F8 */
  --border:         oklch(0.90 0.006 250);   /* hairline borders (decorative)#DBDEE2 */
  --text:           oklch(0.25 0.01  250);   /* primary text                 #1E2226 */
  --text-muted:     oklch(0.54 0.01  250);   /* secondary / meta / muted headings — clears 4.5:1 on all 3 bgs */
  --slate:          oklch(0.356 0.039 249);  /* = #2c3e50 — footer version strip ONLY */

  /* ── LAYER 2 · The client seam — Irrigator's GiSC blue #0078bf (the only per-client values). ── */
  --accent:          oklch(0.55 0.14 245);   /* ≈ #0078bf — btn fill, links, focus ring */
  --accent-hover:    oklch(0.50 0.14 245);   /* ~0.05 L darker (legacy hover #005a8f)   */
  --accent-contrast: oklch(1.00 0    0  );   /* TRUE white on accent fills (label 4.73:1) */
  --accent-text:     oklch(0.50 0.14 245);   /* accent AS TEXT on a non-white surface (5.40:1 on sunken) */

  /* ── LAYER 3 · Operational status. The six legacy greens collapse into ONE --success. ── */
  --success:      oklch(0.62 0.14 150);      /* NON-TEXT: border / icon / dot */
  --success-text: oklch(0.52 0.13 150);      /* darker green for green LABEL text (5.19:1) */
  --warn:         oklch(0.75 0.14 80 );      /* LIGHT fill, carries DARK --text (7.08:1), NEVER white */
  --danger:       oklch(0.575 0.20 25);      /* floor-corrected from #dc3545 (which failed 4.5:1 on --surface) */

  /* ── LAYER 4 · Field-status CONTRACT group — a data vocabulary, not theme.
     Shipped now (named); painted by the map slice. Faithful to the legacy hexes,
     exempt from the one-accent consolidation, never moves when --accent moves. ── */
  --field-available:        oklch(0.828 0.242 145);  /* #36ED54 */
  --field-selected:         oklch(0.727 0.132 239);  /* #49B1F0 */
  --field-registered-other: oklch(0.574 0.013 203);  /* #707B7C */
  --field-claimed:          oklch(0.642 0.226 23 );  /* #F83746 */
  --field-owned:            oklch(0.772 0.173 64 );  /* #ff9903 */
  --field-shared:           oklch(0.608 0.297 312);  /* #bc13fe */
  --precip:                 oklch(0.416 0.078 232);  /* #0f536f */

  /* ── NON-COLOR · Type / Shape / Depth / Motion — CANON DEFAULTS verbatim. ── */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;   /* Lato dropped */
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", monospace;
  --text-sm:   0.875rem;   /* 14px — the floor: labels, meta, helper text */
  --text-base: 1rem;       /* 16px — body, inputs, buttons */
  --text-lg:   1.25rem;    /* 20px — sub-headings */
  --text-xl:   1.75rem;    /* 28px — the auth card title */
  --weight-normal: 400;
  --weight-medium: 500;
  --weight-bold:   700;
  --line-tight: 1.3;
  --line-base:  1.5;

  --radius-sm:   4px;      /* inputs, small controls */
  --radius-md:   8px;      /* the auth card, buttons, dialogs */
  --radius-full: 999px;    /* pills / badges */

  --shadow-sm: 0 1px 2px  oklch(0.25 0.01 250 / 0.06);  /* resting controls */
  --shadow-md: 0 2px 8px  oklch(0.25 0.01 250 / 0.08);  /* hover lift */
  --shadow-lg: 0 8px 24px oklch(0.25 0.01 250 / 0.10);  /* the floating auth card */

  --transition-fast: 120ms ease;
}

*, *::before, *::after { box-sizing: border-box; }

@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ═══════════════════════ Auth shell (header-less; flex column) ═══════════════════════ */
/* Auth is header-less by ruling (the card carries the logo). The flex column retires the
   legacy calc(100vh - 85px) magic number; the footer pins at the bottom, in normal flow. */
body.auth {
  min-height: 100dvh; display: flex; flex-direction: column; margin: 0;
  background: var(--surface); color: var(--text);
  font-family: var(--font-sans); font-size: var(--text-base); line-height: var(--line-base);
}
.auth-frame { flex: 1 1 auto; display: flex; min-height: 0; }

main {
  flex: 1 1 auto; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1rem;
  padding: clamp(1.5rem, 5vw, 3rem) 1rem;
}

/* The floating card — soft depth (one purposeful shadow + a hairline), never a bevel. */
.auth-card {
  width: min(100%, 24rem);
  background: var(--surface-raised); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  padding: clamp(1.5rem, 4vw, 2.25rem); display: grid; gap: 1rem;
}
.auth-card--wide { width: min(100%, 34rem); }   /* register gets room (legacy meaning) */
/* Brand lockup — the pivot mark + the app name, a clean unit floating ABOVE the action card
   (identity is its own quiet moment; the card stays pure task). On the page surface, not a card. */
.brand { display: grid; gap: 0.4rem; justify-items: center; text-align: center; }
.auth-logo { display: block; max-height: 3rem; width: auto; }
.app-name { margin: 0; color: var(--text); font-weight: var(--weight-bold);
            font-size: var(--text-xl);            /* comparable to the action heading ("Sign in") */
            letter-spacing: 0.01em; line-height: var(--line-tight);
            max-width: 20rem; text-wrap: balance; }   /* wrap gracefully above the card */

/* ── Rendering (A) — quiet photo-split: the brand panel only appears in split mode. ── */
.auth-brand { display: none; }
body.auth--split .auth-brand {
  display: block; flex: 1 1 0; min-width: 0; position: relative;
  background: var(--accent);                 /* flat-accent wash — the fallback if no photo */
  overflow: hidden;
}
body.auth--split .auth-brand img { width: 100%; height: 100%; object-fit: cover; display: block; }
body.auth--split main { flex: 0 1 clamp(20rem, 42vw, 32rem); }
/* The one catastrophic breakpoint the canon allows: drop the brand panel on narrow viewports. */
@media (max-width: 40rem) {
  body.auth--split .auth-brand { display: none; }
  body.auth--split main { flex: 1 1 auto; }
}

/* ═══════════════════════ Typography ═══════════════════════ */
/* Muted headings carry the Irrigator "soft, quiet" identity (legacy #6c757d → --text-muted). */
h1, h2, h3 { color: var(--text-muted); font-weight: var(--weight-bold); line-height: var(--line-tight); margin: 0; }
h1 { font-size: var(--text-xl); }
h2 { font-size: var(--text-lg); }
h3 { font-size: var(--text-base); }
p  { margin: 0; }
a  { color: var(--accent); text-underline-offset: 0.15em; }    /* --accent on surface/raised ≥ 4.67:1 */
a:hover { color: var(--accent-hover); }
small, .muted { color: var(--text-muted); font-size: var(--text-sm); }

/* ═══════════════════════ Forms — sunken-well inputs, label-above ═══════════════════════ */
form  { display: grid; gap: 1rem; }
label { display: grid; gap: 0.3rem; font-weight: var(--weight-medium); color: var(--text); }

input:where([type=text], [type=email], [type=password], [type=tel], [type=search]) {
  font: inherit; min-height: 44px; padding: 0.55rem 0.7rem; color: var(--text);
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 2px oklch(0.25 0.01 250 / 0.05);     /* the "sunk" read */
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
input::placeholder { color: var(--text-muted); opacity: 1; }

input:focus-visible {
  outline: none;                              /* replaced, never merely removed */
  border-color: var(--accent);
  box-shadow: 0 0 0 3px oklch(0.55 0.14 245 / 0.35);
}
input[aria-invalid="true"] { border-color: var(--danger); background: oklch(0.985 0.012 25); }
input[aria-invalid="true"]:focus-visible { box-shadow: 0 0 0 3px oklch(0.575 0.20 25 / 0.30); }

/* Form-level error (the adapter returns a single message today) + future per-field .field-error. */
[role=alert], .field-error {
  color: var(--danger); font-size: var(--text-sm); font-weight: var(--weight-medium); margin: 0;
}

/* ═══════════════════════ Buttons — filled-accent primary, bordered-neutral secondary ═══════════════════════ */
button, [type=submit], [type=button] {
  font: inherit; font-weight: var(--weight-medium); line-height: 1.2;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 2.75rem; padding: 0.5rem 1.1rem;                /* 44px touch target */
  border: 1px solid transparent; border-radius: var(--radius-md);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background-color var(--transition-fast), border-color var(--transition-fast),
              box-shadow var(--transition-fast), transform 60ms ease;
}
/* PRIMARY — the form submit is primary by default (no class needed on the markup). */
button, [type=submit], button.primary {
  background: var(--accent); color: var(--accent-contrast);
  border-color: var(--accent); box-shadow: var(--shadow-sm);
}
button:hover, [type=submit]:hover, button.primary:hover {
  background: var(--accent-hover); border-color: var(--accent-hover);
}
button:active, [type=submit]:active, button.primary:active { transform: translateY(1px); box-shadow: none; }
/* SECONDARY — bordered-neutral; keeps the legacy "blue on hover" meaning, drops the 90px pill. */
button.secondary {
  background: var(--surface-raised); color: var(--text); border-color: var(--border); box-shadow: none;
}
button.secondary:hover { border-color: var(--accent); color: var(--accent); background: var(--surface-raised); }
button.secondary:active { transform: translateY(1px); }
button:disabled, [type=submit]:disabled { opacity: 0.6; cursor: not-allowed; box-shadow: none; transform: none; }

/* TERTIARY — the JS-injected show-password toggle: quiet, off the primary cascade. */
button.pw-toggle {
  justify-self: start; min-height: 2.25rem; padding: 0.35rem 0.6rem;
  font-size: var(--text-sm); font-weight: var(--weight-medium);
  background: transparent; color: var(--text-muted); border-color: transparent; box-shadow: none;
}
button.pw-toggle:hover { color: var(--accent-text); background: var(--surface-raised); }

/* RESTORE native focus, restyled to the accent — NEVER removed (legacy stripped it).
   The 2px offset is the CONTRAST mechanism: lifts the ring onto the surface behind. */
:where(button, [type=submit], [type=button], a, input, select, textarea):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* ═══════════════════════ Notices — flashes, the verify nudge ═══════════════════════ */
.flashes { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.flashes li {
  padding: 0.6rem 0.8rem; border: 1px solid var(--border); border-left: 3px solid var(--success);
  border-radius: var(--radius-sm); background: var(--surface-sunken);
  color: var(--text); font-size: var(--text-sm);
}
/* The unverified-email nudge — a warn-tinted band (warn carries dark ink). */
.verify-banner {
  display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap;
  padding: 0.6rem 0.8rem; border: 1px solid var(--border); border-left: 3px solid var(--warn);
  border-radius: var(--radius-sm); background: oklch(0.97 0.03 85); color: var(--text); font-size: var(--text-sm);
}
.verify-banner form { display: inline; margin: 0; }
.verify-banner button { min-height: 2rem; padding: 0.3rem 0.7rem; font-size: var(--text-sm); }

/* ═══════════════════════ Landing stub — actor key/value ═══════════════════════ */
dl { display: grid; grid-template-columns: auto 1fr; gap: 0.35rem 1rem; margin: 0; }
dt { font-weight: var(--weight-medium); color: var(--text-muted); }
dd { margin: 0; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ═══════════════════════ Footer strip — slate, in flow: "A GiSC product" + version ═══════════════════════ */
footer.app-version {
  flex: 0 0 auto; display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: 0.5rem clamp(1rem, 4vw, 2rem);
  background: var(--slate); color: var(--accent-contrast);     /* white on slate = 10.69:1 */
  font-size: 0.8125rem;                                        /* 13px — decorative chrome */
}
.footer-credit  { font-family: var(--font-sans); }
.footer-version { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ═══════════════════════ App shell (staff/farmer screens — header + wide main) ═══════════════════════ */
/* Distinct from the header-less auth shell: a top header (brand + nav + actor + sign-out), a wide content
   main, the same slate footer in flow. The wide data screens live here. */
body.app {
  min-height: 100dvh; display: flex; flex-direction: column; margin: 0;
  background: var(--surface); color: var(--text);
  font-family: var(--font-sans); font-size: var(--text-base); line-height: var(--line-base);
}
.app-header {
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
  padding: 0.6rem clamp(1rem, 4vw, 2rem);
  background: var(--surface-raised); border-bottom: 1px solid var(--border);
}
.app-brand { display: inline-flex; align-items: center; gap: 0.5rem; text-decoration: none; color: var(--text); }
.app-brand .app-logo { display: block; max-height: 2rem; width: auto; }
.app-brand .app-name { font-weight: var(--weight-bold); font-size: var(--text-base); letter-spacing: 0.01em; }
.app-nav { display: flex; gap: 1rem; margin-right: auto; }       /* push the actor block to the right edge */
.app-nav a { color: var(--text-muted); text-decoration: none; font-weight: var(--weight-medium); padding: 0.25rem 0; }
.app-nav a:hover { color: var(--accent); }
.app-nav a[aria-current="page"] { color: var(--accent-text); border-bottom: 2px solid var(--accent); }
.app-user { display: flex; align-items: center; gap: 0.75rem; }
.app-user form { display: flex; gap: 0; margin: 0; }             /* override the global grid-form */
.app-user button { min-height: 2.25rem; padding: 0.35rem 0.8rem; font-size: var(--text-sm); }

.app-main {
  flex: 1 1 auto; width: min(100%, 80rem); margin: 0 auto;
  padding: clamp(1rem, 3vw, 2rem) clamp(1rem, 4vw, 2rem); display: grid; gap: 1rem; align-content: start;
}
/* Dense data-entry pages run wider — more columns, more screen used (set via the main_class block). */
.app-main--wide { width: min(100%, 100rem); }
.app-main > h1 { color: var(--text); font-size: var(--text-xl); }

/* Staff home — link cards */
.card-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }
.card-link {
  display: grid; gap: 0.2rem; padding: 1rem 1.1rem; text-decoration: none;
  background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm); transition: box-shadow var(--transition-fast), border-color var(--transition-fast);
}
.card-link:hover { box-shadow: var(--shadow-md); border-color: var(--accent); }
.card-link-title { color: var(--accent-text); font-weight: var(--weight-bold); }

/* ═══════════════════════ Reports — filter bar, data table, pager ═══════════════════════ */
.report-filters {
  display: flex; flex-direction: column; gap: 0.4rem;
  padding: 0.55rem 0.7rem; margin-bottom: 0.6rem;
  background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.report-filters label { gap: 0.1rem; font-size: var(--text-sm); }
.report-filters select,
.report-filters input { min-height: 32px; }

/* Header row: title left; the action buttons (Clear, Download CSV) + the at-a-glance controls
   (Year, # records) clustered right — margin-left:auto on the buttons pushes the whole right group over. */
.report-head { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; align-items: flex-end; }
.report-head-title h1 { margin: 0; font-size: var(--text-lg); }
.report-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.3rem;
  min-height: 32px; padding: 0.3rem 0.9rem;
  background: var(--accent); color: var(--accent-contrast);
  border: 1px solid var(--accent); border-radius: var(--radius-sm);
  font-size: var(--text-sm); font-weight: var(--weight-medium);
  text-decoration: none; white-space: nowrap;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}
.report-btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-contrast); }
.report-btn-start { margin-left: auto; }   /* pushes the right cluster (Clear · dropdowns · CSV) over */
.report-head-controls { display: flex; gap: 0.9rem; align-items: flex-end; }
.report-head-controls label { font-size: var(--text-sm); }

/* Filter blocks: each row a horizontal strip of equal-width controls (wraps on narrow viewports). */
.filter-row { display: flex; flex-wrap: wrap; gap: 0.4rem 0.9rem; }
.filter-row label { flex: 1 1 12rem; }
.report-filters select {
  font: inherit; padding: 0.3rem 0.5rem; color: var(--text);
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.report-filters-actions { display: flex; align-items: center; gap: 1rem; }
.report-filters-actions a { font-size: var(--text-sm); }

.report-meta { margin: 0; }
.table-scroll { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-md); }
.report-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); background: var(--surface-raised); }
.report-table th, .report-table td { padding: 0.5rem 0.7rem; text-align: left; white-space: nowrap; }
.report-table thead th { background: var(--surface-sunken); border-bottom: 1px solid var(--border); }
.report-table thead a { color: var(--text-muted); font-weight: var(--weight-bold); text-decoration: none; display: inline-flex; gap: 0.25rem; }
.report-table thead a:hover { color: var(--accent); }
.report-table th[aria-sort] a { color: var(--accent-text); }
.report-table tbody tr:nth-child(even) { background: var(--surface-sunken); }
.report-table td.num, .report-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.report-table .grower-cell { white-space: normal; line-height: 1.25; min-width: 12rem; }
.report-table .grower-name { display: block; }
.report-table .grower-email { display: block; font-size: 0.8125rem; }
.report-table .mark { font-weight: var(--weight-bold); }
.report-table .mark.yes { color: var(--success-text); }
.report-table .mark.no  { color: var(--text-muted); }
.report-empty { text-align: center; padding: 1.5rem; white-space: normal; }

.pager { display: flex; gap: 1rem; align-items: center; justify-content: center; padding: 0.5rem; }
.pager a { text-decoration: none; font-weight: var(--weight-medium); }
.pager-status { color: var(--text-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.pager-disabled { color: var(--border); font-weight: var(--weight-medium); }

/* htmx in-flight: dim the table region while a swap is loading (progressive — no-op with JS off). */
#report-table.htmx-request { opacity: 0.55; transition: opacity var(--transition-fast); }

/* ═══════════════════════ Dense data-entry forms — the form standard (.form-dense) ═══════════════════════ */
/* Desktop data entry: pack as many inputs on screen as possible, no scroll. A small label sits tight ABOVE a
   compact control; fields flow into as many columns as fit; sections are thin labeled rules, not padded cards.
   Reusable — apply class="form-dense" to any staff data-entry form. (Overrides the global stacked grid-form +
   the 44px touch-target inputs — this surface is desktop-only.) */
.form-dense { display: grid; gap: 0.7rem; }
/* The dense controls set an explicit display (grid/flex), which overrides the [hidden] UA rule — restore it so
   the JS-toggled conditional fields (data-prt-other / data-fuel) actually hide. */
.form-dense [hidden] { display: none !important; }

/* A section = a thin uppercase header rule + a packed grid of its fields (no card chrome). Plain <section> +
   <h2> (NOT fieldset/legend — legend renders inconsistently under display:grid/flex). */
.form-dense .form-section { display: grid; gap: 0.35rem; margin: 0; padding: 0; border: 0; min-inline-size: 0; }
.form-dense .section-head {
  padding: 0 0 0.15rem; margin: 0 0 0.15rem; border-bottom: 1px solid var(--border);
  font-size: var(--text-sm); font-weight: var(--weight-bold); letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--accent-text);
}

/* The packed grid — many narrow columns; the minmax floor sets the density. align-items:end keeps a radio
   caption + a label baseline-aligned across the row. */
/* FIXED responsive columns (NOT auto-fill) — the column count is the same no matter what's filled in, so
   picking a well never reflows the layout (only the values change). minmax(0,1fr) lets long labels/values wrap
   inside a cell instead of forcing the whole grid wider. align-items:start keeps every label on one top line. */
.form-dense .form-grid {
  display: grid; gap: 0.6rem 1.5rem; align-items: start;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (min-width: 55rem) { .form-dense .form-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 78rem) { .form-dense .form-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.form-dense .form-grid > * { min-width: 0; }   /* let cells shrink below content so columns stay equal */
.form-dense .form-grid .span-2 { grid-column: span 2; }
.form-dense .form-grid .span-3 { grid-column: span 3; }

/* A field: a tiny muted label directly above a compact control. */
.form-dense label { display: grid; gap: 0.12rem; margin: 0; font-size: 0.78rem; font-weight: var(--weight-medium); color: var(--text-muted); }
.form-dense input,
.form-dense select,
.form-dense textarea {
  width: 100%; box-sizing: border-box;   /* fill the fixed column; never push it wider */
  font: inherit; font-size: var(--text-sm); min-height: 30px; padding: 0.25rem 0.45rem; color: var(--text);
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 2px oklch(0.25 0.01 250 / 0.05);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.form-dense textarea { min-height: 2.2rem; resize: vertical; }
.form-dense :where(input, select, textarea):focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px oklch(0.55 0.14 245 / 0.30);
}
.form-dense [aria-invalid="true"] { border-color: var(--danger); background: oklch(0.985 0.012 25); }
.form-dense .field-error { font-size: 0.72rem; }

/* Yes/No radios + the irrig-type checkboxes — caption above, options inline; sits as a grid cell like a field.
   role="group" div + a caption span (not fieldset/legend — predictable under flex). */
.form-dense .radio-group,
.form-dense .checkbox-group { display: flex; flex-wrap: wrap; align-items: center; gap: 0.1rem 0.7rem; margin: 0; padding: 0; border: 0; min-inline-size: 0; }
.form-dense .rg-caption { flex-basis: 100%; margin: 0 0 0.12rem; font-size: 0.78rem; font-weight: var(--weight-medium); color: var(--text-muted); }
.form-dense label.radio,
.form-dense label.checkbox { display: inline-flex; flex-direction: row; align-items: center; gap: 0.2rem; min-height: 30px; font-size: var(--text-sm); font-weight: var(--weight-normal); color: var(--text); cursor: pointer; }
.form-dense label.radio input,
.form-dense label.checkbox input { min-height: 0; box-shadow: none; }
.form-dense .radio-group.has-error > .rg-caption,
.form-dense .checkbox-group.has-error > .rg-caption { color: var(--danger); }
.form-dense .radio-group .field-error,
.form-dense .checkbox-group .field-error { flex-basis: 100%; }

/* Read-only geo — a tight inline strip of label:value pairs (not tall key/value rows). */
.form-dense .geo-readout {
  display: flex; flex-wrap: wrap; gap: 0.1rem 1.1rem; margin: 0; padding: 0.3rem 0.55rem;
  border: 1px dashed var(--border); border-radius: var(--radius-sm); background: var(--surface-sunken); font-size: var(--text-sm);
}
.form-dense .geo-readout > div { display: inline-flex; gap: 0.3rem; align-items: baseline; }
.form-dense .geo-readout dt { color: var(--text-muted); font-weight: var(--weight-medium); }
.form-dense .geo-readout dd { margin: 0; font-variant-numeric: tabular-nums; }

.form-dense .form-actions { display: flex; align-items: center; gap: 1rem; margin-top: 0.1rem; }
.form-dense .form-actions button { min-height: 2rem; padding: 0.35rem 1.1rem; }
