/* Mobile first. No framework and no build step: a handful of screens does not
   justify a bundler, and it keeps the container the same shape as t3o. */
:root {
    --bg: #12100f;
    --surface: #1c1917;
    --text: #f5f0eb;
    --muted: #a8a29e;
    --accent: #d94f2b;
    --line: #2c2724;
    --danger: #e06c5a;
    /* The mark control has no per-status colours -- it uses --accent for its
       single "on" state -- so the chips need their own. Deliberately darker
       than --accent rather than aliasing it: the chip's label is 0.7rem at
       weight 600, which is not "large text", so white on it needs 4.5:1 for
       WCAG AA. --accent itself is 4.1:1 and #5a8fd9 was 3.3:1; these are
       5.2:1, 5.0:1 and 5.7:1. */
    --chip-ticket: #c2411f;
    --chip-want: #3d6fb8;
    --chip-maybe: #6b6560;
    --tap: 44px;
    --gap: 0.75rem;
}

* { box-sizing: border-box; }

/* The hidden attribute must always win. Without this, any rule that sets
   display (.screening's grid, .filter's flex) silently un-hides the element,
   which is how the schedule filter's hidden rows stayed on screen. */
[hidden] { display: none !important; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 16px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
    padding-bottom: calc(var(--tap) + env(safe-area-inset-bottom) + 1rem);
}

.content { padding: var(--gap); max-width: 46rem; margin: 0 auto; }

.tabbar {
    position: fixed;
    inset: auto 0 0 0;
    /* Above the overview's sticky time column and day row, which carry their
       own z-index and would otherwise paint over the bar. */
    z-index: 10;
    display: flex;
    background: var(--surface);
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
}

.tabbar a {
    flex: 1;
    min-height: var(--tap);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    text-decoration: none;
    font-size: 0.8rem;
}

/* Unbuilt destinations (My plan, Friends, Settings): same slot as a real
   tab, visibly inert so they read as "not here yet" rather than a dead
   link. */
.tabbar__soon {
    flex: 1;
    min-height: var(--tap);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    font-size: 0.8rem;
    opacity: 0.5;
}

.day-heading {
    position: sticky;
    top: 0;
    background: var(--bg);
    padding: 0.75rem 0 0.25rem;
    margin: 0;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
}

.screening {
    display: grid;
    grid-template-columns: 3.5rem 1fr auto;
    gap: var(--gap);
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--line);
}

.marks { display: flex; gap: 0.25rem; align-items: start; flex-wrap: wrap; }

/* The marks take their own line inside a schedule row rather than a fourth
   column. Three 44px taps plus the time and thumbnail columns left the title
   62px on a 390px phone -- and a 1fr track will not shrink below its
   min-content, so the row overflowed sideways instead of wrapping. On their
   own line the title gets ~214px back and the buttons have room for words. */
.screening .marks { grid-column: 1 / -1; }

.mark {
    /* Padding, not a fixed width: the label decides how wide each control is,
       and min-width keeps the smallest one ("Maybe") a legal touch target. */
    padding: 0 0.6rem;
    gap: 0.35rem;
    min-width: var(--tap);
    min-height: var(--tap);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    text-decoration: none;
    color: var(--muted);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 0.25rem;
    cursor: pointer;
}

/* 44px minimum on every one of these, per the spec: this is the app's most
   frequent action and it happens on a phone, one-handed. */
.mark--on { background: var(--accent); border-color: var(--accent); color: #fff; }

.screening__time { font-variant-numeric: tabular-nums; color: var(--muted); }
.screening__title { margin: 0 0 0.15rem; font-size: 1rem; }
.screening__title a { color: var(--text); text-decoration: none; }
.screening__meta { color: var(--muted); font-size: 0.8rem; }

.screening--cancelled .screening__title { text-decoration: line-through; opacity: 0.6; }

.tag {
    display: inline-block;
    font-size: 0.7rem;
    padding: 0.1rem 0.4rem;
    border: 1px solid var(--line);
    border-radius: 0.2rem;
    color: var(--muted);
    margin-right: 0.25rem;
}

/* Auth and settings forms. Inputs are full-width and at least a tap target
   tall, because every one of these is typed on a phone. */
.form { display: flex; flex-direction: column; gap: 0.35rem; max-width: 24rem; }
.form label { font-size: 0.8rem; color: var(--muted); margin-top: var(--gap); }

.form input {
    min-height: var(--tap);
    padding: 0 0.6rem;
    font-size: 1rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 0.25rem;
}

.form__hint { font-size: 0.75rem; color: var(--muted); margin: 0.15rem 0 0; }

.form__errors:not(:empty) {
    margin: var(--gap) 0 0;
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--accent);
    border-radius: 0.25rem;
    font-size: 0.85rem;
}
.form__errors ul { margin: 0; padding-left: 1.1rem; }

/* With no errors the summary still renders a hidden <li>, so :not(:empty)
   alone leaves an empty bordered box. */
.form__errors.validation-summary-valid { display: none; }

.btn {
    min-height: var(--tap);
    padding: 0 1rem;
    font-size: 1rem;
    border-radius: 0.25rem;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
}

.btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Outlined rather than filled, so a destructive action reads as different
   from the primary one beside it instead of merely louder. --danger on
   --surface is 5.4:1, so the label clears AA at this size. */
.btn--danger { border-color: var(--danger); color: var(--danger); }

.tabbar__form { flex: 1; display: flex; }

/* Matches the .tabbar a rule so the sign-out button is indistinguishable
   from the real tabs beside it. */
.tabbar__form button {
    flex: 1;
    min-height: var(--tap);
    background: none;
    border: 0;
    color: var(--muted);
    font-size: 0.8rem;
    cursor: pointer;
}

.notice {
    margin: 0 0 var(--gap);
    padding: 0.6rem;
    border: 1px solid var(--accent);
    border-radius: 0.25rem;
    font-size: 0.9rem;
}

.or { color: var(--muted); font-size: 0.8rem; margin: var(--gap) 0 0.35rem; }
a.btn { display: inline-flex; align-items: center; text-decoration: none; }

.tabbar__badge {
    display: inline-block;
    min-width: 1.2rem;
    margin-left: 0.3rem;
    padding: 0 0.25rem;
    border-radius: 0.6rem;
    background: var(--accent);
    color: #fff;
    font-size: 0.7rem;
    text-align: center;
}

/* The tab bar's links are flex columns of one line; a badge needs the label
   and the count on the same line. */
.tabbar a { flex-direction: row; gap: 0; }

.plan-entry { border-left: 3px solid transparent; padding-left: 0.5rem; }

/* A warning, never a block -- so it is a coloured edge and a line of text,
   not something that hides or disables the row. */
.screening--conflict { border-left-color: var(--accent); }

.plan-entry__status { margin: 0 0 0.5rem 4.25rem; font-size: 0.75rem; color: var(--muted); }
.plan-entry__conflict { color: var(--accent); }

.empty { color: var(--muted); }

/* Groups ------------------------------------------------------------- */

.group-list,
.member-list { list-style: none; padding: 0; }

.group-list li,
.member-list li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    /* var(--tap) is this app's 44px minimum touch target. */
    min-height: var(--tap);
    border-bottom: 1px solid var(--line);
}

.group-list__meta,
.member-list__role { color: var(--muted); font-size: 0.85rem; }

/* The li supplies the 44px, but the anchor is what a finger actually hits.
   Stretching it to fill means the whole row is the target rather than the
   text's own line box -- the same fix the buttons got, applied to links. */
.group-list li > a,
.member-list li > a {
    display: flex;
    align-items: center;
    min-height: var(--tap);
    flex: 1;
}

/* The Friends page's per-group line. Previously unstyled: the class was in
   the markup with no rule behind it, so it rendered as unlabelled body text
   indistinguishable from the screening titles under it. */
.group-summary { color: var(--muted); font-size: 0.85rem; margin-bottom: 1rem; }

.group-create { display: flex; flex-wrap: wrap; gap: var(--gap); margin-top: 1.5rem; }
.group-create input { flex: 1 1 12rem; min-height: var(--tap); }

.invite { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* Wraps rather than overflowing: an invite link is 43 characters of
   base64url and a phone is not wide. */
.invite__link { word-break: break-all; font-size: 0.8rem; }

.inline-form { display: inline; margin-left: auto; }

.danger { margin-top: 2rem; }
.danger button { color: var(--danger); }

.note { color: var(--muted); font-size: 0.9rem; }

/* Visible to screen readers only. The chips show initials; the full name
   and status belong in the accessibility tree, not on a 24px circle. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Friend chips -------------------------------------------------------- */

.chips {
    display: flex;
    gap: 0.25rem;
    list-style: none;
    padding: 0;
    margin: 0.25rem 0 0;
}

.chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Small on purpose: these sit beside the title and the var(--tap) mark
       control, and are informational rather than tappable. */
    min-width: 1.5rem;
    height: 1.5rem;
    padding: 0 0.25rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1;
    color: #fff;
}

.chip--ticket { background: var(--chip-ticket); }
.chip--want   { background: var(--chip-want); }
/* Outlined, not filled: a Maybe should read as weaker than a ticket at a
   glance, which a third fill colour did not achieve. --muted on --bg already
   meets AA for this text size. */
.chip--maybe  { background: transparent; border: 1px solid var(--chip-maybe); color: var(--muted); }
.chip--more   { background: transparent; color: var(--muted); font-weight: 400; }

.chip__glyph { margin-right: 0.15rem; font-weight: 400; }

/* Settings ------------------------------------------------------------ */

/* Wraps rather than overflowing: the feed URL is long and a phone is not. */
.feed-url {
    display: block;
    word-break: break-all;
    font-size: 0.8rem;
    padding: 0.5rem;
    background: var(--surface);
    border-radius: 4px;
}

.method-list { list-style: none; padding: 0; }
.method-list li { min-height: var(--tap); display: flex; align-items: center; }

/* Admin --------------------------------------------------------------- */

.admin-menu { list-style: none; padding: 0; }
.admin-menu li > a { display: flex; align-items: center; min-height: var(--tap); }

.admin-search { display: flex; flex-wrap: wrap; gap: var(--gap); align-items: center; }
.admin-search label { font-size: 0.8rem; color: var(--muted); }
.admin-search input {
    flex: 1 1 12rem;
    min-height: var(--tap);
    padding: 0 0.6rem;
    font-size: 1rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 0.25rem;
}

.admin-list { list-style: none; padding: 0; }

.admin-row {
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--line);
}

.admin-row__who { display: flex; flex-direction: column; }
.admin-row__email { color: var(--muted); font-size: 0.85rem; word-break: break-all; }
.admin-row__flags { margin-top: 0.35rem; }

/* A coloured edge rather than a hidden or disabled row: this is a warning
   about what confirming would mean, never a block. Matches the treatment
   .screening--conflict already uses for the same reason. */
.admin-row--unproven { border-left: 3px solid var(--danger); padding-left: 0.5rem; }

.admin-row__warning {
    margin: 0.35rem 0 0;
    color: var(--danger);
    font-size: 0.85rem;
}

.admin-paging { display: flex; gap: var(--gap); margin-top: var(--gap); }

.admin-row__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; }
/* Only the margin is overridden. The base .inline-form sets margin-left:auto
   to push a lone button to the right, which in this flex row would shove the
   first action away from the rest. Its display:inline is not repeated here --
   these are flex items, so the declaration would be computed away. */
.admin-row__actions .inline-form { margin-left: 0; }

.issued-link {
    margin: 0 0 var(--gap);
    padding: 0.6rem;
    border: 1px solid var(--accent);
    border-radius: 0.25rem;
}
.issued-link h2 { margin-top: 0; font-size: 1rem; }

.admin-row__self { color: var(--muted); font-size: 0.85rem; align-self: center; }

/* Two subscribe buttons side by side, wrapping on a narrow phone rather than
   shrinking below the 44px tap target. */
.subscribe-options { display: flex; flex-wrap: wrap; gap: var(--gap); margin-bottom: var(--gap); }

/* The tags and links reuse existing classes; only these three need spacing of
   their own. No touch-target rule: none of this is interactive except the
   links, which inherit the body's text sizing like every other inline link. */
.film-tags { margin: 0 0 0.35rem; }
.film-links { margin: 0 0 var(--gap); }
.film-cast { color: var(--muted); font-size: 0.9rem; }
.synopsis { margin: 0 0 var(--gap); }

/* The day strip. Wraps rather than scrolls: twelve short labels fit a phone
   in three rows, and a horizontal scroller hides days off-screen. */
.admin-days { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0 0 var(--gap); }
.admin-days__day {
    padding: 0.5rem 0.7rem;
    min-height: var(--tap);
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--line);
    border-radius: 0.4rem;
    text-decoration: none;
}
.admin-days__day--current { border-color: currentColor; font-weight: 600; }
.admin-row--cancelled .admin-row__who { text-decoration: line-through; opacity: 0.7; }

/* Only rows rendered by _ScreeningRow carry a thumbnail column. The film
   page builds its own .screening markup with two children, so widening the
   base rule would squeeze its content into the 4.5rem image column. */
.screening--thumbed { grid-template-columns: 3.5rem 4.5rem 1fr; }

/* Thumbnails are a fixed 16:9 box so row heights stay uniform: the published
   stills run from 1.25 to 2.49, and letting rows follow that makes their
   heights differ by about 2x, dragging the time column out of rhythm. */
.screening__thumb {
    width: 4.5rem;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 0.25rem;
    display: block;
    background: var(--surface);
}
/* The placeholder keeps the grid column occupied; it must not draw a box. */
.screening__thumb--empty { background: none; }

/* The hero is never cropped, so it has no aspect-ratio of its own here --
   width and height on the element reserve the space instead. */
.film-hero {
    width: 100%;
    height: auto;
    border-radius: 0.3rem;
    display: block;
    margin: 0 0 var(--gap);
}

.mark__glyph { font-size: 1rem; line-height: 1; }
.mark__label { font-size: 0.8rem; white-space: nowrap; }

/* The configurable feed's checkboxes. Each label is a full-width tap target,
   because on a phone the box itself is far smaller than 44px. */
.status-choices fieldset { border: 1px solid var(--line); border-radius: 0.4rem; margin: 0 0 var(--gap); }
.status-choices legend { padding: 0 0.4rem; color: var(--muted); font-size: 0.8rem; }
.status-choice {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-height: var(--tap);
    cursor: pointer;
}

/* One row per separate calendar: label, subscribe button, then the raw URL
   for pasting on a desktop. */
.feed-list { list-style: none; padding: 0; }
.feed-list li {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--line);
}

/* The Easter egg on the landing page: five taps on the title adds .lit.
   Inline-block so the bulbs wrap the words rather than the column. The
   heading looks and behaves exactly as before until then. */
.marquee-title {
    display: inline-block;
    position: relative;
    /* The padding is the lit sign's border area. The matching negative
       margin cancels it while unlit, so the wordmark stays aligned with the
       cards below and the heading occupies exactly the box it always did. */
    padding: 0.3rem 0.9rem;
    margin: -0.3rem -0.9rem;
    /* Without this, iOS reads a rapid five-tap as double-tap-to-zoom and
       swallows half the clicks -- on the one platform this egg exists for.
       It also drops the 300ms tap delay. */
    touch-action: manipulation;
    /* Stops a rapid five-tap from selecting the word on the way through. */
    -webkit-user-select: none;
    user-select: none;
}

.marquee-title.lit {
    border-radius: 0.4rem;
    background: #1a1512;
    text-shadow: 0 0 0.5rem var(--accent), 0 0 1.5rem rgba(217, 79, 43, 0.55);
    animation: marquee-warmup 1.1s steps(1, end) 1;
}

/* The bulbs: one row above the title and one below, chasing in opposite
   directions. A repeating gradient rather than markup, so the egg adds no
   elements to the page it is hiding in. */
.marquee-title.lit::before,
.marquee-title.lit::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 8px;
    background-image: radial-gradient(circle at 5px 4px, #ffd9a0 2.5px, transparent 3px);
    background-size: 14px 8px;
    animation: marquee-chase 0.6s linear infinite;
}

.marquee-title.lit::before { top: -5px; }
.marquee-title.lit::after { bottom: -5px; animation-direction: reverse; }

@keyframes marquee-chase {
    to { background-position: 14px 0; }
}

/* A tube struggling to strike before it settles. Runs once. */
@keyframes marquee-warmup {
    0%, 14%, 30% { opacity: 0.3; }
    7%, 22%, 100% { opacity: 1; }
}

.marquee-tagline {
    margin: 0.35rem 0 0;
    font-size: 0.7rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent);
}

/* The payoff survives, the motion does not: someone who asked the OS for
   less movement still gets the lit marquee, just without the flicker and
   the chase. Removing the egg entirely would punish them for the setting. */
@media (prefers-reduced-motion: reduce) {
    .marquee-title.lit,
    .marquee-title.lit::before,
    .marquee-title.lit::after {
        animation: none;
    }
}

/* The festival cards on the landing page. The whole card is the link, so the
   tap target is the card rather than a line of text. */
.editions { list-style: none; padding: 0; }
.edition-card { margin: 0 0 var(--gap); }
.edition-card__link {
    display: block;
    color: var(--text);
    text-decoration: none;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 0.5rem;
    overflow: hidden;
}

/* Four stills in one row. They shrink together rather than scrolling, so the
   strip always shows the whole programme sample it was given. */
.edition-card__strip { display: flex; gap: 1px; background: var(--line); }
.edition-card__still {
    flex: 1 1 0;
    min-width: 0;
    width: auto;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
}

.edition-card__body { display: flex; flex-direction: column; gap: 0.15rem; padding: var(--gap); }
.edition-card__name { font-size: 1.05rem; }
/* The line that says whether this is worth opening today. */
.edition-card__status { font-size: 0.85rem; color: var(--accent); }

/* Schedule header ------------------------------------------------------ */

.schedule-head { display: flex; align-items: baseline; gap: var(--gap); flex-wrap: wrap; }
.schedule-head h1 { margin-right: auto; }
.today-link {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    padding: 0 0.75rem;
    border: 1px solid var(--accent);
    border-radius: 999px;
    color: var(--text);
    text-decoration: none;
    font-size: 0.85rem;
}

/* Schedule filter ------------------------------------------------------ */

.filter { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: var(--gap); }
/* One line per group that scrolls sideways rather than wrapping: twelve day
   toggles wrapped would push the list a screen down on a phone. */
.filter__group { display: flex; gap: 0.35rem; overflow-x: auto; scrollbar-width: none; }
.filter__group::-webkit-scrollbar { display: none; }
.filter__row { display: flex; gap: 0.35rem; align-items: center; }
/* 36px, under --tap, on purpose: these are dense chips in a sideways-scrolling
   strip, and the spec caps the whole bar at four lines on a phone. */
.filter__toggle {
    flex: none;
    min-height: 2.25rem;
    padding: 0 0.7rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--muted);
    font: inherit;
    font-size: 0.8rem;
    white-space: nowrap;
}
.filter__toggle[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.filter__search {
    flex: 1;
    min-width: 0;
    min-height: 2.25rem;
    padding: 0 0.7rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: 0.85rem;
}
.filter__empty { color: var(--muted); }
.filter__reset { background: none; border: 0; color: var(--accent); font: inherit; text-decoration: underline; padding: 0; }

/* Overview grid -------------------------------------------------------- */
/* Modelled on the festival's own Übersichtsplan (data/raw/
   slashfilmfestival-uebersichtsplan-2026-10-05.html): a table per venue,
   days across, times down, scrolled sideways on a phone with the time
   column and day row pinned. */

.content--wide { max-width: none; }

.schedule-head__link { color: var(--muted); font-size: 0.85rem; }

/* By table position, not venue: nothing here knows a venue's name. */
.overview--accent-0 { --overview-accent: #d94f2b; }
.overview--accent-1 { --overview-accent: #e0b43a; }
.overview--accent-2 { --overview-accent: #7fa8e8; }
.overview--accent-3 { --overview-accent: #6cbf8a; }
.overview--muted    { --overview-accent: var(--muted); }

.overview__scroll {
    --overview-time: 2.875rem;
    /* The containing block for the cells' visually-hidden labels. Without it
       they are positioned against the page, escape this scroller's overflow,
       and widen the whole page on a phone. */
    position: relative;
    overflow-x: auto;
    overflow-y: clip;
    overscroll-behavior-inline: contain;
    margin-bottom: 1.5rem;
}
.overview__scroll:focus-visible { outline: 2px solid var(--overview-accent); outline-offset: -2px; }
@media (min-width: 64rem) { .overview__scroll { --overview-time: 4rem; } }

.overview {
    table-layout: fixed;
    border-collapse: separate;
    border-spacing: 0;
    width: calc(var(--overview-time) + var(--overview-days) * 10rem);
    font-size: 0.8rem;
}

/* Sticky to the left edge of the scroller so the venue name stays in view. */
.overview__venue {
    position: sticky;
    left: 0;
    width: max-content;
    margin-bottom: 0.35rem;
    padding: 0.15rem 0.5rem;
    text-align: left;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.75rem;
    font-weight: 600;
    color: #12100f;
    background: var(--overview-accent);
}

.overview__corner, .overview__day, .overview__time { position: sticky; background: var(--bg); }
.overview__corner { left: 0; z-index: 2; width: var(--overview-time); border-bottom: 1px solid var(--text); }
/* Pinned sideways only. Pinning the day row while the PAGE scrolls is not
   possible from inside an overflow-x scroller (overflow-y computes to hidden,
   so top:0 would stick to the scroller, which never scrolls vertically), and
   giving each table its own vertical scroll is worse on a phone. A table is
   about 500px tall, so its day row is never more than half a screen away. */
.overview__day {
    z-index: 1;
    padding: 0.25rem 0.4rem;
    text-align: left;
    white-space: nowrap;
    text-transform: uppercase;
    border-bottom: 1px solid var(--text);
    border-left: 1px solid var(--line);
}
.overview__date { color: var(--muted); }
.overview__time {
    left: 0;
    z-index: 1;
    padding: 0.25rem 0.25rem 0.25rem 0;
    vertical-align: top;
    text-align: left;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}

.overview tbody tr + tr > * { border-top: 1px solid var(--line); }
.overview__cell { padding: 0.25rem; vertical-align: top; border-left: 1px solid var(--line); }
.overview__cell--empty { padding-block: 0.5rem; }

.overview-entry { display: grid; gap: 2px; padding: 0.25rem; border: 1px solid transparent; }
.overview-entry + .overview-entry { margin-top: 0.35rem; border-top-color: var(--line); }
.overview-entry:hover, .overview-entry:focus-within { border-color: var(--overview-accent); }
.overview-entry__when { font-weight: 700; }
.overview-entry__title { color: var(--text); text-decoration: none; font-weight: 600; overflow-wrap: anywhere; }
.overview-entry--cancelled .overview-entry__title { text-decoration: line-through; opacity: 0.6; }
.overview-entry__facts { color: var(--muted); font-size: 0.75rem; }
.overview-entry__people { display: flex; align-items: center; gap: 0.25rem; flex-wrap: wrap; }
.overview-entry__people .chips { margin: 0; }
.overview-entry__mark { font-size: 0.85rem; }

.overview-legend { display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; color: var(--muted); font-size: 0.75rem; }
.overview-legend div { display: flex; gap: 0.35rem; }
.overview-legend dt { color: var(--text); }
.overview-legend dd { margin: 0; }

/* Six tabs since the overview arrived. On the narrowest phones (320px) the
   labels otherwise touch -- "ScheduleOverview" -- so they shrink a step. */
@media (max-width: 22rem) {
    .tabbar a, .tabbar__soon, .tabbar__form button { font-size: 0.7rem; padding-inline: 0.15rem; }
}

.back-link {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    min-height: var(--tap);
    color: var(--muted);
    font-size: 0.85rem;
    text-decoration: none;
}

.film-original-title { margin: -0.5rem 0 0.75rem; color: var(--muted); font-style: italic; }
