/* SpritzUp touchscreen — 1280x800 native, reconstructed from the machine.
   Everything is laid out in the LCD's own pixel space; the stage is scaled to fit
   whatever it is mounted in (a browser window now, a screen mesh later). */

@font-face { font-family: "Neue Montreal"; font-weight: 400;
  src: url("../assets/fonts/NeueMontreal-Regular.woff2") format("woff2"); font-display: block; }
@font-face { font-family: "Neue Montreal"; font-weight: 500;
  src: url("../assets/fonts/NeueMontreal-Medium.woff2") format("woff2"); font-display: block; }
@font-face { font-family: "Neue Montreal"; font-weight: 700;
  src: url("../assets/fonts/NeueMontreal-Bold.woff2") format("woff2"); font-display: block; }

:root {
  --bar-bg: #1d2733;
  --bar-fg: #e8eef5;
  --ink: #232a33;
  --ink-soft: #6b7885;
  --ink-faint: #9aa5b1;
  --price: #e0342a;
  --blue: #1a8cff;
  --green: #17b978;
  --amber: #e9a13b;
  --card: #ffffff;
  --stroke: #e4eaf0;
  --shadow: 0 10px 34px rgba(28, 48, 70, .16), 0 2px 8px rgba(28, 48, 70, .08);
  --radius: 16px;
}

* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }

.screen {
  position: relative;
  width: 1280px; height: 800px;
  overflow: hidden;
  /* the 2px corner-soften against the bezel used to live on .lcd-holder, the CSS3D-
     transformed element itself — a grouping property there flattens Safari's projection
     of the whole screen (viewer.css:42-64). This element already clips (line above), so
     it does the same job with none of the risk. */
  border-radius: 2px;
  font-family: "Neue Montreal", system-ui, sans-serif;
  color: var(--ink);
  background: linear-gradient(168deg, #eef3f8 0%, #dde7f0 46%, #cfdcE8 100%);
  user-select: none;
  transform-origin: top left;
}

/* ---------------------------------------------------------------- status bar */

.statusbar {
  height: 58px; flex: 0 0 58px;
  background: var(--bar-bg); color: var(--bar-fg);
  display: flex; align-items: center;
  padding: 0 18px;
  /* No uniform gap. The machine spreads these across the bar - measured left offsets
     22 / 366 / 450 / 564 / 739 / 1134 in the 1280 px grid - and a 34 px gap packed
     everything after the device id 200-300 px too far left. */
  gap: 0;
  font-size: 16px; font-weight: 400; letter-spacing: .1px;
}
.statusbar .spacer { flex: 1; }
.statusbar .item { display: flex; align-items: center; gap: 8px; opacity: .96;
  position: absolute; }
.statusbar .item.i0 { left: 22px; }
.statusbar .item.i1 { left: 366px; }
.statusbar .item.i2 { left: 450px; }
.statusbar .item.i3 { left: 564px; }
.statusbar .item.i4 { left: 739px; }
.statusbar .item.clock { left: auto; right: 22px; }
.statusbar { position: relative; }
.statusbar svg { width: 17px; height: 17px; }

/* ---------------------------------------------------------------- grid */

.stage { position: absolute; inset: 58px 0 0 0; }

.grid {
  position: absolute; inset: 0;
  /* Gap was 95px, taken from the real machine's measured tile pitch of 303px. Deliberately
   * overridden, and the measurement is recorded here rather than deleted: at 95px the row is
   * 34 + 208x5 + 95x4 + 34 = 1488px inside a 1280px panel, so the fifth product was scrolled
   * off and clipped by .screen's overflow. On the real hardware that is fine — it is a
   * touchscreen you drag, and the pitch is what it is. In the 3D viewer it is not: the bay
   * behind the screen shows five bottles and the fascia below it has five nozzles and five
   * buttons, so a screen listing four contradicts the product a visitor is looking at.
   * 42px puts all five in the panel at 1276px, with 4px of slack against sub-pixel rounding.
   * .tile.focus scales to 1.14 (+29px total), which still clears a 42px gap. */
  display: flex; align-items: center; gap: 42px;
  padding: 0 34px;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none;
  touch-action: pan-x;
  cursor: grab;
  scroll-behavior: auto;
}
.grid::-webkit-scrollbar { display: none; }
.grid:active { cursor: grabbing; }

.tile {
  /* min-width:0 is load-bearing, not tidying. Flex items default to min-width:auto, which
   * floors them at their min-content width — and .tile .name is white-space:nowrap, so the
   * longest product names ("Jo Malone Cypress", "Armani Stronger With You") pushed their
   * tiles to 264px and 220px instead of the 208px basis, and the ellipsis those names were
   * given never had a constraint to trigger against. That irregularity is also why the row
   * measured a "303px pitch" that no pair of tiles actually shared. */
  min-width: 0;
  position: relative; flex: 0 0 208px; height: 281px;
  background: var(--card); border-radius: var(--radius);
  box-shadow: var(--shadow);
  display: flex; flex-direction: column;
  padding: 14px 15px 13px;
  transition: transform .16s ease, box-shadow .16s ease;
  cursor: pointer;
}
.tile:active { transform: scale(.972); box-shadow: 0 4px 14px rgba(28,48,70,.16); }
/* the tile nearest screen centre is the focus affordance on the real grid */
.tile.focus { transform: scale(1.14); box-shadow: 0 12px 34px rgba(28,48,70,.26); z-index: 2; }
.tile.focus:active { transform: scale(1.10); }
.tile.depleted { opacity: .48; pointer-events: none; }

.tile .badge {
  position: absolute; top: 11px; right: 11px;
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--blue); color: #fff;
  display: grid; place-items: center;
  font-size: 17px; font-weight: 500;
  box-shadow: 0 2px 7px rgba(26,140,255,.34);
}
.tile .art { flex: 1; display: grid; place-items: center; min-height: 0; padding: 2px 0 8px; }
.tile .art img { max-width: 100%; max-height: 176px; object-fit: contain; }
.tile .name {
  font-size: 17px; font-weight: 500; line-height: 1.16; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  margin-bottom: 7px;
}
.tile .meta { display: flex; align-items: baseline; justify-content: space-between; }
.tile .dose { font-size: 13px; color: var(--ink-faint); }
.tile .cost { font-size: 18px; font-weight: 500; color: var(--price); }

/* ---------------------------------------------------------------- overlays */

.veil {
  position: absolute; inset: 0;
  background: rgba(190, 208, 224, .52);
  backdrop-filter: blur(1.5px);
  display: grid; place-items: center;
  animation: veil-in .16s ease both;
}
@keyframes veil-in { from { opacity: 0 } to { opacity: 1 } }
@keyframes card-in {
  from { opacity: 0; transform: translateY(10px) scale(.985) }
  to   { opacity: 1; transform: none }
}

.card {
  background: var(--card); border-radius: 22px; box-shadow: var(--shadow);
  position: relative; animation: card-in .2s cubic-bezier(.2,.7,.3,1) both;
}
.card .close {
  position: absolute; top: 18px; right: 18px;
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer; color: var(--ink-soft);
}
.card .close:active { background: #eef2f6; }
.card .close svg { width: 22px; height: 22px; }

.timer {
  position: absolute; top: 22px; left: 24px;
  font-size: 19px; font-weight: 500; color: var(--price); opacity: .78;
  font-variant-numeric: tabular-nums;
}
.timer.calm { color: var(--ink-faint); }

/* ---------------------------------------------------------------- product modal */

.product { width: 639px; height: 426px; display: flex; padding: 20px; gap: 18px; }
.product .pane {
  /* plain white, no border and no card. The machine shows the bottle straight on the
     modal ground with the label under it - the bordered pane was invented. */
  flex: 0 0 214px; background: transparent; border: 0;
  padding: 4px; display: flex; flex-direction: column;
}
.product .pane .tag { font-size: 14px; color: var(--ink-faint); }
.product .pane .shot { flex: 1; display: grid; place-items: center; min-height: 0; }
.product .pane .shot img { max-width: 100%; max-height: 250px; object-fit: contain; }
.product .pane .info { font-size: 14px; color: var(--ink-faint); text-align: center; }

.product .detail { flex: 1; display: flex; flex-direction: column; padding-top: 18px; }
.product .detail .timer { position: static; margin: 0 0 6px; }
.product .detail h1 {
  font-size: 26px; font-weight: 500; line-height: 1.15; margin-bottom: 16px; padding-right: 52px;
}
.product .rows { display: flex; flex-direction: column; gap: 12px; flex: 1; }
.product .row2 { display: flex; gap: 12px; }
.field {
  /* left-aligned label/value rows on plain white; the grey centred chips were a
     different design from the machine's */
  background: transparent; border-radius: 0; padding: 2px 0; flex: 1;
  display: flex; flex-direction: row; align-items: baseline;
  justify-content: space-between; gap: 10px;
}
.field .label { font-size: 15px; color: var(--ink-faint); }
.field .value { font-size: 21px; font-weight: 500; }
.field .value.money { color: var(--price); }

.stepper { display: flex; align-items: center; gap: 18px; }
.stepper button {
  width: 27px; height: 27px; border-radius: 50%; border: 0; cursor: pointer;
  background: #414b57; color: #fff; display: grid; place-items: center;
}
.stepper button:disabled { opacity: .3; cursor: default; }
.stepper button:active:not(:disabled) { transform: scale(.92); }
.stepper button svg { width: 13px; height: 13px; }
.stepper .n { font-size: 26px; font-weight: 500; min-width: 26px; text-align: center;
  font-variant-numeric: tabular-nums; }

.btn {
  border: 0; cursor: pointer; border-radius: 999px;
  background: #414b57; color: #fff;
  font-family: inherit; font-size: 19px; font-weight: 500;
  padding: 9px 24px; width: 266px; align-self: center;
  transition: transform .12s ease, background .12s ease;
}
.btn:active { transform: scale(.985); background: #333c47; }
.btn.ghost { background: #eef2f6; color: var(--ink); }

/* ---------------------------------------------------------------- method chooser */

.method { width: 616px; padding: 26px 30px 34px; }
.method h2 {
  font-size: 22px; font-weight: 400; color: var(--ink-soft);
  text-align: center; margin-bottom: 30px; padding: 0 40px;
}
.method .opts { display: flex; gap: 26px; justify-content: center; }
.method .opt {
  width: 176px; height: 168px; border-radius: 16px; background: #f4f7fa;
  border: 2px solid transparent;
  display: grid; place-items: center; cursor: pointer;
  transition: transform .14s ease, border-color .14s ease, background .14s ease;
}
.method .opt:active { transform: scale(.96); }
.method .opt:hover { background: #eef3f8; }
.method .opt svg { width: 96px; height: 96px; color: #3d4a57; }

/* ---------------------------------------------------------------- cart */

.cart { width: 1112px; padding: 22px 22px 26px; }
.cart h2 { font-size: 25px; font-weight: 500; text-align: center; margin-bottom: 22px; }
.cart .cols { display: flex; gap: 20px; align-items: stretch; }
.cart .col {
  flex: 1; background: #fbfcfd; border: 1px solid var(--stroke);
  border-radius: 16px; padding: 16px; min-height: 288px;
  display: flex; flex-direction: column;
}
.cart .col.items { flex: 1.15; }

.line { display: flex; align-items: center; gap: 14px; padding: 11px 0;
  border-bottom: 1px solid #eef2f6; }
.line:last-of-type { border-bottom: 0; }
.line .thumb {
  position: relative; width: 62px; height: 74px; flex: 0 0 62px;
  background: #fff; border-radius: 10px; border: 1px solid var(--stroke);
  display: grid; place-items: center;
}
.line .thumb img { max-width: 82%; max-height: 82%; object-fit: contain; }
.line .thumb .pip {
  position: absolute; top: -7px; left: -7px; width: 24px; height: 24px;
  border-radius: 50%; background: var(--blue); color: #fff;
  display: grid; place-items: center; font-size: 13px; font-weight: 500;
}
.line .who { flex: 1; min-width: 0; }
.line .who .nm { font-size: 16px; font-weight: 500; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.line .who .sub { font-size: 13px; color: var(--ink-faint); margin-top: 3px; }
.line .qty { font-size: 15px; color: var(--ink-soft); }
.line .amt { font-size: 17px; font-weight: 500; }

.totals { margin-top: auto; padding-top: 14px; border-top: 1px solid var(--stroke); }
.totals .t { display: flex; justify-content: space-between; padding: 5px 0; font-size: 17px; }
.totals .t.grand { font-size: 22px; font-weight: 500; }
.totals .t.grand span:last-child { color: var(--price); }

.cart .col h3 { font-size: 15px; font-weight: 400; color: var(--ink-faint);
  text-align: center; margin-bottom: 16px; }
.pick {
  display: flex; align-items: center; gap: 14px;
  background: #fff; border: 2px solid var(--stroke); border-radius: 14px;
  padding: 13px 16px; margin-bottom: 12px; cursor: pointer;
  transition: border-color .14s ease, background .14s ease;
}
.pick:active { transform: scale(.99); }
.pick .ico { width: 44px; height: 40px; border-radius: 9px; background: #f0f4f8;
  display: grid; place-items: center; color: #46535f; }
.pick .ico svg { width: 26px; height: 26px; }
.pick .lbl { flex: 1; text-align: center; font-size: 18px; font-weight: 500; }
.pick .tick { width: 26px; height: 26px; border-radius: 50%; background: var(--green);
  display: none; place-items: center; color: #fff; }
.pick .tick svg { width: 15px; height: 15px; }
.pick.on { border-color: var(--green); background: #f4fdf8; }
.pick.on .tick { display: grid; }

.prompt { display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 22px; text-align: center; flex: 1; }
.prompt p { font-size: 18px; color: var(--ink); }
.prompt svg { width: 132px; height: 132px; color: var(--blue); }
.prompt .pulse { animation: pulse 1.7s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1; transform: scale(1) } 50% { opacity: .62; transform: scale(.96) } }

/* ---------------------------------------------------------------- approved */

.approved { width: 340px; height: 216px; display: grid; place-items: center; }
.approved svg { width: 92px; height: 92px; color: var(--green); animation: pop .34s cubic-bezier(.2,1.4,.4,1) both; }
@keyframes pop { from { transform: scale(.5); opacity: 0 } to { transform: none; opacity: 1 } }

/* ---------------------------------------------------------------- dispense */

.dispense { width: 412px; padding: 24px 24px 20px; text-align: center;
  display: flex; flex-direction: column; align-items: center; }
.dispense .no { font-size: 50px; font-weight: 500; letter-spacing: -.5px; margin: 6px 0 14px; }
.dispense .shot { height: 178px; display: grid; place-items: center; }
.dispense .shot img { max-height: 172px; max-width: 168px; object-fit: contain; }
.dispense .nm { font-size: 19px; font-weight: 500; margin-top: 12px; }
.dispense .qt { font-size: 15px; color: var(--ink-faint); margin-top: 5px; }
.dispense .warn {
  margin-top: 18px; display: flex; align-items: center; gap: 10px;
  background: #fdf6e8; border: 1px solid #f2e0bd; border-radius: 11px;
  padding: 10px 14px; font-size: 14px; color: #8a6a26; text-align: left;
}
.dispense .warn svg { width: 20px; height: 20px; flex: 0 0 20px; color: var(--amber); }
.dispense .queue { margin-top: 12px; font-size: 14px; color: var(--ink-faint); }

/* ---------------------------------------------------------------- spraying */

.spraying { width: 420px; padding: 34px; text-align: center; }
.spraying .no { font-size: 46px; font-weight: 500; margin-bottom: 18px; }
.spraying .bar { height: 8px; border-radius: 4px; background: #e8eef4; overflow: hidden; }
.spraying .bar i { display: block; height: 100%; background: var(--blue); width: 0; }
.spraying p { margin-top: 16px; font-size: 17px; color: var(--ink-soft); }

/* ---------------------------------------------------------------- toast */

.toast {
  position: absolute; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: rgba(35,42,51,.94); color: #fff; border-radius: 999px;
  padding: 12px 24px; font-size: 16px; animation: card-in .18s ease both;
}
