/* ============================================================================
   FORM SPACING v112 — every gap in the app was being applied twice. Loaded last.

   THE MECHANISM, measured on the Sell price card (#/order/new):

     .form-card-body.nodes   display:flex column, gap:14px
       > .form-grid          grid, row-gap 16px
           > .field-wrap     margin-bottom:14px      <-- plus the 16px row gap
               > input.field margin-bottom:14px      <-- plus the wrap's own 14px
       > .oi-feesbox         margin-top:14px         <-- plus the body's 14px gap
       > .oi-totalrow        margin-top:14px         <-- plus the body's 14px gap

   Spacing used to come from margins, back when these containers were plain
   blocks. Then the containers were given `gap` (some of it by me, in polish-v80)
   and nobody removed the margins that had been doing that job. Gaps and margins
   ADD - they do not collapse across a flex or grid gap - so every space in every
   record form in the app is the sum of two.

   Measured result on that one card: 30px between field rows where 16 was
   intended, 28px between blocks where 14 was intended, and 114px of dead air
   between the Price field and the fee row underneath it. That is the reported
   "so much space between the stuff", and it is not local to that card - it is
   every form built from .form-card-body / .form-grid / .field-wrap.

   THE RULE APPLIED HERE: whichever element owns the layout owns the spacing.
   If a container declares a gap, its children declare no margin. The margins are
   removed rather than the gaps because a gap cannot double, cannot collapse
   unexpectedly, and does not need a :last-child exception.
   ========================================================================== */

/* ── 1. THE CONTAINER OWNS THE RHYTHM ────────────────────────────────────── */

/* the stacked card body already spaces its blocks by 14px */
body .form-card-body.nodes>*{margin-top:0;margin-bottom:0}
body .form-card-body.nodes>.section-label{margin-top:6px}
body .form-card-body.nodes>.section-label:first-child{margin-top:0}

/* the field grid already spaces its rows by its row-gap */
body .form-grid>.field-wrap,
body .form-grid>.field,
body .form-grid>.form-row{margin-bottom:0}

/* ── 1b. A CONTAINER WITHOUT A GAP STILL NEEDS ONE ────────────────────────
   The rule directly above is right BETWEEN GRID ROWS - the row-gap covers that
   - but the margin it removes was doing double duty: it also separated the grid
   from whatever followed it. Where the parent is a flex column with a gap
   (.form-card-body.nodes) that is free. The vehicle form's .vfs-body9 is a plain
   block with no gap, so removing the margin left the last grid row touching the
   next full-width field: measured Year/Make -> Model at 0px, and the same for
   Trim -> Labels and Odometer -> Notes. Here the blocks carry the rhythm, at the
   same 20px the grid uses between its own rows. */
body .vfs-body9>.form-grid,
body .vfs-body9>.field-wrap,
body .vfs-body9>.form-row{margin-bottom:20px}
body .vfs-body9>:last-child{margin-bottom:0}

/* ── 2. THE CONTROL INSIDE ITS OWN LABEL WRAPPER ──────────────────────────
   `.field` is a class on the INPUT as well as on wrapper divs (app.css:91 sets
   margin-bottom:14px on it), so an input inside a .field-wrap was adding a
   second 14px inside a box that already had one. Scoped to .field-wrap only:
   the three inputs in the app that use .field WITHOUT a wrapper still rely on
   that margin and keep it. The hint and error lines below a control carry their
   own margin-top, so nothing loses its breathing room.

   A DIRECT-CHILD selector is not enough: on the trip form the pickup input is
   wrapped in an .ac-wrap (autocomplete positioning box), so `>` missed it and
   that field stayed 71px tall for 57px of content while "Deliver by" next to it
   was correct. Matched as a descendant instead. */
body .field-wrap .input,
body .field-wrap input.field,
body .field-wrap select.field,
body .field-wrap textarea.field,
body .field-wrap .money-row,
body .field-wrap .ac-wrap{margin-bottom:0}
body .field-wrap>.field-error{margin-top:5px}

/* ── 2b. AN EMPTY BOX MUST NOT RESERVE A GAP ──────────────────────────────
   In a flex column, a zero-height child still sits between two gaps, so it costs
   28px while displaying nothing. On the trip form .stops-wrap renders empty
   until a stop is added, which is most of the time - it was silently pushing
   Destination a full block away from Pickup. It reappears the moment it has
   content. */
body .form-card-body.nodes>:empty{display:none}

/* ── 2c. AN ACTION ATTACHED TO A FIELD ────────────────────────────────────
   "Use truck's location" and "+ Add stop" are buttons in a flex row that also
   carried their own 6/8px margins, making a 34px control occupy 48px. The row
   spaces them; they do not space themselves.

   And because it belongs to the field above it, it sits closer to that field
   than the next unrelated field does - proximity is what tells you which control
   an action applies to. 14px card gap minus 6 = 8px up, 14px down.

   Specificity note: §1 above zeroes the margin of EVERY direct child of the card
   body, and "body .form-card-body.nodes>*" (two classes) outranks
   "body .trip-loc-tools" (one), so the hug has to name its parent to win. */
body .trip-loc-tools{align-items:center;gap:8px}
body .trip-loc-tools>.btn{margin:0}
body .form-card-body.nodes>.trip-loc-tools{margin:-6px 0 0}
body .form-card-body.nodes>.trip-loc-tools+.trip-loc-tools{margin-top:-2px}

/* ── 3. THE LINE-ITEM / FEE BLOCK ─────────────────────────────────────────
   Same disease: .oi-list is a flex column with gap:8px while its rows also had
   margins (mine, from v111). The box itself becomes a flex column so its two
   children are spaced by one declared gap instead of a margin pair. */
body .oi-feesbox{display:flex;flex-direction:column;gap:10px;margin:0}
body .oi-feesbox>*{margin:0}
body .oi-list{display:flex;flex-direction:column;gap:8px}
body .oi-list>*{margin:0}
body .oi-tools{margin:0}

/* ── 4. THE REMOVE BUTTON SITS ON ITS ROW ─────────────────────────────────
   Reported: "the x is misaligned". It was a 32px button in a 36px row carrying
   a top margin, so it hung 5px below the inputs it removes. Matched to the row:
   same height, same box, no margin. (The selector in form-v109 §6 was
   .oi-fee-row, which matches nothing - the class is .oi-row-fee.) */
body .oi-row-fee{
  display:grid;grid-template-columns:minmax(0,1fr) 130px 36px;
  gap:10px;align-items:center;margin:0}
body .oi-row-fee>*{margin:0;min-width:0}
body .oi-row-fee>input,body .oi-row-fee>select{height:36px;min-height:36px}
body .oi-row-fee .icon-btn,body .oi-row-fee .oi-del{
  width:36px;height:36px;min-height:36px;padding:0;margin:0;
  display:inline-flex;align-items:center;justify-content:center;align-self:center;
  border:1px solid var(--line-2);border-radius:8px;
  background:var(--panel);color:var(--muted)}
@media (hover:hover){
  body .oi-row-fee .icon-btn:hover,body .oi-row-fee .oi-del:hover{
    border-color:var(--danger);color:var(--danger)}
}
/* the column captions line up with the columns they caption */
body .oi-fee-head{
  display:grid;grid-template-columns:minmax(0,1fr) 130px 36px;gap:10px;margin:0;
  font-size:11px;font-weight:680;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted)}
@media (max-width:640px){
  body .oi-row-fee,body .oi-fee-head{grid-template-columns:minmax(0,1fr) 92px 36px}
}

/* ── 5. THE TOTAL LINE CLOSES THE CARD ────────────────────────────────────
   It is the conclusion of the numbers above it, so it reads as attached to them
   rather than floating a block away. */
body .oi-totalrow{
  display:flex;align-items:baseline;justify-content:space-between;
  margin:0;padding:12px 0 0;border-top:1px solid var(--line-1)}
