/* SeatScout.
 *
 * Dark, compact, and built for a phone held one-handed in a cinema car park.
 *
 * Safe areas: the manifest is `display: standalone` and the page sets
 * `viewport-fit=cover`, so an installed iOS app draws under the clock, the
 * Dynamic Island and the home indicator. Nothing reserves that space — every
 * edge that touches the screen pays its own inset through these variables.
 * `env(safe-area-inset-*)` is always 0px without viewport-fit=cover, so the
 * padding silently does nothing if that meta tag is ever dropped.
 *
 * The insets are indirected through variables so the layout can be exercised
 * in a desktop browser by overriding them.
 */
:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);

  /* Deep aubergine and marquee gold — a cinema, and deliberately nothing like
     JP NTFY's forest green, since both apps live on the same home screen and a
     glance at the icon should never land you in the wrong one. Green survives
     here only as a *status* colour (a seat you want is open), never as brand. */
  --bg: #120f1c;
  --panel: #1b1730;
  --panel-2: #251f3f;
  --line: #332c52;
  --text: #ece9f7;
  --muted: #a49cc2;
  --accent: #f2a93b;
  --accent-ink: #2a1c05;   /* text on an amber fill */
  --ok: #35d69b;
  --warn: #ffc861;
  --err: #ff6b7a;
  --taken: #3a3358;

  /* Apple HIG / WCAG 2.5.8: nothing interactive smaller than this. */
  --tap: 44px;
  --radius: 12px;
}

* { box-sizing: border-box; }

/* Any class that sets `display` outranks the browser's own
   `[hidden] { display: none }`, so an element can be hidden in the DOM and
   still on screen. That is exactly what happened to `.showing` (display:flex)
   in the format filter: rows were marked hidden, the count agreed, and the
   page showed them anyway. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}

a { color: var(--accent); }

/* --------------------------------------------------------------------- */
/* Chrome                                                                 */
/* --------------------------------------------------------------------- */
.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: calc(10px + var(--safe-top)) calc(16px + var(--safe-right))
           10px calc(16px + var(--safe-left));
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 650;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}
.brand .logo { width: 22px; height: 22px; }

.topbar nav {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-left: auto;
}
.topbar nav a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 12px;
  border-radius: 9px;
  color: var(--muted);
  text-decoration: none;
  font-size: 15px;
}
.topbar nav a.active, .topbar nav a:hover {
  background: var(--panel-2);
  color: var(--text);
}

main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 20px calc(16px + var(--safe-right))
           calc(40px + var(--safe-bottom)) calc(16px + var(--safe-left));
}

h1 { font-size: 24px; margin: 0 0 4px; }
h2 { font-size: 18px; margin: 28px 0 10px; }
.muted { color: var(--muted); }
.small { font-size: 14px; }

/* --------------------------------------------------------------------- */
/* Panels, forms, buttons                                                 */
/* --------------------------------------------------------------------- */
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 14px;
}

label { display: block; font-size: 14px; color: var(--muted); margin-bottom: 6px; }

input[type=text], input[type=password], input[type=date], input[type=number],
input[type=email], select, textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 10px 12px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  font-size: 16px;      /* 16px or iOS zooms the page on focus */
}
input:focus, select:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

.field { margin-bottom: 14px; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row > * { flex: 1 1 160px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: var(--tap);
  min-width: var(--tap);
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
  color: var(--text);
  font-size: 15px;
  font-weight: 550;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { border-color: var(--accent); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.danger { color: var(--err); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

.actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

.flash {
  padding: 12px 14px;
  border-radius: 10px;
  margin-bottom: 14px;
  border: 1px solid var(--line);
  background: var(--panel);
}
.flash.ok { border-color: var(--ok); }
.flash.error { border-color: var(--err); }
.ok-text { color: var(--ok); }
.err-text { color: var(--err); }
.warn-text { color: var(--warn); }

.pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--muted);
}
.pill.on { border-color: var(--ok); color: var(--ok); }
.pill.off { border-color: var(--line); }
.pill.hot { border-color: var(--ok); background: rgba(61, 220, 151, .14); color: var(--ok); }

/* --------------------------------------------------------------------- */
/* Lists and tables                                                       */
/* --------------------------------------------------------------------- */
.watch { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }

/* Poster thumbnail. Fixed box so a missing or slow image never reflows the
   card, and a film-strip placeholder when there is no artwork — Fandango
   serves its own grey default, which reads as a broken poster rather than as
   "no poster". */
.poster {
  flex: 0 0 44px;
  width: 44px;
  height: 66px;
  border-radius: 6px;
  object-fit: cover;
  background: var(--panel-2);
  border: 1px solid var(--line);
}
.poster.placeholder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}
/* A 404 after the page loaded: fall back to the same empty box. */
.poster.broken { visibility: hidden; }
.watch .body { flex: 1 1 260px; min-width: 0; }
.watch h3 { margin: 0 0 4px; font-size: 17px; }

.seatlist { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; }
.seatchip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.seatchip button {
  all: unset;
  cursor: pointer;
  color: var(--muted);
  /* The chip itself is small, so the remove control carries the tap target. */
  min-width: var(--tap);
  min-height: var(--tap);
  margin: -10px -10px -10px 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.seatchip button:hover { color: var(--err); }

table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 600; }
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* --------------------------------------------------------------------- */
/* Seat map                                                               */
/* --------------------------------------------------------------------- */
.maparea {
  position: relative;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  background: #05070a;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* A bounded viewport. Without this the zoomed map is 1600px tall, the
     container grows to fit it, and the map "scrolls" by scrolling the whole
     page — which reads as the map being cut off. Capped, it becomes a window
     you pan around inside. */
  max-height: min(72vh, 620px);
  /* Touch panning and pinch-zoom are left to the browser: it does both better
     than script can, with momentum. The pointer handlers only take over for a
     mouse, which has no native equivalent of a drag-to-pan. */
  touch-action: pinch-zoom pan-x pan-y;
}
.maparea svg { display: block; width: 100%; height: auto; }

/* Only offer the grab cursor when there is somewhere to grab to. */
.maparea.pannable { cursor: grab; }
.maparea.panning { cursor: grabbing; }
.maparea.painting, .maparea.painting .seat-hit { cursor: crosshair; }
.maparea.mode-pan .seat-hit { cursor: grab; }
.maparea.mode-pan.panning .seat-hit { cursor: grabbing; }

/* Segmented control for what a drag does. */
.modes { display: inline-flex; }
.modes .mode {
  min-height: var(--tap);
  padding: 0 14px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--muted);
  font: inherit;
  font-size: 15px;
  font-weight: 550;
  cursor: pointer;
}
.modes .mode:first-child { border-radius: 10px 0 0 10px; }
.modes .mode:last-child { border-radius: 0 10px 10px 0; margin-left: -1px; }
.modes .mode[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
/* Dragging without pointer capture would otherwise start a text/image
   selection across the map. */
.maparea { user-select: none; -webkit-user-select: none; }

/* Zoomed to 1:1, where a seat's padded hit rect is ~45px — an actual tap
   target. Fitting 39 seats across a 344px phone would give each one 4px, so
   "see the whole room" and "tap a seat" genuinely cannot both be true at once;
   this is the toggle between them rather than a pretence that they can. */
.maparea.zoomed svg { width: 1600px; max-width: none; }

/* Seats are drawn twice: a visible rect, and an invisible one padded out to a
   real tap target. Without the second, selecting a seat on a phone is a test
   of aim rather than intent. */
/* In pan mode the seats stop claiming touches, so a thumb-drag starting on a
   seat scrolls the map natively instead of painting. */
.maparea.mode-pan .seat-hit { touch-action: auto; }

.seat-hit {
  fill: transparent;
  cursor: pointer;
  /* A touch that begins on a seat is a selection, not a scroll. Without this
     the browser claims the gesture and pans the map out from under the thumb
     before the first pointermove arrives. Touches starting on empty map still
     pan, which is how you move around. */
  touch-action: none;
}
.seat { pointer-events: none; }
.seat.free { fill: var(--accent); }
.seat.taken { fill: var(--taken); }
.seat.sel { fill: var(--ok); stroke: #fff; stroke-width: 2.5px; }
/* Selection is also carried by the ring above and the chip list below, so the
   state never depends on colour alone. */
.seat.accessible { rx: 9px; }

/* Accessible seats carry a symbol, not just a rounder corner — shape alone was
   too subtle, and these are seats you must not book by mistake. The glyph is
   never the tap target; the invisible hit rect above it is. */
.seat-icon { pointer-events: none; fill: var(--bg); stroke: var(--bg); }
.seat-icon.on-taken { fill: var(--muted); stroke: var(--muted); }

.legend { display: flex; gap: 14px; flex-wrap: wrap; margin: 10px 0 0; font-size: 13px; }
.legend span { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); }
.legend i { width: 13px; height: 13px; border-radius: 3px; display: inline-block; }

.stepper { display: inline-flex; align-items: center; gap: 0; }
.stepper button {
  width: var(--tap); height: var(--tap);
  font-size: 20px; line-height: 1;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); cursor: pointer;
}
.stepper button:first-child { border-radius: 10px 0 0 10px; }
.stepper button:last-child { border-radius: 0 10px 10px 0; }
.stepper output {
  min-width: 56px; height: var(--tap);
  display: inline-flex; align-items: center; justify-content: center;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  background: var(--bg); font-variant-numeric: tabular-nums; font-weight: 600;
}

.rowpicker { display: flex; flex-wrap: wrap; gap: 6px; }
.rowpicker button {
  min-width: var(--tap); min-height: var(--tap);
  border-radius: 9px; border: 1px solid var(--line);
  background: var(--panel-2); color: var(--text);
  font-weight: 600; cursor: pointer;
}
.rowpicker button[aria-pressed="true"] { border-color: var(--ok); color: var(--ok); }

.sticky-save {
  position: sticky;
  bottom: 0;
  margin-top: 14px;
  padding: 12px 0 calc(12px + var(--safe-bottom));
  background: linear-gradient(180deg, transparent, var(--bg) 22%);
}

/* --------------------------------------------------------------------- */
/* Narrow screens — checked down to 344px (Galaxy Z Fold)                 */
/* --------------------------------------------------------------------- */
@media (max-width: 560px) {
  /* These rules re-state the safe-area padding: overriding padding here
     without it is how the header ends up under the clock. */
  .topbar {
    padding: calc(8px + var(--safe-top)) calc(12px + var(--safe-right))
             8px calc(12px + var(--safe-left));
    gap: 8px;
  }
  main {
    padding: 16px calc(12px + var(--safe-right))
             calc(32px + var(--safe-bottom)) calc(12px + var(--safe-left));
  }
  .topbar nav { width: 100%; margin-left: 0; }
  .topbar nav a { flex: 1 1 auto; justify-content: center; padding: 0 8px; }
  h1 { font-size: 21px; }
  .row > * { flex: 1 1 100%; }
  .actions .btn { flex: 1 1 auto; }
}

/* --------------------------------------------------------------------- */
/* Status page                                                            */
/* --------------------------------------------------------------------- */
.health-item { padding: 14px 16px; margin-bottom: 10px; }
.health-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.health-item .detail { margin: 2px 0 0; }
.access-note {
  margin-top: 8px;
  padding-left: 10px;
  border-left: 2px solid var(--line);
  font-size: 13px;
  color: var(--muted);
}
.health-item .lastran { margin-top: 6px; font-size: 12px; }

.pill.pending { border-color: var(--line); color: var(--muted); }
.pill.warn { border-color: var(--warn); color: var(--warn); }
.pill.err { border-color: var(--err); color: var(--err); }

/* --------------------------------------------------------------------- */
/* Film search (new watch, step 1)                                        */
/* --------------------------------------------------------------------- */
.results {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 30;
  margin-top: 4px;
  max-height: 340px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .5);
}

.result {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  /* Comfortably past a 44px tap target: this list is the primary way in, and
     it's usually driven by thumb on a phone. */
  min-height: 60px;
  padding: 10px 12px;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.result:last-child { border-bottom: 0; }
.result:hover, .result.active { background: var(--line); }
.result img, .result i {
  width: 34px;
  height: 50px;
  flex: 0 0 34px;
  border-radius: 4px;
  object-fit: cover;
  background: var(--bg);
  display: block;
}
.result-empty { padding: 14px 12px; }


/* Which showing's availability the picker is displaying. */
.preview-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.preview-bar label { margin: 0; white-space: nowrap; }
.preview-bar select { width: auto; min-width: 190px; flex: 0 1 auto; }

/* --------------------------------------------------------------------- */
/* Step 2 — one card per cinema, its formats listed inside                */
/* --------------------------------------------------------------------- */
.theater h3 { font-size: 17px; }

.showing {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
.showing:first-of-type { border-top: 0; padding-top: 4px; }
.showing .body { flex: 1 1 240px; min-width: 0; }

#format-filter .rowpicker button {
  /* Format names are words, not single letters like the row picker's. */
  padding: 0 14px;
  font-size: 14px;
  font-weight: 550;
}

/* One booking link per showing in the History detail column. */
.matchlist { margin: 0; padding: 0; list-style: none; }
.matchlist li { padding: 2px 0; }
.matchlist li + li { border-top: 1px solid var(--line); }
.matchlist .seats { margin-left: 8px; }
