/*
 * GameSpot kiosk — the design system.
 *
 * ONE stylesheet. It replaces kiosk-ui.css and home-kiosk.css, which were a base
 * sheet and an override sheet fighting each other through several hundred
 * !important declarations — patching either moved things unpredictably in the
 * other, which is how the design drifted.
 *
 * Rules for keeping it that way:
 *
 *   1. No !important. If a rule needs it, the cascade is wrong; fix the cascade.
 *   2. Colours, spacing and type come from the tokens below. No raw hex, no
 *      magic pixel values, in components.
 *   3. Tablet first. Base styles target ~1024-1280 wide in landscape, which is
 *      the machine in the shop. Narrower is handled at the bottom.
 *   4. Touch targets are never below 56px. Fingers, not cursors, and often
 *      somebody's kid in a hurry.
 *   5. Class names match what the pages already use, so the markup and its
 *      inline JS keep working. This is a restyle, not a rewrite of behaviour.
 */

/* ── tokens ───────────────────────────────────────────────────────────────── */

:root {
  /* Near-black rather than pure black: pure #000 makes the neon vibrate and
     shows every panel seam on a cheap tablet screen. */
  --bg:            #0a0b10;
  --bg-deep:       #06070b;
  --surface:       #14161f;
  --surface-2:     #1b1e2a;
  --surface-3:     #242838;
  --line:          rgba(255, 255, 255, 0.09);
  --line-strong:   rgba(255, 255, 255, 0.16);

  --text:          #f4f6fb;
  --text-dim:      #aab2c6;
  --text-faint:    #6f778c;

  /* The GameSpot orange is the brand and stays the primary accent. The cyan is
     a secondary used only for information, never for actions, so "orange means
     you can press it" holds everywhere. */
  --brand:         #ff5722;
  --brand-hot:     #ff7a45;
  --brand-deep:    #c8380f;
  --cyan:          #22d3ee;

  --green:         #22e06b;
  --red:           #ff3b52;
  --amber:         #ffb020;
  --violet:        #a78bfa;

  --glow-brand:    0 0 0 1px rgba(255, 87, 34, 0.45), 0 0 28px -6px rgba(255, 87, 34, 0.65);
  --glow-green:    0 0 0 1px rgba(34, 224, 107, 0.35), 0 0 22px -8px rgba(34, 224, 107, 0.55);

  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 30px;

  --s-1: 6px;
  --s-2: 10px;
  --s-3: 16px;
  --s-4: 24px;
  --s-5: 34px;
  --s-6: 48px;

  --tap: 56px;                       /* the floor for anything touchable */

  --ui:      'Poppins', 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --display: 'Poppins', 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --mono:    ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ── reset ────────────────────────────────────────────────────────────────── */

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

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body.kiosk-page {
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--ui);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;

  /* A kiosk is a fixed screen somebody prods with a finger. Text selection and
     the double-tap zoom are pure nuisance there. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

body.kiosk-page::before {
  /* One soft brand bloom behind everything, so the near-black has depth without
     costing a repaint on scroll. Fixed, non-interactive, never animated. */
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(60% 45% at 18% 0%,  rgba(255, 87, 34, 0.13), transparent 70%),
    radial-gradient(50% 40% at 92% 8%,  rgba(34, 211, 238, 0.08), transparent 70%),
    radial-gradient(80% 60% at 50% 100%, rgba(167, 139, 250, 0.06), transparent 70%);
}

/* ── AI monitor (staff-only page, used from the owner's MacBook) ─────────── */

.ai-monitor-shell {
  position: relative;
  z-index: 1;
  width: min(1120px, calc(100% - 48px));
  margin: 0 auto;
  padding: 42px 0 64px;
}

.ai-monitor-hero, .ai-event-panel, .ai-stats article {
  border: 1px solid var(--line);
  background: rgba(20, 22, 31, 0.9);
  box-shadow: 0 18px 45px rgba(0, 0, 0, 0.2);
}

.ai-monitor-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-5);
  border-radius: var(--r-lg);
}
.ai-monitor-hero h1 { margin: 0; font-size: clamp(1.7rem, 4vw, 2.6rem); }
.ai-monitor-hero p { max-width: 720px; margin: var(--s-2) 0 0; color: var(--text-dim); }
.ai-eyebrow { color: var(--cyan) !important; font-size: .75rem; font-weight: 700; letter-spacing: .12em; }

.ai-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-3); margin: var(--s-3) 0; }
.ai-stats article { min-height: 108px; padding: var(--s-3); border-radius: var(--r-md); }
.ai-stats span { display: block; color: var(--text-dim); font-size: .82rem; }
.ai-stats strong { display: block; margin-top: var(--s-1); font-size: 1.35rem; overflow-wrap: anywhere; }

.ai-event-panel { border-radius: var(--r-lg); overflow: hidden; }
.ai-panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: var(--s-4); border-bottom: 1px solid var(--line); }
.ai-panel-head h2 { margin: 0; font-size: 1.18rem; }
.ai-panel-head p { margin: 3px 0 0; color: var(--text-dim); font-size: .85rem; }
.ai-live { color: var(--green); font-size: .8rem; font-weight: 700; white-space: nowrap; }
.ai-live i { display: inline-block; width: 8px; height: 8px; margin-right: 5px; border-radius: 50%; background: currentColor; box-shadow: 0 0 12px currentColor; }
.ai-events { display: grid; }
.ai-event-row { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
.ai-event-row:last-child { border-bottom: 0; }
.ai-event-row > div { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
.ai-event-row p { margin: 4px 0; color: var(--text-dim); }
.ai-event-row small { color: var(--text-faint); }
.ai-severity { border-radius: 999px; padding: 2px 9px; background: rgba(34, 211, 238, .14); color: var(--cyan); font-size: .72rem; font-weight: 700; text-transform: uppercase; }
.ai-severity.warn { background: rgba(255, 176, 32, .14); color: var(--amber); }
.ai-severity.critical { background: rgba(255, 59, 82, .14); color: var(--red); }

/* Two live pictures side by side: the AI's annotated Kinect view and the plain
   CCTV. Each sits in a fixed-height black frame and is fitted inside it, so a
   4:3 Kinect picture and a 9:16 upright CCTV picture line up. */
.ai-monitor-page .ai-monitor-shell { width: min(1480px, calc(100% - 48px)); }

.ai-occupancy { display: grid; justify-items: end; gap: 4px; text-align: right; }
.ai-occupancy strong { font-family: var(--display); font-size: clamp(2.8rem, 6vw, 4rem); line-height: 1; color: var(--green); }
.ai-occupancy span { color: var(--text-dim); font-size: .88rem; }

.live-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); margin-top: var(--s-3); }

.live-card {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: rgba(20, 22, 31, 0.9);
  box-shadow: 0 18px 45px rgba(0, 0, 0, 0.2);
  min-width: 0;
}
.live-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); padding: 2px 4px; }
.live-card-head h2 { margin: 0; font-size: 1.15rem; }
.live-card-head p { margin: 2px 0 0; color: var(--text-dim); font-size: .84rem; }
.cctv-state.is-off { color: var(--amber); }
.cctv-state.is-off i { animation: none; }

.live-frame {
  position: relative;
  height: clamp(320px, 66vh, 860px);
  border-radius: var(--r-md);
  background: #000;
  overflow: hidden;
}
.live-frame img { width: 100%; height: 100%; object-fit: contain; }
.live-frame video { position: absolute; top: 50%; left: 50%; max-width: none; transform: translate(-50%, -50%); }
.live-frame:fullscreen { height: 100vh; border-radius: 0; }

.live-frame-note {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--s-3);
  color: var(--text-dim);
  font-weight: 600;
  text-align: center;
  pointer-events: none;
}

.live-frame-tools { position: absolute; right: 10px; bottom: 10px; display: flex; gap: 6px; }
.live-tool {
  min-height: 40px;
  padding: 0 14px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  background: rgba(10, 11, 16, 0.72);
  color: var(--text);
  font-size: .82rem;
  font-weight: 600;
  cursor: pointer;
  backdrop-filter: blur(8px);
}
.live-tool:hover { border-color: var(--brand); }

.live-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 0; padding: 0 4px; color: var(--text-faint); font-size: .8rem; }
.live-legend span { display: inline-flex; align-items: center; gap: 6px; }
.swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; border: 2px solid; }
.swatch.depth { border-color: rgb(60, 230, 80); }
.rec-dot { color: var(--red); }

@media (max-width: 900px) {
  .live-grid { grid-template-columns: 1fr; }
  .live-frame { height: clamp(260px, 58vh, 720px); }
}

@media (max-width: 680px) {
  .ai-monitor-page .ai-monitor-shell { width: min(100% - 28px, 1480px); }
  .ai-occupancy { justify-items: start; text-align: left; }
  .ai-monitor-shell { width: min(100% - 28px, 1120px); padding-top: 22px; }
  .ai-monitor-hero { align-items: flex-start; flex-direction: column; padding: var(--s-4); }
  .ai-stats { grid-template-columns: 1fr; }
  .ai-panel-head, .ai-event-row { padding-left: var(--s-3); padding-right: var(--s-3); }
}

img { max-width: 100%; display: block; }
button { font: inherit; color: inherit; }

:focus-visible {
  outline: 3px solid var(--brand);
  outline-offset: 3px;
}

/* The old sheets drew decorative layers the override sheet then hid. Neither is
   needed now the background is one gradient on the body, but the elements are
   still in the markup, so collapse them rather than leaving ghosts in the flow. */
.static-background,
.bg-orb,
.bg-grain,
.video-background,
.overlay { display: none; }

/* A component's own display rule (inline-flex, grid) otherwise beats the hidden
   attribute, and "hidden" controls quietly stay on screen. */
[hidden] { display: none !important; }

/* ── header ───────────────────────────────────────────────────────────────── */

.kiosk-header {
  position: relative;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  height: 84px;
  padding: 0 var(--s-5);
  background: linear-gradient(180deg, rgba(10, 11, 16, 0.96), rgba(10, 11, 16, 0.72));
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(14px);
}

.kiosk-header::after {
  /* The brand hairline. It is the one piece of chrome that says "this is a
     GameSpot machine" on every screen. */
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: linear-gradient(90deg, var(--brand), var(--brand-hot) 35%, transparent 75%);
}

.brand-lockup {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

.brand-lockup img {
  width: clamp(140px, 15vw, 190px);
  height: auto;
}

.header-buttons {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: none;
}

/* One button shape for the whole header, differing only in accent. */
.lang-button,
.games-button,
.admin-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease),
              transform 0.12s var(--ease), box-shadow 0.18s var(--ease);
}

.lang-button:hover,
.games-button:hover,
.admin-button:hover { background: var(--surface-3); border-color: var(--brand); }

.lang-button:active,
.games-button:active,
.admin-button:active { transform: translateY(1px) scale(0.985); }

.games-button {
  background: linear-gradient(135deg, var(--brand), var(--brand-deep));
  border-color: transparent;
  box-shadow: var(--glow-brand);
}
.games-button:hover { background: linear-gradient(135deg, var(--brand-hot), var(--brand)); }

.lang-button.lang-active { border-color: var(--cyan); color: var(--cyan); }

/* ── page shell ───────────────────────────────────────────────────────────── */

.main-container {
  position: relative;
  z-index: 10;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: var(--s-5) var(--s-5) var(--s-6);
}

/* ── toast ────────────────────────────────────────────────────────────────── */

.toast {
  position: fixed;
  left: 50%;
  bottom: var(--s-5);
  z-index: 300;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  max-width: min(560px, calc(100vw - 40px));
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  font-size: 1rem;
  font-weight: 600;
  box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.95);
  transform: translate(-50%, 20px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease);
}

.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ── modal ────────────────────────────────────────────────────────────────── */

.qr-modal {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: none;
  place-items: center;
  padding: var(--s-4);
  background: rgba(4, 5, 8, 0.82);
  backdrop-filter: blur(8px);
  /* payment.html opens these with style.display = 'flex'; centre either way. */
  align-items: center;
  justify-content: center;
}

.qr-modal.show,
.qr-modal.active { display: grid; }

.qr-container {
  width: min(520px, 100%);
  max-height: calc(100dvh - 60px);
  overflow-y: auto;
  padding: var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: 0 30px 80px -30px #000;
}

.qr-title {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.qr-subtitle { margin-top: 4px; color: var(--text-dim); font-size: 0.95rem; }

.qr-code-box {
  display: grid;
  place-items: center;
  min-height: 240px;
  margin: var(--s-4) 0;
  padding: var(--s-3);
  border-radius: var(--r-md);
  /* The QR itself must sit on white or scanners struggle. */
  background: #fff;
}

.qr-code-box img,
.qr-image { width: 100%; max-width: 240px; height: auto; }

.qr-loading, .qr-fallback { color: #333; font-size: 0.9rem; text-align: center; }

.qr-loading-spinner {
  width: 30px;
  height: 30px;
  margin: 0 auto 10px;
  border: 3px solid rgba(0, 0, 0, 0.15);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.qr-details {
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

/* The amount to pay: the one number the customer types into their UPI app. */
.qr-amount {
  margin-bottom: var(--s-2);
  font-family: var(--display);
  font-size: 2.2rem;
  font-weight: 700;
  line-height: 1.1;
  color: var(--brand-hot);
  font-variant-numeric: tabular-nums;
}

.qr-item {
  display: flex;
  justify-content: space-between;
  gap: var(--s-2);
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}
.qr-item:last-child { border-bottom: 0; }
.qr-item-title { font-weight: 600; }
.qr-item-sub { color: var(--text-faint); font-size: 0.85rem; }

.qr-grand {
  margin-top: var(--s-2);
  font-family: var(--display);
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--brand-hot);
  font-variant-numeric: tabular-nums;
}

.qr-meta { margin-top: 6px; color: var(--text-faint); font-size: 0.85rem; }

.qr-footer {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
}

.qr-close-btn {
  flex: 1;
  min-height: var(--tap);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-weight: 700;
  cursor: pointer;
  transition: background 0.18s var(--ease);
}
.qr-close-btn:hover { background: var(--surface-3); }

.qr-wait { color: var(--text-faint); font-size: 0.85rem; }

/* ── narrower screens ─────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .main-container { padding: var(--s-4) var(--s-3) var(--s-5); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ── page transitions ─────────────────────────────────────────────────────── */

/* transitions.js stamps these on <html>. They belong here rather than in a page,
   because every page shares the same navigation feel: a quick fade out, a
   quick fade in. Opacity only -- a transform on <body> would drag every fixed
   layer (the home film, the scrim) along with it. */

html.page-ready body { animation: pageIn 0.22s var(--ease) both; }
html.page-leaving body { opacity: 0; transition: opacity 0.14s ease-in; }

@keyframes pageIn { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  html.page-ready body { animation: none; }
}

/* One press response for everything a finger can press (transitions.js adds
   the classes). It sinks at once, is held long enough to be seen on a quick
   tap, and springs back on release. It replaces a "ripple" whose styles had
   gone: its span landed in flex buttons as a real box and shoved their
   content around on every tap. */
.is-pressed {
  transform: scale(0.95) !important;
  filter: brightness(1.12);
  transition: transform 80ms ease-out, filter 80ms ease-out !important;
}
.is-released {
  transition: transform 320ms cubic-bezier(0.34, 1.56, 0.64, 1), filter 320ms ease !important;
}
/* Big surfaces move less, or they look like they are falling over. */
body.kiosk-home .console-box.is-pressed,
.game-card.is-pressed,
.payment-method.is-pressed,
.duration-box.is-pressed { transform: scale(0.975) !important; }

/* ── small pieces ─────────────────────────────────────────────────────────── */

/* A neutral chip, used in the QR modal for device/players/duration/id. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--text-dim);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

.qr-items {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: var(--s-2) 0;
}

.qr-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* ══ duration.html ═════════════════════════════════════════════════════════ */

/* A secondary page header. Lighter than .kiosk-header because this screen is a
   step in a flow, not the front door — the title carries it, not the chrome. */
.header {
  position: relative;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(10, 11, 16, 0.96), rgba(10, 11, 16, 0.68));
  backdrop-filter: blur(14px);
}

.header::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: linear-gradient(90deg, var(--brand), var(--brand-hot) 35%, transparent 75%);
}

.logo-row { display: flex; align-items: center; gap: var(--s-3); min-width: 0; }
.logo-row img, .logo-container img { width: clamp(120px, 12vw, 165px); height: auto; }

.title-block { min-width: 0; }

.title-block h1, .header h1 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  line-height: 1.1;
}

.subtitle { margin: 2px 0 0; color: var(--text-dim); font-size: 0.92rem; }

.header-right { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }

/* The "which machine am I booking" chip. It must stay legible at a glance — a
   customer who loses track of which station they picked pays for the wrong one. */
.chip-console {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-2);
  white-space: nowrap;
}
.chip-console-label { color: var(--text-faint); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.12em; }
.chip-console-value { color: var(--brand-hot); font-weight: 700; }

/* Where the customer is in the three-step booking. */
.flow-steps {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 var(--s-2) 0 0;
  padding: 0;
  list-style: none;
}

.flow-steps li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text-faint);
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
}

.flow-steps li + li::before {
  content: '';
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--line-strong);
}

.flow-steps b {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  font-size: 0.8rem;
}

.flow-steps .is-done { color: var(--text-dim); }
.flow-steps .is-done b { border-color: rgba(34, 224, 107, 0.5); background: rgba(34, 224, 107, 0.12); color: var(--green); }
.flow-steps .is-current { color: var(--text); }
.flow-steps .is-current b { border-color: transparent; background: var(--brand); color: #fff; box-shadow: var(--glow-brand); }

@media (max-width: 1180px) {
  .flow-steps li:not(.is-current) span { display: none; }
}

/* ── the two-panel body ───────────────────────────────────────────────────── */

.content-shell {
  position: relative;
  z-index: 10;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 370px;
  gap: var(--s-5);
  align-items: start;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: var(--s-5);
}

.content-area { min-width: 0; display: grid; gap: var(--s-4); }

/* ── duration cards ───────────────────────────────────────────────────────── */

.duration-grid-wrap { min-width: 0; }

.duration-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--s-3);
}

.duration-box {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 132px;
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: linear-gradient(165deg, var(--surface-2), var(--surface));
  cursor: pointer;
  transition: transform 0.16s var(--ease), border-color 0.16s var(--ease),
              box-shadow 0.16s var(--ease), background 0.16s var(--ease);
}

.duration-box:hover { transform: translateY(-3px); border-color: rgba(255, 87, 34, 0.45); }
.duration-box:active { transform: translateY(-1px) scale(0.993); }

/* Selected is unmistakable: brand border, glow, and a filled tick. On a kiosk a
   customer must never wonder whether their tap registered. */
.duration-box.selected {
  border-color: var(--brand);
  background: linear-gradient(165deg, rgba(255, 87, 34, 0.16), var(--surface-2));
  box-shadow: var(--glow-brand);
}

.duration-box.selected::after {
  content: '✓';
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  font-size: 0.85rem;
  font-weight: 700;
}

.duration-box.faded { opacity: 0.38; pointer-events: none; filter: saturate(0.5); }

.duration-top { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

.duration-time {
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.01em;
}

.duration-price {
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--brand-hot);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.badge-best {
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--brand), var(--brand-deep));
  color: #fff;
  font-size: 0.64rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  white-space: nowrap;
}

.price-details { color: var(--text-faint); font-size: 0.85rem; }

/* ── players ──────────────────────────────────────────────────────────────── */

.controller-container { display: grid; gap: var(--s-2); }

.controller-options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.controller-option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 108px;
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.16s var(--ease), background 0.16s var(--ease),
              transform 0.12s var(--ease);
}

.controller-option:hover { border-color: var(--brand); }
.controller-option:active { transform: scale(0.985); }

.controller-option.selected {
  border-color: var(--brand);
  background: linear-gradient(135deg, rgba(255, 87, 34, 0.2), var(--surface-2));
  color: var(--text);
  box-shadow: var(--glow-brand);
}

/* ── the summary panel ────────────────────────────────────────────────────── */

.summary-container { position: sticky; top: var(--s-4); min-width: 0; }

.summary-card {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  box-shadow: 0 24px 60px -30px #000;
}

.summary-title {
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}
.summary-row:last-of-type { border-bottom: 0; }

.summary-label { color: var(--text-dim); font-size: 0.92rem; }
.summary-value { font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }

.summary-main-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
  padding-top: var(--s-2);
  border-top: 1px solid var(--line-strong);
}

.summary-row.total .summary-value,
.summary-main-line .summary-value {
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--brand-hot);
}

.summary-estimate { color: var(--text-faint); font-size: 0.82rem; }

/* Before anything is picked, say what to do instead of "0 devices, ₹0". */
.summary-empty {
  padding: var(--s-4) var(--s-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  color: var(--text-dim);
  font-size: 0.95rem;
  line-height: 1.5;
  text-align: center;
}
.summary-container.visible .summary-empty { display: none; }
.summary-container:not(.visible) .summary-main-line,
.summary-container:not(.visible) .booking-items,
.summary-container:not(.visible) .summary-row.total,
.summary-container:not(.visible) .summary-estimate { display: none; }

/* Each basket row carries its own Change / Edit / Remove, so a second Change
   under the panel only repeated one of them. */
.summary-buttons .summary-back-btn { display: none; }

.summary-buttons { display: grid; gap: var(--s-2); margin-top: var(--s-1); }

/* The primary action. Full width, tall, and the only orange fill on the panel. */
.summary-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 0;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--brand), var(--brand-deep));
  color: #fff;
  font-size: 1.02rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: var(--glow-brand);
  transition: transform 0.12s var(--ease), filter 0.16s var(--ease);
}
.summary-btn:hover { filter: brightness(1.08); }
.summary-btn:active { transform: translateY(1px) scale(0.992); }
.summary-btn:disabled {
  background: var(--surface-3);
  color: var(--text-faint);
  box-shadow: none;
  cursor: not-allowed;
}

.summary-back-btn,
.summary-add-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: var(--tap);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-weight: 600;
  cursor: pointer;
  transition: background 0.16s var(--ease), border-color 0.16s var(--ease);
}
.summary-back-btn:hover, .summary-add-btn:hover { background: var(--surface-3); border-color: var(--brand); }
.summary-add-btn {
  border: 1.5px dashed rgba(255, 87, 34, 0.7);
  background: rgba(255, 87, 34, 0.08);
  color: var(--brand-hot);
  font-size: 1.02rem;
}

/* ── multi-station basket ─────────────────────────────────────────────────── */

.booking-items { display: grid; gap: var(--s-2); }

.kiosk-duration .booking-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px var(--s-2);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.kiosk-duration .booking-item.is-current { border-color: rgba(255, 87, 34, 0.45); }
.kiosk-duration .booking-item > div:first-child { flex: 1; min-width: 0; }
.kiosk-duration .booking-item-actions { flex-basis: 100%; justify-content: flex-end; }
.kiosk-duration .booking-item-action { min-height: 36px; padding: 0 12px; font-size: 0.85rem; font-weight: 600; }

.booking-item-name { font-weight: 700; }
.booking-item-detail { color: var(--text-faint); font-size: 0.84rem; }
.booking-item-price {
  font-weight: 700;
  color: var(--brand-hot);
  font-variant-numeric: tabular-nums;
}

.booking-item-actions { display: flex; gap: 6px; margin-left: auto; }

.booking-item-action {
  display: inline-grid;
  place-items: center;
  min-width: 38px;
  min-height: 38px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface-3);
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.16s var(--ease), border-color 0.16s var(--ease);
}
.booking-item-action:hover { color: var(--text); border-color: var(--brand); }
.booking-item-action.danger:hover { color: var(--red); border-color: var(--red); }

.extend-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border: 1px solid var(--amber);
  border-radius: 999px;
  background: rgba(255, 176, 32, 0.12);
  color: var(--amber);
  font-size: 0.8rem;
  font-weight: 700;
}

/* ── back button ──────────────────────────────────────────────────────────── */

.back-button {
  position: fixed;
  left: var(--s-4);
  bottom: var(--s-4);
  z-index: 60;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: rgba(20, 22, 31, 0.9);
  color: var(--text);
  font-weight: 600;
  cursor: pointer;
  backdrop-filter: blur(10px);
  transition: background 0.16s var(--ease), border-color 0.16s var(--ease);
}
.back-button:hover { background: var(--surface-3); border-color: var(--brand); }

/* ── device picker ────────────────────────────────────────────────────────── */

.device-picker {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: none;
  place-items: center;
  padding: var(--s-4);
  background: rgba(4, 5, 8, 0.82);
  backdrop-filter: blur(8px);
}
.device-picker.visible, .device-picker.show { display: grid; }

.device-picker-card {
  width: min(520px, 100%);
  max-height: calc(100dvh - 60px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: 0 30px 80px -30px #000;
  overflow: hidden;
}

.device-picker-header {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-4);
  border-bottom: 1px solid var(--line);
}

.device-picker-heading {
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: 700;
}
.device-picker-copy { margin-top: 2px; color: var(--text-dim); font-size: 0.9rem; }

.device-picker-close {
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 1.1rem;
  cursor: pointer;
}
.device-picker-close:hover { color: var(--text); border-color: var(--red); }

.device-picker-list {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-4);
  overflow-y: auto;
}

.device-picker-option {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--tap);
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.16s var(--ease), background 0.16s var(--ease);
}
.device-picker-option:hover { border-color: var(--brand); background: var(--surface-3); }

.device-picker-option-name { font-weight: 700; }
.device-picker-option-meta { color: var(--text-faint); font-size: 0.84rem; }
.device-picker-option-arrow { margin-left: auto; color: var(--brand); font-size: 1.2rem; }

.device-picker-empty {
  padding: var(--s-5) var(--s-4);
  text-align: center;
  color: var(--text-faint);
}

/* ── duration page, narrower ──────────────────────────────────────────────── */

@media (max-width: 1050px) {
  .content-shell { grid-template-columns: 1fr; }
  /* The summary stops being a sidebar and becomes the last thing on the page,
     so it must not stay stuck to the top of a column that no longer exists. */
  .summary-container { position: static; }
}

@media (max-width: 560px) {
  /* On a phone the step title matters more than a second copy of the logo. */
  .header .logo-container { display: none; }
  .title-block h1, .header h1 { font-size: 1.45rem; }
  .subtitle { font-size: 0.85rem; }
}

@media (max-width: 900px) {
  .header { flex-wrap: wrap; gap: var(--s-2); padding: var(--s-3); }
  .header-right { margin-left: 0; width: 100%; }
  .content-shell { padding: var(--s-3); gap: var(--s-4); }
  .duration-options { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .duration-box { min-height: 112px; padding: var(--s-3); }
  .duration-price { font-size: 1.5rem; }
  .back-button { left: var(--s-3); right: var(--s-3); bottom: var(--s-3); justify-content: center; }
  /* Keep the fixed back button clear of the last card. */
  .content-shell { padding-bottom: calc(var(--tap) + var(--s-5)); }
}

/* The player buttons sit INSIDE each duration card — pick "1 hour, 2 players"
   in one gesture rather than two. So inside a card they are a compact row that
   shares the width, not the standalone stack they are elsewhere. */
.duration-box .controller-options {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 6px;
  margin-top: auto;
  padding-top: var(--s-2);
}

.duration-box .controller-option {
  min-width: 0;
  min-height: 48px;
  padding: 0 6px;
  border-radius: var(--r-sm);
  font-size: 0.92rem;
}

.duration-box { min-height: 188px; gap: var(--s-2); }

/* Wider cards, because each now carries a row of player buttons as well. */
.duration-options { grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); }

/* Time on top, the price large beneath it, the player row at the foot. */
.duration-top {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "time time badge" "price details details";
  align-items: baseline;
  gap: 2px var(--s-2);
}
.duration-time { grid-area: time; font-size: 1.15rem; color: var(--text-dim); }
.duration-price { grid-area: price; font-size: 2.2rem; }
.price-details { grid-area: details; }
.badge-best { grid-area: badge; align-self: center; }
.duration-box.selected .duration-time { color: var(--text); }
@media (min-width: 1051px) {
  .duration-box { min-height: clamp(188px, 30vh, 250px); padding: var(--s-4) var(--s-4) var(--s-3); }
  .duration-price { font-size: 2.5rem; }
}
.duration-box .controller-option { min-height: 52px; font-size: 1rem; font-weight: 700; }
.duration-box .controller-container { margin-top: auto; }

@media (max-width: 900px) {
  .duration-options { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
  .duration-box { min-height: 150px; }
}

/* ══ payment.html ══════════════════════════════════════════════════════════
 *
 * This screen handles money, so it is the one place where clarity beats style
 * every time. Two things must be readable across the room and impossible to
 * misread: how much is owed, and how much has been paid so far.
 */

/* One column, centred and narrow. Paying is a single-track task: the fewer
   places the eye can go, the less chance of paying for the wrong thing. The
   markup has a single .payment-column, so a sidebar track would only ever be an
   empty 400px of nothing. */
body.kiosk-payment .main-container {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s-5);
  align-items: start;
  max-width: 1180px;
  padding-top: var(--s-5);
}

.payment-summary { min-width: 0; display: grid; gap: var(--s-2); }
.payment-column { min-width: 0; display: grid; gap: var(--s-3); align-content: start; }

.payment-column h2 {
  margin: 0;
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.payment-section-title {
  padding-bottom: var(--s-2);
  color: var(--text-faint);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.payment-badges { display: flex; gap: 6px; }

/* The payment header also carries the badges, so the steps go compact sooner. */
@media (max-width: 1360px) {
  .kiosk-payment .flow-steps li:not(.is-current) span { display: none; }
}

body.kiosk-payment .booking-item-list { display: grid; gap: 0; }

body.kiosk-payment .booking-item {
  justify-content: space-between;
  padding: var(--s-3) 0;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  background: none;
}
body.kiosk-payment .booking-item-copy { font-size: 1.1rem; font-weight: 700; }
body.kiosk-payment .booking-item-meta { margin-top: 2px; font-size: 0.9rem; font-weight: 500; }
body.kiosk-payment .booking-item-price { font-size: 1.15rem; }

/* ── what you are paying for ──────────────────────────────────────────────── */

.payment-details {
  display: grid;
  gap: 2px;
  padding: var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
}

.detail-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.detail-row:last-child { border-bottom: 0; }

.detail-label { color: var(--text-dim); font-size: 0.94rem; }
.detail-value { font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }

/* The amount owed. Deliberately the largest thing on the page. */
.total-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-2);
  padding-top: var(--s-3);
  border-top: 2px solid var(--line-strong);
}

.total-row .detail-label { font-size: 1rem; font-weight: 600; color: var(--text); }

.total-row .detail-value {
  font-family: var(--display);
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--brand-hot);
}

.booking-items-row { display: grid; gap: var(--s-2); }
.booking-item-list { display: grid; gap: var(--s-2); }

.booking-item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.booking-item-copy { min-width: 0; }
.booking-item-meta { color: var(--text-faint); font-size: 0.84rem; }

/* ── choosing how to pay ──────────────────────────────────────────────────── */

.payment-methods {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--s-3);
}

.payment-method {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 170px;
  padding: var(--s-4) var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: linear-gradient(165deg, var(--surface-2), var(--surface));
  cursor: pointer;
  text-align: center;
  transition: transform 0.16s var(--ease), border-color 0.16s var(--ease),
              box-shadow 0.16s var(--ease);
}
.payment-method:hover { transform: translateY(-3px); border-color: rgba(255, 87, 34, 0.5); }
.payment-method:active { transform: translateY(-1px) scale(0.99); }

.payment-method.selected,
.payment-method.active {
  border-color: var(--brand);
  background: linear-gradient(165deg, rgba(255, 87, 34, 0.16), var(--surface-2));
  box-shadow: var(--glow-brand);
}

.payment-method-name { font-size: 1.15rem; font-weight: 700; }
.payment-method-hint { color: var(--text-faint); font-size: 0.82rem; }
.payment-method img, .payment-method svg { height: 40px; width: auto; }

/* ── cash ─────────────────────────────────────────────────────────────────── */

/* The customer is feeding notes into a slot and watching this. It has to answer
   "did that register, and how much more do I owe" without them reading a word. */

.cash-amounts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-3);
  margin-bottom: var(--s-3);
}

.cash-amount {
  display: grid;
  gap: 4px;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  text-align: center;
}

.cash-amount .detail-label,
.cash-inserted + .detail-label { justify-self: center; }

.cash-inserted,
.cash-remaining {
  font-family: var(--display);
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.cash-inserted { color: var(--green); }
.cash-remaining { color: var(--brand-hot); }

/* Progress toward the total. A bar is read faster than two numbers compared. */
.cash-progress {
  position: relative;
  height: 10px;
  margin: var(--s-2) 0 var(--s-3);
  border-radius: 999px;
  background: var(--surface-3);
  overflow: hidden;
}
.cash-progress > * {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--green), #6ef7a5);
  box-shadow: 0 0 16px rgba(34, 224, 107, 0.6);
  transition: width 0.4s var(--ease);
}

/* Each note as it lands. The flash is the receipt for a physical action. */
.cash-note {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  padding: 10px var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-variant-numeric: tabular-nums;
  animation: noteIn 0.45s var(--ease) both;
}

.cash-last-note {
  border-color: var(--green);
  background: rgba(34, 224, 107, 0.12);
  color: var(--green);
  font-weight: 700;
}

@keyframes noteIn {
  from { opacity: 0; transform: translateX(-10px); }
  to   { opacity: 1; transform: none; }
}

/* Status line, then paid / still owed side by side, then the progress bar. The
   markup lists them in a different order, so the grid places them. */
#cashModal .cash-amounts { grid-template-columns: 1fr 1fr; margin-top: var(--s-4); }
#cashModal .cash-note { grid-column: 1 / -1; order: 0; justify-content: center; }
#cashModal .cash-inserted { order: 1; }
#cashModal .cash-remaining { order: 2; }
#cashModal .cash-progress { grid-column: 1 / -1; order: 3; margin: 0; }
#cashModal .cash-last-note { grid-column: 1 / -1; order: 4; }
#cashModal .qr-container { width: min(580px, 100%); }
/* .cash-amount is a grid, which would put "Inserted: ₹" and the number on
   separate rows. */
#cashModal .cash-inserted,
#cashModal .cash-remaining { display: block; padding: var(--s-3); font-size: 1.4rem; white-space: nowrap; }

.cash-actions { display: flex; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-3); }

.cash-btn, .cash-ok-btn, .cash-cancel-btn {
  flex: 1 1 160px;
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-weight: 700;
  cursor: pointer;
  transition: background 0.16s var(--ease), border-color 0.16s var(--ease);
}
.cash-ok-btn {
  border-color: transparent;
  background: linear-gradient(135deg, var(--green), #12a04e);
  color: #04140a;
  box-shadow: var(--glow-green);
}
.cash-cancel-btn:hover { border-color: var(--red); color: var(--red); }
.cash-btn:hover { background: var(--surface-3); border-color: var(--brand); }

/* ── UPI ──────────────────────────────────────────────────────────────────── */

.qr-header { display: grid; gap: 2px; margin-bottom: var(--s-3); }
.qr-instructions { color: var(--text-dim); font-size: 0.94rem; }

/* ── buttons ──────────────────────────────────────────────────────────────── */

.nav-buttons { display: flex; gap: var(--s-3); flex-wrap: wrap; }
body.kiosk-payment #backBtn { flex: 0 1 160px; }
body.kiosk-payment #payBtn { flex: 1 1 220px; min-height: 64px; font-size: 1.15rem; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex: 1 1 180px;
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.16s var(--ease), border-color 0.16s var(--ease),
              transform 0.12s var(--ease), filter 0.16s var(--ease);
}
.btn:hover { background: var(--surface-3); border-color: var(--brand); }
.btn:active { transform: translateY(1px) scale(0.992); }

.btn-orange {
  border-color: transparent;
  background: linear-gradient(135deg, var(--brand), var(--brand-deep));
  color: #fff;
  box-shadow: var(--glow-brand);
}
.btn-orange:hover { filter: brightness(1.08); background: linear-gradient(135deg, var(--brand), var(--brand-deep)); }

.btn-gray { background: var(--surface-3); color: var(--text-dim); }

.btn-disabled,
.btn:disabled {
  background: var(--surface-3);
  color: var(--text-faint);
  border-color: var(--line);
  box-shadow: none;
  cursor: not-allowed;
  filter: none;
}

/* ── status, badges ───────────────────────────────────────────────────────── */

.status-message {
  padding: var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-weight: 600;
}
.status-message.info    { border-color: rgba(34, 211, 238, 0.45); color: var(--cyan); }
.status-message.success { border-color: rgba(34, 224, 107, 0.45); color: var(--green); }
.status-message.error   { border-color: rgba(255, 59, 82, 0.45); color: var(--red); }

.device-control-badge,
.test-mode-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.device-control-badge { background: rgba(34, 211, 238, 0.14); color: var(--cyan); border: 1px solid rgba(34, 211, 238, 0.45); }

/* Test mode means notes are read but NOT credited. It must be impossible to miss
   that money is not really being taken. */
.test-mode-badge {
  background: rgba(255, 176, 32, 0.16);
  color: var(--amber);
  border: 1px solid var(--amber);
}

.setup-buffer-note { padding: 0 var(--s-2); color: var(--text-faint); font-size: 0.86rem; }

/* Multiplayer mode: shown on the payment screen only when both driving sims
   are in the cart. A switch, not a payment choice — it costs nothing. */
.multiplayer-card {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.multiplayer-card:disabled { opacity: 0.55; cursor: default; }
.multiplayer-card .mp-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-dim);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.multiplayer-card .mp-icon svg { width: 24px; height: 24px; }
.multiplayer-card .mp-copy { display: grid; gap: 2px; min-width: 0; }
.multiplayer-card .mp-copy strong { font-size: 1rem; font-weight: 700; }
.multiplayer-card .mp-copy small { color: var(--text-dim); font-size: 0.84rem; }
.multiplayer-card .mp-switch {
  flex: none;
  margin-left: auto;
  width: 54px;
  height: 32px;
  padding: 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  transition: background 0.22s var(--ease);
}
.multiplayer-card .mp-switch i {
  display: block;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--text-dim);
  transition: transform 0.22s var(--ease), background 0.22s var(--ease);
}
.multiplayer-card.is-on { border-color: rgba(255, 87, 34, 0.5); background: rgba(255, 87, 34, 0.1); }
.multiplayer-card.is-on .mp-icon { background: rgba(255, 87, 34, 0.18); color: var(--brand-hot); }
.multiplayer-card.is-on .mp-switch { background: var(--brand); }
.multiplayer-card.is-on .mp-switch i { transform: translateX(22px); background: #fff; }

.loading-spinner, .waiting-spinner {
  width: 42px;
  height: 42px;
  border: 3px solid rgba(255, 255, 255, 0.14);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin 0.85s linear infinite;
}

.preloaded-image { display: none; }

/* ── waiting and success overlays ─────────────────────────────────────────── */

.waiting-overlay,
.success-overlay {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: none;
  place-items: center;
  padding: var(--s-4);
  background: rgba(4, 5, 8, 0.9);
  backdrop-filter: blur(10px);
}
.waiting-overlay.active, .waiting-overlay.show,
.success-overlay.active, .success-overlay.show { display: grid; }

.waiting-container,
.success-container {
  display: grid;
  justify-items: center;
  gap: var(--s-3);
  width: min(520px, 100%);
  max-height: calc(100dvh - 60px);
  overflow-y: auto;
  padding: var(--s-6) var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: var(--surface);
  text-align: center;
  box-shadow: 0 30px 80px -30px #000;
}

.waiting-title,
.success-title {
  font-family: var(--display);
  font-size: 1.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.01em;
}

.waiting-message,
.success-message { color: var(--text-dim); }

.waiting-status { color: var(--text-faint); font-size: 0.88rem; font-variant-numeric: tabular-nums; }

.waiting-cancel {
  min-height: var(--tap);
  margin-top: var(--s-2);
  padding: 0 var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-weight: 700;
  cursor: pointer;
}
.waiting-cancel:hover { border-color: var(--red); color: var(--red); }

.success-check {
  display: grid;
  place-items: center;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--green), #12a04e);
  color: #04140a;
  font-size: 2.6rem;
  font-weight: 700;
  box-shadow: var(--glow-green);
  animation: popIn 0.45s var(--ease) both;
}

@keyframes popIn {
  0%   { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); }
}

.success-details,
.success-session-list {
  display: grid;
  gap: 2px;
  width: 100%;
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  text-align: left;
}

.success-detail-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}
.success-detail-row:last-child { border-bottom: 0; }
.success-detail-label { color: var(--text-dim); font-size: 0.9rem; }
.success-detail-value { font-weight: 700; font-variant-numeric: tabular-nums; }

.success-redirect { color: var(--text-faint); font-size: 0.85rem; }

/* ── payment, narrower ────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  body.kiosk-payment .main-container { grid-template-columns: 1fr; gap: var(--s-4); padding-top: var(--s-4); }
  .flow-steps { display: none; }
  .total-row .detail-value { font-size: 2rem; }
  .cash-inserted, .cash-remaining { font-size: 1.6rem; }
  .payment-methods { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
  .payment-method { min-height: 108px; }
  .btn { flex: 1 1 100%; }
  body.kiosk-payment #backBtn { flex: 1 1 100%; order: 2; }
}

/* Status about things the customer cannot change sits in the header, beside
   the steps. Test mode especially must stay visible: notes are read, NOT
   credited. */
.device-control-badge { background: var(--surface-2); color: var(--text-dim); border: 1px solid var(--line-strong); }
.device-control-badge.is-ready { background: rgba(34, 224, 107, 0.12); color: var(--green); border-color: rgba(34, 224, 107, 0.45); }
.device-control-badge.is-offline { background: rgba(255, 59, 82, 0.14); color: var(--red); border-color: rgba(255, 59, 82, 0.5); }

/* ── staff page header bar (admin.html, bv30-test.html, ai-monitor.html) ──── */

/* .back-button is a fixed corner control on duration.html but an ordinary
   button inside a bar on the staff pages. */
.header-bar .back-button,
.button-group .back-button { position: static; backdrop-filter: none; }

.header-bar {
  position: relative;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(10, 11, 16, 0.96), rgba(10, 11, 16, 0.68));
  backdrop-filter: blur(14px);
}

.header-bar::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: linear-gradient(90deg, var(--brand), var(--brand-hot) 35%, transparent 75%);
}

.page-title {
  font-family: var(--display);
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.01em;
}

.button-group { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

/* ══ games.html — what is installed on each station ════════════════════════
 *
 * The page was a hand-written list of every game on every console, with an
 * "edit mode" behind a passcode in the page source that only hid cards until
 * the next reload. The list now lives on the server, staff sign in with the
 * real staff PIN, and this is what shows it.
 */

body.kiosk-games { display: flex; flex-direction: column; min-height: 100dvh; }
body.kiosk-games.sheet-open { overflow: hidden; }

.games-header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: linear-gradient(180deg, rgba(10, 11, 16, 0.97), rgba(10, 11, 16, 0.85));
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(12px);
}

.games-heading { flex: 1; min-width: 0; text-align: center; }
.games-heading h1 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.3rem, 2.4vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.02em;
}
.games-sub { margin: 2px 0 0; color: var(--text-faint); font-size: 0.85rem; }

.ghost-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 46px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-dim);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.ghost-btn svg { width: 18px; height: 18px; }
@media (hover: hover) { .ghost-btn:hover { background: rgba(255, 255, 255, 0.1); color: var(--text); } }
body.is-managing #manageBtn { background: rgba(255, 87, 34, 0.16); color: var(--brand-hot); }

.manage-banner .btn { flex: none; min-width: 120px; min-height: 44px; }
.manage-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-4);
  background: rgba(255, 87, 34, 0.12);
  color: var(--brand-hot);
  font-size: 0.9rem;
  font-weight: 600;
}

.games-shell {
  position: relative;
  z-index: 1;
  width: min(1280px, 100%);
  margin: 0 auto;
  padding: var(--s-4);
  display: grid;
  gap: var(--s-3);
  align-content: start;
}

/* ── station filter ── */

.station-chips {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  padding-bottom: 4px;
  scrollbar-width: none;
}
.station-chips::-webkit-scrollbar { display: none; }

.station-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 46px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-dim);
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease), color 0.2s var(--ease);
}
.station-chip b {
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
}
.station-chip.is-active {
  border-color: rgba(255, 87, 34, 0.55);
  background: rgba(255, 87, 34, 0.14);
  color: var(--text);
}
.station-chip.is-active b { background: rgba(255, 87, 34, 0.25); }

.station-lead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}
.station-lead .btn { flex: none; min-width: 200px; }
.station-lead-copy { display: grid; gap: 2px; }
.station-lead-copy strong { font-family: var(--display); font-size: 1.2rem; font-weight: 700; }
.station-lead-copy span { color: var(--text-dim); font-size: 0.88rem; }

/* ── the grid of games ── */

.games-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: var(--s-3);
}

.game-card {
  display: flex;
  flex-direction: column;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  text-align: left;
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), box-shadow 0.25s var(--ease);
}
@media (hover: hover) {
  .game-card:hover { border-color: rgba(255, 87, 34, 0.45); box-shadow: 0 16px 34px -22px rgba(0, 0, 0, 0.9); }
}

.game-cover {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 4;
  background: linear-gradient(160deg, var(--surface-3), var(--surface-2));
  background-size: cover;
  background-position: center;
}
.game-cover-fallback {
  font-family: var(--display);
  font-size: 2.6rem;
  font-weight: 700;
  color: var(--text-faint);
}
.game-edit-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255, 87, 34, 0.92);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
}

.game-card-body { display: grid; gap: 6px; padding: var(--s-3); }
.game-title {
  font-family: var(--display);
  font-size: 0.98rem;
  font-weight: 600;
  line-height: 1.2;
  overflow-wrap: anywhere;
}
.game-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.game-tag {
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(34, 211, 238, 0.12);
  color: var(--cyan);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.game-players { color: var(--text-dim); font-size: 0.78rem; font-weight: 600; }
.game-where { color: var(--text-faint); font-size: 0.74rem; line-height: 1.35; }

.game-add {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 8px;
  min-height: 220px;
  border-style: dashed;
  border-color: var(--line-strong);
  background: transparent;
  color: var(--text-dim);
  font-weight: 600;
}
.game-add-plus {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: rgba(255, 87, 34, 0.16);
  color: var(--brand-hot);
  font-size: 1.8rem;
  line-height: 1;
}

.games-empty { margin: var(--s-5) 0; color: var(--text-faint); text-align: center; }

/* ── sheets: one game, the editor, the PIN ── */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: end center;
  padding: var(--s-3);
  background: rgba(4, 5, 8, 0.72);
  backdrop-filter: blur(6px);
  animation: sheetIn 0.18s var(--ease);
}
@keyframes sheetIn { from { opacity: 0; } }

.sheet-panel {
  position: relative;
  width: min(760px, 100%);
  max-height: min(88dvh, 860px);
  overflow-y: auto;
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg);
  box-shadow: 0 -20px 60px -20px rgba(0, 0, 0, 0.9);
  animation: sheetUp 0.24s var(--ease);
}
.sheet-panel.sheet-narrow { width: min(380px, 100%); }
@keyframes sheetUp { from { transform: translateY(24px); } }
@media (min-width: 760px) { .sheet { place-items: center; } }

.sheet-panel h2 { margin: 0 0 var(--s-3); font-family: var(--display); font-size: 1.4rem; font-weight: 700; }

.sheet-close {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-dim);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}

.detail-body { display: grid; grid-template-columns: 200px 1fr; gap: var(--s-4); }
.detail-cover {
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 4;
  border-radius: var(--r-md);
  background: linear-gradient(160deg, var(--surface-3), var(--surface-2));
  background-size: cover;
  background-position: center;
  font-family: var(--display);
  font-size: 3rem;
  font-weight: 700;
  color: var(--text-faint);
}
.detail-copy { display: grid; gap: var(--s-2); align-content: start; min-width: 0; }
.detail-copy h2 { margin: 0; }
.detail-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; color: var(--text-dim); font-size: 0.86rem; }
.detail-text { margin: 0; color: var(--text-dim); line-height: 1.5; }
.detail-stations-label {
  margin-top: var(--s-2);
  color: var(--text-faint);
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.detail-stations { display: grid; gap: 8px; }
.detail-station {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  min-height: 56px;
  padding: 0 var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-weight: 600;
}
.detail-station .btn { flex: none; min-width: 120px; }
.detail-station em { color: var(--text-faint); font-style: normal; font-size: 0.86rem; }
.btn-small { min-height: 44px; padding: 0 18px; font-size: 0.9rem; }
.btn-danger { background: rgba(255, 59, 82, 0.14); border-color: rgba(255, 59, 82, 0.4); color: var(--red); }

/* ── the editor ── */

.edit-grid { display: grid; grid-template-columns: 180px 1fr; gap: var(--s-4); }
.edit-cover { display: grid; gap: var(--s-2); align-content: start; }
.edit-cover-preview {
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 4;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  background-size: cover;
  background-position: center;
  font-family: var(--display);
  font-size: 2.4rem;
  font-weight: 700;
  color: var(--text-faint);
}
.edit-photo-btn { justify-content: center; cursor: pointer; }
.edit-hint { margin: 0; color: var(--text-faint); font-size: 0.76rem; line-height: 1.4; }

.edit-fields { display: grid; gap: var(--s-3); align-content: start; }
.field { display: grid; gap: 6px; }
.field > span {
  color: var(--text-faint);
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}
.field input[type="text"],
.field textarea {
  width: 100%;
  min-height: 52px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 1rem;
}
.field textarea { min-height: 72px; resize: vertical; line-height: 1.45; }
.field input:focus, .field textarea:focus { outline: none; border-color: var(--brand); }

.quick-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.quick-chip {
  min-height: 42px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-dim);
  font-size: 0.86rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease), color 0.15s var(--ease);
}
.quick-chip.is-on {
  border-color: rgba(255, 87, 34, 0.55);
  background: rgba(255, 87, 34, 0.16);
  color: var(--text);
}

.edit-error { margin: var(--s-3) 0 0; color: var(--red); font-size: 0.9rem; font-weight: 600; }
.edit-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-top: var(--s-4);
}
.edit-actions-right { display: flex; gap: var(--s-2); margin-left: auto; }

/* ── staff PIN ── */

.pin-sub { margin: -8px 0 var(--s-3); color: var(--text-dim); font-size: 0.9rem; }
.pin-dots { display: flex; justify-content: center; gap: 12px; margin-bottom: var(--s-3); }
.pin-dots i {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  transition: background 0.15s var(--ease), transform 0.15s var(--ease);
}
.pin-dots i.is-filled { background: var(--brand); transform: scale(1.15); }
.pin-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-2); }
.pin-key {
  min-height: var(--tap);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
  font-family: var(--mono);
  font-size: 1.3rem;
  font-weight: 600;
  cursor: pointer;
}
.pin-key-go { background: var(--brand); border-color: var(--brand); color: #fff; font-family: var(--ui); font-size: 1rem; }

/* ── narrower screens ── */

@media (max-width: 720px) {
  .games-header { padding: var(--s-2) var(--s-3); }
  .games-heading { text-align: left; }
  .games-sub { display: none; }
  .ghost-btn span { display: none; }
  .ghost-btn { padding: 0 14px; }
  .games-shell { padding: var(--s-3); }
  .games-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--s-2); }
  .detail-body { grid-template-columns: 1fr; }
  .detail-cover { width: 160px; }
  .edit-grid { grid-template-columns: 1fr; }
  .edit-cover-preview { width: 150px; }
}

/* ══ door.html — the phone app ═════════════════════════════════════════════
 *
 * One job: lock and unlock. Big targets for a thumb, readable at arm's length
 * in a doorway, and honest when it does not know — an unknown state never
 * renders as "Locked".
 */

body.door-app {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
  background:
    radial-gradient(70% 50% at 50% 0%, rgba(255, 87, 34, 0.14), transparent 70%),
    var(--bg);
}

.door-screen {
  display: grid;
  gap: var(--s-4);
  justify-items: center;
  width: min(420px, 100%);
  text-align: center;
}
.door-screen h1 { margin: 0; font-family: var(--display); font-size: 2rem; font-weight: 700; }

.door-brand img { width: 150px; }
.door-brand.small img { width: 104px; }

.door-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  width: 100%;
}
.door-who { color: var(--text-faint); font-size: 0.82rem; font-weight: 600; }

.door-state { display: grid; gap: 6px; justify-items: center; }
.door-state strong { font-family: var(--display); font-size: 1.5rem; font-weight: 700; }

.door-ring {
  display: grid;
  place-items: center;
  width: 128px;
  height: 128px;
  margin-bottom: var(--s-2);
  border: 3px solid var(--line-strong);
  border-radius: 50%;
  font-size: 3rem;
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.door-ring.is-locked   { border-color: rgba(34, 224, 107, 0.55); box-shadow: var(--glow-green); }
.door-ring.is-unlocked { border-color: rgba(255, 87, 34, 0.7);  box-shadow: var(--glow-brand); }
.door-ring.is-unknown  { border-color: var(--line-strong); color: var(--text-faint); }

.door-note { margin: 0; color: var(--text-dim); font-size: 0.9rem; line-height: 1.5; }
.door-note.is-good { color: var(--green); font-weight: 600; }
.door-note.is-bad  { color: var(--red); font-weight: 600; }

.door-actions { display: grid; gap: var(--s-2); width: 100%; }

.door-btn {
  display: grid;
  gap: 2px;
  min-height: 74px;
  padding: 12px 18px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.door-btn b { font-family: var(--display); font-size: 1.15rem; font-weight: 700; }
.door-btn span { color: var(--text-dim); font-size: 0.84rem; }
.door-btn:disabled { opacity: 0.45; cursor: default; }
.door-btn.unlock { border-color: rgba(255, 87, 34, 0.45); }
.door-btn.lock   { border-color: rgba(34, 224, 107, 0.4); }
/* Tapped once, waiting for the second tap that actually opens the door. */
.door-btn.is-armed {
  border-color: var(--brand);
  background: rgba(255, 87, 34, 0.16);
  box-shadow: var(--glow-brand);
}

/* ══ staff tools ═══════════════════════════════════════════════════════════
 *
 * admin.html, bv30-test.html, door-control.html, manual-billing.html.
 *
 * These are working instruments, not shopfront. Density beats drama: staff read
 * them across a counter while a customer waits, often to answer one question
 * fast. Same tokens as the customer pages so it is recognisably one system, but
 * tighter spacing, more tabular numbers, and far less glow.
 */

/* ── layout ───────────────────────────────────────────────────────────────── */

.shell {
  position: relative;
  z-index: 10;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: var(--s-4) var(--s-4) var(--s-6);
}

.card {
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

.grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--s-3); }
.span-5  { grid-column: span 5; }
.span-6  { grid-column: span 6; }
.span-7  { grid-column: span 7; }
.span-12 { grid-column: span 12; }

.row { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.header-left, .title-left { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
.divider { height: 1px; margin: var(--s-3) 0; background: var(--line); border: 0; }

.footer-bar {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
  padding-top: var(--s-3);
  margin-top: var(--s-3);
  border-top: 1px solid var(--line);
}

.utility { display: flex; gap: var(--s-2); flex-wrap: wrap; }

/* ── text ─────────────────────────────────────────────────────────────────── */

.muted, .hint, .desc, .note { color: var(--text-dim); }
.hint, .note, .small { font-size: 0.84rem; }
.small { font-size: 0.84rem; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.empty { padding: var(--s-5); color: var(--text-faint); text-align: center; }

.ok   { color: var(--green); }
.warn { color: var(--amber); }
.alt  { color: var(--cyan); }
.fast { color: var(--brand-hot); }

.label {
  display: block;
  margin-bottom: 5px;
  color: var(--text-faint);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.kv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--s-2); }

.kv {
  display: grid;
  gap: 2px;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
.kv > :first-child { color: var(--text-faint); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.09em; }
.kv > :last-child { font-weight: 700; font-variant-numeric: tabular-nums; }

/* A single big reading — the note total, the session count. */
.result-big {
  font-family: var(--display);
  font-size: 2.2rem;
  font-weight: 700;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.result-meta { color: var(--text-faint); font-size: 0.84rem; }

/* ── buttons ──────────────────────────────────────────────────────────────── */

.btn-row { display: flex; gap: var(--s-2); flex-wrap: wrap; }

.btn-primary, .btn-danger, .btn-ghost, .small-btn, .link-btn,
.primary, .secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 46px;
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.94rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease),
              color 0.15s var(--ease);
}
.btn-primary:hover, .btn-ghost:hover, .small-btn:hover,
.primary:hover, .secondary:hover { background: var(--surface-3); border-color: var(--brand); }

.btn-primary, .primary {
  border-color: transparent;
  background: linear-gradient(135deg, var(--brand), var(--brand-deep));
  color: #fff;
}
.btn-primary:hover, .primary:hover { filter: brightness(1.08); background: linear-gradient(135deg, var(--brand), var(--brand-deep)); }

/* Destructive actions are outlined until hovered, so the fill only appears once
   the pointer is committed to it. */
.btn-danger, .danger {
  border-color: rgba(255, 59, 82, 0.55);
  background: rgba(255, 59, 82, 0.1);
  color: var(--red);
}
.btn-danger:hover, .danger:hover { background: var(--red); color: #fff; border-color: var(--red); }

.btn-ghost { background: transparent; }
.small-btn { min-height: 38px; padding: 0 var(--s-2); font-size: 0.86rem; }

.link-btn {
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-hot);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.link-btn:hover { color: var(--brand); background: none; }

.btn-primary:disabled, .btn-danger:disabled, .primary:disabled, .small-btn:disabled {
  background: var(--surface-3);
  color: var(--text-faint);
  border-color: var(--line);
  cursor: not-allowed;
  filter: none;
}

.icon { display: inline-grid; place-items: center; flex: none; }

/* ── inputs ───────────────────────────────────────────────────────────────── */

.field { display: grid; gap: 4px; min-width: 0; }

.input,
input[type='text'], input[type='number'], input[type='password'],
input[type='search'], input[type='tel'], select, textarea {
  width: 100%;
  min-height: 46px;
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--bg-deep);
  color: var(--text);
  font: inherit;
  transition: border-color 0.15s var(--ease);
}
textarea { min-height: 100px; padding: var(--s-2) var(--s-3); resize: vertical; }

.input:focus,
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(255, 87, 34, 0.18);
}

input::placeholder, textarea::placeholder { color: var(--text-faint); }

/* ── switches ─────────────────────────────────────────────────────────────── */

.switch-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--line);
}
.switch-row:last-child { border-bottom: 0; }

.switch-label { font-weight: 600; }
.switch-hint { color: var(--text-faint); font-size: 0.82rem; }

.switch {
  position: relative;
  flex: none;
  width: 54px;
  height: 30px;
  margin-left: auto;
  border-radius: 999px;
  background: var(--surface-3);
  border: 1px solid var(--line-strong);
  cursor: pointer;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease);
}
.switch .slider,
.switch::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--text-dim);
  transition: transform 0.18s var(--ease), background 0.18s var(--ease);
}
.switch.on, .switch.active, .switch[aria-checked='true'] {
  background: rgba(34, 224, 107, 0.25);
  border-color: var(--green);
}
.switch.on::after, .switch.active::after, .switch[aria-checked='true']::after {
  transform: translateX(24px);
  background: var(--green);
}

/* ── segmented control ────────────────────────────────────────────────────── */

.segmented {
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-2);
}
.segmented > * {
  min-height: 38px;
  padding: 0 var(--s-3);
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--text-dim);
  font-weight: 600;
  cursor: pointer;
}
.segmented > .active, .segmented > [aria-selected='true'] {
  background: var(--brand);
  color: #fff;
}

/* ── tabs ─────────────────────────────────────────────────────────────────── */

.payment-tabs {
  display: flex;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}

.payment-tab {
  min-height: 46px;
  padding: 0 var(--s-3);
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--text-dim);
  font-weight: 600;
  cursor: pointer;
}
.payment-tab.active { color: var(--brand-hot); border-bottom-color: var(--brand); }

.tab-content { display: none; }
.tab-content.active { display: block; }

/* ── tables ───────────────────────────────────────────────────────────────── */

.device-table, .cal-table, .log-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.device-table th, .cal-table th, .log-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 10px var(--s-2);
  background: var(--surface-2);
  border-bottom: 1px solid var(--line-strong);
  color: var(--text-faint);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  text-align: left;
  white-space: nowrap;
}

.device-table td, .cal-table td, .log-table td {
  padding: 10px var(--s-2);
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

.device-table tbody tr:hover,
.log-table tbody tr:hover { background: rgba(255, 255, 255, 0.03); }

/* Times and money line up for scanning down a column. */
.timer-cell, .cal-table td:last-child, .log-table td:first-child {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* A long log must scroll inside its own box, never stretch the page. */
.log-scroller {
  max-height: 340px;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-deep);
}

/* ── status ───────────────────────────────────────────────────────────────── */

.conn-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 0.86rem;
  font-weight: 600;
  white-space: nowrap;
}
.conn-status-icon, .dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.conn-ok   { color: var(--green); border-color: rgba(34, 224, 107, 0.45); }
.conn-err  { color: var(--red);   border-color: rgba(255, 59, 82, 0.45); }
.conn-wait { color: var(--amber); border-color: rgba(255, 176, 32, 0.45); }

.state-badge, .mini-badge, .tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--text-dim);
  font-size: 0.74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}
.state-badge.ok,   .mini-badge.ok   { color: var(--green); border-color: rgba(34, 224, 107, 0.45); }
.state-badge.warn, .mini-badge.warn { color: var(--amber); border-color: rgba(255, 176, 32, 0.45); }
.state-badge.danger, .mini-badge.danger { color: var(--red); border-color: rgba(255, 59, 82, 0.45); }

/* A live indicator that actually pulses, so a stalled feed is obvious. */
.live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--green);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.live::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  animation: livePulse 1.6s ease-in-out infinite;
}
@keyframes livePulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

.save-status { color: var(--text-faint); font-size: 0.82rem; }

.cal-banner {
  padding: var(--s-3);
  border: 1px solid var(--amber);
  border-radius: var(--r-sm);
  background: rgba(255, 176, 32, 0.1);
  color: var(--amber);
  font-weight: 600;
}

/* ── keypad ───────────────────────────────────────────────────────────────── */

.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-2); }

.key {
  display: grid;
  place-items: center;
  min-height: 58px;
  user-select: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text);
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.12s var(--ease), transform 0.1s var(--ease);
}
.key:hover { background: var(--surface-3); }
.key:active { transform: scale(0.95); background: var(--brand); color: #fff; }

/* ── cart / totals ────────────────────────────────────────────────────────── */

.cart { display: grid; gap: var(--s-2); }
.cart-title { font-weight: 700; }

.cart-row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
.cart-sub { color: var(--text-faint); font-size: 0.82rem; }
.cart-amt { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }

.totals { display: grid; gap: 4px; padding-top: var(--s-2); border-top: 1px solid var(--line-strong); }

.total-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
  font-variant-numeric: tabular-nums;
}
.total-line:last-child {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--brand-hot);
}

/* ── modal ────────────────────────────────────────────────────────────────── */

/* Shown by DEFAULT, which inverts the usual convention and is deliberate:
   admin.html's markup hides its modals with an inline style:"display:none" and
   leaves #loginModal without one, because the PIN prompt is meant to be up when
   the page loads. Its JS only ever sets display:none, after a successful login.
   A default of none here means the prompt never appears and the panel is
   reachable unsigned — which is what happened. Do not "fix" this to none. */
.modal {
  position: fixed;
  inset: 0;
  z-index: 420;
  display: grid;
  place-items: center;
  padding: var(--s-4);
  background: rgba(4, 5, 8, 0.84);
  backdrop-filter: blur(8px);
}
.modal.show, .modal.active, .modal.visible { display: grid; }

.modal-content {
  width: min(620px, 100%);
  max-height: calc(100dvh - 60px);
  overflow-y: auto;
  padding: var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: 0 30px 80px -30px #000;
}

/* ── admin page specifics ─────────────────────────────────────────────────── */

.admin-button-bar {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}

/* admin.html uses .admin-button for its action bar as well as the kiosk header.
   Inside the bar it is a plain control, not a pill. */
.admin-button-bar .admin-button {
  min-height: 46px;
  padding: 0 var(--s-3);
  border-radius: var(--r-sm);
  font-size: 0.92rem;
}

.admin-data { display: grid; gap: var(--s-3); }

/* ── staff pages, narrower ────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .shell { padding: var(--s-3) var(--s-3) var(--s-6); }
  .span-5, .span-6, .span-7 { grid-column: span 12; }
  .grid { gap: var(--s-2); }
  /* Tables keep their shape and scroll sideways rather than crushing columns. */
  .device-table, .cal-table, .log-table { min-width: 560px; }
  .log-scroller, .table-wrap { overflow-x: auto; }
  .btn-row > * { flex: 1 1 auto; }
}

/* ── door-control.html ────────────────────────────────────────────────────── */

/* One screen, one decision. It is deliberately roomy: whoever opens this is
   usually standing at the door with somebody waiting outside. */
body.kiosk-door-control .shell { max-width: 620px; padding-top: var(--s-6); }

body.kiosk-door-control .card { padding: var(--s-5); border-color: var(--line-strong); }

body.kiosk-door-control .top {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}

body.kiosk-door-control .title {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.01em;
}
body.kiosk-door-control .subtitle { color: var(--text-dim); font-size: 0.92rem; }

/* The connection chip. Not the door state — whether we can talk to the
   controller at all, which is the first thing to know when it will not move. */
body.kiosk-door-control .chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  margin-left: auto;
  min-height: 38px;
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}
body.kiosk-door-control .chip .dot { background: var(--text-faint); }
body.kiosk-door-control .chip .dot.ok  { background: var(--green); box-shadow: 0 0 10px var(--green); }
body.kiosk-door-control .chip .dot.err { background: var(--red); }

/* This page's .grid holds one big control, not a 12-column layout. */
body.kiosk-door-control .grid { display: grid; grid-template-columns: 1fr; gap: var(--s-3); }

/* The toggle. Large enough to hit without looking, and it carries its own
   explanation so nobody has to remember which way it goes. */
body.kiosk-door-control .action {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  width: 100%;
  min-height: 108px;
  padding: var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: transform 0.14s var(--ease), border-color 0.16s var(--ease),
              box-shadow 0.16s var(--ease);
}
body.kiosk-door-control .action:hover { border-color: var(--brand); transform: translateY(-2px); }
body.kiosk-door-control .action:active { transform: translateY(0) scale(0.995); }
body.kiosk-door-control .action:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
  border-color: var(--line);
}

body.kiosk-door-control .action.primary {
  background: linear-gradient(135deg, rgba(255, 87, 34, 0.18), var(--surface-2));
  border-color: rgba(255, 87, 34, 0.5);
}
body.kiosk-door-control .action.primary:disabled { background: var(--surface-2); }

body.kiosk-door-control .action .icon { font-size: 2.4rem; line-height: 1; }

/* .label is a tiny uppercase caption elsewhere; inside this button it is the
   verb, so it must not inherit that. */
body.kiosk-door-control .action .label {
  margin: 0;
  font-family: var(--display);
  font-size: 1.4rem;
  font-weight: 700;
  text-transform: none;
  letter-spacing: -0.01em;
  color: var(--text);
}
body.kiosk-door-control .action .desc { color: var(--text-dim); font-size: 0.9rem; }

body.kiosk-door-control .utility { margin-top: var(--s-3); }
body.kiosk-door-control .btn { width: 100%; }

body.kiosk-door-control .status {
  margin-top: var(--s-3);
  padding: var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-deep);
  font-weight: 600;
}

body.kiosk-door-control .muted { margin-top: var(--s-3); font-size: 0.86rem; }
body.kiosk-door-control .link-btn { display: inline-block; margin-top: var(--s-3); }

/* ══ index.html — the station picker ════════════════════════════════════════
 *
 * Deliberately minimal: a title, the voice button, and one big tile per
 * station. The whole tile is the button. Motion carries the life of the page —
 * tiles rise in, free consoles float, the play ring turns, and a light follows
 * the finger — so the chrome itself can stay quiet.
 */

body.kiosk-home {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  overflow-x: hidden;
}

/* The café film behind the tiles, in four fixed layers (see bg-video.js):
 *   .static-background  a still of the film: shows until the film is really
 *                       playing, and stays if the browser refuses to play it
 *   .video-background   home-bg.mp4, 720p and already graded dark in the file,
 *                       so the tablet decodes it without any CSS filter
 *   .overlay            the scrim: dark behind the header and at the floor,
 *                       a vignette, and a fine grain so it reads as film
 *   .bg-orb             a slow drift of brand colour over the top
 * The tiles are solid, so none of this shows through them or changes them;
 * it lives in the gaps, the margins and behind the title. */
body.kiosk-home .static-background,
body.kiosk-home .video-background,
body.kiosk-home .overlay {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

body.kiosk-home .static-background {
  background: var(--bg-deep) url('home-bg.jpg') center / cover no-repeat;
}

body.kiosk-home .video-background {
  object-fit: cover;
  opacity: 0;
  transition: opacity 1.4s var(--ease);
}
body.kiosk-home.bg-video-on .video-background { opacity: 1; }

body.kiosk-home .overlay {
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0.05'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E"),
    linear-gradient(180deg,
      rgba(6, 7, 11, 0.9) 0%,
      rgba(6, 7, 11, 0.5) 16%,
      rgba(6, 7, 11, 0.2) 40%,
      rgba(6, 7, 11, 0.28) 70%,
      rgba(6, 7, 11, 0.9) 100%),
    radial-gradient(120% 90% at 50% 50%, transparent 50%, rgba(6, 7, 11, 0.72) 100%);
}

/* A slow wash of brand colour over the film. Transform-only, so it stays
   cheap on the tablet. */
body.kiosk-home .bg-orb {
  display: block;
  position: fixed;
  inset: -30vmax;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(34vmax 34vmax at 28% 38%, rgba(91, 140, 255, 0.16), transparent 70%),
    radial-gradient(30vmax 30vmax at 74% 66%, rgba(255, 87, 34, 0.14), transparent 70%);
  animation: homeDrift 26s ease-in-out infinite alternate;
}

@keyframes homeDrift { to { transform: translate3d(4vmax, -3vmax, 0) rotate(10deg); } }

/* ── header: quiet ghost buttons ── */

body.kiosk-home .kiosk-header {
  z-index: 5;
  height: 80px;
  padding: 0 var(--s-5);
  background: transparent;
  border-bottom: 0;
  backdrop-filter: none;
}
body.kiosk-home .kiosk-header::after { display: none; }
body.kiosk-home .brand-lockup img { width: clamp(118px, 11vw, 156px); }
body.kiosk-home .header-buttons { gap: 6px; }

body.kiosk-home .lang-button,
body.kiosk-home .games-button,
body.kiosk-home .admin-button {
  gap: 8px;
  min-height: 46px;
  padding: 0 18px;
  border: 0;
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-dim);
  box-shadow: none;
  font-size: 0.9rem;
  font-weight: 600;
}

body.kiosk-home .lang-button:hover,
body.kiosk-home .games-button:hover,
body.kiosk-home .admin-button:hover { background: rgba(255, 255, 255, 0.1); color: var(--text); }
body.kiosk-home .lang-button.lang-active { background: rgba(34, 211, 238, 0.12); color: var(--cyan); }

body.kiosk-home .lang-button::before,
body.kiosk-home .games-button::before,
body.kiosk-home .admin-button::before {
  content: '';
  flex: none;
  width: 18px;
  height: 18px;
  background: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

/* Malayalam labels are longer than the English ones, so switching language
   used to make these buttons jump wider. Hold the wider size in both. */
body.kiosk-home .games-button { min-width: 142px; }
body.kiosk-home .admin-button { min-width: 104px; }
body.kiosk-home .lang-button  { min-width: 124px; }

body.kiosk-home .lang-button {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9M12 3C9.5 5.6 8.2 8.6 8.2 12s1.3 6.4 3.8 9'/%3E%3C/svg%3E");
}
body.kiosk-home .games-button {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 11h4M8 9v4M15 12h.01M18 10h.01'/%3E%3Cpath d='M17.3 5H6.7a4 4 0 0 0-4 3.6l-.9 8.2a2.5 2.5 0 0 0 2.5 2.7c.9 0 1.7-.5 2.1-1.3L8 15h8l1.6 3.2c.4.8 1.2 1.3 2.1 1.3a2.5 2.5 0 0 0 2.5-2.7l-.9-8.2A4 4 0 0 0 17.3 5z'/%3E%3C/svg%3E");
}
body.kiosk-home .admin-button {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4.5' y='11' width='15' height='10' rx='2.5'/%3E%3Cpath d='M8 11V7.5a4 4 0 0 1 8 0V11'/%3E%3C/svg%3E");
}

/* ── the page ── */

body.kiosk-home .main-container {
  position: relative;
  z-index: 1;
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--s-4);
  width: 100%;
  max-width: 1440px;
  padding: 0 var(--s-5) var(--s-5);
}

.home-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
}

.home-title {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  min-width: 0;
}

.home-title h1 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.8rem, 3.4vw, 2.9rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
}

.availability-readout {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  background: rgba(34, 224, 107, 0.1);
  color: var(--green);
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
}
.availability-readout i { width: 8px; height: 8px; border-radius: 50%; background: currentColor; animation: livePulse 2s ease-in-out infinite; }
.availability-readout strong { font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.availability-readout.is-empty { background: rgba(255, 255, 255, 0.05); color: var(--text-faint); }
.availability-readout.is-empty i { animation: none; }

@keyframes livePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34, 224, 107, 0.55); }
  50%      { box-shadow: 0 0 0 7px rgba(34, 224, 107, 0); }
}

/* The voice button, sitting in the hero instead of floating over the tiles. */
.voice-fab.is-inline {
  position: relative;
  right: auto;
  bottom: auto;
  z-index: 1;
  min-height: 58px;
  padding: 6px 22px 6px 6px;
}
.voice-fab.is-inline .voice-fab-icon { width: 46px; height: 46px; }
.voice-fab-wave { display: none; }
.voice-fab.is-inline .voice-fab-wave { display: inline-flex; align-items: center; gap: 3px; height: 22px; margin-left: 6px; }
.voice-fab-wave i {
  width: 3px;
  height: 100%;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.85);
  transform-origin: center;
  animation: voiceWave 1.1s ease-in-out infinite;
}
.voice-fab-wave i:nth-child(2) { animation-delay: -0.3s; }
.voice-fab-wave i:nth-child(3) { animation-delay: -0.6s; }
.voice-fab-wave i:nth-child(4) { animation-delay: -0.15s; }
@keyframes voiceWave { 0%, 100% { transform: scaleY(0.3); } 50% { transform: scaleY(1); } }

/* ── the tiles ── */

body.kiosk-home .device-deck { display: flex; flex: 1; min-height: 0; }

body.kiosk-home .console-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  grid-auto-rows: clamp(280px, calc(100dvh - 250px), 540px);
  align-content: center;
  gap: var(--s-3);
}

body.kiosk-home .console-box {
  --accent: 91, 140, 255;
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--s-4);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 28px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.012)), #0e1017;
  overflow: hidden;
  cursor: default;
  transform: scale(var(--press, 1));
  transition: transform 0.35s var(--ease), border-color 0.25s var(--ease), box-shadow 0.35s var(--ease);
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
body.kiosk-home .console-box[data-kind='sim'] { --accent: 255, 99, 51; }

/* A colour wash at the foot of the tile, and a light where the finger is. */
body.kiosk-home .console-box::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background:
    radial-gradient(260px 260px at var(--mx, 50%) var(--my, 35%), rgba(var(--accent), 0.16), transparent 70%),
    radial-gradient(100% 55% at 50% 100%, rgba(var(--accent), 0.2), transparent 72%);
  transition: opacity 0.3s var(--ease);
}

/* The station number as a big outlined numeral behind the artwork. */
body.kiosk-home .station-number {
  position: absolute;
  top: -0.14em;
  right: 10px;
  z-index: -1;
  font-family: var(--display);
  font-size: clamp(4.6rem, 8.5vw, 8.5rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.05em;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(255, 255, 255, 0.1);
  pointer-events: none;
}

body.kiosk-home .console-sub {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: rgb(var(--accent));
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
}
body.kiosk-home .console-sub::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 10px currentColor;
}

body.kiosk-home .console-media {
  position: relative;
  flex: 1;
  min-height: 70px;
  margin: var(--s-2) 0;
}

body.kiosk-home .console-logo {
  position: absolute;
  inset: 0;
  margin: auto;
  max-width: 92%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 24px 24px rgba(0, 0, 0, 0.65));
  transition: transform 0.45s var(--ease), opacity 0.3s var(--ease), filter 0.3s var(--ease);
}

body.kiosk-home .console-body { display: grid; gap: 8px; min-width: 0; }

body.kiosk-home .console-name {
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.55vw, 1.4rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
}

body.kiosk-home .console-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
  min-height: 54px;
}

body.kiosk-home .status-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text-dim);
  font-size: 0.92rem;
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
body.kiosk-home .status-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }

/* The play button: a warm disc with a light running round its rim. */
body.kiosk-home .console-action {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  color: #fff;
  background: linear-gradient(140deg, var(--brand-hot), var(--brand-deep));
  box-shadow: 0 12px 28px -10px rgba(255, 87, 34, 0.9);
  transition: transform 0.3s var(--ease);
}
body.kiosk-home .console-action::before {
  content: '';
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 58%, rgba(255, 150, 110, 0.95) 84%, transparent 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  animation: spin 2.6s linear infinite;
}
body.kiosk-home .console-action svg { width: 22px; height: 22px; transition: transform 0.3s var(--ease); }

body.kiosk-home .source-badge {
  justify-self: start;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-dim);
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}
body.kiosk-home .source-badge.limit { background: rgba(255, 176, 32, 0.12); color: var(--amber); }

body.kiosk-home .extend-btn {
  min-height: 40px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 176, 32, 0.14);
  color: var(--amber);
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
}

/* "Show installed games": its own quiet button along the foot of every tile,
   whatever the station is doing. Opens the games page on that station. */
body.kiosk-home .games-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  min-height: 44px;
  margin-top: 2px;
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-dim);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
body.kiosk-home .games-link svg { width: 17px; height: 17px; flex: none; }
body.kiosk-home .games-link .games-count {
  min-width: 22px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(var(--accent), 0.18);
  color: var(--text);
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
@media (hover: hover) {
  body.kiosk-home .games-link:hover { background: rgba(255, 255, 255, 0.08); color: var(--text); }
}
body.kiosk-home .games-link:focus-visible { outline: 3px solid rgba(var(--accent), 0.85); outline-offset: 2px; }

/* ── states ── */

body.kiosk-home .state-available { cursor: pointer; }
body.kiosk-home .state-available .status-pill { color: var(--green); }
body.kiosk-home .state-available .status-dot { animation: livePulse 2s ease-in-out infinite; }
body.kiosk-home .state-available .console-logo { animation: tileFloat 5.5s ease-in-out infinite; }
body.kiosk-home .console-box:nth-child(2) .console-logo { animation-delay: -1.1s; }
body.kiosk-home .console-box:nth-child(3) .console-logo { animation-delay: -2.2s; }
body.kiosk-home .console-box:nth-child(4) .console-logo { animation-delay: -3.3s; }
body.kiosk-home .console-box:nth-child(5) .console-logo { animation-delay: -4.4s; }

@keyframes tileFloat { 50% { transform: translateY(-9px); } }

@media (hover: hover) {
  body.kiosk-home .state-available:hover {
    border-color: rgba(var(--accent), 0.5);
    box-shadow: 0 34px 70px -36px rgba(var(--accent), 0.75);
  }
  body.kiosk-home .state-available:hover .console-action { transform: scale(1.08); }
  body.kiosk-home .state-available:hover .console-action svg { transform: translateX(2px); }
}

body.kiosk-home .state-available:active { --press: 0.965; transition-duration: 0.12s; }
body.kiosk-home .state-available:focus-visible { outline: 3px solid rgba(var(--accent), 0.85); outline-offset: 3px; }

body.kiosk-home .state-playing { border-color: rgba(255, 87, 34, 0.28); }
body.kiosk-home .state-playing .status-pill { color: var(--brand-hot); font-size: 1.05rem; font-weight: 700; }
body.kiosk-home .state-playing .console-logo { opacity: 0.6; }

/* Anything that cannot be booked steps back but stays readable. */
body.kiosk-home .console-box.reserved,
body.kiosk-home .console-box.admin-use {
  background: #0b0c11;
  border-color: rgba(255, 255, 255, 0.045);
}
body.kiosk-home .console-box.reserved::before { opacity: 0.25; }
body.kiosk-home .console-box.reserved .console-logo { opacity: 0.3; filter: grayscale(1); }
body.kiosk-home .console-box.reserved .console-name { color: var(--text-dim); }
body.kiosk-home .console-box.reserved .console-sub { opacity: 0.55; }
body.kiosk-home .state-offline .status-pill { color: var(--red); }
body.kiosk-home .state-checkout .status-pill { color: var(--amber); }
body.kiosk-home .state-staff .status-pill { color: var(--cyan); }
body.kiosk-home .state-reserved .status-pill { color: var(--violet); }
body.kiosk-home .state-manual .status-pill { color: var(--text-faint); }

body.kiosk-home .console-box.initial-load { animation: tileIn 0.65s var(--ease) backwards; }
@keyframes tileIn { from { opacity: 0; transform: translateY(28px) scale(0.95); } }

/* ── other screen shapes ── */

/* Portrait tablet: three across, two rows. */
@media (min-width: 601px) and (orientation: portrait) {
  body.kiosk-home .console-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-rows: clamp(250px, calc((100dvh - 240px) / 2), 440px);
    align-content: start;
  }
}

/* Phone: two across, compact tiles, the voice button full width. */
@media (max-width: 600px) {
  body.kiosk-home .kiosk-header { height: 64px; padding: 0 var(--s-3); }
  body.kiosk-home .brand-lockup img { width: 100px; }
  body.kiosk-home .header-buttons { gap: 4px; }
  body.kiosk-home .lang-button,
  body.kiosk-home .games-button { min-height: 40px; padding: 0 12px; font-size: 0.82rem; min-width: 0; }
  body.kiosk-home .lang-button::before { display: none; }
  body.kiosk-home .admin-button { width: 40px; min-width: 0; min-height: 40px; padding: 0; font-size: 0; gap: 0; }

  body.kiosk-home .main-container { gap: var(--s-3); padding: 0 var(--s-3) var(--s-4); }
  .home-hero { gap: var(--s-2); }
  .home-title { gap: var(--s-2); }
  .home-title h1 { font-size: 1.65rem; }
  .availability-readout { height: 30px; padding: 0 10px; font-size: 0.8rem; }
  .voice-slot { width: 100%; }
  .voice-fab.is-inline { width: 100%; min-height: 54px; }
  .voice-fab.is-inline .voice-fab-wave { margin-left: auto; }

  body.kiosk-home .console-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 200px;
    align-content: start;
    gap: 10px;
  }
  body.kiosk-home .console-box { padding: 14px; border-radius: 22px; }
  body.kiosk-home .station-number { font-size: 4rem; right: 6px; }
  body.kiosk-home .console-sub { gap: 6px; font-size: 0.6rem; letter-spacing: 0.12em; }
  body.kiosk-home .console-media { margin: 6px 0; }
  body.kiosk-home .console-name { font-size: 0.98rem; }
  body.kiosk-home .console-body { gap: 4px; }
  body.kiosk-home .console-status { min-height: 42px; gap: 6px; }
  body.kiosk-home .status-pill { font-size: 0.8rem; }
  body.kiosk-home .state-playing .status-pill { font-size: 0.9rem; }
  body.kiosk-home .console-action { width: 42px; height: 42px; }
  body.kiosk-home .console-action svg { width: 18px; height: 18px; }
  body.kiosk-home .extend-btn { min-height: 34px; padding: 0 12px; font-size: 0.78rem; }
  body.kiosk-home .games-link { min-height: 38px; padding: 5px 8px; gap: 6px; font-size: 0.72rem; border-radius: 12px; }
  body.kiosk-home .games-link svg { width: 15px; height: 15px; }
  body.kiosk-home .source-badge { font-size: 0.64rem; }
}

@media (prefers-reduced-motion: reduce) {
  body.kiosk-home .bg-orb,
  body.kiosk-home .console-logo,
  body.kiosk-home .console-action::before,
  body.kiosk-home .status-dot,
  .availability-readout i,
  .voice-fab-wave i { animation: none !important; }
}

/* ── voice booking assistant (voice-assistant.js) ─────────────────────────── */

.voice-fab {
  position: fixed;
  right: var(--s-4);
  bottom: var(--s-4);
  z-index: 320;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 64px;
  padding: 8px 22px 8px 8px;
  border: 0;
  border-radius: 999px;
  color: #fff;
  background: linear-gradient(135deg, var(--brand-hot), var(--brand-deep));
  box-shadow: var(--glow-brand), 0 18px 40px -18px rgba(0, 0, 0, 0.8);
  font: 600 1rem/1.15 var(--ui);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.16s var(--ease);
}
.voice-fab::after {
  content: '';
  position: absolute;
  inset: -6px;
  border: 2px solid rgba(255, 122, 69, 0.55);
  border-radius: inherit;
  pointer-events: none;
  animation: voice-ping 2.6s var(--ease) infinite;
}
.voice-fab:active { transform: scale(0.97); }
.voice-fab-icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.22);
}
.voice-fab-icon svg { width: 24px; height: 24px; }
.voice-fab-text { display: grid; gap: 2px; text-align: left; }
.voice-fab-text small { font-size: 0.72rem; font-weight: 500; letter-spacing: 0.02em; opacity: 0.85; }
.voice-fab.is-compact { padding: 8px; }
.voice-fab.is-compact .voice-fab-text { display: none; }

.voice-sheet {
  position: fixed;
  inset: 0;
  z-index: 330;
  display: grid;
  place-items: center;
  padding: var(--s-3);
  background: rgba(4, 5, 9, 0.74);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s var(--ease);
}
.voice-sheet.is-open { opacity: 1; pointer-events: auto; }

.voice-card {
  display: grid;
  justify-items: center;
  gap: var(--s-3);
  width: min(580px, 100%);
  max-height: calc(100vh - 32px);
  overflow: auto;
  padding: var(--s-4) var(--s-4) var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  box-shadow: 0 40px 90px -40px #000;
  text-align: center;
  transform: translateY(16px);
  transition: transform 0.28s var(--ease);
}
.voice-sheet.is-open .voice-card { transform: none; }

.voice-head { display: flex; align-items: center; justify-content: space-between; width: 100%; }
.voice-kicker {
  color: var(--text-faint);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.voice-close {
  width: 48px;
  height: 48px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: var(--surface-3);
  color: var(--text);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}

.voice-orb { position: relative; display: grid; place-items: center; width: 140px; height: 140px; }
.voice-orb i {
  position: absolute;
  inset: 0;
  border: 2px solid rgba(255, 87, 34, 0.4);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}
.voice-mic {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 108px;
  height: 108px;
  border: 0;
  border-radius: 50%;
  color: #fff;
  background: radial-gradient(circle at 30% 25%, var(--brand-hot), var(--brand-deep));
  box-shadow: var(--glow-brand);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.voice-mic svg { width: 44px; height: 44px; }
.voice-orb[data-state="listening"] .voice-mic { background: radial-gradient(circle at 30% 25%, #ffa37a, var(--brand)); }
.voice-orb[data-state="listening"] i { animation: voice-ring 1.6s var(--ease) infinite; }
.voice-orb[data-state="listening"] i:last-child { animation-delay: 0.55s; }
.voice-orb[data-state="speaking"] .voice-mic { animation: voice-breathe 1.1s ease-in-out infinite; }
.voice-orb[data-state="thinking"] .voice-mic { opacity: 0.72; }
.voice-orb[data-state="thinking"] i:nth-of-type(1) {
  opacity: 1;
  border-color: transparent;
  border-top-color: var(--brand-hot);
  animation: voice-spin 0.9s linear infinite;
}

.voice-status {
  min-height: 1.2em;
  color: var(--brand-hot);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}
.voice-message { color: var(--text); font-size: clamp(1.25rem, 2.6vw, 1.65rem); font-weight: 700; line-height: 1.38; }
.voice-detail { color: var(--text-dim); font-size: 0.9rem; }
.voice-detail:empty, .voice-heard:empty, .voice-order:empty, .voice-quick:empty { display: none; }
.voice-heard { color: var(--text-dim); font-size: 1rem; font-style: italic; }
.voice-heard.is-final { color: var(--text); }

.voice-order { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-1); }
.voice-chip {
  padding: 7px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-3);
  font-size: 0.92rem;
  font-weight: 600;
}
.voice-chip b { color: var(--brand-hot); }

.voice-quick { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); width: 100%; }
.voice-reply {
  display: grid;
  gap: 2px;
  min-width: 118px;
  min-height: var(--tap);
  padding: 8px 18px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-3);
  color: var(--text);
  font: 700 1.08rem/1.15 var(--ui);
  cursor: pointer;
}
.voice-reply small { color: var(--text-dim); font-size: 0.78rem; font-weight: 500; }
.voice-reply:active { border-color: var(--brand); }
.voice-reply.is-primary { border-color: var(--brand); background: var(--brand); color: #fff; }
.voice-reply.is-primary small { color: rgba(255, 255, 255, 0.86); }

.voice-hint { max-width: 46ch; color: var(--text-faint); font-size: 0.92rem; line-height: 1.5; }

.voice-caption {
  position: fixed;
  bottom: var(--s-4);
  left: 0;
  right: 0;
  width: fit-content;
  margin: 0 auto;
  z-index: 325;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(640px, calc(100vw - 32px));
  padding: 10px 18px 10px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: rgba(20, 22, 31, 0.94);
  box-shadow: 0 18px 40px -20px #000;
  color: var(--text);
  font-weight: 600;
  opacity: 0;
  pointer-events: none;
  transform: translateY(12px);
  transition: opacity 0.2s var(--ease), transform 0.25s var(--ease);
}
.voice-caption.is-visible { opacity: 1; transform: none; }
.voice-caption svg { flex: none; width: 18px; height: 18px; color: var(--brand-hot); }

@keyframes voice-ping { 0% { opacity: 0.9; transform: scale(0.96); } 70%, 100% { opacity: 0; transform: scale(1.14); } }
@keyframes voice-ring { 0% { opacity: 0.85; transform: scale(0.78); } 100% { opacity: 0; transform: scale(1.32); } }
@keyframes voice-breathe { 50% { transform: scale(1.05); } }
@keyframes voice-spin { to { transform: rotate(360deg); } }

@media (max-width: 900px) {
  .kiosk-duration .voice-fab { right: var(--s-3); bottom: calc(var(--s-3) + var(--tap) + var(--s-2)); }
  .voice-caption { bottom: calc(var(--s-3) + var(--tap) + 92px); }
  .voice-sheet { place-items: end center; padding: 0; }
  .voice-card { width: 100%; border-radius: var(--r-xl) var(--r-xl) 0 0; }
}

@media (prefers-reduced-motion: reduce) {
  .voice-fab::after, .voice-orb i, .voice-mic { animation: none !important; }
}
