/* Handy (design 3.2; batch F, f5; batch I1, i1): the reference is the iPad mini portrait 744x1133 (6th and 7th gen),
   with the phone 390x844 as the compact tier on the same code, on the tiers of web/platform/tiers.js (compact under
   600 px, medium 600 to 1023 px, wide 1024 px and up; BATCH-I1-PLAN I1-D1 to I1-D7). Density low, 48 px top row,
   56 px bottom bar. Drinks first: the chip row scrolls on the compact tier and wraps from the medium tier, tiles with
   the category colour as a border 3, 3 and 5 across in the items column (batch I2), Mesas rows and Listos cards 1, 2
   and 3 across, the pinned "Enviar ronda" above the bottom bar on the compact tier, sheets with their primary pinned at
   the bottom. Safe areas through base.css's --safe-bottom (I1-D14). Long press hardening on tiles (HANDY-COMPETITION.md
   rank 2): no callout, no selection, no drag, touch-action manipulation. Wholly inside @layer app; colours only
   through tokens.

   Batch I2 (k2; BATCH-I2-PLAN I2-D5, I2-D13 to I2-D18 and 1.3): the ordering layout. web/handy/ordering.js renders
   the Carta and Ticket tabs as one .hd-order, the items column (.hd-items: chips and tiles) first and the ticket column
   (.hd-ticket) second, each with its own data-paint-scroll key. The compact tier (under 600) shows one page at a time
   by data-tab, the page scrolling as before (I2-D13). From 600 the Carta and Ticket tabs are screen-high (I2-D18, the
   definite height chain): the app is 100dvh (100vh before it as the fallback) with min-height 0, .content is a
   scrolling column flex with min-height 0, .hd-order fills it (flex 1 1 0, a 50vh floor, one minmax(0, 1fr) row) and
   each column scrolls on its own (min-height 0, overflow-y auto; no position, max-height or z-index on .hd-items),
   so whatever renders above the columns shortens them and the bottom bar, the app's last in-flow child, stays below
   them. The widths (I2-D5, 1.3, content W - 32, a 16 px column gap, tiles with the 8 px --touch-gap): equal halves from
   600 to 1023 (276 and 276 at 600, 348 and 348 at 744 with tiles 3 across at 110.67, 386 and 386 at 820), from 1024
   minmax(0, 2fr) minmax(340px, 1fr) (636 and 340 at 1024 with tiles 5 across at 120.8, the ticket held at its 340 px
   minimum; 723.33 and 361.67 at 1133 with tiles at 138.27). From 600 the send bar is hidden and the ticket column's
   primary sits in its .ticket-send foot, sticky at the column's bottom (I2-D14); the Ticket tab is hidden and the
   Carta tab reads pressed on both ordering tabs (I2-D16). The bottom bar paints above the page on every tier (z-index
   6: over the send bar's 5, the ticket foot's 1 and the map cards' 1 and 2, web/platform/floormap.css:32-33; under
   the sheet's 10, web/platform/base.css:142, and the step-up sheet's 11 further down this file). iPadOS behaviour
   (100dvh in Safari and standalone, sticky inside an inner scroller, a finger drag across the repaint) is UNVERIFIED
   until measured on the device (BATCH-I2-PLAN 14.2). */
@layer app {
  .app-handy .content { padding-bottom: calc(var(--touch-keypad) + var(--space-4) + var(--safe-bottom)); }
  .app-handy.has-send-bar .content { padding-bottom: calc(var(--touch-keypad) + var(--touch-primary) + var(--space-5) + var(--safe-bottom)); }

  /* Top row: the table name is the door to the table sheet (La cuenta, Cobrar). */
  .app-handy .topbar-table { margin-right: auto; font-size: var(--font-size-400); font-weight: 700; border-color: transparent;
    background: transparent; padding: 0 var(--space-2); }

  /* Mesas by zone, one truthful state per row, minutes that never wrap. */
  .app-handy .zone-head { font-size: var(--font-size-200); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted);
    margin: var(--space-4) 0 var(--space-2); }
  .app-handy .row-state { font-size: var(--font-size-200); color: var(--text-muted); }
  .app-handy .row-min { white-space: nowrap; }

  /* Carta: one scrolling chip row on the compact tier (it wraps from 600, below), then the overflow for Fotos or Lista. */
  .app-handy .carta-row { display: flex; flex-wrap: nowrap; gap: var(--touch-gap); overflow-x: auto; overscroll-behavior-x: contain;
    padding-bottom: var(--space-2); margin-bottom: var(--space-2); scrollbar-width: none; }
  .app-handy .carta-row .chip { flex: none; white-space: nowrap; }
  .app-handy .carta-row .chip-more { margin-left: auto; }
  .app-handy .carta-overflow { display: flex; justify-content: flex-end; gap: var(--touch-gap); margin-bottom: var(--space-2); }

  /* Compact tiles: three across on the compact tier (the phone), a short media box, the category colour as the border. */
  .app-handy .tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .app-handy .tile-wrap { display: flex; min-width: 0; }
  .app-handy .tile-wrap .tile { flex: 1; min-width: 0; border-width: 2px; border-color: var(--cat-fill, var(--border)); padding: var(--space-1); }
  .app-handy .tile-wrap .tile-media { aspect-ratio: auto; min-height: var(--touch-keypad); }
  .app-handy .tile-wrap .tile-name { font-size: var(--font-size-200); overflow-wrap: anywhere; }
  .app-handy .tile-wrap .tile-price { font-size: var(--font-size-200); }
  .app-handy .tile-wrap .tile-cat { display: none; }
  .app-handy .tile { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; touch-action: manipulation; }
  .app-handy .tile img { -webkit-user-drag: none; }
  /* Batch I2 (I2-D13, I2-D18): the compact tier shows one ordering page at a time, the items column on the Carta tab and
     the ticket column on the Ticket tab; the bottom bar paints above the page on every tier (base.css:158 gives the
     sticky bar no z-index, so the map cards' 1 and 2 would paint over its tabs where the plan scrolls under it). */
  .app-handy[data-tab="menu"] .hd-ticket { display: none; }
  .app-handy[data-tab="ticket"] .hd-items { display: none; }
  .app-handy .bottombar { z-index: 6; }

  /* The medium tier (the iPad mini portrait, I1-D3, I1-D4, I1-D6, I1-D7): Mesas rows 2 across (352 px), the chip row
     wrapped, Listos cards 2 across (350 px) on main's last panel only, because the queue panel (web/handy/ticket.js:90)
     comes first as attention and stays a list; the empty line spans the row. The tiles stay 3 across in the items
     column (110.67 px at 744, batch I2). The wide tier: 5 tiles in the items column, 3 rows and 3 cards.
     Batch I2 (I2-D18, the definite height chain): on the Carta and Ticket tabs the app is screen-high and each column
     scrolls on its own; the .content rule sits after the has-send-bar rule above (same specificity, later wins). */
  @media (min-width: 600px) {
    .app-handy .rows { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .app-handy .carta-row { flex-wrap: wrap; overflow-x: visible; }
    .app-handy[data-tab="ready"] .content > .panel:last-child { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); align-items: start; }
    .app-handy[data-tab="ready"] .ready-card { margin-bottom: 0; }
    .app-handy[data-tab="ready"] .content > .panel:last-child > .empty { grid-column: 1 / -1; }
    .app-handy[data-tab="menu"], .app-handy[data-tab="ticket"] { height: 100vh; height: 100dvh; min-height: 0; }
    .app-handy[data-tab="menu"] .content, .app-handy[data-tab="ticket"] .content { min-height: 0; overflow-y: auto; display: flex;
      flex-direction: column; padding-bottom: var(--space-3); }
    .app-handy .hd-order { flex: 1 1 0; min-height: 50vh; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      grid-template-rows: minmax(0, 1fr); column-gap: var(--space-4); }
    .app-handy[data-tab="menu"] .hd-ticket, .app-handy[data-tab="ticket"] .hd-items { display: block; }
    .app-handy .hd-items, .app-handy .hd-ticket { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
    .app-handy .ticket-send { position: sticky; bottom: 0; z-index: 1; background: var(--bg); padding: var(--space-2) 0 0; }
    .app-handy .bottombar .tab[data-value="ticket"] { display: none; }
    .app-handy .bottombar .tab[data-order="on"] { border-top-color: var(--accent); font-weight: 700; }
  }
  @media (min-width: 1024px) {
    .app-handy .tiles { grid-template-columns: repeat(5, minmax(0, 1fr)); }
    .app-handy .rows { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .app-handy[data-tab="ready"] .content > .panel:last-child { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .app-handy .hd-order { grid-template-columns: minmax(0, 2fr) minmax(340px, 1fr); }
  }

  /* The pinned send bar sits above the bottom bar and its safe-area inset (I1-D14), full width; since batch I2 it shows on
     the compact tier only (hidden from 600 by the block below). */
  .app-handy .send-bar { position: sticky; bottom: calc(var(--touch-keypad) + var(--safe-bottom)); z-index: 5; display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--space-2); padding: var(--space-2) var(--space-4); background: var(--surface); border-top: 1px solid var(--border); }
  .app-handy .send-bar .send-last { flex: 1 1 40%; min-width: 0; justify-content: flex-start; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .app-handy .send-bar .send-now { flex: 1 1 50%; }
  .app-handy .send-bar .reason { flex-basis: 100%; }
  /* Batch I2 (I2-D14): from 600 the send bar gives way to the ticket column's own primary (.ticket-send). This block sits
     after the send bar's rules above because its selector is the same one, so only the later rule wins. */
  @media (min-width: 600px) {
    .app-handy .send-bar { display: none; }
  }

  /* Ticket lines are tap targets. */
  .app-handy .line { padding: 0; }
  .app-handy .line-btn { flex: 1; justify-content: flex-start; width: 100%; border-color: transparent; background: transparent;
    padding: 0 var(--space-3); text-align: left; }
  .app-handy .line-mods { color: var(--text-muted); font-size: var(--font-size-200); }
  .app-handy .line.is-void .line-name { text-decoration: line-through; }
  .app-handy .line-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); font-size: var(--font-size-200); }

  /* Sheets: groups, and the primary pinned at the bottom of the scrolling sheet. The foot's 16 px negative inline
     margins span the sheet's content column plus 16 px a side: the whole sheet below 600, a centred 600 px foot from
     600 and 720 from 1024 (base.css's inline padding, I1-D5). Its bottom offset, bottom margin and bottom padding carry
     --safe-bottom as the sheet's own bottom padding does, so the foot stays flush with the sheet's bottom edge (I1-D14). */
  .app-handy .sheet-group { margin: var(--space-2) 0; }
  .app-handy .sheet-group .h { font-size: var(--font-size-200); margin: var(--space-2) 0 var(--space-1); }
  .app-handy .sheet-price { font-size: var(--font-size-300); color: var(--text-muted); font-weight: 400; }
  .app-handy .sheet-pin { position: sticky; bottom: calc(-1 * (var(--space-4) + var(--safe-bottom)));
    margin: var(--space-3) calc(-1 * var(--space-4)); margin-bottom: calc(-1 * (var(--space-4) + var(--safe-bottom)));
    padding: var(--space-3) var(--space-4); padding-bottom: calc(var(--space-3) + var(--safe-bottom));
    background: var(--surface); border-top: 1px solid var(--border); }
  .app-handy .sheet-pin .btn-primary { flex: 1; }

  /* Batch G (g5). Rank 9: the read-back under a line's name (pase, comensal, añadidos with prices, nota); the
     supplement marker; each held pase under its header with Marchar; the sent rounds folded below. */
  .app-handy .line-name { min-width: 0; }
  .app-handy .line-read { display: block; color: var(--text-muted); font-size: var(--font-size-200); font-weight: 400; overflow-wrap: anywhere; }
  .app-handy .line-price { margin-left: auto; white-space: nowrap; }
  .app-handy .supl { color: var(--text-muted); font-size: var(--font-size-200); }
  .app-handy .pase { margin: var(--space-5) 0 var(--space-2); }
  .app-handy .pase-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
  .app-handy .pase-head .h { margin: 0; font-size: var(--font-size-300); }
  .app-handy .sent-rounds { margin-top: var(--space-5); border-top: 1px solid var(--border); }
  /* Rank 11: offline, one line on the first view; the details sheet one tap away. */
  .app-handy .offline-line { justify-content: flex-start; gap: var(--space-2); margin: var(--space-2) var(--space-4); width: auto; }

  /* The checkout (web/platform/checkout.js markup). */
  .app-handy .checkout-due { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); margin: var(--space-2) 0; }
  .app-handy .checkout-amount { font-size: var(--font-size-600); }
  .app-handy .checkout-modes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--touch-gap); }
  .app-handy .btn-pay { min-height: var(--touch-primary); font-weight: 700; font-size: var(--font-size-400); }
  .app-handy .checkout-hint { font-size: var(--font-size-400); font-weight: 700; margin: var(--space-3) 0 var(--space-1); }
  .app-handy .checkout-ref { font-size: var(--font-size-800); font-weight: 700; letter-spacing: 0.08em; text-align: center; margin: var(--space-2) 0; }
  .app-handy .checkout-change { font-size: var(--font-size-500); font-weight: 700; }

  /* Batch H (h5). The staff menu door in the top row; the step-up sheet above the sent-line sheet it confirms; the
     ready banner on Mesas; Listos per line with its age and Servido; the Mover líneas check boxes. */
  .app-handy .topbar-menu { border-color: transparent; background: transparent; padding: 0 var(--space-2); }
  .app-handy .sheet-stepup { z-index: 11; }
  .app-handy .ready-banner { justify-content: flex-start; gap: var(--space-2); font-weight: 700; }
  .app-handy .ready-line { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1) 0; }
  .app-handy .ready-line .btn-small { margin-left: auto; }
  .app-handy .ready-age { display: block; }
  .app-handy .move-lines { list-style: none; margin: 0; padding: 0; }
  .app-handy .move-line { width: 100%; justify-content: flex-start; border: 0; background: transparent; color: var(--text); text-align: left; }
  .app-handy .move-line .box { flex: none; width: var(--space-5); height: var(--space-5); border: 2px solid var(--border); border-radius: var(--space-1); }
  .app-handy .move-line[aria-checked="true"] .box { background: var(--accent); border-color: var(--accent); }
  .app-handy .move-line:disabled { color: var(--text-muted); }
  .app-handy .move-line .line-state { margin-left: auto; font-size: var(--font-size-200); }
}
