/* ==========================================================================
   MKH - Document editor
   Visual language from the Claude Design project.
   Requires tokens.css, base.css, components.css and layout.css.

   Shared by the purchase bill and the sales invoice, which are the same shape:
   a head naming the party and the places, a list of lines, and a foot that adds
   up. A line here carries more than any other form in the app - a product, a
   quantity, a rate, a discount and what it comes to - so it needs its own grid
   rather than stretching the one bills of materials use.

   Named for the shape rather than for purchases, because a stylesheet called
   after one screen is one somebody will edit believing only that screen moves.
   ========================================================================== */

/* --------------------------------------------------------------------------
   The head of the document
   -------------------------------------------------------------------------- */

.doc-head {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) 150px 150px;
  gap: var(--sp-3) var(--sp-4);
  align-items: start;
}

/* A receipt or a payment has no field like a customer and a delivery address:
   a party, an account, a date and an amount are of much the same weight, and
   giving the first of them half the row leaves the account ellipsised in a
   track narrower than the fixed ones beside it. The floor is what a date input
   needs before its own picker starts eating the year. */
.doc-head--money { grid-template-columns: repeat(4, minmax(150px, 1fr)); }

.doc-head__wide { grid-column: 1 / -1; }

/* A field that wants more than one of the narrow tracks but not the whole row:
   the vehicle picker, which searches by name or plate and needs room to show
   what it matched. */
.doc-head__pair { grid-column: 3 / -1; }

/* The due date, which is worked out rather than typed. Sized to sit level with
   the fields beside it, so the row still reads as a row even though one of its
   cells is a read-out rather than a box. */
.doc-due {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-height: 38px;
  padding-top: 8px;
}
.doc-due strong {
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  color: var(--txt);
}
.doc-due span { font-size: var(--fs-xs); color: var(--txt-3); }

/* Which way the tax splits, said out loud as soon as it can be worked out. It
   is decided by two fields that are nowhere near each other on the form - the
   vendor and the warehouse - so leaving the user to infer it is unkind. */
.doc-split {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: var(--sp-3);
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-size: var(--fs-sm);
  color: var(--txt-2);
}
.doc-split svg { width: 15px; height: 15px; flex: none; color: var(--primary); }
.doc-split strong { color: var(--txt); font-weight: var(--fw-semibold); }

/* The margin above stands it off the fields it follows. Used as the first
   thing in a card, there is nothing to stand off from, and the gap reads as a
   line of something that failed to appear. Anything after it keeps its
   distance in the same measure. */
.card__body > .doc-split:first-child { margin-top: 0; }
.card__body > .doc-split + .alert { margin-top: var(--sp-3); }

/* What the customer already owes, in the same shape as the split above it: two
   read-outs about the same document should not look like two different kinds of
   thing. Screen only, and the stylesheet the printer uses does not know this
   class exists.

   The icon is aligned to the first line rather than centred, because this one
   wraps to two lines on a narrow head and a centred icon then floats beside
   nothing. */
.doc-owes {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: var(--sp-3);
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-size: var(--fs-sm);
  color: var(--txt-2);
}
.doc-owes svg {
  width: 15px;
  height: 15px;
  flex: none;
  margin-top: 1px;
  color: var(--txt-3);
}
.doc-owes strong { color: var(--txt); font-weight: var(--fw-semibold); }

/* Anything past due colours the whole strip rather than just the figure. It is
   the one state somebody should catch without reading the sentence. */
.doc-owes--late {
  border-color: var(--warn);
  background: var(--warn-bg);
  color: var(--warn-fg);
}
.doc-owes--late svg,
.doc-owes--late strong { color: var(--warn-fg); }

/* Two sentences, each an inline block that wraps whole. Flex rather than plain
   inline text so the overdue sentence drops to its own line when the head is
   narrow, instead of leaving a figure stranded at the end of the first line
   away from the words that explain it. The row gap is what separates them once
   they stack. */
.doc-owes__text {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 6px;
}

/* --------------------------------------------------------------------------
   One line of a bill
   -------------------------------------------------------------------------- */

/* Grid rather than flex so the figures line up down the list. The amount is a
   read-out rather than a field, and sits in its own track so the numbers form
   a column somebody can add up by eye.

   The discount track matches the rate and the amount rather than being the
   narrow one. It is the only field here that gives up part of its width to a
   control - the rupees-or-per-cent switch sits inside it - so at 90px there
   were barely four digits left to read back what had been typed. */
.doc-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 130px 130px 150px 130px 34px;
  align-items: start;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--line);
}
.doc-line:last-of-type { border-bottom: 0; }

.doc-line .field { margin-bottom: 0; }

/* Per-field labels, hidden while the column captions are doing that job and
   shown the moment those captions go. Without this the row collapses to three
   unlabelled number boxes and nobody can tell the quantity from the rate.

   Kept as real labels rather than sr-only text swapped for visible text, so
   there is one piece of label text per field and tapping it still focuses the
   input. */
.doc-line__label { display: none; }

.doc-line__remove { margin-top: 4px; }

/* The areas the line's stock goes into, under everything else on the line at
   every width: it is about the line as a whole, not about any one figure. */
.doc-line__areas { grid-column: 1 / -1; }

.doc-line__unit {
  margin-top: 6px;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

/* What the quantity comes to in the product's other unit, for something counted
   one way and measured another. Set small and in the figure font under the
   quantity it belongs to: it is a check on what was typed, not a field.

   Allowed to wrap. The column is sized for the ordinary case, but the string
   grows with the figures in it - "12.5 ltr x 240 = 3000 ltr" is a third longer
   again - and held on one line it would run under the rate beside it. */
.doc-line__convert {
  margin-top: 3px;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.4;
  color: var(--txt-3);
}

/* --------------------------------------------------------------------------
   Discount, in rupees or per cent
   -------------------------------------------------------------------------- */

/* The sign doubles as the switch. A second control would not fit the row, and
   a dropdown for two choices is a click where a glance should do. */
.doc-disc { display: flex; align-items: stretch; }

.doc-disc__value {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  min-width: 0;
}

.doc-disc__kind {
  flex: none;
  width: 34px;
  display: grid;
  place-items: center;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--txt-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-left: 0;
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.doc-disc__kind:hover { background: var(--primary-soft); color: var(--primary); }

.doc-disc__kind:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: -1px;
}

/* --------------------------------------------------------------------------
   Typing the amount instead of the rate
   -------------------------------------------------------------------------- */

/* Reads as the figure it replaces until it is pointed at, because it is a
   figure first and a control second. The dotted underline is the only hint it
   is more than text, which is enough for something used occasionally. */
.doc-line__figure--set {
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: underline dotted var(--line-strong);
  text-underline-offset: 3px;

  /* Padded vertically only, and never horizontally: the figure is right
     aligned against the column, and side padding would shift it off that edge.
     The size is what makes it a target a thumb can find, and a short figure
     like 0.00 is barely thirty pixels wide on its own, so the box is given a
     floor in both directions. It grows leftwards into empty column, because
     the content stays flush right and the figure must not move. */
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  min-height: 34px;
  min-width: 44px;
  padding: 2px 0;
}

.doc-line__figure--set:hover { text-decoration-color: var(--primary); color: var(--primary); }

.doc-line__figure--set:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* Right-aligned like the figure it stands in for, so the column does not jump
   when it opens. */
.doc-line__figure-input {
  text-align: right;
  font-weight: var(--fw-semibold);
}

/* The padding above the figure exists to sit its text on the same line as the
   text inside the boxes beside it. An input needs no such nudge - it is a box
   itself - so the padding goes while one is open, or it hangs below the row it
   belongs to.

   Two classes deep on purpose. Every width below restyles this cell with a
   single class, so a single-class rule here would be beaten by whichever came
   later in the file rather than by which one is true. */
.doc-line .doc-line__amount--editing {
  padding-top: 0;

  /* And the same vertical rhythm as the .field boxes it shares a row with:
     label, a 7px gap, then the control. At narrow widths the label is showing
     and this cell is not a .field, so without it the box sits seven pixels
     above the discount beside it. Matches .field in components.css. */
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* The label keeps its own margin, because the field beside it keeps that margin
   as well as the gap: five and seven, on both, is what makes the two boxes
   start on the same line. What goes below the box does not need a margin of its
   own on top of the gap. */
.doc-line .doc-line__amount--editing .doc-line__short,
.doc-line .doc-line__amount--editing .doc-line__tax { margin: 0; }

/* Sold more than the shelf holds. Sits under the product it is about rather
   than in the banner at the foot, so which line is short needs no counting. */
.doc-line__short {
  margin-top: 6px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--warn-fg);
}

/* Under the amount it is a sentence about a figure somebody typed, in a cell
   set in the figures' own type. Words read better in the words' one, and take
   a line less of a column this narrow.

   The cell's label is words as well. Left in the figures' type it was the one
   label on the line that did not match the others, "Amount" beside "Discount"
   in two different faces. */
.doc-line__amount .doc-line__short,
.doc-line__amount .doc-line__label { font-family: var(--font-sans); }

/* What the line comes to. Not an input: it is worked out, and making it look
   like a field invites somebody to try to type in it. */
.doc-line__amount {
  padding-top: 9px;
  text-align: right;
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  font-variant-numeric: tabular-nums;
  color: var(--txt);
}
.doc-line__tax {
  margin-top: 4px;
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

.doc-lines { margin-bottom: var(--sp-3); }

.doc-lines__empty {
  padding: var(--sp-3) 0 var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--txt-3);
}

.doc-lines__error { margin-bottom: var(--sp-3); }

/* Column captions above the first line. A form of five numbers per row needs
   them; a form of two does not, which is why bills of materials has none. */
.doc-line--head {
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--line-strong);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.doc-line--head > * { padding: 0; }
.doc-line--head .doc-line__amount { padding-top: 0; font-family: inherit; font-size: inherit; }

/* --------------------------------------------------------------------------
   What the bill comes to
   -------------------------------------------------------------------------- */

.doc-total { background: var(--surface-2); border-color: var(--line-strong); }

.doc-total__grid {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-left: auto;
  max-width: 420px;
}

.doc-total__line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  font-size: var(--fs-md);
  color: var(--txt-2);
}

.doc-total__line--sum {
  margin-top: var(--sp-1);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  color: var(--txt);
}

.doc-total__value { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* What the customer is saving, on a price agreement. Green because it is the
   one figure that page exists to say, and the same green the printed sheet
   uses, so the screen is a preview of what goes out. Kept bold as well, since
   colour alone is no signal to a reader who cannot see it. */
.doc-total__line--save .doc-total__value,
.doc-line__tax--save {
  color: var(--accent-graphic);
  font-weight: var(--fw-semibold);
}

/* The per cent beside the figure: the same thing said the other way, at the
   size of a caption so it reads as a gloss rather than a second total. */
.doc-total__aside {
  margin-left: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-regular);
  color: var(--txt-3);
}

/* The second figure on the page, and the one nobody expects: what the vendor
   is owed and what the stock is worth are different numbers, because the tax
   is input credit rather than a cost. Said plainly rather than left to be
   discovered. */
.doc-total__stock {
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px dashed var(--line);
  font-size: var(--fs-sm);
  color: var(--txt-2);
  max-width: 420px;
  margin-left: auto;
}
.doc-total__stock strong { color: var(--accent-graphic); font-weight: var(--fw-bold); }

/* --------------------------------------------------------------------------
   Narrowing
   -------------------------------------------------------------------------- */

/* The width asked about below is the room inside the page's padding, and the
   padding is a share of the window, so it is seldom a whole number. Where two
   layouts meet, one is written "700 and under" and the other "over 700",
   never "701 and up": at 700.6 that pair is silent on both sides, and the line
   was laid out by neither. */

/* A figure that can be typed over is a button, made 34px tall so a thumb can
   find it, with its text centred in that height. The nine pixels above it were
   measured for a line of plain text, and left alone they hang the figure seven
   pixels below the quantity and the rate it shares a row with. Two is what
   centres 34 on the 38 of the boxes beside it.

   Only where the line is a single row of columns. Every narrower layout below
   takes the padding off and places the figure its own way. */
@container content (width > 1050px) {
  .doc-line__amount:has(> .doc-line__figure--set) { padding-top: 2px; }
}

@container content (max-width: 1050px) {
  /* The captions stop lining up with anything once the rows wrap, so each
     field takes its own label back. */
  .doc-line--head { display: none; }

  .doc-line__label {
    display: block;
    margin-bottom: 5px;
    font-size: var(--fs-xs);
    font-weight: var(--fw-semibold);
    color: var(--txt-2);
    letter-spacing: 0.01em;
  }

  /* Placed by hand rather than flowed. Left to auto-placement the quantity
     inherited the wide first track and rendered four times the width of the
     rate beside it, and the remove button fell past the amount into a row of
     its own at the far left, belonging to nothing.

     Reads as: product across the top with its remove button in the corner,
     then the three figures side by side, then what the line came to. */
  .doc-line {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) 34px;
    row-gap: var(--sp-2);
  }

  .doc-line__product { grid-column: 1 / 4;  grid-row: 1; }
  .doc-line__remove  { grid-column: 4;      grid-row: 1; justify-self: end; margin-top: 4px; }
  .doc-line__qty     { grid-column: 1;      grid-row: 2; }
  .doc-line__rate    { grid-column: 2;      grid-row: 2; }
  .doc-line__disc    { grid-column: 3 / 5;  grid-row: 2; }

  /* Label on the left, figure on the right, the way a stacked table row reads
     everywhere else in the app. */
  .doc-line__amount {
    grid-column: 1 / -1;
    grid-row: 3;
    display: flex;
    align-items: baseline;
    justify-content: space-between;

    /* The tax line takes a whole row of its own, so the container has to be
       allowed to wrap. Without this a 100% basis simply sits alongside the
       other two and pushes the row wider than the page. */
    flex-wrap: wrap;
    gap: var(--sp-1) var(--sp-3);
    padding-top: 0;
  }
  .doc-line__amount .doc-line__label { margin-bottom: 0; }
  .doc-line__tax { flex: 1 0 100%; text-align: right; margin-top: 0; }
}

/* Between the single row of columns and the phone, the amount has a row to
   itself: named on the left, the figure on the right. It keeps that shape
   while it is being typed over, with the box where the figure was and no wider
   than a figure needs. Stacked like a field, as it is at every other width,
   the box ran the whole width of the card and the note under it swung across
   to the left.

   Not a price agreement's line. Its amount shares a row with two boxes at this
   width rather than having one to itself, so there it is stacked like them. */
@container content (width > 700px) and (width <= 1050px) {
  .doc-line:not(.doc-line--agreement) .doc-line__amount--editing { flex-direction: row; }

  .doc-line:not(.doc-line--agreement) .doc-line__amount--editing .doc-line__figure-input {
    flex: 0 0 180px;
    width: 180px;
  }

  /* Why a typed figure could not stand goes under the figure, like the tax
     line it takes the place of. Left as one more item in the row it sat beside
     the figure and pushed it in from the right-hand edge. */
  .doc-line__amount .doc-line__short {
    flex: 1 0 100%;
    text-align: right;
    margin-top: 0;
  }

  /* A price agreement's amount stands beside two fields at this width, so it
     is stacked the way they are, whether it is a figure or a box: its name
     level with theirs, and the figure on the line of what is typed next to
     it. Left as the row a document's line has, the name beside the figure, it
     sat up on the line of the labels with its own name hanging below theirs,
     and dropped into place the moment it was clicked.

     Stretched rather than lined up on a baseline, which in a column leaves
     each thing only as wide as its own words: the note under the box swung
     across to the left as it opened, away from the figures it is about. */
  .doc-line--agreement .doc-line__amount {
    flex-direction: column;
    align-items: stretch;
    gap: 7px;
  }

  /* The margin a row has no use for and a stack does: five and seven, like
     the discount's next to it, or the box opens five pixels above that one.
     Words, so read from the left like the two labels beside them, in a cell
     whose figures are set against the right. */
  .doc-line--agreement .doc-line__amount .doc-line__label {
    margin-bottom: 5px;
    text-align: left;
  }

  /* The height of a box, so the box takes the figure's place without anything
     else on the line moving. Only as wide as the figure and against the
     right-hand edge, as it is in the row of columns. */
  .doc-line--agreement .doc-line__amount > .doc-line__figure {
    display: inline-flex;
    align-items: center;
    align-self: flex-end;
    min-height: 38px;
  }
}

/* Both heads pair off here. Four even tracks on a tablet come out around 160px
   each, which is enough for a date but not for the name of a customer or of a
   bank account, and these heads are mostly names. Two tracks is the same fields
   at twice the width.

   The document head held out to 700px for a while, and on a 768px tablet that
   left its second track at 129px: wide enough for nothing it carries. The
   delivery address sat there reading "Their billing addr", which is the one
   field on the form that decides where the tax lands, so it has to be legible
   rather than merely present.

   The vendor or customer carries the longest text on the form and is the one
   field that must stay readable, so it takes the row rather than sharing it.
   The dates and the reference are short and pair happily. */
@container content (max-width: 860px) {
  .doc-head--money { grid-template-columns: repeat(2, minmax(150px, 1fr)); }

  .doc-head { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .doc-head > .field:first-child,
  .doc-head__pair,
  .doc-head__wide { grid-column: 1 / -1; }
}

@container content (max-width: 700px) {
  /* Every cell placed by hand rather than left to auto-flow, which would drop
     the discount into the narrow remove track and make it untypeable.

     The remove button sits in the line's top-right corner, level with the
     product it removes, the way a row action does everywhere else here. Left to
     the end of the flow it landed alone on a row of its own, which reads as a
     control belonging to nothing. */
  .doc-line { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 34px; }

  .doc-line__product { grid-column: 1 / 3;  grid-row: 1; }
  .doc-line__remove  { grid-column: 3;      grid-row: 1; justify-self: end; margin-top: 4px; }
  .doc-line__qty     { grid-column: 1;      grid-row: 2; }
  .doc-line__rate    { grid-column: 2 / 4;  grid-row: 2; }
  .doc-line__disc    { grid-column: 1;      grid-row: 3; }

  /* Beside the discount now rather than across the row, so it stacks its label
     over its figure like the fields it sits next to. */
  .doc-line__amount {
    grid-column: 2 / 4;
    grid-row: 3;
    display: block;
    padding-top: 0;
    text-align: left;
  }
  .doc-line__amount .doc-line__label { margin-bottom: 5px; }
  .doc-line__tax { text-align: left; }

  /* Level with the discount box it now sits beside: the gap a field leaves
     under its label, and the height of a box, so the figure reads on the line
     of what is typed next to it. Left as bare text it stood ten pixels above
     that line, and dropped by seven the moment it was opened to be typed in.

     A price agreement's amount has the row to itself here, with no box beside
     it to be level with, so it is left as it was. */
  .doc-line:not(.doc-line--agreement) .doc-line__amount > .doc-line__figure {
    display: inline-flex;
    align-items: center;
    min-height: 38px;
    margin-top: 7px;
  }

  /* The button is never narrower than a thumb, and elsewhere packs its figure
     against the right of that width because the column is right aligned. Here
     the cell reads from the left, and a short figure would start a few pixels
     in from the label above it. */
  .doc-line__amount > .doc-line__figure--set { justify-content: flex-start; }

  .doc-total__grid, .doc-total__stock { max-width: none; }
}

/* A box is taller under a finger than under a mouse, and the figure beside it
   follows. */
@media (pointer: coarse) {
  @container content (max-width: 700px) {
    .doc-line:not(.doc-line--agreement) .doc-line__amount > .doc-line__figure { min-height: 42px; }
  }

  @container content (width > 700px) and (width <= 1050px) {
    .doc-line--agreement .doc-line__amount > .doc-line__figure { min-height: 42px; }
  }

  /* In the row of columns the figure is held level by the room above it rather
     than by its own height, and four more pixels of box is two more of room:
     eleven over a line of plain text, four over the button that can be typed
     over. */
  @container content (width > 1050px) {
    .doc-line__amount { padding-top: 11px; }
    .doc-line__amount:has(> .doc-line__figure--set) { padding-top: 4px; }
  }

  /* The remove button grows as well, from 30 to 38, in a track that is still
     34 wide and under a margin measured for the smaller one. Two above it is
     what centres it on a box of 42. Held against the end of its track, it
     takes the four pixels it lacks from the gap beside it; left at the start,
     as it is in the row of columns, it hung that far past the end of the line.

     Said twice because the button is sometimes the cell and sometimes inside
     one, and a cell is what a track places. */
  .doc-line__remove { margin-top: 2px; }
  .doc-line > .doc-line__remove { justify-self: end; }
  .doc-line > :has(> .doc-line__remove) { justify-self: end; }
}

/* Below this even a pair is too tight for a date input plus its label. */
@container content (max-width: 430px) {
  .doc-head { grid-template-columns: minmax(0, 1fr); }
}

@supports not (container-type: inline-size) {
  @media (max-width: 1330px) {
    .doc-line--head { display: none; }
    .doc-line__label {
      display: block;
      margin-bottom: 5px;
      font-size: var(--fs-xs);
      font-weight: var(--fw-semibold);
      color: var(--txt-2);
      letter-spacing: 0.01em;
    }
    .doc-line {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) 34px;
      row-gap: var(--sp-2);
    }
    .doc-line__product { grid-column: 1 / 4;  grid-row: 1; }
    .doc-line__remove  { grid-column: 4;      grid-row: 1; justify-self: end; margin-top: 4px; }
    .doc-line__qty     { grid-column: 1;      grid-row: 2; }
    .doc-line__rate    { grid-column: 2;      grid-row: 2; }
    .doc-line__disc    { grid-column: 3 / 5;  grid-row: 2; }
    .doc-line__amount {
      grid-column: 1 / -1;
      grid-row: 3;
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--sp-1) var(--sp-3);
      padding-top: 0;
    }
    .doc-line__amount .doc-line__label { margin-bottom: 0; }
    .doc-line__tax { flex: 1 0 100%; text-align: right; margin-top: 0; }
  }
  @media (max-width: 980px) {
    .doc-line { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 34px; }
    .doc-line__product { grid-column: 1 / 3;  grid-row: 1; }
    .doc-line__remove  { grid-column: 3;      grid-row: 1; justify-self: end; margin-top: 4px; }
    .doc-line__qty     { grid-column: 1;      grid-row: 2; }
    .doc-line__rate    { grid-column: 2 / 4;  grid-row: 2; }
    .doc-line__disc    { grid-column: 1;      grid-row: 3; }
    .doc-line__amount {
      grid-column: 2 / 4;
      grid-row: 3;
      display: block;
      padding-top: 0;
      text-align: left;
    }
    .doc-line__amount .doc-line__label { margin-bottom: 5px; }
    .doc-line__tax { text-align: left; }
    .doc-total__grid, .doc-total__stock { max-width: none; }
  }
  @media (max-width: 1080px) {
    .doc-head--money { grid-template-columns: repeat(2, minmax(150px, 1fr)); }
    .doc-head { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .doc-head > .field:first-child,
    .doc-head__pair,
    .doc-head__wide { grid-column: 1 / -1; }
  }
  @media (max-width: 620px) {
    .doc-head { grid-template-columns: minmax(0, 1fr); }
  }
}

/* A rate that filled itself in from the customer's price agreement rather than
   from the last invoice. Said on the line, because a figure that appeared on
   its own should say where it came from, and because the person typing is
   entitled to know before they change it. */
.doc-line__agreed {
  margin-top: 4px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--accent-graphic);
}

/* Priced under what the goods last cost. Sits where the agreed price would and
   takes its place when both are true, because there is room for one line under
   a rate and this is the one worth reading. Amber rather than red: it is a
   decision somebody may well have meant to take, and the setting beside it
   decides whether it also stops the save. */
.doc-line__under {
  margin-top: 4px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--warn-fg);
}

/* --------------------------------------------------------------------------
   A price agreement's line
   -------------------------------------------------------------------------- */

/* One figure shorter than a document's, because there is no quantity: the
   product, what this customer is sold it at, what comes off, and what that
   leaves. Its own template rather than the document's with a hole in the
   middle of it. */
.doc-line--agreement { grid-template-columns: minmax(0, 1fr) 150px 150px 150px 34px; }

.doc-line--agreement .doc-line__sell { min-width: 0; }

@container content (max-width: 1050px) {
  /* Product across the top with its remove button in the corner, then the
     three figures side by side, the same shape the document line takes. */
  .doc-line--agreement { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) 34px; }

  .doc-line--agreement .doc-line__product { grid-column: 1 / 4; grid-row: 1; }
  .doc-line--agreement .doc-line__remove  { grid-column: 4;     grid-row: 1; }
  .doc-line--agreement .doc-line__sell    { grid-column: 1;     grid-row: 2; }
  .doc-line--agreement .doc-line__disc    { grid-column: 2;     grid-row: 2; }
  .doc-line--agreement .doc-line__amount  { grid-column: 3 / 5; grid-row: 2; }
}

@container content (max-width: 700px) {
  /* Two per row on a phone: a price and its discount read as a pair, and what
     they come to gets the line under them. */
  .doc-line--agreement { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 34px; }

  .doc-line--agreement .doc-line__product { grid-column: 1 / 3; grid-row: 1; }
  .doc-line--agreement .doc-line__remove  { grid-column: 3;     grid-row: 1; }
  .doc-line--agreement .doc-line__sell    { grid-column: 1;     grid-row: 2; }
  .doc-line--agreement .doc-line__disc    { grid-column: 2 / 4; grid-row: 2; }
  .doc-line--agreement .doc-line__amount  { grid-column: 1 / 4; grid-row: 3; }
}

/* --------------------------------------------------------------------------
   A packing plan's line
   -------------------------------------------------------------------------- */

/* Three cells and the remove button: the product, what it goes into, and how
   many fit. No money on this row at all, so the two narrow tracks are wider
   than a document's: a packing item is a name rather than a figure. */
.doc-line--packing { grid-template-columns: minmax(0, 1fr) 200px 170px 34px; }

@container content (max-width: 1050px) {
  .doc-line--packing { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 34px; }

  .doc-line--packing .doc-line__product { grid-column: 1 / 3; grid-row: 1; }
  .doc-line--packing .doc-line__remove  { grid-column: 3;     grid-row: 1; }
  .doc-line--packing .doc-line__pack    { grid-column: 1;     grid-row: 2; }
  .doc-line--packing .doc-line__fit     { grid-column: 2 / 4; grid-row: 2; }
}

@container content (max-width: 560px) {
  /* One under the other on a phone: "packed into" holds a name that a half
     width box cuts in two. */
  .doc-line--packing .doc-line__pack,
  .doc-line--packing .doc-line__fit { grid-column: 1 / 4; }
  .doc-line--packing .doc-line__fit { grid-row: 3; }
}
