/* HowtoThing — the design system from design/hifi, as CSS.
   Tokens first; nothing below invents a value that is not here. */

/* --- the two typefaces ---------------------------------------------------
   Hosted here, not linked from Google. The <link> to fonts.googleapis.com used
   to block rendering while two more domains were resolved and TLS-handshaked,
   and it pulled thirteen files across for a page with two input boxes — most of
   the weight of the lightest screen in the app. Measured with tools/perf.sh -w.

   Both faces are SIL Open Font License 1.1, so self-hosting is allowed. This is
   not the Fontcraft licence CLAUDE.md §12 is waiting on; that one is still off
   limits until the webfont files are bought.

   Only the thai and latin ranges are here. Google declares five; a Thai page
   with arabic numerals never asks for cyrillic, latin-ext or vietnamese.
   Refresh with tools/fetch-fonts.sh — the filenames are stable, so mind that
   .htaccess serves woff2 as immutable: a replaced file needs a new name.
   --------------------------------------------------------------------------- */

@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-thai-400-thai.woff2) format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-thai-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-thai-500-thai.woff2) format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-thai-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-thai-600-thai.woff2) format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'IBM Plex Sans Thai';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-thai-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Mitr';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/mitr-400-thai.woff2) format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'Mitr';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/mitr-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Mitr';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/mitr-500-thai.woff2) format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'Mitr';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/mitr-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Mitr';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/mitr-600-thai.woff2) format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'Mitr';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/mitr-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --ink:        #111111;
  --paper:      #ffffff;
  --orange:     #FF882D;   /* the one colour, and it means DISPOSABLE */
  --muted:      #666666;
  --muted-dark: #cfcfcf;   /* muted, but sitting on ink */
  --hint:       #c4c4c4;   /* dashed placeholders */

  --border:     2px;
  --r-card:     14px;
  --r-sheet:    40px;
  --r-pill:     999px;

  --pad:        20px;
  --tap:        44px;      /* never smaller than this */
  --tap-lg:     52px;

  --display: 'Mitr', -apple-system, 'Helvetica Neue', sans-serif;
  --body:    'IBM Plex Sans Thai', -apple-system, 'Helvetica Neue', sans-serif;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

main { display: flex; flex-direction: column; min-height: 100dvh; }

a { color: inherit; }
a:hover { color: var(--orange); }

/* --- the two-layer shell -------------------------------------------------
   A colour block runs full bleed with square corners; the white sheet below
   carries the rounding and rides up over it. Every screen uses this. */

.block {
  padding: calc(env(safe-area-inset-top, 0px) + 26px) var(--pad) 64px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  overflow: hidden;              /* clips the boxes when they jump */
}
.block--orange { background: var(--orange); color: var(--ink); }
.block--dark   { background: var(--ink);    color: var(--paper); }
.block--dark .muted { color: var(--muted-dark); }

.sheet {
  background: var(--paper);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  margin-top: -44px;
  padding-top: 26px;
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 8px);
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  position: relative;
}

.bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

/* The wordmark is cropped to its cap height, so this IS the letter height —
   not a box with slack in it. 14px keeps the same footprint the old file had
   at 20px, with the letters a touch crisper. */
.logo { display: block; flex-shrink: 0; height: 14px; width: auto; }

/* --- type ---------------------------------------------------------------- */

.display   { font-family: var(--display); font-weight: 500; }
.count     { font-family: var(--display); font-weight: 600; font-size: 86px; line-height: 1; }
.h1        { font-family: var(--display); font-weight: 600; font-size: 26px; line-height: 1.2; margin: 0; }
.h2        { font-family: var(--display); font-weight: 600; font-size: 22px; line-height: 1.25; margin: 0; }
.h3        { font-family: var(--display); font-weight: 500; font-size: 15px; margin: 0; }
.muted     { color: var(--muted); }
.small     { font-size: 12px; }
.tiny      { font-size: 11px; }
.wrap      { line-height: 1.6; text-wrap: pretty; }

/* --- rows, cards, lists --------------------------------------------------- */

.pad  { padding-left: var(--pad); padding-right: var(--pad); }
.stack { display: flex; flex-direction: column; gap: 10px; }
.row   { display: flex; align-items: center; gap: 12px; }
.spread { display: flex; justify-content: space-between; align-items: center; gap: 14px; }
.grow  { flex-grow: 1; min-width: 0; }

.card {
  background: var(--paper);
  border: var(--border) solid var(--ink);
  border-radius: var(--r-card);
  padding: 12px;
}
.card--tall  { padding: 14px 18px; min-height: 56px; }
.card--dark  { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.card--dark .muted { color: var(--muted-dark); }

/* Black on a pile card is a selection, not an identity: it marks the list you
   are currently looking at. Every pile is white until you pick it. */
.card.is-on  { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.card.is-on .muted { color: var(--muted-dark); }
.card.is-on svg { stroke: currentColor; }

.thumb {
  width: 52px; height: 52px;
  flex-shrink: 0;
  border: var(--border) dashed var(--hint);
  border-radius: 10px;
  object-fit: cover;
  background: var(--paper);
}
.thumb--lg { width: 96px; height: 96px; }
img.thumb { border-style: solid; border-color: var(--ink); }

.place { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); }
.place svg { flex-shrink: 0; }

.tag {
  display: inline-flex; align-self: flex-start; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 500;
  border: var(--border) solid var(--ink);
  border-radius: var(--r-pill);
  padding: 2px 9px;
}
.tag--accent { background: var(--orange); }

/* --- controls ------------------------------------------------------------- */

.btn {
  font-family: var(--display);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  background: var(--paper);
  border: var(--border) solid var(--ink);
  border-radius: var(--r-pill);
  padding: 0 18px;
  height: var(--tap-lg);
  flex-shrink: 0;
  cursor: pointer;
  white-space: nowrap;
}
.btn--sm     { height: var(--tap); font-size: 14px; padding: 0 16px; }

/* An action with no room for a word. Same 2px capsule as every other button,
   drawn in whatever colour the block it sits on hands down, so one rule works on
   the orange dashboard and on the dark shelves both. */
.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  flex-shrink: 0;
  color: inherit;
  background: none;
  border: var(--border) solid currentColor;
  border-radius: var(--r-pill);
  cursor: pointer;
}
/* Hover must not take the global a:hover orange. On the dashboard that paints an
   orange ring and an orange glyph onto an orange block and the button disappears
   into it. It inverts to a white capsule instead — the same lift-off-the-block
   move .card.is-on makes — which reads the same on the orange block and on the
   dark shelves, and keeps orange meaning DISPOSABLE and nothing else. */
.iconbtn:hover,
.iconbtn:focus-visible {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--ink);
}
.iconbtn:active { transform: translateY(1px); }
.btn--solid  { background: var(--ink); color: var(--paper); }
.btn--accent { background: var(--orange); color: var(--ink); }
.btn--grow   { flex-grow: 1; }
.btn:active  { transform: translateY(1px); }
.btn:focus-visible,
.iconbtn:focus-visible,
.shot-x:focus-visible,
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible { outline: 3px solid var(--orange); outline-offset: 2px; }

.actions {
  display: flex; gap: 8px;
  margin-top: auto;
  padding: 16px var(--pad) calc(env(safe-area-inset-bottom, 0px) + 26px);
  border-top: var(--border) solid var(--ink);
}

/* The two shelves that are deliberately not one of the three piles. They still
   need a door on the dashboard: an item that leaves the piles with nowhere to be
   seen reads as deleted, and nothing here is ever deleted. */
.doors {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin-top: auto;
  padding: 26px var(--pad) 0;
}
.doors .btn { display: inline-flex; align-items: center; text-decoration: none; gap: 7px; }
.doors .btn b { font-weight: 600; }
.doors + .actions { margin-top: 18px; }

.field { display: flex; flex-direction: column; gap: 7px; }
.field > span { font-size: 13px; color: var(--muted); }
.field input,
.field select,
.field textarea {
  font-family: var(--body);
  font-size: 16px;               /* 16px stops iOS zooming on focus */
  color: var(--ink);
  background: var(--paper);
  border: var(--border) solid var(--ink);
  border-radius: 12px;
  padding: 13px 14px;
  min-height: 50px;
  width: 100%;
}
.field textarea { min-height: 92px; resize: vertical; line-height: 1.5; }

/* radio and checkbox groups render as capsules; the input itself is hidden
   but still focusable, so keyboard and screen readers keep working */
.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip { position: relative; }
.chip input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.chip span {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-size: 15px; font-weight: 500;
  color: var(--muted);
  background: var(--paper);
  border: var(--border) solid var(--hint);
  border-radius: var(--r-pill);
  padding: 0 15px;
  height: 46px;
}
.chip input:checked + span { color: var(--paper); background: var(--ink); border-color: var(--ink); }
.chip input:focus-visible + span { outline: 3px solid var(--orange); outline-offset: 2px; }

/* --- the photo queue ------------------------------------------------------
   Photos accumulate: pick some, pick more, the ones already there stay. One
   object, not a row of loose tiles — the add tile is the last cell of the grid
   rather than a button floating under it. assets/photos.js does the rest. */

.shots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 10px;
}
.shot { position: relative; display: flex; flex-direction: column; gap: 6px; min-width: 0; }

.shot-img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border: var(--border) solid var(--ink);
  border-radius: 10px;
  background: var(--paper);
}

/* A file this browser could not draw — HEIC anywhere but Safari. It still goes
   up and the server converts it, so name the format instead of leaving a broken
   image square, which reads as a photo that failed. */
.shot-raw {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-size: 13px;
  color: var(--muted);
}

.shot-x {
  position: absolute;
  top: -7px;
  right: -7px;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-family: var(--display);
  font-size: 15px;
  line-height: 1;
  color: var(--ink);
  background: var(--paper);
  border: var(--border) solid var(--ink);
  border-radius: var(--r-pill);
  cursor: pointer;
}
.shot-x:active { transform: translateY(1px); }

/* On a saved photo the × is a form of its own. It sits on the corner of the
   picture, so it must not take a row in the card's column. */
.shot-drop { position: absolute; top: -7px; right: -7px; display: block; }
.shot-drop .shot-x { position: static; }

/* What a photo is, is optional: "—" is a real answer and the default one. An
   answered picker gets the solid border, so what is still blank reads at a glance. */
.shot select {
  font-family: var(--body);
  font-size: 12px;
  color: var(--ink);
  background: var(--paper);
  border: var(--border) solid var(--hint);
  border-radius: var(--r-pill);
  height: 32px;
  min-height: 0;
  width: 100%;
  padding: 0 22px 0 10px;
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16' fill='none' stroke='%23111111' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 5.5 L8 10.5 L13 5.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  cursor: pointer;
}
.shot select.is-set { border-color: var(--ink); font-weight: 500; }

/* A dashed hint border is this system's way of saying "nothing here yet" — the
   same thing an empty thumbnail slot says on the dashboard. */
.shot-add { position: relative; display: flex; flex-direction: column; gap: 6px; }
.shot-add > span {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 100%;
  aspect-ratio: 1;
  border: var(--border) dashed var(--hint);
  border-radius: 10px;
  color: var(--muted);
  font-family: var(--display);
  font-size: 12px;
  cursor: pointer;
}
.shot-add input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.shot-add:hover > span { border-color: var(--ink); color: var(--ink); }
.shot-add:focus-within > span { outline: 3px solid var(--orange); outline-offset: 2px; }

.queue-foot { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }

/* Without DataTransfer there is no queue to manage, so the input goes back to
   being an ordinary picker rather than hiding behind a tile that cannot work. */
.shots.is-plain { display: block; }
.shots.is-plain .shot-add > span { display: none; }
.shots.is-plain .shot-add input {
  position: static;
  opacity: 1;
  height: auto;
  border: var(--border) solid var(--ink);
  border-radius: 12px;
  padding: 13px 14px;
}

details > summary { list-style: none; cursor: pointer; }
details > summary::-webkit-details-marker { display: none; }
details[open] > summary .chev { transform: rotate(180deg); }
.chev { transition: transform .15s ease; }

/* --- the dashboard's falling boxes ---------------------------------------- */

.boxes { position: relative; flex-shrink: 0; width: 196px; height: 157px; }
.boxes img { position: absolute; left: 0; top: 0; width: 196px; height: auto; display: block; }

@keyframes ht-drop {
  0%          { transform: translateY(0);     animation-timing-function: cubic-bezier(.12,.8,.3,1); }
  4.2%        { transform: translateY(-30%);  animation-timing-function: cubic-bezier(.5,0,.85,.4); }
  12.6%       { transform: translateY(0);     animation-timing-function: cubic-bezier(.2,.85,.4,1); }
  15.1%       { transform: translateY(-7%);   animation-timing-function: cubic-bezier(.5,0,.85,.4); }
  17.6%       { transform: translateY(0);     animation-timing-function: cubic-bezier(.2,.85,.4,1); }
  19%         { transform: translateY(-2.5%); animation-timing-function: cubic-bezier(.5,0,.85,.4); }
  20.4%, 100% { transform: translateY(0); }
}
.boxes img { animation: ht-drop 10s linear infinite; }
.boxes img:nth-child(1) { animation-delay: .16s; }   /* small, behind */
.boxes img:nth-child(2) { animation-delay: .34s; }   /* the one resting on it */
.boxes img:nth-child(3) { animation-delay: 0s; }     /* big one lands first */

@media (prefers-reduced-motion: reduce) {
  .boxes img { animation: none; }
  .btn:active { transform: none; }
}

/* --- the gate ------------------------------------------------------------
   Signing in is not part of the app, it is the door to it: no colour block,
   no sheet, nothing to read but the two fields. */

.gate { flex-grow: 1; display: flex; align-items: center; justify-content: center; padding: 40px 20px; }
.gate-card { width: 100%; max-width: 376px; display: flex; flex-direction: column; gap: 30px; }
.gate-mark { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.gate-mark img { display: block; width: 168px; height: auto; }
.gate .btn { width: 100%; height: 56px; font-size: 16px; }

/* --- messages ------------------------------------------------------------- */

.errors {
  margin: 0 var(--pad) 16px;
  padding: 12px 16px;
  list-style: none;
  border: var(--border) solid var(--ink);
  border-radius: var(--r-card);
  background: var(--orange);
  font-size: 14px;
}
.errors li + li { margin-top: 4px; }

.empty { padding: 28px var(--pad); text-align: center; color: var(--muted); font-size: 14px; }

/* A destructive action that must not look like the ones beside it. No capsule,
   no fill — an underlined word you have to mean to press. */
.linkish {
  display: inline-block;
  font-family: var(--display); font-weight: 500; font-size: 14px;
  background: none; border: 0; border-bottom: var(--border) solid var(--ink);
  padding: 0 0 2px; cursor: pointer; color: inherit; text-decoration: none;
}
.linkish:hover { color: var(--orange); border-color: var(--orange); }
.inline { display: inline; }

/* --- the rail's menu: desktop only ---------------------------------------
   Phones use the buttons pinned to the bottom of the sheet instead. */

.railnav { display: none; }
.railnav-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--display);
  font-size: 16px;
  font-weight: 500;
  text-decoration: none;
  padding: 12px 16px;
  min-height: 48px;
  border: var(--border) solid transparent;
  border-radius: var(--r-pill);
  color: inherit;
}
.railnav-item:hover { border-color: currentColor; color: inherit; }
.railnav-item.is-on { background: currentColor; border-color: currentColor; }
.railnav-item.is-on > span { color: var(--orange); }
.block--dark .railnav-item.is-on > span { color: var(--ink); }
.railnav-badge {
  font-family: var(--display);
  font-size: 13px;
  font-weight: 600;
  background: var(--orange);
  color: var(--ink);
  border: var(--border) solid currentColor;
  border-radius: var(--r-pill);
  min-width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 6px;
}

/* --- tablet portrait and small windows: keep the phone column ------------- */

@media (min-width: 480px) and (max-width: 819px) {
  body { background: #f4f4f4; }
  main { max-width: 420px; margin: 0 auto; background: var(--paper); }
}

/* --- 820px and up: the same two layers, turned on their side --------------
   The sheet stops sliding up over the colour block and slides LEFT over it
   instead. Nothing in the markup changes; only the direction does. */

@media (min-width: 820px) {
  body { background: #f4f4f4; }

  main:not(.gate) {
    flex-direction: row;
    height: 100dvh;
    max-width: none;
    margin: 0;
    overflow: hidden;
  }

  .block {
    width: 372px;
    flex-shrink: 0;
    /* right padding must clear the sheet's 44px overlap, with room to spare */
    padding: 34px 64px 30px 30px;
    gap: 26px;
    overflow: hidden;
  }

  .sheet {
    border-radius: var(--r-sheet) 0 0 var(--r-sheet);
    margin-top: 0;
    margin-left: -44px;
    padding: 38px 40px calc(env(safe-area-inset-bottom, 0px) + 24px);
    overflow-y: auto;
  }

  /* the rail is tall now, so the menu can live at its foot */
  .railnav { display: flex; flex-direction: column; gap: 4px; margin-top: auto; }
  .actions--nav { display: none; }        /* the rail says it already */

  /* the rail is a narrow column, so the number and the drawing stack
     instead of sharing a line the way they do across a phone */
  .block .headline { flex-direction: column; align-items: flex-start; gap: 20px; }

  .count  { font-size: 96px; }
  .boxes  { width: 240px; height: 192px; }
  .boxes img { width: 240px; }

  .pad    { padding-left: 0; padding-right: 0; }
  .errors { margin-left: 0; margin-right: 0; }
  .actions {
    padding-left: 0;
    padding-right: 0;
    padding-bottom: 0;
    border-top: 0;
    justify-content: flex-start;
  }
  .actions .btn--grow { flex-grow: 0; }

  /* the three piles fit side by side instead of stacking */
  .piles { flex-direction: row; }
  .piles > * { flex-grow: 1; flex-basis: 0; }

  /* a list of boxes should not stretch to the width of an ultrawide monitor */
  .sheet > *, .sheet form > * { max-width: 940px; }

  .thumb--lg { width: 112px; height: 112px; }
}

/* Long product names must be free to run onto as many lines as they need —
   a model number with no spaces in it included. */
.item-name, .h1, .h2 { overflow-wrap: anywhere; text-wrap: pretty; }
