/* ---------------------------------------------------------------------------
   Pineapple's grid rules, written against the class names we stamp ourselves
   (pnp-grid, pnp-grid__row, pnp-grid__cell, pnp-grid__header-cell,
   pnp-grid__selection-cell, pnp-grid__row-action). Issues #1751, #2221.

   Structure only. Colour and corner radius belong to the theme — see
   scss/fluent-bootstrap/_pineapple-overrides.scss for the focus-ring colour
   this file consumes. A colour written here cannot follow a theme switch.

   Two device modifiers, both stamped by ResponsiveListViewController:
   .pnp-grid--handheld follows the viewport width (below 768 px), and
   .pnp-grid--mobile follows the device (IDeviceInfoService.IsMobileDevice,
   #2221). A desktop grid carries neither and is untouched by the scoped rules.

   Not here any more (#2221, owner decision 2026-09-30): the grid's cell
   padding, row height and text size. They are DevExpress SizeMode's, and a
   mobile device runs the whole application at SizeMode.Large
   (DeviceSizeModeController). This file used to rewrite the grid's
   per-size-mode padding properties and give every cell a 44 px height and a
   14 px font under .pnp-grid--handheld — which did not sit beside the size
   ladder, it removed it for that grid. Do not buy a row's height back here.
   --------------------------------------------------------------------------- */

/* Weight is typography, not colour, so it stays in the stylesheet while the
   header's background moved to the theme. Every width, not handheld only —
   it came from a site.css rule that had no breakpoint. */
.pnp-grid__header-cell {
  font-weight: 500;
}

/* Digits line up in a column. A WMS list is mostly order numbers, SSCC, lot
   numbers, quantities and dates, and proportional digits leave the column ragged
   — which is exactly the vertical scan an operator performs.

   On every cell, not only on columns of a numeric type. The identifiers this is
   for — SSCC, lot number, order number — are strings, so a type-driven rule would
   miss the columns the requirement is about and catch only the quantity. The
   property affects digit glyphs only; text is unchanged by it.

   Every width: a ragged column is no easier to read on a desktop. */
.pnp-grid__cell,
.pnp-grid__header-cell {
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   The hit-area floor on what an operator taps inside a row (#2221)

   The owner's decision puts the accessibility floor — --pineapple-touch-target,
   44 px, 52 px at the Large size mode — on the two things a row holds that a
   finger taps: the selection checkbox and XAF's inline row actions. Scoped to
   the device, not the width: a 768 px tablet measured every row target under
   the floor (29 px rows, a 20x20 checkbox, 24x24 actions).

   The inline actions are sized and nothing else: an in-flow button that is
   taller simply makes its row taller, which is the table cell's own
   behaviour. The selection checkbox is different — DevExpress positions it
   absolutely, so it cannot make its row taller, and a single-line row at the
   Large size mode is only about 33 px. So a row that shows a selection cell
   is one touch target tall (owner decision on #2221, 2026-10-01: option (a),
   the accessibility-floor exception through our own class, never a SizeMode
   override).
   --------------------------------------------------------------------------- */

/* One touch target tall. `height` on a table cell is a minimum — a row whose
   text wraps stays as tall as its text needs — and the tallest cell sets the
   row, so this lifts every row of a grid with a selection column to the token
   (52 px at Large) and leaves taller rows alone. Measured 2026-10-01 at
   768x1024 (tablet UA): Inventory 33 -> 52 px rows, the selection hit area
   50x32 -> 50x44. On the picking queue, where dx-grid-row-dnd.js makes the
   cell a flex box, and in card mode, where the cell is a line of its own, it
   is the cell's own height: 52 px.

   Widened so the grown control has room to sit in. `min-width` is honoured
   where the cell is a flex item (card mode, the picking queue); a table
   column takes its width from the column, which ResponsiveListViewController
   gives a floor on a mobile device (see the next rule).

   No `overflow` here. The grown control is cut at the cell's edge by
   DevExpress' own `overflow: hidden` on every grid body cell; an
   `overflow: clip` this rule used to carry lost to it and never applied
   (computed `hidden`, measured 2026-10-01). */
.pnp-grid--mobile .pnp-grid__selection-cell {
  height: var(--pineapple-touch-target);
  min-width: var(--pineapple-touch-target);
  text-align: center;
  vertical-align: middle;
}

/* The control is an `input` that DevExpress positions absolutely over the
   painted box with `appearance: none`, so it draws nothing itself: growing it
   grows the hit area and leaves the checkbox the operator sees as it was.
   Measured 2026-09-15: sizing the cell alone left the control at 20x20.

   As wide as a touch target, and a quarter-rem shorter than its row at the
   top and at the bottom: 52x44 at Large in a 52 px row. The rows touch, so a
   control as tall as its row left 0.5 px between one row's target and the
   next row's (measured 2026-10-01, Inventory at 768x1024); the inset keeps
   8 px between them and still meets the 44 px floor.

   Sideways the cell's own edge cuts it, so the gap to the next column is the
   column's business, not this rule's: on a mobile device
   ResponsiveListViewController gives the selection column a floor of the
   touch target plus a quarter-rem each side (60 px, XAF's
   GridSelectionColumnModel.MinWidth), which leaves 4 px on either side of
   the 52 px hit area. At XAF's own width the hit area filled the cell and sat
   flush against an inline Edit button in the next column (0 px, Goods
   Receipt's staged lines, 2026-10-01). Do not shrink the control here to buy
   the gap back: a column's width is the grid's, never a stylesheet's.

   Centred rather than grown from its own corner. A box anchored at the
   checkbox's top-left would reach past the cell and take clicks that belong
   to the next column.

   `input` is an element name, not a DevExpress class name — nothing here
   depends on a `.dxbl-*` name surviving an upgrade. */
.pnp-grid--mobile .pnp-grid__selection-cell input {
  width: var(--pineapple-touch-target);
  height: calc(var(--pineapple-touch-target) - 0.5rem);
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

/* XAF renders an inline row action as a plain <button> inside its own wrapper
   (source-derived: InlineActionButton.razor). It is not a DevExpress
   component and reads no SizeMode, so it rendered 24x24 at every width and in
   every size mode, 1 mm from its neighbour. pnp-grid__row-action is stamped
   on the wrapper through XAF's documented hook (dxdocs 404559) by
   InlineRowActionTargetController; `button` is an element name. min-* rather
   than a fixed size, so a labelled action is never cut. */
.pnp-grid--mobile .pnp-grid__row-action > button {
  min-width: var(--pineapple-touch-target);
  min-height: var(--pineapple-touch-target);
}

/* Focus ring: the width and the offset are structure and live here; the colour
   is the theme's and arrives as a custom property. currentColor is the fallback
   for a theme that has not defined one — visible, never invisible. */
.pnp-grid__row:focus-visible,
.pnp-grid__cell:focus-visible,
.pnp-grid__header-cell:focus-visible,
.pnp-grid__selection-cell:focus-visible {
  outline: var(--pineapple-focus-ring-width, 2px) solid var(--pineapple-grid-focus-ring-color, currentColor);
  outline-offset: var(--pineapple-focus-ring-offset, 2px);
}

/* ---------------------------------------------------------------------------
   Cards on a handheld (#1748)

   A row is stacked into a card instead of being read sideways. Nothing is
   hidden and no column is moved: the grid renders every column it always did,
   and each cell becomes its own line labelled with the caption of the column it
   came from. The caption arrives as an attribute the controller stamps, because
   CSS cannot reach the header cell that holds it.

   The rules need BOTH of our own modifiers: --cards, which the controller
   writes when the company has switched the feature on, and --handheld, which
   the list-view controller writes only below 768 px. A desktop-class viewport
   never carries the second one, so it can never be stacked.

   Measured 2026-09-17: stacking the row alone is not enough. A DxGrid lays its
   columns out in a table and the widths live on the table's own <colgroup> and
   on the cells, so a stacked cell kept its 70-120 px column width and broke the
   caption one letter per line. The table therefore stops being a table in card
   mode, and the column widths are released with it.
   --------------------------------------------------------------------------- */

/* Element names, not DevExpress class names: nothing here depends on a .dxbl-*
   name surviving an upgrade. */
.pnp-grid--cards.pnp-grid--handheld table {
  display: block;
  width: 100%;
  table-layout: auto;
}

.pnp-grid--cards.pnp-grid--handheld colgroup {
  display: none;
}

.pnp-grid--cards.pnp-grid--handheld .pnp-grid__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  width: 100%;
}

/* Each value is its own line. The selection cell and the row's own command
   buttons are not data cells, so they keep their width and stay on the first
   line, where the operator already looks for them. */
.pnp-grid--cards.pnp-grid--handheld .pnp-grid__cell {
  display: flex;
  flex: 1 1 100%;
  width: auto;
  max-width: none;
  min-width: 0;
  align-items: baseline;
  gap: 0.5rem;

  /* Numeric columns are right-aligned in a table, which pushes the label to the
     right-hand edge of its own box and breaks the column of labels. A card has
     one reading edge: the left one. */
  text-align: left;
}

/* The cell's own content box is sized for a column and clips what does not fit.
   A card has the width of the screen instead, so the text wraps and is never
   cut: an operator matches a code character by character against a label. */
.pnp-grid--cards.pnp-grid--handheld .pnp-grid__cell,
.pnp-grid--cards.pnp-grid--handheld .pnp-grid__cell > * {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  overflow-wrap: anywhere;
}

.pnp-grid--cards.pnp-grid--handheld .pnp-grid__cell::before {
  content: attr(data-pnp-caption);
  flex: 0 0 6rem;
  font-size: 0.8125rem;    /* 13px - the label is secondary to the value */
  overflow-wrap: anywhere;
}

/* The column headers say nothing about a card: every line carries its own
   label. Hiding the row itself, not only its cells, gives the operator the
   height back. */
.pnp-grid--cards.pnp-grid--handheld .pnp-grid__header-cell,
.pnp-grid--cards.pnp-grid--handheld thead {
  display: none;
}

/* A column with nothing in it for this row is not a line. The controller marks
   the cell, because CSS cannot ask whether a cell is empty. */
.pnp-grid--cards.pnp-grid--handheld .pnp-grid__cell--empty {
  display: none;
}
