/* The site's look: the grid of films and its headings, a film's showtimes and seat maps, the
   search, Preferences, and an upright phone's page (html.page-scroll). The cards view's own look
   (each film a full-art trading card) is in cardsview.css, put away with it (funcs.go's cardsOn);
   the rules here for its markup still in cards.html (.deck-*, .next-show, the view toggle) stay,
   as the grid is laid out round the stack. Feedback's sheet: feedback.css. */

/* Inter in two parts. The first, cut down to the characters the site uses (static/fonts: see the
   README), is what's normally fetched. The rest of Inter, the full fonts, is fetched only for a page
   that has a character outside it, e.g. a cast's "Nguyễn", "Ștefan" or "Ελένη": in Inter, as before,
   not misdrawn from the cut-down one's parts, nor in a stand-in font. */
@font-face { font-family: "Inter"; src: url("/static/fonts/Inter-Regular.woff") format("woff"); font-weight: 400; font-display: swap;
  unicode-range: U+0000-017F, U+0237, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0308, U+2000-206F, U+20AC, U+2122, U+2190-2193, U+21BA, U+2212, U+25CB, U+25CF, U+FEFF, U+FFFD; }
@font-face { font-family: "Inter"; src: url("/static/fonts/Inter-Medium.woff") format("woff"); font-weight: 500; font-display: swap;
  unicode-range: U+0000-017F, U+0237, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0308, U+2000-206F, U+20AC, U+2122, U+2190-2193, U+21BA, U+2212, U+25CB, U+25CF, U+FEFF, U+FFFD; }
@font-face { font-family: "Inter"; src: url("/static/fonts/Inter-SemiBold.woff") format("woff"); font-weight: 600 800; font-display: swap;
  unicode-range: U+0000-017F, U+0237, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0308, U+2000-206F, U+20AC, U+2122, U+2190-2193, U+21BA, U+2212, U+25CB, U+25CF, U+FEFF, U+FFFD; }
/* the rest: what Inter has that the above leaves out (Latin, Greek and Cyrillic beyond, and its
   symbols; read from the full fonts' character maps), and nothing it hasn't: Arabic or Hindi text
   would otherwise fetch a full font that can't draw it */
@font-face { font-family: "Inter"; src: url("/fonts/Inter-Regular.ttf") format("truetype"); font-weight: 400; font-display: swap;
  unicode-range: U+0180-0236, U+0238-02BA, U+02BD-02C5, U+02C7-02D9, U+02DB, U+02DD-02FF, U+0309-052F, U+0E3F, U+1D00-1DFF,U+1E00-1FFF, U+2070-20AB, U+20AD-20C0, U+20DB-2121, U+2123-213B, U+214D-218F, U+2194-21B9, U+21BB, U+21D0-21EA, U+2202-2211, U+2213-23CF, U+2423, U+2460-24EA, U+25A0-25CA, U+25CC-25CE, U+25D0-25EF, U+2600-2606, U+263C, U+2661-266B, U+26A0, U+2713-2717, U+2756-2788, U+27EF-27FA, U+2913, U+2A38, U+2B06-2B24, U+2C7C-2C7F, U+2DFF, U+2E18, U+A69F, U+A7FF, U+A92E, U+1F12F-1F16B, U+1F850-1F852; }
@font-face { font-family: "Inter"; src: url("/fonts/Inter-Medium.ttf") format("truetype"); font-weight: 500; font-display: swap;
  unicode-range: U+0180-0236, U+0238-02BA, U+02BD-02C5, U+02C7-02D9, U+02DB, U+02DD-02FF, U+0309-052F, U+0E3F, U+1D00-1DFF,U+1E00-1FFF, U+2070-20AB, U+20AD-20C0, U+20DB-2121, U+2123-213B, U+214D-218F, U+2194-21B9, U+21BB, U+21D0-21EA, U+2202-2211, U+2213-23CF, U+2423, U+2460-24EA, U+25A0-25CA, U+25CC-25CE, U+25D0-25EF, U+2600-2606, U+263C, U+2661-266B, U+26A0, U+2713-2717, U+2756-2788, U+27EF-27FA, U+2913, U+2A38, U+2B06-2B24, U+2C7C-2C7F, U+2DFF, U+2E18, U+A69F, U+A7FF, U+A92E, U+1F12F-1F16B, U+1F850-1F852; }
@font-face { font-family: "Inter"; src: url("/fonts/Inter-SemiBold.ttf") format("truetype"); font-weight: 600 800; font-display: swap;
  unicode-range: U+0180-0236, U+0238-02BA, U+02BD-02C5, U+02C7-02D9, U+02DB, U+02DD-02FF, U+0309-052F, U+0E3F, U+1D00-1DFF,U+1E00-1FFF, U+2070-20AB, U+20AD-20C0, U+20DB-2121, U+2123-213B, U+214D-218F, U+2194-21B9, U+21BB, U+21D0-21EA, U+2202-2211, U+2213-23CF, U+2423, U+2460-24EA, U+25A0-25CA, U+25CC-25CE, U+25D0-25EF, U+2600-2606, U+263C, U+2661-266B, U+26A0, U+2713-2717, U+2756-2788, U+27EF-27FA, U+2913, U+2A38, U+2B06-2B24, U+2C7C-2C7F, U+2DFF, U+2E18, U+A69F, U+A7FF, U+A92E, U+1F12F-1F16B, U+1F850-1F852; }

:root {
  --bg: #07070a;
  --gold: #e9cf8e;      /* the cards' own gold: frame, seals, details */
  --gold-deep: #9c7632;
  /* the site's accent, for its controls (buttons, filters, highlights): deep indigo into blue
     for fills, and a lighter tint of it for text, outlines and washes, so they read on the dark */
  --accent: #a996ff;    /* text, outlines, washes */
  --accent-grad: linear-gradient(135deg, #6847d8, #2f5cc4); /* fills */
  --on-accent: #fff;    /* text on the fills */
  --ink: #f4f1ea;
  --ink-soft: rgba(244, 241, 234, 0.78);
  --ink-faint: rgba(244, 241, 234, 0.5);
  --soon: #3ddc84; /* starting within 2 hours */
  --now: #ff5c5c;  /* just started */
  --full-low: #7fd69a;  /* the tier scales' good (.tier-pop-scales) */
  --full-most: #ef7a6e; /* and their poor */
  /* how full a show you've checked was, its bar's colour (.st-time[data-full]): green empty, amber at
     --full-turn %, red full; brighter takes on the tier scales' good and poor (their middle's white) */
  --full-empty: #5fe08a;
  --full-filling: #ffc23d;
  --full-sold: #ff5f52;
  --full-turn: 60; /* (not 50: the emptier shows stay greenish, and it's red only nearing full) */

  /* a card is 63 × 88, like a real one, as big as fits (and, where the buttons at the top left
     reach over it, smaller and lower by --bar-room: cards.js's clearOfBar) */
  --card-h: calc(min(72svh, 740px, calc(90vw * 88 / 63)) - var(--bar-room, 0px)); /* leaving room for the controls below */
  --card-w: calc(var(--card-h) * 63 / 88);
  --times-w: calc(100vw - 32px); /* the showtimes view taking the screen, a margin either side; beside the card, placeTimes sets it */
  --times-gap: 36px;
  --back-h: 34px; /* a phone's ‹ Films (‹ Showtimes) and the folded bar beside it: their row's height (.seat-back, .times-fold) */
  --back-row: calc(var(--back-h) + 6px); /* and with the 6px under it (.seat-back's margin): what's pulled up beside it, or kept clear of it, on its side */
  --ease: cubic-bezier(.2, .8, .2, 1);
  /* for big moves that start from rest: --ease is at full speed from the first frame, which on a
     long move reads as a jump, then it's mostly over; this sets off, then settles the same way */
  --set-off: cubic-bezier(.4, 0, .2, 1);
  /* for what leaves from rest: sets off gently and speeds away (a panel or the search closing) */
  --leave: cubic-bezier(.4, 0, 1, 1);
  /* an upright phone's page pushed on over another, and back (the view transitions: film-push) */
  --push-in: cubic-bezier(.2, .75, .15, 1);
  --push-out: cubic-bezier(.3, .05, .4, 1);
  --panel: rgb(18, 17, 24); /* the panels' dark: Preferences' head, and words on the light fills */
  --rule: 1px solid rgba(255, 255, 255, 0.08); /* a hairline between parts */
  --frost: blur(12px) saturate(1.4); /* the glass behind buttons over a poster */
  --dialog-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 50px 140px rgba(0, 0, 0, 0.85); /* a panel's edge, and its shadow */
  /* a quiet pill (Trailer, Share, the bookmark): its line and glass, and pointed at */
  --pill-line: rgba(255, 255, 255, 0.16);
  --pill-fill: rgba(255, 255, 255, 0.06);
  --pill-line-hover: rgba(255, 255, 255, 0.26);
  --pill-fill-hover: rgba(255, 255, 255, 0.1);
  /* the layers: over the page, the top bar, its buttons, then what floats over them; in the table,
     the cards, their showtimes and the grid, as each is put away or brought up; the trailer over all */
  --z-bar: 50;          /* an upright phone's frosted bar (.page-top) */
  --z-corner: 60;       /* the top corner's buttons and the search bar */
  --z-float: 70;        /* the search opened from its bar, the undo note */
  --z-grid-under: 998;  /* an upright phone's grid, under a film */
  --z-deck-under: 999;  /* the cards, under showtimes taking the screen */
  --z-times: 1000;      /* the showtimes, above any card (cards.js's Z_LIMIT); the grid, put away */
  --z-deck: 1001;       /* the cards, beside the showtimes */
  --z-grid: 1002;       /* the grid and When, Where and Sort */
  --z-grid-over: 1003;  /* over the grid: its summary line, the words when it's empty */
  --z-screen: 1100;     /* the trailer's screen */
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
html {
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%; /* iOS: no bigger text on turning sideways */
  -webkit-tap-highlight-color: transparent; /* iOS: no grey flash on every tap */
}
body {
  margin: 0; overflow: hidden;
  overscroll-behavior: none; /* iOS: the page doesn't bounce when swiped */
  background: var(--bg); color: var(--ink);
  font: 400 16px/1.45 "Inter", system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}
img { display: block; }
/* manipulation: quick taps are taps, not iOS's double-tap zoom (spamming next and back) */
button { font: inherit; color: inherit; touch-action: manipulation; }
[hidden] { display: none !important; }
/* for a screen reader only: there, unseen (the page's heading, what's announced: cards.js's announce;
   how full a show was, .st-full: "81% full"; a by-time row's end and how soon, read out with its time) */
.sr-only, .st-full, .st-one .st-time > .st-end, .st-one .st-time > .st-when { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
/* the keyboard's focus: one ring, the accent's, on every control (the browsers' own differ, and
   Chrome's was a faint blue on the dark). Only from the keyboard: :focus-visible. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* in a row that scrolls along (which cuts what's outside it, above and below too): the ring inside */
:is(.pick-tile, .where-pick, .sort-pick, .st-day, .st-cinema-pick):focus-visible { outline-offset: -2px; }
:is(h2, h3, h4)[tabindex="-1"]:focus { outline: none; } /* a heading focused as its panel opens, just so it starts there (see cards.js's focusIn) */

/* ——— The room: the top card's poster, blurred into light ——— */
.ambient { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.ambient img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transform: scale(1.3); opacity: 0; /* blurred and saturated on the server (?glow=1): no filter here */
  transition: opacity 1.2s var(--ease);
  /* Anything that animates is kept on its own layer for good (will-change), not just while it
     moves: a layer made as an animation starts means redrawing it, and what's under it, before the
     first frame, and Safari runs the clock meanwhile, so animations seemed to start most of the way
     through. (Made as each fade started, this one held up the cards' moves.) */
  will-change: opacity;
}
.ambient img.on { opacity: 0.42; }
.ambient::after { content: ""; position: absolute; inset: 0; background: radial-gradient(ellipse at 50% 45%, transparent 20%, rgba(7, 7, 10, 0.85) 80%); }

.table {
  position: relative; z-index: 1; height: 100%;
  --gap: clamp(18px, 3.5svh, 34px); /* between the cards and the buttons below */
  --line-room: 0px; /* and more, for the filter's line under the cards (.timed: see .next-show) */
  display: grid; place-content: center; justify-items: center; gap: var(--gap);
  padding-top: calc(26px + var(--bar-room, 0px)); /* room for the cards peeking out behind */
  /* nothing reaches past the screen: a phone's browser sizes the page to all of it, body's
     overflow: hidden or not, so the showtimes waiting off to the right made it three screens wide,
     with Preferences, the trailer and the sheets placed by that width, out of sight */
  overflow: clip;
}
/* On a phone, the buttons in the top corners have the top of the screen to themselves: the cards
   start below them, leaving room for the filter's times line (.next-show), and are as big as fits
   from there down to the controls, clear of a home bar. (As tall as on a wider screen, they ran
   under the buttons in Safari, whose own bars take a good part of the screen.) On its side, the
   same, from the top: see below. */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .table {
    --top: calc(max(18px, env(safe-area-inset-top)) + 96px); /* the buttons (40px), the next show, the cards peeking out behind */
    --bottom: calc(36px + env(safe-area-inset-bottom)); /* (room for "Back to the start", under the arrows) */
    --gap: clamp(14px, 2.4svh, 34px);
    padding: var(--top) 0 var(--bottom);
    /* the controls below: Trailer and Showtimes (44px) and the arrows (38px, 6px closer) */
    --card-h: min(calc(90vw * 88 / 63), calc(100svh - var(--top) - var(--bottom) - 2 * var(--gap) - 76px));
    --card-w: calc(var(--card-h) * 63 / 88);
  }
}

/* ——— The stack ——— */
.stack {
  position: relative; width: var(--card-w); height: var(--card-h);
  transition: transform .6s var(--set-off); will-change: transform; /* moved aside for the showtimes (see below; and .ambient img's will-change) */
}
.opening * { transition: none !important; } /* the page opening in the grid (cards.js) */

:root[data-ratings="imdb"] .tile-seals { display: none; } /* (Rotten Tomatoes' awards: only by its ratings) */

/* the arrows and the count, under the buttons (a little closer to them: -6px); "Back to the start"
   is placed from here (.deck-lap) */
.deck-nav {
  position: relative; margin-top: -6px;
  display: flex; flex-direction: column; align-items: center; gap: 8px; color: var(--ink-faint); font-size: 0.85rem; font-weight: 500; font-variant-numeric: tabular-nums;
}
/* with the showtimes taking the screen, the controls go (keeping their room, so nothing moves):
   their close button brings the cards back */
.deck-nav, .deck-actions { will-change: opacity; } /* (see .ambient img's will-change) */
.deck-actions { transition: opacity .3s var(--ease), visibility 0s, translate .45s var(--set-off); } /* (translate: the filter's line, see .next-show; .deck-nav's own, below) */
.times-cover.showing-times :is(.deck-nav, .deck-actions) { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s, translate .45s var(--set-off); }
.deck-button {
  display: grid; place-items: center; padding: 0;
  width: 38px; height: 38px; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(255, 255, 255, 0.04);
  color: var(--ink-soft);
  transition: background .2s, border-color .2s, color .2s, transform .2s var(--ease);
}
/* the arrows: a square's two sides, turned to a point. Turned, the drawn shape sits to one side of
   the square's middle, so it's moved back by --shift to sit in the button's centre, by its shape
   rather than its box (measured, with the lines' thickness: about 0.28 of its size) */
.chevron {
  --size: 9px;
  --shift: calc(var(--size) * 0.28);
  width: var(--size); height: var(--size);
  border-left: 1.8px solid currentColor; border-bottom: 1.8px solid currentColor;
  transform: translateX(var(--shift)) rotate(45deg);
}
.chevron-next { transform: translateX(calc(-1 * var(--shift))) rotate(-135deg); }
/* (hovers only where there's a pointer to hover: on a phone, a tapped button would keep it) */
@media (hover: hover) { .deck-button:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.28); color: var(--ink); } }
.deck-count { min-width: 64px; text-align: center; }
.deck-sort { display: none; color: var(--ink-soft); white-space: nowrap; } /* (the sort's said over the grid, Sort: this was a phone's, where the cards never are now) */
.deck-count:has([data-total]:empty), .own-picks .deck-count { visibility: hidden; } /* until cards.js has counted your films (with your own preferences, the served count may not be yours) */

/* ——— Actions under the controls: Trailer and Showtimes ———
   Quiet glass, with Showtimes filled: it's what you're here for. Colour is left to the icons
   (YouTube's red), which a tinted button fought. */
.deck-actions { position: relative; display: flex; gap: 10px; } /* (relative: your shortlist's bookmark beside them, .deck-save) */
/* round from the last film to the first: said a moment under the count, taking no room */
.deck-lap {
  position: absolute; top: calc(100% + 10px); left: 50%; translate: -50% -4px;
  display: flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 5px 12px 5px 10px; border-radius: 99px;
  background: rgba(255, 255, 255, 0.07); color: var(--ink-soft); font-size: 0.78rem; font-weight: 600;
  opacity: 0; pointer-events: none;
  transition: opacity .4s var(--ease), translate .4s var(--ease);
  will-change: opacity; /* (see .ambient img's will-change) */
}
.deck-lap.shown { opacity: 1; translate: -50% 0; transition-duration: .25s; }
.icon-lap { font-size: 0.95rem; line-height: 1; color: var(--accent); }
.deck-action {
  display: inline-flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 10px 20px 10px 16px; border-radius: 99px;
  border: 1px solid var(--pill-line); background: var(--pill-fill);
  color: var(--ink); font-size: 0.88rem; font-weight: 600;
  transition: background .2s, border-color .2s, color .2s, opacity .3s, box-shadow .2s, filter .2s, transform .2s var(--ease);
}
.deck-action[data-showtimes-open] {
  border-color: transparent; background: var(--accent-grad); color: var(--on-accent);
  box-shadow: 0 8px 24px -10px color-mix(in srgb, var(--accent) 70%, transparent);
}
@media (hover: hover) {
  .deck-action:hover { background: var(--pill-fill-hover); border-color: var(--pill-line-hover); }
  .deck-action[data-showtimes-open]:hover { background: var(--accent-grad); filter: brightness(1.1); }
}
.deck-action.none { opacity: 0; pointer-events: none; } /* nothing to show: gone, without moving anything */
.yt { flex: none; width: 19px; height: 13.5px; } /* YouTube's mark, as is: its red and white */
/* a clapperboard, in the text's colour: the image is just its shape (a mask), 96 × 92 */
.clapper {
  flex: none; width: 16px; height: 15.3px; background: currentColor;
  -webkit-mask: url("/static/clapper.png") center / contain no-repeat;
  mask: url("/static/clapper.png") center / contain no-repeat;
}

/* ——— Showtimes: the cards move left and this view slides in beside them, as tall as a card; the
   controls stay where they are. On a narrow screen, the cards go out of sight and this has the
   screen (see placeTimes). ——— */
.showing-times .stack { transform: translateX(calc(-1 * var(--shift, 0px))); } /* see placeTimes */
/* the cards, which beside the showtimes shrink toward them where the room's short (--deck-scale,
   from placeTimes), in step with the stack's slide: toward their bottom right corner, so their foot
   stays above the buttons below and their top comes down (clear of the corner's buttons, if need
   be). Above the showtimes (a card dragged over them stays on top), but under them where they take
   the screen. */
.deck {
  position: absolute; inset: 0; z-index: var(--z-deck); transform-origin: 100% 100%;
  transition: transform .6s var(--set-off), opacity .4s var(--ease); will-change: transform; /* (see .ambient img's will-change) */
}
.showing-times .deck { transform: translateY(calc(-1 * var(--deck-lift, 0px))) scale(var(--deck-scale, 1)); } /* (lifted back up to the middle where there's room: placeTimes) */
/* under the card (cards.html's .deck-nav): the arrows either side of where you are among the films
   (.deck-place), the top card's group's heading under it (cards.js's sayGroup), the grid's own,
   smaller; then the count. All of it as wide as the card, moved aside with it for the showtimes */
.deck-place-row { display: flex; align-items: center; gap: 12px; width: var(--card-w); }
.table:not(.grid-mode) .deck-nav { margin-top: -27px; gap: 0; } /* (the bar 26px under the card, the heading 12px under the bar, the count 4px under that) */
.deck-nav .deck-count { margin-top: 4px; }
.deck-group { display: flex; justify-content: center; min-height: 1.6em; margin-top: -4px; } /* (close under the bar, its label: the arrows' row is taller than the bar) */
.grid-mode .deck-group, .table.empty .deck-group { display: none; }
.deck-group .grid-group { position: static; margin: 0; padding: 0; clip-path: none; animation: none; font-size: 1rem; white-space: nowrap; }
.deck-group .grid-group::after { display: none; }
/* where the top card is among those showing (cards.js's sayPlace): a bar of the sort's groups, each
   as long as it's large, the top card's lit (What's Hot's top band in its fire), a dot at its
   place; as wide as the card, under it, moved aside with it for the showtimes */
.deck-place { position: relative; flex: 1; display: flex; gap: 3px; height: 6px; }
.grid-mode .deck-place, .table.empty .deck-place { display: none; }
.deck-place-group { height: 100%; border-radius: 3px; background: rgba(255, 255, 255, 0.14); transition: background .25s; }
.deck-place-group.on { background: rgba(255, 255, 255, 0.42); }
.deck-place-group.on.on-fire { background: linear-gradient(90deg, #ff7a2f, #ffc24a); }
.deck-place-group.on.on-gold { background: linear-gradient(90deg, #c99a3c, #fff0c2, #e9cf8e); } /* (Top Rated's top tier, in its gold) */
.deck-place-dot {
  position: absolute; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%;
  background: var(--ink); box-shadow: 0 0 0 2.5px rgba(10, 9, 12, 0.95), 0 1px 5px rgba(0, 0, 0, 0.6);
  transition: left .35s var(--ease);
}
/* a press jumps, a drag runs through the films (cards.js's placeAt): answering a little above and
   below its line, a finger's drag not scrolling the page; the dot bigger on it, and quick to follow
   a drag */
.deck-place { cursor: pointer; touch-action: none; }
.deck-place::before { content: ""; position: absolute; inset: -10px 0; }
.deck-place-dot { pointer-events: none; transition: left .35s var(--ease), scale .15s var(--ease); }
@media (hover: hover) { .deck-place:hover .deck-place-dot { scale: 1.25; } }
.deck-place.dragging .deck-place-dot { scale: 1.35; transition: scale .15s var(--ease); } /* (dragged, right under the pointer: no easing behind it) */
@media (prefers-reduced-motion: reduce) { .deck-place-dot { transition: none; } }
.times-cover .deck { z-index: var(--z-deck-under); }
.times-cover.showing-times .deck { opacity: 0; } /* (gone for the showtimes: a phone on its side, its card narrow, didn't slide far enough) */
/* just text beside the card, on the page itself: no panel */
.times-view {
  position: absolute; top: 0; left: calc(100% + var(--times-gap)); z-index: var(--z-times);
  width: var(--times-w); height: 100%;
  display: flex; flex-direction: column;
  transform: translateX(100vw); opacity: 0;
  transition: transform .6s var(--set-off), opacity .45s var(--ease);
  contain: layout style; /* redrawing the times doesn't touch the page around them (not paint: seat tips reach out) */
  will-change: transform, opacity; /* (see .ambient img's will-change) */
}
.showing-times .times-view { transform: none; opacity: 1; }
.table:not(.times-cover) .times-view { top: var(--times-drop, 0px); height: calc(100% - var(--times-drop, 0px)); } /* (clear of the top right buttons: placeTimes) */
/* taking the screen (narrow): from a margin below the top to one above the bottom, clear of any
   notch or home bar (--times-top, --times-h: see placeTimes) */
.times-cover .times-view {
  top: calc(var(--times-top, 0px) + env(safe-area-inset-top));
  height: calc(var(--times-h, 100%) - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  transition: transform .6s var(--set-off), opacity .45s var(--ease), translate .45s var(--set-off); /* (translate: moved down under the grid's trailer, docked at the top: see .screen) */
}
/* in the grid, a crop of the film's poster behind its name (cards.js's timesCrop): from the right,
   zoomed to its top (where faces mostly are), fading off to the left so the name reads, and down,
   across its days, to the line under them; behind it all. Beside the grid, over the room left above
   the name (leadTimes). Not over a seat map, your shortlist's times, nor a film pointed at */
.times-crop { display: none; }
.grid-mode .times-view { isolation: isolate; }
.grid-mode .times-crop {
  display: block; position: absolute; z-index: -1; pointer-events: none; /* (out to the screen's edges: cards.js's fitCrop) */
  top: calc(-1 * var(--crop-t, 0px)); right: calc(-1 * var(--crop-r, 0px)); width: calc(100% + var(--crop-r, 0px)); height: calc(var(--crop-h, 170px) + var(--crop-t, 0px)); /* (to the line under the days) */
  /* (across the panel's whole width, beside the grid or taking the screen: gone by its left edge, so it fades more gently under the name) */
  background: var(--crop, none) center 20% / cover no-repeat; opacity: 0.9; transition: opacity .3s var(--ease);
  -webkit-mask-image: linear-gradient(to left, #000 35%, transparent), linear-gradient(to top, transparent, #000 62%); -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to left, #000 35%, transparent), linear-gradient(to top, transparent, #000 62%); mask-composite: intersect;
}
.grid-mode .times-view:is(.seat-mode, .list-mode) .times-crop { opacity: 0; }
.times-body > .st-head { margin-top: var(--times-lead, 0px); } /* (beside the grid: its days' line level with the grid's first heading's) */
/* the film's buttons over it frosted, so they read over any poster: a dark glass behind them */
.times-cover :is(.times-trailer, .times-save) { background: rgba(12, 11, 14, 0.55); border-color: rgba(255, 255, 255, 0.18); -webkit-backdrop-filter: var(--frost); backdrop-filter: var(--frost); }
@media (hover: hover) { .times-cover :is(.times-trailer, .times-save):hover { background: rgba(40, 38, 46, 0.7); } }
/* beside the grid too, over the crop: the bookmark and the × (a film's, its times on show) */
.table.grid-mode:not(.times-cover) .times-view:not(.seat-mode, .list-mode, .info-mode) :is(.times-save, .times-close) { background: rgba(12, 11, 14, 0.55); -webkit-backdrop-filter: var(--frost); backdrop-filter: var(--frost); }
@media (hover: hover) { .table.grid-mode:not(.times-cover) .times-view:not(.seat-mode, .list-mode, .info-mode) :is(.times-save, .times-close):hover { background: rgba(40, 38, 46, 0.7); } }
/* two pages side by side: the times, then a show's seat map, sliding across */
/* they reach 10px past each side, padded back in, so a time's highlight isn't clipped at the edge */
.times-pages { position: relative; flex: 1; min-height: 0; display: flex; overflow: clip; margin: 0 -10px; will-change: transform, opacity; } /* clip: can't be scrolled sideways, e.g. by focus; will-change: turned like a page (pageTimes; see .ambient img's will-change) */
.times-body {
  position: relative; /* for the touch screens' bounce, below */
  will-change: transform; /* slides aside for a seat map (see .ambient img's will-change) */
  flex: 0 0 100%; min-width: 0; /* exactly the view's width, whatever's inside */
  overflow-y: auto; scrollbar-width: none;
  padding: 6px 12px 48px; /* room to scroll the last row clear of the fade */
  display: grid; align-content: start; gap: 20px;
  grid-auto-rows: max-content; /* each part its full height, even when the list overflows */
  transition: transform .45s var(--set-off); /* a seat map slides in, the times out: a big move from rest */
  /* fades out at the bottom, so it's clear there's more to scroll to */
  -webkit-mask-image: linear-gradient(#000 calc(100% - 48px), transparent);
  mask-image: linear-gradient(#000 calc(100% - 48px), transparent);
}
.times-body::-webkit-scrollbar { display: none; }
/* the showtimes' page (a film's, or your shortlist's): its head stays, its name, scores and days
   (.st-head), and the rest scrolls under it (.st-scroll: cards.js's layTimes), so another day's a
   tap away however far down, and nothing passes under the panel's buttons; scrolled, the times
   fade out under the days. (The seat page scrolls whole, as before.) */
.times-body:not(.seat-page) { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 0; -webkit-mask-image: none; mask-image: none; }
.st-head { flex: none; display: grid; gap: 20px; }
.st-scroll {
  position: relative; flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none;
  margin: 0 -12px; padding: 0 12px 48px; /* (the page's sides, for a time's highlight; room to scroll the last row clear of the fade) */
  display: grid; align-content: start; gap: 20px; grid-auto-rows: max-content;
  --fade-end: 48px;
  -webkit-mask-image: linear-gradient(#000 calc(100% - var(--fade-end)), transparent);
  mask-image: linear-gradient(#000 calc(100% - var(--fade-end)), transparent);
}
.st-scroll.scrolled {
  -webkit-mask-image: linear-gradient(transparent, #000 20px, #000 calc(100% - var(--fade-end)), transparent);
  mask-image: linear-gradient(transparent, #000 20px, #000 calc(100% - var(--fade-end)), transparent);
}
.st-scroll::-webkit-scrollbar { display: none; }
/* on a touch screen, a short list still moves under your finger and springs back, like a phone's
   own lists: Safari only bounces what overflows, so it's always a pixel taller than its box */
@media (pointer: coarse) {
  :is(.times-body, .st-scroll)::before { content: ""; position: absolute; top: 0; left: 0; width: 1px; height: calc(100% + 1px); pointer-events: none; }
}
.seat-mode .times-body { transform: translateX(-100%); }
.times-view.jump .times-body { transition: none; } /* turning to another film's times (cards.js) */
/* round icon buttons (close ×), their icons drawn as lines so they sit dead centre */
.times-close, .trailer-close {
  display: grid; place-items: center; padding: 0; width: 34px; height: 34px; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.16); background: rgba(255, 255, 255, 0.05); color: var(--ink-soft);
  transition: background .2s, color .2s, transform .2s var(--ease);
}
@media (hover: hover) { .times-close:hover, .trailer-close:hover { background: rgba(255, 255, 255, 0.14); color: var(--ink); } }
.icon-back.icon-forward { transform: rotate(-135deg); margin: 0 3px 0 0; } /* the back chevron, turned to point right */
.times-close { position: absolute; top: calc(6px + (1.5rem * 1.1 - 34px) / 2); right: 0; z-index: 1; } /* centred on the title's line (the times' 6px top padding, then its 1.5rem × 1.1 line) */
.icon-close { position: relative; width: 14px; height: 14px; }
.icon-close::before, .icon-close::after {
  content: ""; position: absolute; left: 0; top: calc(50% - 0.8px); width: 100%; height: 1.6px;
  border-radius: 1px; background: currentColor; transform: rotate(45deg);
}
.icon-close::after { transform: rotate(-45deg); }
.icon-back { /* a chevron, nudged right so it looks centred */
  width: 8px; height: 8px; margin-left: 3px;
  border-left: 1.7px solid currentColor; border-bottom: 1.7px solid currentColor; transform: rotate(45deg);
}
/* open: a ring around Showtimes (it's always filled) */
.deck-action[aria-expanded="true"] {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 3.5px color-mix(in srgb, var(--accent) 80%, transparent), 0 8px 24px -10px color-mix(in srgb, var(--accent) 70%, transparent);
}

.st-title { margin: 0; font-size: 1.5rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; }
/* the film's name flows round the panel's buttons at the top right (a float as wide as they are,
   --title-room): its first line beside them, the rest the panel's whole width, so a long name
   never has to move under them; the trailer's mark before it (.st-play) floated too, cleared */
.times-body .st-title::before { content: ""; float: right; width: var(--title-room, 0px); height: 30px; margin-left: min(10px, var(--title-room, 0px)); }
.times-body .st-title::after { content: ""; display: block; clear: both; }
/* the trailer's button, leading the name: YouTube's mark, the name's height, to tap (cards.js's
   playMark); lit in the accent while it plays */
.st-play {
  float: left; display: grid; place-items: center; width: 36px; height: calc(1.5rem * 1.1); margin: 0 7px 0 -4px; padding: 0;
  border: 0; border-radius: 7px; background: none; cursor: pointer; transition: background .2s, box-shadow .2s;
}
.st-play .yt { width: 28px; height: 20px; transition: transform .2s var(--ease); }
@media (hover: hover) { .st-play:hover { background: rgba(255, 255, 255, 0.08); } .st-play:hover .yt { transform: scale(1.08); } }
.st-play:active .yt { transform: scale(0.94); transition-duration: .06s; }
.playing .st-play { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--accent) 70%, transparent); }
@media (prefers-reduced-motion: reduce) { .st-play, .st-play .yt { transition: none; } .st-play:hover .yt, .st-play:active .yt { transform: none; } }

/* the days as a strip, a short name over the day of the month ("Tmrw" over "15"), sharing the
   width: a week listed fits across a phone with nothing out of sight. (A row of "Fri 16 Oct"s
   ran past the edge from the fifth day on.) */
.st-days { display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none; box-shadow: inset 0 -1px rgba(255, 255, 255, 0.08); } /* (its hairline drawn inside it, so the chosen day's line lies over it: a border's outside what a scroll shows, and cut a day's line to half) */
.st-days::-webkit-scrollbar { display: none; }
/* more than a week of days (cards.js's filterTimes): a week across, the rest a scroll along, each
   snapping whole into place; faded at the end, so it's seen there are more */
.st-days.week-plus { scroll-snap-type: x proximity; mask-image: linear-gradient(to right, #000 calc(100% - var(--pick-fade, 28px)), transparent); }
.st-days.week-plus.at-end { mask-image: none; }
.st-days.week-plus.off-start { mask-image: linear-gradient(to right, transparent, #000 var(--pick-fade, 28px), #000 calc(100% - var(--pick-fade, 28px)), transparent); }
.st-days.week-plus.off-start.at-end { mask-image: linear-gradient(to right, transparent, #000 var(--pick-fade, 28px)); }
.st-days.week-plus > .st-day { scroll-snap-align: start; }
.st-day {
  flex: 0 0 calc((100% - 6 * 4px) / 7); min-width: max-content; cursor: pointer; padding: 4px 3px 9px; /* (a seventh each, however many: every film's days in the same places; each at least its name's width: TONIGHT's wider than the rest, and squeezed to theirs it ran into TMRW) */
  display: grid; justify-items: center; gap: 1px;
  border: 0; border-bottom: 2px solid transparent; background: none;
  color: var(--ink-faint); font-weight: 600;
  transition: color .2s, border-color .2s;
}
.st-day-name { font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase; }
.st-day-num { font-size: 1.1rem; line-height: 1.2; font-variant-numeric: tabular-nums; }
.st-days.said { display: none; } /* (a search's one day: said in the line under them instead, cards.js's filterTimes) */
.st-day[aria-disabled="true"] { opacity: 0.3; cursor: default; pointer-events: none; } /* a day with no shows at the cinema chosen (cards.js's filterTimes): there, greyed, not to be gone to */
.st-days.single .st-day { cursor: default; pointer-events: none; } /* the only day: a label, nothing to switch to (in its place, as the first of several is) */
@media (hover: hover) { .st-day:hover { color: var(--ink); } }
.st-day[aria-selected="true"] { color: var(--ink); border-image: var(--accent-grad) 1; border-bottom-color: var(--accent); }
.st-panel { display: grid; animation: fade .3s var(--ease); }
/* each format in bold, then its times, one to a row */
.st-row { display: grid; gap: 6px; padding: 10px 0 1px; border-top: 1px solid rgba(255, 255, 255, 0.07); } /* (1px under: the last time has its own 9px under it, for its highlight, so it's as far above the next line as the heading's below its own) */
.st-cinema-name + .st-row { border-top: 0; padding-top: 4px; }
/* each cinema's showtimes under its name, with more than one cinema picked; with one, no names */
.st-cinema-name {
  margin: 0 0 6px; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-soft); /* (a label, as the grid's headings are; the gold's for what the film is) */
}
.one-cinema .st-cinema-name { display: none; }
.st-chain-word { font-weight: 500; color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.04em; } /* its chain before its name, lighter, in capitals: "VOX MOE", "REEL DUBAI MALL" (your shortlist's) */
/* a chain's mark (cards.js's chainMark), where a show says its cinema with several picked: its whole
   wordmark, large and faint, white at 5%, behind what's there (which all paints over it), from where
   the cinema's name starts, so the marks make a column under the names. The logo's just its shape
   (a mask), as wide as its height has it, kept whole if it has less room (drawn smaller). Only for
   the eye: it never takes a click */
.chain-mark {
  position: absolute; z-index: -1; left: 0; top: 50%; translate: 0 -50%; aspect-ratio: var(--mark-ratio); max-width: 100%;
  background: rgba(255, 255, 255, 0.05); pointer-events: none;
  -webkit-mask: var(--mark) left center / contain no-repeat;
  mask: var(--mark) left center / contain no-repeat;
}
.one-cinema .chain-mark { display: none; } /* (one cinema: no cinema said, no chain either) */
.st-cinema:not([hidden]) ~ .st-cinema:not([hidden], .st-one) { margin-top: 4px; padding-top: 14px; border-top: 1px solid rgba(255, 255, 255, 0.14); }
.st-format { display: flex; align-items: center; margin: 0; } /* (its room's badge) */
/* a room's badge (cards.html's formatName): every room's one height, 18px, wherever it's said (a
   room's heading, a film's time's line, the preview, your shortlist, the seat page), only its width
   its own. A name in a hairline, softly; IMAX its logo, white on its blue; 4DX, Dolby Cinema and
   ScreenX theirs, white on black */
.room-badge {
  display: inline-flex; align-items: center; flex: none; box-sizing: border-box; height: 18px; padding: 0 6px; border-radius: 5px;
  vertical-align: middle; white-space: nowrap; font-size: 10.5px; font-weight: 600; line-height: 1; letter-spacing: 0.02em;
  color: var(--ink-soft); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18);
}
.room-badge > span:not(.sr-only) { display: inline-flex; align-items: center; }
.room-badge-imax { background: #0071cd; box-shadow: none; }
.room-badge-logo { background: #000; color: #fff; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2); }
/* THEATRE PODS: IMAX | THEATRE, one badge in two, THEATRE's seats within the IMAX show */
.room-pair { display: inline-flex; flex: none; vertical-align: middle; }
.room-pair > .room-badge:first-child { border-radius: 5px 0 0 5px; }
.room-pair > .room-badge:last-child { border-radius: 0 5px 5px 0; }
/* THEATRE, our own take on VOX's mark (it has no logo file): its geometric capitals, spaced, with
   the "EAT" (a dine-in cinema) stressed: semi-bold and a little brighter than the rest (halfway
   to white from the text's colour: on a chosen time, a lighter purple). A device's own geometric
   face: Avenir Next (Apple), Futura, Century Gothic (Windows); else the site's. (span.theatre: so a
   bold line it's in, as the seat page's, doesn't make its EAT bolder) */
.theatre { font-family: "Avenir Next", "Futura", "Century Gothic", "Inter", sans-serif; font-weight: 400; letter-spacing: 0.1em; }
span.theatre b { font-weight: 600; color: color-mix(in srgb, currentColor 50%, var(--ink)); }
.room-badge .theatre { font-size: 0.952em; font-weight: 500; letter-spacing: 0.12em; margin-right: -0.12em; } /* (no space after its last letter) */
/* (its capitals' box just their capitals, so they sit in the badge's middle: all capitals, the
   line's box had them high) */
.room-badge .theatre { text-box: trim-both cap alphabetic; }
/* the IMAX logo in place of the word: its blue made white, on the badge's blue */
.imax-logo { display: block; height: 0.724em; width: auto; filter: brightness(0) invert(1); }
/* Dolby Cinema's one-line logo (1897 × 252, its "y" below the line: lowered a little), in the
   text's colour: the image is just its shape (a mask). Each logo's mask is drawn to its box, which
   has its shape ("contain" drew them a few % big or small at some fractional x in Chrome, clipping
   Dolby's "a") */
.dolby-logo {
  display: inline-block; height: 1em; width: calc(1em * 1897 / 252); translate: 0 0.095em; background: currentColor;
  -webkit-mask: url("/static/dolby-cinema.svg") left center / 100% 100% no-repeat;
  mask: url("/static/dolby-cinema.svg") left center / 100% 100% no-repeat;
}
/* ScreenX's logo (227.6 × 32.3, all capitals: as tall as the text's) and 4DX's (1000 × 399.5, its X
   above the 4D: a little taller), in the text's colour, as Dolby's */
.screenx-logo, .fourdx-logo { display: inline-block; background: currentColor; }
.screenx-logo {
  height: 0.705em; width: calc(0.705em * 227.63 / 32.32);
  -webkit-mask: url("/static/screenx.svg") left center / 100% 100% no-repeat;
  mask: url("/static/screenx.svg") left center / 100% 100% no-repeat;
}
.fourdx-logo {
  height: 1.048em; width: calc(1.048em * 1000 / 399.48);
  -webkit-mask: url("/static/4dx.svg") left center / 100% 100% no-repeat;
  mask: url("/static/4dx.svg") left center / 100% 100% no-repeat;
}
.st-times { display: grid; font-variant-numeric: tabular-nums; }
/* under the days, where the film's on that day (its cinemas' chips: after the where row's, whose look
   they share), and what a time's for. Neither: nothing */
.st-bar { display: grid; gap: 10px; margin-top: -8px; }
.st-bar:empty { display: none; }
.st-from + .st-bar { margin-top: -2px; } /* (under the line saying a search's: clear of it) */
/* a film's times: a row a time, no headings, each on one line, as a ledger: its dot, its time (right-aligned
   in a column of its own, so the colons line up), its cinema with several picked ("MOE", its chain's
   mark behind it), then its room's badge, flush right in a column of its own (each its own cinema and room: cards.js's
   flatten). No end time and no how soon on the rows: the seat page has its end, and how soon shows
   pointed at (.st-when-shown); both are still read out */
.st-one .st-row { padding: 0; border: 0; gap: 0; }
.st-one, .st-one :is(.st-row, .st-times) { min-width: 0; } /* (the panel's width, not their content's: the cinema gives way) */
.st-one .st-format { display: none; } /* (there for what reads a time's format: said in its row) */
.st-one:not([hidden]) ~ .st-one .st-time { background-image: var(--row-line); } /* (a line between, as between a room's times) */
/* the row a grid: its time (.st-clock) in the time column, right-aligned so the colons line up;
   "when" is kept for a countdown, empty for now */
.st-one .st-time {
  display: grid; grid-template-columns: [dot] 16px [time] 4.5em [gap] 9px [where] minmax(0, 1fr) [screens] auto [when] auto [badge] auto;
  position: relative; isolation: isolate; gap: 0; padding-block: 11px; white-space: nowrap; text-align: end;
}
.st-one .st-time > * { grid-row: 1; text-align: start; }
.st-one .st-dot { grid-column: dot; width: 7px; height: 7px; }
.st-one .st-clock { grid-column: time; text-align: end; }
.st-one .st-where { display: contents; font-size: 0.8rem; line-height: 18px; color: var(--ink-faint); } /* (its room's badge's height) */
/* its cinema: short of room, its name gives way, with an "…" (the badge stays). Brighter than the
   rest of the line, as its chain's mark is behind it: 70% (60% fell to 3.9:1 over a mark on a light
   teal backdrop; 70%, 4.6:1) */
.st-where-cinema { grid-row: 1; grid-column: where; display: flex; align-items: center; min-width: 0; overflow: hidden; color: rgba(244, 241, 234, 0.7); }
.st-where-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.one-cinema .st-where-cinema { display: none; }
/* on a phone, a cinema's chip pressed in a film's times: it says where, so its times don't each say
   it again, nor show its chain behind them, as with one cinema (cards.js's filterTimes) */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .one-picked :is(.st-where-cinema, .st-time > .chain-mark) { display: none; }
}
.st-where > :is(.room-badge, .room-pair) { grid-row: 1; grid-column: badge; justify-self: end; margin-left: 10px; }
/* its chain's mark: across, from the cinema's column up to the badge's (the mark's box: from the
   name's left edge, and a long one drawn smaller rather than under the badge); down, the row's
   whole height (no row given: its top to its foot, its padding too), × 0.72 */
.st-one .st-time > .chain-mark { grid-column: where / badge; grid-row: auto; height: 72%; }
/* (its end and how soon: read out with its time but not shown, .sr-only's; either, shown, would go in "when") */
/* how soon, shown pointed at (cards.js's markTimes: .st-when-shown): no room of its own (kept, it
   cut the cinemas' names short in a narrow panel), but over the end of the cinema's, by its badge,
   the name fading out under it there, on the row pointed at alone; nothing moves. Nothing to point
   with: not shown (its dot, the key say soon) */
.st-one .st-time > .st-when-shown { grid-column: where / badge; grid-row: 1; justify-self: end; position: relative; z-index: 1; padding-right: 2px; font-size: 0.82rem; color: var(--ink-soft); }
@media (hover: hover) {
  .st-one .st-time > .st-when-shown { opacity: 0; translate: -4px 0; transition: opacity .2s var(--ease), translate .3s var(--ease); }
  .st-one .st-time:hover > .st-when-shown { opacity: 1; translate: none; }
  .st-one .st-time .st-where-cinema {
    display: block; width: 100%;
    -webkit-mask: linear-gradient(to left, transparent 84px, #000 104px) right -104px top 0 / calc(100% + 104px) 100% no-repeat;
    mask: linear-gradient(to left, transparent 84px, #000 104px) right -104px top 0 / calc(100% + 104px) 100% no-repeat;
    transition: -webkit-mask-position .25s var(--ease), mask-position .25s var(--ease);
  }
  .st-one .st-time:hover .st-where-cinema { -webkit-mask-position: right 0 top 0; mask-position: right 0 top 0; }
}
@media (hover: none) { .st-one .st-time > .st-when-shown { display: none; } }
/* a started show's (to the film's start: cards.js's startsIn) red, as its time is */
.st-one .st-time.now > .st-when-shown { color: var(--now); }
@media (hover: hover) and (prefers-reduced-motion: reduce) { .st-one .st-time > .st-when-shown { translate: none; transition: none; } }
/* a row: the time on the left, its countdown (if any) on the right; the whole row is the button */
.st-time {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px; margin: 0 -10px; width: calc(100% + 20px); /* its highlight reaches past the text */
  border: 0; border-radius: 8px; background: none; cursor: pointer; text-align: left;
  font: inherit; font-size: 0.98rem; color: rgba(244, 241, 234, 0.9);
  transition: background .15s, color .15s;
}
/* a line between rows: straight, over the text's width (not the row's light's, 10px out each side),
   not a shadow, which curled down round the row's rounded corners; so a row lit sets only its colour */
.st-time { --row-line: linear-gradient(rgba(255, 255, 255, 0.04) 0 0); background-size: calc(100% - 20px) 1px; background-position: 10px 0; background-repeat: no-repeat; }
.st-time + .st-time { background-image: var(--row-line); }
.st-time:focus-visible { background-color: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); outline-offset: -2px; } /* (the ring inside: the panel's edge would cut it) */
@media (hover: hover) { .st-time:hover { background-color: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); } }
.st-time.chosen { background-color: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); }
/* back from its seat map, the time it was: lit as it was, a moment, then fading (cards.js's showWhere) */
.st-time.was-here { animation: was-here 1.6s ease-out; }
@keyframes was-here { 0%, 35% { background-color: color-mix(in srgb, var(--accent) 20%, transparent); } }
/* a late show's moon (below); the dot keeps its place on every row, so the times line up */
.st-dot { position: relative; flex: none; width: 9px; height: 9px; border-radius: 50%; opacity: 0; pointer-events: none; }
/* (shown by opacity, not visibility: a visible dot in a hidden page, as under a seat map or a
   film's preview, would still take a click; and none takes one: it's the row's) */
.st-when { margin-left: auto; font-size: 0.82rem; color: var(--ink-soft); } /* how soon, as the grid's preview says it: "in 20 min", "trailers playing" */
/* a rough how soon, another day ("in 3 days"), in a chip, like Discord's timestamps: the plain ones are to the minute */
:is(.st-when, .st-when-shown) code {
  padding: 1px 5px; border-radius: 4px; background: rgba(255, 255, 255, 0.08);
  font: inherit; color: rgba(244, 241, 234, 0.72);
}
/* about when it lets out, after the start: quieter, so the starts still read down the list */
.st-end { margin-left: -4px; color: rgba(244, 241, 234, 0.55); font-size: 0.88rem; } /* (0.55: AA's 4.5:1 on the dark) */
.st-end, .st-when { white-space: nowrap; } /* each whole, never split over two lines */
@media (max-width: 420px) { /* a phone: a show just started has its end and its countdown too */
  .st-time { gap: 8px; }
  .st-end { margin-left: -3px; font-size: 0.8rem; }
  .st-when { font-size: 0.78rem; }
}
/* a show with its trailers playing (cards.js's markTimes: .now): its time red, glowing. The glow is
   drawn once, a layer of its own over the time (the same words, see-through, only their shadow seen),
   and only its opacity changes, so the graphics chip fades it without repainting a thing: an animated
   text-shadow repainted the row, and the blurred room under it, every frame (about half a core) */
.st-clock { position: relative; }
.st-time.now .st-clock { color: var(--now); }
.st-time.now .st-clock::after {
  content: attr(data-clock); position: absolute; inset: 0; pointer-events: none;
  color: transparent; text-shadow: 0 0 10px var(--now), 0 0 2px var(--now);
  opacity: 0; will-change: opacity; animation: clock-glow 1.8s ease-in-out infinite;
}
@keyframes clock-glow { 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .st-time.now .st-clock::after { animation: none; opacity: 0.6; } }
/* a late show (starting after midnight, or out at 1AM or later: funcs.go's lateNight): a crescent
   moon in its dot's place, quiet; so in the preview's */
:root { --moon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.5 14.6A8.5 8.5 0 0 1 9.4 3.5a8.5 8.5 0 1 0 11.1 11.1Z'/%3E%3C/svg%3E"); --moon-ink: #9fb3d9; }
.st-time[data-night] .st-dot {
  background: var(--moon-ink); box-shadow: none; border-radius: 0;
  -webkit-mask: var(--moon) center / contain no-repeat; mask: var(--moon) center / contain no-repeat;
  opacity: 1; scale: 1.35;
}
/* an early show (before 11AM: funcs.go's earlyBird): a sunrise, a half sun on the
   horizon, in the morning's warm colour, as the moon is. Off for now (the owner's, 24 Oct 2026; the
   moon stays): drawn only under html.sunrise, which nothing sets; the times keep data-early */
:root { --sunrise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.5 17a5.5 5.5 0 0 1 11 0Z'/%3E%3Cpath d='M2.5 19.5h19' stroke='black' stroke-width='1.9' stroke-linecap='round'/%3E%3Cpath d='M12 8.2V5.6M6.1 10.6 4.3 8.8M17.9 10.6l1.8-1.8M3.4 15.2H1.8M20.6 15.2h1.6' stroke='black' stroke-width='1.9' stroke-linecap='round'/%3E%3C/svg%3E"); --sunrise-ink: #e8c48a; }
html.sunrise .st-time[data-early] .st-dot {
  background: var(--sunrise-ink); box-shadow: none; border-radius: 0;
  -webkit-mask: var(--sunrise) center / contain no-repeat; mask: var(--sunrise) center / contain no-repeat;
  opacity: 1; scale: 1.5;
}
.st-one .st-time[data-night] .st-dot { scale: 1.55; } /* (a film's times' 7px dot: drawn about 11px, the sunrise 12px) */
html.sunrise .st-one .st-time[data-early] .st-dot { scale: 1.75; }
/* a show checked within the hour, how it suited your party: "Good seats" in the accent, the rest
   quieter */
.st-fit { margin-left: -3px; font-size: 0.8rem; color: var(--ink-faint); white-space: nowrap; }
.st-fit { display: none; } /* (for now the rows say how full a show is instead: .st-full; how it suits your party is still on its seat map) */
/* how full a show was when you checked it (cards.js's sayFull): a bar along the foot of its row, 3px
   up from it (clear of the line under it), as long as it was full of the row's width inside its
   padding (its text's), with rounded ends; its colour mixed in oklch from green, empty, through amber
   to red, full (so 58% and 63% differ a little), glowing as the tier scales' lit parts do. Sold out
   (100%), the whole width, red. Checked over an hour ago, the same bar faded, without its glow. No
   number on screen: the chip says it, read out only */
.st-time[data-full] {
  position: relative;
  --full-ink: color-mix(in oklch,
    color-mix(in oklch, var(--full-empty), var(--full-filling) clamp(0%, calc(var(--full) * 100% / var(--full-turn)), 100%)),
    var(--full-sold) clamp(0%, calc((var(--full) - var(--full-turn)) * 100% / (100 - var(--full-turn))), 100%));
}
.st-time[data-full]::after {
  content: ""; position: absolute; left: 10px; bottom: 3px; height: 3px; width: max(3px, calc((100% - 20px) * var(--full) / 100));
  border-radius: 99px; background: var(--full-ink); box-shadow: 0 0 8px color-mix(in srgb, var(--full-ink) 50%, transparent);
  transform-origin: left center; pointer-events: none;
}
.st-time.full-old::after { opacity: 0.38; box-shadow: none; } /* (the seats may have gone) */
/* the day's last row has no line under it: its own, faint, under its bar (the last time shown, in
   the last room shown, of the last cinema shown) */
.st-panel > .st-cinema:not(:has(~ .st-cinema:not([hidden]))) > .st-row:not(:has(~ .st-row:not([hidden]))) .st-time[data-full]:not(:has(~ .st-time:not([hidden])))::before {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: 3px; height: 1px; background: rgba(255, 255, 255, 0.08); pointer-events: none;
}
/* the first time it's shown, it grows in from the left (once: cards.js takes .full-new off after) */
.st-time.full-new::after { animation: full-grow .9s var(--set-off) .15s both; }
@keyframes full-grow { from { transform: scaleX(0); } }
/* the shortlist's time pills: along the pill's foot, inside its rounded corners, as long as it was
   full of the pill (an empty show's still a sliver: the corner would hide less) */
.list-film .st-time[data-full]::after {
  inset: 0; width: auto; height: auto; border-radius: inherit; box-shadow: none;
  background: linear-gradient(var(--full-ink), var(--full-ink)) left bottom / max(10px, calc(var(--full) * 1%)) 3px no-repeat;
}
.st-time[data-fit="good"] .st-fit { color: color-mix(in srgb, var(--accent) 85%, transparent); }

/* ——— A show's seat map, the second page ——— */
/* the head: "‹ Showtimes" (back) on the first line, beside the close button; then the show, as a
   ticket: its time with chevrons either side to step to the show before or after */
.seat-head { display: grid; justify-items: start; gap: 4px; }
.seat-back {
  display: inline-flex; align-items: center; gap: 8px; min-height: var(--back-h); margin-bottom: calc(var(--back-row) - var(--back-h)); padding: 0 4px 0 0;
  border: 0; background: none; cursor: pointer; color: var(--accent); font: inherit; font-size: 0.86rem; font-weight: 600;
}
.seat-back .icon-back { margin-left: 2px; }
/* back to the films: on a phone, where the showtimes have the screen, in place of the × (a phone's
   way back is at the top left) */
.times-back { display: none; align-self: flex-start; }
.times-cover .times-back { display: inline-flex; }
/* one back link in one place: it says where it goes, and the seat map's own goes */
.times-back .to-times, .seat-mode .times-back .to-films { display: none; }
.seat-mode .times-back .to-times { display: inline; }
.times-cover [data-seat-back] { display: none; }
.times-cover .times-close { display: none; }
@media (hover: hover) { .seat-back:hover { color: var(--ink); } }
/* the show as a ticket (cards.js's sayTicket): glass, a crop of the film's poster down its left;
   the film, its time and where in the middle; the day on a stub at its right, torn off along a
   dashed line, a notch cut out of the card's top and bottom there (as far in from the right as
   the stub's wide, --stub-w: measured) */
.seat-ticket {
  justify-self: stretch; display: grid; grid-template-columns: 58px minmax(0, 1fr) auto;
  grid-template-rows: minmax(6px, 1fr) auto auto auto minmax(8px, 1fr); row-gap: 4px; /* (the middle's 10px over it and 12px under, and in the middle of the card's height) */
  border-radius: 14px; background: rgba(255, 255, 255, 0.05); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  --notch-at: right calc(var(--stub-w, 68px) - 0.75px);
  -webkit-mask: radial-gradient(circle 8px at var(--notch-at) top 0, transparent 7.5px, #000 8px), radial-gradient(circle 8px at var(--notch-at) bottom 0, transparent 7.5px, #000 8px);
  -webkit-mask-composite: source-in;
  mask: radial-gradient(circle 8px at var(--notch-at) top 0, transparent 7.5px, #000 8px), radial-gradient(circle 8px at var(--notch-at) bottom 0, transparent 7.5px, #000 8px);
  mask-composite: intersect;
}
.seat-ticket-poster { grid-column: 1; grid-row: 1 / -1; border-radius: 14px 0 0 14px; background: center / cover no-repeat; } /* (a crop, the card's height: not the poster's shape) */
.seat-ticket > :is(.seat-film, .seat-pick, .seat-when) { grid-column: 2; justify-self: center; }
.seat-film {
  grid-row: 2; margin: 0; padding-inline: 14px; text-align: center; text-wrap: balance; font-size: 1.05rem; font-weight: 700; line-height: 1.25; color: var(--ink);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; /* (three lines at most) */
}
.seat-film.longer { font-size: 0.92rem; } /* (over 22 letters: cards.js) */
.seat-film.longest { font-size: 0.84rem; } /* (over 34) */
.seat-film:focus { outline: none; } /* (focused only to be read on from, as the page opens) */
.seat-ticket > .seat-pick { grid-row: 3; margin: 0; }
/* where: the chain's mark, as a mask in the text's colour; the cinema; the room's badge */
.seat-when { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 7px; margin: 0; font-size: 0.82rem; color: rgba(244, 241, 234, 0.72); }
.seat-ticket > .seat-when { grid-row: 4; justify-content: center; padding-inline: 14px; color: var(--ink-soft); }
.seat-chain {
  flex: none; height: 11px; aspect-ratio: var(--mark-ratio); background: currentColor;
  -webkit-mask: var(--mark) center / contain no-repeat; mask: var(--mark) center / contain no-repeat;
}
/* the stub: the day as a word in the accent ("TODAY", "TONIGHT", "TOMORROW", else "SUN"), its
   number, its month */
.seat-day {
  grid-column: 3; grid-row: 1 / -1; min-width: 68px; margin: 0; padding: 10px 12px; border-left: 1.5px dashed rgba(255, 255, 255, 0.2);
  display: grid; align-content: center; justify-items: center; gap: 4px; line-height: 1;
}
.seat-day-word { margin-right: -0.12em; font-size: 0.62rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); } /* (no space after its last letter: centred) */
.seat-day b { font-size: 1.7rem; font-weight: 800; letter-spacing: -0.02em; color: var(--ink); font-variant-numeric: tabular-nums; }
.seat-day-month { margin-right: -0.12em; font-size: 0.6rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); }
.seat-pick { display: flex; align-items: center; gap: 2px; margin-left: -8px; }
.seat-time { margin: 0; min-width: 5.2ch; text-align: center; font-size: 1.6rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.seat-step { /* a quiet chevron in the time's colour */
  display: grid; place-items: center; width: 30px; height: 34px; padding: 0; border: 0; border-radius: 8px;
  background: none; color: rgba(244, 241, 234, 0.75); cursor: pointer; transition: background .15s, color .15s, opacity .2s, transform .2s var(--ease);
}
@media (hover: hover) { .seat-step:hover:not(:disabled) { background: rgba(255, 255, 255, 0.08); color: var(--ink); } }
.seat-step .icon-back { width: 10px; height: 10px; border-width: 2px; }
.seat-step:disabled { opacity: 0.2; cursor: default; } /* no earlier or later show that day */
/* under the time, how the show suits your party, and where they'd sit ("Good seats" / "F7–8");
   beside it, how many you are */
.seat-fit { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; margin-top: 4px; }
.seat-verdict { margin: 0; min-height: 2.6em; font-size: 0.86rem; line-height: 1.3; color: rgba(244, 241, 234, 0.6); transition: opacity .2s; }
.seat-verdict b { display: block; font-size: 0.95rem; font-weight: 700; color: var(--ink); }
.seat-verdict.fit-good b { color: var(--accent); }
.seat-also { display: block; margin-top: 2px; color: var(--ink-faint); } /* (a THEATRE's Group seat: sayFit) */
.seat-fit.loading .seat-verdict { opacity: 0.35; }
.seat-party {
  flex: none; display: inline-flex; align-items: center; padding: 2px; border-radius: 99px;
  border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(255, 255, 255, 0.04);
}
.seat-party-count { min-width: 3.4em; text-align: center; font-size: 0.82rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.seat-party-step {
  display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: rgba(244, 241, 234, 0.75); cursor: pointer; transition: background .15s, color .15s, opacity .2s, transform .2s var(--ease);
}
@media (hover: hover) { .seat-party-step:hover:not(:disabled) { background: rgba(255, 255, 255, 0.08); color: var(--ink); } }
.seat-party-step:disabled { opacity: 0.25; cursor: default; }
.icon-minus, .icon-plus { position: relative; width: 11px; height: 11px; }
.icon-minus::before, .icon-plus::before, .icon-plus::after {
  content: ""; position: absolute; left: 0; top: calc(50% - 0.8px); width: 100%; height: 1.6px; border-radius: 1px; background: currentColor;
}
.icon-plus::after { transform: rotate(90deg); }
.seat-full-head .seat-verdict { min-height: 0; margin-top: 4px; }
/* a Reel show: no seat map (the site asks only VOX), but in its place its seats left, as the
   listings had them, and when that was (cards.js's sayLeft) */
.seat-page.no-map :is(.seat-map, .seat-legend) { display: none; }
.seat-left { padding: 18px 18px 16px; border-radius: 12px; background: rgba(8, 8, 12, 0.42); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07); }
.seat-left-count { margin: 0; font-size: 0.95rem; font-weight: 600; color: var(--ink); }
.seat-left-count b { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; color: var(--accent); }
.seat-left-note { margin: 6px 0 0; font-size: 0.82rem; line-height: 1.4; color: rgba(244, 241, 234, 0.6); }
/* the seat map, drawn as SVG by seatmap.js: on a dark glass panel, tinted warm for THEATRE */
.seat-map {
  position: relative; min-height: 180px; padding: 14px 10px 16px; border-radius: 12px; overflow: hidden;
  background: rgba(8, 8, 12, 0.42); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
}
.seat-map-dining { background: rgba(28, 20, 14, 0.5); box-shadow: inset 0 0 0 1px rgba(255, 233, 196, 0.1); }
/* the usual look: straight on the page, no panel, in the cards' gold (not the controls' accent) */
.seat-map-standard { padding: 4px 0 0; background: none; box-shadow: none; border-radius: 0; overflow: visible; }
.seats-standard .seats-screen-word { fill: rgba(233, 207, 142, 0.6); letter-spacing: 0.4em; }
.seats-standard .seats-row { fill: rgba(233, 207, 142, 0.55); } /* (readable: see .seats-row) */
.seats-standard .seat { cursor: pointer; }
@media (hover: hover) { .seats-standard .seat:hover { opacity: 1; filter: brightness(1.18); } }
.seat-map:is(.loading, .stepping) { cursor: progress; }
/* checking a show's seats: no panel yet, just its place, kept (cards.js's roomHeights: as the room's
   map was last; a room not seen yet, about a room's shape), and in it, after a moment, the pill */
.seat-map.loading { width: 100%; min-height: 0; height: var(--room-h, auto); max-height: var(--room-h, 52svh); aspect-ratio: 8 / 5; background: none; box-shadow: none; }
/* the show stepped from, until this one's in: dimmed, greyed, a little blurred, out of reach (its
   seats' labels aren't this show's), its legend dimmed too */
.seat-map.stepping .seats-svg { opacity: 0.35; filter: saturate(0.4) blur(1px); pointer-events: none; transition: opacity .2s, filter .2s; }
.seat-map.stepping ~ .seat-legend, .seat-map.stepping .seat-edge { opacity: 0.35; transition: opacity .2s; }
/* zoomed in place, on an upright phone (cards.js's zoomSeats): the drawing wider than its box,
   scrolling sideways in it, its rows' letters pinned over each edge (drawn again there: its own
   hidden), shaded behind while there are seats under them */
.seat-map.zoomed { contain: inline-size; display: flex; align-items: flex-start; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; touch-action: pan-x pan-y; }
.seat-map.zoomed::-webkit-scrollbar { display: none; }
.seat-map.zoomed .seats-svg { flex: none; max-width: none; max-height: none; }
.seat-map.zoomed .seats-svg .seats-row { visibility: hidden; }
.seat-edge { flex: none; position: sticky; z-index: 1; transition: background .2s; }
.seat-edge:first-child { left: 0; }
.seats-svg + .seat-edge { right: 0; }
.seat-edge text { font-family: "Inter", system-ui, sans-serif; }
.seat-map.off-start .seat-edge:first-child { background: linear-gradient(to right, rgba(12, 11, 14, 0.7) 55%, transparent); }
.seat-map:not(.at-end) .seats-svg + .seat-edge { background: linear-gradient(to left, rgba(12, 11, 14, 0.7) 55%, transparent); }
/* the pill (cards.js's checkingSeats): dark glass, a ring turning in the accent's gradient */
.seat-busy {
  position: absolute; z-index: 2; left: 50%; top: 50%; translate: -50% -50%; margin: 0;
  display: flex; align-items: center; gap: 10px; padding: 8px 14px 8px 10px; border-radius: 99px; white-space: nowrap;
  background: rgba(12, 11, 14, 0.72); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1), 0 8px 24px rgba(0, 0, 0, 0.4);
  -webkit-backdrop-filter: var(--frost); backdrop-filter: var(--frost);
  font-size: 0.78rem; color: var(--ink-soft); animation: fade .2s var(--ease);
}
.seat-busy-ring {
  flex: none; width: 18px; height: 18px; border-radius: 50%; background: conic-gradient(transparent 0 25%, #6847d8 60%, var(--accent));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2px)); mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2px));
  animation: spin .8s linear infinite;
}
@keyframes spin { to { rotate: 1turn; } }
/* no seats to show: why, in the map's place, quietly (cards.js's sayProblem), the red just its mark;
   Try again, a chip, and a word that Book's still there */
.seat-map-problem { min-height: 0; display: grid; justify-items: start; gap: 12px; padding: 16px 18px 18px; }
.seat-problem { margin: 0; display: flex; gap: 10px; font-size: 0.88rem; line-height: 1.45; color: var(--ink-soft); }
.seat-problem::before {
  content: "!"; flex: none; display: grid; place-items: center; width: 18px; height: 18px; margin-top: 1px; border-radius: 50%;
  background: var(--now); color: #fff; font-size: 0.7rem; font-weight: 800; line-height: 1;
}
.seat-again {
  display: inline-flex; align-items: center; height: 34px; margin-left: 28px; padding: 0 14px; border: 0; border-radius: 10px; cursor: pointer;
  background: rgba(255, 255, 255, 0.05); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12); color: var(--ink); font: inherit; font-size: 0.8rem; font-weight: 600;
  transition: background .15s, transform .2s var(--ease);
}
@media (hover: hover) { .seat-again:hover { background: rgba(255, 255, 255, 0.1); } }
.seat-again:active { background: rgba(255, 255, 255, 0.14); transform: scale(0.96); }
.seat-problem-note { margin: 0 0 0 28px; font-size: 0.8rem; color: var(--ink-faint); }
/* the best seats together for your party: a soft tile under them, ringed */
.seats-best { fill: rgba(255, 255, 255, 0.1); stroke: rgba(255, 255, 255, 0.8); stroke-width: 1.4; animation: fade .3s var(--ease); }
.seats-svg { display: block; width: 100%; height: auto; max-height: 52svh; animation: fade .4s var(--ease); }
.seat-map .seats-svg { max-width: var(--most-w, none); margin-inline: auto; } /* (a small room's seats at most 28px apart: seatmap.js's MOST_PITCH; in the middle) */
.seats-svg text { font-family: "Inter", system-ui, sans-serif; }
.seats-screen-word { font-size: 7.5px; font-weight: 600; letter-spacing: 0.3em; fill: var(--ink-faint); }
.seats-zone { font-size: 7.5px; font-weight: 600; letter-spacing: 0.4em; opacity: 0.75; } /* a Reel room's area, over its rows: in its colour (seatmap.js) */
.seats-row { font-size: 9px; font-weight: 600; fill: rgba(244, 241, 234, 0.55); } /* (the rows' letters say where the seats are: readable, 4.5:1) */
.seats-pod { fill: rgba(255, 255, 255, 0.045); }
.seats-svg .seats-food { font-family: "Noto Emoji", sans-serif; font-size: 13.5px; fill: rgba(255, 255, 255, 0.19); }
.seat { transition: opacity .15s; }
@media (hover: hover) { .seat:hover { opacity: 0.8; } }
@font-face { font-family: "Noto Emoji"; src: url("/static/fonts/NotoEmoji-food.woff") format("woff"); font-display: swap; }

/* its legend: each area with its price, and taken */
.seat-legend { display: flex; align-items: center; gap: 6px 12px; margin-top: -8px; } /* (its text centred on the expand button, beside it however many lines it takes) */
.seat-legend .seats-legend-text { flex: 1 1 0; min-width: 0; }
.seats-price { font-weight: 500; color: rgba(244, 241, 234, 0.6); }
/* a line of text, like the showtimes, its keys spaced apart (every look's: THEATRE's and Kids' too) */
.seats-legend-text { margin: 0; display: flex; flex-wrap: wrap; align-items: center; column-gap: 18px; font-size: 0.86rem; line-height: 1.8; color: rgba(244, 241, 234, 0.85); }
.seats-key { white-space: nowrap; }
.seats-dot { display: inline-block; width: 9px; height: 9px; margin-right: 7px; border-radius: 50%; vertical-align: 0; }
.seats-dot.taken { box-shadow: inset 0 0 0 1.5px rgba(233, 207, 142, 0.35); }
.seats-wheelchair-key { width: 13px; height: 13px; margin-right: 6px; vertical-align: -2px; overflow: visible; }

/* the expand button, at the end of the legend's line (cards.js: on the map, it covered seats) */
.seat-expand {
  position: relative; margin-left: auto;
  display: grid; place-items: center; width: 30px; height: 30px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); background: rgba(12, 11, 14, 0.7); color: var(--accent);
  transition: background .2s, border-color .2s, transform .2s var(--ease);
}
@media (hover: hover) { .seat-expand:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); border-color: var(--accent); } }
.seat-expand:disabled { cursor: default; } /* (a show stepped to on its way: cards.js) */
.icon-expand { /* four corners, pointing out */
  width: 12px; height: 12px;
  --c: currentColor;
  background:
    linear-gradient(var(--c), var(--c)) 0 0 / 4.5px 1.6px, linear-gradient(var(--c), var(--c)) 0 0 / 1.6px 4.5px,
    linear-gradient(var(--c), var(--c)) 100% 0 / 4.5px 1.6px, linear-gradient(var(--c), var(--c)) 100% 0 / 1.6px 4.5px,
    linear-gradient(var(--c), var(--c)) 0 100% / 4.5px 1.6px, linear-gradient(var(--c), var(--c)) 0 100% / 1.6px 4.5px,
    linear-gradient(var(--c), var(--c)) 100% 100% / 4.5px 1.6px, linear-gradient(var(--c), var(--c)) 100% 100% / 1.6px 4.5px;
  background-repeat: no-repeat;
}
.seat-expand.zoomed .icon-expand { /* zoomed in place: the corners pointing in, to zoom back out */
  background-position: left 0 top 2.9px, left 2.9px top 0, right 0 top 2.9px, right 2.9px top 0, left 0 bottom 2.9px, left 2.9px bottom 0, right 0 bottom 2.9px, right 2.9px bottom 0;
}

/* the seat map, large */
.seat-full {
  width: min(1240px, 96vw); height: min(920px, 92svh); max-width: none; max-height: none;
  padding: 0; border: 0; border-radius: 22px; color: var(--ink);
  background: radial-gradient(100% 50% at 50% 0%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 60%), linear-gradient(rgba(17, 16, 24, 0.98), rgba(9, 9, 13, 0.99));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 25%, transparent), 0 50px 140px rgba(0, 0, 0, 0.85);
}
.seat-full[open] { display: flex; flex-direction: column; animation: rise .35s var(--ease); }
.seat-full::backdrop { background: rgba(4, 4, 6, 0.7); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.seat-full-head { position: relative; padding: 22px 26px 6px; padding-right: 70px; }
.seat-full-head .times-close { top: 20px; right: 22px; }
.seat-full-head .seat-time { min-width: 0; text-align: left; } /* no arrows here, so no need to centre it */
.seat-full-map { position: relative; flex: 1; min-height: 0; overflow: auto; padding: 8px 26px; display: grid; place-items: center; }
.seat-full-map .seats-svg { width: 100%; height: 100%; max-height: none; }
.seat-full-map.seat-map-dining { background: none; box-shadow: none; }
.seat-full-legend { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 26px 22px; }

/* a seat's label, over it on hover or tap: "E-6  Regular · 50 AED" (on the seat page, or the large view) */
.seat-page { position: relative; gap: 14px; } /* (closer than the times: a THEATRE's map and Book fit beside the cards at 1280×800) */
.seat-tip {
  position: absolute; z-index: 5; transform: translate(-50%, -100%); pointer-events: none; white-space: nowrap;
  padding: 6px 10px; border-radius: 8px;
  background: rgba(16, 15, 22, 0.96); box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent), 0 8px 24px rgba(0, 0, 0, 0.5);
  font-size: 0.78rem; color: rgba(244, 241, 234, 0.75);
}
.seat-tip b { color: var(--accent); font-weight: 700; }
.seat-status { margin: 0; font-size: 0.8rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; } /* under the map: when its seats were checked */
.seat-status:empty::before { content: "\200b"; } /* (a line's height, while they're checked: Book doesn't jump as it's said) */
.seat-status.problem { font-size: 0.86rem; color: var(--now); }
.seat-book {
  justify-self: start; padding: 11px 22px; border-radius: 99px; text-decoration: none;
  background: var(--accent-grad); color: var(--on-accent); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  box-shadow: 0 8px 24px -10px color-mix(in srgb, var(--accent) 70%, transparent);
  transition: filter .2s, transform .2s var(--ease);
}
@media (hover: hover) { .seat-book:hover { filter: brightness(1.1); } }
/* Book, and beside it Share: the same shape, in glass, as it's the lesser of the two */
.seat-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.seat-share {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 10px 18px 10px 15px; border-radius: 99px;
  border: 1px solid var(--pill-line); background: var(--pill-fill);
  color: var(--ink); font: inherit; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  transition: background .2s, border-color .2s, transform .2s var(--ease);
}
@media (hover: hover) { .seat-share:hover { background: var(--pill-fill-hover); border-color: var(--pill-line-hover); } }
.seat-share:active { background: rgba(255, 255, 255, 0.16); transform: scale(0.92); transition-duration: .06s; }
.icon-share { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.seat-note { margin: 0; font-size: 0.8rem; color: var(--ink-faint); }
.seat-guide { margin: 0; font-size: 0.8rem; line-height: 1.5; color: var(--ink-faint); } /* a Reel show: "Reel can't link to a show. On its page, pick Fri 16 · Dubai Marina Mall · Reel Standard · 10:40am" */
.seat-guide b { font-weight: 600; color: var(--ink); }
.seat-guide :is(b, span) { white-space: nowrap; } /* (each part whole: a line breaks only between them) */

.st-hint { margin: 0; color: var(--ink-faint); font-size: 0.8rem; }
@keyframes fade { from { opacity: 0; } }
/* just come (cards.js's arrive: a dialog opened, the page shown): its way in, and anything inside
   it, held at its start till its first frame's drawn, then played whole (in Safari it was most of
   the way through by then). And the whole page while it's laid out unseen (cards.html's
   laying-out): the films' deal was over before it was seen, in Safari */
.arriving, .arriving::backdrop, .arriving::before, .arriving::after,
.arriving *, .arriving *::before, .arriving *::after,
html.laying-out *, html.laying-out *::before, html.laying-out *::after { animation-play-state: paused !important; }

/* ——— Preferences: which films and showtimes are shown ——— */
.prefs-open { /* (first in the top left corner) */
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  padding: 9px 16px 9px 13px; border-radius: 99px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(12, 11, 14, 0.62); /* no blur behind: it'd be redone whenever the glow changes */
  color: var(--ink-soft); font-size: 0.8rem; font-weight: 600;
  transition: background .2s, color .2s, border-color .2s, transform .2s var(--ease), opacity .3s var(--ease), visibility 0s;
}
@media (hover: hover) { .prefs-open:hover { background: rgba(255, 255, 255, 0.1); color: var(--ink); border-color: rgba(255, 255, 255, 0.24); } }
/* (wide, and a phone on its side at any width: a quiet word with its icon, as When, Where and
   Sort's, a rounded rect when pointed at) */
@media (min-width: 778px), (orientation: landscape) and (max-height: 499px) {
  .corner-left .prefs-open { border-color: transparent; background: none; border-radius: 10px; padding: 9px 12px 9px 10px; }
  @media (hover: hover) { .corner-left .prefs-open:hover { background: rgba(255, 255, 255, 0.07); border-color: transparent; } }
  /* the grid squeezed to two columns (cards.js's placeGrid): just its icon, the search given the room */
  .two-cols .corner-left .prefs-open { padding: 9px 10px; }
  .two-cols .prefs-label { display: none; }
}
/* on a phone, upright, just its icon, round */
@media (max-width: 777px) and (orientation: portrait), (max-width: 777px) and (min-height: 500px) {
  .prefs-open { width: 40px; height: 40px; padding: 0; justify-content: center; }
  .prefs-label { display: none; }
}
/* the corner's buttons gone while the showtimes have the screen, whose back link is in the corner
   then */
body:has(.times-cover.showing-times) .corner-left { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s; }

/* ——— The search bar: the search, in the top row after the corner's buttons, out to the right
   edge (cards.js places it); filled, with its ×, while a search's results are shown. Pressed, the
   search opens with its field where the bar is (.from-bar), beside the films, nothing dimmed; on a
   phone, over them, as ever. ——— */
/* Taller than the buttons beside it (--bar-h, centred on their 40px), a rounded rectangle as
   the search is once it's open, its words the size of what's typed there; lit softly from within
   (the accent, a sheen from the top) to say it's there to use. */
.page-find {
  --bar-h: 50px;
  position: fixed; top: calc(max(18px, env(safe-area-inset-top)) - (var(--bar-h) - 40px) / 2); z-index: var(--z-corner); height: var(--bar-h);
  right: 20px; width: min(460px, calc(100vw - 440px)); /* (where it'll be, near enough, till cards.js places it: placeFindBar) */
  display: flex; align-items: center; border-radius: 15px; overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(12, 11, 14, 0.32); /* (thin: the page's glow, whatever its colour, through it; no blur behind, as the corner's buttons) */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), inset 0 0 22px rgba(169, 150, 255, 0.06);
  transition: background .2s, border-color .2s, box-shadow .2s, opacity .3s var(--ease), visibility 0s;
}
.page-find-open {
  flex: 1; min-width: 0; height: 100%; display: flex; align-items: center; gap: 12px; padding: 0 18px; border: 0; cursor: text;
  background: none; color: rgba(244, 241, 234, 0.62); font: inherit; font-size: 1.05rem; text-align: left; /* (the search's field's size) */
}
.page-find-open .icon-find { width: 16px; height: 16px; }
.page-find-words { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (hover: hover) {
  .page-find:not(.on):hover { border-color: rgba(255, 255, 255, 0.2); } /* (and its line reaches across: the search's light, below) */
  .page-find:not(.on):hover .page-find-open { color: var(--ink-soft); }
}
/* a search's results shown: the bar as the search had it, its chips as they were in its field (the
   same chip, find-token), what was typed after them, and how many films, faint; its × quiet, a
   grey round (to let go of it all: a chip's own × is the open search's) */
.page-find.on .page-find-open { padding-right: 6px; color: var(--ink); }
.page-find.on .page-find-words { display: flex; align-items: center; gap: 6px; min-width: 0; }
.page-find-words .find-token { flex: none; padding: 0 9px; } /* (no × of its own here) */
.page-find-typed { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-find-count { flex: none; margin-left: 4px; color: var(--ink-faint); font-size: 0.84rem; white-space: nowrap; }
@media (max-width: 777px) and (orientation: portrait), (max-width: 777px) and (min-height: 500px) {
  .page-find-count { display: none; } /* (on a phone, upright, the films are under it) */
  .page-find { right: 16px; width: calc(100vw - 128px); } /* (on a phone, till it's placed: after Preferences' and Sort's icons) */
}
.page-find-words.clipped { mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent); } /* (more than fit: fading out at its end, as the field's start does, cards.js) */
.page-find.on .page-find-clear { width: 28px; height: 28px; margin-right: 11px; background: rgba(255, 255, 255, 0.08); color: var(--ink-soft); }
@media (hover: hover) { .page-find.on .page-find-clear:hover { background: rgba(255, 255, 255, 0.16); color: var(--ink); } }
.page-find.narrow .page-find-open { justify-content: center; padding: 0; }
.page-find.narrow .page-find-words, .page-find.narrow .page-find-clear { display: none; }
body:has(.times-cover.showing-times) .page-find { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s; }
/* beside the films (a wide screen): the bar, opened. Its field is the bar, just where it is (as
   tall, as round, lit the same: placeFind), and the rest grows down from it, so it's the bar that
   opens, not another thing over it; over the right of the page, the films clear to see as they
   change under what's typed (no shade: it's not modal, cards.js's findLive). Closing, it draws
   back up into the bar. */
.find.from-bar {
  position: fixed; inset: 0 auto auto 0; z-index: var(--z-float); width: var(--find-w); margin: var(--find-top) 0 0 var(--find-left);
  border-radius: 14px; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2), 0 50px 140px rgba(0, 0, 0, 0.7); /* (its line outside it: the bar's 15px, outside to out; as bright as the bar's, pointed at) */
  transition: box-shadow .28s var(--set-off); /* (its shadow easing in as results first come under the bar, and out as they go: below) */
}
.find.from-bar[open] { animation: find-grow .28s var(--set-off), find-frost .28s var(--set-off); } /* (growing, the bar's thin glass frosting over, not at once) */
.find.from-bar.closing { animation: find-shrink .18s var(--leave) forwards; }
.find.from-bar .find-bar {
  --find-icon: 16px; /* (the bar's magnifier, and its glint's place) */
  height: var(--find-bar-h);
  background: rgba(255, 255, 255, 0.03); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07); /* (the bar's own band, as it was) */
}
.find.from-bar .find-input::placeholder { color: var(--ink-soft); } /* (the bar's words, as pointed at: it's opened from there) */
/* (the clip from the bar's own shape to all of it, and on past its edges, for its shadow) */
@keyframes find-grow { from { clip-path: inset(-1px -1px calc(100% - var(--find-bar-h) - 1px) -1px round 15px); } to { clip-path: inset(-160px round 15px); } }
@keyframes find-frost { from { background-color: rgba(12, 11, 14, 0.32); -webkit-backdrop-filter: blur(0) saturate(1); backdrop-filter: blur(0) saturate(1); } }
@keyframes find-shrink { from { clip-path: inset(-160px round 15px); } to { clip-path: inset(-1px -1px calc(100% - var(--find-bar-h) - 1px) -1px round 15px); } }
/* opened with nothing under the bar yet (roomy: its e.g. in the bar, nothing typed), it's only the
   bar: its edge, its shadow there but unseen. The clip growing and shrinking (as ever: the same
   animations either way, so typing restarts none) then shows nothing under the bar, where it showed
   the shadow alone, a dark slab sliding open and shut; the shadow eases in as results first come,
   and out as they go (the transition, above). */
.find.from-bar.roomy:not(:has(.find-results > *, .find-ideas:not([hidden]), .find-sum:not([hidden]), .find-foot:not([hidden]))) { box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2), 0 50px 140px transparent; }
@media (prefers-reduced-motion: reduce) { .find.from-bar { transition: none; } }
body:has(.find.from-bar[open]) .page-find { visibility: hidden; } /* (opened: it's the field now) */

/* ——— Find: the search itself, a panel from the bar (on a phone, at the top, clear of the
   keyboard: --find-room, from cards.js) ——— */
.icon-find { /* a magnifying glass (Lucide's search, ISC licence), in the words' colour */
  flex: none; width: 14px; height: 14px; background: currentColor;
  -webkit-mask: url("/static/icon-find.svg") center / contain no-repeat;
  mask: url("/static/icon-find.svg") center / contain no-repeat;
}

.find {
  /* lower down with room to spare; near the top when a keyboard leaves little (a tablet held
     sideways keeps ~330px): what's in sight is --find-room */
  --find-top: clamp(10px, calc((var(--find-room, 100svh) - 420px) / 2), 14svh);
  width: min(560px, calc(100vw - 24px)); max-width: none; margin: var(--find-top) auto auto; padding: 0; border: 0; border-radius: 18px;
  max-height: calc(var(--find-room, 100svh) - var(--find-top) - 24px); overflow: hidden;
  background: rgba(16, 15, 21, 0.74); color: var(--ink);
  backdrop-filter: blur(28px) saturate(1.6); -webkit-backdrop-filter: blur(28px) saturate(1.6); /* (the bar's glass, frosted: what's behind it in its colours, still read over; only while it's open) */
  box-shadow: var(--dialog-shadow);
}
.find[open] { display: flex; flex-direction: column; animation: find-in .3s var(--ease); }
.find::backdrop { background: rgba(4, 4, 6, 0.55); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.find[open]::backdrop { animation: fade .25s var(--ease); }
.find.closing { animation: find-out .18s var(--leave) forwards; }
.find.closing::backdrop { animation: fade-out .22s ease-in forwards; }
@keyframes find-in { from { opacity: 0; transform: translateY(-10px) scale(0.98); } }
@keyframes find-out { to { opacity: 0; transform: translateY(-10px) scale(0.98); } }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .find { --find-top: max(10px, env(safe-area-inset-top)); width: calc(100vw - 20px); border-radius: 16px; }
}
/* on a phone (upright, or on its side), the field wraps instead: every chip in sight on as many
   lines as they take (40px each, the first the bar's middle, as it was), what's typed after them,
   or on a line of its own; the magnifier and Cancel stay by the first. What's under it moves down
   a line as one's added, which on a phone is fine: the keyboard's up and there's no pointer over
   the list. */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .find:not(.from-bar) .find-bar { height: auto; min-height: 58px; align-items: flex-start; padding-block: 9px; }
  .find:not(.from-bar) .find-glint { top: calc(29px - var(--find-icon) * 0.68); } /* (its glint by it, the first line's middle: not the bar's) */
  .find:not(.from-bar) .find-field { height: auto; min-height: 40px; flex-wrap: wrap; column-gap: 6px; row-gap: 0; overflow: visible; }
  .find:not(.from-bar) .find-field.clipped { mask-image: none; }
  .find:not(.from-bar) .find-tokens { display: contents; }
  .find:not(.from-bar) .find-token { margin-block: 7px; max-width: 100%; }
  .find:not(.from-bar) .find-token-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .find:not(.from-bar) .find-input { height: 40px; }
  /* the magnifier and Cancel by the first line, their room kept on it only (the field's ::before;
     Cancel's, cards.js's fitCancel: a spacer after that line's last chip), so the lines under it
     have the bar's whole width, out to 16px from its edge; each where it was, Cancel 44px tall */
  .find:not(.from-bar) .find-bar { padding-right: 16px; }
  .find:not(.from-bar) .find-bar > .icon-find { position: absolute; left: 18px; top: 22px; margin: 0; }
  .find:not(.from-bar) .find-field::before { content: ""; flex: none; width: calc(var(--find-icon) + 6px); height: 40px; } /* (+ the field's 6px gap: the bar's 12 by it, as it was) */
  .find:not(.from-bar) .find-cancel { position: absolute; top: 7px; right: 10px; height: 44px; margin: 0; }
  .find:not(.from-bar) .find-cancel-room { flex: none; height: 40px; }
}
/* the field, with any chips before what's typed, on one line that scrolls sideways as they add
   up: the panel never grows taller with them, so what's under it stays where it was */
.find-bar { --find-icon: 14px; position: relative; flex: none; display: flex; align-items: center; gap: 12px; height: 58px; padding: 0 18px; color: var(--ink-faint); }
.find-bar .icon-find { width: var(--find-icon); height: var(--find-icon); }
.find-field {
  flex: 1; min-width: 0; height: 100%; display: flex; align-items: center; gap: 6px;
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
}
.find-field::-webkit-scrollbar { display: none; }
.find-field.clipped { mask-image: linear-gradient(to right, transparent, #000 22px); } /* (chips scrolled out at its start: cards.js's clipField) */
.find-tokens { flex: none; display: flex; gap: 6px; }
.find-tokens:empty { display: none; }
/* a chip: a rounded rectangle, as the field it's in is (8px, the field's 15px at its height), in the
   accent's tint (--find-chip: the e.g. line's understood parts wear it far fainter, see below) */
.find-token {
  display: inline-flex; align-items: center; gap: 2px; height: 26px; padding: 0 2px 0 9px; border-radius: 8px;
  background: var(--find-chip); color: var(--ink); font-size: 0.8rem; font-weight: 600; white-space: nowrap;
}
.find-token-x {
  display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px; cursor: pointer;
  background: none; color: var(--ink-soft);
}
.find-token-x .icon-close { width: 9px; height: 9px; }
@media (hover: hover) { .find-token-x:hover { background: rgba(255, 255, 255, 0.14); color: var(--ink); } }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) { .find-token-x { width: 30px; height: 30px; margin-right: -3px; } } /* (a finger's, over the chip's edges: nothing moves) */
.find-token.new { animation: token-in .3s var(--set-off); } /* (a chip just made, from what's typed or picked: seen to be) */
@keyframes token-in { from { transform: scale(0.6); opacity: 0; } 60% { transform: scale(1.05); } }
@media (prefers-reduced-motion: reduce) { .find-token.new { animation: none; } }
.find-input {
  flex: 1; min-width: 7em; height: 100%; padding: 0; border: 0; outline: none; background: none;
  color: var(--ink); font: inherit; font-size: 1.05rem; /* (16px or more: iOS zooms in on smaller) */
  -webkit-appearance: none; appearance: none;
}
.find-input::placeholder { color: var(--ink-faint); }
.find-input::-webkit-search-cancel-button { display: none; }
.find-cancel {
  flex: none; margin-right: -8px; padding: 8px; border: 0; background: none; cursor: pointer;
  color: var(--accent); font-size: 0.9rem; font-weight: 600;
}
@media (hover: hover) and (pointer: fine) { .find-cancel { display: none; } } /* (Escape, or a click outside) */
/* under the empty field, faintly, a search to try, in line with what's typed there; fading out
   and the next in (cards.js's turnTry) */
.find-try { flex: none; margin: -10px 0 0; padding: 0 20px 15px 44px; font-size: 0.8rem; color: var(--ink-faint); }
.find.from-bar .find-try { margin: 0; padding: 10px 20px 11px 46px; } /* (under the bar's band, not across its edge) */
/* the bar across the grid's column has room for it inside, at its end before esc, the field empty
   while it's there: so the search opened covers nothing under it (When, the panel's film) */
.find.from-bar.roomy .find-try { position: absolute; top: 0; right: 64px; height: calc(var(--find-bar-h) + 2px); display: flex; align-items: center; gap: 4px; padding: 0; }
.find-try-q {
  padding: 0; border: 0; background: none; cursor: pointer; font: inherit; color: var(--ink-soft);
  transition: opacity .3s var(--ease), color .2s;
}
.find-try-q.out { opacity: 0; }
@media (hover: hover) { .find-try-q:hover { color: var(--accent); } }
@media (prefers-reduced-motion: reduce) { .find-try-q { transition: none; } }
/* ——— The search's light: what says it's a search that understands, one accent light shared by
   the bar and the open search. A hairline of it at the bar's foot, breathing slowly; pointed at,
   it reaches across, lit. Opened, it stays so, as the line between the field and what's under it
   (on a phone, it dawns across the panel's top edge, clear of the e.g. line, which sits up in the
   field's foot there), and the magnifier's glint twinkles in, once; then nothing moves, while you
   type. The parts of the e.g. line that the search understands wear the chips' tint, far fainter;
   left a while, its searches are typed out with a caret of the light, their parts taking the tint
   one by one, as typed words become chips (cards.js's TRY_IDLE). With a keyboard, a key cap at the
   end: "/" on the bar, "esc" open. Only opacity and transform move; with less motion, all still. ——— */
:root {
  --find-light: linear-gradient(90deg, transparent, #9d88ff 30%, #6f8dff 62%, transparent); /* the accent's purple into blue, gone at its ends */
  --find-glow: 0 0 8px 0.5px rgba(140, 130, 255, 0.45);
  --find-shine: #c3b6ff; /* the light at its brightest: the glint, the caret */
  --find-chip: color-mix(in srgb, var(--accent) 22%, transparent); /* a chip's tint */
  --find-tint: color-mix(in srgb, var(--accent) 15%, transparent); /* the e.g. line's understood parts: a chip's, fainter, no chip's shape or weight */
  --find-breathe: 7s;  /* the bar's line, out or in */
  --find-dawn: .6s;    /* opened on a phone: the line across (the glint's in with it, everywhere) */
}
/* the line: centred under the words */
.page-find::after, .find.from-bar .find-bar::after, .find:not(.from-bar)::after, html.page-scroll .find:not(.from-bar) .find-bar::after {
  content: ""; position: absolute; z-index: 1; height: 1px; pointer-events: none;
  background: var(--find-light); box-shadow: var(--find-glow);
}
.page-find::after {
  left: 12%; right: 12%; bottom: 0; transform-origin: 40% 50%; opacity: 0.55;
  animation: find-breathe var(--find-breathe) ease-in-out infinite alternate;
}
/* pointed at, it reaches across, lit (and opened, stays so: the bar's open is across already) */
@media (hover: hover) {
  .page-find::after { transition: left .45s var(--set-off), right .45s var(--set-off), opacity .3s; }
  .page-find:not(.on):hover::after { animation: none; left: 0; right: 0; opacity: 1; transform: none; }
}
.find.from-bar .find-bar::after { left: 0; right: 0; bottom: 0; }
.find:not(.from-bar)::after { left: 14%; right: 14%; top: 0; } /* (a phone's: the panel's rim) */
.find:not(.from-bar)[open]::after { animation: find-dawn var(--find-dawn) var(--set-off) both; } /* (a phone's dawns; the bar's is lit already) */
@keyframes find-breathe { from { opacity: 0.35; transform: scaleX(0.72); } to { opacity: 0.7; transform: none; } }
@keyframes find-dawn { from { opacity: 0; transform: scaleX(0.3); } }
/* the glint, open only: our own, four concave points and a small one below, in the empty corner
   at the glass's top right (over the magnifier's top right corner: --find-icon, the magnifier's
   size), in --find-shine, twinkling in as the line dawns. Each point turns and grows about its own
   middle, the small one a moment after the big (one picture of both, the small one swung round
   the big one's middle). Drawn afresh as it moves, not as a picture of it: so it ends where it
   rests, not a hop away (a picture's drawn at a fraction of a pixel, then snapped once it stops) */
.find-glint {
  position: absolute; pointer-events: none; overflow: visible;
  left: calc(18px + var(--find-icon) * 0.69); top: calc(50% - var(--find-icon) * 0.68);
  width: calc(var(--find-icon) * 0.45); height: calc(var(--find-icon) * 0.625);
  fill: var(--find-shine);
}
.find-glint path { transform-box: view-box; transform: rotate(0.01deg); opacity: 0.999; } /* (at rest a hair turned and a hair see-through, as it's drawn while it twinkles: plain, it's drawn another way, its edges half a pixel apart, a hop as it stops) */
.find-glint-big { transform-origin: 36px 38px; } /* (its middle, in the drawing's 72 × 100) */
.find-glint-small { transform-origin: 56px 82px; fill: color-mix(in srgb, var(--find-shine) 55%, transparent); } /* (fainter: in its colour, as its own see-through drew it a shade apart once still) */
.find[open] .find-glint-big { animation: find-twinkle .9s var(--set-off) .15s both; }
.find[open] .find-glint-small { animation: find-twinkle .8s var(--set-off) .32s both; }
@keyframes find-twinkle { from { opacity: 0; transform: scale(0.2) rotate(-90deg); } 55% { opacity: 0.999; transform: scale(1.25) rotate(8deg); } to { opacity: 0.999; transform: rotate(0.01deg); } }
/* the key caps: with a keyboard in reach (a wide screen, a mouse); not on the bar while it shows a
   search's chips, or as just its magnifier */
.find-key { display: none; }
@media (hover: hover) and (pointer: fine) and (min-width: 778px) {
  .find-key {
    flex: none; display: grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 6px;
    border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(255, 255, 255, 0.04); box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.06);
    color: var(--ink-faint); font-size: 0.72rem; font-weight: 500; line-height: 1; letter-spacing: 0.02em;
    transition: color .2s, border-color .2s;
  }
  .page-find .find-key { margin-left: auto; }
  .page-find.on .find-key, .page-find.narrow .find-key { display: none; }
  .page-find:not(.on):hover .find-key { color: var(--ink-soft); border-color: rgba(255, 255, 255, 0.2); }
  .find .find-key { margin-right: 0; } /* (its right edge the bar's "/"'s) */
}
/* the e.g. line's understood parts (cards.js's tryParts); pending, still to take it (typeTries);
   the caret, thin, of the light */
.find-try-k {
  padding: 0 0.28em; margin: 0 -0.06em; border-radius: 5px; background: var(--find-tint);
  -webkit-box-decoration-break: clone; box-decoration-break: clone; transition: background .5s var(--ease);
}
.find-try-k.pending { background: transparent; }
.find-try-caret { display: inline-block; width: 1.5px; height: 1em; margin: 0 1px; vertical-align: -0.14em; background: var(--find-shine); }
@media (prefers-reduced-motion: reduce) {
  .page-find::after, .find[open]::after, .find[open] .find-glint path { animation: none; }
  .find-try-k { transition: none; }
}
.find-results {
  /* min-height: 0 lets it shrink to the panel and scroll: without it, a flex item stays as tall as
     its results, cut off by the panel, with nothing to scroll (and a finger scrolled the page) */
  flex: 1 1 auto; min-height: 0;
  margin: 0; padding: 6px; list-style: none; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none;
  border-top: var(--rule);
}
.find-results::-webkit-scrollbar { display: none; }
.find-results:empty { display: none; }
/* a film found: its poster, small, as the grid's little cards; its name, and under it who matched
   or its next show; for one your preferences hide, what turning it on does */
.find-hit {
  display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; align-items: center; gap: 14px;
  padding: 7px 12px 7px 8px; border-radius: 10px; cursor: pointer;
}
.find-hit[aria-selected="true"] { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.find-hit:active:not(.touch-moved *) { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.find-art {
  display: block; width: 32px; aspect-ratio: 63 / 88; overflow: hidden; border-radius: 3px; background: #15131b;
  box-shadow: 0 0 0 1px rgba(255, 240, 200, 0.16);
}
.find-art img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 20%; }
.find-words { display: grid; gap: 2px; min-width: 0; }
.find-title, .find-note, .find-why { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.find-why { font-size: 0.76rem; color: color-mix(in srgb, var(--accent) 80%, transparent); } /* (left out by your shortlist: choosing it shows it) */
.find-title { font-size: 0.98rem; font-weight: 600; color: var(--ink); }
.find-note { font-size: 0.8rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.find-hit mark { background: none; color: var(--accent); }
.find-hit.hidden-film :is(.find-art, .find-title) { opacity: 0.55; }
/* what hides it, whole: on two lines if it needs them (on a phone, with who matched) */
.find-hit.hidden-film .find-note {
  white-space: normal; text-wrap: pretty;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
/* on a phone, who matched and the next show on two lines if it needs them (cut on one, the time went) */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .find-note { white-space: normal; text-wrap: pretty; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
}
/* the note (the site's one: what finding a hidden film changed, with Undo, a few seconds). It's
   kept off every control: centred just under the top corners, over the top of the cards or the
   grid (a heading, not a control), and taps beside Undo reach what's under it (the card's scores, a
   heading); while the showtimes have the screen (the corners gone), at the top right, in their
   place, between the back link and the bookmark there, wrapping if it must. Never at the foot,
   where the arrows and showtimes are. */
.undo-note {
  position: fixed; top: calc(max(18px, env(safe-area-inset-top)) + 52px); left: 50%; z-index: var(--z-float);
  width: max-content; max-width: calc(100vw - 32px); margin: 0; padding: 9px 16px; border-radius: 19px; /* (max-content: else, from the middle, it'd wrap at half the screen) */
  border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(12, 11, 14, 0.86);
  color: var(--ink-soft); font-size: 0.82rem; font-weight: 600; line-height: 18px; text-align: center; text-wrap: balance;
  --x: -50%; translate: var(--x) -6px; opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .3s var(--ease), translate .3s var(--ease), visibility 0s .3s;
}
.undo-note.shown { translate: var(--x) 0; opacity: 1; visibility: visible; transition: opacity .3s var(--ease), translate .3s var(--ease), visibility 0s; }
.undo-note .link { font-weight: 600; pointer-events: auto; outline-offset: 0; } /* (its ring kept clear of the "·" and the note's edge) */
body:has(.times-cover.showing-times) .undo-note {
  --x: 0; left: auto; right: 62px; top: max(16px, env(safe-area-inset-top)); max-width: calc(100vw - 170px); text-align: right;
}
.find-act { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); white-space: nowrap; }
/* how a search by what's on was taken, over its films ("IMAX · Tonight · 4 films"); or, bigger,
   that nothing matches */
.find-sum {
  margin: 0; padding: 9px 20px; border-top: var(--rule);
  font-size: 0.78rem; font-weight: 600; color: var(--ink-faint); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.find-sum.none { padding: 16px 20px 18px; font-size: 0.88rem; font-weight: 400; white-space: normal; }
.find-sum-hidden { font-weight: 500; opacity: 0.75; } /* ("+1 hidden by Preferences": not in the count, nor Show's) */
/* nothing found: in words, then its ways out, small pills, each saying what it'd find; one taking
   a typo for what it's nearly ("Did you mean Horror?") in the accent */
.find-none-head { display: block; margin: 0 0 10px; font-size: 0.92rem; font-weight: 650; color: var(--ink); text-wrap: pretty; }
.find-none-note { display: block; font-size: 0.8rem; color: var(--ink-faint); }
.find-ways, .empty-ways { display: flex; flex-wrap: wrap; gap: 8px; }
.find-way { display: inline-flex; align-items: center; gap: 7px; max-width: 100%; min-width: 0; }
.find-way > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.find-way-drop { flex: none; color: var(--ink-faint); font-weight: 500; }
.find-way-to { flex: none; color: var(--ink-faint); }
.find-way b { font-weight: 600; color: var(--ink); }
.find-way.mean { border-color: color-mix(in srgb, var(--accent) 55%, transparent); background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--ink); }
.find-way.mean b { color: var(--accent); }
/* (on a phone, a way out's words wrap rather than run out: "Drop IMAX → 14 films at Dubai Mall
   tomorrow late at night", on two lines, all of it said) */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .find-way:not(.mean) { flex-wrap: wrap; column-gap: 7px; row-gap: 0; height: auto; min-height: 38px; padding-block: 7px; border-radius: 19px; white-space: normal; text-align: left; line-height: 1.3; }
  .find-way:not(.mean) > b { overflow: visible; text-wrap: pretty; }
}
/* the ideas under the field: searches to try (with a line over them), or words to finish one
   with; a row of small pills, as the filter's, wrapping */
.find-ideas { flex: none; padding: 10px 16px 14px; border-top: var(--rule); }
.find-lead { margin: 2px 2px 10px; font-size: 0.8rem; color: var(--ink-faint); text-wrap: pretty; }
.find-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.find-chip {
  height: 34px; padding: 0 13px; border-radius: 99px; border: 1px solid rgba(255, 255, 255, 0.12); cursor: pointer;
  background: rgba(255, 255, 255, 0.04); color: var(--ink-soft); font: inherit; font-size: 0.84rem; font-weight: 600; white-space: nowrap;
  transition: background .2s, border-color .2s, color .2s, transform .2s var(--ease);
}
@media (hover: hover) { .find-chip:hover { background: rgba(255, 255, 255, 0.1); color: var(--ink); } }
.find-chip:active { transform: scale(0.94); transition-duration: .06s; }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) { .find-chip { height: 38px; } } /* (a finger's) */
/* the search's Show button, under its films, always in sight (the panel's foot): its results in
   the grid or the cards, as a filter that's on is filled */
.find-foot { flex: none; padding: 10px 12px 12px; border-top: var(--rule); }
.find-show {
  display: block; width: 100%; height: 44px; border: 0; border-radius: 12px; cursor: pointer;
  background: var(--accent-grad); color: var(--on-accent); font: inherit; font-size: 0.92rem; font-weight: 600;
  transition: filter .2s, transform .2s var(--ease);
}
@media (hover: hover) { .find-show:hover { filter: brightness(1.12); } }
.find-show:active { transform: scale(0.98); transition-duration: .06s; }
.find-sum:not([hidden], .none) + .find-results { border-top: 0; padding-top: 0; } /* (the line over them is the sum's) */

.when-clear {
  display: grid; place-items: center; flex: none; width: 26px; height: 26px; margin-right: 6px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(255, 255, 255, 0.18); color: var(--on-accent); transition: background .2s, transform .2s var(--ease);
}
.when-clear .icon-close { width: 10px; height: 10px; }
@media (hover: hover) { .when-clear:hover { background: rgba(255, 255, 255, 0.3); } }

/* in the showtimes: the times a search's results leave out are left out, and it says so */
.st-from { margin: -6px 0 -4px; font-size: 0.8rem; color: var(--ink-faint); }

/* a time or a room chosen (the filter): the top film's times that suit, under the card, so you
   needn't open its showtimes to see them. The buttons below move down a little to give it room
   (.timed, from cards.js); it moves with the stack, and goes while the showtimes are open, which
   say it all. The first has a green dot within two hours (red: started). */
/* (20px where there's room; on a short window, less, down to none by 660px tall, so the arrows keep
   a margin at the foot: the line then sits in the gap as it is. Without the line, none: .table) */
.table.timed { --line-room: clamp(0px, (100svh - 660px) / 3, 20px); }
.table.timed.showing-times:not(.grid-mode) { --line-room: 0px; } /* (beside the showtimes, which say it all, the line's never there: no room kept for it) */
.deck-actions { translate: 0 var(--line-room); }
.deck-nav { translate: calc(-1 * var(--nav-shift, 0px)) var(--line-room); transition: opacity .3s var(--ease), visibility 0s, translate .6s var(--set-off); } /* (moved aside with the card for the showtimes, in step) */
.showing-times:not(.grid-mode) .deck-nav { --nav-shift: var(--shift, 0px); }
.next-show {
  position: absolute; top: calc(100% + (var(--gap) + var(--line-room)) / 2); left: 50%; translate: -50% -50%;
  margin: 0; display: flex; align-items: center; gap: 10px; white-space: nowrap;
  color: var(--ink-soft); font-size: 0.8rem; font-weight: 500; font-variant-numeric: tabular-nums;
  transition: opacity .3s var(--ease);
}
.showing-times .next-show { opacity: 0; }
.next-show b { color: var(--ink); font-weight: 700; }
.next-day { font-size: 0.7rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-soft); }
.next-in, .next-more { margin-left: -4px; color: var(--ink-faint); }
/* A phone on its side (the height SHORT in cards.js): the stack's room from the top, the corners'
   buttons clear of it beside it (the grid's laid out round it: see .table) */
@media (orientation: landscape) and (max-height: 499px) {
  .table { --top: 26px; }
}
.icon-sliders { /* two sliders */
  position: relative; width: 14px; height: 11px;
  background: linear-gradient(currentColor, currentColor) 0 2px / 100% 1.5px no-repeat, linear-gradient(currentColor, currentColor) 0 8px / 100% 1.5px no-repeat;
}
.icon-sliders::before, .icon-sliders::after {
  content: ""; position: absolute; width: 5px; height: 5px; border-radius: 50%;
  background: var(--bg); box-shadow: inset 0 0 0 1.5px currentColor;
}
.icon-sliders::before { left: 2px; top: 0; }
.icon-sliders::after { right: 2px; top: 6px; }

/* like a phone's settings: a title (Preferences', with a × to close), then grouped rows of switches. A sheet up from
   the bottom (wider screens: no wider than a phone's, in the middle: dialog.sheet, below); on a phone on its side, a
   wide panel instead. Feedback's sheet the same (.fb, feedback.css) */
.prefs, .fb {
  width: min(440px, calc(100vw - 24px)); max-width: none; max-height: 88svh; padding: 0; border: 0; border-radius: 20px; overflow: auto;
  background: rgba(18, 17, 24, 0.98); color: var(--ink);
  box-shadow: var(--dialog-shadow);
  scrollbar-width: none;
  overscroll-behavior: contain; /* its scrolling stays in it, not the page behind */
}
:is(.prefs, .fb)::backdrop { background: rgba(4, 4, 6, 0.6); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
:is(.prefs, .fb)[open] { animation: rise .4s var(--ease); }
:is(.prefs, .fb)[open]::backdrop { animation: fade .3s var(--ease); }
/* (anything but a phone on its side, where it's a wide panel instead, below) */
@media (orientation: portrait), (min-height: 500px) {
  .prefs, .fb { width: min(100%, 440px); margin: auto auto 0; border-radius: 20px 20px 0 0; padding-bottom: env(safe-area-inset-bottom); }
}
/* closing (closePrefs): the way it came, in reverse, setting off gently and speeding away, since
   it's leaving from rest */
:is(.prefs, .fb).closing { animation: rise-out .22s var(--leave) forwards; }
:is(.prefs, .fb).closing::backdrop { animation: fade-out .25s ease-in forwards; }
@keyframes rise-out { to { opacity: 0; transform: translateY(14px) scale(0.98); } }
@keyframes sheet-glass { from { transform: translateY(calc(100% - var(--sheet-under))); } } /* (a sheet's: from just under the screen, not its glass's foot) */
@keyframes sheet-glass-out { to { transform: translateY(calc(100% - var(--sheet-under))); } }
@keyframes fade-out { to { opacity: 0; } }
/* a sheet (makeSheet, in cards.js), on a phone: frosted glass up from the bottom, rounder, with a
   grabber to drag it by, over a light shade (the films clear behind it, not blurred). Its quieter
   words, rows not chosen, are vibrant, as iOS's: lit by the colours
   behind (plus-lighter); its title and what's chosen stay plain white, to read the same over any.
   Its glass goes on under the foot of the screen (--sheet-under, more than cards.js's SHEET_GIVE
   and the spring's overshoot), so pulled up it shows more of itself, never the page beneath; its
   rows stay where they were, clear of the home bar. The shade lightens as it's pulled down
   (--sheet-shade, from cards.js), and a sheet let go on its way (--sheet-out and its curve) goes
   at the finger's speed. Not on a phone on its side (cards.js's makeSheet), where Preferences is
   a wide panel in the middle (below). */
@media (orientation: portrait), (min-height: 500px) {
  dialog.sheet {
    --sheet-under: 96px;
    scroll-padding-bottom: calc(env(safe-area-inset-bottom) + var(--sheet-under)); /* (Tab to a row under the screen: scrolled up into sight) */
    border-radius: 28px 28px 0 0; touch-action: pan-y; /* (its rows scroll, if it has more than fit; a drag that's the sheet's, cards.js holds the scroll off) */
    max-height: calc(88svh + var(--sheet-under)); margin-inline: auto; margin-bottom: calc(-1 * var(--sheet-under)); padding-bottom: calc(env(safe-area-inset-bottom) + var(--sheet-under));
    background: rgba(30, 28, 38, 0.42); backdrop-filter: blur(28px) saturate(1.8); -webkit-backdrop-filter: blur(28px) saturate(1.8);
  }
  dialog.sheet::backdrop { background: rgba(4, 4, 6, 0.35); backdrop-filter: none; -webkit-backdrop-filter: none; opacity: var(--sheet-shade, 1); }
  dialog.sheet[open] { animation: sheet-glass .45s var(--set-off); }
  dialog.sheet[open]::backdrop { animation: fade .45s var(--set-off); } /* (in step with it: caught as it comes up, the shade's where it'd be) */
  dialog.sheet.dragging .pref:active { background: transparent; } /* (a drag, not a press: as iOS, the row's let go) */
  dialog.sheet.dragging .pref:active::before, dialog.sheet.dragging .pref:active + .pref::before { opacity: 1; }
  dialog.sheet.closing { animation: sheet-glass-out var(--sheet-out, .3s) var(--sheet-out-curve, var(--leave)) forwards; }
  dialog.sheet.closing::backdrop { animation: fade-out var(--sheet-out, .25s) ease-in forwards; } /* (over its [open] fade, just above) */
  /* the grabber, iOS's: 36 by 5, clear of the edge (a little more than iOS's 5, with no hard edge
     here to sit under, and rounder corners), the title well below it (some 20px) */
  dialog.sheet::before {
    content: ""; position: absolute; z-index: 2; left: 50%; top: 8px; width: 36px; height: 5px; margin-left: -18px; border-radius: 3px;
    background: rgba(255, 255, 255, 0.32); mix-blend-mode: plus-lighter;
  }
  dialog.sheet .prefs-head { padding-top: 28px; background: transparent; touch-action: none; transition: background-color .2s, box-shadow .2s; } /* (room for the grabber; dragged by, always) */
  dialog.sheet.scrolled .prefs-head { background: rgb(26, 24, 33); } /* (rows under it: solid, in the glass's tint; a blur of its own can't see through the sheet's, and any see-through lets the vibrant rows show) */
  dialog.sheet.prefs .pref:not(:has(input:checked)) .pref-name { color: rgba(255, 255, 255, 0.62); mix-blend-mode: plus-lighter; } /* (.prefs: over Sort's own quieter rows) */
  dialog.sheet.prefs .pref + .pref::before { mix-blend-mode: plus-lighter; } /* (the hairlines too: their own rule, a pseudo-element can't go in :is) */
  dialog.sheet.prefs .pref:has(input:checked) .pref-name { color: #fff; }
}
.prefs form { display: grid; gap: 30px; padding: 0 20px 28px; }
/* the title (and Preferences' ×) stay put at the top as the rows scroll under them, as in a phone's sheets,
   with a hairline beneath once there's something under it (.scrolled, from cards.js) */
.prefs-head {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin: 0 -20px -12px; padding: 22px 20px 14px 24px;
  background: var(--panel); box-shadow: 0 1px 0 transparent;
  transition: box-shadow .2s;
}
.prefs.scrolled .prefs-head { box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08); }
.prefs h2 { margin: 0; font-size: 1.2rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; }
.prefs h2:focus { outline: none; } /* focused on opening, just so it starts there (see cards.html) */
.prefs fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
/* each part's name, a heading of its own (as a phone's settings, where a group's name matters): in
   words as written, a little larger than its rows' names, plain white, with what it does in a line
   just under it, over its rows */
.prefs legend { padding: 0 4px 3px; font-size: 1.02rem; font-weight: 650; letter-spacing: -0.01em; color: var(--ink); }
.prefs-intro { margin: -12px 4px -6px; font-size: 0.8rem; line-height: 1.45; color: var(--ink-soft); } /* (what they're for: close under the title, a little nearer the first part than the parts are to each other) */
.prefs-note { margin: 0 4px 10px; font-size: 0.8rem; line-height: 1.45; color: var(--ink-soft); }

/* a preference: a row with its name and what it covers, how many films, and a switch. Rows sit
   on the panel itself, divided by hairlines, as the showtimes' are (no boxes); lit softly, to the
   rounded edge, under a pointer or a finger. One that's off is a shade quieter, so what's on
   reads at a glance. */
.prefs-group { margin: 0 -10px; }
.pref {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 14px; align-items: center;
  min-height: 62px; padding: 11px 14px; border-radius: 12px; cursor: pointer;
  transition: background .2s;
}
.pref + .pref::before { content: ""; position: absolute; top: 0; left: 14px; right: 14px; height: 1px; background: rgba(255, 255, 255, 0.07); }
/* (the hairlines either side of a lit row give way to it) */
@media (hover: hover) { .pref:hover { background: rgba(255, 255, 255, 0.035); } .pref:hover::before, .pref:hover + .pref::before { opacity: 0; } }
.pref:active:not(.touch-moved *) { background: rgba(255, 255, 255, 0.06); transition-duration: .06s; } /* pressed (not a finger that's set off scrolling: cards.js's touch-moved) */
.pref:active:not(.touch-moved *)::before, .pref:active:not(.touch-moved *) + .pref::before { opacity: 0; }
.pref input { position: absolute; opacity: 0; pointer-events: none; }
.pref-text { display: grid; gap: 2px; }
.pref-name { font-weight: 600; font-size: 0.94rem; letter-spacing: -0.005em; color: var(--ink); transition: color .2s; }
.pref:not(:has(input:checked)) .pref-name { color: var(--ink-soft); }
.pref-name b { font-weight: 800; }
/* an experience's name: its badge, as its shows wear it (a little larger), quieter when it's off */
.pref-name:has(.room-badge, .room-pair) { display: flex; align-items: center; gap: 7px; font-size: 1.05rem; }
.pref-and { font-size: 0.8rem; font-weight: 500; color: var(--ink-faint); } /* (THEATRE & its pods) */
.pref:not(:has(input:checked)) .pref-name :is(.room-badge, .room-pair) { opacity: 0.55; transition: opacity .2s; }
.pref-blurb { font-size: 0.76rem; line-height: 1.35; color: var(--ink-faint); }
/* its chains' marks (a cinema's, an experience's): as a show's, large and faint behind it, from where
   its name starts, side by side if it's several's */
.pref-marks { position: absolute; z-index: -1; inset: 0 14px; display: flex; align-items: center; gap: 14px; pointer-events: none; }
.pref-marks .chain-mark { position: static; translate: none; height: 64%; }
.pref-count { font-size: 0.78rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* the switch: a track with a knob, sliding over when on, a little wider than a phone's, its knob
   stretching while it's held, as a phone's does. On, the track's blue (a setting's, as a phone's:
   not the accent, a filter of the moment's); the knob's the same light one either way. */
.switch {
  position: relative; flex: none; width: 56px; height: 32px; border-radius: 99px;
  background: rgba(255, 255, 255, 0.12); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04);
  transition: background .3s var(--ease);
}
.switch::after {
  content: ""; position: absolute; left: 3px; top: 3px; width: 26px; height: 26px; border-radius: 99px;
  background: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: transform .3s var(--ease), width .2s var(--ease), background .3s var(--ease);
}
.pref:active:not(.touch-moved *) .switch::after { width: 32px; }
.pref:has(input:checked) .switch { background: rgb(10, 132, 255); }
.pref:has(input:checked) .switch::after { transform: translateX(24px); }
.pref:has(input:checked):active:not(.touch-moved *) .switch::after { transform: translateX(18px); } /* (stretching from the right) */
.pref:has(input:focus-visible) .switch { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Ratings: one of a list (whose ratings you go by: cards.js's takeRatings), as a phone's settings pick
   one: each row its site's name, and a check on the one picked, in the switches' blue;
   no switch, as turning one off is picking the other */
.pref-pick { grid-template-columns: minmax(0, 1fr) auto; }
.check { position: relative; width: 22px; height: 22px; }
.check::after {
  content: ""; position: absolute; left: 7px; top: 2px; width: 6px; height: 13px;
  border: solid rgb(10, 132, 255); border-width: 0 2.5px 2.5px 0; border-radius: 1px; rotate: 45deg;
  opacity: 0; scale: 0.6; transition: opacity .2s var(--ease), scale .3s var(--ease);
}
:is(.pref-pick, .fb-kind):has(input:checked) .check::after { opacity: 1; scale: 1; } /* (Feedback's kinds' too: feedback.css) */
:is(.pref-pick, .fb-kind):has(input:focus-visible) .check { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
@media (prefers-reduced-motion: reduce) { .check::after { transition: none; } }
.pref.refused .switch { animation: refuse .4s ease; } /* the last language, which has to stay */
@keyframes refuse { 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } }

.prefs-showing { margin: 3px 0 0; font-size: 0.8rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.prefs-showing:empty { display: none; } /* (nothing to say: no room kept for it under the title) */
.prefs-showing.note { color: var(--accent); }
.prefs-close { flex: none; } /* the round ×, as the showtimes' and the trailer's (no Done: it closes as you go) */

/* ——— The view toggle: cards or grid (and your shortlist), after Preferences and Sort, top left ——— */
.corner-left {
  position: fixed; top: max(18px, env(safe-area-inset-top)); left: 20px; z-index: var(--z-corner);
  display: flex; align-items: center; gap: 10px;
  transition: opacity .3s var(--ease), visibility 0s;
}
/* on a phone, the corner a little closer in and to the edge, the 16px gutter (the search bar
   after it, as far in from the right) */
@media (max-width: 777px) and (orientation: portrait), (max-width: 777px) and (min-height: 500px) {
  .corner-left { left: 16px; gap: 8px; }
}
.view-toggle {
  display: flex; padding: 3px; border-radius: 99px;
  border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(12, 11, 14, 0.62);
}
.view-toggle button {
  display: grid; place-items: center; width: 34px; height: 32px; padding: 0; border: 0; border-radius: 99px; cursor: pointer;
  background: none; color: var(--ink-faint); transition: background .2s, color .2s, transform .2s var(--ease);
}
.view-toggle button[aria-pressed="true"] { background: rgba(255, 255, 255, 0.14); color: var(--ink); }
@media (hover: hover) { .view-toggle button:not([aria-pressed="true"]):hover { color: var(--ink); } }
.view-toggle button:active { transform: scale(0.9); transition-duration: .06s; }
/* the two as a pair: solid, 14px, the same weight (a card and the one tilted behind it: the
   template's SVG; four little squares on whole pixels, 6 + 2 + 6, each rounded alike) */
.icon-cards { display: block; width: 14px; height: 14px; fill: currentColor; }
.icon-grid { position: relative; width: 14px; height: 14px; }
.icon-grid::before {
  content: ""; position: absolute; left: 0; top: 0; width: 6px; height: 6px; border-radius: 1.5px;
  background: currentColor; box-shadow: 8px 0 currentColor, 0 8px currentColor, 8px 8px currentColor;
}

/* ——— Your shortlist (cards.js): a bookmark on each film, and once there's one on it, a button for
   just those: round, after the view toggle (a filter on the films, not a way to lay them out), with
   how many on its corner; filled in the accent while it's on, as the filter's pill is ——— */
.icon-save { flex: none; width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
[aria-pressed="true"] > .icon-save { fill: currentColor; }
.no-shortlist :is(.short-toggle, .times-save, .deck-save) { display: none !important; } /* (the shortlist off: cards.js's SHORTLIST_ON) */
.short-toggle {
  position: relative; display: grid; place-items: center; flex: none; width: 38px; height: 38px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(12, 11, 14, 0.62); color: var(--ink-soft);
  transition: background .2s, color .2s, border-color .2s, transform .2s var(--ease);
  animation: fade .3s var(--ease); /* (coming into the corner: the first film saved) */
}
@media (hover: hover) { .short-toggle:not([aria-pressed="true"]):hover { background: rgba(255, 255, 255, 0.1); color: var(--ink); border-color: rgba(255, 255, 255, 0.24); } }
.short-toggle[aria-pressed="true"] { border-color: transparent; background: var(--accent-grad); color: var(--on-accent); }
.short-count { /* light on the dark glass, dark on the accent: the digit always reads */
  position: absolute; top: -4px; right: -5px; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 99px;
  background: var(--ink); color: var(--panel); font-size: 0.66rem; font-weight: 700; line-height: 17px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.short-toggle[aria-pressed="true"] .short-count { background: var(--panel); color: var(--ink); }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) { .short-toggle { width: 40px; height: 40px; } } /* (as search and Preferences there) */
/* under the cards, after Showtimes: the top film's, round, in the pills' glass; on the shortlist,
   filled in the accent. Beside the pair rather than in their row, so they stay centred over the
   arrows. */
.deck-save {
  position: absolute; top: 0; left: calc(100% + 8px);
  display: grid; place-items: center; width: 42px; height: 42px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--pill-line); background: var(--pill-fill); color: var(--ink-soft);
  transition: background .2s, border-color .2s, color .2s, transform .2s var(--ease);
}
.deck-save .icon-save { width: 17px; height: 17px; }
.deck-save[aria-pressed="true"], .times-save[aria-pressed="true"] { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
@media (hover: hover) {
  .deck-save:hover { background: var(--pill-fill-hover); border-color: var(--pill-line-hover); color: var(--ink); }
  :is(.deck-save, .times-save)[aria-pressed="true"]:hover { color: var(--accent); border-color: var(--accent); }
}
.deck-save:active { background: rgba(255, 255, 255, 0.16); }
/* by a film's showtimes where the one under the cards isn't to hand: in the grid, beside the ×,
   and on a phone, in the ×'s place at the top right */
.times-save {
  position: absolute; top: calc(6px + (1.5rem * 1.1 - 34px) / 2); right: 44px; z-index: 1;
  display: grid; place-items: center; width: 34px; height: 34px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.16); background: rgba(255, 255, 255, 0.05); color: var(--ink-soft);
  transition: background .2s, color .2s, border-color .2s, opacity .3s var(--ease), visibility 0s, transform .2s var(--ease);
}
@media (hover: hover) { .times-save:hover { background: rgba(255, 255, 255, 0.14); color: var(--ink); } }
.times-save:active { background: rgba(255, 255, 255, 0.18); }
/* beside the cards (only on a wide screen: cards.js's cardsFit), the showtimes always there: no ×,
   the bookmark in its place and the trailer by it, as on a phone; the buttons under the card gone */
.table:not(.times-cover, .grid-mode) .times-save { right: 0; }
.table:not(.times-cover, .grid-mode) [data-showtimes-close] { display: none; }
.table:not(.grid-mode) .deck-actions { display: none; }
.grid-mode:not(.times-cover) .times-body { --title-room: 66px; } /* (the bookmark and ×) */
.table:not(.times-cover, .grid-mode) .times-body { --title-room: 34px; } /* (beside the cards: the bookmark) */
/* beside the grid, the bookmark and × quiet icons at the top right, as When, Where and Sort are
   quiet: a rounded rect only pointed at (on a phone, and over the poster's crop, they stay frosted
   pills, for the poster under them) */
.grid-mode:not(.times-cover) .times-view > :is(.times-save, .times-close) {
  top: calc(6px + (1.5rem * 1.1 - 30px) / 2); width: 30px; height: 30px; border: 0; border-radius: 8px; background: none; color: var(--ink-faint);
}
.grid-mode:not(.times-cover) .times-view > .times-save { right: 32px; }
.grid-mode:not(.times-cover) .times-view > .times-close { right: -2px; }
@media (hover: hover) { .grid-mode:not(.times-cover) .times-view > :is(.times-save, .times-close):hover { background: rgba(255, 255, 255, 0.07); color: var(--ink); } }
.grid-mode:not(.times-cover) .times-view > .times-save[aria-pressed="true"] { color: var(--accent); }
.times-cover .times-save { right: 0; }
.list-mode .times-save, .info-mode .times-save { opacity: 0; visibility: hidden; } /* (several films, or one in brief) */
.grid-mode .list-mode .times-close { opacity: 0; visibility: hidden; } /* (beside the grid, they're the panel's own: nothing to close) */

/* your shortlist's showtimes together, a day at a time: each film once, its poster and name, then
   its times as small tiles side by side, under its format (and cinema, with several); a time's
   dot says it's next within 2 hours, or just started */
.list-mode .st-panel { gap: 14px; }
.list-film { display: grid; gap: 6px; }
.list-film + .list-film { padding-top: 14px; border-top: var(--rule); }
.list-head { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }
.list-art {
  flex: none; width: 24px; aspect-ratio: 63 / 88; border-radius: 3px; object-fit: cover; object-position: 50% 20%;
  background: #15131b; box-shadow: 0 0 0 1px rgba(255, 240, 200, 0.16);
}
.list-film .st-cinema:not([hidden]) ~ .st-cinema:not([hidden], .st-one) { margin-top: 0; padding-top: 4px; border-top: 0; }
.list-film .st-cinema-name { margin: 2px 0 6px; font-size: 0.66rem; color: var(--ink-faint); }
.list-film .st-row, .list-film .st-cinema-name + .st-row { gap: 5px; padding: 0 0 4px; border-top: 0; }
.list-film .st-times { display: flex; flex-wrap: wrap; gap: 5px; }
.list-film .st-time {
  width: auto; margin: 0; padding: 5px 9px; gap: 5px; border-radius: 7px;
  background: rgba(255, 255, 255, 0.06); box-shadow: none; font-size: 0.86rem;
}
.list-film :is(.st-end, .st-when) { display: none; } /* (the times alone, to compare; and how a show you've checked suits you) */
.list-film .st-dot { display: none; }
/* the grid's way to them on a phone (beside it, they're in the panel): quiet glass, as Trailer */
.grid-list {
  grid-column: 1 / -1; justify-self: start; display: none; align-items: center; gap: 10px; cursor: pointer;
  padding: 9px 18px 9px 15px; border-radius: 99px; border: 1px solid var(--pill-line);
  background: var(--pill-fill); color: var(--ink); font-size: 0.88rem; font-weight: 600;
  transition: background .2s, transform .2s var(--ease);
}
.times-cover .grid-list { display: inline-flex; }
.grid-list:active { transform: scale(0.94); background: rgba(255, 255, 255, 0.16); transition-duration: .06s; }

/* ——— Grid view: the little cards laid out on the table, reaching left from the stack's right edge
   and down to the foot of the screen, 2 to 5 columns as the room allows (--grid-*, --cols:
   placeGrid), the stack and its controls hidden meanwhile; and in the showtimes' place, the
   details of the film pointed at (cards.js). ——— */
.grid-view {
  position: absolute; z-index: var(--z-times); /* (under the deck, when it's on its way out: a card grows over it) */
  left: var(--grid-left, 0px); width: var(--grid-w, 100%); top: var(--grid-top, 0px); bottom: var(--grid-bottom, 0px);
  display: grid; grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr)); gap: 14px; /* (as far apart down as across: no caption under them, .tile-when) */ align-content: start;
  padding: 8px 20px 72px; overflow-y: auto; /* (20px beside: room for a little card to tilt into, not cut off: cards.js's GRID_SIDE) */ overscroll-behavior: contain; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(transparent, #000 8px, #000 calc(100% - 64px), transparent);
  mask-image: linear-gradient(transparent, #000 8px, #000 calc(100% - 64px), transparent);
  opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s;
}
.grid-view::-webkit-scrollbar { display: none; }
.grid-mode .grid-view { z-index: var(--z-grid); opacity: 1; visibility: visible; transition: opacity .3s var(--ease), visibility 0s; }
/* a film taking the screen from it: gone, as the cards go for the showtimes (its scroll kept) */
.grid-mode.times-cover.showing-times .grid-view { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s; }
.grid-mode .deck, .grid-mode :is(.deck-nav, .deck-actions, .next-show) { visibility: hidden; }
.opens-grid :is(.deck, .deck-nav, .deck-actions, .next-show) { visibility: hidden; } /* (the page opening in the grid, before it's drawn: cards.html) */
@media (max-width: 777px) { .grid-view { gap: 12px; } }
/* when and where over the grid, across its column, level with the panel beside it (placeGrid: its
   110px, the grid under it), then the sort: three lines each led by its name (cards.js's
   drawPickers, saySort). When: a tile
   a day, its film count at its end, in a quiet rounded rect; Where: your cinemas, just their names
   and counts, a rounded rect only pointed at or pressed. Each line scrolls sideways, faded at its
   end; the search's day and cinema filled, those that'd find nothing beside the rest of the search
   dimmed in place, so nothing moves. Just one cinema of yours: no Where, the grid up into its room.
   There as the grid is, and gone with it. */
.pickers {
  position: absolute; z-index: var(--z-grid); left: var(--grid-left, 0px); width: var(--grid-w, 100%); top: var(--pickers-top, 0px);
  display: grid; padding: 4px 20px; box-sizing: border-box; color: var(--ink); /* (the grid's 20px beside: the first in line with its little cards) */
  opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s;
}
.grid-mode .pickers { opacity: 1; visibility: visible; transition: opacity .3s var(--ease), visibility 0s; }
.grid-mode.times-cover.showing-times .pickers, .grid-mode.playing .pickers { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s; }
.pick-line { display: flex; align-items: center; gap: 4px; min-width: 0; }
.pick-line + .pick-line { margin-top: 4px; }
.pickers.no-where .pick-where { display: none; }
.no-where .grid-view { top: calc(var(--grid-top, 0px) - 36px); } /* (Where's line, and the 4px over it) */
.pickers.no-sort .pick-sort { display: none; } /* (your shortlist: soonest first, no sort to choose) */
.no-sort .grid-view { top: calc(var(--grid-top, 0px) - 36px); padding-top: 30px; } /* (Sort's line, and the 4px over it; no heading over the films either, so room above them to lift into, clear of the top's fade) */
.no-where.no-sort .grid-view { top: calc(var(--grid-top, 0px) - 72px); }
/* on a phone (upright), the lines go with the films: the grid's first row, right across it, scrolled
   away with it, the grid's top just under the search bar (cards.js's rollPickers); the films' first
   heading where it was under them (the grid's row gap taken back). Once they're out of sight, a
   quiet line over the grid's top says what they're set to (.pick-summary), a finger's tall (44px),
   the headings stuck just under it, their top padding tucked under it, their words 8px lower (so a
   heading's ⓘ, 44px to a finger, is clear of the line's), so the bar, the line and a heading are
   ~150px (with a 16px line it was ~120, but the line was a 19px tap). */
.pick-roll { --summary-h: 44px; }
.grid-view > .pickers { grid-column: 1 / -1; position: relative; z-index: auto; left: auto; top: auto; width: auto; padding: 4px 0; margin-bottom: -18px; }
.pick-roll:is(.no-where, .no-sort) .grid-view { top: var(--grid-top, 0px); } /* (no Where: the lines are shorter, the grid where it is) */
.pick-roll.no-sort .grid-view { padding-top: 8px; } /* (the lines in it, over the films: as ever) */
.pick-roll .grid-group { top: calc(var(--summary-h) - 12px); } /* (as -8px is: over the grid's 8px padding, and its own 12px over the text, less the 8px between the line and its words) */
/* (stuck, it ends 8px under its words, not 12px, the films just under it, its ⓘ's reach still in
   it; where it sits in the grid as it was, the 4px less below taken back out of its margin) */
.pick-roll .grid-group { padding-bottom: 8px; margin-bottom: -4px; }
.pick-summary { display: none; }
.pick-roll .pick-summary {
  position: absolute; z-index: var(--z-grid-over); left: var(--grid-left, 0px); width: var(--grid-w, 100%); top: var(--grid-top, 0px); height: var(--summary-h);
  display: flex; align-items: center; gap: 4px; padding: 0 20px; border: 0; box-sizing: border-box; background: none; cursor: pointer;
  font: inherit; font-size: 0.8rem; font-weight: 500; line-height: 1.3; color: var(--ink-soft); text-align: left; -webkit-tap-highlight-color: transparent;
  visibility: hidden; transition: opacity .2s var(--ease); /* (its fade's only as a film's opened over the grid, and closed: below) */
}
/* (its ground there at once, as the lines go under it, so no film shows above the stuck heading
   while it fades in; just its words fade in) */
.pick-roll.grid-mode .pick-summary.shown { visibility: visible; }
.pick-roll.grid-mode .pick-summary.shown > * { animation: fade .2s var(--ease); }
.grid-mode.times-cover.showing-times .pick-summary, .grid-mode.playing .pick-summary { opacity: 0; visibility: hidden; transition: opacity .2s var(--ease), visibility 0s .2s; }
.pick-summary-words { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-summary-mark { flex: none; width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; opacity: 0.7; }
.pick-summary:active { color: var(--ink); }
.pick-summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 6px; }
@media (prefers-reduced-motion: reduce) { .pick-roll.grid-mode .pick-summary.shown > * { animation: none; } }
.pick-sorts { display: flex; align-items: center; gap: 2px; height: 32px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.pick-sorts::-webkit-scrollbar { display: none; }
/* When, Where and Sort led by icons, not words (a calendar, a map pin, up and down
   arrows; still said, the rows' own labels: the words were never read out, aria-hidden); the three
   rows' first picks on one left edge: When's tiles' box, and Where's and Sort's words (their own
   pill, pressed, reaching back into the gap before them) */
.pick-lead {
  flex: none; width: 22px; height: 18px; margin-right: 14px; font-size: 0; color: transparent; white-space: nowrap;
  background: color-mix(in srgb, var(--ink) 55%, transparent);
  -webkit-mask: var(--lead-icon) center / 18px 18px no-repeat; mask: var(--lead-icon) center / 18px 18px no-repeat;
}
.pick-line { --lead-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='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4.5' width='18' height='17' rx='3'/%3E%3Cpath d='M16 2.5v4M8 2.5v4M3 10h18'/%3E%3C/svg%3E"); }
.pick-where { --lead-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='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z'/%3E%3Ccircle cx='12' cy='10' r='3'/%3E%3C/svg%3E"); }
.pick-sort { --lead-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='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21 16-4 4-4-4M17 20V4M3 8l4-4 4 4M7 4v16'/%3E%3C/svg%3E"); }
.pick-days, .pick-cinemas { min-width: 0; flex: 1; display: flex; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }
.pick-days::-webkit-scrollbar, .pick-cinemas::-webkit-scrollbar { display: none; }
.pick-days, .pick-cinemas { gap: 4px; }
/* more than fits, faded at whichever end has more (cards.js's edges), as the panel's rows are; on a
   phone, faded further in (--pick-fade), so it's plain there's more to scroll to (cards.js's inSight
   keeps the one pressed clear of it) */
:is(.pick-days, .pick-cinemas).rolls { mask-image: linear-gradient(to right, #000 calc(100% - var(--pick-fade, 24px)), transparent); }
:is(.pick-days, .pick-cinemas).rolls.off-start { mask-image: linear-gradient(to right, transparent, #000 var(--pick-fade, 24px), #000 calc(100% - var(--pick-fade, 24px)), transparent); }
:is(.pick-days, .pick-cinemas).rolls.at-end { mask-image: none; }
:is(.pick-days, .pick-cinemas).rolls.off-start.at-end { mask-image: linear-gradient(to right, transparent, #000 var(--pick-fade, 24px)); }
.pick-roll :is(.pick-days, .pick-cinemas) { --pick-fade: 40px; }
/* (scrolled to its first that finds something, on a phone, the dimmed one before it is all behind
   the start's fade, not seen through it: cards.js's leadInSight; scrolled, faded as ever) */
.pick-roll :is(.pick-days, .pick-cinemas).rolls.off-start.led { mask-image: linear-gradient(to right, transparent calc(var(--led-to, var(--pick-fade)) - 4px), #000 var(--led-to, var(--pick-fade)), #000 calc(100% - var(--pick-fade)), transparent); }
.pick-roll :is(.pick-days, .pick-cinemas).rolls.off-start.at-end.led { mask-image: linear-gradient(to right, transparent calc(var(--led-to, var(--pick-fade)) - 4px), #000 var(--led-to, var(--pick-fade))); }
/* on a phone, Now, Today and Tonight aren't offered while they'd find nothing (Now before the day's
   first show; all of them late at night, the day's last show gone): the days you can go to start
   the line, without the gap after today's. Back as soon as they'd find a show (cards.js's
   drawPickers, every 30 seconds); pressed (a search for now), one stays, to let go of. */
.pick-roll .pick-today[aria-disabled="true"] { display: none; }
.pick-cinemas { align-items: center; height: 32px; }
.pick-tile, .where-pick { font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pick-tile {
  flex: 1 0 64px; display: grid; align-content: center; height: 30px; box-sizing: border-box; padding: 0 8px; border: 0; border-radius: 10px;
  background: rgba(255, 255, 255, 0.035); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07); color: var(--ink-soft); text-align: left;
  transition: background .2s, color .2s, opacity .2s;
}
.pick-words { display: flex; align-items: center; gap: 5px; font-size: 0.76rem; font-weight: 600; white-space: nowrap; }
.pick-count { margin-left: auto; padding-left: 4px; font-weight: 700; font-variant-numeric: tabular-nums; opacity: 0.5; }
.pick-tile[aria-pressed="true"] { background: var(--ink); color: var(--panel); box-shadow: none; }
.pick-tile[aria-pressed="true"] .day-soon-dot { box-shadow: none; }
.pick-tile[aria-disabled="true"] { opacity: 0.32; cursor: default; }
@media (hover: hover) { .pick-tile:not([aria-pressed="true"]):not([aria-disabled="true"]):hover { background: rgba(255, 255, 255, 0.08); color: var(--ink); } }
/* Where's cinemas: tiles as the days over them are, and a film's own cinemas' chips the same (.st-cinema-pick,
   in its showtimes: a .find-chip too, for the rest of its look): a tile, its count faint, the one chosen cream */
.where-pick, .st-cinema-pick {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 9px; border: 0; border-radius: 10px;
  background: rgba(255, 255, 255, 0.035); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07); font-size: 0.76rem;
}
.where-pick { flex: none; font-weight: 600; color: var(--ink-soft); white-space: nowrap; transition: background .2s, color .2s, opacity .2s; }
:is(.where-pick, .st-cinema-pick) .where-count { opacity: 0.5; }
:is(.where-pick, .st-cinema-pick)[aria-pressed="true"] { background: var(--ink); box-shadow: none; color: var(--panel); }
:is(.where-pick, .st-cinema-pick)[aria-pressed="true"] .where-count { opacity: 0.6; }
.where-pick[aria-disabled="true"] { opacity: 0.35; cursor: default; }
.sort-pick[aria-disabled="true"] { opacity: 0.35; cursor: default; } /* (Now: its headings by time, the sort off: cards.js's sayNowSort) */
@media (hover: hover) { .where-pick:not([aria-pressed="true"]):not([aria-disabled="true"]):hover { background: rgba(255, 255, 255, 0.08); color: var(--ink); } }
/* Sort's: Where's look, but the one chosen never filled as a cinema pressed is (it's how the films
   are laid out, not which): a faint rect, its words in the ink */
.sort-pick {
  flex: none; display: inline-flex; align-items: center; height: 28px; padding: 0 10px; border: 0; border-radius: 8px; cursor: pointer;
  background: none; font: inherit; font-size: 0.82rem; font-weight: 600; color: var(--ink-soft); white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.sort-pick[aria-checked="true"] { background: rgba(255, 255, 255, 0.08); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14); color: var(--ink); }
@media (hover: hover) { .sort-pick:not([aria-checked="true"]):not([aria-disabled="true"]):hover { background: rgba(255, 255, 255, 0.07); color: var(--ink); } }
:is(.pick-tile, .where-pick).refused { animation: refuse .4s ease; }
@media (prefers-reduced-motion: reduce) { :is(.pick-tile, .where-pick).refused { animation: none; } .pick-tile { transition: none; } }
/* now's red dot, the next two hours' green: the showtimes' (When's tiles, the panel's headings) */
.day-soon-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--soon); box-shadow: 0 0 6px var(--soon); } /* (the next two hours: the showtimes' green) */
.day-soon-dot.now { background: var(--now); box-shadow: 0 0 6px var(--now); } /* (now: their red, a show just started) */
/* a count beside a cinema's name, faint: Where's films, the panel's shows */
.where-count { font-weight: 700; font-variant-numeric: tabular-nums; opacity: 0.55; }
/* a film's cinemas, in its showtimes, under the days (cards.js's drawCinemas): the search's chips,
   a little smaller, as the panel's, each its name and how many shows; on one line, more than fit a
   scroll along, faded at the end until it's reached (as a week's days) */
.st-cinemas { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; }
.st-cinemas::-webkit-scrollbar { display: none; }
.st-cinemas > * { flex: none; }
.st-cinemas.rolls { mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); }
.st-cinemas.rolls.at-end { mask-image: none; }
.st-cinemas.rolls.off-start { mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent); }
.st-cinemas.rolls.off-start.at-end { mask-image: linear-gradient(to right, transparent, #000 28px); }
/* (the cinemas' chips themselves: as Where's, .where-pick) */
.st-seat-hint { display: flex; align-items: center; gap: 6px; margin: 2px 0 -4px; color: var(--ink-faint); font-size: 0.78rem; }
.st-seat-hint svg { flex: none; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
@media (prefers-reduced-motion: reduce) { .st-cinema-pick, .st-cinema-pick:active { transition: none; transform: none; } }
/* the panel beside the grid: down to the foot of the screen, as the grid is, fading out where it does */
.grid-mode:not(.times-cover) .times-view { top: var(--times-drop, 0px); height: auto; bottom: var(--grid-bottom, 0px); } /* (up level with the search bar, which is over the grid: placeGrid) */
.grid-mode:not(.times-cover) .times-body {
  padding-bottom: 72px;
  -webkit-mask-image: linear-gradient(#000 calc(100% - 64px), transparent); mask-image: linear-gradient(#000 calc(100% - 64px), transparent);
}
.grid-mode:not(.times-cover) .times-body:not(.seat-page) { padding-bottom: 0; -webkit-mask-image: none; mask-image: none; }
.grid-mode:not(.times-cover) .st-scroll { padding-bottom: 72px; --fade-end: 64px; }
/* ——— A film's times on a phone (upright), as a screen of their own (cards.js's dressTimes): under
   its name, what it is in a quiet line and two lines of its story (More, down to the rest), then
   the days; its cinemas' chips the first row of what scrolls. Scrolled (.folded), the name, the
   line and the story scroll away under the bar, which then says "‹ Films", the name on one line, its
   trailer's mark and the bookmark, the days stuck just under it (your shortlist's head folds away
   instead). Nowhere else: beside the grid, a phone on its side, a seat map, as they were ——— */
.st-what, .st-brief, .times-fold { display: none; }
@media (max-width: 777px) {
  /* (the pages clipped at the screen's edges, not 6px in, so the days' band, stuck, reaches them: the
     page's sides 18px, not 12, the times as wide as ever) */
  html.page-scroll .times-cover .times-pages { margin-inline: -17px; }
  html.page-scroll .times-cover .times-body { padding-inline: 19px; }
  .times-cover .times-body.dressed { gap: 0; padding-top: 0; }
  .times-cover .times-view:has(.dressed) .times-back { margin-bottom: 0; } /* (its 6px the head's own: below) */
  .times-cover .dressed .st-head { gap: 0; }
  /* (folded: to nothing, its 14px apart, under the bar; out of reach, but its name still read) */
  .times-cover .dressed .st-lead {
    display: grid; grid-template-rows: 1fr; min-height: 14px;
    transition: grid-template-rows .45s var(--set-off), opacity .3s var(--ease) .05s, visibility 0s;
  }
  .times-cover .dressed .st-lead-in { min-height: 0; overflow: hidden; display: grid; align-content: start; gap: 4px; margin: 0 -8px; padding: 12px 8px 8px; transition: padding .45s var(--set-off); }
  .times-cover .folded.list-mode .dressed .st-lead {
    grid-template-rows: 0fr; opacity: 0; visibility: hidden;
    transition: grid-template-rows .45s var(--set-off), opacity .2s var(--ease), visibility 0s .45s;
  }
  .times-cover .folded.list-mode .dressed .st-lead-in { padding-block: 0; } /* (else its padding would hold it open) */
  .times-cover .folded.list-mode .dressed .st-lead .st-title { visibility: visible; }
  /* the trailer's mark still leads the name, though read after it */
  .times-cover .dressed .st-name { display: flex; align-items: flex-start; }
  .times-cover .dressed .st-name > .st-play { order: -1; flex: none; float: none; }
  .times-cover .dressed .st-name > .st-title { flex: 1; min-width: 0; }
  .times-cover .dressed .st-title::before { content: none; } /* (no buttons beside it to flow round: they're above it) */
  /* (what it is and its story in brief: below, with on its side's) */
  /* the days a little shorter, the room the times' */
  .times-cover .dressed .st-day { padding-block: 2px 6px; }
  .times-cover .dressed .st-day-name { line-height: 1.2; }
  .times-cover .dressed .st-scroll > .st-bar { margin: 8px 0 -10px; }
  /* the line saying a search's (cards.js's sayFrom), over the times: clear of the first as they scroll under it */
  .times-cover .dressed .st-head > .st-from { margin-top: 8px; margin-bottom: 8px; } /* (8px clear, not its -4px: the times' soft top fade starts under it; and 8px under the days, not its -6px, which put it over their line) */
  /* the bar, folded: its name and its trailer's mark, from after ‹ Films to the bookmark */
  .times-cover .times-fold {
    display: flex; align-items: center; gap: 4px; position: absolute; top: 0; left: max(68px, var(--fold-l, 0px)); right: max(44px, var(--fold-r, 0px)); height: var(--back-h); z-index: 1; /* (clear of ‹ Films and the bookmark however wide they are: cards.js's fitFold) */
    opacity: 0; visibility: hidden; transition: opacity .2s var(--ease), visibility 0s .2s;
  }
  .times-cover .times-view.folded:not(.seat-mode, .info-mode) .times-fold { opacity: 1; visibility: visible; transition: opacity .3s var(--ease) .1s, visibility 0s; }
  .times-cover.playing .times-fold { right: max(134px, var(--fold-r-play, 0px)); } /* (the trailer playing: its × Trailer by the bookmark, 4px clear of it) */
  .times-fold-up { /* its name, a button back up to the top (cards.js's openHead): no look of its own but the focus's ring */
    flex: 0 1 auto; min-width: 0; align-self: stretch; display: flex; align-items: center;
    padding: 0 4px; margin: 0 -4px; border: 0; border-radius: 6px; background: none; /* (4px each side, for the ring to clear its name: its name where it was) */ color: inherit; font: inherit; text-align: left; cursor: pointer;
    position: relative;
  }
  .times-fold-up::after { content: ""; position: absolute; inset: -5px 0; } /* (34px drawn: 44px to a finger, as More's) */
  .times-fold-up:focus-visible { outline-offset: 0; }
  .times-fold-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1.02rem; font-weight: 800; letter-spacing: -0.02em; text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55); }
  .times-fold .st-play { float: none; flex: none; height: 30px; margin: 0 0 0 2px; }
  /* the poster's crop, folded, just behind the bar and the days, quieter */
  .times-cover .times-crop { clip-path: inset(0); transition: opacity .3s var(--ease), clip-path .35s var(--ease); }
  .times-cover .times-view.folded:not(.seat-mode, .list-mode, .info-mode) .times-crop { clip-path: inset(0 0 calc(100% - var(--crop-t, 0px) - var(--crop-fold, 92px)) 0); opacity: 0.55; }
  /* your shortlist's times (cards.js's dressList): each film's name, its poster beside it, kept at
     the top while its times scroll under it, till the next film's pushes it off; on the page's own
     colour, so no time shows through it, faded in at its top edge as the times were */
  .times-cover .times-view.list-mode:not(.folded) .dressed .st-lead-in { padding-bottom: 14px; } /* (its name alone over the days: a little more room under it) */
  .times-cover .list-mode .dressed .st-scroll { --stuck-h: 56px; scroll-padding-top: var(--stuck-h); } /* (a time tabbed to: clear of the name over it, as tall as it is: cards.js's stickNames) */
  .times-cover .list-mode .dressed .st-scroll.scrolled {
    -webkit-mask-image: linear-gradient(transparent, #000 8px, #000 calc(100% - var(--fade-end)), transparent);
    mask-image: linear-gradient(transparent, #000 8px, #000 calc(100% - var(--fade-end)), transparent);
  }
  .times-cover .list-mode .dressed .list-head { position: sticky; top: 0; z-index: 1; margin: 0 -12px -8px; padding: 8px 12px 14px; }
  /* (stuck, cards.js's stickNames: at rest, it's on the room as before) its foot fading the times
     out under it, its ends over the page's sides, where no time is, fading into the room */
  .times-cover .list-mode .dressed .list-head.stuck {
    background: linear-gradient(var(--bg) 0 calc(100% - 10px), transparent);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 12px, #000 calc(100% - 12px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 12px, #000 calc(100% - 12px), transparent);
  }
  /* A film's times (not your shortlist's) scroll as one page: its name, what it is and its story
     scroll away under the bar like any page, the days stick under the bar on a glass of their own,
     and the rest follows. Nothing folds or resizes as you scroll (a head that folded on scroll
     resized the scroller under the finger, which made the times jump); once the name's gone
     (.folded, cards.js's watchFold, just a class) the bar shows the film's name and the crop
     quietens. The times at least a screen tall, so another day's never shorter than where its
     days are stuck: they stay put under your finger. */
  .times-cover .times-view:not(.list-mode) .times-body.dressed {
    display: block; overflow-y: auto; overscroll-behavior-y: contain;
    scroll-padding-block: 56px 48px; /* (a time scrolled to, back from its seat map or tabbed to: clear of the days stuck over it, and of the fade at the foot) */
    -webkit-mask-image: linear-gradient(#000 calc(100% - 48px), transparent); mask-image: linear-gradient(#000 calc(100% - 48px), transparent);
  }
  /* (its name and story fading out under the bar as they go, not cut off there; once its days are stuck
     there, they're the edge, unless there are none, a search's one day) */
  .times-cover .times-view:not(.list-mode):is(:not(.folded), :has(.st-days.said)) .times-body.dressed {
    -webkit-mask-image: linear-gradient(transparent, #000 10px, #000 calc(100% - 48px), transparent); mask-image: linear-gradient(transparent, #000 10px, #000 calc(100% - 48px), transparent);
  }
  .times-cover .times-view:not(.list-mode) .dressed > .st-head { display: contents; }
  .times-cover .times-view:not(.list-mode) .dressed > .st-scroll { overflow: visible; min-height: 100%; -webkit-mask-image: none; mask-image: none; }
  .times-cover .times-view:not(.list-mode) .dressed .st-days {
    position: sticky; top: 0; z-index: 3;
  }
  .times-cover .times-view.folded:not(.list-mode) .dressed .st-days {
    --days-ground: rgb(14, 13, 18);
    background: var(--days-ground);
    box-shadow: -19px 0 var(--days-ground), 19px 0 var(--days-ground); /* (its ground out to the screen's edges, past its 18px, with no change to its layout) */
  }
  .times-cover .times-view:not(.list-mode) .dressed > .st-head > .st-from { position: relative; z-index: 1; }
  /* a film opened afresh: as it is at once (cards.js's foldHead) */
  .times-view.fold-now :is(.st-lead, .st-lead-in, .times-fold, .times-crop), .times-view.fold-now .times-crop::after { transition: none !important; } /* (a pseudo-element can't go in :is) */
}
@media (max-width: 777px) and (prefers-reduced-motion: reduce) {
  .times-cover :is(.dressed :is(.st-lead, .st-lead-in), .times-fold, .times-crop), .times-cover .times-crop::after { transition: none !important; }
}
/* a small phone's days, more than a week of them (.week-plus): faded at an end with more as wide
   as When's is (--pick-fade), the day chosen kept clear of it (cards.js's inSight) */
@media (max-width: 400px) and (orientation: portrait) {
  .times-cover .dressed .st-days { --pick-fade: 40px; }
}
/* (what it is and its story, upright or on its side: the same) */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  /* what it is: "2h 1m · Action · 87% · 7.4", each score with its mark; over the poster's crop, a
     soft shadow under the words so they read on a light one; then two lines of its story, More at
     the end of the second */
  .times-cover :is(.dressed, .sided) :is(.st-what, .st-brief-text) { text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55); }
  /* and under them, from just over what it is down, the poster's crop darkened by the page's own
     colour at 70%, faded in toward the crop's top, so the small words read on a bright poster; the
     name over it as it was (--scrim-t: what it is's top in the crop, at rest, cards.js's fitCrop).
     Folded, gone with them */
  .times-cover .times-view:not(.seat-mode, .list-mode, .info-mode):has(.times-body:is(.dressed, .sided)) .times-crop::after {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(transparent calc(var(--scrim-t) - 24px), color-mix(in srgb, var(--bg) 70%, transparent) calc(var(--scrim-t) + 4px));
    transition: opacity .3s var(--ease);
  }
  .times-cover .times-view.folded .times-crop::after { opacity: 0; }
  /* a time tabbed to: scrolled clear of the list's fades, its 20px at the top (scrolled) and its foot's */
  .times-cover :is(.dressed, .sided) .st-scroll { scroll-padding-block: 20px var(--fade-end); }
  /* its genres as chips under it, a little smaller, on a soft shade over its poster; so not
     again with what it is, after its times */
  .times-cover :is(.dressed, .sided) .st-genres { display: flex; gap: 5px; margin: 7px 0 2px; }
  .times-cover :is(.dressed, .sided) .info-about > .genre-chips { display: none; }
  .st-what > .age-tag { font-size: 10.5px; vertical-align: 1px; margin-right: 2px; } /* (its age rating first: just the tag, ageUnit after its story) */
  .st-genres .genre-chip { height: 20px; padding: 0 7px; font-size: 10.5px; background: rgba(0, 0, 0, 0.28); }
  .times-cover :is(.dressed, .sided) .st-what { display: block; margin: 0; font-size: 0.8rem; line-height: 1.4; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
  .times-cover :is(.dressed, .sided) .st-brief { display: flex; align-items: flex-end; gap: 12px; }
  .st-what-score { white-space: nowrap; font-weight: 600; }
  .st-what-score img { display: inline-block; width: 13px; height: 13px; margin-right: 4px; object-fit: contain; vertical-align: -2px; }
  .st-what-score.few { font-weight: 500; color: var(--ink-faint); } /* (an IMDb rating from too few votes to count) */
  .st-brief-text {
    flex: 1; min-width: 0; margin: 0; font-size: 0.86rem; line-height: 1.45; color: var(--ink-soft); text-wrap: pretty;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .st-more { flex: none; position: relative; font-size: 0.82rem; font-weight: 600; line-height: 1.45; }
  .st-more::after { content: ""; position: absolute; inset: -12px -10px; } /* (a finger's) */
}
/* ——— A phone on its side: a usable screen of its own, not upright's squashed. The bar slim (46px: its button 44px inside its border,
   up to 8px from the top), When, Where and Sort going with the films as upright (cards.js's
   rollPickers), the little cards about upright's size (TILE_MIN_SIDE), so more than a row's in
   sight. All of it kept clear of the notch and rounded corners at the left or right, whichever
   way it's turned: the safe area's insets, the wider of the two each side (--sa-side; the grid and
   the panel's column maths read it from .safe-probe: cards.js's safeSide). A film's times in two
   columns (.sided: cards.js's dressTimes): its name, what it is, its story in brief, the days and
   its cinemas on the left, the times scrolling on their own on the right, no wider than reads as
   a row (the time near its room). Its trailer has the screen, its × a round one at the top right. ——— */
.safe-probe { position: fixed; top: 0; left: 0; width: 0; height: 0; visibility: hidden; pointer-events: none; padding: 0 0 0 var(--sa-side, 16px); }
@media (orientation: landscape) and (max-height: 499px) {
  :root {
    --sa-l: env(safe-area-inset-left, 0px); --sa-r: env(safe-area-inset-right, 0px);
    --sa-side: max(16px, var(--sa-l), var(--sa-r));
    --times-w: calc(100vw - 2 * var(--sa-side)); /* (taking the screen, as upright: clear of the notch) */
  }
  .corner-left { top: max(8px, env(safe-area-inset-top)); left: max(20px, var(--sa-side)); }
  .page-find { --bar-h: 46px; top: calc(max(8px, env(safe-area-inset-top)) - (var(--bar-h) - 40px) / 2); }
  .find { width: min(640px, calc(100vw - 2 * var(--sa-side))); } /* (a phone's, as upright: over the films, its results scrolling inside it) */

  /* the left column's width, a film's times' and a seat map's alike (and the bookmark's place at
     its end, and the poster's crop behind it): 2 of 5 of the view's width, less its pages' 10px out
     and the body's 12px in, each side, and the 28px between */
  .times-cover .times-view { --side-col: calc((var(--times-w) - 32px) * 0.4); }
  /* a film's times: the left column (its own scroll if it needs it) under ‹ Films and the bookmark
     at its right end; the right one up to the top, beside them. A seat map's page the same, so the
     pages keep one top as it slides in (the seat page's columns: below) */
  .times-cover .times-body.sided {
    display: grid; grid-template-columns: var(--side-col) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); column-gap: 28px; padding-top: 0;
  }
  .times-cover .times-view:has(.times-body.sided) .times-pages { margin-top: calc(-1 * var(--back-row)); } /* (‹ Films's row: 34px and its 6px) */
  .times-cover .times-view:has(.times-body.sided) .times-back { position: relative; z-index: 2; }
  .times-cover .times-view:has(.times-body.sided) .times-save { right: auto; left: calc(2px + var(--side-col) - 34px); }
  .times-cover .sided .st-head {
    grid-column: 1; grid-row: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none;
    align-content: start; gap: 14px; padding: calc(var(--back-row) + 6px) 8px 12px; margin-top: 0; margin-inline: -8px; /* (its edges, which clip, 8px out: the trailer's mark's reach, 4px out of line, not cut off) */
  }
  /* more of it below, to scroll to (cards.js's moreBelow): its foot fades, so a chip cut off there
     plainly goes on (the mask's the box's, still as it scrolls) */
  .times-cover .sided .st-head.more {
    -webkit-mask-image: linear-gradient(#000 calc(100% - 12px), transparent);
    mask-image: linear-gradient(#000 calc(100% - 12px), transparent);
  }
  .times-cover .sided .st-head::-webkit-scrollbar { display: none; }
  .times-cover .sided .st-title { font-size: 1.3rem; }
  .times-cover .sided .st-title::before { content: none; } /* (no buttons beside it: they're over it) */
  .times-cover .sided .st-lead-in { display: grid; gap: 4px; }
  .times-cover .sided .st-what { margin-top: 4px; }
  .times-cover .sided .st-bar { margin-top: -2px; }
  .times-cover .sided .st-cinemas { flex-wrap: wrap; overflow: visible; mask-image: none; } /* (the column's to scroll, not the line) */
  /* the days, as many to a line as the column has room for, the rest on the next (as the chips):
     a week across doesn't fit a small phone's column, and a strip scrolled sideways hid them */
  .times-cover .sided .st-days { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 0 2px; overflow: visible; mask-image: none; box-shadow: none; } /* (46px: a day's name, TODAY the widest; a small phone's column 5 to a line, so 9 days in 2 lines) */
  .times-cover .sided .st-day-wide { grid-column: span 2; } /* (TONIGHT's name wider than one: two) */
  .times-cover .sided .st-day { min-width: 0; padding: 4px 0 6px; } /* (a little shorter, as upright's: 46px) */
  .times-cover .sided .st-scroll { grid-column: 2; grid-row: 1; padding-top: 6px; }
  .times-cover .sided .st-scroll > * { max-width: 460px; }
  /* the poster's crop behind the left column, from the screen's left edge, fading off to the right
     and down; quieter than upright's (its story and the days are over it, not just its name), and
     none over a seat map, as upright */
  .times-cover .times-view:has(.times-body.sided) .times-crop {
    left: calc(-1 * var(--sa-side)); right: auto; top: calc(-1 * var(--crop-t, 0px));
    width: calc(var(--sa-side) + 2px + var(--side-col) + 60px); height: 100svh; opacity: 0.38;
    -webkit-mask-image: linear-gradient(to right, #000 45%, transparent), linear-gradient(to top, transparent, #000 55%); -webkit-mask-composite: source-in;
    mask-image: linear-gradient(to right, #000 45%, transparent), linear-gradient(to top, transparent, #000 55%); mask-composite: intersect;
  }
  .times-cover .times-view:is(.seat-mode, .list-mode):has(.times-body.sided) .times-crop { opacity: 0; }

  /* its trailer: the whole screen, as big as fits, on black; the times under it as they were; its ×
     round, at the top right, clear of the notch */
  .table.times-cover .screen { inset: 0; height: auto; padding: 0; place-items: center; }
  .table.times-cover .screen-video { position: static; width: min(100vw - 2 * (var(--sa-r) + 54px), 100svh * 16 / 9); height: auto; box-shadow: none; } /* (54px each side, the ×'s and its 10px: where the screen's width is the limit, a small phone's, the × on the black beside it, not on the film) */
  .table.times-cover .times-close.screen-close {
    position: absolute; top: max(10px, env(safe-area-inset-top)); right: max(10px, var(--sa-r)); bottom: auto;
    width: 44px; height: 44px; padding: 0; justify-content: center; border-radius: 50%;
  }
  .table.times-cover .screen-close-label { display: none; }
  .table.times-cover.playing .times-view { translate: none; height: calc(var(--times-h, 100%) - env(safe-area-inset-top) - env(safe-area-inset-bottom)); }

  /* Preferences: a wide panel in the middle (no sheet: cards.js's makeSheet), nearly the screen's
     height, its title (and a note beside it, when there is one) across the top, the cinemas and the
     languages side by side under it, so nearly all of them are in sight at once; the experiences
     under those */
  .prefs { width: min(760px, calc(100vw - 2 * var(--sa-side))); max-height: calc(100svh - 2 * max(10px, env(safe-area-inset-top))); }
  .prefs form { --row-gap: 14px; --foot-fade: 28px; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--row-gap) 28px; } /* (14px and the head's 12/6: tight enough that a small phone's next cinema peeks in at the foot) */
  .prefs-head { grid-column: 1 / -1; padding-block: 12px 6px; }
  .prefs-intro { grid-column: 1 / -1; margin-block: 4px 0; }
  .prefs-head > div { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; }
  .prefs-showing { margin: 0; }
  /* the experiences under them both, across: their rows two by two, in the cinemas' and the
     languages' columns (the group's 10px either side, as theirs: so 8px between, not 28), read
     along; the hairlines over the second row on, the first's right one's none */
  .prefs :is([data-experiences], [data-ratings-pick]) { grid-column: 1 / -1; }
  .prefs [data-ratings-pick] .prefs-group { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 8px; } /* (two across, as the experiences: picked along) */
  .prefs [data-ratings-pick] .pref:nth-child(2)::before { content: none; }
  .prefs [data-experiences] .prefs-group { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 8px; }
  .prefs [data-experiences] .pref:nth-child(2)::before { content: none; }
  .prefs { scroll-padding-bottom: 32px; } /* (a switch tabbed to: clear of the fade at its foot, below) */
  /* more of it below, to scroll to (cards.js's prefsMore): its foot fades into the panel, as a
     film's left column's does, so a row cut off there plainly goes on */
  .prefs form::after { content: ""; grid-column: 1 / -1; position: sticky; bottom: 0; height: var(--foot-fade); margin-top: calc(-1 * (var(--foot-fade) + var(--row-gap))); pointer-events: none; background: linear-gradient(rgba(18, 17, 24, 0), var(--panel)); opacity: 0; transition: opacity .2s; }
  .prefs.more form::after { opacity: 1; }
}
/* on its side and short (a phone's 375 to 399px tall): the left column a little tighter at the top
   and in the days, so a film's first cinemas are whole in sight under them at rest */
@media (orientation: landscape) and (max-height: 399px) {
  .times-cover .sided .st-head { padding-top: var(--back-row); row-gap: 10px; } /* (10px, not 14: the third line of chips peeks in at the foot, under its fade) */
  .times-cover .sided .st-day { padding-block: 2px 4px; }
}
/* ——— A show's seat map on a phone (upright, or on its side: cards.js's dressSeats): the film it's
   for named at the top, by a small crop of its poster; when it's out, under its time; Book and
   Share in a frosted bar at the foot of the screen, in a thumb's reach, the page scrolling under it
   and ending clear of it. (The view stops short of the home bar already, its height less the safe
   area's: .times-cover .times-view.) On its side, two columns instead (below). Nowhere else ——— */
.seat-ends { display: none; }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .times-cover .seat-page { display: flex; flex-direction: column; padding-bottom: 0; -webkit-mask-image: none; mask-image: none; } /* (the bar's the foot now, not a fade) */
  .times-cover .seat-page::before { content: none; } /* (no pixel more than fits, for a touch screen's bounce: a page that fits stays put, its bar too, and one that's longer bounces anyway) */
  .times-cover .seat-page > * { flex: none; }
  .times-cover .seat-ends { display: block; justify-self: center; margin: 2px 0 0; font-size: 0.8rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; } /* (under the ticket) */
  .times-cover .seat-page > .seat-actions {
    position: sticky; bottom: 0; z-index: 3; flex-wrap: nowrap; gap: 10px;
    margin: auto -6px 0; padding: 10px; border-radius: 26px; /* (at the foot however short the page; its sides out to the page's edges) */
    background: rgba(12, 11, 14, 0.55); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
    -webkit-backdrop-filter: var(--frost); backdrop-filter: var(--frost); /* (as the film's buttons') */
  }
  .times-cover .seat-actions .seat-book { flex: 1; text-align: center; }
  .times-cover .seat-actions .seat-share { flex: none; }
  /* the seat map, large: the whole screen (clear of the notch and the home bar), its seats at a
     size to read, scrolled sideways from the middle (expandSeats), and a pinch for closer still;
     upright, at the top, under its time, not in the middle of the room left, and its legend
     straight under it. Faded at whichever end has more to scroll to, as the When line is
     (cards.js's fullEnds), so it's plain it goes on sideways. (The dialog's out of the .table,
     beside it in the page: expandSeats marks a phone's, .phone) */
  .seat-full.phone {
    inset: 0; margin: 0; width: 100vw; height: 100svh; height: 100dvh; border-radius: 0; box-shadow: none;
    padding: env(safe-area-inset-top) var(--sa-r, 0px) env(safe-area-inset-bottom) var(--sa-l, 0px);
  }
  .seat-full.phone .seat-full-head { padding: 18px 20px 6px; padding-right: 70px; }
  .seat-full.phone .seat-full-head .times-close { top: 14px; right: 14px; width: 44px; height: 44px; }
  .seat-full.phone .seat-full-map { flex: 0 1 auto; padding-inline: 20px; touch-action: pan-x pan-y pinch-zoom; align-content: start; place-items: start center; } /* (its own height, no more: the legend under it) */
  .seat-full.phone .seat-full-map .seats-svg { height: auto; } /* (its own height, from its width: not the box's, the drawing in the middle of it) */
  .seat-full.phone .seat-full-map { --end-fade: 40px; mask-image: linear-gradient(to right, #000 calc(100% - var(--end-fade)), transparent); }
  .seat-full.phone .seat-full-map.off-start { mask-image: linear-gradient(to right, transparent, #000 var(--end-fade), #000 calc(100% - var(--end-fade)), transparent); }
  .seat-full.phone .seat-full-map.at-end { mask-image: none; }
  .seat-full.phone .seat-full-map.off-start.at-end { mask-image: linear-gradient(to right, transparent, #000 var(--end-fade)); }
  .seat-full.phone .seat-full-legend { padding: 8px 20px 18px; }
}
/* on its side, two columns, as a film's times: on the left, under ‹ Showtimes and the bookmark,
   the film, the day and room, the time and when it's out, any note, and Book and Share at its
   foot, in a thumb's reach (no bar over the map: it's beside them); on the right, up to the top,
   the map, fitted to the height (its own scroll if it ever needs one), its legend and when its
   seats were checked under it. Without a map, why there's none in its place */
@media (orientation: landscape) and (max-height: 499px) {
  .times-cover .seat-page {
    display: grid; grid-template-columns: var(--side-col) minmax(0, 1fr); grid-template-rows: repeat(5, auto) minmax(0, 1fr) auto auto;
    align-content: stretch; gap: 0 28px; overflow-y: auto; padding-bottom: 14px; /* (Book's glow not cut off by the page's edge) */
  }
  /* the left column one box (cards.js's sideSeats): its head, guide and notes scroll in a part of
     their own when a short screen hasn't room for them all (faded at its foot while there's more,
     as a film's left column: .more), Book and Share under it, always in sight */
  .times-cover .seat-page > .seat-side { grid-column: 1; grid-row: 1 / -1; min-height: 0; display: flex; flex-direction: column; }
  .times-cover .seat-side-scroll { flex: 0 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; margin-inline: -8px; padding-inline: 8px; } /* (its edges, which clip, 8px out: a focused step's ring not cut off) */
  .times-cover .seat-side-scroll::-webkit-scrollbar { display: none; }
  .times-cover .seat-side.more .seat-side-scroll {
    -webkit-mask-image: linear-gradient(#000 calc(100% - 12px), transparent);
    mask-image: linear-gradient(#000 calc(100% - 12px), transparent);
  }
  .times-cover .seat-side-scroll > :is(.seat-guide, .seat-note) { margin-top: 12px; }
  .times-cover .times-view:has(.times-body.sided) .seat-side { padding-top: var(--back-row); } /* (a film's: its pages pulled up beside ‹ Showtimes, as its times; the left column clear of it) */
  .times-cover .seat-page > .seat-map { grid-column: 2; grid-row: 1 / 7; min-height: 120px; overflow: auto; overscroll-behavior: contain; scrollbar-width: none; }
  .times-cover .seat-page > .seat-map.loading { height: auto; max-height: none; aspect-ratio: auto; } /* (the column's height, as the map's) */
  .times-cover .seat-page > .seat-map-problem { align-self: start; } /* (why, at the top: its own height) */
  .times-cover .seat-page > .seat-map::-webkit-scrollbar { display: none; }
  .times-cover .seat-page .seats-svg { height: 100%; max-height: none; } /* (as big as fits the box, either way: the drawing kept whole) */
  .times-cover .seat-page > .seat-left { grid-column: 2; grid-row: 2 / 7; align-self: start; }
  .times-cover .seat-page > .seat-legend { grid-column: 2; grid-row: 7; margin-top: 8px; }
  .times-cover .seat-page > .seat-status { grid-column: 2; grid-row: 8; margin-top: 6px; }
  .times-cover .seat-side > .seat-actions {
    flex: none; margin-top: auto; padding-top: 12px; container-type: inline-size;
    display: flex; flex-wrap: nowrap; gap: 10px; align-items: center;
  }
  .times-cover .seat-actions .seat-book { flex: 1; min-width: 0; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .times-cover .seat-actions .seat-share { flex: none; }
  /* a small phone's column: Share just its icon, round, so Book's words fit beside it (its word
     still read aloud; "Link copied" over it a moment, as a seat's label: cards.js's .saying) */
  @container (max-width: 280px) {
    .times-cover .seat-actions .seat-share { position: relative; width: 44px; height: 44px; padding: 0; justify-content: center; }
    .times-cover .seat-actions .seat-share [data-share-label] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
    .times-cover .seat-actions .seat-share.saying [data-share-label] {
      right: 0; bottom: calc(100% + 8px); width: auto; height: auto; clip-path: none; padding: 6px 10px; border-radius: 8px;
      background: rgba(16, 15, 22, 0.96); box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent), 0 8px 24px rgba(0, 0, 0, 0.5);
      font-size: 0.78rem; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--ink);
    }
  }
  /* a narrow column (a small phone's): Book's words a little closer to its ends, so they fit on
     its one line, whole */
  @container (max-width: 220px) {
    .times-cover .seat-actions .seat-book { padding-inline: 14px; }
  }
  /* the large view: fitted to the screen's height, in the middle, as before */
  .seat-full.phone .seat-full-map { flex: 1; align-content: normal; place-items: center; }
  .seat-full.phone .seat-full-map .seats-svg { height: 100%; }
}
/* on its side and very short (Safari's bars showing, a small phone's): the seat page's left column
   tighter, so more of it's in sight over Book */
@media (orientation: landscape) and (max-height: 339px) {
  .times-cover .seat-side .seat-head { gap: 2px; }
  .times-cover .seat-side-scroll > :is(.seat-guide, .seat-note) { margin-top: 8px; }
  .times-cover .seat-side > .seat-actions { padding-top: 8px; }
}
/* a film only pointed at: in brief, plain text in the showtimes' place (the times faded out
   meanwhile); a click on it chooses it (previewOf, cards.js) */
.film-info { /* (out 10px either side, its text where it was: the room its rows' pulsing dots and their light need, as it scrolls, so clips) */
  position: absolute; inset: 0 -10px; z-index: 2; overflow-y: auto; scrollbar-width: none; cursor: pointer;
  display: grid; align-content: start; gap: 16px; padding: calc(6px + var(--times-lead, 0px)) 12px 40px; /* (beside the grid, down to line its day's line up with the grid's first heading: leadTimes) */
  opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s;
}
.film-info::-webkit-scrollbar { display: none; }
.info-mode .film-info { opacity: 1; visibility: visible; transition: opacity .3s var(--ease) .1s, visibility 0s; }
.info-mode :is(.times-pages, .times-close, .times-back) { opacity: 0; visibility: hidden; }
.times-pages, .times-close { transition: opacity .3s var(--ease), visibility 0s; }
.film-info p { margin: 0; }
.film-info .st-title { padding-right: 0; }
/* pointed at, By time's row's light: a soft glow inside it that follows the pointer (cards.js sets
   --gx and --gy): red, its trailers playing (as its time); else a neutral white, fainter. Behind it all (its chain's mark too), fading in and out. Without motion, no following: a
   still, faint wash. In a light of its own (.st-glow: the row's ::before and ::after have jobs) */
.st-one .st-time { --glow: var(--ink); --glow-k: 16%; } /* (lit all along, it must show) */
.st-one .st-time.now { --glow: var(--now); --glow-k: 21%; }
.st-glow { position: absolute; inset: 0; z-index: -2; border-radius: inherit; pointer-events: none; }
.st-one .st-time > .st-glow { grid-area: auto; } /* (in no track: the whole row, its padding too, as the accent's was; not the time's line alone) */
@media (hover: hover) {
  .st-one .st-time:not(.chosen):hover { background-color: transparent; color: inherit; } /* (its light instead of the accent's) */
  /* no rim: the whole row lit evenly in its dot's colour (it's the row you'd tap, as the accent
     said), and a brighter glow under the pointer over it */
  .st-glow::before {
    content: ""; position: absolute; inset: 0; z-index: -2; border-radius: inherit; pointer-events: none; opacity: 0; transition: opacity .3s var(--ease);
    background:
      radial-gradient(160px circle at var(--gx, 50%) var(--gy, 50%), color-mix(in srgb, var(--glow) calc(var(--glow-k) * 0.9), transparent), transparent 75%),
      color-mix(in srgb, var(--glow) calc(var(--glow-k) * 0.6), transparent);
  }
  .st-time:hover > .st-glow::before { opacity: 1; }
}
@media (hover: hover) and (prefers-reduced-motion: reduce) {
  .st-glow::before { background: color-mix(in srgb, var(--glow) calc(var(--glow-k) / 2), transparent); transition: none; }
}
.film-info > .info-hint { margin: -6px 0 -2px; } /* (a film pointed at: under its name, over the line before all about it; as the seat hint, .st-seat-hint) */
/* the preview of a film pointed at: what it is, all of it, as under its times (cards.js's aboutOf), right under its name */
.film-info > .info-about { margin-top: 4px; padding-top: 14px; }

/* the scores, on their own line under what it is, each named in a quiet word ("94% critics") */
.info-scores { display: flex; flex-wrap: wrap; gap: 6px 16px; width: 100%; }
.info-score { display: inline-flex; align-items: center; gap: 5px; font-size: 0.86rem; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.info-score img { width: 15px; height: 15px; object-fit: contain; }
.info-score-label { font-size: 0.8rem; font-weight: 500; color: var(--ink-faint); }
.info-score.few { color: var(--ink-faint); } /* an IMDb rating from too few votes to count */
.st-head > .info-scores { margin-top: -8px; } /* the cards' showtimes: just under the film's name */
/* what it is and its scores, in a line, with its story under them */
.info-line { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.info-meta { margin: 0; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft); }
/* after its showtimes, what it is: runtime, genres and scores, its story, director and cast */
.info-about { display: grid; gap: 12px; margin-top: -16px; padding-top: 14px; border-top: var(--rule); } /* (-16px: with the panel's 20px gap, its line's as far below the last time as a cinema's is, and as far above its text) */
.info-summary { margin: 0; font-size: 0.92rem; line-height: 1.6; color: var(--ink-soft); text-wrap: pretty; }
.info-about > :is(.info-summary ~ .info-line, * + .info-credits) { margin-top: 10px; padding-top: 18px; border-top: var(--rule); } /* (its story, its line, who made it: each set apart as its age rating is) */
.info-credits { margin: 0; display: grid; gap: 10px; font-size: 0.86rem; line-height: 1.45; }
.info-credits div { display: grid; grid-template-columns: 74px 1fr; gap: 12px; }
.info-credits dt { padding-top: 2px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-faint); }
.info-credits dd { margin: 0; color: var(--ink-soft); }
/* a film's genres, all of them (cards.js's genreChips): each a chip in a room's badge's look, a
   little bigger to be pressed, its outline lit pointed at or focused */
.genre-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; padding: 0; list-style: none; }
.genre-chips > li { display: flex; }
.genre-chip { height: 22px; padding: 0 9px; border-radius: 6px; font-size: 11.5px; }
button.genre-chip { border: 0; background: transparent; font-family: inherit; cursor: pointer; transition: box-shadow .2s, color .2s; }
button.genre-chip:hover, button.genre-chip:focus-visible { color: var(--ink); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 70%, transparent); outline: none; }
button.genre-chip:active { transform: scale(0.96); }
@media (prefers-reduced-motion: reduce) { button.genre-chip { transition: none; } button.genre-chip:active { transform: none; } } /* (after the rules it undoes: before them, it never won) */
.st-genres { display: none; } /* (a phone's, under its film's line: see below) */
/* a name linked to its Rotten Tomatoes page: as the text, underlined when pointed at */
.info-credit { color: inherit; text-decoration: none; text-underline-offset: 3px; text-decoration-color: rgba(244, 241, 234, 0.4); }
@media (hover: hover) { .info-credit:hover { color: var(--ink); text-decoration-line: underline; } }
.info-credit:focus-visible { color: var(--ink); text-decoration-line: underline; }
/* the film chosen's trailer, up top by the bookmark, as tall as it, beside the cards (their view,
   put away for now): over a seat map, where the film's name (and its mark, .st-play) has slid
   aside; lit in the accent while it plays. In the grid, none (below) */
.times-trailer {
  position: absolute; top: calc(6px + (1.5rem * 1.1 - 34px) / 2); right: 88px; z-index: 1; height: 34px;
  display: inline-flex; align-items: center; gap: 7px; padding: 0 13px 0 10px; border-radius: 99px; cursor: pointer;
  border: 1px solid var(--pill-line); background: var(--pill-fill); color: var(--ink);
  font: inherit; font-size: 0.8rem; font-weight: 600;
  transition: background .15s, border-color .15s, color .15s, opacity .3s var(--ease), visibility 0s, transform .2s var(--ease);
}
.times-trailer .yt { width: 16px; height: 11.5px; }
@media (hover: hover) { .times-trailer:hover { background: rgba(255, 255, 255, 0.12); border-color: var(--pill-line-hover); } }
.times-trailer:active { transform: scale(0.93); transition-duration: .06s; }
.playing .times-trailer { border-color: color-mix(in srgb, var(--accent) 70%, transparent); color: var(--accent); }
.table:not(.times-cover, .grid-mode) .times-trailer { right: 44px; } /* (beside the cards: the bookmark's in the ×'s place) */
.list-mode .times-trailer, .info-mode .times-trailer { opacity: 0; visibility: hidden; } /* (several films, or one in brief: as the bookmark) */
.times-cover .times-trailer { right: 44px; } /* (a phone: the bookmark's in the ×'s place) */
.times-cover.playing .times-trailer { opacity: 0; visibility: hidden; } /* (the video's × in its place) */
.times-view:not(.seat-mode) .times-trailer { display: none; } /* (by its name instead: .st-play) */
.grid-mode .times-trailer { display: none; } /* (in the grid, never: by its name, and not over a seat map, which is about its seats; "‹ Showtimes" is a tap away) */

/* each heading with its films: a section across the grid, on the grid's own columns */
.grid-section {
  grid-column: 1 / -1; display: grid; gap: inherit;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr)); /* (without subgrid: the same columns) */
  grid-template-columns: subgrid;
}
.grid-section + .grid-section { margin-top: 14px; }
/* the grid's headings: when the films under them next show, big enough to catch the eye between
   the posters, with a hairline on to the edge. Scrolled, a heading stays at the top over its
   films, their bookmarks too, until the next one pushes it out; right across the grid, its room
   beside the cards too (one lifted and tilted there is under it). A card pointed at that's clear
   of it, lifted, rises over it instead (.risen: see cards.js's rise). */
.grid-group {
  grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; margin: -8px -20px; padding: 12px 20px;
  position: sticky; top: -8px; z-index: 4; /* (over the grid's own 8px padding, its text just clear of the fade at the top; above a little card pointed at, its 1) */
  font-size: 1.2rem; font-weight: 750; letter-spacing: -0.01em; color: var(--ink);
}
.grid-group::after { content: ""; flex: 1; height: 1px; background: rgba(255, 255, 255, 0.16); }
/* a few films' one line, on a phone (cards.js's fewLine): what they are, quietly, not a heading */
.grid-few { font-size: 0.86rem; font-weight: 600; letter-spacing: 0; color: var(--ink-soft); }
.grid-few > span:not(.ambient) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grid-few::after { display: none; } /* (no hairline along it, as the bands' headings have none) */
/* what it stands on: the room itself, the grid cut away under it (cards.js's drawHeads: the
   grid's mask), and so it is too: drawn again there, under the grid (.grid-heads), just where it
   is, showing through the cut. As the grid is, there and gone with it; never pointed at (the
   grid's own heading is, over it) */
.grid-heads {
  position: absolute; z-index: var(--z-grid); overflow: hidden; pointer-events: none; /* (before the grid: under it) */
  opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s;
}
.grid-mode .grid-heads { opacity: 1; visibility: visible; transition: opacity .3s var(--ease), visibility 0s; }
.grid-mode.times-cover.showing-times .grid-heads { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s; }
.grid-heads > .grid-group { position: absolute; margin: 0; box-sizing: border-box; animation: none; }
html.page-scroll .grid-heads { display: none; }
.grid-group-note { font-size: 0.85rem; font-weight: 500; letter-spacing: 0; color: var(--ink-faint); }
/* a search for now's headings (cards.js's NOW_HEADS): the showtimes' dot before each, red or green;
   the note on one line, cut short where it runs out of room, and on a phone gone */
.time-head { white-space: nowrap; }
.time-head .day-soon-dot { flex: none; width: 8px; height: 8px; }
.time-head > span:not(.grid-group-note) { flex: none; }
.time-head .grid-group-note { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.time-head::after { min-width: 12px; }
@media (max-width: 777px) { .time-head .grid-group-note { display: none; } }
/* a Top Rated heading's ⓘ, and what it says (cards.js's sayTier): how its films are put there */
.tier-info {
  position: relative; flex: none; display: grid; place-items: center; width: 20px; height: 20px; margin-left: -2px; padding: 0; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.32); background: none; color: var(--ink-soft); cursor: pointer;
  transition: color .15s, border-color .15s, background .15s, transform .15s var(--ease);
}
.tier-info::after { content: ""; position: absolute; inset: -6px; border-radius: 50%; } /* (a little more than it's drawn, to a pointer too) */
.tier-info svg { display: block; width: 18px; height: 18px; fill: currentColor; }
/* (its "i", a serif italic, a drawn path: Georgia Bold Italic's, as Chrome drew the text it was, its
   ink in the ring's very middle, not where its letter box would put it; as text, Safari on an iPhone
   set it off-centre) */
/* pointed at, a purple wash; pressed, it dips; open, solid purple, so it's plain whose card it is */
@media (hover: hover) { .tier-info:is(:hover, .lit) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); } }
.tier-info:active { transform: scale(0.88); }
.grid-heads .tier-info.keyed { outline: 2px solid var(--accent); outline-offset: 2px; } /* (its heading's, keyed to: :focus-visible's, drawn in the cut: cards.js's lightHead) */
.tier-info[aria-expanded="true"] { border-color: var(--accent); background: var(--accent); color: var(--panel); }
.tier-pop {
  position: fixed; inset: auto; margin: 0; width: min(320px, calc(100vw - 24px)); padding: 16px 18px; box-sizing: border-box;
  border-radius: 14px; border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(20, 18, 24, 0.97);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55); color: var(--ink); font-size: 0.86rem; line-height: 1.45;
}
.tier-pop h4 { margin: 0 0 4px; font-size: 1rem; }
.tier-pop p { margin: 0 0 10px; color: var(--ink-soft); }
.tier-pop .tier-pop-calc { font-size: 0.76rem; color: var(--ink-faint); }
.tier-pop .tier-pop-film { margin-bottom: 4px; font-size: 0.8rem; color: var(--ink-faint); }
.tier-pop-film b { font-weight: 600; color: var(--ink-soft); }
.tier-pop .tier-pop-sum { margin-bottom: 12px; color: var(--ink); }
/* each score's scale: poor, in between and good, as rounded pills, the cut-offs under the gaps;
   the example's score a dot on it, its part lit and the rest dim, its score at the end in its
   colour; a score that doesn't count (none yet, or IMDb's from too few votes), the scale faded */
.tier-pop-scales {
  display: grid; gap: 12px; padding-top: 12px; border-top: 1px solid rgba(255, 255, 255, 0.1);
  --poor: var(--full-most); --between: rgba(255, 255, 255, 0.55); --good: var(--full-low);
}
.tier-key { display: flex; gap: 12px; font-size: 0.68rem; color: var(--ink-faint); }
.tier-key span { display: inline-flex; align-items: center; gap: 5px; }
.tier-key span::before { content: ""; width: 14px; height: 5px; border-radius: 3px; }
.tier-key .poor::before, .tier-scale-track .poor { background: var(--poor); }
.tier-key .between::before, .tier-scale-track .between { background: var(--between); }
.tier-key .good::before, .tier-scale-track .good { background: var(--good); }
.tier-scale { display: grid; grid-template-columns: 56px 1fr 34px; align-items: center; gap: 10px; padding-bottom: 13px; } /* (the cut-offs' room under the whole row: its name, scale and score on one line) */
.tier-scale-name { font-size: 0.74rem; color: var(--ink-soft); }
.tier-scale-track { position: relative; display: flex; gap: 3px; height: 7px; }
.tier-scale-track > i { height: 100%; border-radius: 4px; opacity: 0.35; }
.tier-scale-track > i.on { opacity: 1; box-shadow: 0 0 10px color-mix(in srgb, currentColor 45%, transparent); }
.tier-scale-track > i.poor { color: var(--poor); }
.tier-scale-track > i.between { color: var(--between); }
.tier-scale-track > i.good { color: var(--good); }
.tier-scale-track b { position: absolute; top: 100%; margin-top: 4px; translate: -50% 0; font-size: 0.64rem; font-weight: 400; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.tier-scale-dot {
  position: absolute; top: 50%; width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; border-radius: 50%;
  background: var(--ink); box-shadow: 0 0 0 2.5px rgba(20, 18, 24, 0.97), 0 1px 4px rgba(0, 0, 0, 0.6);
}
.tier-scale-value { font-size: 0.8rem; font-weight: 650; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--ink-soft); }
.tier-scale-value.good { color: var(--good); }
.tier-scale-value.poor { color: var(--poor); }
.tier-scale.uncounted .tier-scale-track { opacity: 0.45; }
.tier-pop .tier-pop-foot { margin: 0; font-size: 0.7rem; color: var(--ink-faint); }
/* by Rotten Tomatoes': its icons inline with its terms (the cards' own, small, on the text's line;
   decorative), and a key under the rule, quieter, saying what the band's terms mean */
.rt-mark { display: inline-block; width: 1.05em; height: 1.05em; margin: 0 0.18em 0 0.05em; object-fit: contain; vertical-align: -0.17em; }
.tier-terms { display: grid; gap: 6px; margin: 10px 0 0; padding: 10px 0 0; border-top: 1px solid rgba(255, 255, 255, 0.1); font-size: 0.74rem; line-height: 1.4; color: var(--ink-faint); }
.tier-terms dt { display: inline; font-weight: 600; color: var(--ink-soft); }
.tier-terms dt::after { content: ":"; }
.tier-terms dd { display: inline; margin: 0 0 0 0.3em; }
.keep-together { white-space: nowrap; } /* (an icon with its word: cards.js's sayRule) */
.tier-terms dt .rt-mark + .rt-mark { margin-left: -0.05em; }
/* What's Hot's top band (150+ screenings), on fire: a flame before it, flickering, its tip
   swaying from its base, and the words themselves burning, a fire's colours drifting up through
   them under a warm glow. Still, for reduced motion. */
.flame { flex: none; width: 30px; height: 30px; margin: -6px -6px -6px -4px; overflow: visible; filter: drop-shadow(0 0 4px rgba(255, 110, 30, 0.6)); }
.flame-outer { fill: #ff6b1f; transform-origin: 50% 95%; animation: flicker 1.7s ease-in-out infinite; }
.flame-core { fill: #ffc94d; transform-origin: 50% 95%; animation: flicker 1.3s ease-in-out infinite reverse; }
@keyframes flicker {
  0%, 100% { transform: scale(1, 1) skewX(0deg); }
  25% { transform: scale(0.97, 1.06) skewX(-3deg); }
  50% { transform: scale(1.02, 0.95) skewX(2deg); }
  75% { transform: scale(0.98, 1.04) skewX(-1.5deg); }
}
.fire-words {
  background: linear-gradient(0deg, #ff4d1a, #ff8a1f 35%, #ffc94d 60%, #ff8a1f 85%, #ff4d1a) 0 0 / 100% 300%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 6px rgba(255, 100, 30, 0.45));
  animation: burn 2.4s linear infinite;
}
@keyframes burn { to { background-position: 0 -300%; } }
@media (prefers-reduced-motion: reduce) { :is(.flame-outer, .flame-core, .fire-words) { animation: none; } }
@media (forced-colors: active) { .fire-words { color: CanvasText; background: none; } }
/* Top Rated's top tier (Rated highly), in gold: sparkles before it (rated-highly-icons.js's, mocked
   with the others), a glint twinkling at their top right, and the words in the cards' gold, a sheen
   sweeping across them now and then under a soft glow. Still, for reduced motion. */
.defs { position: absolute; }
.tier-mark { flex: none; width: 24px; height: 24px; margin: -4px -4px -4px -2px; overflow: visible; filter: drop-shadow(0 0 5px rgba(233, 207, 142, 0.55)); }
.tier-mark-fill { fill: url(#tier-gold); }
.tier-mark-glint { fill: #fff; transform-origin: 20px 4px; animation: twinkle 2.6s ease-in-out infinite; }
@keyframes twinkle {
  0%, 60%, 100% { transform: scale(0) rotate(0); opacity: 0; }
  75% { transform: scale(1.2) rotate(45deg); opacity: 1; }
  90% { transform: scale(0.6) rotate(90deg); opacity: 0.6; }
}
.gold-words {
  background: linear-gradient(100deg, #c99a3c 0%, #e9cf8e 35%, #fff6d6 50%, #e9cf8e 65%, #c99a3c 100%) 0 0 / 250% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 6px rgba(233, 207, 142, 0.35));
  animation: sheen 3.2s ease-in-out infinite;
}
@keyframes sheen { 0% { background-position: 100% 0; } 60%, 100% { background-position: -50% 0; } }
@media (prefers-reduced-motion: reduce) { :is(.tier-mark-glint, .gold-words) { animation: none; } .tier-mark-glint { opacity: 0; } }
@media (forced-colors: active) { .gold-words { color: CanvasText; background: none; } }

/* a little card (as the big ones: 63 × 88, the corners, the shade behind the name), then its next
   show under it. Pointed at, it lifts and tilts toward the pointer, a soft light under it; pressed,
   it dips, and let go, springs back up; the one chosen is ringed, and stays lifted (cards.js: lean,
   pickUp). Only the layer it's on moves (.tile-lift: the card and its bookmark), by its transform. */
.film-tile {
  position: relative; display: grid; align-content: start; min-width: 0;
  transition: z-index 0s .5s; /* let go: kept over the rest till it's back down (.tile-lift's .5s) */
}
.film-tile.pointed { z-index: 1; transition-delay: 0s; } /* (over its neighbours, as it grows: still under the headings' 4) */
/* lifted clear of its heading (not scrolled under it): over it, not cut off by it as it grows up
   toward it (cards.js's rise) */
.film-tile.risen:is(.tracking, .chosen) { z-index: 5; transition-delay: 0s; }
.film-tile.chosen { transition: none; } /* (it stays lifted: scrolled under its heading, under it at once) */
.tile-lift {
  position: relative;
  transform-origin: 50% 60%; /* (it tilts round a point a little below its middle, as a card held there would) */
  transition: transform .5s var(--ease); /* let go: back down on the table */
}
.film-tile.tracking .tile-lift { transition: transform .16s cubic-bezier(.2, .8, .4, 1); } /* following the pointer, a moment behind it */
.film-tile.tracking.pressed .tile-lift { transition: transform .09s cubic-bezier(.2, .8, .4, 1); } /* pressed: down at once */
/* let go of a press: up on a spring, overshooting a little, back, and settling (a damped spring:
   ζ 0.45; cards.js's springUp, for SPRING_TIME). (Where linear() isn't known, a curve that
   overshoots once.) */
.film-tile.springing .tile-lift {
  transition: transform .45s cubic-bezier(.3, 1.6, .5, 1);
  transition: transform .72s linear(0, 0.11, 0.361, 0.65, 0.904, 1.084, 1.181, 1.205, 1.178, 1.125, 1.066, 1.015, 0.98, 0.962, 0.958, 0.964, 0.976, 0.988, 0.998, 1.005, 1.008, 1.009, 1.007, 1.005, 1);
}
/* the one chosen, let go of: lifted as it was pointed at, level (the same functions as lean's, so
   it goes between them smoothly) */
.film-tile.chosen:not(.tracking) .tile-lift { transform: perspective(700px) translateY(-7px) scale(1.05) rotateX(0deg) rotateY(0deg); }
/* lifted: a deeper shadow under it, faded in (not a box-shadow redrawn as it moves) */
.tile-lift::before {
  content: ""; position: absolute; inset: 0; border-radius: 4.6% / calc(4.6% * 63 / 88); pointer-events: none;
  box-shadow: 0 0 0 1px rgba(255, 240, 200, 0.36), 0 28px 42px -20px rgba(0, 0, 0, 0.95);
  opacity: 0; transition: opacity .3s var(--ease);
}
.film-tile:is(.pointed, .chosen) .tile-lift::before { opacity: 1; }
.film-tile.pressed .tile-lift::before { opacity: 0.35; transition-duration: .09s; } /* (down on the table: hardly any) */
.tile-card {
  position: relative; display: block; width: 100%; aspect-ratio: 63 / 88; overflow: hidden; padding: 0; border: 0; cursor: pointer;
  isolation: isolate; /* (its layers stay inside it: all of it under a heading stuck at the top) */
  border-radius: 4.6% / calc(4.6% * 63 / 88); background: #15131b; color: var(--ink); font: inherit; text-align: left;
  box-shadow: 0 0 0 1px rgba(255, 240, 200, 0.16), 0 10px 22px -12px rgba(0, 0, 0, 0.9);
  container-type: inline-size; /* (its seals sized by it: cqw) */
  /* held down on a touch screen: no iOS callout (the poster's "Save Image") or text selection */
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
/* the light (as the grid's design D had it): a glare, always on, a bright spot falling off into
   shade (overlay: the poster's own lights lifted and its darks deepened, as a glossy card catches
   the light). At rest, in the middle; pointed at, much brighter, its spot under the pointer (slid
   there by cards.js's lean: it's twice the card's size, its middle on the spot); pressed, down out
   of the light a little. */
.tile-glare {
  position: absolute; inset: 0; z-index: 4; pointer-events: none;
  background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.75) 0%, rgba(255, 255, 255, 0.2) 18%, rgba(0, 0, 0, 0.3) 48%) 50% 50% / 200% 200% no-repeat;
  mix-blend-mode: overlay;
  opacity: 0.3;
  transition: opacity .35s var(--ease), background-position .6s var(--ease);
}
/* (its light twice the card's size, its spot moved by where it's drawn in the card (cards.js's lean:
   background-position), not a layer twice its size moved over it: that, on every card, was most of
   a slow frame on a phone each time the page was drawn again, as a film closed or a sheet opened) */
.film-tile.tracking .tile-glare { transition: opacity .35s var(--ease), background-position .16s cubic-bezier(.2, .8, .4, 1); } /* (following the pointer) */
.film-tile:is(.tracking, .chosen) .tile-glare { opacity: 0.85; }
.film-tile.tracking.pressed .tile-glare { opacity: 0.5; transition-duration: .09s, .16s; }
/* picked up (chosen): a sheen sweeps across it, a soft band, skewed as a reflection would be
   (cards.js's pickUp moves it; at rest, off past its right edge). Overlay too: the poster's own
   colours lit up as it passes, not white laid over them. */
.tile-sheen {
  position: absolute; top: -10%; bottom: -10%; left: 0; z-index: 5; width: 45%; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4) 50%, transparent);
  mix-blend-mode: overlay;
  transform: translateX(270%);
}
.tile-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 20%; }
/* the name, only on a film with no poster */
.tile-name {
  position: absolute; left: 10%; right: 10%; bottom: 9%; z-index: 3;
  font-size: 0.86rem; font-weight: 800; line-height: 1.12; letter-spacing: -0.02em; text-wrap: balance;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.7);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* its awards' seals (cards.js's tileSeals), the card's made small: each award's icon on a dark
   disc in a gold rim, a coin more than a stamp, with no name round it (at this size, a few pixels
   high). Bottom left: over a poster's small print (its credits, its date), clear of the bookmark,
   and over its title less often than any other corner (tried on all of them). Two overlap, as on
   the card. They lift with the card, as they're on it. */
.tile-seals {
  position: absolute; left: 3.5cqw; bottom: 3.5cqw; z-index: 2; display: flex; pointer-events: none;
  --d: max(22cqw, 34px); /* (each one across: never smaller than its icon can be made out) */
}
.tile-name ~ .tile-seals { top: 3.5cqw; bottom: auto; } /* (no poster: the name's at the bottom) */
.tile-seal {
  --seal: #fa320a; /* the award's colour, a glow from within */
  display: grid; place-items: center; width: var(--d); aspect-ratio: 1; border-radius: 50%;
  border: calc(var(--d) * 0.06) solid transparent; /* the rim: the gold's drawn under it */
  background:
    radial-gradient(circle at 50% 30%, #33211b, #0b090d 75%) padding-box,
    conic-gradient(from 210deg, #fff4cf, #c99a45, #f8e6b0, #7d5a22, #fbe6ad, #a77a33, #fff4cf) border-box;
  box-shadow:
    inset 0 0 0 calc(var(--d) * 0.02) rgba(0, 0, 0, 0.55), /* (the rim's inner edge) */
    inset 0 0 calc(var(--d) * 0.11) color-mix(in srgb, var(--seal) 35%, transparent),
    0 0 0 1px rgba(0, 0, 0, 0.35), 0 calc(var(--d) * 0.05) calc(var(--d) * 0.12) rgba(0, 0, 0, 0.7);
}
.tile-seal.seal-hot { --seal: #ff8a00; transform: rotate(8deg); }
.tile-seal + .tile-seal { margin-left: calc(var(--d) * -0.18); }
.tile-seal img {
  width: 57%; height: 57%; object-fit: contain;
  filter: drop-shadow(0 0 calc(var(--d) * 0.05) color-mix(in srgb, var(--seal) 70%, transparent));
}
/* the film chosen: ringed, as the toggles show what's on */
.film-tile.chosen .tile-card, .film-tile.chosen.pointed .tile-card {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent), 0 14px 28px -12px rgba(0, 0, 0, 0.95);
}
/* its next show: its time, and starting soon, how soon ("in 20 min", "trailers playing"). Off for
   now (the owner's, 24 Oct 2026): a tile is a film to choose, its times in the panel; read out still,
   with its name (cards.js's sayWhen). Its rules kept, to bring it back. */
.tile-when { display: none !important; }
.tile-when {
  display: flex; align-items: center; gap: 7px; margin-top: 9px; min-width: 0; white-space: nowrap; overflow: hidden;
  font-size: 0.78rem; color: var(--ink-faint); font-variant-numeric: tabular-nums;
}
.tile-when b { font-weight: 600; color: var(--ink-soft); }
.tile-when span { overflow: hidden; text-overflow: ellipsis; }
.tile-when:is(.soon, .now) b { color: var(--ink); }
/* switching to the grid: the little cards laid out one after another, like a hand of cards (--n:
   its place, from cards.js) */
.grid-mode :is(.film-tile, .grid-group) { animation: tile-in .34s var(--ease) backwards; animation-delay: calc(40ms + var(--n, 0) * 22ms); }
.grid-mode .grid-group { animation-name: fade; }
.grid-mode .dealt :is(.film-tile, .grid-group) { animation: fade .3s var(--ease); } /* moved round as the clock goes on: just fade in place */
@keyframes tile-in { from { opacity: 0; transform: translateY(12px) scale(0.97); } }
@media (prefers-reduced-motion: reduce) {
  .grid-mode :is(.film-tile, .grid-group) { animation: none !important; }
  /* still: no lift, tilt or spring (cards.js draws none), just the shadow and the ring, and the
     glare at rest in the middle (a light, not a move) */
  .tile-lift, .film-tile.chosen:not(.tracking) .tile-lift { transform: none; transition: none; }
  .tile-glare { transition: none; }
  .tile-sheen { display: none; }
}

/* ——— The screen: the chosen film's trailer, in the grid's place (placed by cards.js: from the
   left margin to the grid's right edge), as big as fits there, its showtimes still beside it; the
   grid fades out from under it, and the lights go down. On a phone, docked at the top, full width,
   the showtimes moved down under it, so you can still find a time and seats as it plays. ——— */
.screen {
  position: fixed; z-index: var(--z-screen); display: grid; place-items: center; container-type: size;
  opacity: 0; visibility: hidden; transition: opacity .4s var(--ease), visibility 0s .4s;
}
.playing .screen { opacity: 1; visibility: visible; transition: opacity .5s var(--ease) .12s, visibility 0s; }
.grid-mode.playing .grid-view { opacity: 0; visibility: hidden; transition: opacity .35s var(--ease), visibility 0s .35s; }
body:has(.table.playing) .ambient img.on { opacity: 0.3; }
.screen-video {
  position: relative; width: min(100cqw, calc((100cqh - 100px) * 16 / 9)); aspect-ratio: 16 / 9; border-radius: 12px; background: #000;
  box-shadow: 0 0 0 1px rgba(255, 240, 200, 0.14), 0 40px 100px -30px rgba(0, 0, 0, 0.95);
  transform: scale(0.96); transition: transform .7s var(--set-off);
}
.playing .screen-video { transform: none; }
.screen-video iframe { display: block; width: 100%; height: 100%; border: 0; border-radius: inherit; background: #000; }
/* beside the panel, its top level with the film's name (placeScreen), its × on its corner */
.table:not(.times-cover) .screen { place-items: start center; }
.table:not(.times-cover) .screen-video { width: min(100cqw, calc(100cqh * 16 / 9)); }
.times-close.screen-close { display: grid; top: -13px; right: -13px; background: rgba(22, 20, 28, 0.96); border-color: rgba(255, 255, 255, 0.22); }
/* a phone: docked at the top (below its notch), the showtimes moved down under it, its × in the
   Trailer button's place beside the bookmark. The video full width, but never more than 45% of the
   screen's height (a short screen, or a wide one: the times keep the rest), then as wide as that
   allows, centred on the black: --dock-v the video's height, --dock-h the dock's, its notch too */
.times-cover {
  --dock-v: min(100vw * 9 / 16, 45svh);
  --dock-h: calc(var(--dock-v) + env(safe-area-inset-top));
}
.times-cover .screen {
  inset: 0 0 auto 0; height: var(--dock-h);
  padding: env(safe-area-inset-top) 0 0; place-items: stretch; background: #000;
}
.times-cover .screen-video { position: static; /* (its × placed from the dock's edges, not the video's) */ justify-self: center; width: min(100%, var(--dock-v) * 16 / 9); height: 100%; border-radius: 0; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.7); transform: none; }
.times-cover .times-close.screen-close { top: auto; bottom: -60px; right: 60px; z-index: 2; } /* (level with the bookmark) */
.screen-close-label { display: none; }
/* there, in the Trailer button's place, it says what it closes: "× Trailer", a pill as that button is */
.times-cover .times-close.screen-close {
  display: inline-flex; align-items: center; gap: 7px; width: auto; padding: 0 13px 0 11px; border-radius: 99px;
  font: inherit; font-size: 0.8rem; font-weight: 600; color: var(--ink);
}
.times-cover .screen-close-label { display: inline; }
.times-cover.playing .times-view { /* (moved down: its transition, with .times-cover .times-view's) */
  translate: 0 calc(var(--dock-v) + 8px); /* (from where it was, under the notch already) */
  height: calc(var(--times-h, 100%) - env(safe-area-inset-top) - env(safe-area-inset-bottom) - var(--dock-v) - 8px);
}
@media (prefers-reduced-motion: reduce) {
  .screen-video { transform: none; transition: none; }
  .times-cover .times-view { transition: none; } /* (as without the trailer: below) */
}

.table.empty:not(.grid-mode) :is(.stack, .deck-nav, .deck-actions) { display: none; }
/* in the grid, When and Where stay where they are, over nothing: another day, another cinema, a
   tap away; the words why over the middle, out of the layout (which would move them down) */
.table.empty.grid-mode .grid-view { visibility: hidden; }
.table.empty.grid-mode .stack { transform: translateX(calc(-1 * var(--shift, 0px))); } /* (where it is beside the times, though there are none: When and Where don't move) */
.table.empty.grid-mode.pick-roll .stack { transform: none; } /* (on a phone the times cover the films, never beside them: the lines, in the grid, stay where they are) */
.table.empty.grid-mode.pick-roll .deck-empty { top: var(--empty-y, 50%); } /* (and the words under them: cards.js's fitEmpty) */
.table.empty.grid-mode.pick-roll.empty-bare .pickers { visibility: hidden; } /* (no room for the words under them: the words alone, as wider) */
.table.empty.grid-mode .deck-empty { position: absolute; z-index: var(--z-grid-over); left: 50%; top: 50%; translate: -50% -50%; }
.deck-empty { margin: 0; max-width: 340px; text-align: center; color: var(--ink-soft); line-height: 1.6; }
.empty-found-words { display: block; color: var(--ink); font-weight: 600; text-wrap: balance; } /* (none found, as the search says it) */
.empty-hidden { display: block; margin-top: 6px; font-weight: 400; color: var(--ink-soft); } /* (what your preferences hide of it, and the way to show it: cards.js's hiddenSaid) */
.empty-ways { justify-content: center; margin: 14px 0 12px; line-height: normal; } /* (its ways out, as the search's: .find-ways) */
.empty-ways:empty { display: none; }
.link { border: 0; background: none; padding: 0; color: var(--accent); font: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }

/* ——— Trailer: the video over everything ——— */

.trailer {
  width: min(92vw, 1120px, calc(86svh * 16 / 9)); max-width: none; padding: 0; border: 0; overflow: visible;
  background: transparent;
}
.trailer::backdrop { background: rgba(4, 4, 6, 0.82); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.trailer[open] { animation: rise .35s var(--ease); }
.trailer-video {
  position: relative; aspect-ratio: 16 / 9; overflow: hidden; border-radius: 14px; background: #000;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent), 0 40px 120px rgba(0, 0, 0, 0.8);
}
.trailer-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.trailer form { position: absolute; top: -48px; right: 0; margin: 0; }
/* a phone on its side: short enough for its × above it */
@media (orientation: landscape) and (max-height: 499px) { .trailer { width: min(92vw, calc((100svh - 110px) * 16 / 9)); } }
@keyframes rise { from { opacity: 0; transform: translateY(14px) scale(0.98); } }

/* ——— A finger's reach: on a touch screen every control takes a tap about 44px across (Apple's
   guide), more than a pointer needs. The small round ones and the links answer a little beyond
   what's drawn, so they look the same; rows and pills just grow a little. ——— */
@media (pointer: coarse) {
  :is(.times-close, .trailer-close, .seat-expand, .seat-back, .view-toggle button, .deck-button, .prefs-open, .when-clear, .short-toggle, .times-save, .seat-party-step)::after {
    content: ""; position: absolute; inset: -5px;
  }
  .trailer-close, .seat-back, .view-toggle button, .deck-button, .prefs-open, .when-clear, .seat-party-step { position: relative; }
  .seat-party-step::after { inset: -4px; } /* (36px drawn: tapped again and again) */
  .times-cover .times-save::after { inset: -6px; } /* (taking the screen, in its corner: 44px to a finger whole, 34px drawn) */
  .seat-expand::after { inset: -7px; }
  .tier-info::after { inset: -12px; } /* (20px drawn: 44px to a finger) */
  .view-toggle button::after { inset: -6px 0; } /* (side by side: only up and down) */
  .when-clear::after { inset: -9px -6px; }
  .seat-back::after { inset: -5px -10px -5px -8px; }
  .deck-button::after, .prefs-open::after, .short-toggle::after { inset: -3px; }
  /* the chevrons either side of a seat map's time: stepping to the next show is what you do there */
  .seat-step { width: 44px; height: 44px; }
  .seat-pick { margin-left: -15px; } /* (the chevron where it was) */
  .st-time { padding-block: 11px; }
  .st-day { padding: 8px 0 12px; }
  .deck-action { padding-block: 11px; }
  .seat-book { padding-block: 13px; }
  .seat-share { padding-block: 12px; }
}
/* ——— On a phone (upright, or on its side), more of it: every button's tap 44px across, but each
   drawn as it was; the reach up and down, into the room between it and the next, never past
   halfway (so a tap just over a day is the day's, not Where's). Where a line scrolls along (and
   so clips what's beyond it), the line's given the height instead. The small words a little
   bigger, and brighter, so they read in a dark room ——— */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  /* When, Where and Sort: each line 44px, its buttons in the middle of it, reaching its edges
     (they were 30px, 4px apart; they scroll away with the films, so the 30px more costs nothing
     once you're looking) */
  .pick-roll .pick-line + .pick-line { margin-top: 0; }
  .pick-roll .grid-view > .pickers { margin-bottom: -14px; } /* (the first heading 4px lower: it was over Sort's reach) */
  .pick-roll :is(.pick-days, .pick-cinemas, .pick-sorts) { height: 44px; align-items: center; }
  .pick-roll :is(.pick-tile, .where-pick, .sort-pick) { position: relative; }
  .pick-roll :is(.pick-tile, .where-pick, .sort-pick)::after { content: ""; position: absolute; inset: calc((var(--h) - 44px) / 2) 0; --h: 28px; }
  .pick-roll :is(.pick-tile, .where-pick)::after { --h: 30px; }
  /* a film's: its trailer's mark (26px drawn) reaches down over the name's line, clear of ‹ Films
     above it; folded, in the bar, all round */
  .st-play { position: relative; }
  .st-play::after { content: ""; position: absolute; inset: -2px -4px -16px; }
  .times-fold .st-play::after { inset: -7px -4px; }
  /* ‹ Films: at the top of what it's in (which cuts off what's over it), so its reach is down, over
     the film's name's top (which it's before, so it's lifted over it) */
  .times-cover .times-back { position: relative; z-index: 2; }
  .times-cover .seat-back::after { inset: 0 -10px -10px -8px; }
  .times-save::after { inset: -6px; }
  .grid-list { min-height: 44px; } /* (your shortlist's Showtimes, over its films: 40px, a finger's now) */
  /* its cinemas' chips 30px as the page's days, 7px more to a finger above and below (the line scrolls: its room's) */
  .times-cover .st-cinemas { padding-block: 7px; margin-block: -7px; }
  .times-cover .st-cinema-pick { position: relative; }
  .times-cover .st-cinema-pick::after { content: ""; position: absolute; inset: -7px 0; }
  .times-cover .sided .st-cinemas { row-gap: 8px; } /* (on its side, wrapped: each line's reach meets the next's) */
  /* the days' names, a little bigger and the days not chosen brighter */
  .st-day-name { font-size: 0.72rem; letter-spacing: 0.06em; }
  .st-day:not([aria-selected="true"]) { color: color-mix(in srgb, var(--ink) 65%, transparent); }
  /* its cast and links: in lines a finger's apart, each name a tap that tall */
  .info-credit { display: inline-block; padding-block: 6px; }
  /* (the 6px over its first line and under its last into the room between the rows, so the rows
     are as far apart as they were, the 12px between them just keeping two rows' taps apart) */
  .info-credits { gap: 12px; }
  .info-credits dd:has(.info-credit) { margin-block: -6px; }
  .room-badge .theatre { font-size: 1em; } /* (10.5px: no word on a badge under it) */
  /* the search: Cancel, and the e.g. to try */
  .find-cancel { position: relative; }
  .find-cancel::after { content: ""; position: absolute; inset: -4px -6px; }
  /* (the e.g. a little lower and more under it, its reach the field's foot to the panel's: the
     field's lower edge was over the top of it, leaving it 9px) */
  .find:not(.from-bar) .find-try { margin-top: -6px; padding-bottom: 23px; }
  .find-try-q { position: relative; z-index: 1; }
  .find-try-q::after { content: ""; position: absolute; inset: -2px -4px -23px; }
  .find.from-bar .find-try-q::after { inset: -10px -4px -11px; }
}

/* ——— Pressed: every button answers a touch, down and up (a phone has no hover to show it). It
   sinks quickly while held and springs back over its own transition. (iOS only applies :active
   with a touch listener on the page: see cards.js.) ——— */
:is(.deck-button, .deck-action, .deck-save, .times-close, .times-save, .trailer-close, .prefs-open, .short-toggle, .seat-step, .seat-party-step, .seat-expand, .seat-book):active:not(:disabled) {
  transform: scale(0.92); transition-duration: .06s;
}
.when-clear:active { transform: scale(0.85); transition-duration: .06s; }
.deck-button:active { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.3); color: var(--ink); }
.deck-action:active { background: rgba(255, 255, 255, 0.16); }
.seat-expand:active { background: color-mix(in srgb, var(--accent) 26%, transparent); }
.deck-action[data-showtimes-open]:active { background: var(--accent-grad); }
.deck-action[data-showtimes-open]:active, .seat-book:active { filter: brightness(1.15); }
.times-close:active, .trailer-close:active, .prefs-open:active, .short-toggle:active:not([aria-pressed="true"]) { background: rgba(255, 255, 255, 0.18); color: var(--ink); }
:is(.seat-step, .seat-party-step):active:not(:disabled) { background: rgba(255, 255, 255, 0.12); color: var(--ink); }
/* rows and words light up rather than shrink */
.st-time:active:not(.touch-moved *) { background-color: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); transition-duration: .06s; }
/* a list's rows (the times, Preferences', the search's) light only once a touch has stayed put a
   moment, as iOS's own lists do, and not at all once the finger's moved off to scroll (cards.js's
   touch-moved): Safari lights a row the instant a finger lands and keeps it lit while the finger
   scrolls the list, so every scroll that started on a row lit it all the way. Let go sooner (a
   quick tap), the row's chosen anyway */
@media (pointer: coarse) { :is(.st-time, .pref, .find-hit):active { transition-delay: .1s; } .find-hit:active { transition-duration: .06s; } }
.st-day:active, .seat-back:active { color: var(--ink); }
.link:active { opacity: 0.7; }

@media (prefers-reduced-motion: reduce) {
  .ambient img { transition: none; }
  .trailer[open], .st-panel { animation: none !important; }
  .stack, .deck, .times-view, .times-body { transition: none; }
  .seat-busy-ring { animation: none; } /* (an arc, still) */
  .st-time.full-new::after { animation: none; } /* (a show's bar how full it was: just there) */
  /* the panels fade in, rather than rise or slide up; the notes come and go in place */
  :is(.prefs, .find, .seat-full, dialog.sheet)[open], .find.from-bar[open] { animation-name: fade; } /* (dialog.sheet: over its own, sheet-glass; the bar's, over its growing) */
  .find.from-bar.closing { animation-name: fade-out; }
  .pref.refused .switch { animation: none; } /* (its words say why: "Keep at least one language") */
  .undo-note, .undo-note.shown { translate: var(--x) 0; }
  .deck-lap, .deck-lap.shown { translate: -50% 0; }
}

/* Windows' high contrast (forced colours) takes away backgrounds and shadows: the icons drawn with
   them, and the switches, keep theirs, in its colours (the system's: light or dark); what's pressed
   or chosen is its highlight */
@media (forced-colors: active) {
  [class^="icon-"], [class*=" icon-"], .clapper, .switch { forced-color-adjust: none; color: ButtonText; }
  :is(.view-toggle button, .short-toggle)[aria-pressed="true"] :is([class^="icon-"], [class*=" icon-"]) { color: HighlightText; }
  .icon-sliders::before, .icon-sliders::after { background: ButtonFace; }
  .switch { border: 1px solid CanvasText; background: Canvas; }
  .switch::after { background: CanvasText; }
  .pref:has(input:checked) .switch { background: Highlight; }
  .pref:has(input:checked) .switch::after { background: HighlightText; }
  :is(.view-toggle button, .short-toggle)[aria-pressed="true"], .st-day[aria-selected="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .film-tile.chosen .tile-card { outline: 2px solid Highlight; outline-offset: 2px; }
  .tile-seal { border-color: CanvasText; } /* (the gold gone: a plain ring round each award's icon) */
}

/* ——— a film's age rating (cards.html's "ageTag"; cards.js's ageTag, ageUnit): the site's own tag,
   a sibling of the rooms' badges and the genres' chips: a name in a hairline, 18px beside them, its
   colour stepping from calm (G) to strong (21+), and never colour alone, the kind of rule its shape
   too. All ages, just its hairline; guided (PG13, PG15), a badge in two, as THEATRE PODS' pair is,
   "PG" on a wash of its colour and the age in the hairline beside it; an age and over, washed in
   its colour, its outline stronger; a rating not confirmed yet (18TC, TBC), dashed ——— */
.age-tag {
  --age: rgba(244, 241, 234, 0.55);
  display: inline-flex; align-items: stretch; flex: none; box-sizing: border-box; height: 1.82em; vertical-align: middle;
  white-space: nowrap; font-size: 11px; font-weight: 700; line-height: 1; letter-spacing: 0.03em; font-variant-numeric: tabular-nums;
}
:is(.age-tag, .age-unit)[data-step="1"] { --age: #8fd0bd; } /* G */
:is(.age-tag, .age-unit)[data-step="2"] { --age: #a9cf91; } /* PG */
:is(.age-tag, .age-unit)[data-step="3"] { --age: #d4cb82; } /* PG13 */
:is(.age-tag, .age-unit)[data-step="4"] { --age: #e6b572; } /* PG15 */
:is(.age-tag, .age-unit)[data-step="5"] { --age: #ee9868; } /* 15+ */
:is(.age-tag, .age-unit)[data-step="6"] { --age: #ef7869; } /* 18+, 18TC */
:is(.age-tag, .age-unit)[data-step="7"] { --age: #e45d80; } /* 21+ */
.age-face {
  display: inline-flex; align-items: stretch; padding: 0 0.6em; border-radius: 5px;
  color: color-mix(in srgb, var(--age) 78%, var(--ink)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--age) 55%, transparent);
}
.age-face > span { display: inline-flex; align-items: center; }
.age-tail { margin-left: 0.45em; padding-left: 0.45em; border-left: 1px solid color-mix(in srgb, var(--age) 45%, transparent); }
[data-group="guided"] > .age-face { padding: 0; }
[data-group="guided"] .age-lead { padding: 0 0.45em 0 0.6em; border-radius: 5px 0 0 5px; background: color-mix(in srgb, var(--age) 22%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--age) 55%, transparent); }
[data-group="guided"] .age-tail { margin: 0; padding: 0 0.6em 0 0.45em; border: 0; }
[data-group="min"] > .age-face { background: color-mix(in srgb, var(--age) 17%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--age) 85%, transparent); color: color-mix(in srgb, var(--age) 55%, var(--ink)); }
[data-group="min"] .age-tail { margin-left: 0.08em; padding-left: 0; border: 0; }
[data-group="tbc"] > .age-face { box-shadow: none; border: 1px dashed color-mix(in srgb, var(--age) 75%, transparent); }
[data-group="tbc"] .age-tail { border-left-style: dashed; font-weight: 600; }
.info-about > .age-unit { margin: 10px 0 2px; padding-top: 18px; border-top: var(--rule); } /* (after the links: set apart, a hairline over it, as the showtimes' rows are divided) */
/* after its story, before who made it (cards.js's ageUnit): the tag, what it means beside it, its
   content notes under that, "Contains" in the tag's colour, that they're the US rating's quieter still */
.age-unit { display: flex; align-items: flex-start; gap: 10px; }
.age-unit > .age-tag { margin-top: -1px; }
.age-contains { flex: 1; min-width: 0; margin: 0; font-size: 0.84rem; line-height: 1.35; color: var(--ink); text-wrap: pretty; }

/* ——— An upright phone: the page itself scrolls (cards.js's pageScrolls), not the grid's box, so
   Safari's toolbar shrinks as you scroll and a tap on the status bar goes to the top; a film's page
   too (html.film-page: the film is the page's content then, the grid put away). Kept plain: the
   content in the page's flow, nothing cut to a fixed height; one fixed room behind it all; one slim
   bar of frosted glass fixed at the top (.page-top: Preferences and the search's button on it, or,
   on a film, ‹ Films and, once its name's gone under it, its name and trailer), the films seen
   blurred through it; the headings plainly sticky under it. ——— */
.roof-probe { position: fixed; top: 0; left: 0; width: 0; height: var(--roof, 0px); visibility: hidden; pointer-events: none; } /* (the bar's foot, measured: cards.js's watchFold) */
html.page-scroll {
  --roof: calc(env(safe-area-inset-top) + 48px); /* the bar's foot */
  --glass: rgb(7 7 10 / 0.68); --glass-blur: saturate(180%) blur(20px); --hairline: rgb(255 255 255 / 0.1);
  --head-h: 38px; /* a heading stuck under the bar: its band (below) */
}
html.page-scroll body { height: auto; min-height: 100%; overflow: visible; overscroll-behavior: auto; }
html.page-scroll:has(dialog[open]:modal) { overflow: hidden; } /* (and kept where it was: cards.js's holdPage) */
html.page-scroll .ambient { bottom: auto; height: 100lvh; } /* (the room: as tall as the screen with Safari's toolbar tucked away, so it isn't resized, its glow moved, as the toolbar comes and goes) */
/* on a film's page the room's in the page (cards.js's pageFilm), first in it, held at the top as it
   scrolls (sticky, not fixed: Safari draws what's on the page under its toolbar, but cut what's fixed
   off at the toolbar, a dark band under it). Up to the page's top, the screen's width, taller than
   the screen by the toolbar's band, taking no room; under all of the film (the poster's crop too) */
html.page-scroll.film-page .times-view > .ambient {
  --room-h: calc(100lvh + 140px);
  position: sticky; inset: 0 auto auto; z-index: -2;
  width: 100vw; height: var(--room-h);
  margin: calc(-1 * (var(--roof) + 4px)) 0 calc(var(--roof) + 4px - var(--room-h)) calc(50% - 50vw);
}
html.page-scroll .table { display: block; place-content: normal; height: auto; min-height: 100svh; padding: 0; overflow-x: clip; } /* (clip: a film waiting off to the right doesn't widen the page) */
html.page-scroll .stack { position: static; width: auto; height: auto; transform: none; will-change: auto; transition: none; }
html.page-scroll :is(.deck, .deck-nav, .deck-actions, .next-show) { display: none; } /* (the cards: never shown on a phone) */
html.page-scroll .grid-view {
  position: relative; left: auto; top: auto; bottom: auto; width: auto;
  padding: calc(var(--roof) + 8px) 20px calc(28px + env(safe-area-inset-bottom));
  overflow: visible; overscroll-behavior: auto; -webkit-mask-image: none; mask-image: none;
}
html.page-scroll .grid-mode .grid-view { z-index: var(--z-grid-under); } /* (under a film) */
/* the bar: frosted glass, a hairline under it (or under the summary line and a heading stuck under
   it, below, once that shows); Preferences on its left, the search's button on its right */
.page-top { display: none; }
html.page-scroll .page-top {
  display: block; position: fixed; left: 0; right: 0; top: 0; z-index: var(--z-bar); height: var(--roof); pointer-events: none;
  background: var(--glass); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 -1px var(--hairline);
}
html.page-scroll body:has(.pick-summary.shown) .page-top { box-shadow: none; }
/* the search: just its button (a magnifying glass) till a search's results are shown; then the bar
   says them, as wider screens' does ("[IMAX] [Tonight]", its ×), from Preferences to the edge */
html.page-scroll .page-find { --bar-h: 40px; top: calc(env(safe-area-inset-top) + 4px); }
html.page-scroll .page-find:not(.on) { border-color: transparent; background: none; box-shadow: none; }
html.page-scroll .page-find:not(.on)::after { display: none; }
html.page-scroll .page-find:not(.on) .page-find-open { justify-content: center; padding: 0; color: var(--ink); }
html.page-scroll .page-find:not(.on) :is(.page-find-words, .find-key) { display: none; }
html.page-scroll .page-find:not(.on) .icon-find { width: 19px; height: 19px; }
/* no summary line under the bar on an upright phone (When, Where and Sort are a scroll back up, or a
   tap on the status bar, away): the headings stick right under the bar, on the same glass, a hairline
   under them, once When, Where and Sort have gone under it (.pick-summary.shown: cards.js's sayRolled,
   the line itself never shown) */
html.page-scroll .pick-roll .pick-summary { display: none; }
html.page-scroll .grid-view::before {
  content: ""; position: fixed; left: 0; right: 0; top: var(--roof); z-index: 3; pointer-events: none;
  height: var(--head-h); /* (down to a stuck heading's foot) */
  background: var(--glass); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 -1px var(--hairline);
  visibility: hidden;
}
html.page-scroll .pick-summary.shown ~ .grid-view::before { visibility: visible; }
/* a phone's search: the whole screen, its field at the top, its results under it scrolling on their
   own; on the page where it's held (cards.js's holdPage), not fixed to the window, which looks the
   same, the page held still: fixed, Safari scrolled the page by itself as its field was focused */
html.page-scroll .find:not(.from-bar) {
  position: absolute; top: var(--held-y, 0px); left: 0; margin: 0; width: 100%; --find-top: 0px;
  height: var(--find-room, 100svh); max-height: none; border-radius: 0; padding-top: env(safe-area-inset-top);
  background: rgb(10 9 13 / 0.97); box-shadow: 0 0 0 100vh rgb(10 9 13 / 0.97); /* (and past its foot, under the keyboard's bar, where the page showed) */
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
/* ——— A film on an upright phone: the page's content (html.film-page, cards.js's pageFilm), the grid
   put away meanwhile, where you were in it put back as you go back. Its own bar the same glass:
   ‹ Films, and once its name's gone under the bar, its name and trailer (.folded); its days
   stuck under it. Opening, it's there at once (fading in); going back, it slides out over the
   grid as ever. A show's seat page is the page's content in turn, its Book bar fixed at the foot. */
/* (the grid put away under the film, but kept laid out and drawn, its posters ready, where it was:
   out of the page's flow, fixed as it was on the screen, unseen; display: none had Safari throw its
   posters away, blank as it came back) */
html.page-scroll.film-page .grid-view { position: fixed; top: calc(-1 * var(--film-at, 0px)); left: 0; right: 0; visibility: hidden; pointer-events: none; }
html.page-scroll.film-page .page-top { display: none; } /* (the film's own bar instead, .film-bar) */
html.page-scroll.film-page .times-cover .times-view {
  position: relative; left: auto; top: auto; width: auto; height: auto; min-height: calc(100lvh + var(--fold-room, 0px)); margin: 0 16px; /* (room to scroll its name under the bar, however short: cards.js's foldRoom) */
  padding-top: calc(var(--roof) + 4px); padding-bottom: env(safe-area-inset-bottom);
  transform: none; translate: none; opacity: 1; contain: none; will-change: auto; transition: none;
  animation: fade .25s var(--ease);
}
.film-bar { display: none; }
html.page-scroll.film-page .times-cover .film-bar {
  display: block; position: fixed; left: 0; right: 0; top: 0; z-index: 4; height: var(--roof); pointer-events: none;
  background: var(--glass); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 -1px var(--hairline);
}
html.page-scroll.film-page .times-cover .times-back { position: fixed; z-index: 5; left: 12px; top: calc(env(safe-area-inset-top) + (48px - var(--back-h)) / 2); margin: 0; }
html.page-scroll.film-page .times-cover .times-fold { position: fixed; z-index: 5; top: calc(env(safe-area-inset-top) + (48px - var(--back-h)) / 2); left: calc(16px + max(68px, var(--fold-l, 0px))); right: calc(16px + max(44px, var(--fold-r, 0px))); }
html.page-scroll.film-page .times-cover :is(.times-save, .times-close) { position: fixed; z-index: 5; top: calc(env(safe-area-inset-top) + 7px); right: 12px; }
html.page-scroll.film-page .times-pages { overflow: clip; align-items: flex-start; will-change: auto; }
html.page-scroll.film-page .times-cover .times-body { overflow: visible; height: auto; transition: none; transform: none; will-change: auto; /* (no layer of its own: else what's fixed in it, a seat page's Book bar, is fixed to it) */ -webkit-mask-image: none; mask-image: none; }
html.page-scroll.film-page .times-cover .times-view:not(.list-mode) .times-body.dressed { overflow: visible; -webkit-mask-image: none; mask-image: none; padding-bottom: 32px; }
html.page-scroll.film-page .times-cover .times-view:not(.seat-mode) .seat-page, html.page-scroll.film-page .times-cover .seat-mode .times-body:not(.seat-page) { display: none; }
html.page-scroll.film-page .times-cover .times-view:not(.list-mode) .dressed .st-days { top: var(--roof); }
/* the days, stuck under the bar (cards.js's .days-stuck): the bar's glass grown down behind them, one
   glass from the top to their foot, its hairline there, so what scrolls up under them (the poster's
   crop, the times) is blurred and tinted as under the bar, never sharp, and no darker. Not stuck,
   they're on the page as it is, nothing of their own behind them (not the dark ground, folded) */
html.page-scroll.film-page .times-cover .times-view.folded:not(.list-mode) .dressed .st-days { background: none; box-shadow: none; }
html.page-scroll.film-page .times-cover .times-view.days-stuck:not(.list-mode, .seat-mode) .film-bar { height: calc(var(--roof) + var(--days-h, 48px)); }
html.page-scroll.film-page .times-cover .times-view.days-stuck:not(.list-mode, .seat-mode) .dressed .st-days { z-index: 5; box-shadow: none; }
html.page-scroll.film-page .times-cover .seat-page { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }
/* Book and Share, the body's while a seat map's open (cards.js's placeBookBar: in the page's boxes,
   which clip, Safari blacked it out past the page's foot), fixed at the foot of the screen, square
   across it; and the page not bouncing past its ends, so nothing's ever seen beyond it, under the bar */
html.page-scroll.film-page body > .seat-actions {
  position: fixed; z-index: 5; left: 0; right: 0; bottom: 0; flex-wrap: nowrap; margin: 0; padding: 10px 16px calc(10px + env(safe-area-inset-bottom)); border-radius: 0;
  background: var(--glass); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); box-shadow: inset 0 1px var(--hairline);
}
body > .seat-actions .seat-book { flex: 1; text-align: center; }
body > .seat-actions .seat-share { flex: none; }
html.page-scroll:has(> body > .seat-actions), html.page-scroll:has(> body > .seat-actions) body { overscroll-behavior-y: none; }
/* a trailer playing: docked at the top over the page (.screen), the film's bar, its buttons and its
   days just under the dock, and the page starting there (--roof, so its days stick under it too) */
html.page-scroll.film-page .times-cover.playing .times-view { --roof: calc(env(safe-area-inset-top) + var(--dock-v) + 48px); }
html.page-scroll.film-page .times-cover.playing :is(.times-back, .times-fold) { top: calc(env(safe-area-inset-top) + var(--dock-v) + (48px - var(--back-h)) / 2); }
html.page-scroll.film-page .times-cover.playing :is(.times-save, .times-close):not(.screen-close) { top: calc(env(safe-area-inset-top) + var(--dock-v) + 7px); }
/* going back: out of the page, over the grid where it's put back (--film-at), then gone (the slide
   is the view transition's: below) */
html.page-scroll .times-cover .times-view {
  left: calc((100vw - var(--times-w)) / 2); top: calc(var(--film-at, 0px) + 16px + env(safe-area-inset-top));
  height: calc(100dvh - 18px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
}
html.page-scroll .times-cover:not(.showing-times) .times-view { visibility: hidden; }
/* the bar's two buttons, plain icons as a phone's own bars have them: no ring, no ground at rest, a
   finger's 44px to tap, a soft round ground pressed; the keyboard's ring only from the keyboard */
html.page-scroll .corner-left { top: calc(env(safe-area-inset-top) + 2px); left: 6px; }
html.page-scroll .corner-left .prefs-open { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--ink); }
html.page-scroll .page-find:not(.on) { top: calc(env(safe-area-inset-top) + 2px); right: 6px; height: 44px; width: 44px; border-radius: 50%; }
html.page-scroll :is(.corner-left .prefs-open, .page-find:not(.on)):active { background: rgb(255 255 255 / 0.12); transition-duration: .06s; }
html.page-scroll .page-find:not(.on) .page-find-open:focus-visible { outline-offset: -4px; border-radius: 50%; }
/* elsewhere, the bar's own ring: it clips what's in it (overflow: hidden), the field's ring with it */
html:not(.page-scroll) .page-find:has(.page-find-open:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
html:not(.page-scroll) .page-find-open:focus-visible { outline: none; }
/* the grid's headings smaller on an upright phone (15px, not 19), their marks, ⓘ and rule to match,
   tighter above and below: stuck under the bar, they take less of the screen */
html.page-scroll .grid-group { font-size: 0.95rem; font-weight: 650; gap: 8px; }
html.page-scroll .grid-group .flame { width: 20px; height: 20px; margin: -4px -4px -4px -2px; }
html.page-scroll .grid-group .tier-mark { width: 17px; height: 17px; margin: -3px -3px -3px -1px; }
html.page-scroll .grid-group .tier-info { width: 17px; height: 17px; }
html.page-scroll .grid-group .tier-info svg { width: 15px; height: 15px; }

/* an upright phone's film: under the bar just its trailer, its name and an ⓘ, down to all about it
   (its line, story and the rest, all there already: fillPanel), its days right under them; its
   genres last there */
.st-about { display: none; }
html.page-scroll.film-page .times-cover .dressed :is(.st-what, .st-genres, .st-brief) { display: none; }
html.page-scroll.film-page .times-cover .dressed .st-name > .st-about {
  position: relative; flex: none; display: grid; place-items: center; align-self: center; width: 22px; height: 22px; margin: 0 2px 0 10px; padding: 0;
  border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.32); background: none; color: var(--ink-soft); cursor: pointer;
  transition: color .15s, border-color .15s, background .15s, transform .15s var(--ease);
}
html.page-scroll.film-page .st-about::after { content: ""; position: absolute; inset: -11px; border-radius: 50%; } /* (44px to a finger) */
html.page-scroll.film-page .st-about svg { display: block; width: 20px; height: 20px; fill: currentColor; }
html.page-scroll.film-page .st-about:active { transform: scale(0.88); background: rgb(255 255 255 / 0.12); }
.st-watch { display: none; }
html.page-scroll.film-page .times-cover .dressed .st-name > .st-play { display: none; } /* (its trailer's button under it instead: .st-watch) */
html.page-scroll.film-page .times-cover .times-close.screen-close { display: none; } /* (closed by that button too: no × Trailer over it) */
html.page-scroll.film-page .times-cover .dressed .st-watch {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; height: 40px; margin-top: 10px; padding: 0;
  border: 0; border-radius: 12px; background: rgba(255, 255, 255, 0.1); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); color: var(--ink); font: inherit; font-size: 0.86rem; font-weight: 600; cursor: pointer;
  transition: background .15s, transform .15s var(--ease);
}
html.page-scroll.film-page .st-watch svg { width: 14px; height: 14px; fill: currentColor; }
html.page-scroll.film-page .st-watch .st-watch-x { fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; }
html.page-scroll.film-page .st-watch:active { transform: scale(0.97); background: rgba(255, 255, 255, 0.16); }
html.page-scroll.film-page .times-cover .dressed .info-about { scroll-margin-top: calc(var(--roof) + var(--days-h, 48px) + 12px); }
html.page-scroll.film-page .times-cover .dressed .info-about > .genre-chips { display: flex; flex-wrap: wrap; } /* (under its line, as wider screens have them) */
/* its days four across, the rest along (.week-plus, cards.js's daysAcross), a whole day at a time */
html.page-scroll.film-page .times-cover .dressed .st-days.week-plus { scroll-snap-type: x mandatory; }
html.page-scroll.film-page .times-cover .dressed .st-days > .st-day { flex: 0 0 calc((100% - 3 * 4px) / 4); } /* (a quarter each, however many: four or fewer where every film's are) */
/* the days a little smaller (85%), each its name and number on one centre line in its quarter (the
   name's letter-spacing taken back off its end, else it sat to the left), as much room over them as
   under them, the chosen one's line under the middle of it */
html.page-scroll.film-page .times-cover .dressed .st-day { padding: 7px 0; }
html.page-scroll.film-page .times-cover .dressed .st-day-name { font-size: 0.61rem; letter-spacing: 0.06em; margin-right: -0.06em; line-height: 1.2; }
html.page-scroll.film-page .times-cover .dressed .st-day-num { font-size: 0.94rem; line-height: 1.2; }

/* an upright phone's film: its links (who made it, Rotten Tomatoes, IMDb) underlined, softly, as
   there's no pointing at them to show it; a finger's reach about each, 44px tall */
@media (hover: none) {
  html.page-scroll.film-page .info-credit { position: relative; text-decoration-line: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); }
  html.page-scroll.film-page .info-credit::after { content: ""; position: absolute; inset: -6px -3px; }
}
/* the search's light on an upright phone: a search shown, on the bottom edge of the bar's pill, as
   wider screens have it (just a magnifier, none: above); the full screen's, under its field (or e.g.) */
html.page-scroll .find:not(.from-bar) .find-bar::after { left: 14%; right: 14%; bottom: -1px; } /* (on the hairline the next part starts with, where the results start: not a second line over it) */
html.page-scroll .find:not(.from-bar)::after { display: none; }
/* the search shown in the bar: just its outline on the bar's glass, no ground of its own (with one,
   Safari took it for what's at the top and let the page show, sharp, under the status bar) */
html.page-scroll .page-find.on { background: none; box-shadow: none; }
html.page-scroll .page-top > .page-find { position: absolute; pointer-events: auto; }
html.page-scroll .grid-group::after { display: none; } /* (no rule after a heading on an upright phone: the words alone) */
/* (the light in one place, under the field: the e.g. under it, where the results come, so the first
   letter typed only swaps the one for the other) */
html.page-scroll .find:not(.from-bar) .find-try { margin-top: 0; padding-top: 14px; padding-bottom: 14px; }
html.page-scroll .pick-sorts { margin-left: -10px; padding-left: 0; } /* (the row's first word, not its pill, on the edge) */
/* every heading (a tier's, a time's, a search's) one band on an upright phone: 38px, its words, mark
   and ⓘ in its middle, stuck right under the bar (not tucked 8px under it), the glass under it as tall */
html.page-scroll .pick-roll .grid-group { top: var(--roof); padding-block: 8px; margin-block: -8px -4px; align-items: center; min-height: var(--head-h); box-sizing: border-box; }
html.page-scroll .pick-roll .grid-group.grid-few { margin-bottom: 2px; } /* (a few films' one line: a little more room under it, the posters not up against its words) */
/* a search shown, its pill as far from Preferences' sliders as they are from the screen's edge, and
   as far again from the right edge: the sliders 14px wide, in the middle of their 44px from 6px in,
   so 21px each side */
html.page-scroll .page-find.on { left: 56px; width: calc(100% - 77px); } /* (measured: the glyph 21–35pt, so 21pt either side of it) */
/* an upright phone: a heading's ⓘ card a sheet (cards.js's openTierSheet), as Feedback's: the card
   itself in it, plainly, its × at the top right */
.tier-sheet {
  width: min(100%, 440px); max-width: none; margin: auto auto 0; padding: 0; border: 0; overflow: auto; /* (its glass, rounding, shade and ways in and out: dialog.sheet's) */
  color: var(--ink); scrollbar-width: none; overscroll-behavior: contain;
}
.tier-sheet-head { position: sticky; top: 0; z-index: 3; display: flex; justify-content: flex-end; height: 0; padding: 0; touch-action: none; }
.tier-sheet-close { margin: 16px 16px 0 0; }
.tier-sheet .tier-pop { display: block; position: static; inset: auto; width: auto; margin: 0; padding: 28px 22px 26px; border: 0; border-radius: 0; background: none; box-shadow: none; font-size: 0.92rem; }
.tier-sheet .tier-pop h4 { margin-right: 44px; font-size: 1.1rem; }
/* an upright phone's sheets: the head over nothing, the rows under it scrolling on their own (cards.js's
   sheetBody), gone at its foot, the head just as it is at rest (no ground of its own, nor darker) */
html.page-scroll dialog.sheet[open] { display: flex; flex-direction: column; overflow: hidden; }
html.page-scroll dialog.sheet > .prefs-head { flex: none; position: relative; margin: 0; padding-bottom: 6px; background: transparent; }
html.page-scroll dialog.sheet > .sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
html.page-scroll dialog.sheet > .sheet-body::-webkit-scrollbar { display: none; }
html.page-scroll dialog.sheet .sheet-body > .prefs-intro { margin-top: 0; } /* (its -12px was under the head, in the rows' scroll: now cut off) */
html.page-scroll dialog.sheet.fb .sheet-body .fb-intro { margin-top: 0; } /* (the feedback's, likewise: its -8px cut its first line off) */

/* ——— an upright phone's grid: no film's glow (there's no pointer to choose one, and none's fetched
   till a film's opened: cards.js's showAmbient), but a light from above as from a cinema's screen,
   its colour the hour's (roomLight). A film open: its own glow, as ever, the light gone under it. ——— */
.room-light { display: none; }
html.page-scroll .room-light {
  display: block; position: fixed; inset: 0 0 auto; height: 100lvh; z-index: 0; pointer-events: none;
  background: radial-gradient(150% 70% at 50% 4%, rgba(var(--room-light, 255, 226, 190), 0.32), rgba(var(--room-light, 255, 226, 190), 0.1) 40%, transparent 72%);
  transition: opacity .45s var(--ease);
}
html.page-scroll:has(.table.showing-times) .room-light { opacity: 0; }
html.page-scroll:not(:has(.table.showing-times)) .ambient { opacity: 0; }
html.page-scroll .ambient { transition: opacity .45s var(--ease); }

/* a film opened or closed on an upright phone (cards.js's filmSwitch): the two pages as pictures, the
   film's sliding in from the right over the grid's, which eases a little to the left, darkening a
   touch, and back again; nothing of the page's own transitions meanwhile (the switch is at once
   under the pictures) */
html.page-scroll .times-cover .times-view, html.page-scroll .grid-mode .grid-view { transition: none !important; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
html:is(.film-in, .seat-in)::view-transition-new(root) { animation: film-push .42s var(--push-in) both; z-index: 2; box-shadow: -10px 0 30px rgb(0 0 0 / 0.45); } /* (a seat page's too: below) */
html:is(.film-in, .seat-in)::view-transition-old(root) { animation: film-under .42s var(--push-in) both; z-index: 1; }
html:is(.film-out, .seat-out)::view-transition-old(root) { animation: film-push .38s var(--push-out) reverse both; z-index: 2; box-shadow: -10px 0 30px rgb(0 0 0 / 0.45); }
html:is(.film-out, .seat-out)::view-transition-new(root) { animation: film-under .38s var(--push-out) reverse both; z-index: 1; }
/* the bars, glass, pictured on their own as the film slides (Safari pictures a page without what a
   backdrop-filter does, so the bars came sharp through and blurred only once it was over): their
   pictures over the pages' pictures, frosting them live as they go, each moving with its page. The
   grid's bar under the film's page, the film's bar over it all */
html:is(.film-in, .film-out) .page-top { view-transition-name: page-top; }
html:is(.film-in, .film-out) .film-bar { view-transition-name: film-bar; }
::view-transition-group(page-top), ::view-transition-group(film-bar) { -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); }
::view-transition-group(page-top) { z-index: 1; }
::view-transition-group(film-bar) { z-index: 3; }
::view-transition-old(page-top), ::view-transition-new(page-top), ::view-transition-old(film-bar), ::view-transition-new(film-bar) { animation: none; mix-blend-mode: normal; }
html.film-in::view-transition-group(film-bar) { animation: film-push .42s var(--push-in) both; box-shadow: -10px 0 30px rgb(0 0 0 / 0.45); }
html.film-in::view-transition-group(page-top) { animation: film-under .42s var(--push-in) both; }
html.film-out::view-transition-group(film-bar) { animation: film-push .38s var(--push-out) reverse both; box-shadow: -10px 0 30px rgb(0 0 0 / 0.45); }
html.film-out::view-transition-group(page-top) { animation: film-under .38s var(--push-out) reverse both; }
/* (what's on the bars, fixed apart from them, pictured on its own too, over its bar's picture, as
   it'd be hidden under it: ‹ Films, the folded name, the film's buttons, its days stuck under the
   bar; the grid's Preferences. Each moving with its page) */
html:is(.film-in, .film-out) .times-view > .times-back { view-transition-name: film-back; }
html:is(.film-in, .film-out) .times-view > .times-fold { view-transition-name: film-fold; }
html:is(.film-in, .film-out) .times-view > .times-save { view-transition-name: film-save; }
html:is(.film-in, .film-out) .times-view > .times-close { view-transition-name: film-close; }
html:is(.film-in, .film-out) .times-view.days-stuck .times-body.dressed .st-days { view-transition-name: film-days; }
html:is(.film-in, .film-out) .corner-left .prefs-open { view-transition-name: grid-prefs; }
::view-transition-group(grid-prefs) { z-index: 2; } /* (the grid's, under the film's bar coming over it) */
::view-transition-group(film-back), ::view-transition-group(film-fold), ::view-transition-group(film-save), ::view-transition-group(film-close), ::view-transition-group(film-days) { z-index: 4; }
::view-transition-old(film-back), ::view-transition-new(film-back), ::view-transition-old(film-fold), ::view-transition-new(film-fold), ::view-transition-old(film-save), ::view-transition-new(film-save), ::view-transition-old(film-close), ::view-transition-new(film-close), ::view-transition-old(film-days), ::view-transition-new(film-days), ::view-transition-old(grid-prefs), ::view-transition-new(grid-prefs) { animation: none; mix-blend-mode: normal; }
html.film-in::view-transition-group(film-back), html.film-in::view-transition-group(film-fold), html.film-in::view-transition-group(film-save), html.film-in::view-transition-group(film-close), html.film-in::view-transition-group(film-days) { animation: film-push .42s var(--push-in) both; }
html.film-out::view-transition-group(film-back), html.film-out::view-transition-group(film-fold), html.film-out::view-transition-group(film-save), html.film-out::view-transition-group(film-close), html.film-out::view-transition-group(film-days) { animation: film-push .38s var(--push-out) reverse both; }
/* (going back, each where it was: cards.js's pinPictures) */
html.film-out::view-transition-group(film-bar) { transform: var(--vt-film-bar) !important; width: var(--vt-film-bar-w) !important; height: var(--vt-film-bar-h) !important; }
html.film-out::view-transition-group(film-back) { transform: var(--vt-film-back) !important; width: var(--vt-film-back-w) !important; height: var(--vt-film-back-h) !important; }
html.film-out::view-transition-group(film-fold) { transform: var(--vt-film-fold) !important; width: var(--vt-film-fold-w) !important; height: var(--vt-film-fold-h) !important; }
html.film-out::view-transition-group(film-save) { transform: var(--vt-film-save) !important; width: var(--vt-film-save-w) !important; height: var(--vt-film-save-h) !important; }
html.film-out::view-transition-group(film-close) { transform: var(--vt-film-close) !important; width: var(--vt-film-close-w) !important; height: var(--vt-film-close-h) !important; }
html.film-out::view-transition-group(film-days) { transform: var(--vt-film-days) !important; width: var(--vt-film-days-w) !important; height: var(--vt-film-days-h) !important; }
html.film-in::view-transition-group(grid-prefs) { animation: film-under .42s var(--push-in) both; }
html.film-out::view-transition-group(grid-prefs) { animation: film-under .38s var(--push-out) reverse both; }
/* (by translate, not transform: a group's place on the screen is its transform; and by the screen's
   width, all the same distance, whatever each is as wide as) */
@keyframes film-push { from { translate: 100vw 0; } }
/* a seat page on an upright phone (cards.js's seatSlide): pushed on over the film's times as the
   film's page is over the grid, its Book bar with it, and back; the film's bar stays where it is,
   its ‹ (Films, Showtimes) and the film's name crossfading on it */
html:is(.seat-in, .seat-out) .film-bar { view-transition-name: film-bar; }
html:is(.seat-in, .seat-out) .times-view > .times-back { view-transition-name: film-back; }
html:is(.seat-in, .seat-out) .times-view > .times-fold { view-transition-name: film-fold; }
html:is(.seat-in, .seat-out) .times-view > .times-save { view-transition-name: film-save; }
html:is(.seat-in, .seat-out) .times-view > .times-close { view-transition-name: film-close; }
html:is(.seat-in, .seat-out)::view-transition-old(film-bar), html:is(.seat-in, .seat-out)::view-transition-old(film-back), html:is(.seat-in, .seat-out)::view-transition-old(film-fold), html:is(.seat-in, .seat-out)::view-transition-old(film-save), html:is(.seat-in, .seat-out)::view-transition-old(film-close) { animation: fade-out .25s var(--ease) both; }
html:is(.seat-in, .seat-out)::view-transition-new(film-bar), html:is(.seat-in, .seat-out)::view-transition-new(film-back), html:is(.seat-in, .seat-out)::view-transition-new(film-fold), html:is(.seat-in, .seat-out)::view-transition-new(film-save), html:is(.seat-in, .seat-out)::view-transition-new(film-close) { animation: fade .25s var(--ease) both; }
@keyframes film-under { to { translate: -25vw 0; filter: brightness(0.7); } }

/* ——— Bands: an upright phone's home (cards.js's fillBands), in place of the sorted grid: each band
   a plain heading and a row of posters scrolled sideways (the page's own scroll up and down, the
   row's along: touch-action leaves both to the browser, which takes whichever way the finger sets
   off), each poster snapping to the row's start, about 3.4 across (3 on an iPhone 17 Pro, 402pt)
   so the next one peeks in from the edge. Just the posters: no line under them (nor its dots), a
   chip on one where the band needs a word (.tile-chip). The headings don't stick (each is its row's). No Sort on an upright phone, nor
   Preferences' Ratings: Rotten Tomatoes' alone (cards.js's sortNow, ratingsFor). ——— */
html.page-scroll .pick-sort { display: none; }
html.page-scroll .prefs [data-ratings-pick] { display: none; }
.grid-band { grid-column: 1 / -1; min-width: 0; }
html.page-scroll .grid-view .band-head {
  position: static; margin: 0; padding: 4px 0 0; clip-path: none;
  font-size: 1.06rem; font-weight: 700; letter-spacing: -0.012em; color: var(--ink);
}
.band-head::after { display: none; }
.band-row {
  --band-gap: 10px;
  --band-w: calc((100vw - 20px) / 3.4 - var(--band-gap)); /* (from the grid's 20px in: ~3.4 posters across) */
  display: flex; gap: var(--band-gap); align-items: start;
  margin: 0 -20px; padding: 12px 20px 4px; /* (out to the screen's edges; room above to lift into) */
  overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scrollbar-width: none;
  scroll-snap-type: x mandatory; scroll-padding-inline: 20px;
  touch-action: pan-x pan-y;
}
/* with a mouse or trackpad, no snapping: a wheel's each notch goes as far as it goes, as on the days
   and cinemas above (Firefox took each notch, snapping, to the next poster: too fast). A finger's
   swipe still comes to rest on one. */
@media (hover: hover) and (pointer: fine) { .band-row { scroll-snap-type: none; } }
.band-row::-webkit-scrollbar { display: none; }
.band-row > .film-tile { flex: none; width: var(--band-w); scroll-snap-align: start; }
.band-row .tile-when { display: none; }
.band-row .tile-seals { --d: max(24cqw, 26px); } /* (smaller posters: their seals a little smaller too, still made out) */
/* a word on a poster (cards.js's tileChip): Limited's days, what hides a Top film. A small dark
   glass chip at its top, centred, over the poster's sky more often than its title; on the lifted
   card, not in it, so it isn't dimmed with a hidden film's poster */
.tile-chip {
  position: absolute; top: 5px; left: 50%; translate: -50% 0; z-index: 6; max-width: calc(100% - 8px); width: max-content;
  display: grid; justify-items: center; padding: 2px 6px; border-radius: 6px; pointer-events: none;
  background: rgb(12 11 18 / 0.74); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  box-shadow: 0 0 0 0.5px rgb(255 255 255 / 0.22), 0 2px 8px rgb(0 0 0 / 0.45);
  font-size: 0.62rem; font-weight: 600; line-height: 1.3; text-align: center; text-wrap: balance;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.tile-chip > span { max-width: 100%; }
.tile-chip.days > span { white-space: nowrap; } /* (Limited's days, two a line: cards.js's sayTile) */
/* Top: each poster with its place beside it, a tall numeral, outlined, its right edge tucked
   under the poster (Netflix's); "10" wider, the poster further along to make room */
.tile-rank { display: none; }
.band-top .band-row > .film-tile { --rank-room: calc(var(--band-w) * 0.36); width: calc(var(--band-w) + var(--rank-room)); padding-left: var(--rank-room); }
.band-top .band-row > .film-tile:has(.tile-rank.wide) { --rank-room: calc(var(--band-w) * 0.86); }
.band-top .tile-rank {
  position: absolute; top: 0; right: calc(100% - var(--rank-room) - var(--band-w) * 0.16);
  height: calc(var(--band-w) * 88 / 63); /* (the poster's: the numeral's foot on its foot) */
  display: flex; align-items: flex-end; pointer-events: none;
  font-size: calc(var(--band-w) * 0.98); font-weight: 800; line-height: 0.74; letter-spacing: -0.04em; font-variant-numeric: tabular-nums;
  color: rgb(9 9 14 / 0.55); -webkit-text-stroke: 2px rgb(236 232 255 / 0.62); paint-order: stroke fill;
  text-shadow: 0 6px 18px rgb(0 0 0 / 0.5);
}
/* a film in Top your preferences hide: in its place, quieter, its poster dimmed and greyed, what
   hides it on it, its chip (cards.js's sayTile) */
.band-top .film-tile.hidden-film .tile-card { opacity: 0.42; filter: saturate(0.25); }
.band-top .film-tile.hidden-film .tile-rank { opacity: 0.45; }
/* (no glass under the bar for a stuck heading: none sticks; the bar's hairline stays) */
html.page-scroll .grid-view.banded::before { display: none; }
html.page-scroll body:has(.grid-view.banded) .page-top { box-shadow: inset 0 -1px var(--hairline); }

/* ——— Bands wider than a phone (cards.js's fillBandsWide): each band a section of the grid, as the
   sorts' were, every film in it with its line under it; no Sort, the bands are the order ——— */
html.bands-home :is(.pick-sort, .prefs [data-ratings-pick]) { display: none; } /* (and Preferences' Ratings: Rotten Tomatoes', the bands' own: cards.js's ratingsFor) */
.grid-view.banded-wide .tile-rank { display: none; }
.grid-view.banded-wide .grid-group::after, .grid-heads.banded-wide .grid-group::after { display: none; } /* (each band's heading just its words: no hairline on along it) */
