/* The site's look: the grid of films and its headings, a film's showtimes and seat maps, the
   search, Preferences, and a phone's page (html.page-scroll: upright, or on its side alike). 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 page, in Preferences: 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 */
  /* the thumb bar's pickers (the month, the column, the age bar's clear): one violet language
     ("Amethyst", the owner's, 1 Nov 2026; the others on explore/column-design) for pressed (a wash),
     under the finger (lifted, bright), picked (deeper) and picking and flying (bright again); words
     on them white */
  --pick-press: rgb(150 125 255 / 0.3);
  --pick-lift: linear-gradient(165deg, #ab96ff, #6a4ce0);
  --pick-lift-glow: inset 0 1px 0 rgb(255 255 255 / 0.35), 0 14px 26px -10px #000, 0 0 24px -4px rgb(140 115 255 / 0.7);
  --pick-on: linear-gradient(165deg, #8a72f0, #5638c8);
  --pick-on-glow: inset 0 1px 0 rgb(255 255 255 / 0.22), 0 6px 16px -8px #000;
  --pick-going-glow: inset 0 1px 0 rgb(255 255 255 / 0.35), 0 0 26px -4px rgb(140 115 255 / 0.75);
  /* and their glass: one dark pane, a soft violet light at its top, a fine edge */
  --pick-glass: radial-gradient(120% 55% at 50% -10%, rgb(169 150 255 / 0.2), transparent 62%), linear-gradient(rgb(255 255 255 / 0.04), transparent 30%), rgb(16 15 22 / 0.9);
  --pick-glass-edge: inset 0 0 0 0.5px rgb(255 255 255 / 0.12), inset 0 1px 0 rgb(255 255 255 / 0.13), 0 1px 2px rgb(0 0 0 / 0.4), 0 36px 70px -24px rgb(0 0 0 / 0.95);
  /* the calls to action (Book on VOX, feedback's Send and Done): a light bar, the ink, its words
     dark, an arrow in a dark tile at its end that nudges on hover (the owner's, 26 Oct 2026, of six
     shapes and seven colours mocked: .claude/tools/button-mocks) */
  --cta: linear-gradient(135deg, #f4f1ea, #cfc9bc);
  --cta-pressed: linear-gradient(135deg, #e8e5de, #c5bfb3);
  --on-cta: #121118;    /* 11:1 and more on it */
  --cta-tile: rgba(18, 17, 24, 0.85); --cta-tile-hover: rgba(18, 17, 24, 0.97);
  --cta-out: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E"); /* (off to the chain's site) */
  --cta-on: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  --cta-done: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
  --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);
  /* the safe area's insets at the left and right (a phone on its side's notch and rounded corners;
     none upright or wider), and the margin a screen's sides keep: 16px, or past them */
  --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)); /* 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) */
  --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);
  /* a 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;          /* a 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;  /* a 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.) */
@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; } /* (the filters' 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); }
/* a phone's film, another day (cards.js's slideDay): one line under the days moved along to it, not
   each tab's own border (relative: where they're not stuck); the times slid across, not faded in;
   the day left, a copy of it as much as was on the screen, going over the times' place; and a finger
   dragging them across, not the page's scroll sideways (up and down, still the browser's) */
.st-day-line { display: none; }
.dressed .st-days.lined { position: relative; }
.dressed .st-days.lined > .st-day-line { display: block; position: absolute; left: 0; bottom: 0; width: 100px; height: 2px; background: var(--accent-grad); transform-origin: 0 0; pointer-events: none; }
.dressed .st-days.lined > .st-day[aria-selected="true"] { border-image: none; border-bottom-color: transparent; }
.dressed .st-panel { touch-action: pan-y pinch-zoom; }
.dressed .st-panel.slid { animation: none; }
.dressed .st-panel.st-ghost[hidden] { display: grid !important; position: absolute; overflow: hidden; pointer-events: none; }
/* 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); }
/* the six luxury rooms (165+ AED a seat, 4 Nov 2026: VOX THEATRE and SAMSUNG ONYX, Reel's Platinum
   Suites, Roxy's Platinum, Movie Club and Movie Club Private): a faint mother-of-pearl wash inside
   a warm hairline, the name in bone, so the badge says "luxury" quietly (the owner's pick, A Nacre,
   of six on explore/pearl-badges, 5 Nov 2026) */
.room-badge-pearl {
  color: #efe9dc; box-shadow: inset 0 0 0 1px rgb(255 246 232 / 0.30);
  background:
    radial-gradient(120% 140% at 18% 0%, rgb(255 246 236 / 0.16), transparent 60%),
    linear-gradient(105deg, rgb(255 222 234 / 0.09), rgb(220 214 255 / 0.10) 50%, rgb(210 242 232 / 0.09));
}
@media (forced-colors: active) { .room-badge-pearl { background: none; } }
/* 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 the filters': 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; }
/* 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): just the times and
   their rooms, easier to take in */
.times-body.one-picked .st-time :is(.st-where-cinema, .chain-mark) { display: none; } /* (over a desktop's, which shows a lone cinema's name as its time's hovered) */
.st-where > :is(.room-badge, .room-pair) { grid-row: 1; grid-column: badge; justify-self: end; margin-left: 10px; }
/* a film in several versions (cards.js's versionSaid): before the badge, its version's name, in the
   line's faint words ("Hindi", "Live"); its chip pressed (.one-version), the chip says which, so none */
.st-version { grid-row: 1; grid-column: screens; display: flex; align-items: center; gap: 6px; margin-left: 10px; justify-self: end; }
.one-version .st-version-name { display: none; }
/* 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
   (or a version's name, before it: never over that), 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 / screens; 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; } }
/* on a phone, a show within the hour counts down to the minute (cards.js's markTimes: .st-live),
   quiet, in "when", by its badge, all as wide (so the shows within the hour, together at the top,
   keep their columns; the cinema's name gives way first); the soonest brighter, in a faint pill,
   as a rough how soon's chip but rounder. Pointed at too (a narrow window), shown once */
.st-live { display: none; }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .st-one .st-time > .st-live { display: flex; justify-content: flex-end; grid-column: when; grid-row: 1; width: 5.9em; margin-left: 4px; font-size: 0.78rem; line-height: 18px; color: var(--ink-faint); }
  .st-one .st-time > .st-live > span { padding: 0 7px; border-radius: 9px; }
  .st-one .st-time.soonest > .st-live > span { background: rgba(255, 255, 255, 0.09); color: var(--ink); }
  .st-one .st-time.live > .st-when-shown { display: 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); } }
/* (back from its sheet, on a phone: the times never left, so just a glance) */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) { html.page-scroll.film-page .times-cover .st-time.was-here { animation-duration: .7s; } }
/* 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 (from 9PM, the time picker's Late: funcs.go's lateNight): a crescent
   moon in its dot's place, quiet; so in the preview's (not a film's own times: showtime-periods.css) */
: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;
  --bolt: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13.6 1.8 4.4 13.4a.8.8 0 0 0 .6 1.3h5.6l-1.3 7.5c-.1.7.8 1.1 1.2.5l9.2-11.6a.8.8 0 0 0-.6-1.3h-5.6l1.3-7.5c.1-.7-.8-1.1-1.2-.5Z'/></svg>"); } /* (and a lightning bolt: Now, the day button's and the month's) */
:root { --pin: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 21.6c-.3 0-.6-.1-.8-.4C8.4 18 5 13.9 5 9.9 5 6 8.1 2.8 12 2.8S19 6 19 9.9c0 4-3.4 8.1-6.2 11.3-.2.3-.5.4-.8.4Zm0-8.9a2.8 2.8 0 1 0 0-5.6 2.8 2.8 0 0 0 0 5.6Z'/></svg>");
  --pin-line: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9'><path d='M12 20.6C9 17.3 6 13.5 6 9.9a6 6 0 0 1 12 0c0 3.6-3 7.4-6 10.7Z'/><circle cx='12' cy='9.9' r='2.2'/></svg>"); } /* (a map pin, solid and in outline: the cinema button's) */
:root { --age-fig: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'><circle cx='8.6' cy='6.6' r='3.1'/><path d='M3 20.4v-2.6a5.6 5.6 0 0 1 11.2 0v2.6'/><circle cx='17.7' cy='10.9' r='2.25'/><path d='M14.6 20.4v-1.5a3.15 3.15 0 0 1 6.3 0v1.5'/></svg>"); } /* (two figures in outline: the age button's, at no limit) */
.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;
}
html.sunrise .st-one .st-time[data-early] .st-dot { scale: 1.75; } /* (a film's times' 7px dot: drawn about 12px. Their moon's gone: the parts of the day's headings say it, showtime-periods.css) */
/* 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 { opacity: 0.35; transition: opacity .2s; }
/* 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 showSeatProblem), 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;
}

/* 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; display: inline-flex; align-items: center; justify-content: space-between; gap: 16px;
  min-height: 48px; box-sizing: border-box; padding: 0 8px 0 20px; border-radius: 14px; text-decoration: none; /* (only as wide as its words) */
  background: var(--cta); color: var(--on-cta); font-size: 0.95rem; font-weight: 650; letter-spacing: 0.005em;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 10px 24px -14px color-mix(in srgb, var(--ink) 90%, transparent);
  transition: box-shadow .3s var(--ease), transform .3s var(--ease);
}
/* its arrow, out to the chain's site, in a dark tile at its end; nudged on hover */
.seat-book::after {
  content: ""; flex: none; width: 32px; height: 32px; border-radius: 10px;
  background: var(--cta-out) 50% 50% / 15px no-repeat, var(--cta-tile);
  transition: background-position .35s var(--set-off), background-color .3s;
}
@media (hover: hover) {
  .seat-book:hover { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 14px 30px -12px var(--ink); }
  .seat-book:hover::after { background-position: calc(50% + 3px) calc(50% - 3px), 0 0; background-color: var(--cta-tile-hover); }
}
.seat-book:active { transform: scale(0.975); transition-duration: .08s; background: var(--cta-pressed); box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3); }
/* Book, and beside it Share: the same shape, in glass, as it's the lesser of the two; the pair in
   the middle */
.seat-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; justify-self: stretch; gap: 10px; }
.seat-share {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  min-height: 48px; box-sizing: border-box; padding: 0 18px 0 16px; border-radius: 14px;
  border: 1px solid var(--pill-line); background: var(--pill-fill);
  color: var(--ink); font: inherit; font-size: 0.95rem; font-weight: 650; letter-spacing: 0.005em;
  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.975); transition-duration: .08s; }
.icon-share { width: 16px; 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: a quiet word with its icon, as When, Where and Sort's, a rounded rect when pointed at) */
@media (min-width: 778px) and (orientation: portrait), (min-width: 778px) and (min-height: 500px) {
  .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, or on its side), just its icon, round */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .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 filters are on (a day, a cinema, a time). 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); }
}
/* the filters: the bar says them, each a chip (find-token), and how many films, faint; its × quiet,
   a grey round (to let go of them all) */
.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; }
.page-find-count { flex: none; margin-left: 4px; color: var(--ink-faint); font-size: 0.84rem; white-space: nowrap; }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .page-find-count { display: none; } /* (on a phone, 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) */
}
/* why a day can't be picked, a moment where the search's words are (cards.js's sayBarWhy) */
.bar-why { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-soft); }
.find-sum > .bar-why { display: block; }
.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 (nothing typed: just its line saying what to type), 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:not(:has(.find-results > *, .find-sum: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 a line 40px tall in the bar's middle, the
   magnifier and Cancel placed by it */
@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-input { height: 40px; }
  /* the magnifier and Cancel by the field, their room kept beside it (the field's ::before; Cancel's,
     --cancel-room, cards.js's fitCancel); 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-field { margin-right: var(--cancel-room, 64px); }
}
/* the field: what's typed, on one line */
.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; }
/* a chip (a filter's, in the search bar): a rounded rectangle, as the bar is, in the accent's tint (--find-chip) */
.find-token {
  display: inline-flex; align-items: center; height: 26px; padding: 0 9px; border-radius: 8px;
  background: var(--find-chip); color: var(--ink); font-size: 0.8rem; font-weight: 600; white-space: nowrap;
}
.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.from-bar .find-cancel { display: none; } } /* (the drop-down under the bar: Escape, or a click outside; the whole-screen search keeps it, with a mouse too: nothing outside it to click) */
/* ——— The search's light: 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), and the magnifier's glint twinkles in, once; then nothing moves, while you type. 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 */
  --find-chip: color-mix(in srgb, var(--accent) 22%, transparent); /* a chip's tint */
  --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 the
   filters' 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) */
}
@media (prefers-reduced-motion: reduce) {
  .page-find::after, .find[open]::after, .find[open] .find-glint path { animation: 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; }
/* the last results, kept while a word's half typed finds nothing (cards.js's keepStale) */
.find-results { transition: opacity .18s ease; }
.find-results.stale { opacity: 0.6; }
/* 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 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.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 .age-tag { margin-right: 3px; font-size: 10px; vertical-align: -1px; } /* (a film's tag, before "Over your age limit": cards.js's start) */
.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 - 150px); text-align: right; /* (its left edge 88px in: clear of ‹ Films) */
}
/* the line over the films that don't fit the filters (cards.js's restSaid), quietly */
.find-hidden-head { list-style: none; margin: 12px 12px 4px; font-size: 0.76rem; font-weight: 600; color: var(--ink-faint); }
.find-act { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); white-space: nowrap; }
/* nothing found, in words: no film or cast name matching it, and what the search is for */
.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-none-head { display: block; margin: 0 0 10px; font-size: 0.92rem; font-weight: 650; color: var(--ink); text-wrap: pretty; overflow-wrap: anywhere; } /* (a long word typed without spaces breaks, not cut off at the edge) */
.find-none-note { display: block; font-size: 0.8rem; color: var(--ink-faint); }
/* nothing for the filters, in the films' place: its ways out, small pills, each saying what it'd
   show ("Drop MOE → 11 films": cards.js's dropWays) */
.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); }
/* (on a phone, a way out's words wrap rather than run out, all of it said) */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .find-way { 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 > b { overflow: visible; text-wrap: pretty; }
}
/* a small pill: a way out, and a film's cinemas and versions in its showtimes (st-cinema-pick) */
.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) */
.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 the filters leave out are left out, and it says so (cards.js's sayFrom) */
.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); }
.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; Feedback a page of it:
   feedback.css) */
.prefs {
  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 */
}
.prefs::backdrop { background: rgba(4, 4, 6, 0.6); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.prefs[open] { animation: rise .4s var(--ease); }
.prefs[open]::backdrop { animation: fade .3s var(--ease); }
.prefs { 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 */
.prefs.closing { animation: rise-out .22s var(--leave) forwards; }
.prefs.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. */
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: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 (an experience's: a cinema's chain is said over it, .prefs-chain-head): 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%; }
/* Screens: each chain's rooms in a rounded panel under its wordmark (one for each group), a hairline between each, as a
   phone's grouped settings (the owner's pick, 27 Oct 2026, of five: .claude/tools/experience-groups/
   rows-chain); each room's badge, then a line on what it is; one that's off keeps its place, quieter */
[data-experiences] .prefs-group { margin: 0 -4px; }
[data-experiences] .prefs-chain-head { padding-left: 15px; padding-right: 15px; }
.prefs-inset { display: grid; gap: 16px; }
.prefs-room-rows { border-radius: 14px; background: rgba(255, 255, 255, 0.05); overflow: clip; }
.prefs-room-rows > .pref { min-height: 56px; padding: 10px 14px 10px 15px; border-radius: 0; }
.prefs-room-rows > .pref + .pref::before { left: 15px; right: 0; background: rgba(255, 255, 255, 0.08); }
@media (hover: hover) { .prefs-room-rows > .pref:hover { background: rgba(255, 255, 255, 0.03); } }
.prefs-room-rows > .pref:active:not(.touch-moved *) { background: rgba(255, 255, 255, 0.05); }
/* in groups (Everyday, Picture & sound, Dine-in…): each its own panel, its name over it in
   small capitals, as a phone's grouped settings */
.prefs-room-group-name { margin: 0; padding: 0 15px 6px; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint); }
.prefs-inset .pref-text { gap: 0; }
.prefs-inset .pref-blurb { margin-top: 4px; font-size: 0.78rem; line-height: 1.4; text-wrap: pretty; }
.prefs-inset .pref:not(:has(input:checked)) .pref-blurb { opacity: 0.55; }
/* a screen with no showtimes at your cinemas (cards.js's sayOffered): greyed, its switch out of reach,
   saying so in place of what it is; a chain with none at all, just that, under its wordmark */
.prefs-room-rows > .pref.unoffered { cursor: default; }
.prefs-room-rows > .pref.unoffered :is(.pref-name, .switch) { opacity: 0.38; }
.prefs-room-rows > .pref.unoffered .pref-blurb { opacity: 1; }
.prefs-room-rows > .pref.unoffered .switch { background: rgba(255, 255, 255, 0.14); } /* (neither on nor off: out of reach) */
@media (hover: hover) { .prefs-room-rows > .pref.unoffered:hover { background: none; } .prefs-room-rows > .pref.unoffered:hover::before, .prefs-room-rows > .pref.unoffered:hover + .pref::before { opacity: 1; } }
.prefs-room-rows > .pref.unoffered:active { background: none; }
.prefs-room-rows > .pref.unoffered:active::before, .prefs-room-rows > .pref.unoffered:active + .pref::before { opacity: 1; } /* (not lit: the hairlines either side stay, as they give way only to a lit row) */
.prefs-chain.unoffered :is(.prefs-inset, .prefs-chain-all) { display: none; }
.prefs-chain-none { margin: 0 15px 4px; font-size: 0.8rem; color: var(--ink-faint); }
/* under the rooms (their lines are ours, and new) and the cinemas (one we don't have): a way to tell us (Send feedback, cards.js's data-go-from) */
.prefs-help { margin: 18px 11px 4px; font-size: 0.8rem; line-height: 1.45; color: var(--ink-faint); text-wrap: pretty; }
[data-cinemas] .prefs-help { margin-inline: 4px; } /* (in line with the cinemas' names: their rows aren't in panels) */
.prefs-help-link { padding: 0; border: 0; background: none; font: inherit; color: var(--accent); cursor: pointer; }
@media (hover: hover) { .prefs-help-link:hover { text-decoration: underline; } }
.prefs-chain:not(.unoffered) .prefs-chain-none { display: none; }
.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, compact as a phone's are now (50 × 28, the
   owner's pick, 27 Oct 2026, of six: .claude/tools/experience-groups/switches), its knob a wide
   capsule (30 × 24) stretching toward its way while it's held, a shade darker. 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: 50px; height: 28px; border-radius: 14px;
  background: rgba(255, 255, 255, 0.14); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
  transition: background .28s var(--ease);
}
.switch::after {
  content: ""; position: absolute; left: 2px; top: 2px; width: 30px; height: 24px; border-radius: 12px;
  background: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 2px 5px rgba(0, 0, 0, 0.22);
  transition: transform .32s var(--ease), width .2s var(--ease), background .2s;
}
.pref:active:not(.touch-moved *) .switch::after { width: 35px; background: #e4e0d8; }
.pref:has(input:checked) .switch { background: rgb(10, 132, 255); }
.pref:has(input:checked) .switch::after { transform: translateX(16px); }
.pref:has(input:checked):active:not(.touch-moved *) .switch::after { transform: translateX(11px); } /* (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);
}
.pref-pick:has(input:checked) .check::after { opacity: 1; scale: 1; }
.pref-pick: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) */

/* ——— Preferences in pages, as a phone's settings (cards.js's goPage): the first, a row for each part
   with what's on in it at its end and a chevron, as feedback's row; a part's page sliding in from
   the right over it (it going a little left and fading), and back ——— */
.pref-nav { width: 100%; grid-template-columns: auto minmax(0, 1fr) auto; min-height: 54px; border: 0; background: none; text-align: left; color: inherit; font: inherit; }
.prefs .pref.pref-nav .pref-name, dialog.sheet.prefs .pref.pref-nav:not(:has(input)) .pref-name { font-size: 1.02rem; font-weight: 650; letter-spacing: -0.01em; color: var(--ink); mix-blend-mode: normal; } /* (a part's name, as its legend: plain white, not a row that's off) */
.pref-nav:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.prefs-sum {
  justify-self: end; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 0.8rem; color: var(--ink-faint); font-variant-numeric: tabular-nums;
}
.prefs-sum-new { color: var(--accent); } /* (cinemas new to you: "· 10 new", the first time it's opened) */
/* the way back, over the page's name: its chevron and the first page's name, in the accent, as a
   phone's settings */
.prefs-back {
  display: inline-flex; align-items: center; gap: 2px; margin: -4px 0 4px -6px; padding: 4px 8px 4px 4px; border: 0; border-radius: 8px;
  background: none; color: var(--accent); cursor: pointer; font: inherit; font-size: 0.84rem; font-weight: 600;
}
.prefs-back[hidden] { display: none; }
.prefs-back-chev { width: 8px; height: 8px; margin: 0 2px 0 6px; border: solid currentColor; border-width: 0 0 1.75px 1.75px; rotate: 45deg; }
@media (hover: hover) { .prefs-back:hover { background: rgba(169, 150, 255, 0.1); } }
.prefs-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
.prefs.at-page .prefs-head > div > :is(.prefs-back, .prefs-page-title), .prefs:not(.at-page) #prefs-title { animation: fade .3s var(--ease); } /* (the head's words swapped, not at once) */
.prefs.at-page .prefs-head > div > .prefs-page-title.swapped { animation: title-swap .3s var(--ease); } /* (Screens' title saying the chain you're among: cards.js's sayPageChain) */
@keyframes title-swap { from { opacity: 0; translate: 0 6px; } }
@media (prefers-reduced-motion: reduce) { .prefs.at-page .prefs-head > div > .prefs-page-title.swapped { animation: fade .2s linear; } }
/* the cinemas, each chain's under its wordmark (legible, some 14px; its name read out), with a way
   to turn them all off (or all on, when they all are), as a phone's settings' sections have: no
   hairline over its first, under its wordmark */
.prefs-chain-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 24px 14px 8px; }
.prefs-chain:first-child .prefs-chain-head { padding-top: 6px; }
.prefs-chain-mark { height: 14px; }
.prefs-group-name { font-size: 0.72rem; font-weight: 650; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-faint); } /* (a heading of words, where a chain's is its mark: the Indian languages') */
.prefs-chain-mark .chain-mark { position: static; display: block; translate: none; max-width: none; height: 100%; background: rgba(255, 255, 255, 0.62); }
.prefs-chain-all {
  margin: -6px -8px; padding: 6px 8px; border: 0; border-radius: 8px; background: none; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 0.8rem; font-weight: 600; transition: background .2s;
}
@media (hover: hover) { .prefs-chain-all:hover { background: rgba(169, 150, 255, 0.1); } }
.prefs-chain-all:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
.prefs-chain-all.refused { animation: refuse .4s ease; } /* (the last of your cinemas, all this chain's: one stays) */
/* a cinema new to you (cards.js's freshCinemas): a small tag after its name, for the visit */
.pref-new {
  display: inline-block; margin-left: 8px; padding: 1px 6px; border-radius: 5px; vertical-align: 1px;
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--accent); background: rgba(169, 150, 255, 0.14);
}
/* the sheet one height all the while (a phone's large sheet), so it doesn't jump as a page
   comes; the head over the pages, each scrolling on its own under it, one over the other. On a
   phone on its side, all but the top 12px: its 86% left a page's rows a sliver under its head */
.prefs[open] { display: flex; flex-direction: column; height: calc(min(86svh, 720px) + var(--sheet-under, 0px) + env(safe-area-inset-bottom)); overflow: hidden; }
@media (orientation: landscape) and (max-height: 499px) {
  .prefs[open] { height: calc(100svh - 12px + var(--sheet-under, 0px) + env(safe-area-inset-bottom)); }
  dialog.sheet { max-height: calc(100svh - 12px + var(--sheet-under)); }
}
.prefs form { flex: 1 1 auto; min-height: 0; display: grid; grid-template: auto minmax(0, 1fr) / minmax(0, 1fr); gap: 0; padding: 0; overflow: clip visible; } /* (a page out to the right cut off; the first, held where it was as the head grows, not: cards.js's stillUnder) */
html.page-scroll dialog.sheet.prefs > .sheet-body { overflow: clip visible; } /* (its head out of it: the pages scroll, not the form) */
.prefs .prefs-head { grid-area: 1 / 1; position: relative; margin: 0; }
.prefs :is(.prefs-root, .prefs-page) {
  grid-area: 2 / 1; display: grid; align-content: start; gap: 30px; min-height: 0; padding: 6px 20px 28px;
  overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none;
}
.prefs :is(.prefs-root, .prefs-page)::-webkit-scrollbar { display: none; }
.prefs .prefs-intro { margin: 0 4px -6px; }
.prefs-page > fieldset > legend { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } /* (its name's in the head: still the part's name, read out) */
/* a page comes as a phone's settings' does: a big move from rest (--set-off), the first going a
   little left and fading under it; back, the same in reverse, in step. Out of sight once it's
   there (visibility, after the move): out of Tab's way too, as inert has it (cards.js) */
.prefs .prefs-root { transition: translate .35s var(--set-off), opacity .22s var(--set-off), visibility 0s; }
.prefs.at-page .prefs-root { translate: -30% 0; opacity: 0; visibility: hidden; transition: translate .35s var(--set-off), opacity .22s var(--set-off), visibility 0s .35s; }
.prefs .prefs-page { translate: 100% 0; visibility: hidden; transition: translate .35s var(--set-off), visibility 0s .35s; }
.prefs .prefs-page.up { translate: none; visibility: visible; transition: translate .35s var(--set-off), visibility 0s; }
dialog.sheet.prefs .prefs-sum:not(:has(.prefs-sum-new)) { color: rgba(255, 255, 255, 0.5); mix-blend-mode: plus-lighter; } /* (vibrant, as the rows' quieter words) */
@media (prefers-reduced-motion: reduce) {
  .prefs :is(.prefs-root, .prefs-page) { transition: none !important; } /* (a page there at once) */
  .prefs-chain-all.refused { animation: none; } /* (its words say why) */
}

/* ——— 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), (orientation: landscape) and (max-height: 499px) {
  .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), (orientation: landscape) and (max-height: 499px) { .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, 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; }
.pick-tile[data-day="notyet"] { opacity: 1; background: none; box-shadow: none; color: rgb(244 241 234 / 0.24); } /* (not fully scheduled yet: no tile, as the month draws it, not dimmed as a day with nothing for you is) */
.pick-tile[data-day="notyet"] .pick-words { font-weight: 500; }
@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; }
/* a film's special event (cards.js's sayEvents, flatten, sortCinemas, eventBanner): its times in a
   fine gold frame, a hairline of the cards' gold and a faint wash of it; on its top edge a gold-foil
   ribbon, "★ PREVIEW SCREENING" (the event's name, its first time's data-event), the light falling
   into the frame from it; a Q&A's guests in that light, centred under the ribbon (.event-banner).
   No star on the times, the frame says it. Its day's tab a
   little gold star over its date, to be found from the other days. Its line under the days heard
   only (.sr-only). (The owner's D of six mocked, 2 Nov 2026; its banner the owner's F, "Ribbon
   light", of seven mocked (explore/event-banner), 3 Nov 2026) */
:root {
  --star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11.1 2.6a1 1 0 0 1 1.8 0l2.4 4.9a1.6 1.6 0 0 0 1.2.9l5.4.8a1 1 0 0 1 .5 1.7l-3.9 3.8a1.6 1.6 0 0 0-.5 1.4l.9 5.4a1 1 0 0 1-1.4 1l-4.8-2.5a1.6 1.6 0 0 0-1.5 0l-4.8 2.5a1 1 0 0 1-1.4-1l.9-5.4a1.6 1.6 0 0 0-.5-1.4L1.6 10.9a1 1 0 0 1 .5-1.7l5.4-.8a1.6 1.6 0 0 0 1.2-.9Z'/%3E%3C/svg%3E"); /* (a rounded five-point star, solid) */
  --gold-foil: linear-gradient(100deg, #b38c46 0%, #f3dea4 28%, #d4b067 52%, #f7e9bd 74%, #b8914b 100%); /* (a ribbon's: the gold, lit unevenly, as foil) */
  --gold-hair: color-mix(in srgb, var(--gold) 42%, transparent); --gold-wash: color-mix(in srgb, var(--gold) 8%, transparent);
}
.st-cinema[data-event]:not([hidden]) { position: relative; padding-right: 8px; background: var(--gold-wash); box-shadow: inset 1px 0 0 var(--gold-hair), inset -1px 0 0 var(--gold-hair); }
.st-cinema[data-event].st-event-top { margin-top: 18px; padding-top: 0; border-radius: 12px 12px 0 0; box-shadow: inset 1px 0 0 var(--gold-hair), inset -1px 0 0 var(--gold-hair), inset 0 1px 0 var(--gold-hair); }
.st-cinema[data-event].st-event-end { margin-bottom: 8px; padding-bottom: 2px; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; box-shadow: inset 1px 0 0 var(--gold-hair), inset -1px 0 0 var(--gold-hair), inset 0 -1px 0 var(--gold-hair); }
.st-cinema[data-event].st-event-top.st-event-end { box-shadow: inset 0 0 0 1px var(--gold-hair); }
.st-cinema[data-event].st-event-top .st-time { background-image: none; } /* (no line between under its banner, wherever it falls in the day: the frame's top bounds it, as .period-first) */
/* its banner (cards.js's eventBanner: unread, heard on each time instead, versionSaid and qaSaid), on
   its first time only: the light from the ribbon, the ribbon on the edge (.event-name, its star and
   name), a Q&A's guests under it (.event-guests), centred as on an invitation, the names in a serif
   italic, "With" and "and" plain words, as who they play is */
.event-banner { display: none; }
.st-event-top > .event-banner {
  display: block; position: relative; margin-right: -8px; padding: 18px 18px 4px; border-radius: 12px 12px 0 0; text-align: center;
  background: radial-gradient(62% 100% at 50% 0%, color-mix(in srgb, var(--gold) 21%, transparent), transparent 78%);
}
.st-event-top:not(.qa-show) > .event-banner { padding-top: 12px; } /* (no guests: room for the ribbon's lower half) */
.event-banner::before { /* (the ribbon's own glow, on the edge round it) */
  content: ""; position: absolute; top: 0; left: 50%; width: min(260px, 80%); height: 26px; translate: -50% -50%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--gold) 30%, transparent), transparent);
}
.event-name {
  display: flex; align-items: center; gap: 5px; position: absolute; z-index: 1; top: 0; left: 50%; translate: -50% -50%; max-width: calc(100% - 28px);
  height: 20px; padding: 0 14px 0 13px; box-sizing: border-box; background: var(--gold-foil); color: #2a1c07;
  font-size: 10px; font-weight: 700; line-height: 20px; letter-spacing: 0.12em; text-transform: uppercase; white-space: nowrap;
  clip-path: polygon(0 0, 100% 0, calc(100% - 6px) 50%, 100% 100%, 0 100%, 6px 50%); /* (swallowtail ends) */
  filter: drop-shadow(0 2px 5px rgb(0 0 0 / 0.55));
}
.event-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; translate: 0 -0.5px; } /* (its capitals in the ribbon's middle, by eye: Chromium and WebKit, 3 Nov 2026) */
.event-star { flex: none; width: 10px; height: 10px; translate: 0 -0.25px; background: currentColor; -webkit-mask: var(--star) center / contain no-repeat; mask: var(--star) center / contain no-repeat; } /* (on the capitals' middle, by eye) */
.event-guests { margin: 0; font-size: 0.74rem; line-height: 1.55; text-wrap: pretty; color: var(--ink-faint); }
.st-day.st-day-event { position: relative; overflow: visible; }
/* a checked time's bar inside the frame: clear of its gold sides, and no faint line of its own (the frame's foot is the row's end) */
.st-cinema[data-event] .st-time[data-full]::after { left: 8px; width: max(3px, calc((100% - 22px) * var(--full) / 100)); }
.st-cinema[data-event] .st-time[data-full]::before { display: none; }
/* a time's light inside the frame: 1px in from the gold, not 10px past the text out over it (and
   2px on the right); its text where it was, the dot's track 2px less for the 2px it starts in */
.st-one[data-event] .st-time {
  margin: 0 0 0 2px; width: calc(100% + 4px); padding-left: 0; padding-right: 6px; border-radius: 7px;
  grid-template-columns: [dot] 14px [time] 4.5em [gap] 9px [where] minmax(0, 1fr) [screens] auto [when] auto [badge] auto;
}
.st-days:has(.st-day-event) { padding-top: 6px; }
.st-day-star { position: absolute; top: -5px; left: 50%; translate: -50% 0; width: 8px; height: 8px; background: var(--gold); -webkit-mask: var(--star) center / contain no-repeat; mask: var(--star) center / contain no-repeat; filter: drop-shadow(0 0 4px color-mix(in srgb, var(--gold) 70%, transparent)); }
@media (forced-colors: active) { .st-cinema[data-event]:not([hidden]) { border: 1px solid CanvasText; } .event-name { color: CanvasText; background: Canvas; border: 1px solid CanvasText; clip-path: none; } .event-star, .st-day-star { background: CanvasText; } }
@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, or on its side), 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 seat map, as they were ——— */
.st-what, .st-brief, .times-fold { display: none; }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  /* (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) */
  /* 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 the filters' (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, the filters' 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), (orientation: landscape) and (max-height: 499px) 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) {
  .times-cover .dressed .st-days { --pick-fade: 40px; }
}
/* (what it is and its story) */
@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 .dressed :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.dressed) .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 .dressed .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 .dressed .st-genres { display: flex; gap: 5px; margin: 7px 0 2px; }
  .times-cover .dressed .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 .dressed .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 .dressed .st-brief { display: flex; align-items: flex-end; gap: 12px; }
  .times-cover .dressed .st-last { display: flex; } /* (Last chance's line: below, with its chip) */
  .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-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) */
}
/* ——— Facts first (cards.js's FACTS_FIRST): under a phone's film's name, what it is on one line,
   "2h 55m · 15+ · 85% · 94% · Action" (cut short at its genre, never wrapped), then two lines of its
   story, More at the end of the second; opened, all of it, Less and Cast and more under it. Over the
   poster's crop, the soft shadow under the words that what it is had. Nowhere else ——— */
.st-facts, .st-story, .st-marks { display: none; } /* (.st-marks: under a phone's poster alone, below) */
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .times-cover .dressed .st-facts {
    display: block; margin: 2px 0 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
    font-size: 0.84rem; line-height: 1.45; color: var(--ink-soft); font-variant-numeric: tabular-nums;
  }
  .st-facts > .age-tag { font-size: 10.5px; vertical-align: 1px; }
  .st-facts-dot { color: var(--ink-faint, var(--ink-soft)); opacity: 0.7; }
  .times-cover .dressed :is(.st-facts, .st-story-text) { text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55); }
  .times-cover .dressed .st-story { display: flex; flex-wrap: wrap; align-items: flex-end; column-gap: 12px; row-gap: 6px; margin-top: 4px; }
  .st-story-text {
    flex: 1; min-width: 0; margin: 0; font-size: 0.86rem; line-height: 1.45; color: var(--ink-soft); text-wrap: pretty; overflow: hidden;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  }
  .st-story.open .st-story-text { flex-basis: 100%; display: block; -webkit-line-clamp: unset; }
  .st-story :is(.st-story-more, .st-story-on) { flex: none; position: relative; font-size: 0.82rem; font-weight: 600; line-height: 1.45; }
  .st-story :is(.st-story-more, .st-story-on)::after { content: ""; position: absolute; inset: -12px -8px; } /* (a finger's) */
  .st-story.fits:not(.open) .st-story-more, .st-story:not(.open) .st-story-on { display: none; }
  .st-story.open.fresh .st-story-on { animation: story-on .3s var(--ease) .12s backwards; }
  .st-story.open .st-story-on::before { content: "↓ "; } /* (down the page, to all about it) */
  /* (the trailer's button a little further from the story than from the name) */
  html.page-scroll.film-page .times-cover .dressed :is(.st-facts, .st-story) + .st-watch { margin-top: 12px; }
}
@keyframes story-on { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .st-story.fresh .st-story-on { animation: none; } }
/* ——— A phone on its side: upright's layout, wider and shorter, kept clear of the notch and the
   rounded corners at the left or right, whichever way it's turned: the safe area's insets, the
   wider of the two each side (:root's --sa-side, 16px where there's none; the grid's column maths
   read it from .safe-probe: cards.js's safeSide) ——— */
.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); }
/* 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.empty { color: var(--ink-faint); } /* a score not given yet ("--%") */
.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); }
.info-credits .tcg-dubbed { color: var(--ink-faint); } /* (a film's dubbed versions, after its original language: cards.js's languageSaid) */
/* 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; }
.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-name { white-space: nowrap; } /* (a name and its comma: cards.js's creditsOf) */
.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), (orientation: landscape) and (max-height: 499px) { .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; }
html:not(.trailer-up) body:has(.table.playing) .ambient img.on { opacity: 0.3; } /* (not under the bar, on a phone's film page: the page as it is) */
.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; }
html.page-scroll .table.empty.grid-mode .grid-view > :not(.pickers) { display: none; } /* (on a phone the grid's in the page: its old films, hidden, would keep it as tall as they were, and the words, in its middle, far down off the screen) */
.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); inset-inline: 16px; width: fit-content; margin-inline: auto; top: 50%; translate: 0 -50%; } /* (centred by its margins, not from half way: from half way it could only be as wide as the half on its right, half a phone) */
.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: dropWays, nextDay, ageWay) */
.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 short window: the video fitted to its height, 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; }
}
/* ——— 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; }
  /* 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 */
  .find-cancel { position: relative; }
  .find-cancel::after { content: ""; position: absolute; inset: -4px -6px; }
}

/* ——— 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):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 { 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; }
/* a finger's press (a phone's, with no hover): what it lands on gives under it, as a thing you
   could push would. Only once it's stayed put a moment (as the rows above: a scroll's first moment
   presses nothing), and not at all once it's set off scrolling (cards.js's touch-moved: let go
   smoothly, not sprung, so a scroll never looks like a press). Let go, it springs back up past
   where it was, a little, and settles (the little cards' spring, .springing: ζ 0.45). */
@media (hover: none) and (pointer: coarse) {
  :root { --spring-back: 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 chips (days, cinemas, a film's languages and cinemas, the search's) and a film's days: they sink, and light a little */
  :is(.pick-tile, .where-pick, .find-chip) { transition: background .2s, border-color .2s, box-shadow .2s, color .2s, opacity .2s, filter .3s var(--ease), transform .55s var(--spring-back); }
  :is(.pick-tile, .where-pick, .find-chip):active:not(.touch-moved *, [aria-disabled="true"]) {
    transform: scale(0.94); transition: transform .08s var(--ease) .07s, background .08s .07s, filter .08s .07s;
  }
  :is(.pick-tile, .where-pick, .find-chip):not([aria-pressed="true"]):active:not(.touch-moved *, [aria-disabled="true"]) { background: rgba(255, 255, 255, 0.1); }
  :is(.pick-tile, .where-pick, .find-chip)[aria-pressed="true"]:active:not(.touch-moved *) { filter: brightness(0.88); } /* (the cream one: a shade darker) */
  .st-day > * { transition: transform .55s var(--spring-back); transform-origin: 50% 100%; }
  .st-day > * + * { transform-origin: 50% 0; } /* (its name and date drawn in toward each other: one thing pressed, not two) */
  .st-day:active:not(.touch-moved *) > * { transform: scale(0.9); transition: transform .08s var(--ease) .07s; } /* (its words, not its line under it) */
  /* the film's Show Trailer: as a chip, a little less (it's wider) */
  html.page-scroll.film-page .times-cover .dressed .st-watch { transition: background .2s, transform .55s var(--spring-back); }
  html.page-scroll.film-page .times-cover .dressed .st-watch:active:not(.touch-moved *) { transform: scale(0.96); background: rgba(255, 255, 255, 0.17); transition: transform .08s var(--ease) .07s, background .08s .07s; }
  /* set off scrolling: let go at once, eased (not sprung back as from a press) */
  html.touch-moved :is(.pick-tile, .where-pick, .find-chip, .st-day > *) { transform: none; transition-duration: .2s; transition-timing-function: var(--ease); } /* (none: Safari keeps it :active meanwhile) */
  html.touch-moved.page-scroll.film-page .times-cover .dressed .st-watch { transform: none; background: rgba(255, 255, 255, 0.1); transition: background .2s, transform .2s var(--ease); }
  /* a little card, pressed (cards.js's lean: a little deeper than a mouse's, 0.96): down out of the
     light a little, all but its top edge, which catches it as it tips */
  .tile-card::after {
    content: ""; position: absolute; inset: 0; z-index: 4; border-radius: inherit; pointer-events: none;
    background: linear-gradient(rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 30%), rgba(0, 0, 0, 0.16);
    opacity: 0; transition: opacity .35s var(--ease);
  }
  .film-tile.pressed .tile-card::after { opacity: 1; transition-duration: .09s; }
}
@media (hover: none) and (pointer: coarse) and (prefers-reduced-motion: reduce) {
  :is(.pick-tile, .where-pick, .find-chip, .st-day > *), html.page-scroll.film-page .times-cover .dressed .st-watch { transform: none !important; } /* (the light alone: no sinking) */
  :is(.pick-tile, .st-cinema-pick) { transition: none; } /* (as they were without motion) */
}

@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-versions { display: grid; gap: 8px; } /* (a film's versions rated differently: each rating, whose it is beside it: cards.js's ageUnit) */
.age-version { display: flex; align-items: center; gap: 8px; }
.age-version-names { font-size: 0.84rem; color: var(--ink); white-space: nowrap; }
.age-contains { flex: 1; min-width: 0; margin: 0; font-size: 0.84rem; line-height: 1.35; color: var(--ink); text-wrap: pretty; }
.age-words { flex: 1; min-width: 0; display: grid; gap: 4px; } /* (a rating not the UAE's: its notes, then that said under them) */
.age-foreign { color: var(--ink-soft); }

/* ——— A 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); /* (taps on it its own: not to a heading or a film blurred under it) */
  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 filters are on; then the bar says them,
   as wider screens' does ("[Tonight] [MOE]", 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 a 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: env(safe-area-inset-top) var(--sa-r) 0 var(--sa-l);
  overflow: visible; /* (its ground's reach past its foot shown, not clipped: a phone's .find hides what's past it, and a strip of the page showed over the keyboard as the browser's own bar went; its results scroll on their own) */
  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;
}
/* its way in (the owner's pick of four, 25 Oct 2026; the others are on the explore/search-transitions
   branch): the magnifier tapped, top right, turns into Cancel in its place, so a tap there again
   undoes it; under it, the search's ground and the page's dimming fade in, then its field and its
   own magnifier (from a little left of its place), the line under them and what's under that.
   Closing, the same back: Cancel turns into the magnifier again as the rest goes. Its ground on its
   ::before (its reach past its foot with it), to fade on a layer of its own; everything that moves
   on a layer of its own for good (will-change: made as it starts, in Safari it cost the first frame,
   and it seemed to start part-way through); the way in held till it's drawn (cards.js's arrive);
   closing, its own (::before, ::backdrop) end together, as closeSheet closes it on the first. The
   magnifier's place on Cancel: cards.js's anchorFind. */
html.page-scroll .find:not(.from-bar) { background: transparent; box-shadow: none; }
html.page-scroll .find:not(.from-bar)::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: rgb(10 9 13 / 0.97); box-shadow: 0 0 0 100vh rgb(10 9 13 / 0.97); will-change: opacity;
}
html.page-scroll .find:not(.from-bar)::backdrop { will-change: opacity; }
html.page-scroll .find:not(.from-bar) :is(.find-bar > .icon-find, .find-glint, .find-field, .find-cancel-word, .find-sum, .find-results),
html.page-scroll .find:not(.from-bar) .find-bar::after { will-change: opacity, transform; }
html.page-scroll .find:not(.from-bar) .find-cancel-word { display: inline-block; }
html.page-scroll .find:not(.from-bar) .find-cancel::before {
  content: ""; position: absolute; left: var(--anchor-x, 0px); top: var(--anchor-y, 0px); width: var(--anchor-size, 19px); height: var(--anchor-size, 19px);
  background: var(--ink); -webkit-mask: url("/static/icon-find.svg") center / contain no-repeat; mask: url("/static/icon-find.svg") center / contain no-repeat;
  opacity: 0; pointer-events: none; will-change: opacity, transform;
}
html.page-scroll .find:not(.from-bar):is([open], .closing) { animation: none; }
html.page-scroll .find:not(.from-bar)[open]:not(.closing)::before { animation: fade .2s var(--ease) both; } /* (its ground first, quickly: nearly whole before the field's over it) */
html.page-scroll .find:not(.from-bar)[open]:not(.closing)::backdrop { animation: fade .3s var(--ease) both; }
html.page-scroll .find:not(.from-bar)[open]:not(.closing) .find-cancel::before { animation: anchor-go .22s var(--set-off) both; }
html.page-scroll .find:not(.from-bar)[open]:not(.closing) .find-cancel-word { animation: anchor-word-in .28s var(--set-off) .07s both; }
html.page-scroll .find:not(.from-bar)[open]:not(.closing) .find-bar > .icon-find { animation: anchor-left-in .3s var(--set-off) .1s both; }
html.page-scroll .find:not(.from-bar)[open]:not(.closing) :is(.find-field, .find-glint) { animation: fade .3s var(--set-off) .12s both; }
html.page-scroll .find:not(.from-bar)[open]:not(.closing) :is(.find-sum, .find-results) { animation: fade .28s var(--set-off) .16s both; }
html.page-scroll .find:not(.from-bar)[open]:not(.closing) .find-bar::after { animation: find-dawn .42s var(--set-off) .16s both; }
html.page-scroll .find:not(.from-bar).closing::before, html.page-scroll .find:not(.from-bar).closing::backdrop { animation: fade-out .2s var(--leave) .12s forwards; }
html.page-scroll .find:not(.from-bar).closing .find-cancel-word { animation: anchor-word-go .16s var(--leave) forwards; }
html.page-scroll .find:not(.from-bar).closing .find-cancel::before { animation: anchor-back .32s var(--set-off) forwards; }
html.page-scroll .find:not(.from-bar).closing :is(.find-bar > .icon-find, .find-field, .find-glint, .find-sum, .find-results),
html.page-scroll .find:not(.from-bar).closing .find-bar::after { animation: fade-out .16s var(--leave) forwards; }
html.page-scroll .find:not(.from-bar).measuring, html.page-scroll .find:not(.from-bar).measuring * { animation: none !important; } /* (cards.js's anchorFind, measuring: things where they'll be) */
/* the bar's own magnifier, while it's open: it's the one on Cancel (and back on it as it closes) */
html.page-scroll body:has(.find:not(.from-bar)[open]) .page-find .icon-find { opacity: 0; }
@keyframes anchor-go { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(0.55); } }
@keyframes anchor-back { 0%, 30% { opacity: 0; transform: scale(0.55); } to { opacity: 1; transform: none; } }
@keyframes anchor-word-in { from { opacity: 0; transform: scale(0.82); } }
@keyframes anchor-word-go { to { opacity: 0; transform: scale(0.82); } }
@keyframes anchor-left-in { from { opacity: 0; transform: translateX(-10px); } }
@media (prefers-reduced-motion: reduce) {
  html.page-scroll .find:not(.from-bar), html.page-scroll .find:not(.from-bar) *, html.page-scroll .find:not(.from-bar)::before,
  html.page-scroll .find:not(.from-bar) *::before, html.page-scroll .find:not(.from-bar) *::after, html.page-scroll .find:not(.from-bar)::backdrop { animation: none !important; }
}
/* ——— The thumb bar (html.thumb: a phone upright, cards.js's THUMB_BAR): what you pick the films
   by (.thumb-picks: the day, the time, the cinema, the age limit) and Preferences, a pill in the middle
   of the foot as wide as they are, on the same glass as the top's bar, floating clear of the home
   indicator; the top's bar kept, the search's magnifier at its right (the site's logo's room at its
   left, later), the films' first band just under it: no When, Where or Sort over them (the day's the
   bar's, a cinema the cinema button's; When's tiles still there, unseen, what the day button
   picks). Tucked away down past the edge as you scroll down (going from rest: --set-off), back up as
   you scroll up (arriving: --push-in). ——— */
.thumb-bar { display: none; }
html.thumb .grid-view { padding-top: calc(var(--roof) + 20px); padding-bottom: calc(96px + env(safe-area-inset-bottom)); } /* (the last films clear of the bar) */
html.thumb .grid-view > .pickers { display: none; }
html.thumb .table > .stack { justify-self: stretch; } /* (the screen's width, however few films: without When's wide line, Chromium's block layout centred it as narrow as they are, .table's justify-items) */
html.thumb .corner-left { display: none; }
html.thumb .thumb-bar {
  --thumb-gap: 10px; /* (over the home indicator's room, or the screen's edge) */
  position: fixed; z-index: var(--z-bar); left: 0; right: 0; bottom: calc(env(safe-area-inset-bottom) + var(--thumb-gap));
  width: max-content; margin-inline: auto;
  display: flex; align-items: center; gap: 9px; height: 58px; padding: 7px; box-sizing: border-box; border-radius: 29px;
  background: var(--glass); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 0 0 1px var(--hairline), 0 12px 32px rgb(0 0 0 / 0.5);
  transition: transform .4s var(--push-in), opacity .2s var(--ease);
}
.thumb-picks { display: flex; align-items: center; gap: 4px; flex: none; }
html.thumb .thumb-bar.tucked { transform: translateY(calc(100% + var(--thumb-gap) + env(safe-area-inset-bottom) + 24px)); transition: transform .3s var(--set-off), opacity .2s var(--ease); } /* (+24px: its shadow gone too) */
html.thumb.film-page .thumb-bar { display: none; } /* (a film's page: its own bar, and its Book buttons at the foot) */
html.thumb .thumb-bar .thumb-prefs {
  flex: none; display: flex; align-items: center; justify-content: center; height: 44px; border: 0; border-radius: 22px;
  background: none; color: var(--ink); font: inherit; font-size: 0.9rem; font-weight: 500; transition: background .2s, color .2s;
}
html.thumb .thumb-bar .thumb-prefs { position: relative; width: 44px; padding: 0; }
html.thumb .thumb-bar .thumb-prefs::before { content: ""; position: absolute; left: -5px; top: 13px; bottom: 13px; width: 1px; background: rgb(255 255 255 / 0.12); } /* (a hairline between what you pick by and Preferences) */
html.thumb .thumb-bar .thumb-prefs .icon-sliders { width: 17px; height: 13px; }
html.thumb .thumb-bar .thumb-prefs .icon-sliders::before, html.thumb .thumb-bar .thumb-prefs .icon-sliders::after { background: rgb(28 27 32); } /* (the knobs hollow on the bar's glass, not the page's black) */
html.thumb .thumb-bar .thumb-prefs:active { background: rgb(255 255 255 / 0.12); transition-duration: .06s; }
html.thumb .thumb-bar :focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* snug (cards.js's fitThumb): what's picked too wide for the screen, its gaps and a lit button's sides
   narrower, the cinema's name and a long time a size smaller (their lifted copies too) */
html.thumb.bar-snug .thumb-bar { gap: 7px; padding-inline: 6px; }
html.thumb.bar-snug .thumb-bar .thumb-prefs::before { left: -4px; }
html.bar-snug .thumb-picks { gap: 2px; }
html.bar-snug :is(.thumb-time, .thumb-cinema).on { padding: 0 5px; }
html.bar-snug .cinema-name { --f: 12px; letter-spacing: -.03em; }
html.bar-snug .time-word.long { --f: 11px; }
html.bar-snug .time-word.longer { --f: 10.5px; }
/* the three buttons' faces, one layout (the day's, the cinema's, the age's): a face with a tiny top
   line (NOV, VOX, UP TO, ONLY) is laid out from its top, not centred by what's in it, so on all three
   the top line's capitals are at one height and the main line (the date, the cinema's name, the
   limit) sits on one baseline, whatever its size: its line box placed from its size (Inter's
   baseline .8633em down a 1em line). Lit (something picked): Amethyst's violet, one fill for all
   three. Faces with no top line (nothing picked: three outline glyphs of one size; several
   cinemas) centred */
.thumb-day.on, .thumb-cinema.on, .thumb-age.on { background: linear-gradient(165deg, rgb(150 128 255 / 0.55), rgb(90 60 210 / 0.55)); box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.18); color: #fff; }
:is(.day-icon.on, .cinema-icon.on:has(> .cinema-cap), .age-icon.on) { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 0; height: 32px; line-height: 1; }
:is(.day-cap, .cinema-cap, .age-cap) { flex: none; height: 6.5px; margin-top: 4.1px; font-size: 6.5px; line-height: 6.5px; font-weight: 800; letter-spacing: .06em; opacity: .75; white-space: nowrap; }
:is(.day-num, .cinema-name, .age-word) { --f: 13.5px; flex: none; height: var(--f); margin-top: calc(14.9px - .8633 * var(--f)); font-size: var(--f); font-weight: 750; letter-spacing: -.02em; line-height: 1; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* the day button (cards.js's sayThumb): its icon alone, a bold date with its weekday tiny over it
   (a bolt, now; a crescent, tonight); picked, lit; none, a small blank calendar. Its own drag (the
   month's, openMonth): never the page's scroll */
.thumb-day {
  flex: none; display: grid; place-items: center; width: 50px; height: 44px; padding: 0; border: 0; border-radius: 22px;
  background: none; color: var(--ink); font: inherit; cursor: pointer; transition: background .2s;
  touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.thumb-day > * { pointer-events: none; }
.thumb-day.landing > * { opacity: 0; } /* (a day picked: its icon out of sight till the date flown lands in it, cards.js's flyMonth) */
.thumb-day:active, .thumb-day.held { background: rgb(255 255 255 / 0.12); transition-duration: .06s; }
.day-icon { display: grid; grid-template-rows: auto auto; align-content: center; place-items: center; gap: 1px; width: 30px; height: 32px; line-height: 1; font-variant-numeric: tabular-nums; }
.day-num { --f: 17px; display: flex; align-items: flex-end; justify-content: center; }
.day-num:has(> .day-bolt) { height: 17px; margin-top: .25px; }
.day-num:has(> .day-moon) { height: 15px; margin-top: 2.4px; } /* (both: their ink's foot on the baseline, measured) */
.day-bolt { display: block; width: 14px; height: 17px; background: currentColor; -webkit-mask: var(--bolt) center / contain no-repeat; mask: var(--bolt) center / contain no-repeat; }
.day-moon { display: block; width: 15px; height: 15px; background: currentColor; -webkit-mask: var(--moon) center / contain no-repeat; mask: var(--moon) center / contain no-repeat; }
.day-glyph { display: block; width: 17px; height: 17px; border-radius: 4.5px; box-shadow: inset 0 0 0 1.6px rgb(244 241 234 / 0.85); background: linear-gradient(rgb(244 241 234 / 0.85), rgb(244 241 234 / 0.85)) 0 0 / 100% 5px no-repeat; }
/* the cinema button (cards.js's sayCinema): as the day's, its icon alone; a cinema picked, its name
   (its chain tiny over it), lit, the button as wide as the name; several, a pin and how many; none,
   an outline pin. Widening or narrowing (widenCinema), what's new is revealed as it goes
   (overflow), the bar growing round it */
.thumb-cinema {
  flex: none; display: grid; place-items: center; min-width: 50px; height: 44px; padding: 0 8px; box-sizing: border-box; border: 0; border-radius: 22px; overflow: hidden;
  background: none; color: var(--ink); font: inherit; cursor: pointer; transition: background .2s;
  touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.thumb-cinema[hidden] { display: none; }
.thumb-cinema > * { pointer-events: none; }
.thumb-cinema.landing > * { opacity: 0; } /* (a cinema picked: its name out of sight till the copy flown lands in it, cards.js's flyColumn) */
.thumb-cinema.on { padding: 0 11px; }
.thumb-cinema:active, .thumb-cinema.held { background: rgb(255 255 255 / 0.12); transition-duration: .06s; }
.cinema-icon { display: grid; grid-template-rows: auto auto; align-content: center; place-items: center; gap: 1px; min-width: 30px; height: 32px; line-height: 1; }
.cinema-icon.any { width: 30px; }
.cinema-pin { display: block; width: 19px; height: 20px; background: rgb(244 241 234 / 0.85); -webkit-mask: var(--pin) center / contain no-repeat; mask: var(--pin) center / contain no-repeat; }
.cinema-icon.any .cinema-pin { width: 21px; height: 22px; -webkit-mask-image: var(--pin-line); mask-image: var(--pin-line); }
.cinema-pins { position: relative; display: block; width: 22px; height: 20px; }
.cinema-pins .cinema-pin { width: 17px; height: 18px; background: var(--ink); }
.cinema-pins b { position: absolute; right: -4px; top: -3px; min-width: 13px; height: 13px; padding: 0 3px; box-sizing: border-box; border-radius: 7px; background: var(--accent); color: var(--panel); font-size: 9px; font-weight: 800; line-height: 13px; text-align: center; }
/* the age button (cards.js's sayAge): as the cinema's size, its face alone; a limit on, lit, the
   limit in words ("PG13", as the cinema's name) with UP TO tiny over it (G only, 18+ only: ONLY);
   none, two figures in outline. Hidden till switched on in Preferences */
.thumb-age {
  position: relative; flex: none; display: grid; place-items: center; width: 50px; height: 44px; padding: 0; box-sizing: border-box; border: 0; border-radius: 22px; overflow: hidden;
  background: none; color: var(--ink); font: inherit; cursor: pointer; transition: background .2s;
  touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.thumb-age[hidden] { display: none; }
.thumb-age > * { pointer-events: none; }
.thumb-age:active, .thumb-age.held { background: rgb(255 255 255 / 0.12); transition-duration: .06s; }
.age-icon { display: grid; grid-template-rows: auto auto; align-content: center; place-items: center; gap: 2.5px; min-width: 30px; height: 32px; line-height: 1; }
.age-icon.any { width: 30px; }
.age-word { translate: 0 .33px; } /* (measured a device pixel high of the cinema's name beside it) */
.age-icon.any .age-fig { width: 22px; height: 22px; translate: 0 .7px; }
.age-fig { display: block; width: 21px; height: 21px; background: rgb(244 241 234 / 0.85); -webkit-mask: var(--age-fig) center / contain no-repeat; mask: var(--age-fig) center / contain no-repeat; }
/* the search's bar leaves the day, the time and the cinema out (their buttons say them) */
html.thumb .page-find .find-day { display: none; }
.page-find-ph { display: none; }

/* ——— The month (cards.js's openMonth): a small calendar grown from the day button, over the page
   dimmed and blurred as the peek's, the button lifted, the card the pickers' glass (--pick-glass);
   its dates rippling out from the button (each its --in), picked, back toward it (--out, --back)
   as the date flies into it. With less motion, just faded. The line's signs (nothing for your
   settings, a no-entry sign; shows finished, a tick) ——— */
:root {
  --sign-out: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Cpath d='M6 18 18 6'/%3E%3C/svg%3E");
  --sign-done: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5 10 17.5 19 7'/%3E%3C/svg%3E");
}
.month {
  position: fixed; inset: 0; z-index: calc(var(--z-screen) + 10); pointer-events: none; color: var(--ink); touch-action: none;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.month.tapping, .month.going, .month.picking { pointer-events: auto; }
.month-shade { position: absolute; inset: 0; background: rgb(6 5 10 / 0.52); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); opacity: 0; transition: opacity .22s var(--set-off); }
.month.up .month-shade { opacity: 1; }
.month.going .month-shade { transition-duration: .18s; }
.month-lift {
  position: absolute; border-radius: 22px; background: rgb(28 26 38 / 0.7); backdrop-filter: blur(28px) saturate(1.8); -webkit-backdrop-filter: blur(28px) saturate(1.8);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1), 0 10px 22px -12px rgba(0, 0, 0, 0.9); transition: transform .28s var(--set-off), box-shadow .28s var(--set-off);
}
.month.up .month-lift { transform: scale(1.06); box-shadow: 0 0 0 0.5px rgb(255 255 255 / 0.22), inset 0 1px 0 rgb(255 255 255 / 0.1), 0 22px 40px -16px rgb(0 0 0 / 0.9); }
.month.going .month-lift { transform: none; transition-duration: .18s; }
.month-card {
  position: absolute; box-sizing: border-box; padding: 14px 12px 12px; border-radius: 26px;
  background: var(--pick-glass); backdrop-filter: blur(30px) saturate(1.7); -webkit-backdrop-filter: blur(30px) saturate(1.7); box-shadow: var(--pick-glass-edge);
  opacity: 0; transform: translateY(14px) scale(0.94); will-change: transform, opacity; transition: transform .3s var(--set-off), opacity .2s var(--set-off);
}
.month.up .month-card { opacity: 1; transform: none; }
.month.going .month-card { transition: transform .18s var(--set-off), opacity .14s var(--set-off); }
/* its line, one row: the date ("Tomorrow, 31 October", fitted) and its films, quiet at the right;
   one height whatever it says (a count's bold, a reason's sign: the card's top edge never jumps as
   a finger slides), the right side a block, so its baseline is always its words' */
.month-read { display: flex; align-items: baseline; gap: 10px; height: 26px; padding: 0 6px; }
.month-title { flex: 1; min-width: 0; font-size: 1.04rem; font-weight: 640; letter-spacing: -.015em; line-height: 24px; white-space: nowrap; overflow: hidden; text-overflow: clip; }
.month-sub { flex: none; display: block; font-size: .8rem; font-weight: 500; line-height: 24px; color: var(--ink-faint); white-space: nowrap; overflow: hidden; }
.month-sub:empty { display: none; }
.month-sub b { margin-right: .25em; color: var(--ink); font-weight: 650; font-variant-numeric: tabular-nums; }
/* a date's reason (cards.js's sayWhy): its sign, then its words; shows finished a touch brighter */
.month-why { display: inline-block; width: 12px; height: 12px; margin-right: 6px; vertical-align: -1px; background: currentColor; -webkit-mask: var(--sign-out) center / contain no-repeat; mask: var(--sign-out) center / contain no-repeat; }
.month-why.done { -webkit-mask-image: var(--sign-done); mask-image: var(--sign-done); }
.month-sub:has(.month-why.done) { color: var(--ink-soft); }
/* the weeks: two-letter weekdays, the weekend's violet */
.month-dow { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; padding: 10px 0 7px; font-size: .62rem; font-weight: 600; letter-spacing: .04em; color: rgb(244 241 234 / 0.4); text-align: center; }
.month-dow .weekend { color: color-mix(in srgb, var(--accent) 62%, rgb(244 241 234 / 0.4)); }
.month-cells { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
/* each date (cards.js's dayLook): an eyebrow (TODAY, the moon tonight, NOV), the date, on a faint
   tile as far as it's scheduled (data-day): full, the tile alone; notyet (not fully scheduled yet
   by every chain of yours), no tile, a faint date; the past, blank and not answering. Today ringed. Every date's eyebrow and number centred as a pair, so the numbers
   sit on one line along a week (today's and a no-entry's as the rest) */
.month-cell {
  position: relative; height: 50px; box-sizing: border-box; border-radius: 14px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  opacity: 0; transform: scale(0.6); transition: transform .26s var(--set-off) var(--in, 0s), opacity .18s var(--set-off) var(--in, 0s), background .15s, box-shadow .15s;
}
.month.up .month-cell { opacity: 1; transform: none; }
.month.up .month-cell:is(.over, .press, .hint), .month.going .month-cell { transition-delay: 0s; }
.month-eye { display: flex; align-items: center; justify-content: center; height: 9px; font-size: .5rem; line-height: 9px; font-weight: 750; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); white-space: nowrap; }
.month-eye.today { color: var(--accent); }
.month-date { margin-top: 3px; font-size: 1.08rem; font-weight: 600; letter-spacing: -.02em; line-height: 1; font-variant-numeric: tabular-nums; }
.month-cell.today { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.month-cell.today .month-date { font-weight: 700; color: color-mix(in srgb, var(--accent) 55%, white); }
.month-cell.gone { visibility: hidden; pointer-events: none; }
.month-cell.none .month-date { font-weight: 500; }
/* not in When's days, a finger slid onto it: lifted in grey glass, so where it is shows (its tile,
   if it has one, kept) */
.month.up .month-cell.hint { transform: translateY(-5px) scale(1.1); background: rgb(255 255 255 / 0.12); box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.25); }
.month.up .month-cell.hint > * { color: rgb(244 241 234 / 0.75); }
.month-cell[data-day="full"]:not(.on, .over, .press, .pressed, .today) { background: rgb(255 255 255 / 0.035); }
.month-cell[data-none]:not(.over, .hint) .month-date { color: rgb(143 156 192 / 0.5); font-weight: 500; }
.month-cell[data-day="notyet"]:not(.over, .hint) .month-date { color: rgb(244 241 234 / 0.24); font-weight: 500; } /* (not to be picked: about as dim as a faded no-entry's, so brighter reads as pickable) */
/* can't be picked (data-none): settings (nothing for your current settings), the tile faded while
   the month's up, a no-entry sign in the eyebrow's place, the pair centred; done (today, its shows
   finished, until 5AM), a violet line straight through the date (white while lifted). Today's tile
   then a quiet grey ring */
.month-cell.today[data-none]:not(.on, .over, .press, .pressed) { background: rgb(255 255 255 / 0.035); box-shadow: inset 0 0 0 1px rgb(244 241 234 / 0.12); }
.month-cell.today[data-none] .month-eye { color: var(--ink-faint); }
.month.up:not(.picking) .month-cell[data-none="settings"]:not(.over, .hint, .press, .pressed) { opacity: .5; } /* (only while the month's up: coming in, picking, they go as the rest do) */
.month-noentry { flex: none; display: block; width: 9px; height: 9px; background: rgb(244 241 234 / 0.75); -webkit-mask: var(--sign-out) center / contain no-repeat; mask: var(--sign-out) center / contain no-repeat; }
.month-cell[data-none="done"] .month-date { position: relative; }
.month-cell[data-none="done"]:not(.over, .hint) .month-date { color: rgb(244 241 234 / 0.62); }
.month-cell[data-none="done"] .month-date::after { content: ""; display: block; position: absolute; left: -4px; right: -4px; top: 50%; height: 2px; margin-top: -1px; border-radius: 1px; background: #8a6cff; } /* (the picked tile's violet, deeper than TODAY's pale --accent, which read as white over the date) */
.month-cell[data-none="done"].over .month-date::after { background: #fff; }
.month .month-cell.today[data-none="done"] .month-eye { color: color-mix(in srgb, var(--accent) 70%, transparent); } /* (kept as it lifts) */
.month-cell.press { background: var(--pick-press); }
/* pressed, one that can't be picked (off: in When's days, refused; none: not in them): the slide's
   grey glass, not the pick's violet, so a tap says no as a slide onto it does */
.month-cell.press:is(.off, .none) { background: rgb(255 255 255 / 0.12); }
/* lifted under a sliding finger (or the keys): bright violet; lifted as soon as it's over, the
   month still opening, or going (not .up's still). One that can't be picked: grey glass */
.month .month-cell.over { z-index: 2; transform: translateY(-7px) scale(1.18); background: var(--pick-lift); box-shadow: var(--pick-lift-glow); }
.month .month-cell.over > * { color: white; opacity: 1; } /* (today's date too) */
.month-cell.over .month-glyph { background: white; }
/* picked: a deeper violet */
.month-cell.on { background: var(--pick-on); box-shadow: var(--pick-on-glow); }
.month .month-cell.on > * { color: #fff; }
.month-cell.on .month-glyph { background: #fff; }
.month .month-cell.on.over { background: var(--pick-lift); }
.month-cell.on.over > * { color: white; }
.month .month-cell.over.off { transform: translateY(-5px) scale(1.1); background: rgb(255 255 255 / 0.14); box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.25), 0 10px 20px -10px #000; }
.month .month-cell.over.off > * { color: rgb(244 241 234 / 0.75); }
/* the clear (×, a day picked), a chip taken out to the key over the button (.clear) */
.month-chip {
  display: flex; align-items: center; justify-content: center; gap: 8px; height: 46px; padding: 0 12px; border-radius: 16px; box-sizing: border-box;
  background: linear-gradient(rgb(255 255 255 / 0.075), rgb(255 255 255 / 0.04)); box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.14), inset 0 1px 0 rgb(255 255 255 / 0.08);
  font-size: .9rem; font-weight: 620; letter-spacing: -.01em;
  opacity: 0; transform: translateY(10px) scale(.94);
  transition: transform .3s var(--set-off) var(--in, 0s), opacity .2s var(--set-off) var(--in, 0s), background .15s, color .15s, box-shadow .15s;
}
.month.up:not(.picking) .month-chip { opacity: 1; transform: none; }
.month.up:not(.picking) .month-chip:is(.over, .press, .on), .month.going .month-chip { transition-delay: 0s; }
.month :is(.month-cell, .month-chip):focus { outline: none; } /* (a screen reader's put on it: its own ring) */
/* the evening's moon, in today's eyebrow: TODAY's ink (white lifted or picked) */
.month-glyph { flex: none; display: block; width: 9px; height: 9px; -webkit-mask: var(--glyph) center / contain no-repeat; mask: var(--glyph) center / contain no-repeat; }
.month-glyph.moon { --glyph: var(--moon); background: var(--accent); }
.month-cell[data-none="done"]:not(.over) .month-glyph { background: color-mix(in srgb, var(--accent) 70%, transparent); }
.month.up:not(.picking) .month-chip.over { background: var(--pick-lift); color: white; box-shadow: var(--pick-lift-glow); transform: translateY(-4px) scale(1.05); }
.month-chip.press { background: var(--pick-press); }
.month-chip.on { background: var(--pick-on); color: #fff; box-shadow: var(--pick-on-glow); }
/* a pick (flyMonth): what's picked pressed in violet, the rest rippling back toward the button, the
   furthest first; the card's glass and words faded; the shade lifted; a copy of it flying */
.month.flying .month-shade { opacity: 0; transition: opacity .3s var(--set-off) .07s; } /* (as the copy sets off: the grid's filtered under it first) */
.month.flying.from-drag .month-shade { transition-delay: .06s; transition-duration: .26s; }
.month.picking :is(.month-cell, .month-chip):not(.pressed) { opacity: 0; transform: translate(var(--back, 0px, 0px)) scale(.7); transition: transform .2s var(--set-off) var(--out, 0s), opacity .14s var(--set-off) var(--out, 0s); }
.month.picking.from-drag :is(.month-cell, .month-chip):not(.pressed) { transition-delay: 0s; transition-duration: .14s, .1s; }
.month.picking :is(.month-read, .month-dow) { opacity: 0; transition: opacity .16s var(--set-off) .06s; }
.month.picking .month-card {
  background-color: rgb(22 20 30 / 0); background-image: none; box-shadow: none; -webkit-backdrop-filter: blur(0px) saturate(1); backdrop-filter: blur(0px) saturate(1);
  transition: background-color .22s var(--set-off) .04s, box-shadow .22s var(--set-off) .04s, -webkit-backdrop-filter .22s, backdrop-filter .22s;
}
.month.picking .month-cell.pressed { opacity: 1; z-index: 3; transform: scale(.94); background: var(--pick-lift); box-shadow: var(--pick-going-glow); transition: transform .08s var(--set-off); } /* (its violet at once: drawn before the grid filters under it) */
.month.picking .month-cell.pressed > * { color: #fff; }
.month.picking .month-lift { transform: scale(1.06); }
.month.picking.going { opacity: 0; transition: opacity .18s var(--set-off); } /* (less motion: the date pressed, then all of it faded at once) */
.month.picking:is(.settling, .landed) .month-lift { transform: none; opacity: 0; -webkit-backdrop-filter: none; backdrop-filter: none; transition: transform .2s var(--set-off), opacity .12s var(--set-off); } /* (settling just before the date arrives: its glass and old day gone as it's there, the new day's pop not blurred under it) */
.month-fly { position: absolute; left: 0; top: 0; pointer-events: none; will-change: transform; }
.month-ghost {
  position: absolute; box-sizing: border-box; display: flex; flex-direction: column; align-items: center; justify-content: center; border-radius: 14px;
  background: var(--pick-lift); box-shadow: var(--pick-going-glow); will-change: transform, opacity;
}
.month-ghost > * { color: #fff; }
.month-ghost .month-glyph { background: #fff; }
@media (prefers-reduced-motion: reduce) {
  .month-lift, .month-card, .month.going .month-card, .month-cell { transition-property: opacity !important; }
  .month-chip { transition-property: opacity, background, color !important; }
  .month-card, .month-cell, .month-chip, .month.up .month-lift { transform: none !important; }
}

/* ——— The column (cards.js's openColumn): your cinemas in a narrow column grown from the cinema
   button, over the page dimmed and blurred as the month's, the button lifted, on the pickers' glass
   (--pick-glass); its rows rippling up from the button (each its --in), picked, back toward it
   (--out, --back) as the name flies into it; All, the clear, over the button. Two columns side by side where one would be
   too tall (.two). With less motion, just faded. ——— */
.column {
  position: fixed; inset: 0; z-index: calc(var(--z-screen) + 10); pointer-events: none; color: var(--ink); touch-action: none;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.column.tapping, .column.going, .column.picking { pointer-events: auto; }
.column-shade { position: absolute; inset: 0; background: rgb(6 5 10 / 0.52); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); opacity: 0; transition: opacity .22s var(--set-off); }
.column.up .column-shade { opacity: 1; }
.column.going .column-shade { transition-duration: .18s; }
.column-lift {
  position: absolute; border-radius: 22px; background: rgb(28 26 38 / 0.7); backdrop-filter: blur(28px) saturate(1.8); -webkit-backdrop-filter: blur(28px) saturate(1.8);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1), 0 10px 22px -12px rgba(0, 0, 0, 0.9); transition: transform .28s var(--set-off), box-shadow .28s var(--set-off), opacity .12s;
}
.column-lift > .thumb-cinema { width: 100%; }
.column.up .column-lift { transform: scale(1.06); box-shadow: 0 0 0 0.5px rgb(255 255 255 / 0.22), inset 0 1px 0 rgb(255 255 255 / 0.1), 0 22px 40px -16px rgb(0 0 0 / 0.9); }
.column.going .column-lift { transform: none; transition-duration: .18s; }
.column.picking:is(.settling, .landed) .column-lift { transform: none; opacity: 0; -webkit-backdrop-filter: none; backdrop-filter: none; transition: transform .2s var(--set-off), opacity .12s var(--set-off); }
.column-card {
  position: absolute; box-sizing: border-box; display: flex; flex-direction: column; padding: 12px 10px 10px; border-radius: 26px;
  background: var(--pick-glass); backdrop-filter: blur(30px) saturate(1.7); -webkit-backdrop-filter: blur(30px) saturate(1.7); box-shadow: var(--pick-glass-edge);
  opacity: 0; transform: translateY(14px) scale(0.94); will-change: transform, opacity; transition: transform .3s var(--set-off), opacity .2s var(--set-off);
}
.column.up .column-card { opacity: 1; transform: none; }
.column.going .column-card { transition: transform .18s var(--set-off), opacity .14s var(--set-off); }
.column.picking .column-card { background-color: rgb(22 20 30 / 0); background-image: none; box-shadow: none; -webkit-backdrop-filter: blur(0px) saturate(1); backdrop-filter: blur(0px) saturate(1); transition: background-color .22s var(--set-off) .04s, box-shadow .22s var(--set-off) .04s, -webkit-backdrop-filter .22s, backdrop-filter .22s; }
.column.picking .column-read { opacity: 0; transition: opacity .16s var(--set-off) .06s; }
.column.flying .column-shade { opacity: 0; transition: opacity .3s var(--set-off) .07s; }
.column.going.picking { opacity: 0; transition: opacity .2s var(--set-off) .05s; }
.column-fly { position: absolute; left: 0; top: 0; pointer-events: none; will-change: transform; }
.column-ghost { will-change: transform, opacity; }
/* its line: the cinema under the finger (or picked), its chain a small tag, its films quiet at the
   right; at rest, All; a hairline under it */
.column-read { display: flex; align-items: center; gap: 10px; min-height: 24px; padding: 2px 8px 10px; margin: 0 2px 8px; border-bottom: 0.5px solid rgb(255 255 255 / 0.07); }
.column-title { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; font-size: 1rem; font-weight: 650; letter-spacing: -.02em; line-height: 24px; white-space: nowrap; overflow: hidden; }
.column-title .column-chain { padding: 3px 5px 2px; border-radius: 5px; background: rgb(255 255 255 / 0.07); line-height: 1; } /* (the cinema as its row calls it: "Palm Jumeirah VOX") */
/* the nudge, with every cinema on and never chosen: a small tinted pill at the very top, far from the
   thumb (read after the rows: last in the card, drawn first), to Preferences' Cinemas page */
.column-nudge {
  order: -1; align-self: flex-start; display: flex; align-items: center; gap: 5px; margin: -2px 0 8px 2px; padding: 5px 10px 5px 11px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent); box-shadow: inset 0 0 0 0.5px color-mix(in srgb, var(--accent) 35%, transparent);
  font-size: .74rem; font-weight: 600; color: #d4caff; cursor: pointer;
  opacity: 0; transform: translateY(6px); transition: opacity .18s var(--set-off) var(--in, 0s), transform .26s var(--set-off) var(--in, 0s), background .15s;
}
.column-nudge::after { content: ""; width: 5px; height: 5px; margin-left: 1px; border: solid currentColor; border-width: 1.5px 1.5px 0 0; transform: rotate(45deg); } /* (its chevron) */
.column.up .column-nudge { opacity: 1; transform: none; }
.column-nudge.press { background: color-mix(in srgb, var(--accent) 24%, transparent); }
.column-nudge:focus { outline: none; }
.column:is(.going, .picking) .column-nudge { opacity: 0; transition-delay: 0s; transition-duration: .14s; }
.column-sub { flex: none; display: flex; align-items: center; font-size: .74rem; font-weight: 500; line-height: 24px; color: var(--ink-faint); white-space: nowrap; }
.column-sub b { margin-right: .25em; color: var(--ink); font-size: .86rem; font-weight: 650; font-variant-numeric: tabular-nums; }
/* its rows, from the foot up: each its name, its chain faint beside it, its films and a bar for them
   (as the month's: longer and brighter for more, --fill) */
.column-body { display: grid; gap: 8px; }
.column-body.two { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: end; } /* (halves that share the width, whatever their names: a long one cut short, its films in sight) */
.column-list { display: flex; flex-direction: column-reverse; gap: 2px; }
.column-row {
  position: relative; display: flex; align-items: center; gap: 8px; height: var(--row-h, 44px); padding: 0 12px; box-sizing: border-box; border-radius: 13px;
  background: rgb(169 150 255 / 0.05); font-size: .93rem; font-weight: 600; letter-spacing: -.01em;
  opacity: 0; transform: translateY(10px) scale(.92); /* (rising a little as they ripple in) */ transition: transform .26s var(--set-off) var(--in, 0s), opacity .18s var(--set-off) var(--in, 0s), background .15s, box-shadow .15s, color .15s;
}
.column.up .column-row { opacity: 1; transform: none; }
.column.up .column-row:is(.over, .press), .column.going .column-row { transition-delay: 0s; }
.two .column-row { padding: 0 10px; } /* (and its copy flying: .column-fly.two) */
/* two columns, two chains or more: each chain's name once, over its rows, in place of a tag on every
   row (cards.js's COLUMN_CAP high); halved where a chain changes (.cut), both from the foot at one
   rhythm; else the column with fewer spaced out to the other's height, so both start and end level */
.column-body.capped { align-items: stretch; }
.capped:not(.cut) .column-list { justify-content: space-between; }
.column-cap {
  flex: none; height: 20px; box-sizing: border-box; padding: 0 12px 2px; display: flex; align-items: center; gap: 8px;
  font-size: .5rem; font-weight: 750; letter-spacing: .12em; color: rgb(244 241 234 / 0.42);
  opacity: 0; transition: opacity .18s var(--set-off) var(--in, 0s);
}
.column-cap::after { content: ""; flex: 1; height: 0.5px; background: rgb(255 255 255 / 0.08); } /* (a hairline running on from it) */
.column.up .column-cap { opacity: 1; }
.column:is(.going, .picking) .column-cap { opacity: 0; transition-delay: 0s; transition-duration: .12s; }
.column-row.chain-start { margin-bottom: 7px; }
.column-row.chain-start::after { content: ""; position: absolute; left: 14px; right: 14px; bottom: -5.5px; height: 0.5px; background: rgb(255 255 255 / 0.06); } /* (a hairline where the chain changes) */
.column-name { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 6px; white-space: nowrap; overflow: hidden; }
.column-short { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.column-chain { flex: none; font-size: .5rem; font-weight: 750; letter-spacing: .1em; color: rgb(244 241 234 / 0.42); }
.column-row:focus { outline: none; } /* (a screen reader's put on it: its own ring) */
.column-n { flex: none; min-width: 1.4em; font-size: .76rem; font-weight: 600; color: rgb(244 241 234 / 0.62); font-variant-numeric: tabular-nums; text-align: right; }
/* its bar in a slot as wide as the longest (so the counts make a column), from the slot's left */
.column-bar {
  display: block; flex: none; width: 19px; height: 3px;
  transform: scaleX(0); transform-origin: left; opacity: 0; transition: transform .34s var(--set-off), opacity .2s var(--set-off);
}
.column-bar::before {
  content: ""; display: block; width: calc(3px + 16px * var(--fill, 0)); height: 100%; border-radius: 2px;
  background: color-mix(in srgb, var(--accent) calc(45% + 55% * var(--fill, 0)), rgb(244 241 234 / 0.3));
  box-shadow: 0 0 calc(8px * var(--fill, 0)) color-mix(in srgb, var(--accent) calc(70% * var(--fill, 0)), transparent);
}
.column.up .column-bar { transform: none; opacity: 1; transition-delay: calc(var(--in, 0s) + .12s); }
.two .column-bar { display: none; }
.column-row.off > * { opacity: .38; }
/* pressed, a violet wash; picked (as it opens again), a deeper violet; under the finger, lifted in a
   bright violet, the one picked quietening to a violet ring meanwhile (.sliding), so only one's lit */
.column.up .column-row.press { background: var(--pick-press); color: var(--ink); transform: scale(.98); }
.column-row.on { background: var(--pick-on); color: #fff; box-shadow: var(--pick-on-glow); }
.column-row.on :is(.column-chain, .column-n) { color: rgb(255 255 255 / 0.7); }
.column-row.on .column-bar::before { background: rgb(255 255 255 / 0.8); box-shadow: none; }
.column .column-row.over { z-index: 2; transform: translateX(-4px) scale(1.05); background: var(--pick-lift); color: white; box-shadow: var(--pick-lift-glow); }
.column .column-row.over > * { opacity: 1; }
.column-row.over :is(.column-chain, .column-n) { color: rgb(255 255 255 / 0.75); }
.column-row.over .column-bar::before { background: white; box-shadow: none; }
.column-card.sliding .column-row.on:not(.over) { background: none; box-shadow: inset 0 0 0 1px rgb(169 150 255 / 0.65); color: var(--ink); }
.column-card.sliding .column-row.on:not(.over) :is(.column-chain, .column-n) { color: rgb(244 241 234 / 0.5); }
.column-card.sliding .column-row.on:not(.over) .column-bar::before { background: var(--accent); }
/* one with nothing for you, slid over: a quiet lift (its glass lighter, still dimmed): not one to pick */
.column .column-row.off.over { transform: translateX(-2px); background: rgb(255 255 255 / 0.08); color: var(--ink); box-shadow: none; }
.column .column-row.off.over > * { opacity: .5; }
.column-row.off.over :is(.column-chain, .column-n) { color: var(--ink-faint); }
.column.picking .column-row:not(.pressed) { opacity: 0 !important; transform: translate(var(--back, 0px, 0px)) scale(.7); transition: transform .2s var(--set-off) var(--out, 0s), opacity .14s var(--set-off) var(--out, 0s); }
.column.picking.from-drag .column-row:not(.pressed) { transition-delay: 0s; transition-duration: .14s, .1s; }
.column.picking .column-row.pressed { opacity: 1; z-index: 3; transform: scale(.97); background: var(--pick-lift); color: #fff; box-shadow: var(--pick-going-glow); transition: transform .08s var(--set-off); }
.column.picking.from-drag .column-row.pressed { transform: translateX(-4px) scale(1.05); } /* (let go of, lifted: it stays lifted as it goes) */
.column.picking .column-row.pressed :is(.column-chain, .column-n) { color: rgb(255 255 255 / 0.7); } /* (and its copy flying: the same row from press to landing) */
.column.picking .column-row.pressed .column-bar::before { background: rgb(255 255 255 / 0.8); box-shadow: none; }
@media (prefers-reduced-motion: reduce) {
  .column-lift, .column-card, .column.going .column-card, .column-row, .column-bar, .column-nudge { transition-property: opacity !important; }
  .column-card, .column-row, .column-bar, .column.up .column-lift, .column-nudge { transform: none !important; }
}
/* ——— The age button's note (cards.js's sayAgeNote): over the thumb bar a moment, what the films
   are now: the limit in words, its rating bold in its colour (as the bar's line has it) ——— */
.age-note {
  position: fixed; left: 50%; z-index: calc(var(--z-screen) + 20); display: flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px 0 9px; box-sizing: border-box; border-radius: 18px;
  background: rgb(28 26 38 / 0.78); -webkit-backdrop-filter: blur(24px) saturate(1.7); backdrop-filter: blur(24px) saturate(1.7);
  box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.16), inset 0 1px 0 rgb(255 255 255 / 0.08), 0 12px 28px -10px rgb(0 0 0 / 0.8);
  color: var(--ink); font-size: .84rem; font-weight: 600; letter-spacing: -.01em; white-space: nowrap; pointer-events: none;
  opacity: 0; transform: translate(-50%, 10px) scale(.94); transition: transform .3s var(--set-off), opacity .2s var(--set-off);
}
.age-note.up { opacity: 1; transform: translate(-50%, 0); }
.age-note.going { opacity: 0; transform: translate(-50%, 4px) scale(.97); transition-duration: .22s, .18s; }
.age-note.on { padding-left: 14px; }
.age-note-name[data-tag] b { font-weight: 750; color: var(--tc, var(--ink)); }
.age-note-cap { color: var(--ink-soft); font-weight: 600; }
.age-note > .age-fig { width: 18px; height: 18px; margin-left: 3px; }
.age-note-dot { color: var(--ink-faint); }
.age-note-n { color: var(--ink-soft); font-weight: 500; font-variant-numeric: tabular-nums; }
/* ——— The bar (cards.js's openAgeBar): grown sideways out of the age button over the thumb bar, the
   page lightly dimmed, the button lifted; one bar split into regions, each in its rating's colour
   (the tags'), named in plain words (No limit, the clear, over the button); the one under the
   finger filled full and ringed in white. With less motion, just faded. ——— */
.age-bar {
  position: fixed; inset: 0; z-index: calc(var(--z-screen) + 10); pointer-events: none; color: var(--ink); touch-action: none;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.age-bar:is(.tapping, .going, .picking) { pointer-events: auto; }
.age-shade { position: absolute; inset: 0; background: rgb(6 5 10 / 0.36); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); opacity: 0; transition: opacity .22s var(--set-off); }
.age-bar.up .age-shade { opacity: 1; }
.age-bar.going .age-shade { opacity: 0; transition-duration: .18s; }
.age-lift {
  position: absolute; border-radius: 22px; background: rgb(28 26 38 / 0.7); backdrop-filter: blur(28px) saturate(1.8); -webkit-backdrop-filter: blur(28px) saturate(1.8);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1), 0 10px 22px -12px rgba(0, 0, 0, 0.9); transition: transform .28s var(--set-off), box-shadow .28s var(--set-off), opacity .12s;
}
.age-lift > .thumb-age { width: 100%; }
.age-bar.up > .age-lift { transform: scale(1.06); box-shadow: 0 0 0 0.5px rgb(255 255 255 / 0.22), inset 0 1px 0 rgb(255 255 255 / 0.1), 0 22px 40px -16px rgb(0 0 0 / 0.9); }
.age-bar.going > .age-lift { transform: none; transition-duration: .18s; }
.age-card {
  position: absolute; box-sizing: border-box; padding: 16px 12px 12px; border-radius: 28px;
  background: radial-gradient(120% 70% at 50% -20%, rgb(169 150 255 / 0.14), transparent 60%), rgb(19 18 26 / 0.88);
  backdrop-filter: blur(30px) saturate(1.7); -webkit-backdrop-filter: blur(30px) saturate(1.7);
  box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.15), inset 0 1px 0 rgb(255 255 255 / 0.12), 0 30px 60px -24px rgb(0 0 0 / 0.95);
  opacity: 0; transform: translate(var(--from-x, 0), var(--from-y, 0)) scale(var(--from-s, .3), .6); will-change: transform, opacity;
  transition: transform .32s var(--set-off), opacity .16s var(--set-off);
}
.age-bar.up .age-card { opacity: 1; transform: none; }
.age-bar.going .age-card { opacity: 0; transform: translate(var(--from-x, 0), var(--from-y, 0)) scale(var(--from-s, .3), .6); transition: transform .24s var(--set-off), opacity .2s var(--set-off) .04s; }
/* its line: the one under the finger ("Up to" quiet, the rating in its colour), its films at the
   right, what its rating means under them */
.age-read {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "title n" "blurb blurb"; align-items: baseline;
  column-gap: 12px; row-gap: 3px; padding: 0 8px 14px; white-space: nowrap;
}
.age-read-title { grid-area: title; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 1.12rem; font-weight: 650; letter-spacing: -.02em; line-height: 1.2; }
.age-read-cap { font-weight: 500; color: var(--ink-soft); }
.age-read-title b { font-weight: 700; color: var(--tc, var(--ink)); }
:is(.age-read, .age-note-name)[data-tag="G"] { --tc: var(--g1); }
:is(.age-read, .age-note-name)[data-tag="PG"] { --tc: var(--g2); }
:is(.age-read, .age-note-name)[data-tag="PG13"] { --tc: var(--g3); }
:is(.age-read, .age-note-name)[data-tag="PG15"] { --tc: var(--g4); }
:is(.age-read, .age-note-name)[data-tag="15+"] { --tc: var(--g5); }
:is(.age-read, .age-note-name)[data-tag="18+"] { --tc: var(--g6); }
.age-read-n { grid-area: n; font-size: .8rem; font-weight: 600; color: var(--ink-soft); font-variant-numeric: tabular-nums; letter-spacing: -.005em; }
.age-read-blurb { grid-area: blurb; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: .8rem; line-height: 1.3; color: var(--ink-faint); }
/* the meter: the scale's segments (the rail), filled in the ratings' colours as one run from G up to
   the limit (the fill; both cut to the segments: cards.js's ageSegs); 18+ only apart past a
   hairline, outlined. The ratings' colours (the tags'), the note's too */
:is(.age-card, .age-note) { --g1: #8fd0bd; --g2: #a9cf91; --g3: #d4cb82; --g4: #e6b572; --g5: #ee9868; --g6: #ef7869; }
.age-card {
  --run: linear-gradient(90deg, var(--g1) 10%, var(--g2) 30%, var(--g3) 50%, var(--g4) 70%, var(--g5) 90%); }
.age-track { position: relative; display: flex; gap: 3px; height: 56px; --r: 16px; }
:is(.age-rail, .age-fill) {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  -webkit-mask: var(--segs) 0 0 / 100% 100% no-repeat; mask: var(--segs) 0 0 / 100% 100% no-repeat;
}
.age-rail { background: rgb(255 255 255 / 0.06); }
.age-fill {
  background: linear-gradient(180deg, rgb(255 255 255 / 0.24), transparent 55%) var(--g-l) 0 / calc(var(--s-r) - var(--g-l)) 100% no-repeat, var(--run) var(--g-l) 0 / calc(var(--s-r) - var(--g-l)) 100% no-repeat;
  clip-path: inset(0 calc(var(--w) - var(--f-r)) 0 var(--g-l)); transition: clip-path .34s var(--set-off);
}
.age-track.still > .age-fill { transition: none; }
.age-reg {
  position: relative; z-index: 1; flex: 1 1 0; display: grid; place-items: center; padding: 0; border-radius: 6px;
  --c: rgb(255 255 255 / 0.5); background: none; color: color-mix(in srgb, var(--c) 78%, white);
  opacity: 0; transition: color .14s linear, opacity .2s var(--set-off) .08s;
}
.age-bar.up .age-reg { opacity: 1; }
.age-bar.going .age-reg:not(.pressed) { opacity: 0; transition-delay: 0s; transition-duration: .1s; }
.age-reg[data-tag="G"] { --c: var(--g1); }
.age-reg[data-tag="PG"] { --c: var(--g2); }
.age-reg[data-tag="PG13"] { --c: var(--g3); }
.age-reg[data-tag="PG15"] { --c: var(--g4); }
.age-reg[data-tag="15+"] { --c: var(--g5); }
.age-reg[data-tag="18+"] { --c: var(--g6); }
.age-reg[data-tag="18+"] { flex: 0 0 56px; margin-left: 14px; border-radius: var(--r); box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--c) 55%, transparent); }
.age-reg[data-tag="18+"]::before { content: ""; position: absolute; left: -9px; top: 12px; bottom: 12px; width: 1px; background: rgb(255 255 255 / 0.14); }
.age-reg-name { font-size: .84rem; font-weight: 700; letter-spacing: -.01em; line-height: 1; white-space: nowrap; }
.age-reg[data-tag="18+"] .age-reg-name { display: grid; place-items: center; gap: 2px; }
.age-only { display: block; font-size: .56rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; opacity: .8; }
.age-reg.lit { color: #17141f; transition: color .16s linear .12s, opacity .2s var(--set-off) .08s; }
.age-reg.head.lit .age-reg-name { font-weight: 800; }
.age-reg[data-tag="18+"].over { background: linear-gradient(180deg, color-mix(in srgb, var(--c), white 14%), var(--c)); box-shadow: 0 0 18px -6px var(--c); color: #17141f; }
.age-reg.none:not(.over, .lit) > * { opacity: .38; } /* (none of its films on the page: greyed, still pickable, as the month's empty days) */
.age-reg:focus { outline: none; } /* (the fill says the one the focus is on: a screen reader's, or keys') */
@media (prefers-reduced-motion: reduce) {
  .age-lift, .age-card, .age-note { transition-property: opacity !important; }
  .age-card, .age-bar.going .age-card, .age-bar.up > .age-lift { transform: none !important; }
  .age-note, .age-note.up, .age-note.going { transform: translate(-50%, 0) !important; }
}
/* ——— The clear (cards.js's dressClear): the month's ×, the column's All, the age bar's No limit, one
   round × key floating just over its lifted button, the card raised to make room; there only with
   something to clear (.now: hidden). A glass key at rest, a violet wash pressed, lifted in the
   pickers' bright violet under the finger and as it's picked, its copy turning back into the
   button (flyClear: .clear-ghost) ——— */
:is(.month, .column, .age-bar) > .clear {
  position: absolute; z-index: 3; box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; margin: 0; padding: 0; border-radius: 50%;
  color: var(--ink-soft); background: linear-gradient(rgb(255 255 255 / 0.085), rgb(255 255 255 / 0.04)); box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.18), inset 0 1px 0 rgb(255 255 255 / 0.08);
  --clear-glow: inset 0 1px 0 rgb(255 255 255 / 0.35), 0 12px 24px -10px #000, 0 0 22px -4px rgb(140 115 255 / 0.7);
}
:is(.month, .column, .age-bar) > .clear.now { display: none; }
:is(.month, .column, .age-bar):has(> .clear:not(.now)) > :is(.month-card, .column-card, .age-card) { translate: 0 -46px; }
:is(.month, .column, .age-bar) > .clear.press { background: var(--pick-press); color: var(--ink); }
:is(.month, .column, .age-bar).up > .clear.over:not(.now), :is(.month, .column, .age-bar).picking > .clear.pressed { background: var(--pick-lift); color: #fff; box-shadow: var(--clear-glow); transform: scale(1.08); }
:is(.month, .column, .age-bar).picking > .clear.pressed { transform: scale(.95); opacity: 1; }
.clear-x { position: relative; flex: none; display: block; width: 14px; height: 14px; }
.clear-x::before, .clear-x::after { content: ""; position: absolute; left: 50%; top: 50%; width: 1.8px; height: 16px; border-radius: 1px; background: currentColor; transform: translate(-50%, -50%) rotate(45deg); }
.clear-x::after { transform: translate(-50%, -50%) rotate(-45deg); }
.clear-fly { position: fixed; left: 0; top: 0; z-index: calc(var(--z-screen) + 30); pointer-events: none; will-change: transform; }
.clear-ghost {
  position: absolute; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border-radius: 50%;
  background: var(--pick-lift); color: #fff; box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.35), 0 12px 24px -10px #000, 0 0 22px -4px rgb(140 115 255 / 0.7); will-change: transform, opacity;
}
@media (prefers-reduced-motion: reduce) { :is(.month, .column, .age-bar) > .clear { transform: none !important; } }
/* the search's magnifier in the top's bar: a finger's 44px, at its right, the bar's height */
html.thumb.page-scroll .page-top > .page-find {
  --bar-h: 44px; top: calc(env(safe-area-inset-top) + 2px); left: auto; right: max(6px, var(--sa-r)); width: 44px; border-radius: 22px;
}
html.thumb.page-scroll .page-top > .page-find:not(.on) .page-find-open:active { background: rgb(255 255 255 / 0.1); }
/* filters on: a pill saying them (its chips, its ×), past the room
   kept at the left for the site's logo (--logo-room), to the right edge */
html.thumb.page-scroll { --logo-room: 96px; }
/* the site's logo in that room: the D mark, "Dubai Film / Collective" beside it (logo.svg: the
   letters drawn as shapes, Inter Tight 500; .claude/tools/logo-dfc), as tall as the mark's 24px, in bone;
   just the mark while the filters' pill is there, gone on a film's page and in the search */
.site-logo { display: none; }
html.thumb.page-scroll .site-logo {
  display: block; position: absolute; left: max(20px, var(--sa-l)); top: calc(env(safe-area-inset-top) + 24px); translate: 0 -50%;
  height: 24px; aspect-ratio: 349.5 / 100; background: #e6dfd0;
  -webkit-mask: url("/static/logo.svg") left / contain no-repeat; mask: url("/static/logo.svg") left / contain no-repeat;
  clip-path: inset(0 -1px 0 0); transition: opacity .2s, clip-path .3s var(--set-off);
}
html.thumb.page-scroll:has(.page-find.on:not(.day-only)) .site-logo { clip-path: inset(0 calc(100% - 24px) 0 0); }
html.thumb.page-scroll:is(.film-page, :has(.find[open])) .site-logo { opacity: 0; }
html.thumb.page-scroll .page-top > .page-find.on:not(.day-only) {
  --bar-h: 36px; top: calc(env(safe-area-inset-top) + 6px); left: calc(var(--logo-room) + var(--sa-l)); right: max(12px, var(--sa-r)); width: auto; border-radius: 18px;
}
html.thumb.page-scroll .page-top > .page-find.on:not(.day-only) .page-find-open { gap: 8px; padding-left: 12px; font-size: 0.92rem; }
html.thumb.page-scroll .page-top > .page-find.on:not(.day-only) .page-find-open .icon-find { width: 15px; height: 15px; }
html.thumb.page-scroll .page-top > .page-find.on:not(.day-only) .find-token { height: 24px; }
html.thumb.page-scroll .page-top > .page-find.on:not(.day-only) .page-find-clear { width: 26px; height: 26px; margin-right: 6px; }
/* just what the thumb bar's buttons say (a day, a cinema, a time): the magnifier, as with none */
html.thumb.page-scroll .page-top > .page-find.day-only { border-color: transparent; background: none; box-shadow: none; }
html.thumb.page-scroll .page-top > .page-find.day-only::after { display: none; }
html.thumb.page-scroll .page-top > .page-find.day-only .page-find-open { justify-content: center; padding: 0; color: var(--ink); }
html.thumb.page-scroll .page-top > .page-find.day-only :is(.page-find-words, .find-key, .page-find-clear) { display: none; }
html.thumb.page-scroll .page-top > .page-find.day-only .icon-find { width: 19px; height: 19px; }
/* the search opened from it: where the page's held, and as far down as the visual viewport's been
   moved (cards.js's fitFind: Safari may move it as the field's focused), as tall as what's in sight
   over the keyboard (--find-room), so what it's found scrolls above it; with
   the keyboard down, clear of the home indicator */
html.thumb.page-scroll .find:not(.from-bar) { top: calc(var(--held-y, 0px) + var(--find-dy, 0px)); padding-bottom: env(safe-area-inset-bottom); }
html.thumb.page-scroll .find:not(.from-bar).keyed { padding-bottom: 0; }
.find:focus { outline: none; } /* (focused itself, back from a film: cards.js's openFind, the keyboard left down) */
/* back from a film found in it (cards.js's backToFind): there as it was, at once, under the film's
   page going down (or gone at once, by the phone's own back, which has shown its own way back):
   nothing on it coming in, no magnifier turning into Cancel (it's not come from the bar) */
html.thumb.page-scroll .find:not(.from-bar).returning[open]:not(.closing)::before,
html.thumb.page-scroll .find:not(.from-bar).returning[open]:not(.closing)::backdrop,
html.thumb.page-scroll .find:not(.from-bar).returning[open]:not(.closing) .find-cancel-word,
html.thumb.page-scroll .find:not(.from-bar).returning[open]:not(.closing) :is(.find-bar > .icon-find, .find-field, .find-glint, .find-sum, .find-results),
html.thumb.page-scroll .find:not(.from-bar).returning[open]:not(.closing) .find-bar::after { animation: none; }
html.thumb.page-scroll .find:not(.from-bar).returning[open]:not(.closing) .find-cancel::before { animation: none; opacity: 0; }
html.thumb .find.returning[open] .find-glint path { animation: none; }
/* the films it finds as posters, three across (more on a phone on its side, each about as wide as
   upright's), each its name under it and who matched (found by a person), as the grid's little cards */
html.thumb.page-scroll .find:not(.from-bar) .find-results:not(:empty) {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(112px, calc((100% - 24px) / 3)), 1fr)); align-content: start; gap: 18px 12px; padding: 14px 16px 18px;
}
html.thumb.page-scroll .find:not(.from-bar) .find-hit { display: flex; flex-direction: column; align-items: stretch; gap: 7px; padding: 0; border-radius: 0; background: none; }
html.thumb.page-scroll .find:not(.from-bar) .find-art { position: relative; width: 100%; border-radius: 7px; }
html.fly .find-art.fly-poster > .tile-age { visibility: hidden; } /* (its tag, a limit's (.tile-age), left behind: the film's page has its own) */
html.thumb.page-scroll .find:not(.from-bar) .find-hit[aria-selected="true"] .find-art { box-shadow: 0 0 0 2px var(--accent); }
html.thumb.page-scroll .find.returning .find-art { transition: box-shadow .25s var(--ease); } /* (the film come back from: its ring in once its poster's landed, not at once: cards.js's filmFly) */
html.thumb.page-scroll .find:not(.from-bar) .find-hit:active:not(.touch-moved *) .find-art { transform: scale(0.96); transition: transform .06s; }
html.thumb.page-scroll .find:not(.from-bar) .find-words { gap: 3px; }
html.thumb.page-scroll .find:not(.from-bar) .find-title { font-size: 0.82rem; line-height: 1.2; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
html.thumb.page-scroll .find:not(.from-bar) .find-note { font-size: 0.7rem; line-height: 1.25; }
/* a film that doesn't fit the filters, upright: at full strength, after those that do, under one
   line across the grid saying what keeps them out (cards.js's restSaid); one your preferences hide,
   its page says so under the seat hint, with Add (sayPeek) */
html.thumb .find-hit.hidden-film :is(.find-art, .find-title) { opacity: 1; }
html.thumb.page-scroll .find:not(.from-bar) .find-hidden-head { grid-column: 1 / -1; margin: 6px 0 -8px; font-size: 0.72rem; color: var(--ink-faint); list-style: none; }
html.thumb.page-scroll .find:not(.from-bar) .find-hidden-head:first-child { margin-top: 0; }
.st-peek .link { font-size: inherit; }
/* upright, the field's one line, what's typed as typed */
html.thumb .find:not(.from-bar) .find-field { position: relative; flex-wrap: nowrap; }
html.thumb .find:not(.from-bar) .find-input { position: relative; z-index: 1; min-width: 5em; }
@media (prefers-reduced-motion: reduce) {
  html.thumb .thumb-bar, html.thumb .thumb-bar.tucked { transition: none; }
}
/* a film opened or closed (filmSwitch): the bar pictured on its own, its glass frosting live, sliding
   under the film's page as the top's bar does */
html.thumb:is(.film-in, .film-out) .thumb-bar { view-transition-name: thumb-bar; }
::view-transition-group(thumb-bar) { z-index: 1; --vt-r: calc(100vw - max(12px, var(--sa-r))); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); border-radius: 29px; }
::view-transition-old(thumb-bar), ::view-transition-new(thumb-bar) { animation: none; mix-blend-mode: normal; }
html.film-in::view-transition-group(thumb-bar) { animation: film-under .42s var(--push-in) both, bar-covered .42s var(--push-in) both; }
html.film-out::view-transition-group(thumb-bar) { animation: film-under .38s var(--push-out) reverse both, bar-covered .38s var(--push-out) reverse both; }

/* ——— A film on a 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: max(12px, var(--sa-l)); 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(max(16px, var(--sa-l)) + max(68px, var(--fold-l, 0px))); right: calc(max(16px, var(--sa-r)) + max(44px, var(--fold-r, 0px))); }
/* its name fading as it's scrolled up to the bar (from where it rests, 16px under it, to half under
   it), then the bar's name rising in in its place (cards.js's .named); its trailer's mark there once
   the whole head's gone (.folded) */
html.page-scroll.film-page .times-cover .times-view:not(.list-mode, .seat-mode) .dressed .st-title { animation: title-under linear both; animation-timeline: scroll(root); animation-range: 0px 32px; }
@keyframes title-under { to { opacity: 0; } }
html.page-scroll.film-page .times-cover .times-view.named:not(.seat-mode, .info-mode, .list-mode) .times-fold { opacity: 1; visibility: visible; transition: opacity 0s, visibility 0s; }
html.page-scroll.film-page .times-cover .times-view:not(.named) .times-fold { transition: opacity .2s var(--ease), visibility 0s .2s; }
html.page-scroll.film-page .times-cover .times-fold-up { opacity: 0; translate: 0 12px; transition: opacity .15s var(--ease), translate .15s var(--ease); }
html.page-scroll.film-page .times-cover .times-view.named .times-fold-up { opacity: 1; translate: none; transition: opacity .3s var(--ease), translate .42s var(--push-in); }
html.page-scroll.film-page .times-cover .times-view:not(.folded) .times-fold .st-play { opacity: 0; visibility: hidden; }
html.page-scroll.film-page .times-cover .times-fold .st-play { transition: opacity .3s var(--ease) .1s, visibility 0s; }
@media (prefers-reduced-motion: reduce) { html.page-scroll.film-page .times-cover .times-fold-up { translate: none; } }
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: max(12px, var(--sa-r)); }
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 max(16px, var(--sa-r)) calc(10px + env(safe-area-inset-bottom)) max(16px, var(--sa-l)); 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-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);
   upright, led by its poster, the bar stays at the top, the player under it (.trailer-up, below) */
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:not(.trailer-up) .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:not(.trailer-up) .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: max(6px, var(--sa-l)); } /* (clear of a phone on its side's notch, as everything at the sides) */
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: max(6px, var(--sa-r)); 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 a 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; }

/* a 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; }

/* ——— A phone's film page, upright, led by its poster (cards.js's headOf, .poster-head): the whole
   poster (its own shape, 2:3: every poster's 600x900) a card in the middle under the bar, its light
   behind it (--glow: its most vivid colour, over --deep: its average, deepened), its name, line,
   story and Show Trailer centred under it, then the days. Under a trailer docked at the top, all of
   it under the dock (--p0). On its side too, the card no taller than leaves its name in sight under
   it (the owner's, 5 Nov 2026: a phone's one layout either way up). A seat map, or a film with no
   poster: as it was (the crop) ——— */
.times-poster, .head-grip { display: none; }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  html.page-scroll.film-page .times-cover .times-view.poster-head {
    --deep: color-mix(in oklab, var(--tone, rgb(40 36 52)) 26%, #060609);
    --glow: color-mix(in oklab, var(--vivid, rgb(150 132 210)) 70%, #fff 8%);
    --p0: calc(var(--roof) - 48px - env(safe-area-inset-top)); /* (a trailer's dock's height, playing) */
    --head-t: calc(env(safe-area-inset-top) + 48px + 14px); /* (the card's top: under the bar) */
    --poster-w: min(60vw, calc((100svh - 120px) * 2 / 3)); --poster-h: calc(var(--poster-w) * 3 / 2); /* (upright, 60vw; on its side, short, by its height) */
  }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .times-crop { display: none; }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .times-poster {
    display: block; position: absolute; z-index: -1; pointer-events: none; overflow: hidden;
    top: var(--p0); left: -16px; width: 100vw; height: calc(var(--poster-h) + 55vh); /* (past the times' margins: out to the screen's edges) */
    background:
      radial-gradient(70% 34% at calc(50% + var(--gx, 0px)) calc(30% + var(--gy, 0px)), color-mix(in oklab, var(--glow) 34%, transparent), transparent 72%),
      linear-gradient(color-mix(in oklab, var(--deep) 92%, transparent) 30%, transparent); /* (its colour on down the page, gone into the room) */
  }
  /* the card: leaning toward a finger on it, or swaying (cards.js's cardLean; flat till then), a soft
     light across it from where it's turned toward; the tile's sheen across it as its page arrives
     (headShine) */
  .head-card {
    position: absolute; top: var(--head-t); left: calc((100vw - var(--poster-w)) / 2); width: var(--poster-w); height: var(--poster-h);
    border-radius: 12px; overflow: hidden; background: #15131b;
    box-shadow: 0 0 0 1px rgba(255, 240, 220, 0.14), 0 18px 40px -14px rgba(0, 0, 0, 0.85);
    transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); will-change: transform;
  }
  .head-face { position: absolute; inset: 0; clip-path: inset(0 round 12px); } /* (the corners too: turned and blended, its sheen got past overflow's rounding) */
  .head-face > img { display: block; width: 100%; height: 100%; object-fit: cover; }
  .head-light {
    position: absolute; inset: 0; pointer-events: none; mix-blend-mode: soft-light; opacity: var(--so, 0);
    background: radial-gradient(75% 55% at var(--sx, 50%) var(--sy, 30%), rgba(255, 255, 255, 0.9), transparent 70%);
  }
  /* (a finger on it: over the card, the page's words over it where it is, so it's not the page's
     scroll; cards.js's headGrip) */
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .head-grip {
    display: block; position: absolute; z-index: 2; touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
    top: calc(var(--p0) + var(--head-t)); left: calc((100vw - var(--poster-w)) / 2 - 16px); width: var(--poster-w); height: var(--poster-h);
  }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-lead-in { padding-top: calc(10px + var(--poster-h) + 18px); justify-items: center; text-align: center; }
  .times-view.poster-head .dressed :is(.st-name, .st-last, .st-story) { justify-content: center; }
  .times-view.poster-head .dressed .st-name > .st-title { flex: none; max-width: 100%; text-wrap: balance; }
  /* (under its name, in place of the facts line: its scores, just their marks, a touch bigger, then
     its genres said, "Action · Adventure", each a centred line; cards.js's marksOf) */
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-facts { display: none; }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-marks { display: grid; justify-items: center; gap: 6px; width: 100%; margin: 6px 0 2px; }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-marks-scores { width: auto; margin: 0; justify-content: center; gap: 6px 20px; }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-marks-scores .info-score { gap: 6px; font-size: 0.95rem; text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55); }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-marks-scores .info-score img { width: 16px; height: 16px; }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-marks-genres { max-width: 100%; margin: 0; font-size: 0.84rem; line-height: 1.45; color: var(--ink-soft); text-align: center; text-wrap: balance; text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55); }
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-marks + :is(.st-last, .st-story) { margin-top: 8px; }
  .times-view.poster-head .dressed .st-title { text-shadow: 0 1px 14px rgba(0, 0, 0, 0.5); }
  /* (its name fading as it nears the bar from where it rests, under the card: --title-at, cards.js's fitHead) */
  html.page-scroll.film-page .times-cover .times-view.poster-head:not(.list-mode, .seat-mode) .dressed .st-title {
    animation-range: calc(var(--title-at, 64px) - var(--roof) - 16px) calc(var(--title-at, 64px) - var(--roof) + 16px);
  }
  /* (a trailer up, its name resting just under the player: fading from as it reaches it, not as soon as it's scrolled) */
  html.page-scroll.film-page.trailer-up .times-cover .times-view.poster-head:not(.list-mode, .seat-mode) .dressed .st-title {
    animation-range: calc(var(--title-at, 64px) - var(--roof)) calc(var(--title-at, 64px) - var(--roof) + 32px);
  }
  /* a white poster's glow, dimmed: the room under it no grey wash */
  html.head-pale.film-page .ambient img.on { opacity: 0.2; }
}
@media (prefers-reduced-motion: reduce) { .head-grip { display: none !important; } } /* (no lean: nothing to hold the page still for) */

/* ——— A trailer on a phone's film page, upright, led by its poster (cards.js's turnBegin): the
   card turned into the player, pinned just under the bar, which stays where it always is; the page's
   --roof the player's foot (as docked: its days stuck under the player, its name folding into the
   bar as it goes under it), the poster's room closed up so its name and times come up under it;
   nothing dimmed. × Trailer in the bar's corner, only while the page's own Close Trailer is out of
   sight (.trailer-x: fading as the bar's name does). A seat map's sheet as tall as ever, over the
   player if it comes to it (playing on under it).
   The picture that turns (.trailer-fly): the card hidden meanwhile, and while it plays; the player
   hidden till it's landed ——— */
.trailer-fly { display: none; }
@media (max-width: 777px), (orientation: landscape) and (max-height: 499px) {
  .trailer-fly {
    display: block; position: fixed; z-index: calc(var(--z-screen) + 2); overflow: hidden; pointer-events: none; background: #000;
    box-shadow: 0 0 0 1px rgba(255, 240, 220, 0.14), 0 18px 40px -14px rgba(0, 0, 0, 0.85);
  }
  .trailer-fly img { display: block; width: 100%; height: 100%; object-fit: cover; }
  html.trailer-up .head-card { visibility: hidden; }
  html.trailer-turning .screen { opacity: 0 !important; transition: none !important; }
  html.page-scroll.film-page.trailer-up .times-cover .screen { top: calc(env(safe-area-inset-top) + 48px); height: var(--dock-v); padding: 0; }
  html.page-scroll.film-page.trailer-up .times-cover .dressed .st-lead-in { transition: none; } /* (its room closed up at once, the page moved back from there: cards.js's turnFlip) */
  html.page-scroll.film-page.trailer-up .times-cover.playing .times-view.poster-head:not(.seat-mode, .list-mode) .dressed .st-lead-in { padding-top: 10px; }
  html.page-scroll.film-page.trailer-up .times-cover .times-close.screen-close { display: inline-flex; position: absolute; top: calc(7px - 48px); bottom: auto; right: calc(max(12px, var(--sa-r)) + 46px); }
  html.page-scroll.film-page.trailer-up.no-shortlist .times-cover .times-close.screen-close { right: max(12px, var(--sa-r)); } /* (no bookmark: in its corner) */
  html.page-scroll.film-page.trailer-up .times-cover.playing .times-fold { right: calc(max(16px, var(--sa-r)) + max(134px, var(--fold-r-play, 0px))); } /* (the folded bar 4px clear of it, as anywhere it plays: cards.js's fitFoldPlay) */
  html.page-scroll.film-page.trailer-up:not(.trailer-x) .times-cover .times-close.screen-close { opacity: 0; visibility: hidden; transition: opacity .2s var(--ease), visibility 0s .2s; }
  html.page-scroll.film-page.trailer-up.trailer-x .times-cover .times-close.screen-close { opacity: 1; visibility: visible; transition: opacity .3s var(--ease), visibility 0s; }
  /* (a trailer playing: no card to lean, so nothing over the page there) */
  html.page-scroll.film-page .times-cover.playing .head-grip { display: none !important; }
}

/* a 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 a 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 */
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 a phone: the words alone) */
/* (the light in one place, under the field: the line saying what to type under it, where the
   films come, so the first letter typed only swaps the one for the other) */
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 a 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: calc(56px + var(--sa-l)); width: calc(100% - 77px - var(--sa-l) - var(--sa-r)); } /* (measured: the glyph 21–35pt, so 21pt either side of it) */
/* a phone: a heading's ⓘ card a sheet (cards.js's openTierSheet), as Preferences: 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; }
/* a 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; }

/* ——— a 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 a 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.film-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); }
html.film-in::view-transition-old(root) { animation: film-under .42s var(--push-in) both; z-index: 1; }
html.film-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.film-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-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); }
/* (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; }
/* (the grid's bar and its Preferences, sliding under: pictured over both pages, as a group is over the root:
   cut off where the film's page has come over them, in step with it (bar-covered), or they showed
   through the film's bar as it came, its glass blurring them. --vt-r: each one's right edge, at rest) */
::view-transition-group(page-top) { --vt-r: 100vw; }
::view-transition-group(grid-prefs) { --vt-r: calc(max(6px, var(--sa-l)) + 44px); }
html.film-in::view-transition-group(page-top), html.film-in::view-transition-group(grid-prefs) { animation: film-under .42s var(--push-in) both, bar-covered .42s var(--push-in) both; }
html.film-out::view-transition-group(page-top), html.film-out::view-transition-group(grid-prefs) { animation: film-under .38s var(--push-out) reverse both, bar-covered .38s var(--push-out) reverse both; }
@keyframes bar-covered { from { clip-path: inset(-20px calc(var(--vt-r) - 100vw) -20px -20px); } to { clip-path: inset(-20px calc(var(--vt-r) - 25vw) -20px -20px); } }
/* (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; } }
@keyframes film-under { to { translate: -25vw 0; filter: brightness(0.7); } }
/* a film grown out of its poster in the grid, and back into it (cards.js's posterMorph), in place
   of the slide: the film's page scaled down onto the poster and cut to its shape (from its top, as
   tall as the poster to the page's width: --morph-ph), growing to the whole screen; the poster
   pictured on its own over it, growing with it in step and fading into it; the grid dimming under
   it, where it is. The bars crossfade where they are: the grid's out, the film's in (and back) */
.morph-probe { position: fixed; top: 0; left: 0; width: 1px; height: 1px; pointer-events: none; }
html.film-morph .morph-probe { view-transition-name: morph-probe; } /* (where the page's top is in the pictures: cards.js's morphOffset) */
html.film-morph .tile-card.morphing { view-transition-name: film-poster; box-shadow: none; } /* (just the poster: not its ring, grown with it) */
html.film-morph .tile-lift:has(> .morphing)::before { opacity: 0; transition: none; }
::view-transition-group(film-poster) { z-index: 2; } /* (over the pages, the film's at 2 too; under the film's bar) */
::view-transition-old(film-poster), ::view-transition-new(film-poster) { height: 100%; mix-blend-mode: normal; }
html.film-morph.film-in::view-transition-new(root) { transform-origin: 0 0; box-shadow: none; animation: morph-page .42s var(--push-in) both; }
html.film-morph.film-in::view-transition-old(root) { animation: morph-under .42s var(--push-in) both; }
html.film-morph.film-in::view-transition-group(film-poster) { animation: morph-poster .42s var(--push-in) both; }
html.film-morph.film-in::view-transition-old(film-poster) { animation: morph-poster-fade .42s linear both; }
html.film-morph.film-out::view-transition-old(root) { transform-origin: 0 0; box-shadow: none; animation: morph-page .38s var(--push-out) reverse both; }
html.film-morph.film-out::view-transition-new(root) { animation: morph-under .38s var(--push-out) reverse both; }
html.film-morph.film-out::view-transition-group(film-poster) { animation: morph-poster .38s var(--push-out) reverse both; }
html.film-morph.film-out::view-transition-new(film-poster) { animation: morph-poster-in .38s linear both; }
html.film-morph.film-in::view-transition-group(film-bar), html.film-morph.film-in::view-transition-group(film-back), html.film-morph.film-in::view-transition-group(film-fold), html.film-morph.film-in::view-transition-group(film-save), html.film-morph.film-in::view-transition-group(film-close), html.film-morph.film-in::view-transition-group(film-days),
html.film-morph.film-out::view-transition-group(page-top), html.film-morph.film-out::view-transition-group(grid-prefs) { box-shadow: none; animation: fade .26s var(--ease) .14s both; }
html.film-morph.film-out::view-transition-group(film-bar), html.film-morph.film-out::view-transition-group(film-back), html.film-morph.film-out::view-transition-group(film-fold), html.film-morph.film-out::view-transition-group(film-save), html.film-morph.film-out::view-transition-group(film-close), html.film-morph.film-out::view-transition-group(film-days),
html.film-morph.film-in::view-transition-group(page-top), html.film-morph.film-in::view-transition-group(grid-prefs) { box-shadow: none; animation: fade-out .22s var(--ease) both; }
/* (onto the page's top, across it; or, a page led by its poster, onto that, where it is: --morph-tx,
   -ty and -tw, cut at first to the part of it the grid's poster shows, --morph-tt down it and
   --morph-ph tall, opening out to the whole of it: cards.js's morphOnto) */
@keyframes morph-page {
  from {
    transform: translate(calc(var(--morph-x) - var(--morph-tx, 0px) * var(--morph-s)), calc(var(--morph-y) + var(--morph-dy, 0px) * (1 - var(--morph-s)) - (var(--morph-ty, 0px) + var(--morph-tt, 0px)) * var(--morph-s))) scale(var(--morph-s));
    clip-path: inset(calc(var(--morph-dy, 0px) + var(--morph-ty, 0px) + var(--morph-tt, 0px)) calc(100% - var(--morph-tx, 0px) - var(--morph-tw, 100%)) calc(100% - var(--morph-dy, 0px) - var(--morph-ty, 0px) - var(--morph-tt, 0px) - var(--morph-ph)) var(--morph-tx, 0px) round var(--morph-r));
  }
  to { transform: translate(0, 0) scale(1); clip-path: inset(0 0 0 0 round 0); }
}
@keyframes morph-under { to { scale: 0.96; filter: brightness(0.6); } } /* (eased back a touch, too: Safari drew the grid's picture, unmoved, with its rows scrolled twice over) */
html.film-morph::view-transition { background: #000; } /* (round the grid eased back: not the page itself, live, as Safari shows it) */
@keyframes morph-poster {
  from { transform: translate(var(--morph-x), calc(var(--morph-y) + var(--morph-dy, 0px))); width: var(--morph-w); height: var(--morph-h); }
  to { transform: translate(var(--morph-tx, 0px), calc(var(--morph-ty, 0px) + var(--morph-tt, 0px) + var(--morph-dy, 0px) * var(--morph-land, 0))); width: var(--morph-tw, 100vw); height: var(--morph-ph); }
}
@keyframes morph-poster-fade { 0%, 6% { opacity: 1; } 50%, 100% { opacity: 0; } } /* (seen, then gone into the page well before it's all there: a picture of a little poster, soft grown big) */
@keyframes morph-poster-in { 0%, 25% { opacity: 0; } 72%, 100% { opacity: 1; } } /* (back: there as it nears its place, the page in it gone) */

/* ——— A film opened and closed on an upright phone with its poster flying (cards.js's filmFly):
   the tile's picture, then the card's face, one picture (film-poster) moved and grown by the browser
   from one's place to the other's, cut to the tile's 63:88 at first (as .tile-art: 20% down) and
   opening out to the whole poster, its corners and shadow eased by cards.js; the page slides up from
   the foot as a sheet over the grid, dimmed behind it. With reduced motion, a crossfade. Big moves
   from rest (--set-off) ——— */
html.fly .tile-card.fly-poster { view-transition-name: film-poster; box-shadow: none; }
html.fly .find-art.fly-poster { view-transition-name: film-poster; box-shadow: none; } /* (a film found: its poster flies from its row: cards.js's pick) */
/* (to and from an upright phone's search: the grid's bars under the search, and the film's bar and
   what's on it on the film's page, not pictured on their own: no bar of the grid's to be one with,
   the film's came over the search's field at once, its glass blurring it, and went with nothing
   under it. They come and go with the sheet; the search, its field and its light, stays where it
   is, only dimmed, not eased back: cards.js's filmFly, backToFind) */
html:is(.back-to-find, .fly-find) :is(.page-top, .thumb-bar, .film-bar, .times-view > :is(.times-back, .times-fold, .times-save, .times-close), .times-body.dressed .st-days) { view-transition-name: none !important; }
html.fly-sheet.fly-find.film-in::view-transition-old(root) { animation-name: fly-dim-still; }
html.fly-sheet.back-to-find.film-out::view-transition-new(root) { animation-name: fly-dim-still; }
@keyframes fly-dim-still { to { filter: brightness(0.45); } }
html.fly .head-face > img.fly-poster { view-transition-name: film-poster; }
html.fly .tile-lift:has(> .fly-poster)::before { opacity: 0; transition: none; }
html.fly .tile-lift:has(> .fly-poster) > .tile-chip { view-transition-name: fly-chip; } /* (its word, Until Fri, over its poster: going as it leaves, back as it lands) */
::view-transition-group(fly-chip) { z-index: 1; }
::view-transition-old(fly-chip), ::view-transition-new(fly-chip) { mix-blend-mode: normal; }
/* (faded as a whole, its group: the browser gives the group the chip's glass, its blur, which a
   picture fading alone left behind, a frosted patch over the page all the way) */
html.fly.film-in::view-transition-group(fly-chip) { animation: fade-out calc(var(--fly-ms) * .2) linear both; }
html.fly.film-out::view-transition-group(fly-chip) { animation: fade calc(var(--fly-ms) * .25) linear calc(var(--fly-ms) * .75) both; }
::view-transition-old(fly-chip), ::view-transition-new(fly-chip) { animation: none; }
html.flying .head-card { box-shadow: none; background: none; transform: none; will-change: auto; } /* (the flying picture's shadow, in its place: not one already waiting where it lands) */
html.fly::view-transition { background: rgb(7 7 10); }
html.fly::view-transition-group(film-poster) { z-index: 1; overflow: clip; animation-timing-function: cubic-bezier(.4, 0, .2, 1); animation-duration: var(--fly-ms); }
html.fly::view-transition-old(film-poster), html.fly::view-transition-new(film-poster) {
  height: 100%; object-fit: cover; object-position: 50% 20%; mix-blend-mode: normal; animation: none;
}
/* (the tile's picture over the card's at first, its seals and light going as it leaves; back, the
   tile's coming over it as it nears home) */
html.fly.film-in::view-transition-old(film-poster) { z-index: 1; animation: fade-out calc(var(--fly-ms) * .35) linear both; }
html.fly.film-out::view-transition-new(film-poster) { z-index: 1; animation: fade calc(var(--fly-ms) * .3) linear calc(var(--fly-ms) * .65) both; }
html.fly-sheet.film-in { --fly-ms: .56s; }
html.fly-sheet.film-out { --fly-ms: .46s; }
html.fly-rm { --fly-ms: .22s; }
/* the bars, the flying poster under them all: the top's one bar throughout, the grid's and the
   film's pictured as one (top-bar), its glass frosting live, only what's on it coming and going; the
   grid's thumb bar where it is, under the sheet: covered as it comes up, uncovered as it goes down
   (cards.js's filmFly: its box moved up as its picture's moved down, its picture cut off by its box's
   foot; its glass on its picture, then, frosting what's under it where it is) */
html.fly .page-top, html.fly .film-bar { view-transition-name: top-bar; }
::view-transition-group(top-bar) { z-index: 3; -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); }
::view-transition-old(top-bar) { display: none; }
::view-transition-new(top-bar) { animation: none; mix-blend-mode: normal; }
html.fly::view-transition-group(film-back), html.fly::view-transition-group(film-fold), html.fly::view-transition-group(film-save), html.fly::view-transition-group(film-close), html.fly::view-transition-group(film-days), html.fly::view-transition-group(grid-prefs) { z-index: 4; }
html.fly::view-transition-group(thumb-bar) { z-index: 2; }
html.fly.film-in::view-transition-group(film-back), html.fly.film-in::view-transition-group(film-fold), html.fly.film-in::view-transition-group(film-save), html.fly.film-in::view-transition-group(film-close), html.fly.film-in::view-transition-group(film-days),
html.fly.film-out::view-transition-group(grid-prefs) { box-shadow: none; clip-path: none; animation: fade .26s var(--ease) .14s both; }
html.fly.film-out::view-transition-group(film-back), html.fly.film-out::view-transition-group(film-fold), html.fly.film-out::view-transition-group(film-save), html.fly.film-out::view-transition-group(film-close), html.fly.film-out::view-transition-group(film-days),
html.fly.film-in::view-transition-group(grid-prefs) { box-shadow: none; clip-path: none; animation: fade-out .22s var(--ease) both; }
html.fly-rm::view-transition-group(thumb-bar) { animation: fade-out .22s linear both; }
html.fly-rm.film-out::view-transition-group(thumb-bar) { animation: fade .22s linear both; }
html.fly::view-transition-old(root), html.fly::view-transition-new(root) { box-shadow: none; }
/* the sheet */
html.fly-sheet.film-in::view-transition-old(root) { animation: fly-dim .56s var(--set-off) both; }
html.fly-sheet.film-in::view-transition-new(root) { animation: fly-sheet .56s var(--set-off) both; }
html.fly-sheet.film-out::view-transition-old(root) { z-index: 2; animation: fly-sheet .46s var(--set-off) reverse both; }
html.fly-sheet.film-out::view-transition-new(root) { z-index: 1; animation: fly-dim .46s var(--set-off) reverse both; }
/* (what's on the bars: the film's as the sheet's nearly up, the grid's as it's nearly down) */
html.fly-sheet.film-in::view-transition-group(film-back), html.fly-sheet.film-in::view-transition-group(film-fold), html.fly-sheet.film-in::view-transition-group(film-save), html.fly-sheet.film-in::view-transition-group(film-close),
html.fly-sheet.film-out::view-transition-group(grid-prefs) { animation: fade .2s var(--ease) .3s both; }
html.fly-sheet::view-transition-group(thumb-bar) { overflow: clip; overflow-clip-margin: 20px; border-radius: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; animation: none; }
html.fly-sheet::view-transition-image-pair(thumb-bar) { border-radius: 29px; -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); }
@keyframes fly-sheet { from { translate: 0 100vh; clip-path: inset(0 round 22px 22px 0 0); box-shadow: 0 -12px 40px rgb(0 0 0 / 0.5); } to { clip-path: inset(0 round 0); } }
@keyframes fly-dim { to { scale: 0.95; filter: brightness(0.45); } }
/* reduced motion: a crossfade */
html.fly-rm.film-in::view-transition-old(root), html.fly-rm.film-out::view-transition-old(root) { animation: fade-out .22s linear both; }
html.fly-rm.film-in::view-transition-new(root), html.fly-rm.film-out::view-transition-new(root) { animation: fade .22s linear both; }
html.fly-rm::view-transition-group(*) { animation-duration: .22s !important; animation-delay: 0s !important; }

/* cards.js's slowTab (?slow=): a tab on the right edge, halfway down */
.slow-tab {
  position: fixed; z-index: 10000; right: 0; top: 50%; translate: 0 -50%; display: flex; flex-direction: column; gap: 2px; padding: 4px;
  border-radius: 12px 0 0 12px; background: rgb(20 18 28 / 0.82); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  box-shadow: 0 0 0 1px rgb(255 255 255 / 0.12), 0 8px 24px -10px #000; font: 600 12px/1 system-ui, sans-serif;
}
.slow-tab button { border: 0; border-radius: 8px; padding: 9px 8px; background: none; color: rgb(255 255 255 / 0.7); font: inherit; }
.slow-tab .on { background: var(--accent); color: #fff; }

/* ——— Bands: a 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; on its side, no taller than a band, its heading and its
   row, fits under the bar, so more of them are across. 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 a 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: min(calc((100vw - 20px) / 3.4 - var(--band-gap)), calc((100svh - 120px) * 63 / 88)); /* (from the grid's 20px in: ~3.4 posters across; on its side, 120px for the bar, the heading and the row's room above and below) */
  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%; }
/* 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; }
/* Top's #1 (cards.js's topOne: .top-one): its numeral in gold foil, outlined in the cards' gold over
   a warm dark, a faint glow round it, and every 5.5s a bright light crossing it (a copy of its figure,
   data-n, laid exactly over it, clipped to it: a bright band slid across). Wider, where Top's places
   aren't numbered, a small coin at its poster's corner instead (below: Bands wider than a phone). The
   2, 3 … as they are. Room round Top's row for the glow, its row's place kept (the margins take the
   padding back). Off-screen, still where it was; with less motion, still, the light partway over.
   (The owner's A, "Foil 1", of eight mocked, 2 Nov 2026) */
.band-top .band-row { padding-top: 26px; margin-top: -14px; padding-bottom: 30px; margin-bottom: -26px; }
.band-top .top-one .tile-rank { -webkit-text-stroke-color: var(--gold); color: rgb(40 28 8 / 0.55); filter: drop-shadow(0 0 6px rgb(233 207 142 / 0.35)); }
.band-top .top-one .tile-rank::after {
  content: attr(data-n); position: absolute; inset: 0; display: flex; align-items: flex-end;
  color: transparent; -webkit-text-stroke-color: transparent;
  background: linear-gradient(100deg, transparent 38%, rgb(255 249 230 / 0.15) 44%, #fffdf3 50%, rgb(255 249 230 / 0.15) 56%, transparent 62%) 0 0 / 300% 100% no-repeat;
  -webkit-background-clip: text; background-clip: text;
  animation: top-sweep 5.5s ease-in-out infinite;
}
@keyframes top-sweep { 0%, 45% { background-position: 100% 0; } 85%, 100% { background-position: 0% 0; } }
.top-one.deco-away .tile-rank::after { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .band-top .top-one .tile-rank::after { animation: none; background-position: 60% 0; } }
/* a Special Event poster (cards.js's eventTicket: .event-tile), cut as a ticket: scalloped top and
   bottom, a notch each side at the stub, its cut edge in gold, a printed gold rule just inside it
   and a dotted tear line across the stub. A light crosses it once, the first time it's well in view
   (.deco-shone), not again and again: it drew the eye from the rest of the page. No Rotten Tomatoes
   seals on it. Room above and below its row for its shadow. With less motion, no light. (The owner's
   M, "Ticket, once": E, "Ticket", of the mocked looks, its light once and its seals off, 3 Nov 2026) */
.band-special .band-row { padding-top: 24px; margin-top: -12px; padding-bottom: 22px; margin-bottom: -18px; }
.event-tile .tile-lift { container-type: inline-size; filter: drop-shadow(0 0 0.5px rgb(233 207 142 / 0.95)) drop-shadow(0 0 3px rgb(233 207 142 / 0.25)); } /* (its cut edge in gold: a drop-shadow follows the card's mask, as a box-shadow can't) */
.event-tile .tile-lift::before { box-shadow: 0 28px 42px -20px rgb(0 0 0 / 0.95); }
.event-tile .tile-card {
  --nh: 80%; --n: max(5px, 2.6cqw); --sc: max(2.6px, 1.2cqw); --sp: max(9px, 4cqw); /* (the stub's height; its notches; the scallops and their pitch) */
  --ticket:
    radial-gradient(circle var(--n) at 0 var(--nh), #0000 97%, #000),
    radial-gradient(circle var(--n) at 100% var(--nh), #0000 97%, #000),
    radial-gradient(circle var(--sc) at 50% 0, #0000 96%, #000) 0 0 / var(--sp) 100% repeat-x,
    radial-gradient(circle var(--sc) at 50% 100%, #0000 96%, #000) 0 0 / var(--sp) 100% repeat-x;
  -webkit-mask: var(--ticket); -webkit-mask-composite: source-in;
  mask: var(--ticket); mask-composite: intersect;
  border-radius: 2px;
}
.event-tile .tile-seals { display: none; }
.event-ticket { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.event-ticket::before { /* (the printed rule) */
  content: ""; position: absolute; inset: max(5px, 2.4cqw); border-radius: 2px;
  border: 1px solid rgb(233 207 142 / 0.55); box-shadow: 0 0 0 1px rgb(0 0 0 / 0.25);
}
.event-tear {
  position: absolute; left: calc(var(--n) + 3px); right: calc(var(--n) + 3px); top: var(--nh); height: 2px; margin-top: -1px;
  background: radial-gradient(circle, rgb(233 207 142 / 0.75) 0 0.9px, transparent 1.3px) 0 50% / 5px 2px repeat-x;
}
.event-shim {
  position: absolute; top: -20%; bottom: -20%; left: 0; width: 38%;
  background: linear-gradient(90deg, transparent, rgb(255 246 214 / 0.32) 45%, rgb(255 255 255 / 0.5) 50%, rgb(255 246 214 / 0.32) 55%, transparent);
  mix-blend-mode: screen; transform: translateX(-120%) skewX(-18deg);
}
.event-tile.deco-shone .event-shim { animation: event-shine 1.6s 0.25s cubic-bezier(0.45, 0, 0.25, 1) both; }
@keyframes event-shine { from { transform: translateX(-120%) skewX(-18deg); } to { transform: translateX(330%) skewX(-18deg); } }
@media (prefers-reduced-motion: reduce) { .event-shim { display: none; } }
/* Rated Highly's heading (cards.js's bandHead: .laurelled): its words between two small gold laurel
   branches, as an award's title, the words a warm white; now and then a glint at a branch's tip, the
   left's then the right's, 2s apart. In the heading, so the desktop's drawn copies have them too.
   With less motion, still: the left's glint shown, the right's not. (The owner's A, "Laurel heading",
   of seven mocked, 2 Nov 2026) */
.band-laurel {
  display: block; flex: none; position: relative; width: 0.95em; height: 1.5em; margin: -0.3em 0; pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 62'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='1' x2='0' y2='0'%3E%3Cstop offset='0' stop-color='%239c7632'/%3E%3Cstop offset='.5' stop-color='%23e9cf8e'/%3E%3Cstop offset='1' stop-color='%23fff4cf'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='url%28%23g%29'%3E%3Cpath d='M32 58Q6 40 14 4' fill='none' stroke='%23e9cf8e' stroke-width='1.3' stroke-linecap='round'/%3E%3Cellipse cx='26.2' cy='49.5' rx='5.0' ry='2.0' transform='rotate%28-101 26.2 49.5%29'/%3E%3Cellipse cx='22.3' cy='53.9' rx='5.0' ry='2.0' transform='rotate%28-177 22.3 53.9%29'/%3E%3Cellipse cx='21.7' cy='44.2' rx='4.8' ry='1.9' transform='rotate%28-91 21.7 44.2%29'/%3E%3Cellipse cx='17.4' cy='47.8' rx='4.8' ry='1.9' transform='rotate%28-167 17.4 47.8%29'/%3E%3Cellipse cx='18.3' cy='38.4' rx='4.5' ry='1.8' transform='rotate%28-81 18.3 38.4%29'/%3E%3Cellipse cx='13.7' cy='41.0' rx='4.5' ry='1.8' transform='rotate%28-157 13.7 41.0%29'/%3E%3Cellipse cx='16.0' cy='32.1' rx='4.3' ry='1.7' transform='rotate%28-71 16.0 32.1%29'/%3E%3Cellipse cx='11.2' cy='33.8' rx='4.3' ry='1.7' transform='rotate%28-147 11.2 33.8%29'/%3E%3Cellipse cx='14.7' cy='25.3' rx='4.1' ry='1.6' transform='rotate%28-62 14.7 25.3%29'/%3E%3Cellipse cx='9.9' cy='26.1' rx='4.1' ry='1.6' transform='rotate%28-138 9.9 26.1%29'/%3E%3Cellipse cx='14.3' cy='17.9' rx='3.8' ry='1.5' transform='rotate%28-53 14.3 17.9%29'/%3E%3Cellipse cx='9.8' cy='18.0' rx='3.8' ry='1.5' transform='rotate%28-129 9.8 18.0%29'/%3E%3Cellipse cx='15.0' cy='9.9' rx='3.6' ry='1.5' transform='rotate%28-45 15.0 9.9%29'/%3E%3Cellipse cx='10.8' cy='9.4' rx='3.6' ry='1.5' transform='rotate%28-121 10.8 9.4%29'/%3E%3Cellipse cx='14.0' cy='1.0' rx='1.9' ry='4' /%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat; filter: drop-shadow(0 0 3px rgba(233, 207, 142, 0.4));
}
.band-laurel.l { margin-right: -2px; }
.band-laurel.r { transform: scaleX(-1); margin-left: -2px; }
.band-laurel::after {
  content: ""; position: absolute; left: 25%; top: -8%; width: 8px; aspect-ratio: 1; margin: -4px;
  background: #fffbe8; clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
  opacity: 0; animation: laurel-glint 4s ease-in-out infinite;
}
.band-laurel.r::after { animation-delay: 2s; }
@keyframes laurel-glint { 0%, 55%, 100% { opacity: 0; transform: scale(0) rotate(0); } 72% { opacity: 1; transform: scale(1.1) rotate(45deg); } 86% { opacity: 0.5; transform: scale(0.6) rotate(90deg); } }
.laurelled > span { color: #f3e6c4; }
@media (prefers-reduced-motion: reduce) {
  .band-laurel::after { animation: none; }
  .band-laurel.l::after { opacity: 1; transform: scale(0.9) rotate(30deg); }
}
/* (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); }
/* Last chance (cards.js's LAST_CHANCE): a film leaving within two days, in a quiet amber, kept
   clear of What's Hot's orange and the seats' filling yellow: its posters' chip (.tile-chip.last:
   "Last day", "Until Fri"), and on its page, under what it is, a pill and its final show (.st-last,
   shown on a phone's page alone: above) */
:root { --last: #f1c27a; }
/* a Special Event film's chip, its event's day after a gold star: in the events' gold, its edge a
   gold hairline (the frames' on the film's page); the Q&A chip's look it was (3 Nov 2026) */
.tile-chip.event { grid-auto-flow: column; align-items: center; gap: 4px; color: var(--gold); box-shadow: 0 0 0 0.5px var(--gold-hair), 0 2px 8px rgb(0 0 0 / 0.45); }
.tile-chip.event::before { content: ""; width: 8px; height: 8px; translate: 0 -0.5px; /* (the owner's pick by eye, as the frames') */ background: var(--gold); -webkit-mask: var(--star) center / contain no-repeat; mask: var(--star) center / contain no-repeat; }
@media (forced-colors: active) { .tile-chip.event { color: CanvasText; } .tile-chip.event::before { background: CanvasText; } }
.tile-chip.last { color: var(--last); box-shadow: 0 0 0 0.5px rgb(241 194 122 / 0.42), 0 2px 8px rgb(0 0 0 / 0.45); }
.st-last { display: none; align-items: center; flex-wrap: wrap; gap: 4px 8px; margin: 6px 0 0; font-size: 0.8rem; line-height: 1.35; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.last-pill {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px; border-radius: 999px; white-space: nowrap;
  background: rgb(241 194 122 / 0.13); box-shadow: inset 0 0 0 0.5px rgb(241 194 122 / 0.45);
  font-size: 10.5px; font-weight: 650; letter-spacing: 0.02em; color: var(--last);
}
.st-last-when { text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55); }
@media (forced-colors: active) { :is(.tile-chip.last, .last-pill) { color: CanvasText; } }

/* ——— The age limit (cards.js's): its row on Preferences' first page, a phone's only (wider, as it
   was), set apart from the parts as who you go with, not what's on. A limit on (html.who-on), every
   poster's age tag at its bottom right (its seals bottom left), on a small dark glass as a band's
   chip, so its colours read on any poster; faded in and out, not at once ——— */
html:not(.page-scroll) .prefs-who-nav { display: none; }
.prefs-who-nav { margin-top: 14px; }
/* the age page (cards.js's The age limit): what it does, then the switch that shows its button, the
   button pictured beside it (faded while off), and what off means */
[data-who] > .prefs-note { text-wrap: pretty; }
.age-show { margin-top: 14px; }
.age-show .pref { grid-template-columns: auto minmax(0, 1fr) auto; }
.age-show-face { display: grid; place-items: center; width: 50px; height: 44px; border-radius: 22px; background: rgb(255 255 255 / 0.06); color: var(--ink); transition: background .2s, opacity .2s; }
.age-show-face.on { background: color-mix(in srgb, var(--accent) 24%, transparent); }
.age-show .pref:not(:has(input:checked)) .age-show-face { opacity: .45; }
.age-off-line { margin-top: 8px; }
.age-show:has(input:checked) + .age-off-line { display: none; } /* (said only while it's off) */
.tile-age {
  position: absolute; right: 4px; bottom: 4px; z-index: 6; display: flex; padding: 2px; border-radius: 7px; pointer-events: none;
  background: rgb(12 11 18 / 0.72); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  box-shadow: 0 0 0 0.5px rgb(255 255 255 / 0.18), 0 2px 8px rgb(0 0 0 / 0.45);
  opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility 0s .3s; /* (hidden, not just clear: no glass drawn under a hundred posters) */
}
.tile-age > .age-tag { font-size: 9.5px; }
/* a wide tag (PG | 13, 18TC) beside two seals: no room for both on a phone's poster, so the tag's
   lifted clear of them, its foot just over theirs. In the poster's height (%: the lift's, the
   card's), as the seals are sized in its width (cqw, .tile-seals): 1cqw = 0.716% of it */
:root:not([data-ratings="imdb"]) .tile-lift:has(.tile-art ~ .tile-seals > .tile-seal + .tile-seal) > .tile-age:has(> :is([data-group="guided"], [data-group="tbc"])) {
  bottom: calc(2.5% + var(--seal-d) + 3px); /* (the seals' bottom, their size, a gap) */
}
.tile-age { --seal-d: max(15.75%, 34px); } /* (.tile-seals' --d: 22cqw, 34px at least) */
.band-row .tile-age { --seal-d: max(17.2%, 26px); } /* (a band's smaller seals: 24cqw, 26px at least) */
html.who-on.page-scroll .tile-age { opacity: 1; visibility: inherit; transition-delay: 0s; } /* (inherit: a tile hidden, nothing left on the page, hides its tag too) */
@media (prefers-reduced-motion: reduce) { .tile-age { transition: none; } }

/* ——— 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; }
/* but Top's #1 (.top-one: above): its numeral as a coin pinned at its poster's top left, a gold rim
   round a dark face (the award seals' look), its figure outlined in gold, the foil's light crossing it */
.grid-view.banded-wide .band-top .top-one .tile-rank {
  display: grid; place-items: center; position: absolute; top: 12px; left: -18px; z-index: 8; width: 50px; height: 50px; border-radius: 50%;
  border: 3px solid transparent;
  background: radial-gradient(circle at 50% 30%, #2a2130, #0b090d 75%) padding-box, conic-gradient(from 210deg, #fff4cf, #c99a45, #f8e6b0, #7d5a22, #fbe6ad, #a77a33, #fff4cf) border-box;
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.7);
  font-size: 30px; font-weight: 800; line-height: 1; letter-spacing: -0.04em; font-variant-numeric: tabular-nums;
  color: rgb(9 9 14 / 0.55); -webkit-text-stroke: 1.5px var(--gold); paint-order: stroke fill;
}
.grid-view.banded-wide .band-top .top-one .tile-rank::after { display: grid; place-items: center; }
.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) */

/* ——— Peek (cards.js's TILE_PEEK): on a phone, a poster held lifts out of its band, a little glass
   card by it saying the film in brief, as the sheets' glass; let go, back down. A big move from
   rest (--set-off); with less motion, just faded in and out. ——— */
.film-tile.peeked .tile-lift { opacity: 0; } /* (lifted out: the layer's copy over its place) */
.peek { position: fixed; inset: 0; z-index: calc(var(--z-screen) + 10); --peek-shift: 0px; pointer-events: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.peek-shade {
  position: absolute; inset: 0; background: rgba(4, 4, 6, 0.58); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .3s var(--set-off);
}
.peek-poster {
  position: absolute; overflow: hidden; border-radius: 4.6% / calc(4.6% * 63 / 88); background: #15131b;
  box-shadow: 0 0 0 1px rgba(255, 240, 200, 0.16), 0 10px 22px -12px rgba(0, 0, 0, 0.9);
  transition: transform .4s var(--set-off), box-shadow .4s var(--set-off);
}
.peek-poster img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 20%; }
.peek-card {
  position: absolute; padding: 14px 16px 12px; border-radius: 22px; color: var(--ink);
  background: rgba(30, 28, 38, 0.62); backdrop-filter: blur(28px) saturate(1.8); -webkit-backdrop-filter: blur(28px) saturate(1.8); /* (a little darker than a sheet's: over posters, read even unblurred) */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1), 0 24px 60px -18px rgba(0, 0, 0, 0.85);
  opacity: 0; transform: translateY(var(--peek-shift)) scale(0.92);
  transition: opacity .22s var(--set-off), transform .35s var(--set-off);
}
.peek.up :is(.peek-shade, .peek-card) { opacity: 1; }
.peek.up .peek-card { transform: translateY(var(--peek-shift)); transition-delay: .04s; }
.peek.up .peek-poster { transform: translateY(var(--peek-shift)) scale(1.05); box-shadow: 0 0 0 1px rgba(255, 240, 200, 0.3), 0 30px 50px -18px rgba(0, 0, 0, 0.95); } /* (cards.js's PEEK_LIFT) */
.peek.going .peek-card { transition-duration: .15s, .2s; } /* (put away quicker than it came) */
.peek.going .peek-shade { transition-duration: .25s; }
.peek-title { margin: 0 0 6px; font-size: 1.05rem; font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; text-wrap: balance; }
.peek-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.peek-meta .info-meta { margin: 0; font-size: 0.86rem; font-weight: 600; color: var(--ink-soft); }
.peek-meta .info-scores { width: auto; gap: 6px 12px; }
.peek-meta .info-score-label { display: none; } /* (just their icons: it's short) */
.peek-summary {
  margin: 8px 0 0; font-size: 0.86rem; line-height: 1.35; color: var(--ink-soft);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
.peek-next { display: flex; align-items: baseline; gap: 6px; margin: 10px 0 0; font-size: 0.86rem; color: var(--ink-soft); white-space: nowrap; overflow: hidden; }
.peek-next b { font-weight: 700; color: var(--ink); }
.peek-next span { overflow: hidden; text-overflow: ellipsis; }
.peek-next-label { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-faint); }
.peek-next-where::before { content: "· "; color: var(--ink-faint); }
.peek-next.soon b { color: var(--soon); }
.peek-next.now b { color: var(--now); }
.peek-actions { display: flex; gap: 8px; margin-top: 12px; }
.peek-go {
  flex: 1; padding: 10px 12px; border-radius: 12px; text-align: center; font-size: 0.9rem; font-weight: 600;
  background: var(--pill-fill); box-shadow: inset 0 0 0 1px var(--pill-line); color: var(--ink);
  transition: background-color .12s, box-shadow .12s, transform .12s var(--ease);
}
.peek-go.over { background: rgba(255, 255, 255, 0.2); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.36); transform: scale(1.03); } /* (the finger on it: let go, it's done) */
@media (prefers-reduced-motion: reduce) { /* (just faded: moved to fit, if it must, at once) */
  .peek-poster { transition: none; }
  .peek-card, .peek.up .peek-card { transform: translateY(var(--peek-shift)); transition: opacity .22s; }
  .peek.up .peek-poster { transform: translateY(var(--peek-shift)); }
  .peek-go.over { transform: none; }
}
/* ——— A show's seat map in a sheet (a phone, either way up: cards.js's enterSeatSheet): the seat page
   itself moved into a sheet over the film, in every sheet's glass (dialog.sheet), as tall as the
   show needs. Its head (the grabber, the show, a ×) is what drags it, never the map; the map pinched
   in its own box (cards.js's pinchTo), its legend and how full it is quiet under it, and Book over
   Share, the sheet's width, at its foot. Its quieter words vibrant, as the other sheets' are ——— */
.seat-meter { display: none; }
dialog.seat-sheet {
  width: min(100%, 560px); max-width: none; padding-top: 0; padding-inline: 0; border: 0; color: var(--ink);
  max-height: calc(100svh - env(safe-area-inset-top) - 72px + var(--sheet-under));
}
dialog.seat-sheet[open] { display: flex; flex-direction: column; overflow: hidden; }
/* (a phone on its side, short: all but the top 12px, as Preferences there; what's past its foot, Book
   and Share, a short scroll up in its page) */
@media (orientation: landscape) and (max-height: 499px) { dialog.seat-sheet { max-height: calc(100svh - 12px + var(--sheet-under)); } }
dialog.seat-sheet .seat { pointer-events: none; } /* (a seat, untouched: no label on a tap, not yet; the map pinched and scrolled as before) */
dialog.seat-sheet .seat-tip { display: none; }
.seat-sheet-head { flex: none; position: relative; padding: 30px 64px 4px 22px; touch-action: none; }
.seat-sheet-close { position: absolute; top: 22px; right: 16px; width: 32px; height: 32px; }
/* the show: the time in the top left corner, to when it's out; under it where; the day's stub at its right */
.seat-sheet-show { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0 12px; }
.seat-sheet-text { flex: 1 1 0; min-width: 0; } /* (no width of its own to ask: the stub always beside it, the event's line alone under them) */
.seat-sheet-eventline { flex: 0 0 100%; margin-top: 4px; }
.seat-sheet-title { margin: 0; font-size: 1.6rem; font-weight: 700; letter-spacing: -0.03em; line-height: 1.1; font-variant-numeric: tabular-nums; color: #fff; outline: none; }
.seat-sheet-end { margin-left: 4px; font-size: 0.92rem; font-weight: 500; letter-spacing: 0; color: rgba(255, 255, 255, 0.5); mix-blend-mode: plus-lighter; }
.seat-sheet-where { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 6px 0 0; font-size: 0.9rem; line-height: 1.4; color: rgba(255, 255, 255, 0.62); }
.seat-sheet-where > :not(.seat-sheet-room) { mix-blend-mode: plus-lighter; }
.seat-sheet-room { display: inline-flex; align-items: center; } /* (the room's badge, as the times have it) */
.seat-sheet-event { display: inline-flex; align-items: center; gap: 5px; color: var(--gold); }
.seat-sheet-where > .seat-sheet-event { mix-blend-mode: normal; } /* (an event's show: its name after a gold star, as its frame on the times has it) */
.seat-sheet-event::before { content: ""; flex: none; width: 11px; height: 11px; background: currentColor; -webkit-mask: var(--star) center / contain no-repeat; mask: var(--star) center / contain no-repeat; }
/* the day, a ticket's stub past a perforation: TONIGHT over 29 over THU (a moon by it for a Late show, from 9PM: cards.js's dayStub) */
.seat-sheet-stub {
  flex: none; display: grid; justify-items: center; align-content: center; gap: 1px; width: 52px; padding: 3px 0 3px 12px; margin-right: 2px;
  border-left: 1.5px dashed rgba(255, 255, 255, 0.24); line-height: 1; font-variant-numeric: tabular-nums;
}
.stub-cap { font-size: 9px; font-weight: 700; letter-spacing: 0.08em; color: var(--accent); white-space: nowrap; }
.stub-num { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; color: #fff; }
.stub-day { display: inline-flex; align-items: center; gap: 3px; font-size: 9px; font-weight: 600; letter-spacing: 0.1em; color: rgba(255, 255, 255, 0.55); }
.stub-moon { width: 10px; height: 10px; background: var(--moon-ink); -webkit-mask: var(--moon) center / contain no-repeat; mask: var(--moon) center / contain no-repeat; }
/* its page: no scrolling to speak of (the map's zoomed where it is), so no ground of its own anywhere */
.seat-sheet .seat-page {
  flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 2px 16px 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none;
  transform: none; transition: none; -webkit-mask-image: none; mask-image: none;
}
.seat-sheet .seat-page::-webkit-scrollbar { display: none; }
.seat-sheet .seat-page::before { content: none; }
.seat-sheet .seat-page > * { flex: none; }
.seat-sheet :is(.seat-head, .seat-expand) { display: none; } /* (the ticket: the film's page behind says which film; the head says the rest. Zoomed by a pinch) */
/* the map, pinched in its box: what's zoomed past it cut off at its edges, a hairline round it then */
.seat-sheet .seat-map { overflow: clip; touch-action: none; border-radius: 12px; transition: box-shadow .2s; }
.seat-sheet .seat-map.pinched { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1); }
.seat-sheet .seats-svg { transform-origin: 0 0; }
/* its legend from the left, on as many lines as it takes (a line held for it as the seats are checked: the sheet keeps its height as they come) */
.seat-sheet .seat-legend { justify-content: flex-start; min-height: 22px; margin-top: -2px; }
.seat-sheet .seats-legend-text { flex: 1 1 auto; min-width: 0; column-gap: 14px; font-size: 0.76rem; line-height: 1.7; color: rgba(255, 255, 255, 0.7); }
/* how full, and when it was checked: "20% full · checked 40s ago" */
.seat-sheet .seat-meter { display: flex; align-items: center; min-height: 18px; margin: -4px 2px 0; font-size: 0.76rem; color: rgba(255, 255, 255, 0.62); }
.seat-sheet .seat-meter > * { mix-blend-mode: plus-lighter; }
.seat-meter-words { font-variant-numeric: tabular-nums; }
.seat-meter-checked { white-space: pre; }
.seat-sheet .seat-status { margin: -6px 2px 0; font-size: 0.76rem; }
.seat-sheet .seat-status:empty { display: none; }
/* Book over Share, each the sheet's width: Book's words in the middle, the chain's mark for its name
   (in its words' colour), its arrow at its end */
.seat-sheet .seat-page > .seat-actions { flex-direction: column; align-items: stretch; flex-wrap: nowrap; gap: 8px; margin: auto 0 0; padding: 6px 0 12px; }
.seat-sheet .seat-book { position: relative; justify-content: center; min-height: 52px; padding: 0 52px; border-radius: 16px; }
.seat-sheet .seat-book::after { position: absolute; right: 10px; top: 10px; }
.seat-sheet .seat-book-words { display: inline-flex; align-items: center; }
.seat-sheet .seat-book-chain {
  display: inline-block; height: 13px; aspect-ratio: var(--book-ratio); margin-left: 6px; font-size: 0; /* (its name, read, not shown) */
  background: currentColor; -webkit-mask: var(--book-mark) center / contain no-repeat; mask: var(--book-mark) center / contain no-repeat;
}
.seat-sheet .seat-share { justify-content: center; min-height: 48px; border-radius: 16px; }
/* A phone film's time row, pressed (cards.js's pressedTime, and TAP_SINK for a quick tap): sinks a little, lit a little brighter,
   with an inset edge (once the finger's stayed put a moment, as every row here), and springs back as
   it's let go; set off scrolling, let go at once, eased. Less motion: lit only */
@media (hover: none) and (pointer: coarse) {
  html.page-scroll.film-page .times-cover .st-time { transition: background-color .2s, color .2s, box-shadow .2s, transform .55s var(--spring-back); }
  html.page-scroll.film-page .times-cover .st-time:active:not(.touch-moved *) {
    transform: scale(0.97); background-color: color-mix(in srgb, var(--accent) 26%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 38%, transparent), inset 0 2px 6px rgba(0, 0, 0, 0.25);
    transition: transform .08s var(--ease) .07s, background-color .08s .07s, box-shadow .08s .07s, color .08s .07s;
  }
  html.page-scroll.film-page.touch-moved .times-cover .st-time { transform: none; transition-duration: .2s; transition-timing-function: var(--ease); }
}
@media (prefers-reduced-motion: reduce) { html.page-scroll.film-page .times-cover .st-time:active:not(.touch-moved *) { transform: none; } }


/* A film's trailers in several languages, a choice of them (cards.js's askTrailer): each language a
   button, ▶ and its name in its own script, its English name beside it, quieter */
.trailer-lang { -webkit-tap-highlight-color: transparent; }
.trailer-lang .trailer-native { font-weight: 650; }
.trailer-lang .trailer-en { font-size: 0.72em; font-weight: 500; color: var(--ink-faint); }
.trailer-ico { display: inline-grid; place-items: center; color: var(--accent); }
.trailer-ico svg { width: 11px; height: 11px; fill: currentColor; }
/* Show Trailer split in its place, a button for each in its look (splitWatch) */
html .times-cover .dressed .st-watch.split-away { opacity: 0; pointer-events: none; }
html .times-cover .dressed .st-watch.split-away.split-back { pointer-events: auto; } /* (its languages closing up into it) */
.trailer-split.closing { pointer-events: none; }
.trailer-split { position: relative; width: 100%; z-index: 1; }
.trailer-split .trailer-part {
  position: absolute; top: 0; height: 100%; display: flex; align-items: center; justify-content: center; gap: 7px; padding: 0 8px; overflow: hidden; white-space: nowrap;
  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.9rem; cursor: pointer;
  transition: background .15s, transform .15s var(--ease);
}
.trailer-split .trailer-part.tight .trailer-en { display: none; }
.trailer-split .trailer-part.bare { padding: 0 4px; }
.trailer-split .trailer-part.bare .trailer-ico { display: none; }
.trailer-split .trailer-part:active { transform: scale(0.96); background: rgba(255, 255, 255, 0.17); }
.trailer-split .trailer-was { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 8px; pointer-events: none; color: var(--ink); font-size: 0.86rem; font-weight: 600; }
.trailer-split .trailer-was svg { width: 14px; height: 14px; fill: currentColor; }
/* from a small mark (the ▶ by the name): pills on glass, grown out of it (trailerPop) */
.trailer-pop {
  position: fixed; z-index: calc(var(--z-screen) + 5); display: flex; gap: 6px; padding: 6px; border-radius: 16px;
  background: rgba(30, 28, 38, 0.86); -webkit-backdrop-filter: blur(24px) saturate(1.6); backdrop-filter: blur(24px) saturate(1.6);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 18px 40px -12px rgba(0, 0, 0, 0.7);
}
.trailer-pop .trailer-pill {
  display: flex; align-items: center; gap: 7px; height: 38px; padding: 0 14px 0 12px; white-space: nowrap; border: 0; border-radius: 11px;
  background: rgba(255, 255, 255, 0.08); color: var(--ink); font: inherit; font-size: 0.88rem; cursor: pointer; transition: background .15s, transform .15s var(--ease);
}
.trailer-pop .trailer-pill:hover { background: rgba(255, 255, 255, 0.14); }
.trailer-pop .trailer-pill:active { transform: scale(0.95); }

/* ——— A Cinema Akil show (cards.js's showAkil): no map, its seating unassigned. In the map's place how
   many seats are left, large, and the room's fill under it in the colours of the time's bar, grown in
   from rest; the seating and, outdoors, where, small and quiet. Under it the price, as a map's legend,
   and how full, as its meter: in the side panel too ——— */
.seat-page.akil-on .seat-meter { display: flex; align-items: center; min-height: 18px; margin: -4px 2px 0; font-size: 0.76rem; color: var(--ink-faint); }
.seat-sheet .seat-page.akil-on .seat-meter { color: rgba(255, 255, 255, 0.62); }
.seat-page.akil-on .seat-legend:empty { display: none; }
.seat-page.akil-on .seat-legend { margin: -4px 2px -8px; min-height: 0; }
.akil-legend .seats-price { font-variant-numeric: tabular-nums; }
.seat-map.akil-card { min-height: 0; display: grid; gap: 12px; padding: 16px 18px 18px; touch-action: auto; animation: fade .25s var(--set-off); }
.seat-sheet .seat-map.akil-card { overflow: visible; }
.akil-problem { margin: 0; font-size: 0.8rem; line-height: 1.45; color: var(--ink-faint); }
.akil-left { display: grid; gap: 8px; }
.akil-left-count { margin: 0; font-size: 0.95rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.akil-left-count b { font-size: 2rem; font-weight: 700; letter-spacing: -0.03em; color: var(--ink); margin-right: 2px; }
.akil-left-of { color: var(--ink-faint); }
.akil-bar {
  position: relative; display: block; height: 6px; border-radius: 99px; background: rgba(255, 255, 255, 0.08); overflow: hidden;
  --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%));
}
.akil-bar::after { content: ""; position: absolute; inset: 0 auto 0 0; width: max(6px, calc(var(--full) * 1%)); border-radius: inherit; background: var(--full-ink); transform-origin: left; animation: full-grow .9s var(--set-off) .1s both; }
.akil-bar.old::after { opacity: 0.45; } /* (the listings' counts: faded, as an old check's bar) */
.akil-fact { margin: 0; font-size: 0.8rem; line-height: 1.6; color: var(--ink-soft); }
/* a show's Q&A (cards.js's qaRow, eventBanner): its time in the event's gold frame, its ribbon
   "★ Q&A WITH THE CAST", its guests under the ribbon, each whole, their names in Cormorant Garamond's
   italic, who they play quieter; its film in Special Event, no chip on its poster (the owner's, 3 Nov
   2026). (The owner's D of four mocked, 3 Nov 2026; its guests in the banner, F of seven, 3 Nov 2026) */
@font-face { font-family: "Cormorant Garamond"; src: url("/static/fonts/CormorantGaramond-SemiBoldItalic-latin.woff2") format("woff2"); font-weight: 600; font-style: italic; font-display: swap; } /* (only for a Q&A's guests: not preloaded, as Inter is) */
.qa-guest { display: inline-block; max-width: 100%; } /* (a guest whole: a line breaks between guests; inside one only if it's wider than the line) */
.qa-name { font-family: "Cormorant Garamond", Georgia, serif; font-style: italic; font-weight: 600; font-size: 1.4em; line-height: 1; color: color-mix(in srgb, var(--gold) 78%, var(--ink)); }
.qa-role { color: var(--ink-faint); }
