/* ============================================================
   CineLogger — sidebar-led dark system, oklch tokens
   Near-black neutral ground, one warm amber accent carrying
   emphasis (primary actions, the "what this saved you" figures).
   Inter-led type stack, 16px card radius, pill controls.
   Redesign per design_handoff_cinelogger (2026-08-21) — see
   ARCHITECTURE.md §10.2 for the token-mapping rationale.
   ============================================================ */

:root {
  --color-bg: oklch(0.15 0.005 260);
  --color-surface: oklch(0.2 0.006 260);
  --color-surface-raised: oklch(0.24 0.006 260);
  --color-surface-sunken: oklch(0.17 0.005 260);
  --color-border: oklch(0.26 0.006 260);
  --color-border-strong: oklch(0.3 0.006 260);

  --color-accent: oklch(0.78 0.13 75);
  --color-accent-bright: oklch(0.83 0.13 75);
  --color-accent-ink: oklch(0.16 0.02 75);
  --color-accent-dim: oklch(0.85 0.1 75);
  --color-accent-wash: oklch(0.78 0.13 75 / 0.12);

  --color-text: oklch(0.96 0.003 260);
  --color-text-dim: oklch(0.6 0.006 260);
  /* --color-text-dim (0.6) drops under the 4.5:1 text minimum on the lighter
     --color-surface-raised background specifically (measures 4.17:1) -- this
     exists for exactly that case (tag pills, kbd hints) rather than raising
     text-dim itself, which is used far too broadly (nav items at rest, table
     body copy, labels) to safely brighten without re-auditing everywhere. */
  --color-text-dim-strong: oklch(0.64 0.006 260);
  --color-text-faint: oklch(0.42 0.006 260);

  --color-danger: oklch(0.71 0.15 19);
  --color-danger-bg: oklch(0.71 0.15 19 / 0.12);
  --color-danger-ink: oklch(0.18 0.02 25);
  --color-success-bg: oklch(0.78 0.13 75 / 0.12);

  /* Every "what your membership earned you" figure renders amber -- the One Job
     Rule (see DESIGN.md). --color-positive is kept as a semantic alias so the
     savings surfaces can name intent in markup, but it resolves to amber and is
     never a second accent. A ticket produces a saving only when both prices are
     recorded and the venue is in a held membership's chain (app/services/savings.py). */
  --color-positive: var(--color-accent-dim);
  --color-positive-wash: var(--color-accent-wash);
  /* The "review" verdict is a de-emphasis, not an accent -- the uppercase label
     carries the meaning on its own. */
  --color-review: var(--color-text-dim-strong);
  --sv-track: oklch(1 0 0 / 0.07);

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Roboto, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --radius: 16px;
  --radius-sm: 8px;
  --sidebar-width: 232px;
  --side-margin: 10%;
  --max-width-form: 640px;
  --topbar-height: 3.75rem;
  --bottom-nav-height: 4.25rem;
}

* {
  box-sizing: border-box;
}

html {
  color-scheme: dark;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Guest shell (no sidebar -- <main> is a direct child of body here; the
   authenticated shell's own <main> is handled by .app-main > main instead,
   so this selector never double-applies). Grows to fill the viewport so a
   short guest page still pushes .site-footer (normal flow, below) to the
   bottom edge. */
body > main {
  flex: 1 0 auto;
}

/* Contains any horizontal overflow bleeding out of page content (e.g. the
   diary table, wider than its viewport-narrow wrapper below a min-width
   floor) to <main>'s own box, instead of letting it inflate .app-main/body
   and drag the whole page sideways. Deliberately not on html/body directly:
   overflow-x set there without an explicit overflow-y forces overflow-y to
   auto too (CSS's paired-axis rule), which turns <body> into its own actual
   scroll container and broke .sidebar's position:sticky -- confirmed live,
   the sidebar stopped pinning to the viewport on any page taller than one
   screen. <main> sits outside .sidebar's ancestor chain entirely, so this
   can't touch that.

   `clip`, not `hidden`: the paired-axis rule only coerces `visible` to `auto`
   when the other axis is `scroll`/`auto`, so `overflow-x: clip` leaves
   `overflow-y` as `visible` and never makes <main> a scroll container. With
   `hidden` it did -- and that vertically clipped the diary's `···` row menu
   (its "Delete" item) when the list ran near <main>'s bottom edge, e.g. a
   diary holding a single entry. */
main {
  overflow-x: clip;
}

a {
  color: var(--color-accent);
  text-decoration: none;
}

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

img {
  max-width: 100%;
  display: block;
}

:focus-visible {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

/* Off-screen until focused -- lets a keyboard user jump past the sidebar's
   nav items and the topbar's search/primary-action before reaching content,
   instead of tabbing through the whole shell on every page load. */
.skip-link {
  position: fixed;
  top: -100%;
  left: 1rem;
  z-index: 100;
  padding: 0.65rem 1.3rem;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-weight: 700;
  font-size: 0.9rem;
  transition: top 0.15s ease;
}

.skip-link:focus,
.skip-link:hover {
  color: var(--color-accent-ink);
}

.skip-link:focus {
  top: 1rem;
  outline: 2px solid var(--color-accent-ink);
  outline-offset: 2px;
}

.eyebrow {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-accent);
  font-size: 0.78rem;
}

/* ---------- Layout shell: sidebar + main ---------- */

.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 2rem;
  padding: 1.625rem 1.125rem;
  background: var(--color-bg);
  border-right: 1px solid var(--color-border);
  /* Pinned to the viewport (not just the top of a long scrolling page) so the
     user block at the bottom (margin-top: auto below) never scrolls out of
     view -- without this, a tall .app-shell stretches the sidebar to match
     the full page height and the user info ends up far below the fold. */
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: 0.56rem;
  padding: 0 0.375rem;
  color: var(--color-text);
}

.sidebar-logo:hover {
  color: var(--color-text);
}

.sidebar-logo-mark {
  flex-shrink: 0;
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 20px;
}

.sidebar-logo-mark span {
  width: 4px;
  border-radius: 1px;
  background: var(--color-accent);
}

.sidebar-logo-mark span:nth-child(1) {
  height: 10px;
}

.sidebar-logo-mark span:nth-child(2) {
  height: 18px;
}

.sidebar-logo-mark span:nth-child(3) {
  height: 14px;
  background: oklch(0.78 0.13 75 / 0.45);
}

.sidebar-logo-label {
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.01em;
}

.sidebar-logo-label span {
  color: var(--color-accent);
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
}

.sidebar-nav-item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.56rem 0.625rem;
  border-radius: 9px;
  color: var(--color-text-dim);
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
}

.sidebar-nav-item:hover {
  color: var(--color-text);
  text-decoration: none;
}

.sidebar-nav-item:focus-visible {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: -2px;
}

.sidebar-nav-item.is-active {
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

.sidebar-nav-icon {
  display: inline-flex;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.sidebar-nav-icon svg {
  width: 100%;
  height: 100%;
}

.nav-badge {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: var(--color-danger);
  color: var(--color-danger-ink);
  font-size: 0.68rem;
  font-weight: 700;
}

/* ---------- Sidebar user block ---------- */

.sidebar-user {
  position: relative;
  margin-top: auto;
}

.sidebar-user-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5rem 0.625rem;
  border-radius: 9px;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.sidebar-user-trigger:hover,
.sidebar-user-trigger[aria-expanded="true"] {
  background: var(--color-surface-raised);
}

.sidebar-user-avatar {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.8rem;
}

.sidebar-user-info {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
}

.sidebar-user-name {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-user-email {
  font-size: 0.72rem;
  color: var(--color-text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-user-menu {
  position: absolute;
  bottom: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  padding: 0.35rem;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  z-index: 20;
}

.sidebar-user-menu[hidden] {
  display: none;
}

.sidebar-user-menu-item {
  display: block;
  width: 100%;
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  border: none;
  background: none;
  color: var(--color-text-dim);
  font: inherit;
  font-size: 0.82rem;
  text-align: left;
  cursor: pointer;
}

.sidebar-user-menu-item:hover {
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
}

.no-js .sidebar-user-menu {
  display: flex !important;
  position: static !important;
  box-shadow: none;
  margin-top: 0.4rem;
}

.sidebar-user-menu-header {
  display: none;
  padding: 0.35rem 0.6rem 0.6rem;
  margin-bottom: 0.25rem;
  border-bottom: 1px solid var(--color-border);
}

.sidebar-user-menu-name {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-user-menu-email {
  display: block;
  font-size: 0.72rem;
  color: var(--color-text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-main > main {
  flex: 1 0 auto;
}

/* ---------- Top bar ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 2.5rem;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
}

.topbar-search {
  position: relative;
  flex: 1;
  max-width: 420px;
}

.topbar-search-form {
  position: relative;
  display: flex;
  align-items: center;
}

.topbar-search-icon {
  position: absolute;
  left: 0.75rem;
  width: 16px;
  height: 16px;
  color: var(--color-text-faint);
  pointer-events: none;
}

.topbar-search input {
  width: 100%;
  padding: 0.55rem 2.6rem 0.55rem 2.25rem;
  border-radius: 9px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font: inherit;
  font-size: 0.85rem;
}

.topbar-search input::placeholder {
  color: var(--color-text-dim);
}

.topbar-search input:focus {
  border-color: var(--color-accent);
}

.topbar-search:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
  border-radius: 9px;
}

.topbar-search-kbd {
  position: absolute;
  right: 0.5rem;
  padding: 0.15rem 0.4rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-raised);
  color: var(--color-text-dim-strong);
  font-size: 0.68rem;
  font-weight: 600;
  pointer-events: none;
}

/* Live dropdown under the topbar search: diary matches ("have I seen this?")
   plus a persistent footer row into film search ("not logged it? add it"). */
.topbar-search-results {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  margin: 0;
  padding: 0.35rem;
  list-style: none;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
  max-height: 24rem;
  overflow-y: auto;
}

.topbar-search-option {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.45rem 0.55rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--color-text);
}

.topbar-search-option[aria-selected="true"],
.topbar-search-option:hover {
  background: var(--color-surface-sunken);
}

.topbar-search-option img,
.topbar-search-option-poster {
  width: 28px;
  height: 42px;
  border-radius: 4px;
  object-fit: cover;
  background: var(--color-surface-sunken);
  flex-shrink: 0;
}

.topbar-search-option-body {
  min-width: 0;
}

.topbar-search-option-title {
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-search-option-sub {
  font-size: 0.75rem;
  color: var(--color-text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-search-status {
  padding: 0.5rem 0.55rem;
  font-size: 0.82rem;
  color: var(--color-text-dim);
}

.topbar-search-add {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.2rem;
  padding: 0.55rem 0.55rem;
  border-top: 1px solid var(--color-border);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-accent-dim);
}

.topbar-search-add[aria-selected="true"],
.topbar-search-add:hover {
  background: var(--color-accent-wash);
}

.topbar-search-add svg {
  flex-shrink: 0;
}

/* When the results list has only the "add" footer (no diary matches), it
   doesn't need the divider above it. */
.topbar-search-add:first-child {
  margin-top: 0;
  border-top: 0;
}

.topbar-log-btn {
  flex-shrink: 0;
  gap: 0.55rem;
}

.topbar-btn-kbd {
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
  background: oklch(0.16 0.02 75 / 0.35);
  font-size: 0.68rem;
  font-weight: 700;
}

/* "Log a film" below the nav-swap breakpoint, replacing .topbar-log-btn --
   pinned above the fixed bottom tab bar. Hidden by default; shown at
   max-width:900px alongside the rest of the mobile shell swap. */
.fab {
  display: none;
  position: fixed;
  right: 1rem;
  bottom: calc(var(--bottom-nav-height) + 0.75rem);
  z-index: 41;
  width: 54px;
  height: 54px;
  align-items: center;
  justify-content: center;
  /* New one-off shape: between --radius-sm (8px) and --radius (16px) isn't
     right for a 54px circular-ish control -- see DESIGN.md Shape. */
  border-radius: 18px;
  border: 0;
  /* Same warm avatar gradient as .profile-avatar-lg/.sidebar-user-avatar,
     not a new pairing. */
  background: linear-gradient(150deg, oklch(0.82 0.14 75), oklch(0.62 0.13 45));
  color: var(--color-accent-ink);
  /* Same shadow alpha as .confirm-dialog, this app's other genuinely
     overlaid (not resting-card) surface. */
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45);
}

.fab:hover {
  color: var(--color-accent-ink);
}

.fab svg {
  width: 22px;
  height: 22px;
}

.page {
  flex: 1;
  width: 100%;
  padding: 1.625rem 2.5rem 3rem;
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 2rem;
}

.page-title {
  font-size: 1.85rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  margin: 0;
}

.page-subtitle {
  color: var(--color-text-dim);
  margin: 0.3rem 0 0;
  font-size: 0.95rem;
}

.page-summary {
  color: var(--color-accent);
  font-weight: 600;
  font-size: 0.88rem;
  margin: 0.4rem 0 0;
}

/* ---------- Flash messages ---------- */

.flash-list {
  padding: 1.25rem 2.5rem 0;
  display: grid;
  gap: 0.6rem;
}

.flash {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.8rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  font-size: 0.92rem;
}

.flash.error {
  background: var(--color-danger-bg);
  border-color: var(--color-danger);
}

/* The "you just logged a film" confirmation -- Peak-End Rule: the last thing the
   flow shows leads with the figure that grew, so it gets the amber treatment
   rather than the neutral surface every other success flash uses. */
.flash-logged {
  background: var(--color-accent-wash);
  border-color: var(--color-accent);
  font-weight: 600;
}

.flash-logged .flash-icon {
  color: var(--color-accent-dim);
}

/* Transient toast stack -- the diary's "Removed X · Undo" affordance. */
.toast-stack {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: max-content;
  max-width: calc(100vw - 2rem);
}

.toast {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.7rem 0.75rem 0.7rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
  font-size: 0.88rem;
}

.toast-action {
  flex-shrink: 0;
  padding: 0.3rem 0.7rem;
  border: 0;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.toast-action:hover {
  background: var(--color-accent-bright);
}

@media (max-width: 900px) {
  .toast-stack {
    bottom: calc(var(--bottom-nav-height) + 1rem);
  }
}

.flash-icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 0.1rem;
  color: var(--color-text-dim);
}

.flash.error .flash-icon {
  color: var(--color-danger);
}

.flash-api-key {
  background: var(--color-accent-wash);
  border: 1px solid var(--color-accent);
}

.flash-api-key-label {
  margin: 0 0 0.5rem;
  font-weight: 600;
  color: var(--color-accent-dim);
}

.flash-api-key-value {
  display: block;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  overflow-wrap: anywhere;
}

/* ---------- Buttons & forms ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.65rem 1.3rem;
  border-radius: 999px;
  border: 1px solid var(--color-accent);
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-family: inherit;
  font-weight: 700;
  font-size: 0.9rem;
  /* Normalise <a class="btn"> against <button class="btn">: the UA gives a
     bare <button> its own line-height, so without this the same label renders
     a few px shorter/taller depending on the element (visible on the film-
     detail page, where a link and a form button sit side by side). */
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
}

.btn:hover {
  background: var(--color-accent-bright);
  color: var(--color-accent-ink);
  text-decoration: none;
  box-shadow: 0 0 0 4px oklch(0.78 0.13 75 / 0.16);
}

.btn:active {
  transform: translateY(1px);
}

.btn:disabled {
  background: var(--color-surface-raised);
  border-color: var(--color-border);
  color: var(--color-text-faint);
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

.btn-secondary {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-border-strong);
}

.btn-secondary:hover {
  background: var(--color-surface-raised);
  color: var(--color-text);
  box-shadow: none;
}

.btn-danger {
  background: transparent;
  color: var(--color-danger);
  border-color: var(--color-danger);
}

.btn-danger:hover {
  background: var(--color-danger-bg);
  color: var(--color-danger);
  box-shadow: none;
}

.btn-block {
  width: 100%;
}

.btn-sm {
  padding: 0.35rem 0.85rem;
  font-size: 0.78rem;
}

@media (max-width: 900px) {
  .btn-sm {
    min-height: 44px;
  }
}

.table-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Confirm dialog: reserved for destructive actions that cascade to other
   records) and every lower-stakes one (delete a cached film, a cinema) --
   `.confirm-dialog--severe` only deepens the shadow and turns the confirm
   button danger-red; the button's label always names the real action. */
.confirm-dialog {
  max-width: 420px;
  width: calc(100% - 2.5rem);
  padding: 1.5rem;
  background: var(--color-surface-raised);
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
}

.confirm-dialog--severe {
  border-color: var(--color-danger);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5);
}

.confirm-dialog::backdrop {
  background: rgba(0, 0, 0, 0.6);
}

.confirm-dialog-body {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.confirm-dialog-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.confirm-dialog-message {
  margin: 0;
  line-height: 1.5;
  color: var(--color-text-dim-strong);
}

.confirm-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
}

.toggle-form-wrap {
  margin: 0 0 1.75rem;
  padding: 1.25rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.toggle-form-wrap[hidden] {
  display: none;
}

/* Progressive-enhancement fallback: app.js removes .no-js from <html> as soon
   as it runs. Anything below only matters when JS never ran, so these forms
   and panels (normally revealed on click/select) stay reachable regardless. */
.no-js .toggle-form-wrap,
.no-js [data-new-venue-field],
.no-js [data-venue-panel],
.no-js .bulk-action-bar,
.no-js [data-bulk-edit-toggle] {
  display: block !important;
}

.bulk-action-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 1rem;
  padding: 0.75rem 1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.bulk-action-bar[hidden] {
  display: none;
}

.bulk-action-count {
  color: var(--color-text-dim);
  font-size: 0.85rem;
  margin-right: auto;
}

form {
  display: grid;
  gap: 1.1rem;
}

.form-narrow {
  max-width: var(--max-width-form);
}

.admin-add-section {
  margin-top: 2rem;
}

.admin-filter-form {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  margin-bottom: 1.75rem;
}

.admin-filter-form .field {
  flex: 1;
  max-width: 320px;
}

.filter-details {
  margin-bottom: 1.25rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface-sunken);
}

.filter-details-summary {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.85rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.filter-details-summary::-webkit-details-marker {
  display: none;
}

.filter-details-summary svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--color-text-dim);
}

.filter-details-chevron {
  margin-left: auto;
  transition: transform 0.15s ease;
}

.filter-details[open] .filter-details-chevron {
  transform: rotate(180deg);
}

/* Collapsible group of reference tables on an admin hub (Chains & locations on
   the Cinema page), so the needs-attention section leads and the rest folds. */
.admin-collapse {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface-sunken);
}

.admin-collapse-summary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1.1rem;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.admin-collapse-summary::-webkit-details-marker {
  display: none;
}

.admin-collapse-summary svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--color-text-dim);
}

.admin-collapse-summary .filter-result-count {
  margin-left: auto;
}

.admin-collapse-summary .filter-details-chevron {
  margin-left: 0;
  transition: transform 0.15s ease;
}

.admin-collapse[open] .filter-details-chevron {
  transform: rotate(180deg);
}

.admin-collapse > .stats-section {
  margin: 0;
  padding: 0 1.1rem 1.1rem;
}

.admin-collapse > .stats-section:first-of-type {
  padding-top: 0.5rem;
  border-top: 1px solid var(--color-border);
}

.filter-count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
  font-size: 0.68rem;
  font-weight: 700;
}

.logs-filter-form {
  display: grid;
  gap: 1.25rem;
  padding: 0 1.1rem 1.1rem;
}

.filter-group {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.9rem;
}

.filter-group-title {
  grid-column: 1 / -1;
  padding: 0;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-accent);
}

.logs-filter-form .form-actions {
  padding-top: 0.15rem;
  border-top: 1px solid var(--color-border);
}

.inline-form {
  display: inline;
}

.field {
  display: grid;
  gap: 0.4rem;
}

.field label {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-dim);
}

.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="date"],
.field input[type="datetime-local"],
.field input[type="number"],
.field select,
.field textarea {
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 0.65rem 0.8rem;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.95rem;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--color-accent);
}

.field input:disabled {
  color: var(--color-text-faint);
  cursor: not-allowed;
}

.field-input-name {
  max-width: 280px;
}

.field-input-currency {
  max-width: 200px;
}

.field-input-email {
  max-width: 320px;
}

.field textarea {
  min-height: 6rem;
  resize: vertical;
}

.checkbox-field {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-direction: row;
}

.checkbox-list {
  display: grid;
  gap: 0.6rem;
  max-height: 360px;
  overflow-y: auto;
  padding: 0.25rem;
}

.checkbox-field label {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 500;
  color: var(--color-text);
}

.field-error {
  color: var(--color-danger);
  font-size: 0.82rem;
}

.field-hint {
  color: var(--color-text-dim);
  font-size: 0.8rem;
}

/* ---------- Standalone auth pages (password reset) ---------- */

.auth-standalone {
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1rem;
}

.auth-card {
  width: 100%;
  max-width: 400px;
  padding: 2rem;
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}

.auth-card-logo {
  display: inline-block;
  margin-bottom: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-text);
  text-decoration: none;
}
.auth-card-logo span { color: var(--color-accent); }

.auth-card-title {
  margin: 0 0 0.5rem;
  font-size: 1.35rem;
}

.auth-card-sub {
  margin: 0 0 1.5rem;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--color-text-dim);
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.auth-field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.auth-field label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-dim);
}

.auth-input {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font: inherit;
}
.auth-input:focus { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.auth-input.is-error { border-color: var(--color-danger); }

.auth-input-code {
  font-family: var(--font-mono);
  font-size: 1.3rem;
  letter-spacing: 0.4em;
  text-align: center;
}

.auth-submit { width: 100%; justify-content: center; margin-top: 0.25rem; }

.auth-card-foot {
  margin: 1.25rem 0 0;
  font-size: 0.85rem;
  color: var(--color-text-dim);
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.field-label-standalone {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-dim);
  margin-bottom: 0.5rem;
}

.form-actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.form-section {
  display: grid;
  gap: 1.1rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-border);
}

.form-section:first-of-type {
  padding-top: 0;
  border-top: none;
}

.form-section-title {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-accent);
  margin: 0;
}

.checkbox-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.checkbox-list-option {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.92rem;
  color: var(--color-text);
  cursor: pointer;
}

/* ---------- Chip toggles (multi-select as pills) ---------- */

.fieldset-reset {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.fieldset-reset > legend {
  padding: 0;
  margin: 0 0 1.1rem;
  width: 100%;
}

.chip-toggle-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.chip-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.8rem 1.15rem;
  border-radius: 999px;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-dim);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.chip-toggle input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.chip-toggle:has(input:checked) {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-ink);
}

.chip-toggle:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

/* ---------- Profile page ----------
   Rebuilt from local_references/design_handoff_cinelogger 3/PROFILE-BRIEF.md.
   Deliberately its own small palette (card surface/border, label/positive
   colors) distinct from the app's global tokens -- exact oklch values from the
   handoff, scoped as custom properties on .profile-shell rather than folded
   into :root, since the brief didn't ask for these to become sitewide tokens. */

.profile-shell {
  --profile-card-bg: oklch(0.165 0.004 260);
  --profile-card-border: oklch(0.235 0.005 260);
  --profile-divider: oklch(0.22 0.005 260);
  --profile-label: oklch(0.62 0.005 260);
  --profile-text: oklch(0.92 0.004 260);
  --profile-text-dim: oklch(0.62 0.005 260);
  --profile-text-dimmer: oklch(0.6 0.005 260);
  --profile-field-label: oklch(0.75 0.005 260);
  --profile-field-bg: oklch(0.21 0.005 260);
  --profile-field-border: oklch(0.29 0.005 260);
  --profile-positive: oklch(0.84 0.14 145);

  /* One column, blocks stacked (identity -> memberships -> account -> data).
     The 2026-08-30 memberships rethink made every membership a full-width row,
     so the old two-track split (account form squeezed left, memberships right)
     no longer holds -- the rows and the price matrix want the whole width. */
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-bottom: 70px;
}

.profile-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

/* ---------- Identity card ---------- */

.profile-identity {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px;
  border-radius: 16px;
  background: linear-gradient(150deg, oklch(0.2 0.014 75), oklch(0.16 0.004 260) 60%);
  border: 1px solid oklch(0.26 0.008 260);
}

/* Demoted to a faint text action in the account form footer (2026-08-30) -- a
   plainly reachable sign-out on the profile page itself is still worth having
   regardless of the hidden-on-mobile sidebar menu, just not as its own block. */
.profile-logout-btn {
  padding: 0;
  margin-left: 4px;
  border: 0;
  background: none;
  color: var(--color-text-dim);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

.profile-logout-btn:hover {
  color: var(--color-text);
}

.profile-identity-top {
  display: flex;
  align-items: center;
  gap: 14px;
}

.profile-avatar-lg {
  width: 54px;
  height: 54px;
  border-radius: 15px;
  flex-shrink: 0;
  background: linear-gradient(150deg, oklch(0.82 0.14 75), oklch(0.62 0.13 45));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 21px;
  font-weight: 800;
  color: oklch(0.2 0.02 60);
}

.profile-identity-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.profile-identity-name {
  margin: 0;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.4px;
  color: oklch(0.98 0.002 260);
  line-height: 1.1;
}

.profile-identity-meta {
  font-size: 12.5px;
  color: var(--profile-text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.profile-stat-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--color-border-strong);
  border-radius: 11px;
  overflow: hidden;
}

.profile-stat-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 11px 12px;
  background: var(--color-surface-sunken);
}

.profile-stat-label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-dim-strong);
}

.profile-stat-value {
  font-size: 18px;
  font-weight: 800;
  color: oklch(0.95 0.003 260);
}

.profile-stat-value--positive {
  color: var(--profile-positive);
}

/* ---------- Generic card + label ---------- */

.profile-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 18px 20px 20px;
  border-radius: 14px;
  background: var(--profile-card-bg);
  border: 1px solid var(--profile-card-border);
}

.profile-card--flush {
  padding: 18px 20px 6px;
}

.profile-card-label {
  margin: 0;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--profile-label);
}

.profile-card--flush > .profile-card-label {
  margin-bottom: 4px;
}

.profile-card-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
}

/* ---------- Account & preferences fields ---------- */

/* Three-up field row (Display name / Email / Currency), collapsing to a single
   column on narrow viewports -- the account block sits below the memberships
   now, full width, so the fields spread rather than stack. */
.profile-account-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

@media (max-width: 700px) {
  .profile-account-grid {
    grid-template-columns: 1fr;
  }
}

.profile-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.profile-field label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--profile-field-label);
}

.profile-field input[type="text"],
.profile-field select {
  width: 100%;
  padding: 10px 12px;
  border-radius: 9px;
  background: var(--profile-field-bg);
  border: 1px solid var(--profile-field-border);
  color: oklch(0.93 0.004 260);
  font: inherit;
  font-size: 13.5px;
  box-sizing: border-box;
}

.profile-field input:focus,
.profile-field select:focus {
  border-color: var(--color-accent);
}

.profile-field-hint {
  font-size: 12px;
  color: var(--profile-text-dimmer);
}

.profile-email-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 9px;
  background: oklch(0.145 0.004 260);
  border: 1px solid oklch(0.22 0.005 260);
  color: var(--profile-text-dim);
  font-size: 13.5px;
}

.profile-email-row span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.profile-email-locked {
  flex-shrink: 0;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: oklch(0.62 0.005 260);
}

/* Page-level sticky action bar: Save / Discard / Log out apply to the whole
   profile page (memberships up top mark the form dirty just as the account
   fields do), so the controls sit in one bar pinned to the bottom of the
   viewport rather than buried inside the account card. */
.profile-action-bar {
  position: sticky;
  bottom: 12px;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
  padding: 12px 16px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--profile-card-bg) 88%, transparent);
  border: 1px solid var(--profile-card-border);
  backdrop-filter: blur(8px);
  box-shadow: 0 8px 28px oklch(0 0 0 / 0.35);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.profile-action-bar.is-dirty {
  border-color: var(--color-accent);
  box-shadow: 0 8px 28px oklch(0 0 0 / 0.4), 0 0 0 1px var(--color-accent);
}

.profile-action-bar-btns {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

.profile-form-status {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--profile-text-dimmer);
}

.profile-action-bar.is-dirty .profile-form-status { color: var(--color-accent); }

/* ---------- Card-scoped buttons (Discard, Rotate, Export, Choose file...) ---------- */

.profile-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 15px;
  border-radius: 9px;
  background: oklch(0.24 0.005 260);
  border: 1px solid oklch(0.32 0.005 260);
  color: oklch(0.9 0.004 260);
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}

.profile-btn:hover {
  background: oklch(0.29 0.005 260);
}

.profile-btn--danger {
  background: transparent;
  border-color: oklch(0.42 0.12 25);
  color: oklch(0.74 0.16 25);
}

.profile-btn--danger:hover {
  background: oklch(0.28 0.08 25);
  color: oklch(0.74 0.16 25);
}

.profile-btn--save {
  padding: 9px 15px;
  font-size: 12.5px;
}

/* ---------- Cinema memberships rows ----------
   2026-08-30 rethink (see local_references/Redesigning cinema membership profiles):
   every membership is a full-width row showing only the held tier + a payback
   meter; the tier list is a <details> picker, collapsed by default, one open at
   a time (native `name=` accordion). Picturehouse's 15 tiers render as a price
   matrix (tier type x region) rather than 15 radios. */

.profile-membership-rows {
  display: flex;
  flex-direction: column;
}

.profile-membership-row-wrap {
  position: relative;
  border-top: 1px solid var(--profile-divider);
}

.profile-membership-row-wrap:first-child {
  border-top: 0;
}

/* Held membership with tiers but none chosen: a quiet weight nudge, not the
   value-amber (that stays "this is what you saved"). */
.profile-membership-row-wrap.needs-tier {
  box-shadow: inset 2px 0 0 var(--color-text-dim);
}

/* Remove: unchecks the still-in-DOM membership checkbox, committed on Save.
   Absolutely placed over the row's trailing edge so it stays put whether the
   picker is open or closed. */
.profile-membership-row-remove {
  position: absolute;
  top: 21px;
  right: 6px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 600;
  color: oklch(0.6 0.005 260);
  cursor: pointer;
}

.profile-membership-row-remove input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.profile-membership-row-remove:hover {
  color: oklch(0.85 0.1 25);
}

.profile-membership-row-remove:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Checkbox starts checked (unchecked rows don't render) -- only ever matches
   after a click marks the row for removal. */
.profile-membership-row-wrap:has(.profile-membership-row-remove input:not(:checked)) {
  opacity: 0.5;
}

.profile-membership-row-wrap:has(.profile-membership-row-remove input:not(:checked)) .profile-membership-row-plan {
  text-decoration: line-through;
}

.profile-membership-row {
  border-radius: var(--radius-sm);
}

.profile-membership-row-head {
  display: grid;
  grid-template-columns: 40px minmax(160px, 1fr) minmax(240px, 340px) auto;
  align-items: center;
  gap: 18px;
  padding: 15px 76px 15px 6px;
  cursor: pointer;
  list-style: none;
}

.profile-membership-row-head::-webkit-details-marker {
  display: none;
}

.profile-membership-row--static .profile-membership-row-head {
  cursor: default;
}

.profile-membership-row-head:hover {
  background: oklch(0.195 0.005 260);
}

.profile-membership-row--static .profile-membership-row-head:hover {
  background: none;
}

.profile-membership-row:focus-visible {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: -2px;
  border-radius: 8px;
}

.profile-membership-row-badge {
  width: 40px;
  height: 40px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--color-bg);
}

.profile-membership-row-id {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.profile-membership-row-plan {
  font-size: 15px;
  font-weight: 600;
  color: var(--profile-text);
}

.profile-membership-row-chain {
  font-size: 12px;
  color: oklch(0.6 0.005 260);
}

.profile-membership-row-status {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.profile-membership-row-tier-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.profile-membership-row-tier {
  font-size: 13px;
  font-weight: 500;
  color: var(--profile-text);
}

.profile-membership-row-tier.is-unset {
  color: oklch(0.6 0.005 260);
}

.profile-membership-row-price {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--color-accent-dim);
}

.profile-membership-row-meter {
  display: block;
  width: 100%;
  height: 3px;
  border-radius: 2px;
  overflow: hidden;
}

.profile-membership-row-meter-track {
  fill: oklch(0.27 0.005 260);
}

.profile-membership-row-meter-fill {
  fill: oklch(0.6 0.005 260);
}

.profile-membership-row-meter-fill.is-profit {
  fill: var(--profile-positive);
}

.profile-membership-row-cap {
  font-family: var(--font-mono);
  font-size: 11px;
  color: oklch(0.6 0.005 260);
}

.profile-membership-row-toggle {
  justify-self: end;
  white-space: nowrap;
  font-size: 12.5px;
  color: oklch(0.62 0.005 260);
}

.profile-membership-row-head:hover .profile-membership-row-toggle {
  color: var(--profile-text);
}

.profile-membership-row:not([open]) .profile-membership-row-toggle-close,
.profile-membership-row[open] .profile-membership-row-toggle-open {
  display: none;
}

/* ---------- Tier picker (revealed inside an open row) ---------- */

.profile-membership-picker {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 2px 6px 22px 64px;
}

.profile-tier-flat {
  display: grid;
  grid-template-columns: repeat(2, minmax(200px, 1fr));
  gap: 8px;
}

.profile-tier-matrix {
  display: grid;
  gap: 8px;
  justify-content: start;
  align-items: center;
}

.profile-tier-matrix[data-cols="2"] {
  grid-template-columns: minmax(140px, 1fr) repeat(2, minmax(108px, 150px));
}

.profile-tier-matrix[data-cols="3"] {
  grid-template-columns: minmax(140px, 1fr) repeat(3, minmax(108px, 150px));
}

.profile-tier-matrix[data-cols="4"] {
  grid-template-columns: minmax(140px, 1fr) repeat(4, minmax(100px, 140px));
}

.profile-tier-matrix-col {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: oklch(0.6 0.005 260);
  padding: 0 12px 2px;
}

.profile-tier-matrix-rowlabel {
  font-size: 13px;
  color: var(--profile-label);
}

.profile-tier-cell {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 10px 12px;
  border-radius: 9px;
  border: 1px solid var(--profile-field-border);
  background: oklch(0.145 0.004 260);
  cursor: pointer;
}

.profile-tier-cell--flat {
  justify-content: space-between;
}

.profile-tier-matrix .profile-tier-cell {
  justify-content: flex-start;
}

.profile-tier-cell--empty {
  justify-content: center;
  color: oklch(0.45 0.005 260);
  cursor: default;
}

.profile-tier-cell input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.profile-tier-cell:hover {
  border-color: oklch(0.45 0.005 260);
}

.profile-tier-cell--empty:hover {
  border-color: var(--profile-field-border);
}

.profile-tier-cell:has(input:checked) {
  border-color: var(--color-accent);
  background: var(--color-accent-wash);
  box-shadow: inset 0 0 0 1px oklch(0.78 0.13 75 / 0.35);
}

.profile-tier-cell:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 1px;
}

.profile-tier-cell-name {
  font-size: 13px;
  color: var(--profile-label);
}

.profile-tier-cell-price {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: oklch(0.6 0.005 260);
}

.profile-tier-cell:has(input:checked) .profile-tier-cell-name {
  color: var(--color-accent-dim);
}

.profile-tier-cell:has(input:checked) .profile-tier-cell-price {
  color: var(--color-accent);
}

.profile-membership-picker-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
}

.profile-tier-clear {
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 600;
  color: oklch(0.6 0.005 260);
  cursor: pointer;
}

.profile-tier-clear input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.profile-tier-clear:hover {
  color: var(--profile-text);
}

.profile-tier-clear:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: no-preference) {
  .profile-membership-row-toggle,
  .profile-tier-cell {
    transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
  }
}

@media (max-width: 760px) {
  .profile-membership-row-head {
    grid-template-columns: 40px 1fr;
    gap: 10px 14px;
    padding-right: 76px;
  }

  .profile-membership-row-status {
    grid-column: 1 / -1;
  }

  .profile-membership-row-toggle {
    grid-column: 1 / -1;
    justify-self: start;
  }

  .profile-membership-picker {
    padding-left: 6px;
  }

  .profile-membership-picker.is-matrix {
    overflow-x: auto;
  }
}

.profile-tier-alert {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin: 0 0 0.9rem;
  padding: 0.6rem 0.8rem;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}

.profile-tier-alert svg {
  flex-shrink: 0;
  margin-top: 0.1rem;
  color: var(--color-text-dim);
}

/* Fixed palette of chain-avatar colors, assigned deterministically by name in
   app/auth/routes.py -- a hex value can't be set via style="" (see that
   file's _chain_style docstring for why), so each chain gets a class instead. */
.chain-color-1 {
  background: #c9a87c;
}

.chain-color-2 {
  background: #8fa9c9;
}

.chain-color-3 {
  background: #c98fa9;
}

.chain-color-4 {
  background: #9ac9a2;
}

.chain-color-5 {
  background: #b8ae8c;
}

.chain-color-6 {
  background: #a8a0d8;
}

/* Pricing-tier picker: a small vertical radio list (tier name + price) for a
   membership that has tiers. All options + prices stay visible (no dropdown to
   open), one tap to pick, selected row tinted -- Hick's/Fitts's/Von Restorff.
   CSS-only: real <input type=radio>, custom dot via ::before. */
.profile-tier-picker {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 8px 8px;
  border-top: 1px solid oklch(0.27 0.005 260);
}

.profile-tier-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 7px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 12px;
  color: oklch(0.72 0.005 260);
}

.profile-tier-option:hover {
  background: oklch(0.24 0.005 260);
}

.profile-tier-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.profile-tier-option::before {
  content: "";
  flex: 0 0 auto;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 1.5px solid oklch(0.42 0.005 260);
  box-sizing: border-box;
}

.profile-tier-option:has(input:checked) {
  background: var(--color-accent-wash);
  color: oklch(0.92 0.004 260);
}

.profile-tier-option:has(input:checked)::before {
  border-color: var(--color-accent);
  background: radial-gradient(
    circle,
    var(--color-accent) 0 3px,
    transparent 3.5px
  );
}

.profile-tier-option:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: -1px;
}

.profile-tier-option-name {
  flex: 1;
  min-width: 0;
  line-height: 1.3;
}

.profile-tier-option-price {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: oklch(0.62 0.005 260);
}

.profile-tier-option:has(input:checked) .profile-tier-option-price {
  color: var(--color-accent-dim);
}

.profile-tier-option-per {
  color: oklch(0.5 0.005 260);
}

.profile-tier-option--none {
  font-style: italic;
}

/* Add panel: reveal the tier list only once the membership itself is ticked
   (progressive disclosure) -- pure CSS off the sibling checkbox state. */
.chip-toggle-cell {
  display: flex;
  flex-direction: column;
  min-width: 190px;
}

.chip-toggle-cell .profile-tier-picker {
  display: none;
  margin-top: 7px;
  border: 1px solid oklch(0.27 0.005 260);
  border-radius: 9px;
  padding-top: 6px;
}

.chip-toggle-cell:has(.chip-toggle input:checked) .profile-tier-picker {
  display: flex;
}

.profile-membership-add {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 15px 6px;
  border: 0;
  border-top: 1px solid var(--profile-divider);
  background: transparent;
  color: oklch(0.62 0.005 260);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}

.profile-membership-add-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  border: 1px dashed oklch(0.42 0.005 260);
  font-size: 13px;
}

.profile-membership-add:hover {
  color: var(--color-accent-dim);
}

.profile-membership-add:hover .profile-membership-add-glyph {
  border-color: var(--color-accent);
}

.profile-membership-add-panel {
  margin-top: 12px;
}

/* ---------- Data & access divided rows ---------- */

.profile-data-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--profile-divider);
}

.profile-card--flush > .profile-data-row:last-child {
  padding-bottom: 18px;
  border-bottom: none;
}

.profile-data-row-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1 1 240px;
  min-width: 0;
}

.profile-data-row-title {
  font-size: 13.5px;
  font-weight: 600;
  color: oklch(0.92 0.004 260);
}

.profile-data-row-meta {
  font-size: 12px;
  color: oklch(0.6 0.005 260);
}

.profile-data-row-meta a {
  color: inherit;
  text-decoration: underline;
}

.profile-data-row-code {
  font-family: var(--font-mono);
  color: oklch(0.72 0.005 260);
}

.profile-quota-used {
  /* Same weight as .profile-data-row-code, not a new step in this card's
     local neutral scale. */
  color: oklch(0.72 0.005 260);
}

.profile-data-row-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.profile-import-form {
  flex-shrink: 0;
}

.profile-file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.profile-import-form:has(.profile-file-input:focus-visible) .profile-btn {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

/* ---------- Auth card ---------- */

.wordmark {
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--color-text);
}

.wordmark span {
  color: var(--color-accent);
}

.auth-shell {
  min-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem var(--side-margin);
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 2rem;
}

.auth-card .wordmark {
  display: block;
  text-align: center;
  margin: 0 0 0.4rem;
}

.auth-tagline {
  text-align: center;
  color: var(--color-text-dim);
  font-size: 0.85rem;
  margin: 0 0 1.5rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--color-border);
}

.auth-switch {
  margin-top: 1.25rem;
  text-align: center;
  font-size: 0.88rem;
  color: var(--color-text-dim);
}

/* ---------- Empty state ---------- */

.empty-state {
  text-align: center;
  padding: 4rem 1.5rem;
  color: var(--color-text-dim);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius);
}

.empty-state p {
  margin: 0 0 1.25rem;
}

.empty-state-icon {
  margin: 0 auto 1rem;
  width: 40px;
  height: 40px;
  color: var(--color-text-faint);
}

.empty-state-icon svg {
  width: 100%;
  height: 100%;
}

.empty-state-hint {
  color: var(--color-text-dim);
  font-size: 0.85rem;
  margin: -0.75rem 0 1.25rem;
}

/* ---------- Onboarding checklist ---------- */

.onboarding--card {
  margin-bottom: 1.5rem;
  padding: 1.1rem 1.25rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.onboarding--card[hidden] {
  display: none;
}

.onboarding-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.9rem;
}

.onboarding-title {
  margin: 0;
  font-weight: 700;
  font-size: 0.95rem;
}

.onboarding-progress {
  margin: 0.15rem 0 0;
  font-size: 0.78rem;
  color: var(--color-text-dim);
}

.onboarding-dismiss {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: -0.6rem -0.6rem 0 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--color-text-dim);
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.onboarding-dismiss:hover {
  color: var(--color-text);
  background: var(--color-surface-raised);
}

.onboarding-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.7rem;
  text-align: left;
}

.onboarding-step {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
}

.onboarding-step-marker {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: 0.05rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1.5px solid var(--color-border-strong);
  color: var(--color-accent-ink);
}

.onboarding-step.is-done .onboarding-step-marker {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.onboarding-step-body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.onboarding-step-label {
  font-weight: 600;
  font-size: 0.9rem;
}

.onboarding-step.is-done .onboarding-step-label {
  color: var(--color-text-dim);
  text-decoration: line-through;
}

.onboarding-step-hint {
  font-size: 0.8rem;
  color: var(--color-text-dim);
}

/* In the empty state the checklist is the body -- no card chrome, just centred
   in the dashed panel with the steps left-aligned in a sensible column. */
.empty-state .onboarding {
  max-width: 26rem;
  margin: 0 auto 1.5rem;
}

/* ---------- Diary: filter pills ---------- */

.filter-row {
  position: sticky;
  top: var(--topbar-height);
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.875rem;
  padding: 0.6rem 0;
  background: var(--color-bg);
}

.filter-row-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.filter-pills {
  display: flex;
  gap: 0.5rem;
}

.date-range-form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.date-range-form select {
  padding: 0.42rem 0.7rem;
  border-radius: 100px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-sunken);
  color: var(--color-text-dim);
  font-size: 0.78rem;
  font-weight: 600;
}

.filter-date-apply {
  padding: 0.3rem 0.7rem;
  font-size: 0.72rem;
}

.no-js .filter-date-apply {
  display: inline-flex !important;
}

.active-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: -0.4rem 0 1rem;
}

.active-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 32px;
  padding: 0.3rem 0.75rem;
  border-radius: 100px;
  background: var(--color-accent-wash);
  border: 1px solid var(--color-accent);
  color: var(--color-accent-dim);
  font-size: 0.74rem;
  font-weight: 600;
}

.active-filter-chip:hover {
  background: var(--color-accent);
  color: var(--color-accent-ink);
  text-decoration: none;
}

.filter-pill {
  padding: 0.44rem 0.875rem;
  border-radius: 100px;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-dim);
  font-size: 0.78rem;
  font-weight: 600;
}

.filter-pill:hover {
  color: var(--color-text);
  text-decoration: none;
}

.filter-pill:focus-visible {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

.filter-pill.is-active {
  border-color: var(--color-accent);
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

.filter-result-count {
  font-size: 0.78rem;
  color: var(--color-text-dim);
}

/* Shown only while a non-date sort is active, since that quietly turns off the
   month grouping (Occam's Razor -- name the side effect rather than hide it). */
.sort-note {
  margin: 0 0 1rem;
  font-size: 0.8rem;
  color: var(--color-text-dim);
}

/* ---------- Diary: hero card ---------- */

.diary-hero-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.125rem;
}

.diary-hero-card {
  flex: 2 1 320px;
  min-width: 0;
  padding: 1.375rem;
  border-radius: var(--radius);
  border: 1px solid oklch(0.78 0.13 75 / 0.28);
  background: linear-gradient(135deg, oklch(0.24 0.03 75), oklch(0.21 0.02 75) 62%);
}

.diary-hero-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  /* Same accent-tinted label color as .stat-card--accent .stat-label. */
  color: oklch(0.75 0.03 75);
}

.diary-hero-figures {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem;
  margin-top: 0.4rem;
}

.diary-hero-value {
  /* Deliberately larger than the standard Stat step (1.875rem) -- this is the
     one hero figure per row (see DESIGN.md's Accent variant), and the
     fix this replaces was exactly that it read at the same weight as the
     secondary stats beside it. */
  font-size: 2.4rem;
  line-height: 1;
  font-weight: 800;
  letter-spacing: -0.03em;
  /* Same accent-tinted value color as .stat-card--accent .stat-value. */
  color: oklch(0.96 0.01 75);
}

.diary-hero-delta {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-accent-ink);
  background: var(--color-accent);
  border-radius: 999px;
  padding: 0.2rem 0.6rem;
  white-space: nowrap;
}

.diary-hero-spark {
  width: 100%;
  height: 62px;
  display: block;
  margin-top: 1.125rem;
}

.diary-hero-spark-bar {
  fill: oklch(0.78 0.13 75 / 0.32);
}

.diary-hero-spark-bar.is-current {
  fill: var(--color-accent);
}

.diary-hero-spark-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 0.45rem;
  font-size: 0.68rem;
  font-family: var(--font-mono);
  /* Same muted-on-accent-card color as .stat-card--accent .stat-subline. */
  color: oklch(0.75 0.03 75);
}

/* Forward-looking "this month vs last" line on the hero card (Goal-Gradient). */
.diary-hero-momentum {
  margin: 0.75rem 0 0;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-accent-dim);
}

.diary-hero-side {
  flex: 1 1 260px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.diary-side-stat {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border-radius: 14px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}

.diary-side-stat-text {
  min-width: 0;
}

.diary-side-stat-label {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-dim);
}

.diary-side-stat-sub {
  display: block;
  font-size: 0.74rem;
  color: var(--color-text-dim);
  margin-top: 0.2rem;
}

.diary-side-stat-value {
  font-size: 1.35rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--color-text);
  white-space: nowrap;
}

/* ---------- Diary: row list ---------- */

/* Instant filter/sort/pagination (setupDiaryPjax) swaps this region in place;
   while the fetch is out, dim it and lock out further clicks. Focus outline is
   suppressed because the container only takes focus programmatically after a
   pager step, to move the reader to the top of the new results. */
.diary-results {
  transition: opacity 0.12s ease;
}

.diary-results.is-loading {
  opacity: 0.55;
  pointer-events: none;
}

.diary-results:focus {
  outline: none;
}

.diary-list {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface-sunken);
}

/* No `overflow: hidden` here -- it clipped each row's `···` actions dropdown,
   most visibly the last (or only) row's, whose menu opens down past the
   container's bottom edge and lost its "Delete" item. The frame's rounded
   corners are kept tidy by rounding the first/last child instead, so a row's
   hover fill still can't bleed past them. */
.diary-month:first-child > :first-child {
  border-top-left-radius: var(--radius);
  border-top-right-radius: var(--radius);
}

.diary-month:last-child > :last-child {
  border-bottom-left-radius: var(--radius);
  border-bottom-right-radius: var(--radius);
}

.diary-month-header {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 1rem;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.diary-month-title {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-dim);
}

.diary-month-figures {
  display: flex;
  gap: 0.875rem;
  align-items: center;
  font-size: 0.72rem;
  font-family: var(--font-mono);
  color: var(--color-text-dim);
}

.diary-month-saved {
  color: var(--color-accent-dim);
  font-weight: 600;
}

.diary-row {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.875rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--color-border);
}

.diary-month:last-child .diary-row:last-child {
  border-bottom: none;
}

.diary-row:hover,
.diary-row:has(:focus-visible) {
  background: var(--color-surface-raised);
}

/* Collapse animation while a delete sits in its 5s undo window. Height is set
   inline by JS (measured -> 0); reduced-motion users skip straight to hidden. */
.diary-row.is-removing {
  overflow: hidden;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
  border-bottom-width: 0;
  transition: height 0.25s ease, opacity 0.18s ease, padding 0.25s ease;
}

.diary-row-poster,
.diary-row-poster-placeholder {
  flex: 0 0 auto;
  width: 40px;
  height: 58px;
  border-radius: 6px;
  object-fit: cover;
  background: var(--color-surface-raised);
}

.diary-row-poster-placeholder {
  background: repeating-linear-gradient(
    135deg,
    var(--color-surface-raised) 0,
    var(--color-surface-raised) 5px,
    var(--color-border) 5px,
    var(--color-border) 10px
  );
}

.diary-row-title {
  flex: 4 1 220px;
  min-width: 0;
}

.diary-row-film {
  display: block;
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--color-text);
  overflow-wrap: anywhere;
}

a.diary-row-film {
  text-decoration: none;
}

a.diary-row-film:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.diary-row-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.25rem;
  font-size: 0.75rem;
  color: var(--color-text-dim);
  overflow-wrap: anywhere;
}

.diary-row-date {
  font-family: var(--font-mono);
}

.diary-row-seat {
  font-family: var(--font-mono);
  color: var(--color-text-dim);
}

.diary-row-paid,
.diary-row-saved {
  flex: 1 1 100px;
  min-width: 0;
}

.diary-row-micro {
  display: block;
  margin-bottom: 0.2rem;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-text-dim);
}

.diary-row-paid-value {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.84rem;
  color: var(--color-text-dim);
}

.diary-row-paid-secondary {
  display: block;
  margin-top: 0.1rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--color-text-dim);
  text-decoration: line-through;
}

.diary-row-paid-secondary.diary-row-paid-note {
  text-decoration: none;
  font-style: italic;
}

.diary-row-saved-value {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--color-accent-dim);
  background: var(--color-accent-wash);
  border-radius: 6px;
  padding: 0.1rem 0.5rem;
}

.diary-row-saved-negative {
  color: var(--color-text-dim);
  background: var(--color-surface-raised);
}

.diary-row-saved-none {
  font-size: 0.82rem;
  color: var(--color-text-dim);
}

.diary-row-add-price {
  display: inline-flex;
  align-items: center;
  border: 1px dashed var(--color-border-strong);
  border-radius: 7px;
  padding: 0.2rem 0.55rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--color-text-dim);
}

.diary-row-add-price:hover {
  color: var(--color-text);
  border-color: var(--color-text-dim);
  text-decoration: none;
}

/* ---------- Diary: poster grid view ---------- */

.page-header-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.view-toggle {
  display: inline-flex;
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  padding: 2px;
}

.view-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 30px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--color-text-dim);
  cursor: pointer;
}

.view-toggle-btn svg {
  width: 16px;
  height: 16px;
}

.view-toggle-btn.is-active {
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

.diary-results.is-grid .diary-list {
  border: 0;
  background: none;
  overflow: visible;
}

.diary-results.is-grid .diary-month {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1.1rem;
  padding: 0.5rem 0 1.5rem;
}

.diary-results.is-grid .diary-month-header {
  grid-column: 1 / -1;
}

.diary-results.is-grid .diary-row {
  flex-direction: column;
  align-items: stretch;
  gap: 0.4rem;
  padding: 0;
  border: 0;
}

.diary-results.is-grid .diary-row:hover {
  background: none;
}

.diary-results.is-grid .diary-row-poster,
.diary-results.is-grid .diary-row-poster-placeholder {
  width: 100%;
  height: auto;
  aspect-ratio: 2 / 3;
  border-radius: var(--radius-sm);
}

.diary-results.is-grid .diary-row-title,
.diary-results.is-grid .diary-row-saved {
  flex: none;
}

.diary-results.is-grid .diary-row-film {
  font-size: 0.82rem;
}

.diary-results.is-grid .diary-row-meta .tag {
  display: none;
}

.diary-results.is-grid .diary-row-paid,
.diary-results.is-grid .diary-row-saved .diary-row-micro {
  display: none;
}

.diary-results.is-grid .row-menu {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
}

.diary-results.is-grid .row-menu-trigger {
  background: oklch(0.15 0.005 260 / 0.6);
  border-color: transparent;
  color: var(--color-text);
}

/* ---------- Diary: bulk edit ---------- */

.cell-edit {
  display: none;
}

/* Bulk edit turns the diary list into an aligned spreadsheet-style grid: one
   sticky header, then a row per entry whose cells line up under it. The read
   layout's nested wrappers (.diary-row-title / -paid / price-fields) collapse to
   `display: contents` so every editable cell becomes a direct grid item, placed
   by an explicit `grid-column` (source order doesn't match column order). */
.diary-bulk-head { display: none; }

.diary-list.is-bulk-editing {
  --bulk-grid: minmax(140px, 1.6fr) 150px 108px 116px 116px 88px;
}

.diary-list.is-bulk-editing .diary-bulk-head {
  display: grid;
  grid-template-columns: var(--bulk-grid);
  gap: 0.75rem;
  position: sticky;
  top: 0;
  z-index: 3;
  padding: 0.6rem 1rem;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border-strong);
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-dim);
}

.diary-list.is-bulk-editing .cell-display {
  display: none;
}

.diary-list.is-bulk-editing .diary-month-header {
  grid-column: 1 / -1;
}

.diary-list.is-bulk-editing .diary-row {
  display: grid;
  grid-template-columns: var(--bulk-grid);
  gap: 0.75rem;
  align-items: center;
  padding: 0.45rem 1rem;
  background: var(--color-surface-raised);
}

.diary-list.is-bulk-editing .diary-row-poster,
.diary-list.is-bulk-editing .diary-row-poster-placeholder,
.diary-list.is-bulk-editing .diary-row-saved,
.diary-list.is-bulk-editing .row-menu {
  display: none;
}

.diary-list.is-bulk-editing .diary-row-title,
.diary-list.is-bulk-editing .diary-row-paid,
.diary-list.is-bulk-editing .bulk-edit-price-fields {
  display: contents;
}

.diary-list.is-bulk-editing .bulk-cell {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  /* Pin every cell to the row's first line: DOM order is film, date, seat,
     rewatch, price, price -- without this the default sparse auto-flow bumps the
     two price cells (columns 4-5) onto a second grid row once the cursor has
     passed them at the rewatch cell (column 6). */
  grid-row: 1;
}

.diary-list.is-bulk-editing .bulk-col-film {
  grid-column: 1;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bulk-col-film-year { color: var(--color-text-dim); font-weight: 400; }

.diary-list.is-bulk-editing .bulk-col-date { grid-column: 2; }
.diary-list.is-bulk-editing .bulk-col-seat { grid-column: 3; }
.diary-list.is-bulk-editing .bulk-col-full { grid-column: 4; }
.diary-list.is-bulk-editing .bulk-col-paid { grid-column: 5; }
.diary-list.is-bulk-editing .bulk-col-rewatch {
  grid-column: 6;
  flex-direction: row;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  color: var(--color-text-dim);
  cursor: pointer;
}

/* Header row carries the labels on wide screens -- the per-cell labels only
   reappear in the stacked narrow layout below. */
.diary-list.is-bulk-editing .bulk-edit-field-label { display: none; }

@media (max-width: 760px) {
  .diary-list.is-bulk-editing .diary-bulk-head { display: none; }
  .diary-list.is-bulk-editing .diary-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem 0.9rem;
    padding: 0.75rem 1rem;
  }
  .diary-list.is-bulk-editing .bulk-cell { grid-column: auto; }
  .diary-list.is-bulk-editing .bulk-col-film {
    flex-basis: 100%;
    white-space: normal;
  }
  .diary-list.is-bulk-editing .bulk-edit-field-label { display: block; }
}

.bulk-edit-hint {
  display: none;
  margin: -0.5rem 0 1rem;
  font-size: 0.78rem;
  color: var(--color-text-dim);
}

/* "N entries have no price" nudge above the diary list (Zeigarnik). */
.diary-nudge {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  margin: 0 0 1.5rem;
  padding: 0.7rem 0.9rem;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}

.diary-nudge svg {
  flex-shrink: 0;
  width: 17px;
  height: 17px;
  margin-top: 0.12rem;
  color: var(--color-text-dim);
}

.bulk-edit-hint kbd {
  padding: 0.05rem 0.4rem;
  border-radius: 6px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-raised);
  font: inherit;
  font-size: 0.72rem;
}

.bulk-edit-field {
  display: none;
  flex-direction: column;
  gap: 0.2rem;
}

.bulk-edit-field-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-dim);
}

.bulk-edit-input {
  width: 100%;
  max-width: 128px;
  padding: 0.32rem 0.5rem;
  border-radius: 6px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  font-size: 0.8rem;
}

/* In the aligned grid the input fills its column; the 128px cap is only for the
   old stacked layout. */
.diary-list.is-bulk-editing .bulk-edit-input {
  max-width: none;
}

.bulk-edit-input:focus {
  border-color: var(--color-accent);
}

/* Live validation as the user types, rather than only surfacing a bad row
   after the whole batch is submitted -- toggled by setupBulkEdit() in
   app.js off the input's own HTML5 constraint-validation state. */
.bulk-edit-input.is-invalid {
  border-color: var(--color-danger);
}

.bulk-edit-input.is-invalid:focus {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 1px var(--color-danger);
}

.bulk-edit-price-fields {
  display: none;
  flex-direction: column;
  gap: 0.5rem;
}

.bulk-edit-rewatch {
  display: none;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  color: var(--color-text-dim);
  cursor: pointer;
}

.bulk-edit-rewatch input {
  width: 15px;
  height: 15px;
}

[data-bulk-edit-toggle] svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

[data-bulk-edit-toggle][aria-pressed="true"] {
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
  border-color: var(--color-accent);
}

.row-menu {
  position: relative;
  display: flex;
  justify-content: flex-end;
}

.row-menu-trigger {
  position: relative;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  /* A real hairline at rest, not transparent -- previously invisible until
     hover, so the control had no resting affordance at all. */
  border: 1px solid var(--color-border);
  background: none;
  /* text-faint measured 2.26:1 on this row background, under the 4.5:1
     minimum; text-dim clears it here at 4.84:1 (the row surface is dark
     enough -- see --color-text-dim-strong above for the lighter-surface
     case this token doesn't cover). */
  color: var(--color-text-dim);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.row-menu-trigger::after {
  /* Invisible hit-area extension to the 44x44px touch-target minimum
     without inflating the visible glyph or the row's height/density. */
  content: "";
  position: absolute;
  inset: -8px;
}

.row-menu-trigger:hover,
.row-menu-trigger[aria-expanded="true"] {
  color: var(--color-text);
  background: var(--color-surface-raised);
  border-color: var(--color-border-strong);
}

.row-menu-dropdown {
  position: absolute;
  top: calc(100% + 0.3rem);
  right: 0;
  min-width: 160px;
  padding: 0.35rem;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
  z-index: 15;
}

.row-menu-dropdown[hidden] {
  display: none;
}

.row-menu-form {
  display: contents;
}

.row-menu-item {
  display: block;
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: none;
  background: none;
  border-radius: 6px;
  color: var(--color-text);
  font: inherit;
  font-size: 0.8rem;
  text-align: left;
  cursor: pointer;
}

.row-menu-item:hover {
  background: var(--color-surface);
  text-decoration: none;
}

.row-menu-item-danger {
  color: var(--color-danger);
}

.row-menu-item-danger:hover {
  background: var(--color-danger-bg);
}

.row-menu-divider {
  height: 1px;
  margin: 0.3rem 0.2rem;
  background: var(--color-border);
}

.no-js .row-menu-trigger {
  display: none;
}

.no-js .row-menu-dropdown {
  display: flex !important;
  position: static !important;
  flex-direction: row;
  flex-wrap: wrap;
  box-shadow: none;
  min-width: 0;
}

.no-js .row-menu-divider {
  display: none;
}

.tag {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  font-size: 0.76rem;
  color: var(--color-text-dim-strong);
}

a.tag:hover {
  color: var(--color-text);
  border-color: var(--color-border-strong);
  text-decoration: none;
}

a.tag.is-active {
  background: var(--color-accent-wash);
  border-color: var(--color-accent);
  color: var(--color-accent-dim);
}

.tag-highlight {
  color: var(--color-text);
}

.pagination {
  display: flex;
  justify-content: center;
  gap: 1rem;
  margin-top: 2rem;
  font-size: 0.85rem;
}

/* ---------- Search / results ---------- */

.search-eyebrow {
  text-align: center;
  margin: 0 0 1rem;
}

.search-hero {
  position: relative;
  max-width: 640px;
  margin: 0 auto 2.5rem;
}

.search-hero-form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  padding: 0.4rem 0.4rem 0.4rem 1.1rem;
}

.search-hero-form:focus-within {
  border-color: var(--color-accent);
}

.search-hero-form:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

.search-hero-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: var(--color-text-dim);
}

.search-hero-form input {
  flex: 1;
  border: none;
  background: none;
  padding: 0.7rem 0;
  font-size: 1.1rem;
  color: var(--color-text);
}


.search-hero-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: none;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-size: 0;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.15s ease;
}

.search-hero-submit::before {
  content: "";
  display: block;
  width: 16px;
  height: 16px;
  background: currentColor;
  -webkit-mask: 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'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: 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'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") center / contain no-repeat;
}

.search-hero-submit:hover {
  background: var(--color-accent-bright);
}

.film-suggestions {
  position: absolute;
  z-index: 10;
  top: 100%;
  left: 0;
  right: 0;
  margin: 0.5rem 0 0;
  padding: 0.4rem;
  list-style: none;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
  max-height: 22rem;
  overflow-y: auto;
}

.film-suggestion {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.film-suggestion:hover {
  background: var(--color-surface-sunken);
}

/* Status row (searching / no matches / unreachable) -- not a result, so no
   hover affordance and no pointer. */
.film-suggestion--status,
.film-suggestion--status:hover {
  cursor: default;
  background: none;
  color: var(--color-text-dim);
  font-size: 0.85rem;
}

.film-suggestion img,
.film-suggestion-poster-placeholder {
  width: 32px;
  height: 48px;
  border-radius: 4px;
  object-fit: cover;
  background: var(--color-surface-sunken);
  flex-shrink: 0;
}

.film-suggestion-title {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text);
}

.film-suggestion-year {
  font-size: 0.78rem;
  color: var(--color-text-dim);
}

.results-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 1.25rem;
}

.result-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color 0.15s ease;
}

.result-card:hover {
  border-color: var(--color-accent);
}

.result-card a {
  display: block;
  color: var(--color-text);
}

.result-card a:hover {
  text-decoration: none;
}

.result-poster {
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  background: var(--color-surface-raised);
}

.result-poster-placeholder {
  width: 100%;
  aspect-ratio: 2 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface-raised);
  color: var(--color-text-dim);
  font-size: 0.75rem;
  text-align: center;
  padding: 0.5rem;
}

.result-info {
  padding: 0.65rem 0.75rem;
}

.result-title {
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.3;
}

.result-year {
  font-size: 0.78rem;
  color: var(--color-text-dim);
}

/* ---------- Add / edit entry (confirm screen) ---------- */

.confirm-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 2.5rem;
  max-width: 900px;
}

.confirm-poster {
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
}

.confirm-poster-placeholder {
  width: 100%;
  aspect-ratio: 2 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  color: var(--color-text-dim);
  font-size: 0.8rem;
  text-align: center;
  padding: 0.75rem;
}

.confirm-film-title {
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  margin: 0 0 0.25rem;
}

.confirm-film-meta {
  color: var(--color-text-dim);
  font-size: 0.85rem;
  margin: 0 0 1.25rem;
}

.image-credit {
  margin: 0.5rem 0 0;
  font-size: 0.7rem;
  color: var(--color-text-dim);
  text-align: center;
}

.image-credit a {
  color: var(--color-text-dim);
  text-decoration: underline;
}

/* ---------- Cinema / streaming toggle ---------- */

.segmented {
  display: inline-flex;
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  overflow: hidden;
}

.segmented-option {
  position: relative;
  padding: 0.5rem 1.4rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text-dim);
  cursor: pointer;
}

.segmented-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.segmented-option.is-active {
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-weight: 700;
}

.segmented-option:focus-within {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

.venue-panel {
  display: grid;
  gap: 1rem;
}

.venue-panel[hidden] {
  display: none;
}

/* Inline "you could be saving here" prompt under the cinema picker. */
.venue-membership-hint {
  margin: -0.35rem 0 0;
  padding: 0.6rem 0.75rem;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--color-text);
  background: var(--color-accent-wash);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-sm);
}

.venue-membership-hint[hidden] {
  display: none;
}

/* An inline text button that reads as a link -- used inside the membership
   hint for the one-tap "0 if the membership covered it". */
.link-button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.link-button:hover {
  color: var(--color-accent-bright);
}

/* ---------- Date quick chips ---------- */

.date-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.6rem;
}

.date-chip {
  padding: 0.34rem 0.75rem;
  border-radius: 100px;
  border: 1px solid var(--color-border-strong);
  background: transparent;
  color: var(--color-text-dim);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
}

.date-chip:hover {
  color: var(--color-text);
}

.date-chip[aria-pressed="true"] {
  border-color: var(--color-accent);
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

/* ---------- Price fields ---------- */

.price-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

/* Live "you saved" readout under the price fields -- recalculates as the user
   types, so the reward figure is visible before the entry is even saved. */
.saving-preview {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text-dim);
}

.saving-preview[data-tone="positive"] {
  color: var(--color-accent-dim);
}

.saving-preview[data-tone="negative"] {
  color: var(--color-danger);
}

/* ---------- Tag input ---------- */

.tag-input {
  position: relative;
}

.tag-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.5rem;
}

.tag-chips:empty {
  margin-bottom: 0;
}

.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.55rem;
  border-radius: 999px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  font-size: 0.8rem;
  color: var(--color-text);
}

.tag-chip button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  /* Negative margin keeps the visible chip the same size while the button
     itself is a real box; ::after takes the tap target past the 24px AA
     minimum without overlapping the neighbouring chip. */
  margin: -0.3rem -0.35rem -0.3rem 0;
  border-radius: 999px;
  background: none;
  border: none;
  color: var(--color-text-dim);
  cursor: pointer;
  font-size: 0.95rem;
  line-height: 1;
  padding: 0;
}

.tag-chip button::after {
  content: "";
  position: absolute;
  inset: -6px;
}

.tag-chip button:hover {
  color: var(--color-danger);
}

.tag-suggestions,
.combobox-list {
  position: absolute;
  z-index: 10;
  top: 100%;
  left: 0;
  right: 0;
  margin: 0.25rem 0 0;
  padding: 0.3rem;
  list-style: none;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
  max-height: 200px;
  overflow-y: auto;
}

.tag-suggestions li,
.combobox-option {
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.88rem;
}

.tag-suggestions li:hover,
.combobox-option:hover,
.combobox-option.is-active {
  background: var(--color-surface-sunken);
  color: var(--color-accent-bright);
}

/* Type-to-search venue picker -- shares the tag field's dropdown look so
   "choose a cinema", "choose a service" and "add a new one" all read as the
   same control (Law of Similarity). */
.combobox {
  position: relative;
}

.combobox-input {
  width: 100%;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 0.65rem 0.8rem;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.95rem;
}

.combobox-input:focus {
  border-color: var(--color-accent);
}

.combobox-option[aria-selected="true"] {
  font-weight: 600;
  color: var(--color-accent-dim);
}

.combobox-option--add {
  border-top: 1px solid var(--color-border);
  margin-top: 0.2rem;
  padding-top: 0.5rem;
  color: var(--color-text-dim);
  font-weight: 600;
}

.combobox-option--add:hover,
.combobox-option--add.is-active {
  color: var(--color-accent-bright);
}

.combobox-option--empty {
  color: var(--color-text-dim);
  cursor: default;
  font-size: 0.85rem;
}

/* ---------- Admin: cinema review-queue cells ---------- */

.cinema-review-cell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
  min-width: 190px;
}

.cinema-review-cell > select:not([data-combobox]),
.cinema-review-cell > .combobox {
  width: 100%;
}

.cinema-review-cell .combobox-input {
  padding: 0.4rem 0.6rem;
  font-size: 0.85rem;
}

/* The list is absolutely positioned to the narrow cell -- let it break out so
   long cinema names stay readable. */
.cinema-review-cell .combobox-list {
  min-width: 260px;
}

.cinema-review-cell-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

/* ---------- Stats ---------- */

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}

.stats-grid-2x2 {
  grid-template-columns: repeat(2, 1fr);
}

/* Period picker (All time / By year / By month) -- reuses the diary's
   .filter-pills + .date-range-form controls, just in its own row. */
.stats-period-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

.stats-period-empty {
  margin-bottom: 1.75rem;
}

/* Single-month view: no timeline (a line needs >1 period), so the chart card
   shows the month's figure as plain text instead. */
.stats-month-figure {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 1.25rem 0 0.5rem;
}

.stats-month-figure-value {
  font-size: 2.4rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--color-text);
}

.stats-month-figure-label {
  font-size: 0.8rem;
  color: var(--color-text-dim);
}

.stats-hero-row {
  display: grid;
  grid-template-columns: 1.55fr 1fr;
  gap: 1rem;
  margin-bottom: 1rem;
}

/* Progressive disclosure: with no side column yet (projection + best-value both
   still locked), the chart card takes the full width rather than leaving a gap. */
.stats-hero-row--solo,
.stats-secondary-row--solo {
  grid-template-columns: 1fr;
}

.stats-hero-side {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.stats-secondary-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin-bottom: 1.75rem;
}

/* One quiet line explaining what's still locked and why -- so an absent section
   reads as "not yet", not "missing". */
.stats-locked-note {
  margin: -0.5rem 0 1.75rem;
  font-size: 0.82rem;
  color: var(--color-text-dim);
}

.stats-chart-card {
  display: flex;
  flex-direction: column;
}

.stats-chart-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.stats-chart-header-actions {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
}

.stats-delta-pill {
  padding: 0.3rem 0.7rem;
  border-radius: 100px;
  background: var(--color-success-bg);
  color: var(--color-accent-dim);
  font-size: 0.74rem;
  font-weight: 700;
  white-space: nowrap;
}

.stats-toggle-pill {
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: 100px;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
}

.stats-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  cursor: pointer;
  border-radius: 100px;
  padding: 0.3rem 0.7rem;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  background: none;
  color: var(--color-text-dim);
}

/* Some toggle buttons are real <a> links (chart granularity -- a server
   round-trip), some are <button>s (metric swap -- client-side). Same look. */
a.stats-toggle-btn,
a.stats-toggle-btn:hover {
  text-decoration: none;
}

.stats-toggle-btn.is-active {
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

.stats-toggle-btn:focus-visible {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

.stats-chart {
  width: 100%;
  height: 140px;
  display: block;
}

.stats-chart-gridline {
  stroke: var(--color-border);
  stroke-width: 1;
}

.stats-chart-area {
  stroke: none;
}

.stats-chart-gradient-start {
  stop-color: var(--color-accent);
  stop-opacity: 0.35;
}

.stats-chart-gradient-end {
  stop-color: var(--color-accent);
  stop-opacity: 0;
}

.stats-chart-line {
  stroke: var(--color-accent);
  stroke-width: 2;
}

.stats-chart-dot {
  fill: var(--color-accent);
}

.stats-chart-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 0.5rem;
  font-size: 0.68rem;
  color: var(--color-text-dim);
}

.stats-chart-empty {
  color: var(--color-text-dim);
  font-size: 0.85rem;
  margin: 1rem 0 0;
}

.stats-best-value-card {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.stats-best-value-body {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  margin-top: 0.5rem;
}

.stats-best-value-poster,
.stats-best-value-poster-placeholder {
  flex-shrink: 0;
  width: 44px;
  height: 64px;
  border-radius: 6px;
  object-fit: cover;
  background: var(--color-surface-raised);
}

.stats-best-value-poster-placeholder {
  background: repeating-linear-gradient(
    135deg,
    var(--color-surface-raised) 0,
    var(--color-surface-raised) 5px,
    var(--color-border) 5px,
    var(--color-border) 10px
  );
}

.stats-best-value-title {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--color-text);
}

.stats-best-value-venue {
  font-size: 0.76rem;
  color: var(--color-text-dim);
  margin-top: 0.15rem;
}

.stats-best-value-saved {
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--color-accent-dim);
  margin-top: 0.35rem;
}

.stats-venue-card {
  display: flex;
  flex-direction: column;
}

.stats-venue-rows {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  margin-top: 0.75rem;
}

.stats-venue-row-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.3rem;
}

.stats-venue-row-label {
  font-weight: 700;
  font-size: 0.82rem;
  color: var(--color-text);
}

.stats-venue-row-figures {
  font-size: 0.72rem;
  color: var(--color-text-dim);
}

.stats-venue-bar {
  width: 100%;
  height: 8px;
  display: block;
}

.stats-venue-bar-track {
  fill: var(--color-surface-raised);
}

.stats-venue-bar-spent {
  fill: var(--color-text-dim);
}

.stats-venue-bar-saved {
  fill: var(--color-accent);
}

.stats-venue-legend {
  display: flex;
  gap: 1rem;
  margin-top: 1rem;
  font-size: 0.72rem;
  color: var(--color-text-dim);
}

.stats-legend-swatch {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-right: 0.3rem;
}

.stats-legend-swatch-spent {
  background: var(--color-text-dim);
}

.stats-legend-swatch-saved {
  background: var(--color-accent);
}

.stats-percentile-card {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  padding: 1.75rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.stats-percentile-ring {
  width: 80px;
  height: 80px;
  flex-shrink: 0;
  transform: rotate(-90deg);
}

.stats-percentile-ring-track {
  fill: none;
  stroke: var(--color-surface-raised);
  stroke-width: 6;
}

.stats-percentile-ring-fill {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 6;
  stroke-linecap: round;
}

.stats-percentile-ring-text {
  fill: var(--color-text);
  font-size: 0.95rem;
  font-weight: 800;
  transform: rotate(90deg);
  transform-origin: 40px 40px;
}

.stats-percentile-headline {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--color-text);
}

.stats-percentile-caption {
  margin: 0.35rem 0 0;
  color: var(--color-text-dim);
  font-size: 0.85rem;
}

.stat-card {
  padding: 1.25rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.stat-card--accent {
  background: linear-gradient(135deg, oklch(0.24 0.03 75), oklch(0.21 0.02 75));
  border-color: oklch(0.3 0.03 75 / 0.5);
}

.stat-value {
  display: block;
  font-size: 1.875rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--color-text);
  line-height: 1;
}

.stat-card--accent .stat-value {
  color: oklch(0.96 0.01 75);
}

.stat-label {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-dim);
}

.stat-card--accent .stat-label {
  color: oklch(0.75 0.03 75);
}

.stat-subline {
  margin-top: 0.3rem;
  font-size: 0.75rem;
  color: var(--color-text-dim);
}

.stat-card--accent .stat-subline {
  color: oklch(0.75 0.03 75);
}

.stats-section {
  margin-bottom: 2rem;
}

.stats-section:last-child {
  margin-bottom: 0;
}

.stats-section-title {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-text-dim);
  margin: 0 0 1rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--color-border);
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 1rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--color-border);
}

.section-header .stats-section-title {
  margin: 0;
  padding: 0;
  border: none;
}

/* ---------- Stats sub-navigation ---------- */

.stats-subnav {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--color-border);
}

.stats-subnav-tab {
  padding: 0.4rem 0.8rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--color-text-dim);
}

.stats-subnav-tab:hover {
  text-decoration: none;
  color: var(--color-text);
}

.stats-subnav-tab.is-active {
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

/* "Membership value →" link on the Overview page, and its mirror back. */
.stats-cross-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-size: 0.85rem;
  font-weight: 600;
}

.stats-cross-link:hover {
  text-decoration: none;
  border-color: var(--color-accent);
  color: var(--color-accent-dim);
}

.stats-cross-link svg {
  flex-shrink: 0;
  color: var(--color-text-dim);
}

.stats-cross-link:hover svg {
  color: var(--color-accent);
}

/* Aggregate card on the Membership value page (period views only). */
.stats-value-summary {
  margin-bottom: 1.25rem;
}

.stats-value-summary--profit .stat-value {
  color: var(--color-accent-dim);
}

.stats-delta-line {
  margin-top: 0.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-accent-dim);
}

/* ---------- Membership return ---------- */

.stats-return-summary {
  font-size: 0.78rem;
  color: var(--color-text-dim);
}

.stats-return-summary.is-profit {
  color: var(--color-accent-dim);
}

.stats-return-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
}

.stats-return-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.9rem;
}

.stats-return-plan {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-text);
  line-height: 1.3;
}

.stat-card--accent .stats-return-plan {
  color: oklch(0.96 0.01 75);
}

.stats-return-chain {
  margin-top: 0.15rem;
  font-size: 0.75rem;
  color: var(--color-text-dim);
}

.stat-card--accent .stats-return-chain {
  color: oklch(0.75 0.03 75);
}

.stats-return-badge {
  flex-shrink: 0;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--color-surface-raised);
  color: var(--color-text-dim);
}

.stats-return-badge.is-profit {
  background: var(--color-accent);
  color: var(--color-accent-ink);
}

.stats-return-period {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.7rem;
  font-size: 0.72rem;
  color: var(--color-text-dim);
}

.stat-card--accent .stats-return-period {
  color: oklch(0.75 0.03 75);
}

.stats-return-period-tag {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text);
}

.stat-card--accent .stats-return-period-tag {
  color: oklch(0.96 0.01 75);
}

.stats-return-value {
  font-size: 1.875rem;
}

.stats-return-subline {
  margin-top: 0.3rem;
  font-size: 0.75rem;
  color: var(--color-text-dim);
}

.stat-card--accent .stats-return-subline {
  color: oklch(0.75 0.03 75);
}

.stats-return-bar {
  display: block;
  width: 100%;
  height: 6px;
  margin-top: 0.85rem;
}

.stats-return-bar-track {
  fill: var(--color-surface-raised);
}

.stat-card--accent .stats-return-bar-track {
  fill: oklch(0.3 0.03 75 / 0.5);
}

.stats-return-bar-fill {
  fill: var(--color-text-dim);
}

.stats-return-bar-fill.is-profit {
  fill: var(--color-accent);
}

.stats-return-foot {
  margin-top: 0.55rem;
  font-size: 0.72rem;
  color: var(--color-text-dim);
}

.stat-card--accent .stats-return-foot {
  color: oklch(0.75 0.03 75);
}

.stats-return-nudge {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--color-text-dim);
}

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

.admin-subnav {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.75rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--color-border);
}

.admin-subnav-group {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-left: 1.25rem;
  border-left: 1px solid var(--color-border);
}

.admin-subnav a {
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.82rem;
  color: var(--color-text-dim);
}

.admin-subnav a:hover {
  text-decoration: none;
  color: var(--color-text);
}

.admin-subnav a.is-active {
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

/* Neutral "heads up" note on an admin page -- distinct from a red error flash,
   which this state is not. */
.admin-notice {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  margin: 0 0 1.5rem;
  padding: 0.7rem 0.9rem;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}

.admin-notice svg {
  flex-shrink: 0;
  margin-top: 0.1rem;
  color: var(--color-text-dim);
}

/* ---------- Admin: currency rates ---------- */

.currency-rates-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: flex-start;
}

.currency-rate-grid {
  display: grid;
  /* 1 column on narrow viewports; 2-3 as width allows. */
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 0.85rem;
  width: 100%;
}

.currency-rate-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}

.currency-rate-card.is-base {
  background: var(--color-surface-sunken);
}

.currency-rate-card.is-placeholder {
  border-color: var(--color-review, var(--color-border-strong));
}

.currency-rate-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.currency-rate-code {
  font-weight: 700;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--color-text);
}

.currency-rate-symbol {
  color: var(--color-text-dim);
  font-size: 0.95rem;
}

.currency-rate-flag {
  margin-left: auto;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-review, var(--color-text-dim));
}

.currency-rate-tag {
  font-size: 0.72rem;
  color: var(--color-text-dim);
}

.currency-rate-input-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.currency-rate-eq {
  font-size: 0.78rem;
  color: var(--color-text-dim);
  white-space: nowrap;
}

.currency-rate-input-row input,
.currency-rate-input {
  width: 100%;
  min-width: 0;
  padding: 0.4rem 0.55rem;
  border-radius: 6px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font: inherit;
  font-family: var(--font-mono);
  font-size: 0.85rem;
}

.currency-rate-input.is-error { border-color: var(--color-danger); }
.currency-rate-input:focus { outline: 2px solid var(--color-accent); outline-offset: 1px; }

.currency-rate-unit {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--color-text-dim);
}

/* ---------- Admin: needs-attention + at-a-glance ---------- */

.admin-attention {
  margin-bottom: 1.75rem;
}

.admin-attention-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.875rem;
  padding: 1rem 1.125rem;
  border-radius: 14px;
  border: 1px solid oklch(0.78 0.13 75 / 0.26);
  background: linear-gradient(120deg, oklch(0.78 0.13 75 / 0.1), transparent 60%), var(--color-surface);
}

.admin-attention-item + .admin-attention-item {
  margin-top: 0.75rem;
}

.admin-attention-text {
  flex: 1 1 260px;
  min-width: 0;
}

.admin-attention-title {
  display: block;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--color-text);
}

.admin-attention-detail {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.8rem;
  color: var(--color-text-dim);
}

.admin-attention-cta {
  flex: 0 0 auto;
}

.admin-attention-clear {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0;
  padding: 0.9rem 1.125rem;
  border-radius: 14px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  font-size: 0.88rem;
  color: var(--color-text-dim);
}

.admin-attention-clear svg {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--color-accent-dim);
}

.admin-glance {
  margin-bottom: 1.75rem;
}

.admin-glance-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1px;
  margin: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--color-border);
}

.admin-glance-grid > div {
  background: var(--color-surface);
  padding: 0.85rem 1rem;
}

.admin-glance-grid dt {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-dim);
}

.admin-glance-grid dd {
  margin: 0.25rem 0 0;
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--color-text);
}

.admin-glance-grid dd.admin-glance-flag {
  color: var(--color-accent);
}

.admin-activity-card {
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  overflow: hidden;
}

.admin-activity-header {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1.125rem;
  border-bottom: 1px solid var(--color-border);
}

.admin-activity-title {
  margin: 0;
  padding: 0;
  border: none;
}

.admin-activity-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
  align-items: center;
  padding: 0.75rem 1.125rem;
  border-bottom: 1px solid var(--color-border);
}

.admin-activity-row:last-child {
  border-bottom: none;
}

.admin-activity-dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-accent);
}

.admin-activity-text {
  flex: 3 1 240px;
  min-width: 0;
  font-size: 0.85rem;
  color: var(--color-text-dim);
}

.admin-activity-time {
  flex: 1 1 90px;
  font-size: 0.74rem;
  font-family: var(--font-mono);
  color: var(--color-text-dim);
}

.admin-activity-empty {
  padding: 1rem 1.125rem;
  margin: 0;
}

.breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 1.25rem;
  font-size: 0.85rem;
  color: var(--color-text-dim);
}

.breadcrumbs a {
  color: var(--color-text-dim);
}

.breadcrumbs a:hover {
  color: var(--color-text);
}

.breadcrumb-sep {
  color: var(--color-border);
}

.breadcrumb-current {
  color: var(--color-text);
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.admin-table th,
.admin-table td {
  padding: 0.75rem 1rem;
  text-align: left;
  /* Wraps in place rather than forcing the whole table wider (and the row
     into horizontal scroll) -- the same overflow-wrap: anywhere protection
     the diary table applies to its own free-text cells, now applied
     consistently here instead of via a different mechanism. Short cells
     (dates, counts, badges) never reach their wrap point, so this is only
     visible where a long user-entered name actually needs it. */
  overflow-wrap: anywhere;
}

.admin-table th {
  background: var(--color-surface-raised);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-text-dim);
}

.admin-table tbody tr:not(:last-child) {
  border-bottom: 1px solid var(--color-border);
}

.admin-table tbody tr:hover {
  background: var(--color-surface-raised);
}

.cell-mono {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--color-text-dim);
}

/* Secondary line under a table cell's main value (e.g. "+ covers Group 1",
   an effective-count aside). */
.cell-sub {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--font-sans);
  font-size: 0.72rem;
  color: var(--color-text-dim);
}

/* Read-only "this tier also reaches these through a nested tier" panel on the
   group-cinemas admin page. */
.group-inherited-note {
  margin: 0 0 1.25rem;
  padding: 0.7rem 0.9rem;
  font-size: 0.82rem;
  line-height: 1.5;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}

.group-inherited-note p {
  margin: 0;
}

.group-inherited-note p + p {
  margin-top: 0.4rem;
}

.btn-danger-text {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--color-danger);
  cursor: pointer;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.8rem;
}

.btn-danger-text:hover {
  text-decoration: underline;
}

.btn-secondary-text {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--color-accent);
  cursor: pointer;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.8rem;
}

.btn-secondary-text:hover {
  text-decoration: underline;
}

/* ---------- Error pages ---------- */

.error-page {
  text-align: center;
  padding: 5rem 1.5rem;
}

.error-code {
  font-size: 4rem;
  font-weight: 800;
  color: var(--color-accent);
  margin: 0;
}

.error-message {
  font-size: 1rem;
  font-weight: 400;
  margin: 0 0 0.75rem;
}

.error-detail {
  max-width: 42ch;
  margin: 0 auto 1.5rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--color-text-dim);
}

.error-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: center;
  flex-wrap: wrap;
}

/* ---------- Footer ---------- */

/* One full-width band (markup in templates/_footer.html), shared by the
   authenticated app shell and the dark landing page. Three columns --
   credit | legal links | TMDB attribution -- split by hairlines, stacking
   below 900px. On desktop (>900px) it's sticky to the viewport bottom so
   it stays in view as the page scrolls; on short pages the body / .app-main
   flex column above already pins it there, and on mobile the bottom tab bar
   owns the screen edge so the in-app band is dropped (see the 900px block).
   Single typeface, hierarchy by colour only. The band takes its ground
   from whatever it sits on -- the app/guest shell's --color-bg here, and
   on the landing page a `transparent` fill (home.css) so that page's
   vignette/grain carry through -- so there's no seam where the footer
   meets the page. The warm greys below are the text ramp only.
   Spec: local_references/footer 2a/footer-brief.md */

/* Reuse of the self-hosted DM Sans already shipped for the landing page
   (home.css @font-face's it too; declared here so base.html -- which only
   loads style.css -- gets it as well). CSP font-src stays 'self'. */
@font-face {
  font-family: "DM Sans";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/dm-sans-latin.woff2") format("woff2");
}

.site-footer {
  background: var(--color-bg);
  border-top: 1px solid var(--color-border);
}

/* The landing page's own ground isn't a flat fill -- it's --home-bg under a
   vignette/grain overlay -- so home.css overrides this to `transparent` and
   lets those layers show through. See `.home .site-footer` there. */

/* Desktop: keep the band in view while the page scrolls. `sticky` (not
   `fixed`) means it still occupies its own space at the end of the flow,
   so nothing needs a bottom-padding offset and it lands flush at the true
   page end. The landing page opts out (home.css keeps it `position:
   relative`) -- that's a single marketing scroll that should end on the
   footer, not carry it the whole way down. */
@media (min-width: 901px) {
  .site-footer {
    position: sticky;
    bottom: 0;
    z-index: 5;
  }
}

.site-footer-grid {
  display: grid;
  /* Equal thirds (the brief's 1fr/auto/1.4fr left the legal column a thin
     sliver). Text stays left-aligned within each. */
  grid-template-columns: 1fr 1fr 1fr;
  font-family: "DM Sans", var(--font-sans);
}

.site-footer-col {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  padding: 30px 36px;
}

.site-footer-col-legal {
  padding: 30px 32px;
  border-left: 1px solid #1a1a18;
  border-right: 1px solid #1a1a18;
}

.site-footer-line {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.55;
  font-weight: 400;
  color: #c3c0b8;
  text-wrap: pretty;
}

.site-footer-muted {
  /* Nudged up from #6f6e69 (~3.4:1 on the near-black ground, on every page) to
     clear 4.5:1 -- the footer-brief palette otherwise stands. */
  color: #8b897f;
}

.site-footer-emoji {
  font-size: 14px;
}

/* Two classes deep on purpose: on the landing page these links also match
   home.css's `.home a` (same 0,1,1 specificity, loaded later), so a single
   `.site-footer-grid a` would lose the cascade and pick up the landing
   palette instead of the brief's exact values. */
.site-footer .site-footer-grid a {
  color: #e9b563;
  text-decoration: none;
}

.site-footer .site-footer-grid a:hover {
  color: #f6d49a;
}

/* Legal column: the whole line is the link, so it reads as primary text
   rather than an inline amber link. */
.site-footer .site-footer-col-legal a {
  color: #d8d4cb;
}

@media (max-width: 900px) {
  .site-footer-grid {
    grid-template-columns: 1fr;
  }

  .site-footer-col {
    padding: 24px 20px;
  }

  .site-footer-col-legal {
    border-left: 0;
    border-right: 0;
  }

  .site-footer-col + .site-footer-col {
    border-top: 1px solid #1a1a18;
  }
}

/* ---------- Cookie consent banner (base.html, only when GA is configured) ---------- */
/* Loads on every page, the dark landing page included, so it sticks to the shared
   style.css tokens rather than the page it happens to sit on. Hidden until
   analytics.js decides a first-time visitor needs to see it. */
/* base.html renders the banner with the `hidden` attribute and analytics.js
   toggles it (off for a first-time visitor, back on after Accept/Reject). This
   rule is what makes that attribute actually stick: `.cookie-banner`'s own
   `display: flex` below would otherwise beat the UA `[hidden]` rule and pin the
   banner on screen for every visitor, every page load, with no way to dismiss it. */
.cookie-banner[hidden] {
  display: none;
}

.cookie-banner {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  z-index: 60;
  width: min(40rem, calc(100vw - 2rem));
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.25rem;
  padding: 0.9rem 1.1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.7);
}

.cookie-banner-text {
  margin: 0;
  flex: 1 1 16rem;
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--color-text-dim-strong);
}

.cookie-banner-text a {
  color: var(--color-text-dim-strong);
  text-decoration: underline;
}

.cookie-banner-actions {
  display: flex;
  gap: 0.5rem;
  flex: 0 0 auto;
}

.cookie-banner-btn {
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--color-border-strong);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
}

.cookie-banner-btn:hover {
  border-color: var(--color-text-faint);
}

.cookie-banner-btn-accept {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-ink);
  font-weight: 600;
}

.cookie-banner-btn-accept:hover {
  background: var(--color-accent-bright);
  border-color: var(--color-accent-bright);
  color: var(--color-accent-ink);
}

@media (max-width: 480px) {
  .cookie-banner {
    bottom: 0;
    width: 100vw;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }
}

/* ---------- Responsive ---------- */

@media (max-width: 900px) {
  :root {
    --side-margin: 5%;
  }

  .app-shell {
    flex-direction: column;
  }

  /* PROFILE-BRIEF.md rule 7: interactive targets >=44px tall at touch
     widths -- 900px matches the nav-swap breakpoint below, since that's
     this app's actual touch/mobile threshold, not the narrower 640px phone
     breakpoint this rule used to be scoped to. */
  .profile-btn {
    min-height: 44px;
  }

  .profile-tier-option,
  .profile-tier-cell {
    min-height: 44px;
  }

  /* Nav swap: the sidebar becomes a fixed bottom tab bar (logo and account
     menu drop out -- Log a film becomes the .fab below, and account access
     moves to the profile page's own account-form footer Log out action) and the sticky
     desktop footer legal line is dropped for the same fixed screen edge. */
  .sidebar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    z-index: 40;
    width: 100%;
    height: auto;
    flex-direction: row;
    align-items: stretch;
    gap: 0;
    padding: 0.35rem 0.5rem calc(env(safe-area-inset-bottom, 0px) + 0.35rem);
    border-right: none;
    border-top: 1px solid var(--color-border);
    overflow-y: visible;
  }

  .sidebar-logo,
  .sidebar-user {
    display: none;
  }

  .sidebar-nav {
    flex-direction: row;
    width: 100%;
    gap: 0;
  }

  .sidebar-nav-item {
    position: relative;
    flex: 1;
    flex-direction: column;
    justify-content: center;
    gap: 0.3rem;
    min-height: 52px;
    padding: 0.4rem 0.2rem;
    /* Same size as Micro-label, not a new step, at this width. */
    font-size: 0.62rem;
    text-align: center;
  }

  .sidebar-nav-icon {
    width: 21px;
    height: 21px;
  }

  .nav-badge {
    position: absolute;
    top: 0;
    right: 22%;
    margin-left: 0;
  }

  /* Authenticated shell only: the fixed bottom tab bar (.sidebar, above)
     owns the screen edge here, so the in-app footer drops on mobile. The
     guest pages and the landing page render their footer outside .app-main
     and keep it at every width (stacked -- see .site-footer-grid). */
  .app-main .site-footer {
    display: none;
  }

  .topbar-log-btn {
    display: none;
  }

  .fab {
    display: flex;
  }

  .topbar {
    padding: 0.6rem 5%;
  }

  .topbar-search-kbd,
  .topbar-btn-kbd {
    display: none;
  }

  .page {
    padding: 1.5rem 5% calc(var(--bottom-nav-height) + 1.5rem);
  }

  .flash-list {
    padding: 1.25rem 5% 0;
  }

  .stats-hero-row,
  .stats-secondary-row {
    grid-template-columns: 1fr;
  }

  /* Touch-target floor for the page-level filter controls specifically --
     not applied to .tag, which sits at row density where a 44px pill would
     wreck the row rhythm the diary list depends on for scanability.
     .diary-row-add-price is the exception within a row: unlike .tag it's a
     real action (opens the entry to price it), not a display/filter chip. */
  .filter-pill,
  .diary-row-add-price,
  .stats-toggle-btn {
    min-height: 44px;
  }

  .date-range-form select {
    min-height: 44px;
  }
}

@media (max-width: 640px) {
  :root {
    --side-margin: 1.25rem;
  }

  .page {
    padding: 1.25rem 1.25rem calc(var(--bottom-nav-height) + 1rem);
  }

  .flash-list {
    padding: 1.25rem 1.25rem 0;
  }

  .confirm-layout {
    grid-template-columns: 1fr;
  }

  .confirm-poster,
  .confirm-poster-placeholder {
    max-width: 160px;
  }

  .search-hero-form {
    padding-left: 0.8rem;
  }

  .search-hero-form input {
    font-size: 1rem;
  }

  .auth-card {
    padding: 1.5rem;
  }

  .price-fields {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* Touch input (Fitts's Law): give the standalone pill/chip controls a
   comfortable tap height on coarse pointers without inflating the desktop
   density the sidebar system is tuned for. The diary-row filter tags are left
   alone -- they sit inline within a text line and WCAG 2.5.8's spacing
   exception covers them. */
@media (pointer: coarse) {
  .filter-pill,
  .date-chip,
  .active-filter-chip,
  .stats-toggle-btn,
  .stats-subnav-tab,
  .row-menu-item,
  .view-toggle-btn,
  .home-chip,
  .pagination a,
  .pagination span,
  .date-range-form select,
  .stats-period-bar select {
    min-height: 44px;
  }

  .filter-pill,
  .date-chip,
  .view-toggle-btn,
  .home-chip {
    display: inline-flex;
    align-items: center;
  }
}

/* ============================================================
   Savings redesign — Home (/), film detail, Memberships.
   One canonical savings object (app/services/savings.py) drawn
   several ways. Money + metadata labels are mono/uppercase;
   prose stays Inter. Every saved figure renders amber, the same
   as the diary — the One Job Rule holds across all surfaces.
   ============================================================ */

.sv-pos { color: var(--color-accent-dim); }

.sv-kicker {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-accent-dim);
}

.sv-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.5rem;
}

/* ---------- Command bar ---------- */

.home2 {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 1.5rem clamp(1rem, 4vw, 2.5rem) 3rem;
}

.cmdbar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0 1rem;
  height: 3.5rem;
  border: 1px solid var(--color-accent-wash);
  border-radius: 12px;
  background:
    linear-gradient(var(--color-surface), var(--color-surface)) padding-box,
    var(--color-accent-wash) border-box;
  box-shadow: 0 0 0 1px var(--color-accent-wash), 0 18px 40px -28px var(--color-accent);
}

.cmdbar:focus-within {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent), 0 18px 40px -24px var(--color-accent);
}

/* The input runs edge to edge inside the bar, so the keyboard-focus ring goes on
   the wrapper -- the same 2px accent-bright ring every other control in the app
   uses (see .topbar-search), not the softer 1px :focus-within treatment above. */
.cmdbar:has(.cmdbar-input:focus-visible) {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: 2px;
}

.cmdbar-kbd,
.cmdbar-enter kbd {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  padding: 0.15rem 0.4rem;
  border-radius: 6px;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-dim-strong);
  background: var(--color-surface-sunken);
}

.cmdbar-input {
  flex: 1;
  min-width: 4rem;
  border: 0;
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-mono);
  font-size: 1rem;
  outline: none;
}

.cmdbar-input::placeholder { color: var(--color-text-faint); }

.cmdbar-chips {
  display: flex;
  gap: 0.4rem;
  flex-shrink: 0;
  overflow: hidden;
  max-width: 55%;
}

.cmdbar-chip {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  padding: 0.3rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-dim-strong);
  background: var(--color-surface-sunken);
}

.cmdbar-chip--film { color: var(--color-text); border-color: var(--color-border-strong); }
.cmdbar-chip--price { color: var(--color-positive); border-color: var(--color-positive-wash); }
.cmdbar-chip--unresolved { opacity: 0.55; }

.cmdbar-enter {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-text-dim-strong);
}

.cmdbar-suggest {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 20;
  margin: 0;
  padding: 0.35rem;
  list-style: none;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  box-shadow: 0 24px 60px -30px #000;
}

.cmdbar-suggest li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.9rem;
}

.cmdbar-suggest li:hover,
.cmdbar-suggest li.is-active { background: var(--color-surface-sunken); }

.cmdbar-suggest img {
  width: 30px;
  height: 44px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
}

.cmdbar-suggest-year { color: var(--color-text-dim); font-family: var(--font-mono); font-size: 0.8rem; }

/* ---------- Hero numbers band ---------- */
/* One full-width card, three cells split by internal hairlines -- the lifetime
   figure, cost per film and hours in the dark, glanceable above everything. */
.sv-hero {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.sv-hero-cell { padding: 1.5rem 1.75rem; min-width: 0; }
.sv-hero-cell + .sv-hero-cell { border-left: 1px solid var(--color-border); }

.sv-hero-v {
  margin: 0.55rem 0 0.45rem;
  font-size: clamp(1.9rem, 1.4vw + 1.3rem, 2.5rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
}

.sv-hero-sub { margin: 0; font-size: 0.85rem; color: var(--color-text-dim); }

/* ---------- Dashboard section framing ---------- */

.sv-sec { display: flex; flex-direction: column; gap: 0.9rem; }

.sv-sec-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}

.sv-sec-h { margin: 0; font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }

.sv-sec-aside { display: flex; align-items: baseline; gap: 1.25rem; }

.sv-sec-legend {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-text-faint);
}

.sv-sec-link {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  white-space: nowrap;
}

/* ---------- Membership rows ---------- */

.sv-gauge-cta-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  max-width: 460px;
}
.sv-gauge-cta-card .btn { margin-top: 0.5rem; }
.sv-gauge-cta-h { margin: 0; font-weight: 700; }
.sv-gauge-cta-b { margin: 0 0 0.4rem; color: var(--color-text-dim-strong); font-size: 0.9rem; }

/* Two membership cells abreast on the dashboard -- four held memberships read
   as a 2x2 block, not a single column beside a screen-width gap. Collapses to
   one column on tablet/handset. */
.sv-mlist {
  padding: 0.5rem 1.5rem;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 3rem;
}

.sv-mrow {
  display: grid;
  grid-template-columns: 60px minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: start;
  column-gap: 1.1rem;
  row-gap: 0.3rem;
  padding: 1.15rem 0;
  border-top: 1px solid var(--color-border);
}
.sv-mrow:nth-child(-n + 2) { border-top: 0; }

.sv-mrow-verdict { grid-column: 2; }
.sv-ring { grid-row: 1 / span 2; align-self: center; }

.sv-ring { position: relative; display: grid; place-items: center; width: 60px; height: 60px; }
.sv-ring svg { width: 100%; height: 100%; display: block; }
.sv-ring-arc { stroke: var(--color-accent); }
/* Past break-even: the ring is full and reads brighter -- still amber, a within-
   accent emphasis for the milestone, not a second colour. */
.sv-ring.is-over .sv-ring-arc { stroke: var(--color-accent-bright); }
.sv-ring.is-idle { opacity: 0.55; }

.sv-ring-num {
  position: absolute;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--color-accent-bright);
}
.sv-ring.is-idle .sv-ring-num { color: var(--color-text-dim); }

.sv-mrow-body { min-width: 0; }

.sv-mrow-name {
  margin: 0 0 0.25rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  font-weight: 600;
}

.sv-mrow-tag {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--color-text-dim);
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
}

.sv-mrow-meta {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--color-text-dim);
}

.sv-mrow-verdict {
  margin: 0.15rem 0 0;
  font-size: 0.9rem;
  line-height: 1.4;
  color: var(--color-text-dim-strong);
}

/* Tablet / handset: one membership per row, hero cells stacked. */
@media (max-width: 1024px) {
  .sv-mlist { grid-template-columns: 1fr; }
  .sv-mrow:nth-child(2) { border-top: 1px solid var(--color-border); }
  .sv-mrow:first-child { border-top: 0; }
  .sv-hero { grid-template-columns: 1fr; }
  .sv-hero-cell + .sv-hero-cell { border-left: 0; border-top: 1px solid var(--color-border); }
}

/* ---------- Latest panel ---------- */

.sv-latest { padding: 1.25rem 1.5rem; }
.sv-latest-empty { margin: 0; color: var(--color-text-dim); padding: 1rem 0; }

.sv-row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.75rem 0;
  border-top: 1px solid var(--color-border);
  color: inherit;
}
.sv-row:first-of-type { border-top: 0; }
.sv-row:hover { color: inherit; }
.sv-row:hover .sv-row-title { color: var(--color-accent); }

.sv-row-thumb {
  width: 34px;
  height: 50px;
  flex-shrink: 0;
  border-radius: 4px;
  background: repeating-linear-gradient(-45deg, var(--color-surface-raised) 0 6px, var(--color-surface-sunken) 6px 12px);
  overflow: hidden;
}
.sv-row-thumb img { width: 100%; height: 100%; object-fit: cover; }

.sv-row-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.sv-row-title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sv-row-sub { font-size: 0.82rem; color: var(--color-text-dim); }

.sv-row-money { font-family: var(--font-mono); font-size: 0.95rem; flex-shrink: 0; }
.sv-row-money--saved { color: var(--color-positive); }
.sv-row-money--none { color: var(--color-text-faint); }

.sv-unvalued {
  display: block;
  margin-top: 0.5rem;
  padding-top: 0.9rem;
  border-top: 1px dashed var(--color-border-strong);
  font-size: 0.88rem;
  color: var(--color-accent);
}

/* ---------- Film detail ---------- */

.fdetail { max-width: 760px; padding: 1.5rem clamp(1rem, 4vw, 2.5rem) 3rem; display: flex; flex-direction: column; gap: 1.5rem; }

.fdetail-head { display: flex; gap: 1.5rem; }
.fdetail-poster { width: 104px; height: 150px; object-fit: cover; border-radius: 8px; flex-shrink: 0; }
.fdetail-poster--empty { background: repeating-linear-gradient(-45deg, var(--color-surface-raised) 0 8px, var(--color-surface-sunken) 8px 16px); }
.fdetail-head-body { display: flex; flex-direction: column; gap: 0.5rem; }
.fdetail-title { margin: 0; font-size: 1.9rem; font-weight: 800; letter-spacing: -0.01em; }
.fdetail-year { color: var(--color-text-dim); font-weight: 700; }
.fdetail-meta { margin: 0; color: var(--color-text-dim-strong); font-size: 0.9rem; }
.fdetail-actions { margin-top: 0.4rem; display: flex; flex-wrap: wrap; gap: 0.6rem; }
.fdetail-actions .inline-form { display: inline-flex; }

.fdetail-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--color-border);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}
.fdetail-cell { background: var(--color-surface-sunken); padding: 1.2rem 1.4rem; }
.fdetail-cell-l { margin: 0 0 0.5rem; font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.13em; text-transform: uppercase; color: var(--color-text-dim); }
.fdetail-cell-v { margin: 0; font-size: 1.6rem; font-weight: 700; }

.fdetail-hist-h { margin: 0; }
.fdetail-hist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.fdetail-hrow-link {
  display: grid;
  grid-template-columns: 60px 1fr auto;
  align-items: center;
  gap: 0.8rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  color: inherit;
}
.fdetail-hrow-link:hover { color: inherit; border-color: var(--color-border-strong); }
.fdetail-hrow-date { font-family: var(--font-mono); font-size: 0.8rem; color: var(--color-accent-dim); }
.fdetail-hrow-venue { font-weight: 500; }
.fdetail-hrow-saved { font-family: var(--font-mono); font-size: 0.9rem; }
.fdetail-hrow-saved--unvalued { color: var(--color-accent); font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; }
.fdetail-note { margin: 0; color: var(--color-text-faint); font-size: 0.9rem; padding-top: 0.5rem; border-top: 1px solid var(--color-border); }

/* ---------- Memberships ---------- */

.mships { padding: 1.5rem clamp(1rem, 4vw, 2.5rem) 3rem; display: flex; flex-direction: column; gap: 1.5rem; }
.mships-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.mships-h1 { margin: 0.5rem 0 0.5rem; font-size: 2.1rem; font-weight: 800; letter-spacing: -0.01em; }

.mships-toggle {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-sunken);
}
.mships-toggle-opt {
  padding: 0.35rem 0.9rem;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-dim-strong);
}
.mships-toggle-opt:hover { color: var(--color-text); }
.mships-toggle-opt.is-active {
  background: var(--color-accent-wash);
  color: var(--color-accent-dim);
}

.mships-table { padding: 0.5rem 1.5rem 1rem; }
.mships-thead, .mships-trow {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1.2fr;
  align-items: center;
  gap: 1rem;
  padding: 0.9rem 0;
}
.mships-thead {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-text-dim);
  border-bottom: 1px solid var(--color-border);
}
.mships-trow { border-bottom: 1px solid var(--color-border); }
.mships-trow:last-child { border-bottom: 0; }
.mships-num { font-family: var(--font-mono); text-align: right; }
.mships-name { font-weight: 600; }
.mships-tier { color: var(--color-text-dim); font-weight: 400; }
.mships-verdict { font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase; }
.mships-verdict--keep { color: var(--color-accent); }
.mships-verdict--review { color: var(--color-review); }
.mships-verdict--paid { color: var(--color-positive); }

.mships-forecast { display: flex; flex-direction: column; gap: 1rem; }
.mships-forecast-line { margin: 0; font-size: 1.05rem; line-height: 1.55; }
.mships-bars { display: flex; align-items: stretch; gap: 0.5rem; height: 112px; padding-bottom: 1.3rem; }
.mships-bar {
  position: relative;
  flex: 1;
  min-width: 0;
}
.mships-bar-fill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  min-height: 3px;
  border-radius: 2px 2px 0 0;
  background: var(--color-accent);
}
.mships-bar.is-current .mships-bar-fill { background: var(--color-accent-bright); }
.mships-bar.is-forecast .mships-bar-fill {
  background: repeating-linear-gradient(
    -45deg,
    color-mix(in srgb, var(--color-accent) 55%, transparent) 0 3px,
    transparent 3px 6px
  );
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-accent) 45%, transparent);
}
.mships-bar-tick {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1.1rem;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--color-text-faint);
}
.mships-bar.is-current .mships-bar-tick { color: var(--color-accent-bright); }
.mships-bars-legend {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.12em;
  color: var(--color-text-faint);
}

.mships-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
  color: var(--color-text-dim-strong);
  font-size: 0.9rem;
}
.mships-foot a { font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.06em; }

@media (max-width: 860px) {
  .sv-mrow {
    grid-template-columns: 44px minmax(0, 1fr);
    column-gap: 1rem;
  }
  .sv-ring { width: 44px; height: 44px; }
  .cmdbar-chips { display: none; }
  .fdetail-head { flex-direction: column; }
  .mships-thead, .mships-trow { grid-template-columns: 1.6fr 1fr 1fr; }
  .mships-thead span:nth-child(3), .mships-trow > *:nth-child(3) { display: none; }
}

/* ---------- Log sheet (screen 2) framing ---------- */
.logsheet-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.logsheet-hint {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  color: var(--color-text-faint);
  white-space: nowrap;
}

/* ---------- In-app footer: one quiet credit + legal line (redesign) ---------- */
.app-footer {
  padding: 1rem clamp(1rem, 4vw, 2.5rem);
}
.app-footer-line {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--color-text-dim);
}
.app-footer-line a { color: var(--color-text-dim-strong); }
.app-footer-line a:hover { color: var(--color-accent); }
.app-footer-brand { color: var(--color-text-dim-strong); }
.app-footer .site-footer-emoji { font-size: 13px; }

/* ---------- Memberships: expandable verdict rows ---------- */
.mships-trow-wrap { border-bottom: 1px solid var(--color-border); }
.mships-trow-wrap:last-child { border-bottom: 0; }
.mships-trow-wrap > summary { list-style: none; cursor: pointer; }
.mships-trow-wrap > summary::-webkit-details-marker { display: none; }
.mships-trow-wrap[data-empty] > summary { cursor: default; }
.mships-trow-wrap > summary:hover .mships-name { color: var(--color-accent); }
.mships-trow-wrap[open] > summary .mships-name { color: var(--color-text); }

.mships-tickets { padding: 0.25rem 0 0.9rem; display: flex; flex-direction: column; gap: 0.15rem; }
.mships-ticket {
  display: grid;
  grid-template-columns: 52px 1fr auto auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  color: var(--color-text-dim-strong);
  font-size: 0.88rem;
}
.mships-ticket:hover { background: var(--color-surface-sunken); color: var(--color-text); }
.mships-ticket-date { font-family: var(--font-mono); font-size: 0.75rem; color: var(--color-accent-dim); }
.mships-ticket-film { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mships-ticket-venue { color: var(--color-text-dim); font-size: 0.8rem; }
.mships-ticket-saved { font-family: var(--font-mono); }
.mships-ticket-empty { margin: 0.3rem 0.6rem; color: var(--color-text-faint); font-size: 0.85rem; }

/* "Pick a tier" -- the one verdict that's an action, not a readout. */
.mships-verdict-link { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.mships-verdict-link:hover { color: var(--color-accent); }
.mships-tier-prompt {
  margin: 0.3rem 0.6rem 0.9rem;
  color: var(--color-text-dim-strong);
  font-size: 0.88rem;
  line-height: 1.5;
}
.mships-tier-prompt a { color: var(--color-accent-dim); }
/* Sticky topbar clearance for the #manage-<id> / verdict-row jump links. */
.mships-trow-wrap,
.mships-manage-row { scroll-margin-top: 5rem; }

/* ============================================================
   Log sheet — one screen, no steps (DESIGN-BRIEF.md screen 2).
   Rendered as a page (.logsheet2-page) and as a <dialog>
   (.logsheet2-dialog) off the same _log_sheet_body partial.
   ============================================================ */

.logsheet2-page { max-width: 720px; }

.logsheet2-dialog {
  width: min(680px, calc(100vw - 2rem));
  max-height: calc(100vh - 4rem);
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  overflow: auto;
}
.logsheet2-dialog::backdrop {
  background: oklch(0 0 0 / 0.55);
  backdrop-filter: blur(2px);
}
.logsheet2-dialog .logsheet2 { padding: 1.75rem; }

.logsheet2 { display: flex; flex-direction: column; gap: 1.25rem; }

.logsheet2-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.logsheet2-title { margin: 0; font-size: 1.5rem; font-weight: 800; letter-spacing: -0.01em; }
.logsheet2-hint {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  color: var(--color-text-faint);
  white-space: nowrap;
}

.logsheet2-label {
  display: block;
  margin-bottom: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-text-dim);
}
.logsheet2-label-note { color: var(--color-accent); }

.logsheet2-input {
  width: 100%;
  padding: 0.7rem 0.85rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font: inherit;
}
.logsheet2-input:focus-visible { outline: 2px solid var(--color-accent-bright); outline-offset: 1px; }
.logsheet2-input--mono { font-family: var(--font-mono); }
.logsheet2-input.is-free { color: var(--color-positive); }

.logsheet2-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.logsheet2-field .date-chips { margin-top: 0.5rem; }

/* Film chip / search */
.logsheet2-film { position: relative; }
.logsheet2-chip {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-accent-wash);
  background: var(--color-accent-wash);
}
.logsheet2-chip-poster { width: 46px; height: 66px; object-fit: cover; border-radius: 4px; flex-shrink: 0; }
.logsheet2-chip-poster--empty { background: repeating-linear-gradient(-45deg, var(--color-surface-raised) 0 6px, var(--color-surface-sunken) 6px 12px); }
.logsheet2-chip-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.logsheet2-chip-title { font-weight: 700; }
.logsheet2-chip-meta { font-size: 0.8rem; color: var(--color-text-dim); }
.logsheet2-chip-change {
  background: none; border: 0; cursor: pointer;
  color: var(--color-accent); font: inherit; padding: 0;
}

.logsheet2-results {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0.3rem;
  position: absolute;
  left: 0; right: 0;
  z-index: 5;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 24px 60px -30px #000;
  max-height: 300px;
  overflow: auto;
}
.logsheet2-results a {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.5rem 0.55rem; border-radius: 6px; color: var(--color-text);
}
.logsheet2-results a:hover { background: var(--color-surface-sunken); }
.logsheet2-results img { width: 28px; height: 42px; object-fit: cover; border-radius: 3px; }
.logsheet2-results-year { color: var(--color-text-dim); font-family: var(--font-mono); font-size: 0.8rem; margin-left: auto; }

.logsheet2-newvenue { margin-top: 0.5rem; }

/* Covered block */
.logsheet2-covered {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
}
.logsheet2-covered-h { margin: 0 0 0.2rem; font-weight: 700; }
.logsheet2-covered-b { margin: 0; font-size: 0.85rem; color: var(--color-text-dim); }

.logsheet2-switch { position: relative; flex-shrink: 0; cursor: pointer; }
.logsheet2-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.logsheet2-switch-track {
  display: block; width: 46px; height: 26px; border-radius: 999px;
  background: var(--color-surface-raised); border: 1px solid var(--color-border-strong);
  transition: background 0.15s ease;
}
.logsheet2-switch-track::after {
  content: ""; position: absolute; top: 4px; left: 4px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--color-text-dim); transition: transform 0.15s ease, background 0.15s ease;
}
.logsheet2-switch input:checked + .logsheet2-switch-track { background: var(--color-accent); border-color: var(--color-accent); }
.logsheet2-switch input:checked + .logsheet2-switch-track::after { transform: translateX(20px); background: var(--color-accent-ink); }
.logsheet2-switch input:focus-visible + .logsheet2-switch-track { outline: 2px solid var(--color-accent-bright); outline-offset: 2px; }

/* Live consequence banner */
.logsheet2-banner {
  margin: 0;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-sm);
  font-size: 0.92rem;
  line-height: 1.5;
  white-space: pre-wrap;
  background: var(--color-surface-sunken);
  color: var(--color-text-dim-strong);
  border: 1px solid var(--color-border);
}
.logsheet2-banner[data-tone="positive"] {
  background: var(--color-positive-wash);
  border-color: var(--color-positive-wash);
  color: var(--color-positive);
}

.logsheet2-actions { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.logsheet2-actions-right { display: flex; gap: 0.6rem; }

@media (max-width: 600px) {
  .logsheet2-grid { grid-template-columns: 1fr; }
  .logsheet2-dialog .logsheet2 { padding: 1.25rem; }
}

/* ---------- Memberships: prior-cycle history + manage ---------- */
.mships-history { padding: 0.5rem 0 0.8rem; display: flex; flex-direction: column; gap: 0.35rem; }
.mships-history .sv-kicker { margin-bottom: 0.2rem; }
.mships-history-row {
  display: grid;
  grid-template-columns: 1fr auto 3.5rem;
  align-items: center;
  gap: 1rem;
  padding: 0.35rem 0.6rem;
  font-size: 0.85rem;
  color: var(--color-text-dim-strong);
}
.mships-history-label { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.06em; color: var(--color-accent-dim); }
.mships-history-fee { color: var(--color-text-faint); }

.mships-manage summary { list-style: none; cursor: pointer; }
.mships-manage summary::-webkit-details-marker { display: none; }
.mships-manage-summary { display: flex; align-items: center; justify-content: space-between; }
.mships-manage[open] .mships-manage-chevron { transform: rotate(180deg); }
.mships-manage-chevron { color: var(--color-text-dim); transition: transform 0.15s ease; }
.mships-manage-body { display: flex; flex-direction: column; gap: 0.75rem; margin-top: 1rem; }
.mships-manage-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--color-border);
}
.mships-manage-row:last-of-type { border-bottom: 0; }
.mships-manage-name { display: flex; align-items: center; gap: 0.5rem; font-weight: 600; flex: 1; min-width: 12rem; }
.mships-manage-tier { display: flex; align-items: center; gap: 0.4rem; }
.mships-manage-tier select, .mships-manage-add select {
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font: inherit;
  font-size: 0.85rem;
}
.mships-manage-add { display: flex; gap: 0.5rem; padding-top: 0.5rem; }
.mships-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 7px;
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 700;
  color: #1a1a1a;
}
html:not(.no-js) .mships-manage-set { display: none; }

/* ---------- Command bar: per-word greying overlay ---------- */

.cmdbar-input-wrap {
  position: relative;
  flex: 1;
  display: flex;
  min-width: 4rem;
}

.cmdbar-input-wrap .cmdbar-input { flex: 1; min-width: 0; }

/* Enhancement only -- with JS off the overlay is never built and the input's
   own text must stay visible. */
html:not(.no-js) .cmdbar-input {
  color: transparent;
  caret-color: var(--color-text);
}
html:not(.no-js) .cmdbar-input::selection {
  background: var(--color-accent-wash);
  color: var(--color-text);
}

.cmdbar-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  overflow: hidden;
  pointer-events: none;
  white-space: pre;
  font-family: var(--font-mono);
  font-size: 1rem;
  line-height: 3.5rem;
}

.cmdbar-tok--ok { color: var(--color-accent-dim); }
.cmdbar-tok--film { color: var(--color-text); }
.cmdbar-tok--pending { color: var(--color-text-dim); }

/* ---------- Sortable admin tables ---------- */

.admin-table th.is-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.admin-table th.is-sortable::after {
  content: "\2195"; /* ↕ */
  margin-left: 0.35em;
  opacity: 0.35;
  font-size: 0.9em;
}

.admin-table th.is-sorted-asc::after { content: "\2191"; opacity: 0.9; }
.admin-table th.is-sorted-desc::after { content: "\2193"; opacity: 0.9; }

.admin-table th.is-sortable:hover { color: var(--color-text); }

.admin-table th.is-sortable:focus-visible {
  outline: 2px solid var(--color-accent-bright);
  outline-offset: -2px;
}

/* ---------- Film-detail history: format · time ---------- */

.fdetail-hrow-detail {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: var(--color-text-dim-strong);
  margin-top: 0.15rem;
}

/* ---------- Keyboard shortcuts reference page ---------- */

.shortcuts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 1rem;
  max-width: 960px;
}

.shortcuts-group {
  padding: 1.1rem 1.25rem 1.25rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.shortcuts-group-title {
  margin: 0 0 0.25rem;
  font-size: 0.95rem;
}

.shortcuts-group-note {
  margin: 0 0 0.9rem;
  font-size: 0.82rem;
  color: var(--color-text-dim);
  line-height: 1.45;
}

.shortcuts-list {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.shortcuts-row {
  display: grid;
  grid-template-columns: minmax(120px, max-content) 1fr;
  gap: 0.35rem 1rem;
  align-items: baseline;
}

.shortcuts-row dt {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.2rem;
}

.shortcuts-row dd {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--color-text);
}

.shortcuts-row kbd {
  display: inline-block;
  min-width: 1.5rem;
  padding: 0.1rem 0.4rem;
  border-radius: 6px;
  border: 1px solid var(--color-border-strong);
  border-bottom-width: 2px;
  background: var(--color-surface-raised);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  text-align: center;
  color: var(--color-text);
}

.shortcuts-plus,
.shortcuts-or {
  font-size: 0.72rem;
  color: var(--color-text-dim);
}

@media (max-width: 520px) {
  .shortcuts-row {
    grid-template-columns: 1fr;
    gap: 0.15rem;
  }
}
