/* Background tuning. Raise --bg-scrim to fade the store photo more,
   lower it to show more. --bg-blur softens the shelf lines. */
:root {
  --bg-scrim: 72%;
  --bg-blur: 3px;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

/* html carries the solid page colour. body must stay TRANSPARENT.
   The store photo lives on body::before at z-index -1. In CSS paint order,
   a normal block's background is painted AFTER negative-z-index children —
   so if body had its own solid background, it would sit on top of the photo
   and hide it completely. Transparent body lets the photo show through,
   with html's colour as the fallback underneath it. */
html {
  background: var(--bg);
}

/* `html body` rather than `body`, so this outranks a plain `body { background }`
   anywhere else — tokens.css included — whatever order the files load in. */
html body {
  background: transparent;
  color: var(--text);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
}

/* The store photo. Blurred and laid under a ~90% scrim of the page colour
   so shelf lines never compete with the text on top of it. inset:-20px
   oversizes it past the viewport so the blur doesn't leave a soft,
   transparent edge. */

body::before {
  content: "";
  position: fixed;
  inset: -20px;
  z-index: -1;
  background-image: linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-scrim), transparent),
      color-mix(in srgb, var(--bg) var(--bg-scrim), transparent)
    ),
    url("/public/bg/light-mobile.webp");
  background-size: cover;
  background-position: center;
  filter: blur(var(--bg-blur));
}

@media (min-width: 720px) {
  body::before {
    background-image: linear-gradient(
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent),
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent)
      ),
      url("/public/bg/light-desktop.webp");
  }
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body::before {
    background-image: linear-gradient(
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent),
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent)
      ),
      url("/public/bg/dark-mobile.webp");
  }
}

@media (prefers-color-scheme: dark) and (min-width: 720px) {
  :root:not([data-theme="light"]) body::before {
    background-image: linear-gradient(
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent),
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent)
      ),
      url("/public/bg/dark-desktop.webp");
  }
}

:root[data-theme="dark"] body::before {
  background-image: linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-scrim), transparent),
      color-mix(in srgb, var(--bg) var(--bg-scrim), transparent)
    ),
    url("/public/bg/dark-mobile.webp");
}

@media (min-width: 720px) {
  :root[data-theme="dark"] body::before {
    background-image: linear-gradient(
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent),
        color-mix(in srgb, var(--bg) var(--bg-scrim), transparent)
      ),
      url("/public/bg/dark-desktop.webp");
  }
}

h1,
h2,
h3 {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin: 0;
}

button {
  font-family: inherit;
}

#app {
  min-height: 100vh;
}

/* Loading */

.loading-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  color: var(--text-muted);
}

/* The junior card sign-in (js/junior.js) — the older membership card.
   The member sign-in is Stage F-7a's .pw-card, at the end of this file. */

.signin-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
}

.membership-card {
  width: 100%;
  max-width: 360px;
  background: var(--blue);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
}

.card-stripe {
  height: 20px;
  background: var(--yellow);
}

.card-body {
  padding: 32px 28px 28px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.card-title {
  font-size: 1.5rem;
  color: var(--on-blue);
}

.card-subtitle {
  margin: -12px 0 0;
  color: var(--on-blue);
  opacity: 0.75;
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

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

.card-field-label {
  color: var(--on-blue);
  opacity: 0.75;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.card-field input {
  background: transparent;
  border: none;
  border-bottom: 2px solid var(--on-blue);
  color: var(--on-blue);
  font-family: inherit;
  font-size: 1.1rem;
  padding: 10px 2px;
  min-height: 44px;
  width: 100%;
}

.card-field input::placeholder {
  color: var(--on-blue);
  opacity: 0.5;
}

.card-field input:focus {
  border-bottom-color: var(--yellow);
}

.card-button {
  font-size: 1rem;
}

.card-status {
  min-height: 1.2em;
  margin: 0;
  color: var(--on-blue);
  font-size: 0.9rem;
}

.card-status-error {
  color: var(--yellow);
}

/* "Your Card" screen base — see the Stage 7a section, further down this
   file, for the rest of it. A container, not just a media-query target:
   the sidebar rail/full sidebar (css/sidebar.css) eats into the viewport
   unpredictably, so .cc-layout below switches to two columns off this
   element's own rendered width, the same reasoning as the Year screen's
   @container sheet and Staff Picks' @container staffpicks. */

.card-screen {
  container-type: inline-size;
  container-name: cardscreen;
  padding: 20px 16px 40px;
}

/* App shell — screen area, floating drawer trigger. The background
   itself lives on body::before, above. */

.app-shell {
  position: relative;
  min-height: 100vh;
}

.screen {
  padding: 20px 16px 110px;
  max-width: 480px;
  margin: 0 auto;
}

/* Sits above the drawer (z-index 101 > 100) so it stays put and stays
   clickable in exactly the same spot whether the drawer is open or
   closed — the same physical button serves as both the menu and close
   icon, swapped in ui.js, so the thumb never has to move. */
.drawer-trigger {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: none;
  background: var(--yellow);
  color: var(--on-yellow);
  font-size: 1.4rem;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  z-index: 101;
}

body.drawer-open {
  overflow: hidden;
}

/* ---------- The drawer ----------
   A full-screen overlay, always dark regardless of theme: the store at
   night, under a scrim. Everything on it uses light-on-dark values
   (--on-blue for text, translucent white for pill fills) rather than the
   theme's --surface, which is white in light mode and would put white
   pills on a dark photo. */

.drawer {
  position: fixed;
  inset: 0;
  z-index: 100;
  background-image: linear-gradient(rgba(5, 17, 40, 0.74), rgba(5, 17, 40, 0.92)),
    url("/public/bg/dark-mobile.webp");
  background-size: cover;
  background-position: center;
  overflow-y: auto;
}

@media (min-width: 720px) {
  .drawer {
    background-image: linear-gradient(rgba(5, 17, 40, 0.74), rgba(5, 17, 40, 0.92)),
      url("/public/bg/dark-desktop.webp");
  }
}

/* The drawer is never display:none — nothing can animate to or from that.
   It stays in the layout and fades via opacity + visibility, driven by the
   body.drawer-open class that ui.js already toggles. visibility:hidden also
   takes it out of the tab order and stops it catching clicks while closed.
   The [hidden] attribute ui.js sets is overridden here so it can't cut the
   animation short. */
.drawer,
.drawer[hidden] {
  display: block;
  opacity: 0;
  visibility: hidden;
  transition: opacity 240ms ease, visibility 0s linear 240ms;
}

body.drawer-open .drawer {
  opacity: 1;
  visibility: visible;
  transition: opacity 240ms ease, visibility 0s linear 0s;
}

/* Pills rise into place bottom-up, nearest the thumb first — the same
   order they're ranked in. */
.drawer-header,
.drawer-pill {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 260ms ease, transform 340ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

body.drawer-open .drawer-header,
body.drawer-open .drawer-pill {
  opacity: 1;
  transform: none;
}

body.drawer-open .drawer-pill:disabled {
  opacity: 0.35;
}

body.drawer-open .drawer-pill:nth-last-child(1) { transition-delay: 20ms; }
body.drawer-open .drawer-pill:nth-last-child(2) { transition-delay: 55ms; }
body.drawer-open .drawer-pill:nth-last-child(3) { transition-delay: 90ms; }
body.drawer-open .drawer-pill:nth-last-child(4) { transition-delay: 125ms; }
body.drawer-open .drawer-pill:nth-last-child(5) { transition-delay: 160ms; }
body.drawer-open .drawer-pill:nth-last-child(6) { transition-delay: 195ms; }
body.drawer-open .drawer-pill:nth-last-child(7) { transition-delay: 230ms; }
body.drawer-open .drawer-header { transition-delay: 265ms; }

@media (prefers-reduced-motion: reduce) {
  .drawer,
  .drawer-header,
  .drawer-pill {
    transition: none;
    transform: none;
  }
}

/* Column flex, everything pushed to the bottom-right. The header takes
   margin-bottom:auto, which absorbs the free space below it and lifts it
   to the top of the screen — so the member card sits up top, far from
   the thumb, and the pills stack at the bottom, near it. */
.drawer-content {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 10px;
  padding: 28px 20px 100px;
}

.drawer-header {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  margin-bottom: auto;
  padding: 0 4px;
}

.drawer-name {
  color: var(--on-blue);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.drawer-since {
  color: var(--on-blue);
  opacity: 0.6;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Each pill: icon, a dashed "perforation" divider like a ticket's
   tear-off stub, then a right-aligned label. */

.drawer-pill {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 340px;
  min-height: 56px;
  padding: 0 24px 0 18px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.07);
  color: var(--on-blue);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: pointer;
}

.drawer-pill:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
}

.drawer-pill-icon {
  flex: 0 0 22px;
  text-align: center;
  font-size: 1rem;
  line-height: 1;
  opacity: 0.7;
}

.drawer-pill-divider {
  flex: 0 0 auto;
  align-self: center;
  height: 24px;
  width: 0;
  border-left: 1px dashed currentColor;
  opacity: 0.35;
}

.drawer-pill-label {
  flex: 1 1 auto;
  text-align: right;
  font-size: 0.95rem;
}

.drawer-pill-active {
  background: var(--yellow);
  color: var(--on-yellow);
  border-color: var(--yellow);
  min-height: 60px;
  box-shadow: 0 4px 18px rgba(255, 194, 14, 0.25);
}

.drawer-pill-active .drawer-pill-icon {
  opacity: 1;
}

.drawer-pill:disabled {
  opacity: 0.35;
  cursor: default;
}

/* The Shelf */

.shelf-screen {
  display: flex;
  flex-direction: column;
  gap: 20px;
}


.search-field {
  display: block;
}

.search-field input {
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 1rem;
}

.search-field input:focus {
  border-color: var(--blue);
}

.search-results:empty,
.add-panel-slot:empty,
.shelf-modal-slot:empty {
  display: none;
}

.search-results {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.search-error {
  color: var(--text-muted);
  margin: 0;
}

/* The VHS case — shared by search results and the shelf */

.vhs-case {
  display: flex;
  flex-direction: column;
  background: var(--case-bg);
  border-radius: 6px;
  padding: 8px;
  gap: 6px;
  border: none;
  text-align: left;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}

button.vhs-case {
  cursor: pointer;
  font: inherit;
}

.vhs-sleeve {
  display: block;
  aspect-ratio: 2 / 3;
  border-radius: 3px;
  overflow: hidden;
  background: var(--case-bg);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.vhs-sleeve img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.vhs-sleeve-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--on-blue);
  opacity: 0.5;
  font-size: 0.75rem;
  text-transform: uppercase;
}

.vhs-title {
  color: var(--on-blue);
  font-weight: 500;
  font-size: 0.85rem;
  line-height: 1.25;
}

.vhs-year {
  color: var(--on-blue);
  opacity: 0.6;
  font-size: 0.75rem;
}

.vhs-labels {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.vhs-label-tag {
  background: var(--yellow);
  color: var(--on-yellow);
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 3px;
}

/* "We Watched This" — the return slot on a backlog case */

.watch-slot {
  margin-top: 4px;
  width: 100%;
  min-height: 44px;
  border: none;
  border-radius: 4px;
  background: var(--case-bg);
  color: var(--yellow);
  font-weight: 700;
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15);
}

/* Add panel */

.add-panel {
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 10px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.add-panel-title {
  margin: 0;
  font-weight: 500;
  color: var(--text);
}

/* Label chips, restyled as strips of label-maker tape (see the tape
   tokens in css/tokens.css). Picked colour comes from the label's own
   id (id mod 4), via a data-tape-color attribute the caller sets — so a
   label is always the same colour everywhere, not chosen by markup
   order. The small end dots are ::before/::after, not markup. */
.label-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 10px;
  padding: 4px;
}

.label-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 14px;
  border: none;
  border-radius: 2px;
  background: var(--tape-unpicked-bg);
  color: var(--text-muted);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  cursor: pointer;
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.08);
  transform: none;
  transition: transform 220ms cubic-bezier(0.3, 1.6, 0.5, 1);
}

.label-chip::before,
.label-chip::after {
  content: "";
  width: 5px;
  height: 5px;
  flex-shrink: 0;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.45;
}

.label-chip[data-tape-color="0"] { --tape-color: var(--tape-red); }
.label-chip[data-tape-color="1"] { --tape-color: var(--tape-navy); }
.label-chip[data-tape-color="2"] { --tape-color: var(--tape-black); }
.label-chip[data-tape-color="3"] { --tape-color: var(--tape-green); }

.label-chip-selected {
  background: var(--tape-color, var(--yellow));
  color: var(--tape-picked-text);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5), 0 -1px 0 rgba(255, 255, 255, 0.18);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    inset 0 -2px 0 rgba(0, 0, 0, 0.3),
    0 4px 8px rgba(0, 0, 0, 0.28);
  transform: rotate(var(--tape-rotate, -3deg)) scale(1.04);
}

/* Cycle the "just stuck on" tilt by the chip's position in the row,
   regardless of which chips happen to be picked. */
.label-chips .label-chip-selected:nth-child(4n + 1) { --tape-rotate: -3deg; }
.label-chips .label-chip-selected:nth-child(4n + 2) { --tape-rotate: 2.5deg; }
.label-chips .label-chip-selected:nth-child(4n + 3) { --tape-rotate: -2deg; }
.label-chips .label-chip-selected:nth-child(4n) { --tape-rotate: 3deg; }

@media (prefers-reduced-motion: reduce) {
  .label-chip {
    transition: none;
  }

  .label-chip-selected {
    transform: none;
  }
}

.add-panel-status {
  margin: 0;
  min-height: 1.2em;
  color: var(--text-muted);
  font-size: 0.85rem;
}

.add-panel-status-error {
  color: var(--text);
  font-weight: 700;
}

.add-panel-actions {
  display: flex;
  gap: 10px;
}

.add-panel-actions .add-confirm {
  flex: 1;
}

.add-cancel {
  padding: 0 18px;
}

/* Filter chips — shelf talkers */

.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.shelf-talker {
  min-height: 44px;
  padding: 0 16px;
  border-radius: 4px;
  border: none;
  background: var(--yellow);
  color: var(--on-yellow);
  font-weight: 700;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
  opacity: 0.55;
}

.shelf-talker-active {
  opacity: 1;
}

/* Shelf */

.shelf {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.shelf-empty {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--text-muted);
  text-transform: uppercase;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  padding: 40px 0;
}

/* Watch / ranking flow */

.watch-screen {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.back-link {
  align-self: flex-start;
  padding: 0 8px;
}

/* ---------- The return slip (ranking step 1) ----------
   The film's VHS case sits at the counter, tilted, and the two questions
   are a store return slip: yellow stripe like the membership card, dashed
   header rule, and a torn-ticket perforation (with notches cut into each
   edge) between the questions. A picked tile turns navy, tilts slightly,
   and gets a yellow "stamp" with a check. */

.return-screen {
  gap: 16px;
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
}

.return-hero {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 4px 4px 6px;
}

.return-case {
  flex: 0 0 118px;
  width: 118px;
  padding: 7px;
  background: var(--case-bg);
  border-radius: 6px;
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.35);
  transform: rotate(-5deg);
}

.return-hero-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
}

.return-tag {
  padding: 3px 8px;
  border-radius: 3px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.return-title {
  font-size: 1.6rem;
  line-height: 1.02;
  letter-spacing: 0.01em;
  color: var(--text);
  overflow-wrap: anywhere;
}

.return-year {
  color: var(--text-muted);
  font-size: 0.9rem;
}

.return-rewind {
  color: var(--text-muted);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.return-slip {
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
}

.return-slip-stripe {
  height: 10px;
  background: var(--yellow);
}

.return-slip-body {
  padding: 14px 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.return-slip-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: 10px;
  border-bottom: 2px dashed var(--edge);
}

.return-slip-name,
.return-slip-year {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  text-transform: uppercase;
}

.return-slip-name {
  font-size: 0.95rem;
  letter-spacing: 0.08em;
  color: var(--text);
}

.return-slip-year {
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

.slip-group {
  border: none;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.slip-label {
  padding: 0;
  margin-bottom: 10px;
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.slip-tiles {
  display: grid;
  gap: 10px;
}

.slip-tiles-three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.slip-tiles-two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.slip-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 6px;
  border-radius: 10px;
  border: 2px solid var(--edge);
  background: var(--bg);
  color: var(--text);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 160ms ease, background-color 160ms ease, border-color 160ms ease;
}

.slip-tile-person {
  min-height: 104px;
}

.slip-tile-place {
  min-height: 92px;
}

.slip-tile-selected {
  background: var(--blue);
  border-color: var(--blue);
  color: var(--on-blue);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.25);
  transform: rotate(-1.5deg);
}

.slip-initials {
  display: flex;
  align-items: center;
}

.slip-initial {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border: 2px solid var(--bg);
}

.slip-initial img {
  width: 100%;
  height: 100%;
  display: block;
}

/* "Both" — the second circle overlaps the first. */
.slip-initial + .slip-initial {
  margin-left: -12px;
}

/* The images carry their own colors — a white ring keeps the selected
   tile's circles from blending into the tile's own navy fill. */
.slip-tile-selected .slip-initial {
  border-color: var(--on-blue);
}

/* The stamp is hidden until its tile is picked. Switching it from
   display:none to flex is what replays the animation on every pick. */
.slip-stamp {
  position: absolute;
  top: -9px;
  right: -9px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--on-yellow);
  display: none;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  transform: rotate(-12deg);
  pointer-events: none;
}

.slip-tile-selected .slip-stamp {
  display: flex;
  animation: slip-stamp-in 280ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

@keyframes slip-stamp-in {
  0% {
    transform: scale(1.9) rotate(-35deg);
    opacity: 0;
  }
  60% {
    transform: scale(0.86) rotate(-8deg);
    opacity: 1;
  }
  100% {
    transform: scale(1) rotate(-12deg);
    opacity: 1;
  }
}

/* The torn-ticket line between the two questions. The notches sit on the
   slip's outer edge (the slip's 18px padding + half the notch), and the
   slip's overflow:hidden trims them to half-circles. */
.slip-perforation {
  position: relative;
  height: 18px;
}

.slip-perforation::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 8px;
  border-top: 2px dashed var(--edge);
}

.slip-notch {
  position: absolute;
  top: -2px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--edge);
}

.slip-notch-left {
  left: -30px;
}

.slip-notch-right {
  right: -30px;
}

/* Continue — a quiet dashed hint until both answers are in, then a solid
   yellow button that pops into place. */
.continue-button {
  width: 100%;
  min-height: 58px;
  font-size: 0.875rem;
}

.continue-button-ready {
  font-size: 1.05rem;
  animation: continue-pop 320ms ease both;
}

@keyframes continue-pop {
  0% {
    transform: scale(0.95);
  }
  60% {
    transform: scale(1.03);
  }
  100% {
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .slip-tile {
    transition: none;
  }

  .slip-tile-selected .slip-stamp,
  .continue-button-ready {
    animation: none;
  }
}

/* ---------- The Showdown (ranking step 2) ----------
   Two VHS cases face off with a VS sticker between them; tapping a case
   answers. The two cases are a neutral either/or, not a recommendation —
   identical case, size and type, and neither pre-highlighted. The yellow
   bits (Tonight tag, rank sticker) only say which tape is which. Yellow is
   saved for committing a decision (Start the Showdown, Lock It In), never
   for one side of a choice still being made. */

.showdown-screen {
  gap: 14px;
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
}

.showdown-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.showdown-title {
  font-size: 1.9rem;
  line-height: 1;
  letter-spacing: 0.01em;
  color: var(--text);
}

/* The VCR tape counter — always a black box, like the VHS case, so the
   yellow digits sit on black in both light and dark mode. */
.showdown-counter {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--case-bg);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}

.showdown-counter-label {
  color: var(--on-blue);
  opacity: 0.6;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.12em;
}

.showdown-counter-value {
  color: var(--yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.25rem;
  letter-spacing: 0.08em;
}

.showdown-question {
  margin: 0;
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--text);
}

.showdown-faceoff {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
  padding: 6px 2px 4px;
}

.showdown-case {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 7px 7px 10px;
  border: none;
  border-radius: 6px;
  background: var(--case-bg);
  text-align: left;
  font: inherit;
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 240ms ease;
}

.showdown-case-new {
  transform: rotate(-2deg);
}

/* The opponent slides in fresh each round. "backwards" (not "both") so
   the animation lets go when it ends, and the pick transitions below can
   take over the transform. */
.showdown-case-old {
  transform: rotate(2deg);
  animation: showdown-slide-in 300ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

@keyframes showdown-slide-in {
  from {
    transform: translateX(60px) rotate(8deg);
    opacity: 0;
  }
  to {
    transform: rotate(2deg);
    opacity: 1;
  }
}

/* After a tap: the winner lifts and straightens, the loser drops away. */
.showdown-faceoff.is-deciding .showdown-case {
  pointer-events: none;
}

.showdown-case.is-winner {
  transform: scale(1.05) rotate(0deg);
}

.showdown-case.is-loser {
  transform: translateY(28px) rotate(8deg);
  opacity: 0;
}

.showdown-case .vhs-sleeve {
  position: relative;
}

.showdown-tag {
  position: absolute;
  top: 6px;
  left: 6px;
  padding: 3px 7px;
  border-radius: 3px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* The price-sticker rank badge, as on the Year grid. */
.showdown-sticker {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--on-yellow);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.75rem;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}

.showdown-case-title {
  color: var(--on-blue);
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.2;
}

.showdown-case-meta {
  color: var(--on-blue);
  opacity: 0.6;
  font-size: 0.75rem;
}

.showdown-vs {
  position: absolute;
  left: 50%;
  top: 33%;
  width: 54px;
  height: 54px;
  margin-left: -27px;
  margin-top: -27px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--on-yellow);
  border: 3px solid var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.125rem;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.3);
  transform: rotate(-8deg);
  pointer-events: none;
}

.showdown-hint {
  margin: 0;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* The landing zone — every slot the film could still land in. */

.landing-zone {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px 16px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 12px;
}

.landing-zone-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: 8px;
  border-bottom: 2px dashed var(--edge);
}

.landing-zone-name,
.landing-zone-range {
  color: var(--text);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.landing-zone-ticks {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 26px;
}

.landing-zone-ticks-dense {
  gap: 1px;
}

.landing-zone-ticks-solid {
  gap: 0;
}

.landing-tick {
  flex: 1 1 0;
  min-width: 0;
  height: 14px;
  border-radius: 2px;
  background: var(--edge);
  transition: height 200ms ease, background-color 200ms ease;
}

.landing-tick-live {
  height: 26px;
  background: var(--blue);
}

.landing-tick-opponent {
  height: 26px;
  background: var(--yellow);
}

.landing-zone-footer {
  display: flex;
  justify-content: space-between;
  color: var(--text-muted);
  font-size: 0.6875rem;
  font-weight: 700;
}

@media (prefers-reduced-motion: reduce) {
  .showdown-case,
  .landing-tick {
    transition: none;
  }

  .showdown-case-old {
    animation: none;
  }
}

/* ---------- Where It Lands (ranking step 3) ----------
   A slice of the year's list: neighbours as plain rows with a mini VHS
   box, the new film as a lifted yellow row you can drag. Rows are
   absolutely positioned — js/watch.js sets each row's `top` — so they can
   slide past each other. One row is 56px tall with an 8px gap: a 64px
   pitch, which must match ROW_PITCH_PX in watch.js. */

.lands-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 12px 14px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 12px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}

.lands-card-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 0 4px 8px;
  border-bottom: 2px dashed var(--edge);
}

.lands-card-name {
  color: var(--text);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.lands-card-aside {
  color: var(--text-muted);
  font-size: 0.75rem;
}

.lands-list {
  position: relative;
  margin: 0 4px;
}

.lands-row {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 56px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 12px 0 4px;
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--bg);
  color: var(--text);
  transition: top 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.lands-rank {
  flex: 0 0 38px;
  text-align: right;
  color: var(--text-muted);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.25rem;
}

/* The mini VHS box — black case, poster inside. */
.lands-mini {
  flex: 0 0 34px;
  width: 34px;
  padding: 3px;
  border-radius: 3px;
  background: var(--case-bg);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
}

.lands-mini-sleeve {
  display: block;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  border-radius: 1px;
  background: var(--case-bg);
}

.lands-mini-sleeve img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.lands-text {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  text-align: left;
}

.lands-title {
  font-size: 0.875rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lands-meta {
  color: var(--text-muted);
  font-size: 0.6875rem;
  font-weight: 700;
}

/* The new film — lifted, yellow, draggable. */
.lands-row-new {
  left: -4px;
  right: -4px;
  z-index: 2;
  padding: 0 14px 0 8px;
  border: none;
  background: var(--yellow);
  color: var(--on-yellow);
  font: inherit;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.25);
  cursor: grab;
  touch-action: none;
  transition: top 180ms cubic-bezier(0.2, 0.8, 0.2, 1), transform 120ms ease, box-shadow 120ms ease;
}

.lands-row-new .lands-rank {
  color: var(--on-yellow);
  font-size: 1.375rem;
}

.lands-row-new .lands-title {
  font-size: 0.9375rem;
}

.lands-row-new .lands-meta {
  color: var(--on-yellow);
  opacity: 0.7;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.lands-grip {
  flex: 0 0 auto;
  opacity: 0.6;
}

/* While dragging, the row follows the finger exactly — no easing on top. */
.lands-row-new.is-dragging {
  cursor: grabbing;
  box-shadow: 0 16px 30px rgba(0, 0, 0, 0.35);
  transform: scale(1.03) rotate(-1deg);
  transition: transform 120ms ease, box-shadow 120ms ease;
}

.nudge-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.nudge-button {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  border-radius: 10px;
  border: 2px solid var(--edge);
  background: var(--surface);
  color: var(--text);
  font-size: 1.2rem;
  font-weight: 700;
  cursor: pointer;
}

.nudge-button:disabled {
  opacity: 0.35;
  cursor: default;
}

.nudge-caption {
  flex: 1 1 auto;
  margin: 0;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.8125rem;
  font-weight: 700;
}

.lands-lock {
  min-height: 58px;
  font-size: 1.05rem;
}

@media (prefers-reduced-motion: reduce) {
  .lands-row,
  .lands-row-new,
  .lands-row-new.is-dragging {
    transition: none;
  }
}

/* Year screen */

.year-screen {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.year-switcher {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.year-tab {
  min-height: 44px;
  padding: 0 16px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--text);
  font-weight: 500;
  cursor: pointer;
}

.year-tab-active {
  background: var(--blue);
  color: var(--on-blue);
  border-color: var(--blue);
}

.rental-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  padding-top: 14px;
  border-top: 2px dashed var(--edge);
}

.rental-heading {
  border-bottom: 2px solid var(--text);
  padding-bottom: 6px;
  color: var(--text);
}

.view-toggle {
  display: flex;
  border: 1px solid var(--edge);
  border-radius: 8px;
  overflow: hidden;
}

.view-toggle-button {
  min-height: 44px;
  padding: 0 16px;
  border: none;
  background: var(--surface);
  color: var(--text);
  font-weight: 500;
  cursor: pointer;
}

.view-toggle-active {
  background: var(--blue);
  color: var(--on-blue);
}

.year-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.rank-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--on-yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}

.year-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.year-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--edge);
}

.year-list-rank {
  flex: 0 0 28px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  color: var(--text-muted);
  text-align: right;
}

.year-list-thumb {
  flex: 0 0 40px;
  width: 40px;
  aspect-ratio: 2 / 3;
  border-radius: 3px;
  overflow: hidden;
  background: var(--case-bg);
}

.year-list-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.year-list-title {
  flex: 1 1 auto;
  color: var(--text);
  font-weight: 500;
}

.year-list-year {
  flex: 0 0 auto;
  color: var(--text-muted);
  font-size: 0.85rem;
}

/* The film that was just ranked — briefly highlighted, then fades back to
   normal (js/year.js removes the class after ~2.5s). List rows get a
   yellow fill, so their text switches to on-yellow for contrast; grid
   cases get a yellow ring instead, since the poster already fills the box. */

.year-list-row {
  transition: background-color 1.2s ease;
}

.year-list-row.year-highlight {
  background-color: var(--yellow);
}

.year-list-row.year-highlight .year-list-rank,
.year-list-row.year-highlight .year-list-title,
.year-list-row.year-highlight .year-list-year {
  color: var(--on-yellow);
}

.year-grid-case {
  transition: box-shadow 1.2s ease;
}

.year-grid-case.year-highlight {
  box-shadow: 0 0 0 3px var(--yellow), 0 4px 10px rgba(0, 0, 0, 0.3);
}

/* ---------- Desktop ----------
   Phone-first, but a laptop is where the year gets reviewed and the
   backlog gets filled — both of which want width. Under 900px nothing
   changes. Above it, the column widens and every poster grid gains
   columns, so a desktop browser shows a shelf rather than a phone strip. */

@media (min-width: 900px) {
  .screen {
    max-width: 1040px;
    padding: 36px 32px 120px;
  }

  .shelf,
  .search-results {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px;
  }

  .year-list-row {
    padding: 10px 16px;
  }

  .year-list-thumb {
    flex-basis: 48px;
    width: 48px;
  }
}

@media (min-width: 1280px) {
  .shelf,
  .search-results {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* ---------- Rank a Film screen, add panel (shared with the Shelf) ---------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.rank-screen {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.rank-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}



/* The counter lookup — a navy card with the membership card's yellow
   stripe. The field inside is always white with near-black type, like a
   signature line, in both light and dark mode: --on-blue is the white and
   --on-yellow the near-black, neither of which changes with the theme. */
.lookup-card {
  background: var(--blue);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.22);
}

.lookup-stripe {
  height: 10px;
  background: var(--yellow);
}

.lookup-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px 16px;
}

.lookup-label {
  color: var(--on-blue);
  opacity: 0.8;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.lookup-field {
  position: relative;
}

.lookup-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  margin-top: -11px;
  color: var(--blue);
  pointer-events: none;
}

.lookup-input {
  width: 100%;
  min-height: 58px;
  padding: 0 16px 0 46px;
  border: none;
  border-radius: 8px;
  background: var(--on-blue);
  color: var(--on-yellow);
  font-family: inherit;
  font-size: 1.125rem;
  font-weight: 500;
}

.lookup-input::placeholder {
  color: var(--on-yellow);
  opacity: 0.55;
}

/* "Already ranked" and similar stop-here messages — yellow fill, dark text. */
.rank-notice {
  margin: 0;
  padding: 12px 14px;
  border-radius: 8px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-weight: 700;
}

.rank-notice:empty,
.rank-picks:empty,
.rank-results:empty {
  display: none;
}

.rank-picks,
.rank-results {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.rank-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 2px dashed var(--edge);
}

.rank-section-name {
  color: var(--text);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.rank-section-aside {
  color: var(--text-muted);
  font-size: 0.75rem;
}

/* Tapes being pulled off the shelf — each rises into place a beat after
   the one before (the delay is set per tape in rank.js). "backwards" so
   the animation lets go of the tape once it's done. */
.rank-pull-in {
  animation: rank-pull-in 360ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

@keyframes rank-pull-in {
  from {
    transform: translateY(26px) rotate(3deg);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

/* "On your shelf" quick picks — four small tapes. */
.shelf-picks-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}

.shelf-pick {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 5px 5px 7px;
  border: none;
  border-radius: 4px;
  background: var(--case-bg);
  text-align: left;
  font: inherit;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.3);
  cursor: pointer;
}

.shelf-pick-title {
  color: var(--on-blue);
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.2;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Search results — full-size tapes, marked if you already have them. */
.rank-results-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.rank-result .vhs-sleeve {
  position: relative;
}

.rank-result-ranked {
  cursor: default;
}

.rank-result-ranked .vhs-sleeve img,
.rank-result-ranked .vhs-sleeve-empty {
  opacity: 0.45;
}

.rank-stamp {
  position: absolute;
  left: 50%;
  top: 42%;
  width: 116px;
  margin-left: -58px;
  padding: 7px 0;
  border-radius: 4px;
  background: var(--yellow);
  color: var(--on-yellow);
  text-align: center;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
  transform: rotate(-10deg);
}

.rank-shelf-tag {
  position: absolute;
  top: 6px;
  left: 6px;
  padding: 3px 7px;
  border-radius: 3px;
  background: var(--blue);
  color: var(--on-blue);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}

.rank-empty {
  margin: 0;
  padding: 20px 16px;
  border: 1px dashed var(--edge);
  border-radius: 8px;
  color: var(--text-muted);
  text-align: center;
}

/* 700px, not 900 — from here up the results grid shares its row with the
   Rank a Film flow's left-hand film panel (see the Stage 3 section at the
   end of this file), so it earns its 4 columns at a narrower viewport than
   a full-width grid would. */
@media (min-width: 700px) {
  .rank-results-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rank-pull-in {
    animation: none;
  }
}

.add-panel-film {
  display: flex;
  align-items: center;
  gap: 12px;
}

.add-panel-thumb {
  flex: 0 0 52px;
  width: 52px;
  aspect-ratio: 2 / 3;
  border-radius: 4px;
  overflow: hidden;
  background: var(--case-bg);
}

.add-panel-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.add-panel-film-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.add-panel-film-text .add-panel-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  text-transform: uppercase;
  font-size: 1rem;
  line-height: 1.2;
}

.add-panel-year {
  color: var(--text-muted);
  font-size: 0.85rem;
}

.add-panel-actions:empty {
  display: none;
}

.add-panel > .add-cancel {
  align-self: center;
}

/* ---------- Home ---------- */

.home-screen {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.rank-cta {
  min-height: 60px;
  border: none;
  border-radius: 10px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.1rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
}

.home-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.home-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.see-more-link {
  min-height: 44px;
  padding: 0 4px;
  border: none;
  background: none;
  color: var(--blue);
  font-weight: 700;
  font-size: 0.85rem;
  cursor: pointer;
}

.home-empty {
  margin: 0;
  padding: 16px;
  border: 1px dashed var(--edge);
  border-radius: 8px;
  color: var(--text-muted);
  text-align: center;
}

.home-shelf-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
}

/* ---------- The Shelf: flip a case to the back of the box ----------
   Each case is two faces stacked in one grid cell. .is-flipped turns the
   pair round; the hidden face can't be tapped (pointer-events here, and
   `inert` set in shelf.js). The back has the membership card's yellow
   stripe across the top, so a turned case reads as the back at a glance. */

.shelf-tape {
  display: grid;
  perspective: 900px;
}

.shelf-tape-flipper {
  display: grid;
  transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  transition: transform 460ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.shelf-tape.is-flipped .shelf-tape-flipper {
  transform: rotateY(180deg);
}

.shelf-tape-face {
  grid-area: 1 / 1;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.shelf-tape:not(.is-flipped) .shelf-tape-back,
.shelf-tape.is-flipped .shelf-tape-front {
  pointer-events: none;
}

.shelf-tape-front {
  width: 100%;
}

.shelf-tape-back {
  transform: rotateY(180deg);
  padding: 12px 10px 10px;
  gap: 10px;
  border-top: 6px solid var(--yellow);
}

/* With "reduce motion" on, the case doesn't spin: the back fades in over
   the front instead. */
@media (prefers-reduced-motion: reduce) {
  .shelf-tape-flipper,
  .shelf-tape.is-flipped .shelf-tape-flipper {
    transition: none;
    transform: none;
  }

  .shelf-tape-face {
    backface-visibility: visible;
    -webkit-backface-visibility: visible;
    transition: opacity 180ms ease;
  }

  .shelf-tape-back {
    transform: none;
    opacity: 0;
  }

  .shelf-tape.is-flipped .shelf-tape-back {
    opacity: 1;
  }

  .shelf-tape.is-flipped .shelf-tape-front {
    opacity: 0;
  }
}

/* The top of the back — tap it to turn the case back over. */
.shelf-back-info {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1 1 auto;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--on-blue);
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.shelf-back-heading,
.shelf-back-fact {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.shelf-back-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8125rem;
  line-height: 1.15;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.shelf-back-year {
  font-size: 0.6875rem;
  opacity: 0.6;
}

.shelf-back-label {
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.55;
}

.shelf-back-value {
  font-size: 0.9375rem;
  font-weight: 700;
}

/* The dashed perforation — the app's signature line. */
.shelf-back-perf {
  border-top: 2px dashed rgba(255, 255, 255, 0.22);
}

.shelf-back-links,
.shelf-back-actions.is-confirming {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.shelf-back-actions {
  display: grid;
}

.shelf-back-link,
.shelf-back-keep {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 4px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 4px;
  background: transparent;
  color: var(--on-blue);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}

/* Quieter than the buttons above it. */
.shelf-back-delete {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 4px;
  background: transparent;
  color: rgba(255, 255, 255, 0.75);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}

/* "Delete it" commits, so it gets the yellow fill with dark text. */
.shelf-back-yes {
  min-height: 44px;
  padding: 0 4px;
  border: none;
  border-radius: 4px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
}

.shelf-back-actions button:disabled {
  opacity: 0.5;
  cursor: default;
}

/* The case is always dark, so yellow text is readable here. */
.shelf-back-error {
  margin: 0;
  color: var(--yellow);
  font-size: 0.75rem;
  font-weight: 700;
}

.shelf-back-error:empty {
  display: none;
}

/* ---------- The Year: film details ----------
   List rows are now buttons that slide a details strip open underneath.
   Grid cases flip using the Shelf's .shelf-tape styles above; only the
   rank badge on the back is new here. */

/* The row is a button now, so it needs the browser's button look taken
   off. `button.` keeps this away from Home's top-10 rows, which share the
   .year-list-row class but are plain list items. */
button.year-list-row {
  width: 100%;
  border-top: none;
  border-left: none;
  border-right: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.year-list-chevron {
  flex: 0 0 auto;
  color: var(--text-muted);
  transition: transform 280ms ease;
}

.year-entry.is-open .year-list-chevron {
  transform: rotate(180deg);
}

.year-entry.is-open .year-list-title {
  font-weight: 700;
}

.year-list-row.year-highlight .year-list-chevron {
  color: var(--on-yellow);
}

/* The strip slides from zero height to its natural height. The grid-row
   trick animates to "however tall the content is" without measuring it. */
.year-details {
  display: grid;
  grid-template-rows: 0fr;
  background: var(--surface);
  transition: grid-template-rows 280ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.year-entry.is-open .year-details {
  grid-template-rows: 1fr;
  border-bottom: 1px solid var(--edge);
}

.year-entry.is-open .year-list-row {
  border-bottom-color: transparent;
}

.year-details-clip {
  overflow: hidden;
  min-height: 0;
}

/* Starts with the dashed perforation, and lines up under the poster. */
.year-details-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0 10px;
  padding: 12px 0 14px 40px;
  border-top: 2px dashed var(--edge);
}

/* The .year-facts label/value grid that used to sit here is gone — the
   phone details now show the same three facts as chips (.year-chips, in
   the ticket-stub section at the end of this file), and .year-details is
   display:none from 700px up, so nothing else rendered it. */

/* Ticket or TV icon beside Theater or Home — list and grid back alike. */
.year-where {
  display: flex;
  align-items: center;
  gap: 5px;
}

.year-where-icon {
  flex: 0 0 auto;
}

.year-links {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.year-link {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  border: 1px solid var(--edge);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
}

/* The back of a grid case: rank badge beside the title. */
.year-back-heading {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.year-back-heading .shelf-back-heading {
  min-width: 0;
}

.year-back-badge {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--on-yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

@media (min-width: 900px) {
  .year-details-body {
    margin: 0 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .year-details,
  .year-list-chevron {
    transition: none;
  }
}

/* Widens .screen for the 700–899px gap between the sidebar rail (from
   700px, css/sidebar.css) and the existing 900px breakpoint above — real
   iPads in portrait (mostly 744–834px) otherwise still got the 480px
   phone width. Added for Home's Stage 2 two-column layout (css/home.css);
   Year/Shelf/Rank just gain a bit more room in this range too, since
   .screen is shared. Bounded to max-width so it never overrides the
   existing 900px rule at 900px and up. */
@media (min-width: 700px) and (max-width: 899px) {
  .screen {
    max-width: 900px;
    padding: 28px 24px 110px;
  }
}

/* ================================================================
   Stage 3 of the laptop/tablet layout — the Rank a Film flow
   Phone (under 700px): no change. The step tracker and film panel below
   are display:none, and .rankflow-main is display:contents, so its
   children sit exactly where they always have — direct children of
   .rank-screen / .return-screen / .showdown-screen / .lands-screen, with
   that screen's own flex + gap untouched.

   700px and up: a step tracker across the top (Find it / Return slip /
   Showdown / Where it lands, with a Cancel link) and a two-column body —
   the film panel on the left, staying put through every step, and the
   step's own content on the right. Reuses each step's existing root
   class (.rank-screen etc., which now also carries .rankflow-step) as
   the grid container itself, so no extra wrapper element is needed —
   js/ui.js's stepTrackerHTML and filmPanelHTML build the two new pieces,
   shared by js/rank.js (step 1) and js/watch.js (steps 2–4).
   ================================================================ */

.step-tracker {
  display: none;
}

.rankflow-panel {
  display: none;
}

.rankflow-main {
  display: contents;
}

@media (min-width: 700px) {
  .rankflow-step {
    display: grid;
    grid-template-columns: 280px 1fr;
    grid-template-areas:
      "tracker tracker"
      "panel   main";
    align-items: start;
    gap: 20px;
    max-width: none;
    width: 100%;
    margin: 0;
  }

  /* The step tracker's own Cancel link replaces the phone-only one. */
  .rankflow-step > .back-link {
    display: none;
  }

  .step-tracker {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    grid-area: tracker;
  }

  .step-list {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .step-pill {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px 5px 4px;
    border-radius: 999px;
    background: var(--surface);
    border: 1px solid var(--edge);
    color: var(--text-muted);
    font-weight: 700;
    font-size: 0.7rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
  }

  .step-pill-marker {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--edge);
    color: var(--text);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 0.68rem;
  }

  .step-pill-current {
    background: var(--blue);
    border-color: var(--blue);
    color: var(--on-blue);
  }

  .step-pill-current .step-pill-marker {
    background: var(--on-blue);
    color: var(--blue);
  }

  .step-pill-done {
    color: var(--text);
  }

  .step-pill-done .step-pill-marker {
    background: var(--yellow);
    color: var(--on-yellow);
  }

  .step-cancel {
    flex: 0 0 auto;
    padding: 0 6px;
    font-size: 0.85rem;
  }

  /* The film panel — an empty dashed case before a film is picked, then
     the tilted poster and receipt. Sticky so it stays in view as the
     right column's content changes height between steps. */
  .rankflow-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    grid-area: panel;
    position: sticky;
    top: 20px;
    padding: 18px 16px;
    background: var(--surface);
    border: 1px solid var(--edge);
    border-radius: 12px;
    text-align: center;
  }

  .panel-empty {
    width: 100%;
    aspect-ratio: 2 / 3;
    border: 2px dashed var(--edge);
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 0.8rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
  }

  .panel-case {
    width: 62%;
    padding: 8px;
    background: var(--case-bg);
    border-radius: 6px;
    box-shadow: 0 14px 26px rgba(0, 0, 0, 0.35);
    transform: rotate(-4deg);
  }

  .panel-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
  }

  .panel-tag {
    padding: 3px 8px;
    border-radius: 3px;
    background: var(--yellow);
    color: var(--on-yellow);
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  .panel-title {
    font-size: 1.1rem;
    line-height: 1.05;
    color: var(--text);
    overflow-wrap: anywhere;
  }

  .panel-year {
    color: var(--text-muted);
    font-size: 0.8rem;
  }

  .panel-receipt {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 12px;
    border-top: 2px dashed var(--edge);
  }

  .panel-receipt-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
  }

  .panel-receipt-label {
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  .panel-receipt-value {
    color: var(--text);
    font-weight: 700;
    font-size: 0.875rem;
  }

  .rankflow-main {
    display: flex;
    flex-direction: column;
    gap: 18px;
    grid-area: main;
    min-width: 0;
  }

  /* Return Slip and Showdown/Where It Lands read better capped to a
     comfortable width rather than stretched to the full main column —
     the search step's results grid is the one that wants the extra room. */
  .return-screen .rankflow-main,
  .showdown-screen .rankflow-main {
    max-width: 600px;
  }

  /* The Return Slip's own small poster + title (phone only) is redundant
     once the film panel is showing the same thing on the left. */
  .return-hero {
    display: none;
  }
}

@media (min-width: 1200px) {
  .rankflow-step {
    grid-template-columns: 340px 1fr;
    gap: 28px;
  }
}

/* ================================================================
   Stage 4 of the laptop/tablet layout — the Year screen (Rental History)
   Phone (under 700px): no change. .rental-band is display:contents, so
   its children — the kicker/year/count (new, hidden here) and the
   original .year-switcher / .rental-header (unchanged) — sit exactly
   where they always have, direct children of .year-screen. The wide
   list's extra columns (.year-list-wide) and the column header row
   (.year-list-headrow) are display:none; the accordion rows and their
   tap-to-expand behaviour are untouched.

   700px and up: the switcher and heading move into one blue banded
   header (yellow top edge, rounded corners) with a big year number and
   film count on the left. The list shows every column at once — no
   expand — via .year-entry becoming a two-part grid: the row button
   (rank, poster, title, year) on the left, .year-list-wide (New to,
   Watched, date, IMDb/Trailer) on the right, both under one column
   header row. The grid view gains columns (5 iPad, 6 laptop). A past
   year gets a small closed-year note above the list.
   ================================================================ */

.rental-kicker,
.rental-year-row {
  display: none;
}

/* .rental-left wraps the kicker + year row only so 700px+ can stack them
   tightly (see below) — display:contents on phone makes the wrapper
   invisible to .rental-band's own grid, so .rental-kicker/.rental-year-row
   still sit exactly where the phone grid-template-areas expect them. */
.rental-left {
  display: contents;
}

.rental-count-rented {
  display: none;
}

.year-list-wide,
.year-list-headrow,
.year-closed-note {
  display: none;
}

/* The year number + chevron is one real <button> at 700px+ (a dropdown of
   years replaces the pills there) but stays plain, un-clickable-looking
   text on phone — reset everywhere so wrapping it in a button changes
   nothing about how .rental-year itself looks or sits, at any width. */
.rental-year-button {
  all: unset;
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  cursor: pointer;
}

.rental-year-picker {
  position: relative;
  display: inline-flex;
}

.rental-year-chevron,
.rental-year-menu,
.rental-bars,
.rental-receipt,
.rental-toolbar {
  display: none;
}

@media (min-width: 700px) {
  /* ---------- The header band ----------
     Three pieces beside the year block: the year dropdown replaces the
     pills, a month-by-month bar chart, and a cream receipt card — all
     built from films already loaded for this year (plus the previous
     year's, for Pace). iPad (700-1199px): the year block and receipt
     share a row, the bars get their own full-width row below. Laptop
     (1200px+, further down) makes all three one row instead. */

  .rental-band {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(220px, 300px);
    grid-template-areas:
      "left   receipt"
      "bars   bars";
    column-gap: 28px;
    row-gap: 14px;
    align-items: stretch;
    padding: 20px 26px 22px;
    background: var(--blue);
    border-top: 8px solid var(--yellow);
    border-radius: 14px;
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.22);
  }

  /* The kicker, year button and count as one tight stack, centred in
     whatever height the grid row gives this column — not spread to the
     row's own top and bottom. .rental-year-row goes display:contents so
     its two children (the year picker and the count) join .rental-kicker
     as three flat, evenly-gapped items instead of a nested row. */
  .rental-left {
    display: flex;
    grid-area: left;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: 10px;
  }

  .rental-year-row {
    display: contents;
  }

  .rental-kicker {
    display: block;
    color: var(--yellow);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    white-space: nowrap;
  }

  .rental-year {
    color: var(--on-blue);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 4.5rem; /* ~72px, iPad */
    line-height: 0.95;
    letter-spacing: -0.02em;
  }

  .rental-count {
    color: var(--yellow);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 1rem; /* ~16px, iPad */
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
  }

  .rental-count-rented {
    display: inline;
  }

  /* The dropdown replaces the pills here — see .year-switcher below. */
  .rental-year-chevron {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px; /* iPad — 40px from 1200px+, below */
    height: 44px;
    border: 2px solid rgba(255, 255, 255, 0.45);
    border-radius: 50%;
    background: none;
    color: var(--on-blue);
    transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
  }

  .rental-year-button:hover .rental-year-chevron,
  .rental-year-button[aria-expanded="true"] .rental-year-chevron {
    background: var(--yellow);
    border-color: var(--yellow);
    color: var(--on-yellow);
  }

  .rental-year-button[aria-expanded="true"] .rental-year-chevron {
    transform: rotate(180deg);
  }

  .rental-year-menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: 20;
    min-width: 130px;
    max-height: 240px;
    overflow-y: auto;
    padding: 6px;
    background: var(--surface);
    border: 1px solid var(--edge);
    border-radius: 10px;
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25);
  }

  .rental-year-menu.is-open {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  .rental-year-option {
    min-height: 44px;
    padding: 0 14px;
    border: none;
    border-radius: 6px;
    background: none;
    color: var(--text);
    font-weight: 600;
    text-align: left;
    cursor: pointer;
  }

  .rental-year-option:hover {
    background: var(--bg);
  }

  .rental-year-option.is-current {
    background: var(--yellow);
    color: var(--on-yellow);
  }

  /* The pills are only the phone way to switch years now — the dropdown
     above the band handles it here. */
  .rental-band .year-switcher {
    display: none;
  }

  /* ---------- Rentals by month ---------- */

  .rental-bars {
    display: block;
    grid-area: bars;
    padding-top: 14px;
    border-top: 1px dashed rgba(255, 255, 255, 0.3);
  }

  .rental-bars-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 10px;
  }

  .rental-bars-label {
    color: var(--yellow);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .rental-bars-busiest {
    color: var(--on-blue);
    opacity: 0.85;
    font-size: 0.7rem;
    font-weight: 600;
  }

  .rental-bars-busiest strong {
    opacity: 1;
  }

  .rental-bars-row {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    height: 90px; /* ~iPad */
  }

  .rental-bar-col {
    flex: 1 1 0;
    min-width: 0;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
    gap: 6px;
  }

  .rental-bar-track {
    width: 100%;
    max-width: 18px;
    height: 100%;
    display: flex;
    align-items: flex-end;
  }

  .rental-bar {
    width: 100%;
    min-height: 2px;
    border-radius: 3px 3px 0 0;
    background: rgba(255, 255, 255, 0.85); /* past months */
  }

  .rental-bar-current .rental-bar {
    background: var(--yellow);
  }

  .rental-bar-ghost {
    width: 100%;
    height: 14px;
    border-radius: 3px;
    border: 1px dashed rgba(255, 255, 255, 0.4);
    background: none;
  }

  .rental-bar-label {
    color: var(--on-blue);
    opacity: 0.75;
    font-size: 0.6rem;
    font-weight: 600;
    text-transform: uppercase;
  }

  .rental-bar-current .rental-bar-label {
    color: var(--yellow);
    opacity: 1;
  }

  .rental-bar-future .rental-bar-label {
    opacity: 0.45;
  }

  /* ---------- The receipt ---------- */

  .rental-receipt {
    display: block;
    grid-area: receipt;
    align-self: start;
    padding: 16px 16px 14px;
    background: var(--receipt-bg);
    color: var(--receipt-ink);
    border-radius: 4px;
    box-shadow: 0 10px 22px rgba(0, 0, 0, 0.28);
    transform: rotate(-2deg);
  }

  .rental-receipt-head {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: 10px;
    margin-bottom: 10px;
    border-bottom: 1px dashed var(--paper-dash, var(--receipt-edge));
    text-align: center;
  }

  .rental-receipt-brand {
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 0.8rem;
    letter-spacing: 0.06em;
  }

  .rental-receipt-sub {
    color: var(--receipt-muted);
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  .rental-receipt-rows {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .rental-receipt-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    font-size: 0.72rem;
  }

  .rental-receipt-label {
    flex: 0 0 auto;
    color: var(--receipt-muted);
    font-weight: 600;
    white-space: nowrap;
  }

  /* Title and "when" share the label's baseline, flowing together as
     plain inline text — wrapping only if the row runs out of room,
     rather than a stacked column or a forced single-line ellipsis. */
  .rental-receipt-value {
    flex: 1 1 auto;
    min-width: 0;
    text-align: right;
    font-weight: 700;
  }

  .rental-pace-up {
    color: var(--receipt-pace-up);
  }

  .rental-pace-down {
    color: var(--receipt-pace-down);
  }

  .rental-receipt-when {
    color: var(--receipt-muted);
    font-weight: 600;
    font-size: 0.65rem;
  }

  .rental-receipt-barcode {
    height: 22px;
    margin-top: 12px;
    background-image: repeating-linear-gradient(to right, var(--receipt-ink) 0 2px, transparent 2px 5px);
    opacity: 0.7;
  }

  /* ---------- The nested (phone-only) header hides; the toolbar below
     takes over the view toggle here ---------- */

  .rental-band .rental-header {
    display: none;
  }

  .rental-toolbar {
    display: flex;
    justify-content: flex-end;
  }

  /* ---------- The closed-year note ---------- */

  .year-closed-note {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border: 2px dashed var(--edge);
    border-radius: 8px;
    color: var(--text-muted);
    font-size: 0.85rem;
  }

  .year-closed-icon {
    flex: 0 0 auto;
  }

  /* ---------- Grid view: more columns, same flip-to-back cases ---------- */

  .year-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 18px;
  }

  /* ---------- List view: every column at once, no tap-to-expand ---------- */

  .year-list-row {
    cursor: default;
  }

  .year-list-chevron {
    display: none;
  }

  .year-details {
    grid-column: 1 / -1;
  }

  .year-entry {
    display: grid;
    grid-template-columns: 1fr 370px;
    align-items: center;
    gap: 12px;
    padding: 4px 0;
  }

  .year-list-headrow {
    display: grid;
    padding: 0 0 8px;
    border-bottom: 2px dashed var(--edge);
  }

  .year-head-film,
  .year-head-label {
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .year-head-film {
    padding-left: 78px; /* lines up under the row button's title, past its rank + poster */
  }

  .year-list-title {
    min-width: 0;
  }

  .year-list-wide {
    display: grid;
    grid-template-columns: 90px 100px 76px 110px;
    align-items: center;
    gap: 8px;
  }

  .year-wide-newto {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
  }

  .year-newto-circles {
    display: flex;
    flex: 0 0 auto;
  }

  .year-newto-initial {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border: 2px solid var(--surface);
  }

  .year-newto-initial img {
    width: 100%;
    height: 100%;
    display: block;
  }

  .year-newto-initial + .year-newto-initial {
    margin-left: -7px;
  }

  .year-newto-word,
  .year-wide-date {
    color: var(--text);
    font-size: 0.75rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .year-wide-watched.year-where {
    color: var(--text);
    font-size: 0.75rem;
    font-weight: 500;
  }

  .year-wide-links {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .year-wide-links .year-link {
    min-height: 44px;
    font-size: 0.65rem;
  }
}

@media (min-width: 1200px) {
  .rental-band {
    grid-template-columns: minmax(230px, 300px) 1fr minmax(240px, 320px);
    grid-template-areas: "left bars receipt";
    column-gap: 36px;
    padding: 24px 32px 26px;
  }

  .rental-year {
    font-size: 5.5rem; /* ~88px, laptop */
  }

  .rental-count {
    font-size: 1.125rem; /* ~18px, laptop */
  }

  .rental-year-chevron {
    width: 40px;
    height: 40px;
  }

  /* One middle column instead of its own row, with a dashed divider on
     each side instead of the dashed line above it. */
  .rental-bars {
    padding: 0 28px;
    border-top: none;
    border-left: 1px dashed rgba(255, 255, 255, 0.3);
    border-right: 1px dashed rgba(255, 255, 255, 0.3);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .rental-bars-row {
    height: 110px; /* ~laptop */
  }

  .year-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .year-entry {
    grid-template-columns: 1fr 470px;
    gap: 20px;
  }

  .year-head-film {
    padding-left: 88px;
  }

  .year-list-wide {
    grid-template-columns: 110px 120px 90px 120px;
    gap: 12px;
  }

  .year-newto-word,
  .year-wide-date,
  .year-wide-watched.year-where {
    font-size: 0.85rem;
  }

  .year-wide-links {
    flex-direction: row;
    gap: 8px;
  }

  .year-wide-links .year-link {
    min-height: 44px;
    font-size: 0.7rem;
  }
}
/* ================================================================
   Stage 5 of the laptop/tablet layout — the Shelf screen
   Phone (under 700px): no change. .shelf-header is display:contents, so
   its children — the title, the film count (new, hidden here) and the
   existing search field — sit exactly where they always have, direct
   children of .shelf-screen. The search results' Add tag, the
   Already-on-your-shelf tag, and the Just Added sticker are all
   display:none; tapping a result opens the same add panel it always has.

   700px and up: title + film count on the left with the search field
   stretched across the middle, in one row with a dashed divider under
   it. No Staff Pick button — SPEC.md lists that screen as deferred, so
   it's left out for now, the same call made for Manage Labels below.
   Search results become a bordered panel of two-column rows (small
   poster, title/year, an Add tag), with an Already-on-your-shelf tag
   replacing Add for a film already on the Shelf — both computed from
   films already loaded, no new lookups. The case grid gains columns (5
   iPad, 6 laptop), same flip-to-back cases. A film just added shows a
   yellow Just Added sticker and sorts first in the grid for the rest of
   the visit (skipped if that film is also Coming Soon, so the two
   ribbon stickers never stack).
   ================================================================ */

.shelf-header {
  display: contents;
}

.shelf-count {
  display: block;
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.ja-sticker {
  display: none;
}

@media (min-width: 700px) {
  .shelf-header {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: end;
    column-gap: 24px;
    row-gap: 4px;
    padding-bottom: 18px;
    border-bottom: 2px dashed var(--edge);
  }

  .shelf-count {
    display: block;
    grid-column: 1;
    grid-row: 2;
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
  }

  .shelf-header .search-field {
    grid-column: 2;
    grid-row: 1 / 3;
    align-self: center;
  }

  /* ---------- Search results: a bordered panel of rows ---------- */

  .search-results {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 6px 16px;
    background: var(--surface);
    border: 1px solid var(--edge);
    border-radius: 10px;
    padding: 12px;
  }

  .search-result {
    display: grid;
    grid-template-columns: 44px 1fr auto;
    grid-template-rows: auto auto;
    column-gap: 10px;
    row-gap: 2px;
    align-items: center;
    background: none;
    box-shadow: none;
    padding: 6px;
    border-radius: 6px;
  }

  .search-result:hover {
    background: var(--bg);
  }

  .search-result .vhs-sleeve {
    grid-column: 1;
    grid-row: 1 / 3;
    width: 44px;
  }

  .search-result .vhs-title {
    grid-column: 2;
    grid-row: 1;
    color: var(--text);
  }

  .search-result .vhs-year {
    grid-column: 2;
    grid-row: 2;
    color: var(--text-muted);
  }

  .search-result-add {
    display: flex;
    grid-column: 3;
    grid-row: 1 / 3;
    align-items: center;
    justify-content: center;
    min-width: 60px;
    min-height: 44px;
    padding: 0 14px;
    border-radius: 6px;
    background: var(--yellow);
    color: var(--on-yellow);
    font-weight: 700;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
  }

  .search-result-owned-tag {
    display: block;
    grid-column: 3;
    grid-row: 1 / 3;
    max-width: 90px;
    color: var(--text-muted);
    font-size: 0.65rem;
    font-weight: 700;
    text-align: right;
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }

  /* The Shelf rework's phone-only text swaps (see the section at the end
     of this file) — desktop keeps the original wording. */
  .sr-add-phone,
  .sr-owned-phone {
    display: none;
  }

  .search-result-owned {
    opacity: 0.55;
    pointer-events: none;
  }

  .search-result-owned .search-result-add {
    display: none;
  }

  /* ---------- The case grid: more columns, same flip-to-back cases ---------- */

  .shelf {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 18px;
  }

  /* ---------- The "Just added" sticker ---------- */

  .ja-sticker {
    position: absolute;
    top: 12px;
    left: 0;
    right: 14px;
    z-index: 1;
    display: block;
    padding: 8px 10px;
    border-radius: 0 3px 3px 0;
    background: var(--yellow);
    color: var(--on-yellow);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    text-align: left;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.35);
    transform: rotate(-3deg);
    pointer-events: none;
  }
}

@media (min-width: 1200px) {
  .shelf {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

/* ================================================================
   Stage 7a — Your Card, part 1: the counter
   Replaces Stage 6a's card + details panel and Stage BO-1's door sign
   with one layout that works at every width: no phone-vs-700px split,
   nothing hidden by media query. `.cc-layout` is a CSS grid whose four
   named areas (card, receipt, signout, plaque) are the same four
   children throughout — only the grid's own template changes, from
   one stacked column on phone to a two-column one from 700px. Every
   class here is new (a "cc-" prefix) and scoped under .card-screen;
   the .membership-card/.card-button/.card-field styles above are
   untouched.

   The card and receipt are physical objects, the same reasoning as
   --case-bg and --card-stock: they keep one fixed colour regardless
   of the store light (only the page header text follows the theme).
   The receipt reuses the --receipt-* tokens already defined for the
   Rental History header's own receipt (.rental-receipt, further up
   this file) rather than a second set. The card needed one new fixed
   token, --card-navy — its old --blue background did follow the
   theme, which this stage's card should no longer do; its plain
   white text follows --case-bg's own convention (see .vhs-case) of
   not needing a paired "on-" token.
   ================================================================ */




/* ---------- The grid that reflows card / receipt / signout / plaque ---------- */

.cc-layout {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas:
    "card"
    "receipt"
    "signout"
    "plaque";
  justify-items: center;
}

/* On phone these wrappers aren't boxes at all — display:contents lifts
   their two children (card + plaque, or receipt + Sign Out) straight into
   .cc-layout's own grid, which places each leaf by its own grid-area
   exactly as if the wrapper weren't there. From 620px each one becomes a
   real flex column instead — see below. */
.cc-col-card,
.cc-col-receipt {
  display: contents;
}

/* The two-column switch is gated on the card-screen's own rendered
   width (@container, not @media — see the .card-screen comment above),
   not a flat "700px": the sidebar rail leaves as little as ~550px of
   real room at a 700px viewport, which would clip a fixed two-column
   layout. minmax() column tracks below size the card and receipt
   fluidly within whatever room actually exists, reaching their target
   sizes (card ~580px, receipt ~360px) only once the container is wide
   enough — in practice that ends up being iPad-and-up, not literally
   700px wide.

   Only one grid row now ("card receipt") — .cc-col-card and
   .cc-col-receipt are themselves the grid items, each a flex column
   stacking its own two children with its own margin-top below. The
   original layout put plaque and Sign Out in a *second* shared grid row,
   which forced them to start at the same y regardless of whether card or
   receipt was taller — so the gap under the shorter one was wrong. Two
   independent columns fix that: the plaque's gap is measured from the
   card's own bottom, Sign Out's from the receipt's own bottom, full stop. */
@container cardscreen (min-width: 620px) {
  .cc-layout {
    grid-template-columns: minmax(320px, 580px) minmax(240px, 360px);
    grid-template-areas: "card receipt";
    justify-content: center;
    align-items: start;
    column-gap: 80px;
  }

  .cc-col-card,
  .cc-col-receipt {
    display: flex;
    flex-direction: column;
    width: 100%;
  }

  .cc-col-card {
    grid-area: card;
    align-items: flex-start;
  }

  .cc-col-receipt {
    grid-area: receipt;
    align-items: center;
  }
}

/* ---------- The card, and its flip (Stage 7b) ----------
   .cc-card is the outer button: sizing, tilt and perspective only, no
   longer a background or padding of its own. .cc-card-inner is what
   actually turns (rotateY, on .is-flipped); .cc-card-front/.cc-card-back
   are its two faces, each absolutely filling the button and hidden on
   their own back (backface-visibility) so only one is ever visible.
   prefers-reduced-motion, further down, swaps that 3D turn for a quick
   opacity cross-fade instead. */

.cc-card {
  grid-area: card;
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  max-width: 350px;
  aspect-ratio: 350 / 250;
  padding: 0;
  border: none;
  border-radius: 14px;
  background: transparent;
  transform: rotate(-2deg);
  perspective: 1400px;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: #ffffff;
}

.cc-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: transform 0.6s ease;
  transform-style: preserve-3d;
}

.cc-card.is-flipped .cc-card-inner {
  transform: rotateY(180deg);
}

.cc-card-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  background: var(--card-navy);
  box-shadow: 0 16px 34px rgba(0, 0, 0, 0.3);
  backface-visibility: hidden;
}

.cc-card-front {
  justify-content: space-between;
  gap: 16px;
  padding: 18px;
}

.cc-card-front::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 16px;
  border-radius: 14px 14px 0 0;
  background: var(--yellow);
}

.cc-card-back {
  transform: rotateY(180deg);
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .cc-card-inner,
  .cc-card-face {
    transition: opacity 0.15s ease;
  }

  .cc-card.is-flipped .cc-card-inner {
    transform: none;
  }

  .cc-card-back {
    transform: none;
    opacity: 0;
  }

  .cc-card.is-flipped .cc-card-front {
    opacity: 0;
  }

  .cc-card.is-flipped .cc-card-back {
    opacity: 1;
  }
}

.cc-card-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.cc-card-top {
  align-items: flex-start;
}

.cc-card-brand {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.cc-card-brand-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 18px;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.cc-card-brand-sub {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.82;
}

.cc-card-valid {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  padding: 5px 7px;
  border-radius: 6px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 9px;
  line-height: 1.05;
  letter-spacing: 0.06em;
  text-align: center;
  text-transform: uppercase;
  transform: rotate(7deg);
}

.cc-card-middle {
  gap: 14px;
  justify-content: flex-start;
}

.cc-card-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid #ffffff;
  background: var(--blue);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.2rem;
}

.cc-card-avatar img {
  width: 100%;
  height: 100%;
  display: block;
}

.cc-card-name-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.cc-card-name {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 36px;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  line-height: 0.95;
}

.cc-card-other {
  display: flex;
  align-items: center;
  gap: 6px;
}

.cc-card-other-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.7);
  background: var(--blue);
  font-size: 0.6rem;
}

.cc-card-other-avatar img {
  width: 100%;
  height: 100%;
  display: block;
}

.cc-card-other-text {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.88;
}

.cc-card-bottom {
  align-items: flex-end;
}

.cc-card-since-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.cc-card-since {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.82;
}

.cc-card-barcode {
  height: 24px;
  display: flex;
  align-items: stretch;
}

.cc-card-barcode span {
  display: block;
  background: rgba(255, 255, 255, 0.9);
}

.cc-card-flip-hint {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  color: var(--yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.cc-card-flip-hint svg {
  width: 13px;
  height: 13px;
}

@container cardscreen (min-width: 620px) {
  .cc-card {
    width: 100%;
    max-width: 580px;
    aspect-ratio: 580 / 372;
    transform: rotate(-3deg);
  }

  .cc-card-front {
    padding: 30px;
  }

  .cc-card-front::before {
    height: 24px;
  }

  .cc-card-brand-title {
    font-size: 28px;
  }

  .cc-card-brand-sub {
    font-size: 12px;
    letter-spacing: 0.16em;
  }

  .cc-card-valid {
    padding: 8px 10px;
    font-size: 12px;
  }

  .cc-card-avatar {
    width: 92px;
    height: 92px;
    font-size: 1.6rem;
  }

  .cc-card-name {
    font-size: 58px;
  }

  .cc-card-other-avatar {
    width: 30px;
    height: 30px;
  }

  .cc-card-other-text {
    font-size: 12px;
  }

  .cc-card-since {
    font-size: 12px;
    letter-spacing: 0.14em;
  }

  .cc-card-barcode {
    height: 34px;
  }

  .cc-card-flip-hint {
    font-size: 12px;
    letter-spacing: 0.12em;
  }

  .cc-card-flip-hint svg {
    width: 16px;
    height: 16px;
  }
}

/* ---------- The card back: the punch card (Stage 7b) ----------
   A black magnetic stripe near the top, then the punch grid and label
   row, the signature strip, and the fine print/"Flip back" footer.
   Sized phone-first to match the phone mockup, then scaled up to the
   desktop mockup's own numbers at the same 620px container breakpoint
   the front face uses. */

.cc-card-stripe {
  display: block;
  margin-top: 16px;
  height: 34px;
  background: var(--card-stripe);
  flex-shrink: 0;
}

.cc-card-back-body {
  flex: 1;
  min-height: 0;
  box-sizing: border-box;
  padding: 10px 16px 12px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 7px;
  /* The mockup never set its own line-height, so it inherited whatever
     "normal" resolves to for Archivo — but this app's global `html body`
     rule sets line-height:1.4, which (plus stray whitespace between the
     inline spans below) made every row taller than the mockup's own
     numbers assumed, overflowing the card. line-height:1 here removes
     that, tightening every row back down to its text's own font-size. */
  line-height: 1;
}

.cc-punch-label-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.cc-punch-label {
  font-size: 9px;
  font-weight: 700;
  /* Tighter than the mockup's 0.12em: at this width, the full label text
     at 0.12em doesn't fit on one line even in the mockup itself (checked
     by rendering it) — it wraps, which is what blew the height budget.
     nowrap plus a smaller tracking keeps it on one line without changing
     the font-size the mockup specified. */
  letter-spacing: 0.06em;
  white-space: nowrap;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.88);
}

.cc-punch-free {
  flex-shrink: 0;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--yellow);
  white-space: nowrap;
}

.cc-punch-grid {
  display: grid;
  grid-template-columns: repeat(10, 21px);
  justify-content: space-between;
  row-gap: 6px;
}

.cc-punch {
  width: 21px;
  height: 21px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 2px dashed rgba(255, 255, 255, 0.4);
  color: var(--yellow);
}

.cc-punch-filled {
  border: none;
  background: var(--bg);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5);
}

.cc-punch-filled.cc-punch-tenth {
  box-shadow: 0 0 0 3px var(--yellow), inset 0 2px 4px rgba(0, 0, 0, 0.5);
}

.cc-punch-tenth:not(.cc-punch-filled) {
  border-color: var(--yellow);
}

.cc-punch svg {
  width: 10px;
  height: 10px;
}

.cc-sig-block {
  display: flex;
  flex-direction: column;
  /* Trimmed from the mockup's implicit ~4px (its own unset line-height
     left slack here) to keep the card's total height inside the frame —
     see the .cc-card-back-body comment above. */
  gap: 2px;
}

.cc-sig-caption {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75);
}

.cc-sig-strip {
  display: flex;
  align-items: center;
  justify-content: space-around;
  height: 30px;
  border-radius: 4px;
  background-image: repeating-linear-gradient(135deg, var(--card-sig-a) 0 7px, var(--card-sig-b) 7px 9px);
  color: var(--card-navy);
  font-family: "Caveat", cursive;
  font-weight: 600;
  font-size: 21px;
}

.cc-sig-name-a {
  transform: rotate(-3deg);
}

.cc-sig-name-b {
  transform: rotate(2deg);
}

.cc-card-back-footer {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 16px;
}

.cc-card-fineprint {
  font-size: 9px;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.78);
}

.cc-card-fineprint-full {
  display: none;
}

.cc-card-fineprint-short {
  display: block;
}

.cc-card-flip-back {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  color: var(--yellow);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

.cc-card-flip-back svg {
  width: 13px;
  height: 13px;
}

@container cardscreen (min-width: 620px) {
  .cc-card-stripe {
    margin-top: 20px;
    height: 40px;
  }

  .cc-card-back-body {
    /* Shrunk again (round 3) — the round-2 numbers above still clipped the
       signature strip and hid the fine print/Flip back row once actually
       rendered, even inside a card with overflow:hidden. These leave room
       to spare inside the 580 x 372 card. */
    padding: 14px 28px 16px;
    gap: 10px;
  }

  .cc-punch-label {
    font-size: 12px;
  }

  .cc-punch-free {
    font-size: 14px;
  }

  .cc-punch-grid {
    grid-template-columns: repeat(10, 24px);
    row-gap: 8px;
  }

  .cc-punch {
    width: 24px;
    height: 24px;
  }

  .cc-punch svg {
    width: 14px;
    height: 14px;
  }

  .cc-sig-caption {
    font-size: 11px;
  }

  .cc-sig-strip {
    height: 38px;
    font-size: 26px;
  }

  .cc-card-fineprint {
    font-size: 11px;
  }

  .cc-card-fineprint-full {
    display: block;
  }

  .cc-card-fineprint-short {
    display: none;
  }

  .cc-card-flip-back {
    font-size: 11px;
  }

  .cc-card-flip-back svg {
    width: 15px;
    height: 15px;
  }
}

/* ---------- The receipt ----------
   Tucked under the card on phone: pulled up ~30px (negative margin)
   behind the card's own higher z-index, with extra top padding so its
   own heading still clears the card's bottom edge. From 700px they sit
   side by side instead, so both reset to normal. */

.cc-receipt {
  grid-area: receipt;
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 300px;
  margin-top: -30px;
  padding: 48px 20px 30px;
  background: var(--receipt-bg);
  color: var(--receipt-ink);
  border-radius: 3px 3px 0 0;
  filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.25));
  transform: rotate(1deg);
}

/* The torn edge: a separate 8px strip fused to the receipt's bottom
   edge, same technique as the mockup's own two-part receipt — teeth
   12px wide (6px steps), 8px deep. Pixel-based so it lines up exactly
   with the receipt's two target widths (300/360); real phones are
   comfortably wider than 300px + the screen's own side padding, so
   the fixed coordinates always land inside the rendered box. */
.cc-receipt::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -8px;
  height: 8px;
  background: var(--receipt-bg);
  clip-path: polygon(0 0, 300px 0, 294px 8px, 288px 0, 282px 8px, 276px 0, 270px 8px, 264px 0, 258px 8px, 252px 0, 246px 8px, 240px 0, 234px 8px, 228px 0, 222px 8px, 216px 0, 210px 8px, 204px 0, 198px 8px, 192px 0, 186px 8px, 180px 0, 174px 8px, 168px 0, 162px 8px, 156px 0, 150px 8px, 144px 0, 138px 8px, 132px 0, 126px 8px, 120px 0, 114px 8px, 108px 0, 102px 8px, 96px 0, 90px 8px, 84px 0, 78px 8px, 72px 0, 66px 8px, 60px 0, 54px 8px, 48px 0, 42px 8px, 36px 0, 30px 8px, 24px 0, 18px 8px, 12px 0, 6px 8px, 0 0);
}

@container cardscreen (min-width: 620px) {
  .cc-receipt {
    width: 100%;
    max-width: 360px;
    margin-top: 0;
    padding: 20px 20px 30px;
    transform: rotate(1deg);
  }

  .cc-receipt::after {
    clip-path: polygon(0 0, 360px 0, 354px 8px, 348px 0, 342px 8px, 336px 0, 330px 8px, 324px 0, 318px 8px, 312px 0, 306px 8px, 300px 0, 294px 8px, 288px 0, 282px 8px, 276px 0, 270px 8px, 264px 0, 258px 8px, 252px 0, 246px 8px, 240px 0, 234px 8px, 228px 0, 222px 8px, 216px 0, 210px 8px, 204px 0, 198px 8px, 192px 0, 186px 8px, 180px 0, 174px 8px, 168px 0, 162px 8px, 156px 0, 150px 8px, 144px 0, 138px 8px, 132px 0, 126px 8px, 120px 0, 114px 8px, 108px 0, 102px 8px, 96px 0, 90px 8px, 84px 0, 78px 8px, 72px 0, 66px 8px, 60px 0, 54px 8px, 48px 0, 42px 8px, 36px 0, 30px 8px, 24px 0, 18px 8px, 12px 0, 6px 8px, 0 0);
  }
}

.cc-receipt-heading {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px dashed var(--paper-dash, var(--receipt-edge));
  text-align: center;
}

.cc-receipt-heading-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.cc-receipt-heading-sub {
  color: var(--receipt-muted);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.cc-receipt-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 3px 0;
  font-size: 0.78rem;
  /* Tightens -label and -value (different font-sizes) down to just their
     own text height, instead of each carrying the global line-height:1.4
     at a different px value. The row itself is already correctly built —
     one flex container, space-between, baseline, label and value as its
     only two children, nothing block-level or dl/dt/dd in the mix — the
     remaining stagger between them is the receipt's own tilt (it rotates
     as one rigid piece, so a wide row's right edge sits a few px lower
     than its left, same as the mockup does when actually rendered). */
  line-height: 1;
}

.cc-receipt-label {
  flex: 0 0 auto;
  color: var(--receipt-muted);
  font-weight: 600;
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.cc-receipt-value {
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
  font-weight: 700;
  word-break: break-word;
}

.cc-receipt-rule {
  margin: 10px 0;
  border-bottom: 1px dashed var(--paper-dash, var(--receipt-edge));
}

.cc-receipt-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  text-align: center;
}

.cc-receipt-bekind {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.cc-receipt-barcode {
  width: 130px;
  height: 20px;
  background-image: repeating-linear-gradient(to right, var(--receipt-ink) 0 2px, transparent 2px 5px);
  opacity: 0.7;
}

.cc-receipt-thanks {
  color: var(--receipt-muted);
  font-size: 0.7rem;
}

/* ---------- Sign out ---------- */

.cc-signout {
  grid-area: signout;
  width: 100%;
  max-width: 350px;
  margin-top: 20px;
  min-height: 52px;
  padding: 0 24px;
  font-size: 1rem;
}

@container cardscreen (min-width: 620px) {
  .cc-signout {
    width: auto;
    max-width: none;
    padding: 0 36px;
    /* 30px from the receipt's own visual bottom corner — the receipt
       tilts (rotate(2.5deg)), which pushes its lowest visual point a few
       px past its unrotated layout box, so this reads a little larger
       than a flat 30px would. */
    margin-top: 38px;
  }
}

/* ---------- The door plaque (was Stage BO-1's .door-sign) ----------
   The "EMPLOYEES ONLY" link that opens the Back Office (js/back-
   office.js) — same id and click handler as before, restyled: a fixed
   black plaque, like the VHS case (--case-bg), with four screw dots
   and a yellow arrow. */

.door-sign {
  grid-area: plaque;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  max-width: 320px;
  min-height: 44px;
  margin-top: 20px;
  padding: 14px 22px;
  border: none;
  border-radius: 8px;
  background: var(--case-bg);
  color: #ffffff;
  text-align: left;
  cursor: pointer;
}

@container cardscreen (min-width: 620px) {
  .door-sign {
    max-width: 460px;
    /* 64px from the card's own visual bottom corner. The card tilts
       (rotate(-3deg) at this width) and is much wider than it is tall, so
       that rotation pushes its lowest visual point well past its
       unrotated layout box — this reads a good deal larger than a flat
       64px would to actually land 64px below what the eye sees as the
       card's corner. .cc-col-card's own align-items:flex-start (not
       justify-self, now that this is a flex item of that column, not a
       grid item of .cc-layout) is what keeps it left-aligned under the
       card instead of centered. */
    margin-top: 85px;
  }
}

.door-sign-screw {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--plaque-screw);
}

.door-sign-screw:nth-of-type(1) { top: 7px; left: 7px; }
.door-sign-screw:nth-of-type(2) { top: 7px; right: 7px; }
.door-sign-screw:nth-of-type(3) { bottom: 7px; left: 7px; }
.door-sign-screw:nth-of-type(4) { bottom: 7px; right: 7px; }

.door-sign-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.door-sign-plaque {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.9375rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.door-sign-sub {
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.75rem;
}

.door-sign-arrow {
  flex-shrink: 0;
  color: var(--yellow);
}

/* ================================================================
   Stage 6b — disabled filter chips
   Used by Home's "Pull from" row (css/home.css) for a label with
   nothing eligible on the Shelf right now. Shares .shelf-talker with
   the Shelf's own filter chips, which never disables one.
   ================================================================ */

.shelf-talker:disabled {
  opacity: 0.28;
  cursor: not-allowed;
}

/* ================================================================
   Stage 6c — Manage Labels
   Reached only from the Shelf's own "Manage labels" link, at the end
   of its filter chip row (js/shelf-flow.js). No sidebar or drawer
   entry — js/main.js keeps the Shelf highlighted in the menu while
   it's open.

   Phone: a single column of rows, same pieces at every width. 700px
   and up: the column widens (up to ~820px) with roomier row spacing.
   ================================================================ */

.manage-labels-link {
  display: flex;
  align-items: center;
  padding: 0 4px;
  font-size: 0.8rem;
}

.labels-screen {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.labels-intro {
  margin: 0;
  color: var(--text-muted);
}

.labels-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.labels-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  padding: 14px;
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--surface);
}

.labels-row-editing,
.labels-row-confirm {
  flex-direction: column;
  align-items: stretch;
}

.labels-sticker {
  flex: none;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-weight: 700;
  font-size: 0.8125rem;
}

.labels-sticker-locked {
  background: var(--blue);
  color: var(--yellow);
}

.labels-count {
  flex: 1 1 auto;
  min-width: 140px;
  color: var(--text-muted);
  font-size: 0.875rem;
}

.labels-row-locked {
  opacity: 0.85;
}

.labels-row-actions {
  flex: none;
  display: flex;
  gap: 8px;
}

.labels-rename,
.labels-remove,
.labels-cancel {
  padding: 0 14px;
  font-size: 0.8125rem;
}

.labels-save,
.labels-remove-yes,
.labels-add-button {
  padding: 0 16px;
  font-size: 0.8125rem;
}

.labels-rename-input,
.labels-add-input {
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
  font-size: 1rem;
}

.labels-confirm-text {
  margin: 0;
  color: var(--text);
}

.labels-row-error {
  margin: 0;
  color: var(--danger);
  font-size: 0.8125rem;
  font-weight: 700;
}

.labels-add {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 14px;
  border: 2px dashed var(--edge);
  border-radius: 10px;
}

.labels-add-input {
  flex: 1 1 200px;
  background: var(--surface);
}

.labels-add-button {
  flex: none;
}

.labels-add .labels-row-error {
  flex-basis: 100%;
}

@media (min-width: 700px) {
  .labels-screen {
    max-width: 820px;
  }

  .labels-row,
  .labels-add {
    padding: 18px 20px;
    gap: 12px 20px;
  }
}

/* ================================================================
   Stage 4b of the laptop/tablet layout — the Year list view, redesigned
   Phone (under 700px): no change — same accordion, same markup
   behaviour. Grid view: no change at any width.

   700px and up, list view only:
   - Three bugs fixed: a row click no longer opens the (now-removed)
     accordion strip, .year-details is hidden outright, and a mouse
     click no longer leaves an outline box (:focus-visible only; a
     light var(--bg) hover tint on the row instead).
   - Ranks 1–3 move onto a "Top of the Charts" shelf — a card of three
     VHS cases (js/year.js's topChartsHTML) sitting above the sheet.
   - Ranks 4 and down stay in the existing accordion markup (js/year.js's
     rowHTML/.year-entry), which becomes a "printout sheet" card at this
     width: tractor-feed edges, greenbar row striping, and a rubber-stamp
     Returned date. .year-list-row and .year-list-wide switch to
     display:contents so their children — rank, poster, film, New to,
     Watched, Returned, Links — line up as one flat grid on .year-entry,
     rather than the phone's two-part button-plus-strip layout. A year
     with three films or fewer hides the sheet, header row included;
     ranks 1–3 (.year-podium-row) are hidden either way, since the shelf
     above already shows them.
   - The column widths live once as --sheet-cols, a custom property set
     on .year-sheet-inner and read by every .year-entry's
     grid-template-columns, so the header row and every film row always
     line up. Fixed post-launch: which layout applies is chosen by the
     SHEET's own rendered width (@container sheet queries on .year-sheet,
     which is a container-type:inline-size box), not the window's — a
     sidebar or rail can leave the sheet narrower than the viewport
     implied, and picking by window width let the Links column run past
     the sheet's right edge. Three layouts:
       a) sheet 1150px+: full — rank 52px | poster 60px | film
          minmax(260px, 1fr) | New to 112px | Watched 112px | Returned
          132px | Links 168px, 16px gap, New to/Watched as two real
          columns.
       b) sheet 900–1149px: rank 44px | poster 60px (54x80 case) | film
          minmax(220px, 1fr) | a merged New to/Watched cell 120px |
          Returned 128px | Links 160px, 14px gap. js/year.js wraps New
          to and Watched in one .year-wide-newtowatched
          (.year-head-newtowatched for the header), a vertical flex
          stack (circles+name over icon+word) at this width and below;
          it becomes display:contents at 1150px+, splitting back into
          two real grid columns.
       c) sheet under 900px: rank 40px | poster 48px (44x64 case) |
          film minmax(160px, 1fr) | one "Details" column 132px | Links
          96px, 12px gap. Details stacks New to, Watched and the
          Returned stamp (still the same three markup cells, just
          regrouped visually: .year-wide-newtowatched sits in the
          entry's row 1, .year-wide-date in row 2, both in the Details
          column, with rank/poster/film/Links spanning both rows via
          grid-row:1/-1 to stay vertically centered); the header label
          switches to "Details" (.year-head-details). IMDb/Trailer
          (.year-wide-links) stack instead of sitting side by side.
     In every layout the film cell keeps min-width:0 and clamps its
     title to two lines with an ellipsis (a title attribute carries the
     full name for a hover tooltip), and the Returned stamp and the
     IMDb/Trailer tags are white-space:nowrap. .year-sheet-inner also
     gets overflow-x:auto as a safety net, so a layout that still
     doesn't fit scrolls inside the sheet's own frame instead of
     clipping. The tractor-feed edge graphic stays sized off the
     window (cosmetic only, doesn't affect whether columns fit).
   ================================================================ */

.year-charts-card {
  display: none;
}

@media (min-width: 700px) {
  /* ---------- Bug fixes ---------- */

  .year-details {
    display: none;
  }

  /* ---------- Top of the Charts (ranks 1–3) ---------- */

  .year-charts-card {
    display: block;
    position: relative;
    margin-bottom: 22px;
    background: var(--surface);
    border: 1px solid var(--edge);
    border-radius: 14px;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
    padding: 22px 28px 0;
    overflow: hidden;
  }

  .year-charts-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px 16px;
    padding-bottom: 14px;
    border-bottom: 2px dashed var(--edge);
  }

  .year-charts-title {
    margin: 0;
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 1.125rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text);
  }

  .year-charts-sub {
    color: var(--text-muted);
    font-size: 0.8125rem;
  }

  .year-charts-row {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 36px;
    padding: 26px 8px 24px;
  }

  .year-charts-ledge {
    height: 16px;
    margin: 0 -28px;
    background: var(--blue);
  }

  .year-chart-case {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .year-chart-case[data-rank="1"] {
    order: 2;
  }

  .year-chart-case[data-rank="2"] {
    order: 1;
  }

  .year-chart-case[data-rank="3"] {
    order: 3;
  }

  .year-chart-vhs {
    position: relative;
    width: 136px;
    background: var(--case-bg);
    padding: 7px;
    border-radius: 6px;
    box-shadow: 0 14px 26px rgba(0, 0, 0, 0.32);
  }

  .year-chart-case[data-rank="1"] .year-chart-vhs {
    width: 170px;
  }

  .year-chart-case[data-rank="2"] .year-chart-vhs {
    transform: rotate(-3deg);
  }

  .year-chart-case[data-rank="3"] .year-chart-vhs {
    transform: rotate(3deg);
  }

  .year-chart-vhs .vhs-sleeve {
    aspect-ratio: 2 / 3;
  }

  .year-chart-case.year-highlight .year-chart-vhs {
    box-shadow: 0 0 0 3px var(--yellow), 0 14px 26px rgba(0, 0, 0, 0.32);
  }

  .year-chart-badge {
    position: absolute;
    top: -14px;
    left: -14px;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--yellow);
    color: var(--sticker-ink);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 1.25rem;
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
  }

  .year-chart-case[data-rank="1"] .year-chart-badge {
    width: 60px;
    height: 60px;
    font-size: 1.625rem;
  }

  .year-chart-caption {
    margin-top: 14px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    max-width: 180px;
  }

  .year-chart-title {
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    text-transform: uppercase;
    color: var(--text);
    font-size: 1rem;
  }

  .year-chart-case[data-rank="1"] .year-chart-title {
    font-size: 1.25rem;
  }

  .year-chart-meta {
    color: var(--text-muted);
    font-size: 0.8125rem;
  }

  .year-chart-links {
    display: flex;
    gap: 8px;
  }

  /* ---------- The link tags shared by the shelf and the sheet ---------- */

  .year-sheet-link {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 0 12px;
    border: 1px solid var(--edge);
    border-radius: 8px;
    background: var(--surface);
    color: var(--text);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
  }

  /* ---------- The printout sheet (ranks 4 and down) ---------- */

  .year-sheet-empty {
    display: none;
  }

  .year-sheet {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--edge);
    border-radius: 14px;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    /* The column layout below is chosen by this element's own rendered
       width (@container sheet queries), not the window's — so it holds
       up next to the sidebar/rail at any viewport size. */
    container-type: inline-size;
    container-name: sheet;
  }

  .year-sheet::before,
  .year-sheet::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 22px;
    background-image: radial-gradient(circle, var(--feed-hole) 4px, var(--edge) 4px 4.5px, transparent 4.5px);
    background-repeat: repeat-y;
    background-position: center top;
    background-size: 100% 22px;
  }

  .year-sheet::before {
    left: 0;
  }

  .year-sheet::after {
    right: 0;
  }

  .year-sheet-inner {
    margin: 0 22px;
    padding: 0 16px;
    border-left: 2px dashed var(--edge);
    border-right: 2px dashed var(--edge);
    /* Safety net: if a column layout still doesn't fit (a very narrow
       or unusual sheet width), it scrolls sideways inside its own
       frame instead of clipping the Links column. */
    overflow-x: auto;
  }

  .year-list-headrow.year-entry {
    border-bottom: 2px dashed var(--edge);
  }

  .year-head-film {
    grid-column: 3;
    padding-left: 0;
  }

  /* One header cell for New to/Watched — the shared default (layout b):
     the combined label shows, the two split ones hide. The
     @container sheet (min-width: 1150px) block further down switches
     it to display:contents so the split labels become real grid items
     in their own columns instead; the @container sheet
     (max-width: 899.98px) block shows the "Details" label instead. */
  .year-head-newtowatched {
    grid-column: 4;
  }

  .year-head-newto,
  .year-head-watched,
  .year-head-details {
    display: none;
  }

  .year-head-returned {
    grid-column: 5;
  }

  .year-head-links {
    grid-column: 6;
  }

  /* The column template lives here once, as a custom property, so the
     header row and every film row (both .year-entry) always line up.
     Its value — and the entry's column-gap and padding — are set by
     the @container sheet rules further down, one per layout. */
  .year-entry {
    grid-template-columns: var(--sheet-cols);
    border-bottom: 1px solid var(--edge);
    background: var(--surface);
  }

  .year-list > .year-entry:nth-child(odd) {
    background: var(--greenbar);
  }

  /* .year-list-row painting its own background (the phone highlight
     mechanism) does nothing once it's display:contents, so the just-
     ranked fill is repainted here on the row's actual box instead. */
  .year-list > .year-entry {
    transition: background-color 1.2s ease;
  }

  .year-list > .year-entry:has(.year-list-row.year-highlight) {
    background: var(--yellow);
  }

  .year-list > .year-entry:has(.year-list-row.year-highlight) .year-list-rank,
  .year-list > .year-entry:has(.year-list-row.year-highlight) .year-list-title,
  .year-list > .year-entry:has(.year-list-row.year-highlight) .year-list-year {
    color: var(--on-yellow);
  }

  /* Declared last so the hover tint always wins the tie over the
     greenbar stripe and the just-ranked highlight above. */
  .year-list > .year-entry:hover {
    background: var(--bg);
  }

  .year-podium-row {
    display: none;
  }

  .year-list-row,
  .year-list-wide {
    display: contents;
  }

  .year-list-rank {
    grid-column: 1;
    text-align: center;
    color: var(--blue);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 1.375rem;
  }

  .year-list-thumb {
    grid-column: 2;
    width: 54px;
    height: 80px;
    padding: 3px;
    box-sizing: border-box;
    border-radius: 4px;
  }

  .year-list-filmcol {
    grid-column: 3;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
  }

  .year-list-title {
    min-width: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .year-list-year {
    font-size: 0.8125rem;
    color: var(--text-muted);
  }

  /* One grid cell for New to/Watched — the shared default, i.e. layout
     b) above: the two cells stack (circles + name, then icon + word)
     instead of sitting in separate columns. The @container sheet
     (min-width: 1150px) block further down switches this to
     display:contents, so .year-wide-newto and .year-wide-watched
     become real grid items again, each in its own column; the
     @container sheet (max-width: 899.98px) block instead keeps this
     stack but pulls the Returned stamp into the same column below it. */
  .year-wide-newtowatched {
    grid-column: 4;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
  }

  .year-wide-date {
    grid-column: 5;
    display: flex;
    align-items: center;
    overflow: visible;
    white-space: normal;
  }

  .year-wide-links {
    grid-column: 6;
    display: flex;
    flex-direction: row;
    gap: 8px;
  }

  .year-stamp {
    display: inline-block;
    border: 2px solid var(--blue);
    border-radius: 4px;
    padding: 4px 8px;
    color: var(--blue);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    transform: rotate(-3deg);
  }
}

/* Cosmetic sizing that still follows the window rather than the sheet —
   the Top of the Charts shelf (untouched by this section) and the
   tractor-feed hole graphic, neither of which affects whether the
   sheet's columns fit. */
@media (min-width: 1200px) {
  .year-charts-row {
    gap: 64px;
  }

  .year-chart-vhs {
    width: 160px;
  }

  .year-chart-case[data-rank="1"] .year-chart-vhs {
    width: 200px;
  }

  .year-sheet::before,
  .year-sheet::after {
    width: 28px;
    background-image: radial-gradient(circle, var(--feed-hole) 4.5px, var(--edge) 4.5px 5px, transparent 5px);
    background-size: 100% 28px;
  }

  .year-sheet-inner {
    margin: 0 28px;
    padding: 0 20px;
  }
}

/* ================================================================
   The sheet's own three column layouts, picked by @container queries
   against .year-sheet's rendered width (set above), not the window's —
   so the Links column can never run past the sheet's right edge just
   because a laptop's sidebar left less room than the viewport implied.

   a) 1150px+  — full layout: New to and Watched as two real columns.
   b) 900–1149px — New to/Watched merge into one stacked cell (header
      reads "New to / Watched").
   c) under 900px — compact: New to, Watched and the Returned stamp all
      stack into one "Details" column; IMDb/Trailer stack instead of
      sitting side by side.
   ================================================================ */

/* ---------- a) 1150px and up — full layout ---------- */
@container sheet (min-width: 1150px) {
  .year-sheet-inner {
    --sheet-cols: 52px 60px minmax(260px, 1fr) 112px 112px 132px 168px;
  }

  .year-entry {
    column-gap: 16px;
    padding: 12px 20px;
  }

  .year-list-rank {
    font-size: 1.625rem;
  }

  .year-list-title {
    font-size: 1.0625rem;
  }

  .year-sheet-link {
    min-height: 40px;
  }

  /* New to and Watched split into two real grid columns. */
  .year-head-newtowatched {
    display: contents;
  }

  .year-head-newto,
  .year-head-watched {
    display: block;
  }

  .year-head-combined {
    display: none;
  }

  .year-head-newto {
    grid-column: 4;
  }

  .year-head-watched {
    grid-column: 5;
  }

  .year-head-returned {
    grid-column: 6;
  }

  .year-head-links {
    grid-column: 7;
  }

  .year-wide-newtowatched {
    display: contents;
  }

  .year-wide-newto {
    grid-column: 4;
  }

  .year-wide-watched {
    grid-column: 5;
  }

  .year-wide-date {
    grid-column: 6;
  }

  .year-wide-links {
    grid-column: 7;
  }
}

/* ---------- b) 900–1149px — New to/Watched merged ----------
   Everything else (the merged cell itself, its grid-column, the
   Returned and Links columns) is already the shared default set in
   the 700px media query above, since it's this layout's own shape —
   only the column widths, gap and padding are this tier's own. */
@container sheet (min-width: 900px) and (max-width: 1149.98px) {
  .year-sheet-inner {
    --sheet-cols: 44px 60px minmax(220px, 1fr) 120px 128px 160px;
  }

  .year-entry {
    column-gap: 14px;
    padding: 12px 0;
  }
}

/* ---------- c) under 900px — compact ----------
   New to, Watched and the Returned stamp share one "Details" column
   (rank/poster/film/Links then span both of the entry's two rows to
   stay vertically centered); IMDb/Trailer stack instead of sitting
   side by side. */
@container sheet (max-width: 899.98px) {
  .year-sheet-inner {
    --sheet-cols: 40px 48px minmax(160px, 1fr) 132px 96px;
  }

  .year-entry {
    grid-template-rows: auto auto;
    row-gap: 6px;
    column-gap: 12px;
    padding: 12px 0;
  }

  .year-list-rank,
  .year-list-thumb,
  .year-list-filmcol,
  .year-wide-links {
    grid-row: 1 / -1;
    align-self: center;
  }

  .year-list-thumb {
    width: 44px;
    height: 64px;
  }

  .year-head-combined {
    display: none;
  }

  .year-head-details {
    display: block;
  }

  .year-head-returned {
    display: none;
  }

  .year-head-links {
    grid-column: 5;
  }

  .year-wide-newtowatched {
    grid-row: 1;
    gap: 6px;
  }

  .year-wide-date {
    grid-column: 4;
    grid-row: 2;
  }

  .year-wide-links {
    grid-column: 5;
    flex-direction: column;
    gap: 6px;
  }
}

/* ================================================================
   The Shelf — Edit labels
   The back of a flipped case: the label tags plus an "Edit labels"
   button that swaps them for the same chip picker the "Add to Shelf"
   panel uses (.label-chip, .label-chips — see the Add panel section
   above), recolored here since the case back is always the dark VHS
   color, in both light and dark mode. No Save — each chip tap
   attaches or detaches the label immediately.
   ================================================================ */

.shelf-back-labels {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.shelf-back-edit-labels {
  align-self: flex-start;
  min-height: 44px;
  padding: 0 4px;
  border: none;
  background: none;
  color: var(--on-blue);
  opacity: 0.75;
  font-weight: 700;
  font-size: 0.75rem;
  text-decoration: underline;
  cursor: pointer;
}

.shelf-back-edit-labels:hover,
.shelf-back-edit-labels:focus-visible {
  opacity: 1;
}

/* The chip picker's unpicked chips, recolored for the dark case back —
   the case is always dark regardless of theme, so this reaches past the
   theme-following --tape-unpicked-bg straight for its fixed dark value.
   Selected chips keep the normal .label-chip-selected tape fill — :not()
   here so this dark override never fights it for specificity — plus a
   thin outline so black and navy tape still stand out. */
.shelf-back-label-chips .label-chip:not(.label-chip-selected) {
  background: var(--dark-tape-unpicked-bg);
  color: rgba(255, 255, 255, 0.75);
}

.shelf-back-label-chips .label-chip-selected {
  outline: 1px solid rgba(255, 255, 255, 0.25);
}

.shelf-back-label-chips .label-chip-new {
  background: transparent;
  border: 2px dashed rgba(255, 255, 255, 0.35);
  color: rgba(255, 255, 255, 0.75);
}

.label-chip-new-field {
  display: flex;
  align-items: center;
  gap: 6px;
}

.label-chip-new-input {
  min-height: 44px;
  width: 140px;
  padding: 0 10px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(255, 255, 255, 0.08);
  color: var(--on-blue);
  font-family: inherit;
  font-size: 0.85rem;
}

.label-chip-new-input::placeholder {
  color: rgba(255, 255, 255, 0.5);
}

.label-chip-new-add {
  min-height: 44px;
  min-width: 44px;
  padding: 0 12px;
  border: none;
  border-radius: 999px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-weight: 700;
  font-size: 0.8rem;
  cursor: pointer;
}

.label-chip-new-cancel {
  min-height: 44px;
  min-width: 44px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  background: transparent;
  color: var(--on-blue);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.shelf-back-labels-done {
  align-self: flex-start;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 4px;
  background: transparent;
  color: var(--on-blue);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}

.shelf-back-label-chips button:disabled,
.shelf-back-label-chips input:disabled {
  opacity: 0.5;
  cursor: default;
}

/* ================================================================
   Personality pass — shared pieces used across Staff Picks, the Staff
   Room, the Back Office and anywhere else that wants the same touches.
   The tilts, tape and askew details are the design (a 90s video store,
   not a set of forms) — see CLAUDE.md's design rules. Static tilts are
   never transitioned; only a state change (like the selected outline)
   animates, and that respects prefers-reduced-motion below.
   ================================================================ */

.tilt-a { transform: rotate(-2.5deg); }
.tilt-b { transform: rotate(2deg); }
.tilt-c { transform: rotate(-1.5deg); }
.tilt-d { transform: rotate(1.5deg); }
.tilt-e { transform: rotate(-3deg); }
.tilt-f { transform: rotate(3deg); }

/* ---------- The shared "selected" state for a Staff Picks case: lift,
   tilt a little and a 4px yellow outline held off the edge. Clerk name
   tags have their own selected look (.ja-tag--active, the clip-on tag) and
   are never tilted. ---------- */
.sp-case-selected {
  transform: translateY(-6px) rotate(-3deg);
}

.sp-case-selected {
  outline: 4px solid var(--yellow);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .sp-clerk,
  .sp-case {
    transition: none;
  }
}

/* ================================================================
   Shelf & Year grid case sizing fix
   Both faces of a flipping case used to share one grid cell as equal
   siblings, so the taller one — the back, now that Edit labels can add a
   chip picker — set the whole case's height, leaving empty space under a
   normal front. These rules make the front the one that sizes the case
   again: .shelf-tape-back comes out of the flipper's grid flow and is
   absolutely positioned to exactly cover the front's box instead, with
   its own scrollbar for anything that doesn't fit. Applies to both the
   Shelf and the Year grid, since the Year grid's cases share every one
   of these classes (see the Stage 4b comment near .shelf-tape above).
   ================================================================ */

.shelf-tape-flipper {
  position: relative;
}

.shelf-tape-back {
  position: absolute;
  inset: 0;
  padding: 10px 8px 8px;
  gap: 8px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.25) transparent;
}

.shelf-tape-back::-webkit-scrollbar {
  width: 6px;
}

.shelf-tape-back::-webkit-scrollbar-track {
  background: transparent;
}

.shelf-tape-back::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.25);
  border-radius: 999px;
}

/* Tighter back typography, so a normal back fits without scrolling even
   at the laptop 6-column width. */
.shelf-back-info {
  gap: 6px;
}

.shelf-back-value {
  font-size: 0.8125rem;
}

.shelf-back-labels {
  gap: 6px;
}

.shelf-back-link,
.shelf-back-keep,
.shelf-back-delete,
.shelf-back-labels-done {
  font-size: 0.6875rem;
  letter-spacing: 0.02em;
}

.shelf-back-link,
.shelf-back-keep {
  padding: 0 2px;
}

/* ================================================================
   Shelf & Year case back — scales with the CASE, not the screen
   Why the block above (tuned for phone) still overflowed at the iPad
   (5-column) and laptop (6-column) grid widths: those breakpoints add
   MORE columns to the same, capped-width .screen, so each case actually
   gets NARROWER in pixels than a phone case, even though the viewport
   itself is bigger. The rules above size text in rem, which tracks the
   root font size (i.e. the viewport), not the box the text sits in — so
   the back kept rendering phone-sized type inside a smaller box and
   overflowed.
   The fix: .shelf-tape becomes a size query container, and everything
   below reads cqi (1% of THAT container's own width) instead. Each
   property is a clamp(narrow-case size, scales with cqi, phone size) —
   the max is exactly the phone-tuned value above, so on any phone-width
   case the clamp saturates at that max and phone is pixel-identical to
   before; on a narrower iPad/laptop case the cqi term wins and shrinks
   text, gaps and padding to fit. Button touch targets stay a flat 44px
   min-height throughout — that floor doesn't move for any screen size
   (see the touch-target rule in CLAUDE.md) — only their font, padding
   and gaps shrink. Applies to the Year grid too, since it shares every
   one of these classes with the Shelf.
   ================================================================ */

.shelf-tape {
  container-type: inline-size;
}

.shelf-tape-back {
  padding: clamp(5px, 5cqi, 10px) clamp(4px, 4cqi, 8px) clamp(4px, 4cqi, 8px);
  gap: clamp(3px, 4.5cqi, 8px);
}

.shelf-back-info {
  gap: clamp(2px, 3.5cqi, 6px);
}

.shelf-back-title,
.shelf-back-value {
  font-size: clamp(0.5625rem, 7cqi, 0.8125rem);
}

.shelf-back-year {
  font-size: clamp(0.5rem, 6cqi, 0.6875rem);
}

.shelf-back-label {
  font-size: clamp(0.5rem, 5.5cqi, 0.625rem);
}

/* Less air above "Edit labels" — this is also the gap under the label
   tags, when there are any. */
.shelf-back-labels {
  gap: clamp(1.5px, 2cqi, 4px);
}

.shelf-back-edit-labels {
  font-size: clamp(0.625rem, 6cqi, 0.75rem);
  padding: 0 clamp(2px, 3cqi, 4px);
}

.shelf-back-links {
  gap: clamp(4px, 5cqi, 8px);
}

.shelf-back-link,
.shelf-back-keep,
.shelf-back-delete,
.shelf-back-yes,
.shelf-back-labels-done {
  font-size: clamp(0.5625rem, 5.5cqi, 0.6875rem);
}

.shelf-back-link,
.shelf-back-keep {
  padding: 0 clamp(1px, 1.5cqi, 2px);
}

.shelf-back-yes {
  padding: 0 clamp(2px, 3cqi, 4px);
}

.shelf-back-labels-done {
  padding: 0 clamp(6px, 8cqi, 16px);
}

.shelf-back-actions.is-confirming {
  gap: clamp(4px, 5cqi, 8px);
}

.shelf-back-delete {
  gap: clamp(3px, 3cqi, 6px);
}

.shelf-back-delete svg {
  width: clamp(10px, 8cqi, 14px);
  height: clamp(10px, 8cqi, 14px);
}

/* ================================================================
   Stage FB-1 (Clerk Feedback) — the Year list's "Did <Name> nail it?"
   follow-up card. Shown once, right after a rank lands on the Year list
   (js/year.js), only if the just-ranked film carries a clerk's own
   "<Name>'s pick" label (js/clerk-feedback.js's findFeedbackPrompt, via
   js/main.js). Absent otherwise — in which case .year-main/.year-fb-slot
   are never rendered at all, and the Year screen's markup is exactly
   what it was before this stage.

   Phone: the card sits above the list (plain document order, no extra
   CSS needed). 700px+: card on the left (280px, 320px from 1200px),
   list on the right, via .year-main.has-feedback's own grid — untouched
   by, and independent of, the Stage 4b sheet layout inside .year-body.
   ================================================================ */

.year-main.has-feedback {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

@media (min-width: 700px) {
  .year-main.has-feedback {
    display: grid;
    grid-template-columns: 280px 1fr;
    align-items: start;
    gap: 24px;
  }
}

@media (min-width: 1200px) {
  .year-main.has-feedback {
    grid-template-columns: 320px 1fr;
  }
}

.yfb-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 14px;
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.16);
  transform: rotate(-1deg);
  overflow: visible;
}

.yfb-stripe {
  height: 6px;
  border-radius: 14px 14px 0 0;
  background: var(--yellow);
}

/* The clerk's J&A name tag (js/ui.js), clipped onto the card's top-left
   corner. */
.yfb-hello {
  position: absolute;
  top: -18px;
  left: 16px;
  z-index: 1;
  width: 132px;
}

.yfb-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 26px 18px 18px;
}

.yfb-kicker {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.yfb-heading {
  margin: 0;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.25rem;
  line-height: 1.1;
  color: var(--text);
}

.yfb-film {
  display: flex;
  align-items: center;
  gap: 12px;
}

.yfb-case {
  flex: 0 0 46px;
  display: block;
  position: relative;
  width: 46px;
  aspect-ratio: 2 / 3;
  border-radius: 4px;
  overflow: hidden;
  background: var(--case-bg);
}

.yfb-case img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.yfb-case .vhs-sleeve-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--on-blue);
  opacity: 0.5;
  font-size: 0.5625rem;
  text-transform: uppercase;
  text-align: center;
  padding: 0 2px;
}

.yfb-film-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.yfb-film-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.9375rem;
  line-height: 1.15;
  color: var(--text);
}

.yfb-film-year {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.yfb-asked {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.yfb-sticker {
  display: inline-block;
  background: var(--yellow);
  color: var(--on-yellow);
  font-weight: 700;
  font-size: 0.75rem;
  padding: 3px 8px;
  border-radius: 4px;
  transform: rotate(-2deg);
}

.yfb-pitch {
  margin: 0;
  font-style: italic;
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--text);
}

/* Shared Hit/Miss stamp buttons — used here on the after-ranking card and
   by Staff Picks' rack shelf-talker (css/staff-picks.css), which relies on
   this same .fb-stamp family rather than its own copy, so the two places
   can't drift apart. Solid fills (not an outline-until-chosen look): HIT is
   navy with white text, MISS is stamp red with white text, both a fixed
   pairing (--blue/--on-blue, --stamp-red/--on-stamp-red) that already meets
   4.5:1 contrast elsewhere in the app. A slight tilt is the house style;
   --fb-tilt carries it through the resting, pressed and chosen states so
   they can't fall out of sync with each other. */
.fb-stamps {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 4px;
}

.fb-stamp {
  min-height: 84px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  border: none;
  border-radius: 10px;
  font: inherit;
  cursor: pointer;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.28);
  transform: rotate(var(--fb-tilt));
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.fb-stamp-icon {
  width: 24px;
  height: 24px;
}

.fb-stamp-hit {
  --fb-tilt: -2deg;
  background: var(--blue);
  color: var(--on-blue);
}

.fb-stamp-miss {
  --fb-tilt: 1.5deg;
  background: var(--stamp-red);
  color: var(--on-stamp-red);
}

.fb-stamp:active:not(:disabled) {
  transform: rotate(var(--fb-tilt)) scale(0.96);
}

.fb-stamp.is-chosen {
  transform: rotate(var(--fb-tilt)) scale(1.05);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.4);
}

.fb-stamp:disabled {
  cursor: default;
}

.fb-stamp:disabled:not(.is-chosen) {
  opacity: 0.45;
}

.fb-stamp-main {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.125rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.fb-stamp-sub {
  font-size: 0.6875rem;
  font-weight: 700;
  opacity: 0.85;
}

.yfb-status {
  margin: 0;
  min-height: 1.1em;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--blue);
}

.yfb-not-now {
  align-self: flex-start;
  padding: 0 4px;
  font-size: 0.8125rem;
}

/* The rubber-stamp mark that lands on the card once a verdict is chosen —
   ink text on a double border, like Home's STAFF PICK stamp
   (.hp-staff-stamp in css/home.css), not a fill, so it reads as stamped
   rather than labelled. */
.yfb-mark {
  display: none;
  position: absolute;
  top: 14px;
  right: 14px;
  padding: 4px 10px;
  border: 4px double var(--blue);
  border-radius: 4px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.875rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--blue);
  transform: rotate(8deg);
}

.yfb-mark.is-visible {
  display: block;
  animation: yfb-mark-in 320ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.yfb-mark.is-miss {
  border-color: var(--stamp-red);
  color: var(--stamp-red);
}

@keyframes yfb-mark-in {
  from {
    transform: rotate(8deg) scale(1.8);
    opacity: 0;
  }
  to {
    transform: rotate(8deg) scale(1);
    opacity: 1;
  }
}

.yfb-skipped {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  border: 2px dashed var(--edge);
  border-radius: 10px;
  color: var(--text-muted);
  font-size: 0.8125rem;
}

.yfb-ask-again {
  padding: 0 4px;
  font-size: 0.8125rem;
}

@media (prefers-reduced-motion: reduce) {
  .yfb-mark.is-visible {
    animation: none;
  }
}

/* ================================================================
   Stage FB-1b (Clerk Feedback) — small Hit/Miss stamps inside a ranked
   film's own details, for any film carrying a clerk's own "<Name>'s pick"
   label, not just the one just-ranked film FB-1's card above ever covers.
   Lives at the end of the phone list's slide-open row (.year-details-body)
   and the grid case's back (.shelf-tape-back), right where css/year.js's
   pickFeedbackHTML puts it. Reuses the shared .fb-stamp family (defined
   above) with a .fb-stamp-compact modifier — same fill/icon/tilt, sized
   down to fit, but min-height stays a flat 44px throughout (the touch-
   target rule in CLAUDE.md), same as .year-link right next to it.
   ================================================================ */

.yfb-mini {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 2px;
  padding-top: 10px;
  border-top: 2px dashed var(--edge);
}

.yfb-mini-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.yfb-mini-line {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text-muted);
}

/* A smaller version of .yfb-mark's ink-stamp look — double border, no
   fill — next to the line instead of pinned to a card corner. */
.yfb-mini-mark {
  display: inline-block;
  padding: 2px 6px;
  border: 3px double var(--blue);
  border-radius: 4px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.6875rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--blue);
  transform: rotate(-4deg);
}

.yfb-mini-mark.is-miss {
  border-color: var(--stamp-red);
  color: var(--stamp-red);
}

.fb-stamps-mini {
  gap: 8px;
  margin-top: 0;
}

.fb-stamp-compact {
  min-height: 44px;
  flex-direction: row;
  gap: 6px;
  padding: 0 10px;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.24);
}

.fb-stamp-compact .fb-stamp-icon {
  width: 16px;
  height: 16px;
}

.fb-stamp-compact .fb-stamp-main {
  font-size: 0.75rem;
}

.fb-stamp-compact.is-chosen {
  transform: rotate(var(--fb-tilt)) scale(1.03);
}

.yfb-mini-status {
  margin: 0;
  min-height: 1em;
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--blue);
}

/* Inside the grid case's back, text and gaps scale with the case's own
   width (cqi) rather than the viewport, same reasoning — and the same
   .shelf-tape size-query container — as the rest of .shelf-tape-back's
   content (see the "scales with the CASE" section above). min-height
   stays the flat 44px from .fb-stamp-compact above; only padding, gaps
   and font shrink. */
/* No border-top here — .shelf-back-perf right above it is already this
   case back's own dashed divider, so a second one would double up. */
.shelf-tape-back .yfb-mini {
  gap: clamp(3px, 3.5cqi, 6px);
  padding-top: 0;
  border-top: none;
}

.shelf-tape-back .yfb-mini-line {
  font-size: clamp(0.5rem, 5.5cqi, 0.625rem);
}

.shelf-tape-back .yfb-mini-mark {
  font-size: clamp(0.5rem, 5cqi, 0.5625rem);
  padding: clamp(1px, 1.5cqi, 2px) clamp(3px, 3cqi, 5px);
}

.shelf-tape-back .fb-stamps-mini {
  gap: clamp(3px, 3cqi, 6px);
}

.shelf-tape-back .fb-stamp-compact {
  padding: 0 clamp(3px, 3cqi, 6px);
  gap: clamp(2px, 2cqi, 4px);
}

.shelf-tape-back .fb-stamp-compact .fb-stamp-icon {
  width: clamp(11px, 5.5cqi, 14px);
  height: clamp(11px, 5.5cqi, 14px);
}

.shelf-tape-back .fb-stamp-compact .fb-stamp-main {
  font-size: clamp(0.5625rem, 5.5cqi, 0.6875rem);
}

/* ================================================================
   The Year screen's LIST view on phone — ticket stubs (under 700px)

   Only phone list view changes. Everything here is inside
   @media (max-width: 699px), the same 700px line the rail/sidebar and
   every other stage of the laptop layout use, so iPad and laptop keep
   the Stage 4/4b shelf-and-sheet exactly as it was. Grid view is
   untouched too: the navy counter is painted on .year-list-wrap, which
   only list view renders.

   The header band is shared by both views, so its phone restyle shows
   in grid view as well — one band can't look two ways at once. It's
   navy rather than sitting on the page background because rule 5 in
   CLAUDE.md forbids yellow text on a light surface, and the gold
   "RENTAL HISTORY" kicker would otherwise sit on --bg in day mode.

   Each ticket is one .year-entry. The stub, the dashed perforation and
   the body are three background layers on that one element, so they run
   the full height of the ticket — including the details panel when it's
   open — with no extra markup. The two notches are its ::before and
   ::after, filled with the counter colour so they read as bites.

   Colours come from the --ticket-* tokens in css/tokens.css. They're
   fixed in both themes, like --case-bg and the Staff Picks rack: a
   printed ticket is an object, not a surface.
   ================================================================ */

@media (max-width: 699px) {
  /* ---------- Header: pills and the view toggle on one row ---------- */

  .rental-band {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "switcher toggle"
      "kicker   kicker"
      "yearrow  yearrow"
      "rewind   rewind";
    align-items: center;
    column-gap: 12px;
    row-gap: 14px;
    padding: 14px 16px 16px;
    background: var(--ticket-page-bg);
    border-radius: 12px;
  }

  /* The dashed edge is the top of the ticket counter, so it only belongs
     there when the counter follows — grid view (and an empty year) gets a
     plain rounded block instead. */
  .year-screen:has(.year-list-wrap) .rental-band {
    border-radius: 12px 12px 0 0;
    border-bottom: 2px dashed var(--ticket-perf);
  }

  /* Years scroll sideways rather than squeezing, the same call the Staff
     Room's name tags make when there are more than three clerks. */
  .rental-band .year-switcher {
    grid-area: switcher;
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 8px;
  }

  .rental-band .year-tab {
    min-height: 44px;
    background: var(--ticket-bg);
    border: 1px solid var(--ticket-perf);
    color: var(--ticket-text);
    font-weight: 700;
    white-space: nowrap;
  }

  .rental-band .year-tab-active {
    background: var(--yellow);
    border-color: var(--yellow);
    color: var(--ticket-ink);
  }

  .rental-band .rental-header {
    grid-area: toggle;
    flex-wrap: nowrap;
    gap: 0;
    padding-top: 0;
    border-top: none;
  }

  .rental-band .rental-heading {
    display: none;
  }

  .rental-band .view-toggle {
    border: 1px solid var(--ticket-perf);
  }

  .rental-band .view-toggle-button {
    min-height: 44px;
    padding: 0 14px;
    background: var(--ticket-bg);
    color: var(--ticket-text);
    font-weight: 700;
  }

  .rental-band .view-toggle-active {
    background: var(--yellow);
    color: var(--ticket-ink);
  }

  /* The kicker and the big year are hidden by default and shown from
     700px up (Stage 4). Phone now shows them too, its own way. Its text
     color is --ticket-accent, not a flat --yellow, so it never becomes
     yellow text on the light ticket's near-white page background. */
  .rental-band .rental-kicker {
    display: block;
    grid-area: kicker;
    color: var(--ticket-accent);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .rental-band .rental-year-row {
    display: flex;
    grid-area: yearrow;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
  }

  /* Its own full-width line, clear of the pills/toggle row above — no more
     squeezing in beside the List/Grid toggle. */
  .rental-band .rental-rewind-button {
    grid-area: rewind;
    width: 100%;
  }

  .rental-year {
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 4rem;
    line-height: 0.9;
    color: var(--ticket-text);
  }

  .rental-count {
    color: var(--ticket-muted);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
  }

  /* ---------- The counter the tickets sit on ---------- */
  /* Pulled up through .year-screen's own 16px gap so it reads as one
     navy block with the header above it. List view only — grid view has
     no .year-list-wrap, so it keeps the page background as before. */

  .year-list-wrap {
    padding: 16px 12px 18px;
    background: var(--ticket-page-bg);
    border-radius: 0 0 12px 12px;
  }

  /* Only when the list sits straight under the band. With the FB-1
     "Did <Name> nail it?" card in play the body is nested inside
     .year-main instead, and the card is what follows the band. */
  .year-screen > .year-body .year-list-wrap {
    margin-top: -16px;
  }

  .year-list {
    gap: 12px;
  }

  /* ---------- The ticket ---------- */

  .year-entry {
    position: relative;
    border-radius: 12px;
    background-color: var(--ticket-bg);
    background-image:
      repeating-linear-gradient(to bottom, var(--ticket-perf) 0 4px, transparent 4px 8px),
      linear-gradient(to right, var(--ticket-stub) 0 62px, transparent 62px);
    background-size: 2px 100%, 100% 100%;
    background-position: 60px 0, 0 0;
    background-repeat: no-repeat;
    box-shadow: 0 6px 14px rgba(0, 0, 0, 0.35);
    transition: box-shadow 1.2s ease;
  }

  /* Ranks 1–3 get a gold stub. .year-podium-row is already on exactly
     those three rows (it's what hides them at 700px+, where they move
     to the Top of the Charts shelf instead), so there's nothing new to
     mark up here. */
  .year-entry.year-podium-row {
    background-image:
      repeating-linear-gradient(to bottom, var(--ticket-perf) 0 4px, transparent 4px 8px),
      linear-gradient(to right, var(--yellow) 0 62px, transparent 62px);
  }

  /* The two bites out of the perforation. Centred on the dashed line
     (53 + 8 = 61px) and filled with the counter colour behind them. */
  .year-entry::before,
  .year-entry::after {
    content: "";
    position: absolute;
    left: 53px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--ticket-page-bg);
    z-index: 2;
  }

  .year-entry::before {
    top: -8px;
  }

  .year-entry::after {
    bottom: -8px;
  }

  /* ---------- The ticket's top row ---------- */

  .year-entry .year-list-row {
    position: relative;
    z-index: 1;
    gap: 0;
    min-height: 88px;
    padding: 12px 12px 12px 0;
    background: transparent;
    border: none;
    border-radius: 12px;
  }

  .year-entry .year-list-rank {
    flex: 0 0 62px;
    align-self: stretch;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    text-align: center;
    color: var(--ticket-accent);
  }

  .year-entry.year-podium-row .year-list-rank {
    color: var(--ticket-ink);
  }

  .year-ticket-no {
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .year-rank-num {
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 1.875rem;
    line-height: 1;
  }

  .year-entry .year-list-thumb {
    flex: 0 0 46px;
    width: 46px;
    height: 69px;
    aspect-ratio: auto;
    margin-left: 16px;
    padding: 2px;
    box-sizing: border-box;
    border-radius: 3px;
    background: var(--case-bg);
  }

  /* A block box, so the title and year share the first line and the
     staff-pick sticker (a block-level flex) drops to its own below. */
  .year-entry .year-list-filmcol {
    flex: 1 1 auto;
    min-width: 0;
    display: block;
    margin-left: 12px;
  }

  .year-entry .year-list-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ticket-text);
  }

  .year-entry .year-list-year {
    margin-left: 6px;
    font-size: 0.875rem;
    font-weight: 400;
    color: var(--ticket-muted);
  }

  .year-entry .year-list-chevron {
    margin-left: 10px;
    color: var(--ticket-muted);
  }

  /* ---------- The staff-pick sticker ---------- */

  .year-pick-tag {
    display: flex;
    width: fit-content;
    align-items: center;
    gap: 4px;
    margin-top: 7px;
    padding: 3px 7px;
    border-radius: 3px;
    background: var(--ticket-sticker);
    border: 1px solid var(--ticket-sticker-border);
    color: var(--ticket-ink);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
    transform: rotate(-3deg);
    transform-origin: left center;
  }

  .year-list > .year-entry:nth-child(even) .year-pick-tag {
    transform: rotate(2deg);
  }

  .year-pick-star {
    flex: 0 0 auto;
  }

  /* ---------- Open: chips, then the two buttons ---------- */

  .year-entry .year-details {
    background: transparent;
  }

  .year-entry.is-open .year-details {
    border-bottom: none;
  }

  /* Clears the stub, then lines up under the poster. */
  .year-entry .year-details-body {
    margin: 0 12px 0 62px;
    padding: 12px 4px 16px 16px;
    gap: 14px;
    border-top: 2px dashed var(--ticket-perf);
  }

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

  .year-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-height: 34px;
    padding: 0 12px;
    border-radius: 999px;
    background: var(--ticket-chip-bg);
    color: var(--ticket-text);
    font-size: 0.8125rem;
    font-weight: 600;
  }

  .year-chip .year-where-icon {
    color: var(--ticket-accent);
  }

  .year-chip-badges {
    display: inline-flex;
    align-items: center;
  }

  .year-chip-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    overflow: hidden;
  }

  .year-chip-badge img {
    width: 100%;
    height: 100%;
    display: block;
  }

  /* Only a second badge overlaps — J on its own sits square. */
  .year-chip-badge + .year-chip-badge {
    margin-left: -5px;
    box-shadow: 0 0 0 2px var(--ticket-chip-bg);
  }

  .year-chip-stamp {
    display: inline-flex;
    align-items: center;
    min-height: 34px;
    padding: 0 10px;
    border: 2px solid var(--ticket-accent);
    border-radius: 4px;
    color: var(--ticket-accent);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    transform: rotate(-4deg);
  }

  .year-details-body .year-links {
    gap: 10px;
  }

  .year-details-body .year-link {
    font-size: 0.75rem;
    letter-spacing: 0.1em;
  }

  /* Both buttons share one subtle look now — an outline, not a fill.
     Trailer is no longer gold. */
  .year-link-imdb,
  .year-link-trailer {
    background: transparent;
    border-color: var(--ticket-perf);
    color: var(--ticket-text);
  }

  .year-link-imdb:hover,
  .year-link-trailer:hover,
  .year-link-imdb:active,
  .year-link-trailer:active {
    background: var(--ticket-hover-fill);
  }

  /* A film with no imdb_id has only the Trailer button, which then takes
     the whole row rather than sitting in half of it. */
  .year-link-trailer:only-child {
    grid-column: 1 / -1;
  }

  /* ---------- FB-1b's Hit/Miss line, on the ticket ---------- */
  /* Its fills carry their own contrast, so only the ink and rules around
     them need the ticket's palette. --stamp-red already follows the site
     theme on its own (the lighter dark-mode red), so it reads fine now
     the ticket follows the theme too. */

  .year-details-body .yfb-mini {
    border-top-color: var(--ticket-perf);
  }

  .year-details-body .yfb-mini-line {
    color: var(--ticket-muted);
  }

  .year-details-body .yfb-mini-mark {
    border-color: var(--ticket-accent);
    color: var(--ticket-accent);
  }

  .year-details-body .yfb-mini-mark.is-miss {
    border-color: var(--stamp-red);
    color: var(--stamp-red);
  }

  .year-details-body .fb-stamp-hit {
    box-shadow: 0 0 0 1px var(--ticket-perf), 0 3px 8px rgba(0, 0, 0, 0.24);
  }

  /* Hit/Miss vote buttons on a ticket: before a vote both stay filled as
     always. After a vote, the button NOT chosen becomes an outline in its
     own colour instead of just dimming while still filled. Keyed off the
     group having an .is-chosen sibling, not :disabled — the buttons are
     only ever disabled for the moment a vote is saving (js/year.js
     re-enables them once it settles, so a vote can be changed later), so
     a :disabled selector never matched once a save finished or on a
     fresh page load. */
  .year-details-body .fb-stamps:has(.fb-stamp-hit.is-chosen) .fb-stamp-miss,
  .year-details-body .fb-stamps:has(.fb-stamp-miss.is-chosen) .fb-stamp-hit {
    background: transparent;
    opacity: 0.55;
  }

  .year-details-body .fb-stamps:has(.fb-stamp-miss.is-chosen) .fb-stamp-hit {
    border: 1.5px solid var(--blue);
    color: var(--blue);
  }

  .year-details-body .fb-stamps:has(.fb-stamp-hit.is-chosen) .fb-stamp-miss {
    border: 1.5px solid var(--stamp-red);
    color: var(--stamp-red);
  }

  /* ---------- The just-ranked film ---------- */
  /* A yellow fill would swallow the whole ticket, stub included, so the
     highlight is a gold ring round the ticket instead. It still fades
     out after ~2.5s the same way (js/year.js drops the class). */

  .year-list > .year-entry:has(.year-list-row.year-highlight) {
    box-shadow: 0 0 0 3px var(--yellow), 0 6px 14px rgba(0, 0, 0, 0.35);
  }

  .year-entry .year-list-row.year-highlight {
    background-color: transparent;
  }

  .year-entry .year-list-row.year-highlight .year-list-rank {
    color: var(--ticket-accent);
  }

  .year-entry.year-podium-row .year-list-row.year-highlight .year-list-rank {
    color: var(--ticket-ink);
  }

  .year-entry .year-list-row.year-highlight .year-list-title {
    color: var(--ticket-text);
  }

  .year-entry .year-list-row.year-highlight .year-list-year,
  .year-entry .year-list-row.year-highlight .year-list-chevron {
    color: var(--ticket-muted);
  }
}

@media (max-width: 699px) and (prefers-reduced-motion: reduce) {
  .year-entry {
    transition: none;
  }
}

/* The two pieces of ticket markup that live in the row button rather
   than inside .year-details (which is display:none here anyway), hidden
   so the sheet layout at 700px+ is exactly what it was. */
@media (min-width: 700px) {
  .year-ticket-no,
  .year-pick-tag {
    display: none;
  }
}

/* ================================================================
   Staff-pick sticker on the 700px+ list (the printout sheet)
   The phone ticket's cream sticker is hidden at 700px+ (rule just
   above), since cream on the white sheet barely reads. This brings it
   back inside the film column, under the title and year, as a yellow
   sticker with navy ink. Same star, same alternating tilt as the phone
   ticket. Grid view and phone are untouched.
   ================================================================ */
@media (min-width: 700px) {
  .year-list-filmcol .year-pick-tag {
    display: inline-flex;
    align-self: flex-start;
    align-items: center;
    gap: 4px;
    margin-top: 6px;
    padding: 3px 8px;
    border-radius: 3px;
    background: var(--yellow);
    color: var(--on-yellow);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
    transform: rotate(-3deg);
    transform-origin: left center;
  }

  .year-list > .year-entry:nth-child(even) .year-list-filmcol .year-pick-tag {
    transform: rotate(2deg);
  }

  /* A just-ranked row flashes yellow, so the sticker swaps to navy
     for those few seconds rather than vanishing into it. */
  .year-list > .year-entry:has(.year-list-row.year-highlight) .year-list-filmcol .year-pick-tag {
    background: var(--blue);
    color: var(--on-blue);
  }
}

/* ================================================================
   Shelf rework — the aisle sign replaces the filter-chip row, at every
   width. js/shelf-flow.js builds it from js/ui.js's shared aisleSignHTML/
   aisleRowsHTML/aisleChooserHTML/wireAisleChooser — the same functions
   and the same .hp-aisle-* look Home's Tonight's Pick "Pull from" aisle
   uses (Stage 6d, css/home.css), which the Shelf now loads too rather
   than duplicating that CSS here. .shelf-talker/.shelf-talker-active
   above are untouched — the Shelf no longer renders them, but the Staff
   Room's report-card filter chips still do.

   Phone (under 700px) also gets slim search-result rows and a bottom-
   sheet Add panel in place of the inline one — see the @media block
   below. 700px+ search results and the inline add panel are unchanged.
   ================================================================ */


/* The Shelf's own extra row in the chooser — Coming Soon isn't a label,
   so it's set apart from the plain label rows above it: a dashed divider,
   then navy fill with yellow type (same reasoning as the old .shelf-talker
   "Coming soon" chip this replaces — see css/coming-soon.css). */
.hp-aisle-row-comingsoon-wrap {
  margin-top: 8px;
  padding-top: 10px;
  border-top: 1px dashed var(--edge);
}

.hp-aisle-row-comingsoon,
.hp-aisle-row-comingsoon:hover,
.hp-aisle-row-comingsoon.is-current {
  background: var(--sticker-ink, var(--blue));
  border-radius: 8px;
}

.hp-aisle-row-comingsoon .hp-aisle-row-name,
.hp-aisle-row-comingsoon .hp-aisle-row-count,
.hp-aisle-row-comingsoon .hp-aisle-row-check {
  color: var(--yellow);
}

/* "Manage labels", moved from the old filter-chip row to the bottom of
   the chooser sheet. */
.aisle-manage-labels-row {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 2px dashed var(--edge);
}

/* Dimmed and unclickable at every width now — previously only true at
   700px+, since a phone tap just opened the inline panel and let its own
   "Already on the shelf" status message say so instead. */
.search-result-owned {
  opacity: 0.55;
  pointer-events: none;
}

@media (max-width: 699px) {
  /* ---------- Slim search-result rows in a bordered panel ---------- */

  .search-results {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--edge);
    border-radius: 10px;
    overflow: hidden;
  }

  .search-result {
    display: grid;
    grid-template-columns: 36px 1fr auto;
    grid-template-rows: auto auto;
    column-gap: 10px;
    row-gap: 2px;
    align-items: center;
    width: 100%;
    min-height: 44px;
    padding: 10px 12px;
    background: none;
    box-shadow: none;
    border-radius: 0;
  }

  .search-result + .search-result {
    border-top: 1px dashed var(--edge);
  }

  .search-result .vhs-sleeve {
    grid-column: 1;
    grid-row: 1 / 3;
    width: 36px;
    border: 1px solid var(--case-bg);
  }

  .search-result .vhs-title {
    grid-column: 2;
    grid-row: 1;
    color: var(--text);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 0.75rem;
    text-transform: uppercase;
    line-height: 1.25;
  }

  .search-result .vhs-year {
    grid-column: 2;
    grid-row: 2;
    color: var(--text-muted);
    font-size: 0.7rem;
  }

  .search-result-add {
    grid-column: 3;
    grid-row: 1 / 3;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 32px;
    padding: 0 12px;
    border-radius: 999px;
    background: var(--yellow);
    color: var(--on-yellow);
    font-weight: 700;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
  }

  .sr-add-wide,
  .sr-owned-wide {
    display: none;
  }

  .search-result-owned-tag {
    grid-column: 3;
    grid-row: 1 / 3;
    display: block;
    max-width: 90px;
    color: var(--text-muted);
    font-size: 0.65rem;
    font-weight: 700;
    text-align: right;
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }

  /* The owned tag replaces the Add pill outright — both sit in the same
     grid cell, so without this they'd show on top of one another. */
  .search-result-owned .search-result-add {
    display: none;
  }

  /* ---------- The Add sheet ---------- */

  .add-sheet-overlay {
    position: fixed;
    inset: 0;
    z-index: 70;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    animation: add-sheet-fade-in 200ms ease;
  }

  .add-sheet-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(5, 17, 40, 0.55);
  }

  .add-sheet {
    position: relative;
    width: 100%;
    max-width: 480px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    gap: 12px;
    background: var(--surface);
    border-radius: 20px 20px 0 0;
    box-shadow: 0 -12px 28px rgba(0, 0, 0, 0.3);
    padding: 10px 18px calc(env(safe-area-inset-bottom, 0px) + 18px);
    animation: add-sheet-slide-up 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
  }

  .add-sheet-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
    /* Clears room for the New Arrival sticker's own negative top offset,
       which would otherwise clip against this scroll container's edge. */
    padding-top: 10px;
  }

  .add-sheet-film {
    display: flex;
    align-items: center;
    gap: 14px;
  }

  .add-sheet-case {
    position: relative;
    flex: 0 0 auto;
    width: 64px;
    transform: rotate(-4deg);
  }

  .add-sheet-case .vhs-sleeve {
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
  }

  /* The orange "New Arrival" sticker — --price-sticker (tokens.css, also
     Tonight's Pick's "price sticker") with --on-yellow's dark ink. */
  .add-sheet-new-sticker {
    position: absolute;
    top: -8px;
    right: -14px;
    z-index: 1;
    padding: 3px 8px;
    border-radius: 3px;
    background: var(--price-sticker);
    color: var(--on-yellow);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 0.5625rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
    transform: rotate(9deg);
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
  }

  .add-sheet-film-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
  }

  .add-sheet-title {
    color: var(--text);
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 1rem;
    text-transform: uppercase;
    line-height: 1.2;
    overflow-wrap: anywhere;
  }

  .add-sheet-year {
    color: var(--text-muted);
    font-size: 0.8rem;
  }

  .add-sheet-labels-heading {
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .add-sheet-confirm,
  .add-sheet-cancel {
    flex: none;
    width: 100%;
  }
}

@keyframes add-sheet-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes add-sheet-slide-up {
  from {
    transform: translateY(24px);
  }
  to {
    transform: translateY(0);
  }
}

@media (max-width: 699px) and (prefers-reduced-motion: reduce) {
  .add-sheet-overlay,
  .add-sheet {
    animation: none;
  }
}

/* ---------- Stage FN-2: Member reviews on the Return Slip ---------- */
/* One cream card per member below "Theater or home?", matching
   design/member-reviews-slip.html (reference only). Built by
   js/member-reviews.js. The paper stays cream under every store light
   (the fixed --note-* tokens), so its ink is fixed too — never --text,
   which turns light at night. The dashed perforation above the heading
   reuses the slip's own .slip-perforation. */

.mr-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.mr-heading-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.mr-heading {
  margin-bottom: 0;
}

.mr-optional {
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 700;
}

.mr-cards {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.mr-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  background: var(--note-paper);
  border-radius: 4px;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.25);
}

/* Slight opposite tilts, like two notes dropped on the counter. */
.mr-card-left {
  transform: rotate(-1.2deg);
}

.mr-card-right {
  transform: rotate(1deg);
}

.mr-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.mr-mascot {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--card-navy);
  border: 2px solid var(--card-navy);
  box-sizing: border-box;
}

.mr-mascot img {
  width: 100%;
  height: 100%;
  display: block;
}

.mr-mascot-letter {
  color: var(--paper-white);
  font-weight: 700;
  font-size: 0.8rem;
}

.mr-name {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--note-ink);
}

.mr-count {
  margin-left: auto;
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--note-muted);
  font-variant-numeric: tabular-nums;
}

.mr-count-warn {
  color: var(--note-stamp-red);
}

.mr-input {
  box-sizing: border-box;
  width: 100%;
  min-height: 44px;
  padding: 6px 2px;
  border: none;
  border-bottom: 2px solid var(--note-edge);
  border-radius: 0;
  background: transparent;
  color: var(--note-ink);
  font-family: "Permanent Marker", cursive;
  font-size: 1.0625rem;
}

.mr-input::placeholder {
  color: var(--note-faint);
  opacity: 1;
}

.mr-input:focus {
  border-bottom-color: var(--note-ink);
}

.mr-unavailable {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* "Ranked! The reviews didn't save…" — shown over the Year list when the
   film was placed but the notes weren't. Same look as the Staff Room's
   .sr-toast; removes itself after a few seconds. */
.mr-toast {
  position: fixed;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  max-width: min(92vw, 420px);
  box-sizing: border-box;
  margin: 0;
  padding: 12px 18px;
  border-radius: 10px;
  background: var(--blue);
  color: var(--on-blue);
  font-size: 0.875rem;
  font-weight: 600;
  text-align: center;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
  z-index: 40;
  animation: mr-toast-in 200ms ease;
}

@keyframes mr-toast-in {
  from {
    opacity: 0;
    transform: translate(-50%, 8px);
  }
  to {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .mr-toast {
    animation: none;
  }
}

/* ---------- Stage FN-3: Member reviews on the Year screen ---------- */
/* Show, add and edit each member's one-liner on a ranked film, matching
   design/member-reviews-phone.html and design/member-reviews-laptop.html
   (reference only). Built by js/year-reviews.js; the slots it fills are
   placed by js/year-list.js (phone ticket, 700px+ sheet row, Top of the
   Charts panel) and js/year-grid.js (back of a flipped case). The cream
   cards reuse FN-2's .mr-card/.mr-card-head/.mr-mascot/.mr-name/.mr-count/
   .mr-input above, so the paper and ink are the same fixed --note-*
   tokens; only what sits around the cards (the heading, the dashed "+ Add"
   button, Edit notes, Cancel) takes its colours from wherever the slot
   lives — a ticket, the sheet, or a black case. */

.mr-slot {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.mr-y-heading {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.mr-y-cards {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Fox on yellow, Owl on navy, per the mockups (FN-2's slip keeps its
   plain navy ring — these only apply where mascotRingClass in
   js/member-reviews.js adds them, chosen by the member's mascot). */
.mr-mascot.mr-mascot-fox {
  background: var(--yellow);
  border-color: var(--yellow);
}

.mr-mascot.mr-mascot-owl {
  background: var(--card-navy);
  border-color: var(--card-navy);
}

.mr-mascot.mr-mascot-dim {
  opacity: 0.55;
}

.mr-y-note {
  margin: 0;
  color: var(--note-ink);
  font-family: "Permanent Marker", cursive;
  font-size: 1.0625rem;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

/* "+ Add <Name>'s take" — a dashed empty card, in whatever muted ink the
   surrounding surface uses (the border follows the text colour). */
.mr-y-add {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 8px 12px;
  border: 2px dashed currentColor;
  border-radius: 4px;
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}

.mr-y-add:hover {
  color: var(--text);
}

.mr-y-status {
  margin: 0;
  color: var(--stamp-red);
  font-size: 0.8125rem;
  font-weight: 600;
}

.mr-y-status:empty {
  display: none;
}

.mr-y-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.mr-y-edit {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 14px;
  font-size: 0.75rem;
}

.mr-y-save {
  padding: 0 22px;
  font-size: 0.875rem;
}

.mr-y-cancel {
  padding: 0 16px;
  font-size: 0.875rem;
}

/* The pencil tag on a row with notes: a scrap of the same cream paper,
   tilted, with the count. */
.mr-pencil {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 7px;
  border: 1px solid var(--note-edge);
  border-radius: 3px;
  background: var(--note-paper);
  color: var(--note-ink);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1;
  white-space: nowrap;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
  transform: rotate(3deg);
}

.mr-pencil svg {
  flex: 0 0 auto;
}

/* The 700px+ reviews strip and the Top of the Charts panels only exist at
   that width. */
.mr-wide,
.mr-chart-toggle {
  display: none;
}

/* ---------- Phone: inside an opened ticket ---------- */
@media (max-width: 699px) {
  .year-entry .year-list-filmcol .mr-pencil {
    margin-left: 8px;
    vertical-align: 2px;
  }

  .year-details-body .mr-y-heading,
  .year-details-body .mr-y-add {
    color: var(--ticket-muted);
  }

  .year-details-body .mr-y-add:hover {
    color: var(--ticket-text);
  }

  .year-details-body .mr-y-cancel {
    color: var(--ticket-text);
  }

}

/* ---------- 700px+: an opened sheet row, and Top of the Charts ---------- */
@media (min-width: 700px) {
  /* Rows now open (to show their reviews), so the whole row is a target. */
  .year-list > .year-entry {
    cursor: pointer;
  }

  .year-list-filmcol .mr-pencil-slot:not(:empty) {
    display: flex;
    margin-top: 6px;
  }

  /* Spans every column, on its own row under the film's own cells. */
  .year-list > .year-entry.is-open > .mr-wide {
    display: block;
    grid-column: 1 / -1;
    margin-top: 12px;
    padding: 16px 0 8px;
    border-top: 2px dashed var(--edge);
    cursor: auto;
  }

  .mr-wide .mr-slot,
  .mr-chart-panel .mr-slot {
    max-width: 820px;
  }

  /* The two cards side by side. */
  .mr-wide .mr-y-cards,
  .mr-chart-panel .mr-y-cards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px;
    align-items: start;
  }

  .mr-chart-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    margin-top: 4px;
    padding: 0 14px;
    border: 2px solid var(--edge);
    border-radius: 999px;
    background: transparent;
    color: var(--text);
    font-family: inherit;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
  }

  .mr-chart-toggle[aria-expanded="true"] {
    border-color: var(--yellow);
    background: var(--yellow);
    color: var(--on-yellow);
  }

  .mr-chart-panel {
    padding: 18px 0 24px;
    border-top: 2px dashed var(--edge);
  }

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

  .mr-chart-panel-title {
    display: block;
    margin-bottom: 12px;
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
    font-size: 0.9375rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text);
  }
}

/* ---------- Grid: on the back of a flipped case ----------
   A black case with white type, so the heading, "+ Add" and the buttons
   follow the case's own ink; sizes shrink with the case (cqi, like the
   rest of .shelf-tape-back) while every button keeps its 44px floor. */
.mr-slot-case {
  gap: clamp(6px, 5cqi, 10px);
  padding-top: clamp(4px, 4cqi, 8px);
  /* The case's own white ink — the same token .shelf-back-info uses. */
  color: var(--on-blue);
}

.mr-slot-case .mr-y-heading {
  color: inherit;
  opacity: 0.55;
  font-size: clamp(0.5rem, 5.5cqi, 0.625rem);
}

.mr-slot-case .mr-y-cards {
  gap: clamp(6px, 5cqi, 10px);
}

.mr-slot-case .mr-card {
  padding: clamp(6px, 5cqi, 10px) clamp(6px, 5cqi, 10px);
  gap: 4px;
}

.mr-slot-case .mr-mascot {
  width: clamp(20px, 14cqi, 26px);
  height: clamp(20px, 14cqi, 26px);
}

.mr-slot-case .mr-card-head {
  gap: clamp(4px, 4cqi, 8px);
}

.mr-slot-case .mr-name {
  font-size: clamp(0.5625rem, 6cqi, 0.75rem);
  letter-spacing: 0.04em;
}

.mr-slot-case .mr-y-note,
.mr-slot-case .mr-input {
  font-size: clamp(0.75rem, 8cqi, 1rem);
}

.mr-slot-case .mr-y-add {
  min-height: 44px;
  padding: 4px clamp(6px, 5cqi, 10px);
  gap: clamp(4px, 4cqi, 8px);
  color: inherit;
  opacity: 0.8;
  font-size: clamp(0.625rem, 6.5cqi, 0.8125rem);
}

.mr-slot-case .mr-y-cancel {
  color: inherit;
}

.mr-slot-case .mr-y-edit,
.mr-slot-case .mr-y-save,
.mr-slot-case .mr-y-cancel {
  min-height: 44px;
  padding: 0 clamp(6px, 6cqi, 14px);
  font-size: clamp(0.5625rem, 6cqi, 0.75rem);
}

.mr-slot-case .mr-y-status {
  font-size: clamp(0.625rem, 6cqi, 0.8125rem);
}

/* A row with no notes has an empty pencil slot — take it out of the
   layout entirely so it adds no gap. */
.mr-pencil-slot:empty {
  display: none;
}

/* ---------- Year grid: keep each case inside its column ----------
   Since Stage 7b the Year grid's case front is the Shelf's black
   clamshell (.sc-case), whose poster is a plain <img> at width 100%.
   .shelf-tape and .shelf-tape-flipper are both one-cell grids with an
   automatic column, and an automatic column grows to fit the poster's
   natural width (often 342px or 500px from TMDB) instead of the
   column the case sits in — so posters came out at their own sizes,
   overflowing the grid and pushing the rank sticker and the title out
   of view. minmax(0, 1fr) caps that column at the case's own width,
   so the poster crops to the sleeve's 2:3 box like the Shelf's does.
   Scoped to .year-tape so nothing else that uses .shelf-tape changes. */
.year-tape,
.year-tape .shelf-tape-flipper {
  grid-template-columns: minmax(0, 1fr);
}

/* ---------- Year Rewind button (Stage R-1, repositioned in R-3c) ----------
   Sits inside .rental-left, right under the year/film-count row, at every
   width and for every year (current and a past year's "Final tally" band
   alike — same markup, css/year-header.js's rewindButtonHTML). Straight,
   never tilted; 48px covers both the phone spec's 48px floor and the
   desktop spec's 44px floor, so one value does both. */
.rental-rewind-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 48px;
  padding: 0 16px;
  border: none;
  border-radius: 6px;
  background: var(--yellow);
  color: var(--on-yellow);
  font-family: "Archivo Black", "Archivo", sans-serif;
  font-size: 13px;
  letter-spacing: 0.02em;
  cursor: pointer;
}

/* ---------- Print-only content (Stage R-3e) ----------
   A belt-and-braces guard for the Rewind screen's printable page
   (css/rewind.css's .rw-print-page): that file is the only place styling
   it, and a stray "*/" buried in one of its own comments once corrupted
   the parse there and silently dropped the very rule meant to hide it,
   leaving the print block visible on screen with no visible error. This
   class lives here instead, in app.css, which every screen already loads
   unconditionally and has no comments anywhere near it — so a future typo
   in css/rewind.css can't do the same thing twice. Not rewind-specific:
   any future print-only block can reuse it. */
.print-only {
  display: none !important;
}

@media print {
  .print-only {
    display: block !important;
  }
}

/* ---------- Shape pass Stage 2: Keys ----------
   The four button kinds from design/shape-kit/SHAPE-KIT.md ("Keys").
   .key is shared; add exactly one of the four modifiers. Each button
   keeps its own layout rules (width, margin, placement) in its own
   class — these only set the look. */

.key {
  min-height: 44px;
  border: 2px solid var(--ink);
  border-radius: var(--r-key);
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 0.06s ease, box-shadow 0.06s ease;
}

.key:active:not([disabled]) {
  transform: translateY(3px);
  box-shadow: none;
}

.key[disabled] {
  opacity: 0.5;
  box-shadow: none;
  cursor: default;
}

.key--commit {
  min-height: 52px;
  background: var(--yellow);
  color: var(--ink);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  letter-spacing: 0.05em;
  box-shadow: var(--shadow-key);
}

.key--secondary {
  min-height: 46px;
  background: var(--paper-white);
  color: var(--ink);
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 700;
  letter-spacing: 0.08em;
  box-shadow: var(--shadow-key-sm);
}

.key--danger {
  min-height: 46px;
  background: var(--danger);
  color: var(--on-danger);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  box-shadow: var(--shadow-key-sm);
}

.key--quiet {
  min-height: 44px;
  border: none;
  background: none;
  box-shadow: none;
  text-transform: none;
  color: var(--link);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 4px;
}

.key--quiet:active:not([disabled]) {
  transform: none;
}

/* Night: secondary keys sitting on the page go dark. Commit and danger
   keep their fills; their shadows already turn black via the tokens. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .key--secondary {
    background: var(--dark-field);
    border-color: var(--dark-rim);
    color: var(--dark-text);
  }
}

:root[data-theme="dark"] .key--secondary {
  background: var(--dark-field);
  border-color: var(--dark-rim);
  color: var(--dark-text);
}

/* Night: a secondary key on a light panel (the shelf-talker, the coaching
   note, a receipt or card stock) keeps its Day look, just dimmed — add
   .key--on-paper alongside .key--secondary. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .key--secondary.key--on-paper {
    background: var(--dark-key-on-paper);
    border-color: var(--ink);
    color: var(--ink);
  }
}

:root[data-theme="dark"] .key--secondary.key--on-paper {
  background: var(--dark-key-on-paper);
  border-color: var(--ink);
  color: var(--ink);
}

/* ---------- Shape pass Stage 2: one focus ring ---------- */

button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* ================================================================
   Shelf strips (shape pass Stage 3) — every page and Home section
   title is a navy shelf strip with a yellow clip-on label, per
   design/shape-kit/SHAPE-KIT.md "Headers — Shelf strip". The strip
   runs edge to edge across its column by cancelling the column's own
   side padding: --screen-pad-x mirrors .screen's padding at each
   breakpoint, and a container with extra padding of its own sets
   --strip-bleed instead. Never tilted. At Night the strip and label
   keep their colours; only the edges go black (--strip-edge).
   ================================================================ */

.screen {
  --screen-pad-x: 16px;
}

@media (min-width: 700px) and (max-width: 899px) {
  .screen {
    --screen-pad-x: 24px;
  }
}

@media (min-width: 900px) {
  .screen {
    --screen-pad-x: 32px;
  }
}

.strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-inline: calc(-1 * var(--strip-bleed, var(--screen-pad-x, 16px)));
  padding-inline: max(12px, var(--strip-bleed, var(--screen-pad-x, 16px)));
  background: var(--blue);
  border-top: 2px solid var(--strip-edge);
  border-bottom: 5px solid var(--strip-edge);
  transform: none;
}

.strip--page {
  min-height: 62px;
}

.strip--section {
  min-height: 48px;
}

.strip-label {
  margin: 0;
  min-width: 0;
  padding: 6px 12px;
  background: var(--yellow);
  border: 2px solid var(--strip-edge);
  border-radius: var(--r-paper);
  color: var(--ink);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  font-size: 20px;
  line-height: 1.1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.strip--section .strip-label {
  padding: 4px 10px;
  font-size: 13px;
}

.strip-link {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  min-height: 44px;
  padding: 0 4px;
  border: 0;
  background: none;
  color: var(--on-blue);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 4px;
  white-space: nowrap;
  cursor: pointer;
}

/* The small muted line that used to sit above or below a title. */
.strip-sub {
  margin: 8px 0 0;
  color: var(--text-muted);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* Your Card's section adds its own 16px side padding inside .screen. */
.card-screen {
  --strip-bleed: calc(var(--screen-pad-x, 16px) + 16px);
}

.card-screen > .strip-sub {
  margin-bottom: 20px;
}

/* Rank a Film: the hero no longer left-aligns its children, so the
   strip can stretch. From 700px it sits in the right-hand column beside
   the film panel, so it stays inside that column. */
.rank-hero {
  align-items: stretch;
  gap: 0;
}

@media (min-width: 700px) {
  .rank-hero {
    --strip-bleed: 0px;
  }
}

/* The Shelf: the title and aisle sign moved out of .shelf-header into
   the strip, so from 700px the count and search share one row. */
@media (min-width: 700px) {
  .shelf-header .shelf-count {
    grid-row: 1;
    align-self: center;
  }

  .shelf-header .search-field {
    grid-row: 1;
  }
}

/* 700–1199px: Top of the year is the right-hand grid column, so its
   strip stays inside that column instead of bleeding into the gap. */
@media (min-width: 700px) and (max-width: 1199px) {
  .hp-section-top > .strip {
    --strip-bleed: 0px;
  }
}

/* ================================================================
   Staff Picks look pass: the clip-on name tag (js/ui.js's jaNameTagHTML)
   — the one clerk name tag every screen uses (replaces Shape pass Stage
   4's notched ticket). White plastic with a grey metal clip on top, a
   navy band with the store's name, the clerk's name under it. An object:
   the same in day and night. Never tilted. The clip sticks up 9px, so
   the tag keeps that much room above itself.
   ================================================================ */

.ja-tag {
  position: relative;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  width: 100%;
  min-width: 112px;
  margin-top: 9px;
  border: 2px solid var(--ink);
  border-radius: 7px;
  background: var(--paper-white);
  box-shadow: 0 3px 0 var(--ink);
}

.ja-tag--active {
  box-shadow: 0 0 0 3px var(--yellow), 4px 4px 0 3px var(--ink);
}

.ja-tag-clip {
  position: absolute;
  top: -11px;
  left: 50%;
  width: 28px;
  height: 9px;
  margin-left: -14px;
  box-sizing: border-box;
  border: 2px solid var(--ink);
  border-bottom: none;
  border-radius: 3px 3px 0 0;
  background: var(--tag-clip);
}

.ja-tag-band {
  display: block;
  padding: 4px 6px 3px;
  border-radius: 5px 5px 0 0;
  background: var(--cert-navy);
  color: var(--yellow);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 9px;
  line-height: 1.1;
  letter-spacing: 0.16em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ja-tag--active .ja-tag-band {
  background: var(--yellow);
  color: var(--ink);
}

.ja-tag-plate {
  display: block;
  padding: 9px 6px 10px;
  color: var(--ink);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.1;
  letter-spacing: 0.04em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (min-width: 700px) {
  .ja-tag-plate {
    padding-block: 12px 13px;
  }
}

/* ================================================================
   Shape pass Stage 6a: the Shelf's shelving and search field.
   The grid sits on a shelf unit. Every case's slot carries its own
   ledge segment along its bottom; with no column gap the segments join
   into one ledge per row at any column count. .shelf::after repeats the
   ledge under the last row so a part-filled row still runs full width.
   Slots bottom-align, so every case in a row stands on the same ledge.
   Only applies once there are cases, so the empty states are untouched.
   ================================================================ */

.shelf:has(.sc-slot) {
  position: relative;
  column-gap: 0;
  row-gap: 0;
  align-items: end;
  padding: 0 4px;
  background: var(--shelf-back);
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-ink);
}

.shelf .sc-slot {
  padding: 18px 8px 19px;
}

.shelf .sc-slot::after,
.shelf:has(.sc-slot)::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: -4px;
  right: -4px;
  height: 19px;
  box-sizing: border-box;
  background: var(--blue);
  border-top: 2px solid var(--ink);
  border-bottom: 5px solid var(--ink);
  pointer-events: none;
}

.shelf:has(.sc-slot)::after {
  left: 0;
  right: 0;
}

/* The "Checked out" placeholder covers just the case, not the slot's
   padding or its ledge. */
.shelf .sc-checked-out {
  inset: 18px 8px 19px;
}

/* The boxed search field. */
.shelf-header .search-field {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 50px;
  padding: 0 12px;
  background: var(--paper-white);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-ink-sm);
}

.shelf-search-icon {
  flex: none;
}

.shelf-header .search-field input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-size: 16px;
  outline: none;
}

.shelf-header .search-field:has(input:focus-visible) {
  outline: var(--focus-ring);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .shelf:has(.sc-slot) {
    background-color: var(--dark-shelf-back);
    background-image: linear-gradient(to bottom, rgba(255, 214, 140, 0.10), transparent 35%);
    border-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .shelf .sc-case {
    box-shadow: 0 0 0 1.5px var(--dark-case-edge), 0 12px 20px rgba(0, 0, 0, 0.6);
  }

  :root:not([data-theme="light"]) .shelf-header .search-field {
    background: var(--dark-field);
    border-color: var(--dark-rim);
    color: var(--dark-text);
  }

  :root:not([data-theme="light"]) .shelf-header .search-field input {
    color: var(--dark-text);
  }
}

:root[data-theme="dark"] .shelf:has(.sc-slot) {
  background-color: var(--dark-shelf-back);
  background-image: linear-gradient(to bottom, rgba(255, 214, 140, 0.10), transparent 35%);
  border-color: var(--dark-rim);
}

:root[data-theme="dark"] .shelf .sc-case {
  box-shadow: 0 0 0 1.5px var(--dark-case-edge), 0 12px 20px rgba(0, 0, 0, 0.6);
}

:root[data-theme="dark"] .shelf-header .search-field {
  background: var(--dark-field);
  border-color: var(--dark-rim);
  color: var(--dark-text);
}

:root[data-theme="dark"] .shelf-header .search-field input {
  color: var(--dark-text);
}

/* ---------- Shape pass Stage 6b: search slip, Add drawer, Add panel ---------- */
/* From design/shape-pass/stage6-add-drawer.html (reference only). Search
   results print on a receipt slip; the phone Add sheet is a counter drawer
   (card stock, square top, yellow stripe, a drawer pull); the 700px+ Add
   panel is the same card stock with the same stripe. Each sets its own
   dark ink, so nothing inherits the page's light Night text. Label tape
   chips and VHS cases are untouched. */

.search-results:not(:empty) {
  background: var(--receipt-bg);
  color: var(--receipt-ink);
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-ink-sm);
}

.search-results .search-result .vhs-title {
  color: var(--receipt-ink);
}

.search-results .search-result .vhs-year,
.search-results .search-result-owned-tag {
  color: var(--receipt-muted);
}

/* The row's Add is a small printed key — never a commit key. The whole
   row is the button, so the row itself carries the 44px target. */
.search-results .search-result-add {
  min-height: 32px;
  padding: 0 12px;
  border-radius: var(--r-key);
  background: var(--paper-white);
  color: var(--ink);
  font-size: 0.7rem;
  box-shadow: var(--shadow-key-sm);
}

@media (max-width: 699px) {
  .search-results:not(:empty) {
    padding: 0 12px;
  }

  .search-results .search-result {
    padding: 10px 0;
  }

  .search-results .search-result + .search-result {
    border-top: 1px dashed var(--paper-dash, var(--receipt-edge));
  }
}

@media (min-width: 700px) {
  .search-results:not(:empty) {
    row-gap: 0;
    padding: 4px 14px;
  }

  .search-results .search-result {
    padding: 8px 0;
    border-radius: 0;
  }

  .search-results .search-result:nth-child(n + 3) {
    border-top: 1px dashed var(--paper-dash, var(--receipt-edge));
  }

  .search-results .search-result:hover {
    background: color-mix(in srgb, var(--receipt-edge) 35%, transparent);
  }
}

/* The counter drawer (phone Add sheet). Stripe and its ink line are
   painted as background layers above the card stock. */
@media (max-width: 699px) {
  .add-sheet {
    background:
      linear-gradient(var(--ink), var(--ink)) 0 8px / 100% 2px no-repeat,
      linear-gradient(var(--yellow), var(--yellow)) 0 0 / 100% 8px no-repeat,
      var(--card-stock);
    color: var(--ink);
    border-top: 3px solid var(--ink);
    border-radius: 0;
    box-shadow: 0 -10px 24px rgba(0, 0, 0, 0.35);
    padding-top: 10px;
  }

  .add-sheet-pull {
    flex: none;
    align-self: center;
    width: 72px;
    height: 12px;
    box-sizing: border-box;
    background: var(--drawer-pull);
    border: 2px solid var(--ink);
    border-radius: 3px;
  }

  .add-sheet .add-sheet-title {
    color: var(--ink);
  }

  .add-sheet .add-sheet-year,
  .add-sheet .add-sheet-labels-heading,
  .add-sheet .add-panel-status {
    color: var(--text-muted);
  }
}

/* The Add panel (700px+): the same card stock and stripe, as a flat sheet
   of paper with an ink edge. */
.add-panel {
  background:
    linear-gradient(var(--ink), var(--ink)) 0 8px / 100% 2px no-repeat,
    linear-gradient(var(--yellow), var(--yellow)) 0 0 / 100% 8px no-repeat,
    var(--card-stock);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-ink);
  padding-top: 26px;
}

.add-panel .add-panel-title {
  color: var(--ink);
}

.add-panel .add-panel-year,
.add-panel .add-panel-status {
  color: var(--text-muted);
}

.add-panel .add-panel-status-error,
.add-sheet .add-panel-status-error {
  color: var(--ink);
}

/* Quiet keys printed on paper keep the Day link colour at every light —
   Night's yellow link would be yellow text on light paper. */
.add-panel .key--quiet,
.add-sheet .key--quiet {
  color: var(--card-navy);
}

/* Night: lamp-lit paper, darker small print. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .search-results:not(:empty) {
    background: var(--dark-receipt-bg);
  }

  :root:not([data-theme="light"]) .search-results .search-result .vhs-year,
  :root:not([data-theme="light"]) .search-results .search-result-owned-tag {
    color: var(--dark-receipt-muted);
  }

  :root:not([data-theme="light"]) .add-panel,
  :root:not([data-theme="light"]) .add-sheet {
    background:
      linear-gradient(var(--ink), var(--ink)) 0 8px / 100% 2px no-repeat,
      linear-gradient(var(--yellow), var(--yellow)) 0 0 / 100% 8px no-repeat,
      var(--dark-card-stock);
  }

  :root:not([data-theme="light"]) .add-panel .add-panel-year,
  :root:not([data-theme="light"]) .add-panel .add-panel-status,
  :root:not([data-theme="light"]) .add-sheet .add-sheet-year,
  :root:not([data-theme="light"]) .add-sheet .add-sheet-labels-heading,
  :root:not([data-theme="light"]) .add-sheet .add-panel-status {
    color: var(--dark-paper-muted);
  }

  :root:not([data-theme="light"]) .add-panel .add-panel-status-error,
  :root:not([data-theme="light"]) .add-sheet .add-panel-status-error {
    color: var(--ink);
  }
}

:root[data-theme="dark"] .search-results:not(:empty) {
  background: var(--dark-receipt-bg);
}

:root[data-theme="dark"] .search-results .search-result .vhs-year,
:root[data-theme="dark"] .search-results .search-result-owned-tag {
  color: var(--dark-receipt-muted);
}

:root[data-theme="dark"] .add-panel,
:root[data-theme="dark"] .add-sheet {
  background:
    linear-gradient(var(--ink), var(--ink)) 0 8px / 100% 2px no-repeat,
    linear-gradient(var(--yellow), var(--yellow)) 0 0 / 100% 8px no-repeat,
    var(--dark-card-stock);
}

:root[data-theme="dark"] .add-panel .add-panel-year,
:root[data-theme="dark"] .add-panel .add-panel-status,
:root[data-theme="dark"] .add-sheet .add-sheet-year,
:root[data-theme="dark"] .add-sheet .add-sheet-labels-heading,
:root[data-theme="dark"] .add-sheet .add-panel-status {
  color: var(--dark-paper-muted);
}

:root[data-theme="dark"] .add-panel .add-panel-status-error,
:root[data-theme="dark"] .add-sheet .add-panel-status-error {
  color: var(--ink);
}

/* ---------- Shape pass Stage 7a: Rental History controls ----------
   From design/shape-kit/SHAPE-KIT.md ("Switchers", "VCR displays").
   Year tabs become folder tabs, List / Grid becomes a pair of VCR keys,
   and the Rewind button becomes a VCR front panel. Markup lives in
   js/year.js and js/year-header.js. The ticket stubs are untouched. */

/* Folder tabs. The folder line is an inset shadow along the bottom of
   the row, so it survives the row's sideways scroll; the other tabs stop
   2px above it and the current tab runs down over it. */
.year-screen .year-switcher,
.seen-passed-screen .snp-tabs,
.fixranking-screen .fr-years {
  align-items: flex-end;
  gap: 4px;
  box-shadow: inset 0 -2px 0 var(--ink);
}

.year-screen .year-tab,
.seen-passed-screen .snp-tab,
.fixranking-screen .fr-year-tab {
  min-height: 44px;
  margin-bottom: 2px;
  padding: 0 14px;
  border: 2px solid var(--ink);
  border-bottom: none;
  border-radius: var(--r-plastic) var(--r-plastic) 0 0;
  background: var(--folder-tab-bg);
  color: var(--ink);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 14px;
  font-weight: 400;
  white-space: nowrap;
}

.year-screen .year-tab.year-tab-active,
.seen-passed-screen .snp-tab.snp-tab-active,
.fixranking-screen .fr-year-tab.fr-year-tab-active {
  position: relative;
  z-index: 1;
  min-height: 50px;
  margin-bottom: 0;
  background: var(--yellow);
  border-color: var(--ink);
  color: var(--on-yellow);
}

/* VCR keys: a dark housing holding two keys. The same in Day and Night. */
.year-screen .view-toggle {
  display: flex;
  gap: 4px;
  padding: 4px;
  border: 2px solid var(--ink);
  border-radius: 3px;
  background: var(--vcr-housing);
  overflow: visible;
}

.year-screen .view-toggle-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 12px;
  border: none;
  border-radius: 2px;
  background: var(--vcr-key-bg);
  color: var(--vcr-key-text);
  box-shadow: 0 3px 0 var(--vcr-shadow);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: transform 0.06s ease, box-shadow 0.06s ease;
}

.year-screen .view-toggle-button.view-toggle-active {
  background: var(--yellow);
  color: var(--ink);
  box-shadow: inset 0 3px 0 rgba(0, 0, 0, 0.35);
  transform: translateY(2px);
}

/* The Rewind panel: one wide button, a VCR's front. */
.year-screen .rental-rewind-button {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  width: 100%;
  min-height: 64px;
  padding: 10px 12px;
  border: 2px solid var(--ink);
  border-radius: var(--r-key);
  background:
    linear-gradient(to bottom, rgba(255, 255, 255, 0.12), transparent 2px),
    var(--vcr-housing);
  box-shadow: var(--shadow-key);
  color: var(--vcr-key-text);
  text-align: left;
  transition: transform 0.06s ease, box-shadow 0.06s ease;
}

.year-screen .rental-rewind-button:active {
  transform: translateY(3px);
  box-shadow: none;
}

.rr-led {
  flex: none;
  padding: 6px 8px;
  border-radius: 2px;
  background: var(--vcr-led-bg);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.9);
  color: var(--vcr-led);
  text-shadow: 0 0 6px var(--vcr-led-glow);
  font-family: "Doto", "DotGothic16", monospace;
  font-weight: 900;
  font-size: 14px;
  line-height: 1;
  white-space: nowrap;
}

.rr-text {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.rr-title {
  color: var(--vcr-title);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 15px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.1;
}

.rr-sub {
  color: var(--vcr-panel-sub);
  font-size: 12px;
  line-height: 1.2;
}

.rr-deck {
  display: flex;
  flex: none;
  align-items: center;
  gap: 6px;
}

.rr-reel {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--vcr-panel-sub);
  background: radial-gradient(circle, var(--vcr-key-text) 0 2px, var(--vcr-led-bg) 3px);
}

.rr-key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 28px;
  margin-left: 2px;
  border: 2px solid var(--ink);
  border-radius: 3px;
  background: var(--yellow);
  color: var(--ink);
  box-shadow: 0 2px 0 var(--vcr-shadow);
}

/* Narrow phones: the reels step aside so the title keeps its room. */
@media (max-width: 379px) {
  .rr-reel {
    display: none;
  }
}

/* Night: the unpicked folder tabs go dark; the current tab stays yellow. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .year-screen .year-switcher,
:root:not([data-theme="light"]) .seen-passed-screen .snp-tabs,
:root:not([data-theme="light"]) .fixranking-screen .fr-years {
    box-shadow: inset 0 -2px 0 var(--dark-rim);
  }

  :root:not([data-theme="light"]) .year-screen .year-tab,
:root:not([data-theme="light"]) .seen-passed-screen .snp-tab,
:root:not([data-theme="light"]) .fixranking-screen .fr-year-tab {
    border-color: var(--dark-rim);
    background: var(--dark-field);
    color: var(--dark-text);
  }

  :root:not([data-theme="light"]) .year-screen .year-tab.year-tab-active,
:root:not([data-theme="light"]) .seen-passed-screen .snp-tab.snp-tab-active,
:root:not([data-theme="light"]) .fixranking-screen .fr-year-tab.fr-year-tab-active {
    border-color: var(--dark-rim);
    background: var(--yellow);
    color: var(--on-yellow);
  }
}

:root[data-theme="dark"] .year-screen .year-switcher,
:root[data-theme="dark"] .seen-passed-screen .snp-tabs,
:root[data-theme="dark"] .fixranking-screen .fr-years {
  box-shadow: inset 0 -2px 0 var(--dark-rim);
}

:root[data-theme="dark"] .year-screen .year-tab,
:root[data-theme="dark"] .seen-passed-screen .snp-tab,
:root[data-theme="dark"] .fixranking-screen .fr-year-tab {
  border-color: var(--dark-rim);
  background: var(--dark-field);
  color: var(--dark-text);
}

:root[data-theme="dark"] .year-screen .year-tab.year-tab-active,
:root[data-theme="dark"] .seen-passed-screen .snp-tab.snp-tab-active,
:root[data-theme="dark"] .fixranking-screen .fr-year-tab.fr-year-tab-active {
  border-color: var(--dark-rim);
  background: var(--yellow);
  color: var(--on-yellow);
}

/* ---------- Shape pass Stage 7b: Rental History on laptop ----------
   From design/shape-pass/stage7-year-laptop.html (reference only).
   700px+ only; phone is Stage 7a's and is untouched. The band keeps its
   content and layout but becomes a shape-kit object; the year menu is
   the printed pick list (rows reuse css/home.css's .hp-aisle-row); Top
   of the Charts stands on Home's shelf unit; the printout becomes
   square tractor-feed paper. */

@media (min-width: 700px) {
  /* The band: ink border, a yellow top edge, square paper corners. */
  .year-screen .rental-band {
    grid-template-areas:
      "left   receipt"
      "bars   bars"
      "rewind rewind";
    padding-top: 26px;
    border: 2px solid var(--ink);
    border-radius: var(--r-paper);
    background:
      linear-gradient(var(--yellow), var(--yellow)) top / 100% 8px no-repeat,
      var(--blue);
    box-shadow: var(--shadow-ink);
  }

  /* The Rewind panel was squeezed in the left column, so it gets its
     own full-width row along the bottom of the band. */
  .year-screen .rental-band .rental-rewind-button {
    grid-area: rewind;
    margin-top: 4px;
  }

  /* The receipt: straight-edged paper, lifted, leaning 1 degree. */
  .year-screen .rental-receipt {
    border-radius: 0;
    box-shadow: var(--shadow-lift);
    transform: rotate(-1deg);
  }

  /* The year menu: a printed pick list on receipt paper. */
  .year-screen .rental-year-menu {
    min-width: 190px;
    padding: 10px 16px 12px;
    border: none;
    border-radius: var(--r-paper);
    background: var(--receipt-bg);
    color: var(--receipt-ink);
    box-shadow: var(--shadow-lift);
  }

  .year-screen .rental-year-menu.is-open {
    gap: 0;
  }

  .year-screen .rental-year-option.hp-aisle-row,
  .year-screen .rental-year-option.hp-aisle-row:hover,
  .year-screen .rental-year-option.hp-aisle-row.is-current {
    min-height: 44px;
    padding: 8px 0;
    border-radius: 0;
    background: none;
    color: var(--receipt-ink);
    font-weight: 400;
  }

  .year-screen .rental-year-option .hp-aisle-row-name {
    font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  }

  /* Top of the Charts: a plain section, the cases on a shelf unit. */
  .year-screen .year-charts-card {
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
  }

  .year-screen .year-charts-head {
    margin-bottom: 14px;
  }

  .year-screen .year-charts-unit {
    padding: 0 12px;
  }

  .year-screen .year-charts-row {
    padding: 34px 8px 0;
  }

  .year-screen .year-charts-ledge {
    margin: 0 -12px;
  }

  .year-charts-captions {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 36px;
    padding: 14px 8px 0;
  }

  .year-charts-captions .year-chart-caption {
    width: 136px;
    max-width: none;
    margin-top: 0;
  }

  .year-charts-captions .year-chart-caption[data-rank="1"] {
    order: 2;
    width: 170px;
  }

  .year-charts-captions .year-chart-caption[data-rank="2"] {
    order: 1;
  }

  .year-charts-captions .year-chart-caption[data-rank="3"] {
    order: 3;
  }

  .year-charts-captions .year-chart-caption[data-rank="1"] .year-chart-title {
    font-size: 1.25rem;
  }

  /* The printout: square tractor-feed paper. Its text colours are reset
     here so every cell inside it reads as ink on paper in both themes. */
  .year-screen .year-sheet {
    --surface: var(--paper-white);
    --edge: var(--tractor-perf);
    --greenbar: var(--bluebar);
    background: var(--surface);
    border: 2px solid var(--ink);
    border-radius: 0;
    box-shadow: var(--shadow-ink);
  }

  .year-screen .year-sheet::before,
  .year-screen .year-sheet::after {
    width: 26px;
    background-image: radial-gradient(circle, var(--bg) 4px, var(--tractor-perf) 4px 5px, transparent 5px);
    background-size: 100% 24px;
  }

  .year-screen .year-sheet-inner {
    margin: 0 26px;
    border-left: 2px dashed var(--tractor-perf);
    border-right: 2px dashed var(--tractor-perf);
  }

  .year-screen .year-list > .year-entry:hover {
    background: var(--bluebar);
  }
}

@media (min-width: 1200px) {
  .year-screen .rental-band {
    grid-template-areas:
      "left   bars   receipt"
      "rewind rewind rewind";
    padding-top: 30px;
  }

  .year-charts-captions {
    gap: 64px;
  }

  .year-charts-captions .year-chart-caption {
    width: 160px;
  }

  .year-charts-captions .year-chart-caption[data-rank="1"] {
    width: 200px;
  }
}

/* Night: the band's rim, lamp-lit receipt and pick list, and the
   printout on lamp-lit paper with dark ink. */
@media (min-width: 700px) and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .year-screen .rental-band {
    border-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .year-screen .rental-receipt,
  :root:not([data-theme="light"]) .year-screen .rental-year-menu {
    background: var(--dark-receipt-bg);
    --receipt-muted: var(--dark-receipt-muted);
  }

  :root:not([data-theme="light"]) .year-screen .year-sheet {
    --surface: var(--dark-receipt-bg);
    --greenbar: var(--bluebar-night);
    --text: var(--ink);
    --text-muted: var(--dark-receipt-muted);
    border-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .year-screen .year-list > .year-entry:hover {
    background: var(--bluebar-night);
  }
}

@media (min-width: 700px) {
  :root[data-theme="dark"] .year-screen .rental-band {
    border-color: var(--dark-rim);
  }

  :root[data-theme="dark"] .year-screen .rental-receipt,
  :root[data-theme="dark"] .year-screen .rental-year-menu {
    background: var(--dark-receipt-bg);
    --receipt-muted: var(--dark-receipt-muted);
  }

  :root[data-theme="dark"] .year-screen .year-sheet {
    --surface: var(--dark-receipt-bg);
    --greenbar: var(--bluebar-night);
    --text: var(--ink);
    --text-muted: var(--dark-receipt-muted);
    border-color: var(--dark-rim);
  }

  :root[data-theme="dark"] .year-screen .year-list > .year-entry:hover {
    background: var(--bluebar-night);
  }
}

/* ---------- Shape pass Stage 8a: Return Slip and Showdown ----------
   The Return Slip becomes white paper (yellow stripe, ink rule, hard ink
   shadow) carrying its own dark ink, so its text never follows the page.
   Its tiles become straight stamped keys; a picked tile goes navy with a
   yellow check stamp. The Showdown's face-off sits on a navy counter and
   the landing zone becomes a black VCR ruler. Night rules follow. */

.return-slip {
  --text: var(--ink);
  --text-muted: var(--receipt-muted);
  --slip-rule: var(--edge);
  background: var(--paper-white);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-ink);
}

.return-slip-stripe {
  border-bottom: 2px solid var(--ink);
}

.return-slip-header {
  border-bottom-color: var(--slip-rule);
}

.slip-perforation::before {
  border-top-color: var(--slip-rule);
}

.slip-notch {
  border: 2px solid var(--ink);
}

.slip-tile,
.slip-tile-person,
.slip-tile-place {
  min-height: 92px;
  border: 2px solid var(--ink);
  border-radius: 3px;
  background: var(--paper-white);
  color: var(--ink);
  box-shadow: var(--shadow-key-sm);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8125rem;
  font-weight: 400;
  transform: none;
}

.slip-tile-selected {
  background: var(--card-navy);
  border-color: var(--ink);
  color: var(--paper-white);
  box-shadow: var(--shadow-ink-sm);
  transform: none;
}

.slip-initial,
.slip-tile-selected .slip-initial {
  border: 2px solid var(--ink);
}

.slip-stamp {
  top: -8px;
  right: -8px;
  width: 26px;
  height: 26px;
  border: 2px solid var(--ink);
  color: var(--ink);
  box-shadow: none;
  transform: rotate(-6deg);
}

.slip-tile-selected .slip-stamp {
  animation-name: slip-stamp-in-8a;
}

@keyframes slip-stamp-in-8a {
  0% {
    transform: scale(1.9) rotate(-30deg);
    opacity: 0;
  }
  60% {
    transform: scale(0.86) rotate(-4deg);
    opacity: 1;
  }
  100% {
    transform: scale(1) rotate(-6deg);
    opacity: 1;
  }
}

/* The Showdown counter — the face-off sits on navy with a yellow top edge.
   The two tapes keep their lean toward each other (-2deg / 2deg). */
.showdown-faceoff {
  padding: 20px 18px 18px;
  background: var(--blue);
  border: 2px solid var(--ink);
  border-top: 8px solid var(--yellow);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-ink);
}

.showdown-vs {
  border: 3px solid var(--ink);
  color: var(--ink);
  box-shadow: none;
  transform: rotate(-6deg);
}

/* The landing zone — a black VCR ruler, the same in both themes. */
.landing-zone {
  gap: 8px;
  padding: 12px 14px;
  background: var(--vcr-ruler);
  border: 2px solid var(--ink);
  border-radius: 3px;
  box-shadow: var(--shadow-ink-sm);
}

.landing-zone-header {
  padding-bottom: 0;
  border-bottom: none;
}

.landing-zone-name {
  color: var(--vcr-key-text);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
}

.landing-zone-range {
  color: var(--yellow);
  font-family: "Doto", "DotGothic16", monospace;
  font-weight: 900;
  font-size: 1.25rem;
  text-shadow: 0 0 6px var(--vcr-amber-glow);
}

.landing-zone-ticks {
  padding-bottom: 4px;
  border-bottom: 2px solid var(--vcr-tick-off);
}

.landing-tick {
  height: 12px;
  border-radius: 1px;
  background: var(--vcr-tick-off);
}

.landing-tick-live {
  height: 26px;
  background: var(--paper-white);
}

.landing-tick-opponent {
  height: 26px;
  background: var(--yellow);
}

.landing-zone-footer {
  color: var(--vcr-ruler-muted);
}

/* Night: the slip goes lamp-lit, its unpicked tiles dim like keys printed
   on paper, picked tiles stay navy; the counter gets the dark-object rim. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .return-slip {
    --text-muted: var(--dark-receipt-muted);
    --slip-rule: var(--dark-paper-dash);
    background: var(--dark-receipt-bg);
  }

  :root:not([data-theme="light"]) .slip-tile:not(.slip-tile-selected) {
    background: var(--dark-key-on-paper);
  }

  :root:not([data-theme="light"]) .showdown-faceoff {
    border-color: var(--dark-rim);
    border-top-color: var(--yellow);
  }
}

:root[data-theme="dark"] .return-slip {
  --text-muted: var(--dark-receipt-muted);
  --slip-rule: var(--dark-paper-dash);
  background: var(--dark-receipt-bg);
}

:root[data-theme="dark"] .slip-tile:not(.slip-tile-selected) {
  background: var(--dark-key-on-paper);
}

:root[data-theme="dark"] .showdown-faceoff {
  border-color: var(--dark-rim);
  border-top-color: var(--yellow);
}

@media (prefers-reduced-motion: reduce) {
  .slip-tile-selected .slip-stamp {
    animation: none;
  }
}

/* ---------- Shape pass Stage 8b: Where It Lands clipboard, tape counter ----------
   Where It Lands' list sits on a sheet of white paper clipped to a wood
   board. Neighbour rows lose their boxes and are split by dashed rules;
   the new film is a straight yellow slip with a hard ink shadow, and the
   nudge arrows become small white keys. The round counter becomes a
   black VCR tape counter with glowing yellow Doto digits. The wood, clip,
   counter and yellow row are the same in both themes; night rules follow. */

.lands-board {
  position: relative;
  margin-top: 18px;
  padding: 12px;
  background: var(--clipboard-wood);
  border: 2px solid var(--ink);
  border-radius: var(--r-plastic);
  box-shadow: var(--shadow-ink);
}

.lands-clip {
  position: absolute;
  top: -18px;
  left: 50%;
  z-index: 3;
  width: 120px;
  height: 34px;
  margin-left: -60px;
  box-sizing: border-box;
  background: linear-gradient(var(--clip-metal-top), var(--clip-metal-bottom));
  border: 2px solid var(--ink);
  border-radius: 4px 4px 2px 2px;
  box-shadow: 0 3px 0 var(--ink);
}

.lands-clip::after {
  content: "";
  position: absolute;
  top: 7px;
  left: 50%;
  width: 36px;
  height: 10px;
  margin-left: -18px;
  box-sizing: border-box;
  border-radius: 5px;
  background: var(--bg);
  border: 2px solid var(--ink);
}

.lands-card {
  --text: var(--ink);
  --text-muted: var(--receipt-muted);
  --sheet-rule: var(--edge);
  padding: 26px 12px 14px;
  background: var(--paper-white);
  color: var(--ink);
  border: none;
  border-radius: var(--r-paper);
  box-shadow: none;
}

.lands-card-header {
  border-bottom-color: var(--sheet-rule);
}

.lands-row {
  border: none;
  border-radius: 0;
  background: transparent;
}

.lands-row:not(.lands-row-new)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  border-top: 1px dashed var(--sheet-rule);
}

/* The last neighbour row (the one right before the yellow row in the
   markup) is the lowest on the sheet, so no rule under it. */
.lands-row:has(+ .lands-row-new)::after {
  content: none;
}

.lands-row:not(.lands-row-new) .lands-rank {
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 0.875rem;
  font-weight: 700;
}

.lands-row-new {
  background: var(--yellow);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  box-shadow: 4px 4px 0 var(--ink);
}

.lands-row-new .lands-rank,
.lands-row-new .lands-meta {
  color: var(--ink);
}

.lands-row-new.is-dragging {
  box-shadow: 6px 6px 0 var(--ink);
  transform: scale(1.03);
}

.nudge-button {
  width: 44px;
  height: 44px;
  border: 2px solid var(--ink);
  border-radius: 3px;
  background: var(--paper-white);
  color: var(--ink);
  box-shadow: 0 2px 0 var(--ink);
}

.showdown-counter {
  align-items: center;
  padding: 6px 10px;
  background: var(--vcr-ruler);
  border: 2px solid var(--ink);
  border-radius: 2px;
  box-shadow: none;
}

.showdown-counter-label {
  color: var(--vcr-counter-label);
  opacity: 1;
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 9px;
  letter-spacing: 0.14em;
}

.showdown-counter-value {
  color: var(--yellow);
  font-family: "Doto", monospace;
  font-weight: 900;
  font-size: 1.5rem;
  line-height: 1;
  text-shadow: 0 0 6px var(--vcr-amber-glow);
}

/* Night: the sheet goes lamp-lit like the Return Slip; the board takes
   the dark-object rim. Wood, clip and the yellow row stay put. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .lands-card {
    --text-muted: var(--dark-receipt-muted);
    --sheet-rule: var(--dark-paper-dash);
    background: var(--dark-receipt-bg);
  }

  :root:not([data-theme="light"]) .lands-board {
    border-color: var(--dark-rim);
  }
}

:root[data-theme="dark"] .lands-card {
  --text-muted: var(--dark-receipt-muted);
  --sheet-rule: var(--dark-paper-dash);
  background: var(--dark-receipt-bg);
}

:root[data-theme="dark"] .lands-board {
  border-color: var(--dark-rim);
}

/* ---------- Shape pass Stage 9a: the phone menu ----------
   The drawer's pills become straight hanging signs on a rail: white
   paper, ink border and shadow, an icon tile on the left (the member's
   mascot for Your Card), a grey count tag on the right, and two dotted
   chains rising from the top. The current screen's sign goes yellow.
   Rank a Film, nearest the thumb, is the dark "return slot". Nothing
   tilts. Night rules follow. */

.drawer-content {
  gap: 14px;
}

.drawer-header {
  align-items: flex-end;
  width: 100%;
  max-width: 340px;
  box-sizing: border-box;
  padding: 12px 14px;
  background: var(--blue);
  border: 2px solid var(--ink);
  border-top: 6px solid var(--yellow);
  border-radius: 3px;
  box-shadow: var(--shadow-ink-sm);
}

.drawer-rail {
  display: block;
  width: 100%;
  max-width: 340px;
  height: 8px;
  box-sizing: border-box;
  background: var(--menu-rail);
  border-top: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
}

.drawer-pill {
  position: relative;
  gap: 12px;
  padding: 8px 14px 8px 9px;
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  background: var(--paper-white);
  color: var(--ink);
  box-shadow: var(--shadow-ink-sm);
  font-size: 15px;
  letter-spacing: 0.06em;
}

.drawer-pill:hover:not(:disabled) {
  background: var(--paper-white);
}

.drawer-pill::before,
.drawer-pill::after {
  content: "";
  position: absolute;
  top: -16px;
  height: 14px;
  border-left: 2px dotted var(--menu-chain);
  pointer-events: none;
}

.drawer-pill::before {
  left: 30%;
}

.drawer-pill::after {
  left: 82%;
}

.drawer-pill-tile {
  flex: 0 0 38px;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 2px;
  background: var(--blue);
  color: var(--yellow);
}

.drawer-pill-tile svg {
  display: block;
}

.drawer-pill-card .drawer-pill-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.drawer-pill-label {
  font-size: 15px;
}

.drawer-pill-count {
  flex: 0 0 auto;
  padding: 3px 7px;
  border-radius: 2px;
  background: var(--menu-count-bg);
  color: var(--ink);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0;
}

/* The current screen's sign. */
.drawer-pill-active {
  min-height: 56px;
  background: var(--yellow);
  color: var(--ink);
  border-color: var(--ink);
  box-shadow: var(--shadow-ink-md);
}

.drawer-pill-active:hover:not(:disabled) {
  background: var(--yellow);
}

.drawer-pill-active .drawer-pill-tile {
  background: var(--ink);
  color: var(--yellow);
}

.drawer-pill-active .drawer-pill-count {
  background: var(--ink);
  color: var(--yellow);
}

/* Rank a Film: the return slot. No chains — a slot line across its top. */
.drawer-pill-slot,
.drawer-pill-slot.drawer-pill-active,
.drawer-pill-slot:hover:not(:disabled) {
  min-height: 64px;
  padding: 14px 14px 8px 9px;
  background: var(--vcr-housing);
  color: var(--yellow);
  box-shadow: var(--shadow-ink-md);
}

.drawer-pill-slot::before {
  top: 6px;
  left: 50%;
  width: 110px;
  height: 5px;
  margin-left: -55px;
  border-left: none;
  border-radius: 2px;
  background: var(--vcr-led-bg);
  box-shadow: inset 0 1px 2px var(--vcr-shadow);
}

.drawer-pill-slot::after {
  content: none;
}

.drawer-pill-slot .drawer-pill-tile,
.drawer-pill-slot.drawer-pill-active .drawer-pill-tile {
  background: var(--yellow);
  color: var(--ink);
}

.drawer-pill-slot .drawer-pill-label {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
  font-size: 17px;
}

.drawer-pill-kicker {
  color: var(--vcr-ruler-muted);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
}

/* Night: white signs dim to paper under the lamp; the yellow current
   sign and the dark return slot stay as they are. Shadows follow the
   Night ink shadow tokens on their own. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .drawer-pill:not(.drawer-pill-active):not(.drawer-pill-slot) {
    background: var(--dark-key-on-paper);
  }
}

:root[data-theme="dark"] .drawer-pill:not(.drawer-pill-active):not(.drawer-pill-slot) {
  background: var(--dark-key-on-paper);
}

/* ---------- Shape pass Stage 10c: Your Card ----------
   From design/shape-pass/stage10-your-card-laptop.html (reference only).
   The card keeps its flip and its lean (-2° phone, -3° wider — both
   within the kit's 3°), and always sits above the receipt (z-index 2 vs
   1), so where they overlap the receipt tucks behind. The receipt's
   barcode now uses the same varied-width generator as the card's own
   (js/shelf.js's barCode/barcodeHTML). Laptop: two top-aligned columns
   filling the content width — the card (~560px) with the plaque under
   it, the receipt (~320px, 1° lean) with Sign Out under it. */

.cc-receipt-barcode {
  display: flex;
  align-items: stretch;
  width: auto;
  background-image: none;
}

.cc-receipt-barcode span {
  display: block;
  background: var(--receipt-ink);
}

@media (min-width: 1200px) {
  .cc-layout {
    grid-template-columns: minmax(0, 560px) minmax(0, 320px);
    justify-content: space-between;
    align-items: start;
    column-gap: 48px;
  }

  .cc-card {
    max-width: 560px;
    aspect-ratio: 580 / 372;
  }

  .cc-receipt {
    max-width: 320px;
    transform: rotate(1deg);
  }

  .cc-signout {
    max-width: 320px;
  }
}

/* ---------- Your Card: real Code 39 barcodes ----------
   The card and the receipt both carry the member code (JA + member-since
   year + first initial) as a real Code 39 SVG from js/ui.js's code39SVG,
   1px narrow bars, with the code printed underneath. The card's sits on a
   small white label so the bars read as dark ink, never white on navy;
   the receipt's is dark ink straight on the paper. Both colours are fixed,
   so neither changes at night. */

.cc-card-barcode,
.cc-receipt-barcode {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  width: auto;
  height: auto;
  background: none;
  opacity: 1;
}

.cc-card-barcode {
  align-self: flex-start;
  padding: 3px 4px 2px;
  border-radius: 2px;
  background: var(--paper-white);
  color: var(--print-ink);
}

.cc-receipt-barcode {
  color: var(--receipt-ink);
}

.cc-barcode-svg {
  display: block;
  flex-shrink: 0;
}

.cc-card-barcode .cc-barcode-text,
.cc-receipt-barcode .cc-barcode-text {
  display: block;
  background: none;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 9px;
  line-height: 1;
  letter-spacing: 0.3em;
  text-align: center;
  color: inherit;
}

.cc-receipt-barcode .cc-barcode-text {
  font-size: 10px;
}

@container cardscreen (min-width: 620px) {
  .cc-card-barcode {
    height: auto;
  }
}

/* ================================================================
   Rental Agreement — Stage 2 (js/rental.js): Home's entry button, the
   Start screen, the Tapes-dealt placeholder and the invite card. Phone
   first; wider screens just centre the same column. Everything here is
   straight — no tilt on headers, panels, keys, lists or the slip.
   ================================================================ */

/* Home: Tonight's Pick and the entry button share the pick column. */
.hp-pick-col {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

@media (min-width: 700px) {
  .hp-pick-col {
    grid-area: pick;
  }
}

/* The navy counter with a yellow top edge — Home's entry, the signing
   panel, the dealt placeholder and the invite card all share it. */
.ra-entry,
.ra-panel,
.ra-dealt,
.ra-invite {
  background: var(--blue);
  color: var(--on-blue);
  border: 2px solid var(--ink);
  border-top: 8px solid var(--yellow);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-ink);
}

.ra-entry {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 72px;
  padding: 14px 16px;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.ra-entry:active {
  transform: translateY(3px);
  box-shadow: none;
}

.ra-entry-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.ra-entry-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.ra-entry-line {
  font-size: 0.875rem;
  font-weight: 600;
}

.ra-entry-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: var(--yellow);
  color: var(--ink);
  font-weight: 800;
  font-size: 1.125rem;
}

/* ---------- The screen ---------- */

.ra-screen {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 560px;
  margin: 0 auto;
}

.ra-heading {
  margin: 4px 0 0;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.375rem;
  line-height: 1.15;
  color: var(--text);
}

.ra-lede {
  margin: -8px 0 0;
  color: var(--text-muted);
  font-size: 0.9375rem;
  line-height: 1.45;
}

.ra-status {
  margin: 0;
  color: var(--danger);
  font-weight: 700;
  font-size: 0.875rem;
}

/* Signing tonight */
.ra-panel {
  padding: 14px 16px 6px;
}

.ra-panel-title,
.ra-terms-title {
  margin: 0 0 6px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.ra-members {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ra-member {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 60px;
  padding: 8px 0;
}

.ra-member + .ra-member {
  border-top: 2px dashed color-mix(in srgb, var(--on-blue) 35%, transparent);
}

.ra-mascot {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  overflow: hidden;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: var(--paper-white);
  color: var(--ink);
  font-weight: 800;
}

.ra-mascot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ra-member-name {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 800;
  font-size: 1rem;
}

.ra-you {
  font-weight: 600;
  font-size: 0.8125rem;
}

.ra-member-status {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  text-align: right;
}

.ra-badge {
  padding: 3px 8px;
  border-radius: var(--r-paper);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ra-badge--ready {
  border: 2px solid var(--ink);
  background: var(--yellow);
  color: var(--ink);
}

.ra-badge--waiting {
  border: 2px dashed var(--on-blue);
  color: var(--on-blue);
}

.ra-member-note {
  font-size: 0.75rem;
  font-weight: 600;
}

/* Pull from */
.ra-pull {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.ra-screen .hp-aisle-sign {
  transform: none;
  border: 2px solid var(--ink);
  box-shadow: var(--shadow-ink-sm);
}

.ra-screen .hp-aisle-current {
  max-width: 220px;
}

.ra-screen .ra-aisle-locked {
  cursor: default;
}

.ra-pull-note {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.875rem;
}

.ra-send {
  padding: 0 18px;
}

/* The chooser's rows are real checkboxes on the printed pick list. */
.ra-aisle-list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.ra-aisle-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 4px 0;
  color: var(--receipt-ink);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
}

.ra-aisle-row + .ra-aisle-row {
  border-top: 2px dotted var(--receipt-edge);
}

.ra-aisle-row:first-child {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  letter-spacing: 0.04em;
}

.ra-aisle-check {
  flex: none;
  width: 24px;
  height: 24px;
  margin: 0;
  accent-color: var(--card-navy);
  cursor: pointer;
}

.ra-aisle-name {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* The terms — a paper slip, straight. */
.ra-terms {
  padding: 16px 18px 14px;
  background: var(--receipt-bg);
  color: var(--receipt-ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-lift);
}

.ra-terms-title {
  padding-bottom: 8px;
  margin-bottom: 8px;
  border-bottom: 2px dashed var(--paper-dash, var(--receipt-edge));
}

.ra-terms-list {
  margin: 0;
  padding-left: 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 0.9375rem;
  line-height: 1.35;
}

/* Deal the tapes */
.ra-deal {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding-bottom: 8px;
}

.ra-deal-key {
  width: 100%;
  font-size: 1rem;
}

.ra-deal-caption {
  margin: 0;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.875rem;
  font-weight: 700;
}

.ra-call-off {
  align-self: center;
}

/* Tapes dealt — the placeholder until round one exists. */
.ra-dealt {
  padding: 22px 18px;
  text-align: center;
}

.ra-dealt-title {
  margin: 0 0 6px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.5rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.ra-dealt-line {
  margin: 0;
  font-size: 0.9375rem;
}

.ra-dealt-cancel {
  align-self: center;
  padding: 0 22px;
}

/* ---------- The invite card, on the other member's device ----------
   Fixed above every screen; on phone it sits just above the round drawer
   trigger so the two never overlap. */
.ra-invite {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 88px);
  z-index: 90;
  max-width: 440px;
  margin: 0 auto;
  padding: 14px 16px 10px;
}

@media (min-width: 700px) {
  .ra-invite {
    left: auto;
    right: 24px;
    bottom: 24px;
    width: 380px;
  }
}

.ra-invite-title {
  margin: 0 0 4px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.125rem;
  line-height: 1.2;
}

.ra-invite-line {
  margin: 0 0 12px;
  font-size: 0.9375rem;
  line-height: 1.4;
}

.ra-status--invite {
  margin-bottom: 10px;
  padding: 6px 8px;
  background: var(--paper-white);
  border-radius: var(--r-paper);
}

.ra-invite-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.ra-invite-join {
  flex: 1 1 auto;
}

.ra-invite .key--quiet {
  color: var(--on-blue);
}

/* ---------- Night ---------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ra-entry,
  :root:not([data-theme="light"]) .ra-panel,
  :root:not([data-theme="light"]) .ra-dealt,
  :root:not([data-theme="light"]) .ra-invite {
    border-color: var(--dark-rim);
    border-top-color: var(--yellow);
  }

  :root:not([data-theme="light"]) .ra-terms {
    background: var(--dark-receipt-bg);
  }

  :root:not([data-theme="light"]) .ra-screen .hp-aisle-sign {
    border-color: var(--dark-rim);
  }
}

:root[data-theme="dark"] .ra-entry,
:root[data-theme="dark"] .ra-panel,
:root[data-theme="dark"] .ra-dealt,
:root[data-theme="dark"] .ra-invite {
  border-color: var(--dark-rim);
  border-top-color: var(--yellow);
}

:root[data-theme="dark"] .ra-terms {
  background: var(--dark-receipt-bg);
}

:root[data-theme="dark"] .ra-screen .hp-aisle-sign {
  border-color: var(--dark-rim);
}

/* ================================================================
   Rental Agreement — Stage 3 (js/rental-hand.js): round one, one tape
   at a time. Only the tape leans (like a Showdown tape); the strip, the
   panel, the keys, the dots and the status strip stay straight.
   ================================================================ */

/* The LED readout sits on the right of the strip. */
.ra-readout {
  flex: none;
}

/* The navy panel holding the tape and its details. */
.ra-tape-panel {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 18px 16px 16px;
}

.ra-tape {
  flex: 0 0 120px;
  width: 120px;
  padding: 6px 6px 8px;
  border-radius: var(--r-plastic);
  background: var(--case-bg);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.35);
  transform: rotate(-2deg);
}

.ra-tape.is-fresh {
  animation: ra-tape-in 300ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

@keyframes ra-tape-in {
  from {
    transform: translateX(40px) rotate(6deg);
    opacity: 0;
  }
  to {
    transform: rotate(-2deg);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ra-tape.is-fresh {
    animation: none;
  }
}

.ra-tape-info {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1 1 auto;
}

.ra-tape-title {
  margin: 0;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.25rem;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.ra-tape-meta {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 600;
}

/* Now playing on — plain stickers, not links. */
.ra-where {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
}

.ra-where-label {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.ra-where-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.ra-where-loading {
  font-size: 0.8125rem;
  font-weight: 600;
}

.ra-where-tag,
.ra-where-stamp {
  padding: 3px 8px;
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  background: var(--paper-white);
  color: var(--ink);
  font-size: 0.8125rem;
  font-weight: 800;
}

.ra-where-tag--rent {
  background: var(--receipt-bg);
  color: var(--receipt-ink);
}

.ra-where-stamp {
  border-color: var(--stamp-red);
  color: var(--stamp-red);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Yeses left, with four dots that empty as they're used. */
.ra-yeses {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  color: var(--text);
  font-weight: 800;
}

.ra-yes-dots {
  display: flex;
  gap: 8px;
}

.ra-yes-dot {
  width: 16px;
  height: 16px;
  border: 2px solid var(--text);
  border-radius: 50%;
}

.ra-yes-dot.is-left {
  border-color: var(--ink);
  background: var(--yellow);
}

/* Not tonight / Up for it, side by side. */
.ra-vote {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.ra-vote-key {
  min-height: 52px;
  padding: 0 10px;
  font-size: 1rem;
}

.ra-vote-note {
  margin: -6px 0 0;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.875rem;
  font-weight: 700;
}

/* The other member's progress — a dark strip, straight. */
.ra-progress {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  background: var(--case-bg);
  color: var(--on-blue);
}

.ra-progress-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.ra-progress-line {
  font-weight: 800;
  font-size: 0.9375rem;
}

.ra-progress-note {
  font-size: 0.8125rem;
  opacity: 0.8;
}

/* Deal me in / Back to Home. */
.ra-wide-key {
  width: 100%;
  font-size: 1rem;
}

/* Bigger tape from iPad up; the column is already capped at 560px. */
@media (min-width: 700px) {
  .ra-tape {
    flex-basis: 150px;
    width: 150px;
  }

  .ra-tape-title {
    font-size: 1.5rem;
  }
}

/* Night: the dark objects take the rim; empty dots follow the page text. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ra-progress {
    border-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .ra-tape {
    box-shadow: 0 0 0 1.5px var(--dark-case-edge, var(--dark-rim)), 0 6px 14px rgba(0, 0, 0, 0.6);
  }
}

:root[data-theme="dark"] .ra-progress {
  border-color: var(--dark-rim);
}

:root[data-theme="dark"] .ra-tape {
  box-shadow: 0 0 0 1.5px var(--dark-case-edge, var(--dark-rim)), 0 6px 14px rgba(0, 0, 0, 0.6);
}

/* ================================================================
   Rental Agreement — Stage 4 (js/rental-rank.js): round two, your
   order. Only the handwritten signature name leans; the rows, the
   panel, the slip, the keys and the dragged row all stay straight.
   ================================================================ */

.ra-rank-panel {
  padding: 14px 12px 12px;
}

.ra-rank-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* One white card per film. Flat until it's picked up (the HyperCard
   rule): the 2px border is there so the yellow one doesn't shift it. */
.ra-rank-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 76px;
  padding: 6px 4px 6px 8px;
  border: 2px solid transparent;
  border-radius: var(--r-paper);
  background: var(--paper-white);
  color: var(--ink);
  user-select: none;
  -webkit-user-select: none;
}

@media (prefers-reduced-motion: no-preference) {
  .ra-rank-row {
    transition: transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
  }
}

.ra-rank-row.is-lifted,
.ra-rank-list.no-slide .ra-rank-row {
  transition: none;
}

.ra-rank-row.is-lifted {
  z-index: 2;
  border-color: var(--yellow);
  box-shadow: 0 0 0 2px var(--ink), 0 14px 26px rgba(0, 0, 0, 0.4);
}

/* The position number — a little dot-matrix LED. */
.ra-rank-pos {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 36px;
  width: 36px;
  height: 40px;
  border: 2px solid var(--ink);
  border-radius: 2px;
  background: var(--vcr-ruler);
  color: var(--yellow);
  font-family: "Doto", "DotGothic16", monospace;
  font-weight: 900;
  font-size: 1.5rem;
  line-height: 1;
  text-shadow: 0 0 6px var(--vcr-amber-glow);
}

.ra-rank-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 44px;
  width: 44px;
  height: 64px;
  padding: 3px;
  overflow: hidden;
  border-radius: var(--r-plastic);
  background: var(--case-bg);
}

.ra-rank-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 2px;
}

.ra-rank-noart {
  color: var(--on-blue);
  font-size: 0.75rem;
  font-weight: 700;
  text-align: center;
  line-height: 1.1;
}

.ra-rank-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1 1 auto;
  min-width: 0;
}

.ra-rank-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.ra-rank-meta {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
  opacity: 0.75;
}

/* The drag handle: a real 44px button, three lines. Only here does a
   touch stop scrolling the page. */
.ra-rank-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-key);
  background: transparent;
  color: var(--ink);
  cursor: grab;
  touch-action: none;
}

.ra-rank-list.is-dragging .ra-rank-handle {
  cursor: grabbing;
}

.ra-rank-grip {
  width: 22px;
  height: 14px;
  background:
    linear-gradient(var(--ink), var(--ink)) top / 100% 2px no-repeat,
    linear-gradient(var(--ink), var(--ink)) center / 100% 2px no-repeat,
    linear-gradient(var(--ink), var(--ink)) bottom / 100% 2px no-repeat;
}

.ra-rank-handle:disabled {
  cursor: default;
  opacity: 0.3;
}

/* Member signature — a paper slip, straight; only the name leans. */
.ra-sign-slip {
  padding: 14px 18px 18px;
  background: var(--receipt-bg);
  color: var(--receipt-ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-lift);
}

.ra-sign-head {
  margin: 0 0 10px;
  padding-bottom: 8px;
  border-bottom: 2px dashed var(--paper-dash, var(--receipt-edge));
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.ra-sign-line {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  min-height: 52px;
  border-bottom: 2px solid var(--receipt-ink);
}

.ra-sign-x {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.25rem;
  line-height: 1.4;
}

.ra-sign-name {
  display: inline-block;
  min-width: 0;
  padding-bottom: 2px;
  font-family: "Permanent Marker", "Caveat", cursive;
  font-size: 1.75rem;
  line-height: 1.2;
  color: var(--card-navy);
  overflow-wrap: anywhere;
  transform: rotate(-2deg);
  transform-origin: left bottom;
}

/* Signed. Waiting for … */
.ra-signed {
  padding: 16px 18px;
}

.ra-signed .ra-dealt-line {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1rem;
  letter-spacing: 0.02em;
}

@media (min-width: 700px) {
  .ra-rank-panel {
    padding: 16px 14px 14px;
  }

  .ra-rank-title {
    font-size: 1.125rem;
  }
}

/* Night: the white cards dim like keys printed on paper; the slip goes
   lamp-lit and keeps its own dark ink. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ra-rank-row {
    background: var(--dark-key-on-paper);
  }

  :root:not([data-theme="light"]) .ra-sign-slip {
    background: var(--dark-receipt-bg);
  }
}

:root[data-theme="dark"] .ra-rank-row {
  background: var(--dark-key-on-paper);
}

:root[data-theme="dark"] .ra-sign-slip {
  background: var(--dark-receipt-bg);
}

/* ================================================================
   Rental Agreement — Stage 5 (js/rental-reveal.js): the reveal, a signed
   agreement form on slip paper. Only three things lean: the tape, the
   night's one stamp and the handwritten names. The form, the table, the
   signature lines and the keys stay straight. Never decorated for
   holidays — it's printed paper.
   ================================================================ */

.rv-form {
  position: relative;
  padding: 18px 18px 20px;
  background: var(--receipt-bg);
  color: var(--receipt-ink);
  border-radius: var(--r-paper);
  box-shadow: var(--shadow-lift);
}

/* The form's printed header, with a solid rule under it. */
.rv-form-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 8px;
  margin-bottom: 14px;
  border-bottom: 2px solid var(--receipt-ink);
}

.rv-form-title {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.rv-form-store {
  flex: none;
  color: var(--receipt-muted);
  font-size: 0.75rem;
  font-weight: 700;
}

.rv-label {
  margin: 0 0 10px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* "The members agree to rent" with the night's one stamp beside it. The
   stamp is in the row, not floating over it, so it takes real room and
   can't cover the title, the header's rule or the table; on a very narrow
   screen it wraps below the label. */
.rv-agree-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  margin-bottom: 14px;
}

.rv-agree-row .rv-label {
  margin: 0;
}

/* The winning tape and its details. */
.rv-film {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 14px;
}

.rv-tape {
  flex: 0 0 100px;
  width: 100px;
}

.rv-film-info {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1 1 auto;
}

.rv-film-title {
  margin: 0;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.375rem;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.rv-film-meta {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 600;
}

.rv-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}

/* IMDb and Trailer — secondary keys printed on paper. */
.rv-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 14px;
  border: 2px solid var(--ink);
  border-radius: var(--r-key);
  background: var(--paper-white);
  color: var(--ink);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: var(--shadow-key-sm);
}

.rv-link:active {
  transform: translateY(3px);
  box-shadow: none;
}

/* The stamp — AGREED, NIGHT DROP, or STAFF PICK (below) — leaning a
   little at the right end of the agree row. */
.rv-stamp {
  flex: none;
  margin: 4px 4px 4px auto;
  padding: 4px 12px;
  border: 3px solid var(--stamp-red);
  border-radius: var(--r-paper);
  color: var(--stamp-red);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.25rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transform: rotate(-6deg);
  opacity: 0.9;
  pointer-events: none;
}

/* Sections below the tape, each under a dashed rule. */
.rv-section {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 2px dashed var(--paper-dash, var(--receipt-edge));
}

/* How you each ranked them — a real table, sized to fit a phone with up
   to four members and four films without scrolling sideways. */
.rv-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.rv-table th,
.rv-table td {
  padding: 7px 4px;
  border-bottom: 1px dashed var(--paper-dash, var(--receipt-edge));
  vertical-align: middle;
}

.rv-table thead th {
  border-bottom: 2px solid var(--receipt-ink);
  font-size: 0.75rem;
  font-weight: 800;
}

/* Member names and Total stay whole words; a long name is clipped with
   an ellipsis (screen readers still get all of it) so four members fit. */
.rv-table thead .rv-col-num {
  max-width: 4em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rv-col-film {
  text-align: left;
  font-weight: 700;
  overflow-wrap: break-word;
  hyphens: auto;
}

.rv-table .rv-col-num {
  width: 1%;
  padding-left: 2px;
  padding-right: 2px;
  text-align: center;
}

.rv-table tbody .rv-col-num {
  white-space: nowrap;
}

.rv-total {
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
}

/* The winner's row: a yellow fill with dark ink, never yellow text. */
.rv-table tr.is-winner th,
.rv-table tr.is-winner td {
  background: var(--yellow);
  color: var(--receipt-ink);
}

.rv-footnote {
  margin: 8px 0 0;
  color: var(--receipt-muted);
  font-size: 0.8125rem;
  font-weight: 700;
}

.rv-match-line {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
}

/* Signatures: one straight line per member; only the name leans. */
.rv-sigs {
  display: grid;
  gap: 14px;
}

.rv-sig {
  display: flex;
  align-items: flex-end;
  gap: 12px;
}

.rv-sig-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
}

.rv-sig-line {
  display: flex;
  align-items: flex-end;
  min-height: 48px;
  border-bottom: 2px solid var(--receipt-ink);
}

.rv-hand {
  display: inline-block;
  min-width: 0;
  padding: 0 4px 2px;
  font-family: "Permanent Marker", "Caveat", cursive;
  font-size: 1.625rem;
  line-height: 1.2;
  color: var(--card-navy);
  overflow-wrap: anywhere;
  transform: rotate(-2deg);
  transform-origin: left bottom;
}

.rv-sig-caption {
  margin-top: 4px;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* STAFF PICK — Tonight's Pick's stamp (.hp-staff-stamp in
   css/home.css): a double border, the clerk's name small underneath. */
.rv-stamp--staff {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 4px 12px;
  border: 4px double var(--stamp-red);
  border-radius: var(--r-key);
  letter-spacing: 0.03em;
}

.rv-stamp-main {
  font-size: 1.125rem;
  line-height: 1;
}

.rv-stamp-sub {
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.12em;
}

/* Watched it? Rank it — the white key under Done, press play on phone. */
.rv-rank {
  width: 100%;
}

.rv-new {
  align-self: center;
  margin-top: -6px;
}

/* The moment of the reveal: the form comes in, then the stamp lands a
   beat later — about 0.75s in all. --rv-t (set by js/rental-reveal.js)
   is a negative delay, so a redraw mid-entrance carries on from there. */
.rv-form.is-arriving {
  animation: rv-form-in 420ms cubic-bezier(0.2, 0.8, 0.2, 1) var(--rv-t, 0ms) backwards;
}

.rv-form.is-arriving .rv-stamp {
  animation: rv-stamp-in 260ms cubic-bezier(0.3, 1.4, 0.5, 1) calc(480ms + var(--rv-t, 0ms)) backwards;
}

@keyframes rv-form-in {
  from {
    opacity: 0;
    transform: translateY(28px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes rv-stamp-in {
  from {
    opacity: 0;
    transform: rotate(-6deg) scale(1.8);
  }
  to {
    opacity: 0.9;
    transform: rotate(-6deg) scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .rv-form.is-arriving,
  .rv-form.is-arriving .rv-stamp {
    animation: none;
  }
}

@media (min-width: 700px) {
  .rv-form {
    padding: 24px 26px 26px;
  }

  .rv-tape {
    flex-basis: 140px;
    width: 140px;
  }

  .rv-film-title {
    font-size: 1.75rem;
  }

  .rv-sigs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 24px;
  }
}

/* Night: the form goes lamp-lit and keeps its own dark ink; small print
   and the stamp darken for that paper; IMDb/Trailer dim like any key
   printed on paper. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .rv-form {
    background: var(--dark-receipt-bg);
  }

  :root:not([data-theme="light"]) .rv-form-store,
  :root:not([data-theme="light"]) .rv-footnote {
    color: var(--dark-receipt-muted);
  }

  :root:not([data-theme="light"]) .rv-stamp,
  :root:not([data-theme="light"]) .rv-form .ra-where-stamp {
    border-color: var(--dark-stamp-on-paper);
    color: var(--dark-stamp-on-paper);
  }

  :root:not([data-theme="light"]) .rv-link {
    background: var(--dark-key-on-paper);
  }
}

:root[data-theme="dark"] .rv-form {
  background: var(--dark-receipt-bg);
}

:root[data-theme="dark"] .rv-form-store,
:root[data-theme="dark"] .rv-footnote {
  color: var(--dark-receipt-muted);
}

:root[data-theme="dark"] .rv-stamp,
:root[data-theme="dark"] .rv-form .ra-where-stamp {
  border-color: var(--dark-stamp-on-paper);
  color: var(--dark-stamp-on-paper);
}

:root[data-theme="dark"] .rv-link {
  background: var(--dark-key-on-paper);
}

/* ================================================================
   Rental Agreement — Stage 6 (js/rental-desk.js): the front desk, where
   a clerk settles a night with no match or a tie. Only the tape leans.
   The name tags, the speech balloon, the paper card, the label tape,
   the keys and the week strip all stay straight. Also the reveal's two
   front-desk endings (js/rental-reveal.js): the clerk's pitch quoted
   under the film (its STAFF PICK stamp is with the Stage 5 rules).
   ================================================================ */

/* "NO MATCH" is the longest readout; give the strip label room on a
   narrow phone. */
@media (max-width: 399px) {
  .rd-readout .showdown-counter-value {
    font-size: 1.125rem;
  }
}

/* Who's at the desk — the navy counter, name tags in a row of three. */
.rd-desk {
  padding: 14px 14px 16px;
}

.rd-clerks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 8px;
}

.rd-clerk {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 44px;
  padding: 6px 0 0;
  border: none;
  background: transparent;
  color: var(--on-blue);
  font: inherit;
  text-align: center;
  cursor: pointer;
}

.rd-clerk:disabled {
  cursor: default;
}

.rd-clerk-spec {
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.25;
  opacity: 0.75;
}

.rd-clerk[aria-pressed="true"] .rd-clerk-spec {
  color: var(--yellow);
  opacity: 1;
}

/* The clerk and what they're saying: the name tag on the left, a round
   speech balloon pointing at it. */
.rd-says {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  align-items: start;
  gap: 16px;
}

.rd-says-tag {
  display: block;
  padding-top: 4px;
}

.rd-balloon {
  position: relative;
  padding: 12px 14px;
  border: 2px solid var(--ink);
  border-radius: 16px;
  background: var(--card-stock);
  color: var(--receipt-ink);
  box-shadow: var(--shadow-ink-sm);
}

/* The tail, an ink outline with the balloon's fill inside it. */
.rd-says .rd-balloon::before,
.rd-says .rd-balloon::after {
  content: "";
  position: absolute;
  top: 22px;
  border-style: solid;
  border-color: transparent;
}

.rd-says .rd-balloon::before {
  left: -14px;
  border-width: 8px 14px 8px 0;
  border-right-color: var(--ink);
}

.rd-says .rd-balloon::after {
  left: -10px;
  top: 24px;
  border-width: 6px 10px 6px 0;
  border-right-color: var(--card-stock);
}

.rd-balloon-line {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1.4;
}

.rd-balloon.is-thinking .rd-balloon-line {
  font-style: italic;
  font-weight: 600;
}

.rd-balloon-sign {
  margin: 6px 0 0;
  font-size: 0.8125rem;
  font-weight: 800;
  text-align: right;
}

/* The clerk's pick — a paper card with the tape, straight. */
.rd-card {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px;
  border-radius: var(--r-paper);
  background: var(--receipt-bg);
  color: var(--receipt-ink);
  box-shadow: var(--shadow-lift);
}

.rd-tape {
  flex: 0 0 100px;
  width: 100px;
}

.rd-card-info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
  flex: 1 1 auto;
}

.rd-card-title {
  margin: 0;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 1.25rem;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.rd-card-meta {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 600;
}

.rd-card .ra-where {
  align-self: stretch;
}

/* "<Name>'s pick" — label-maker tape, notched ends, straight. */
.rd-label-tape {
  margin-top: 6px;
  padding: 5px 14px;
  background: var(--tape-black);
  color: var(--tape-picked-text);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
  clip-path: polygon(0 0, 100% 0, calc(100% - 6px) 50%, 100% 100%, 0 100%, 6px 50%);
}

/* Clerk picks this week — a dark strip with an LED readout. */
.rd-week {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  background: var(--case-bg);
  color: var(--on-blue);
}

.rd-week-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.rd-week-title {
  font-weight: 800;
  font-size: 0.9375rem;
}

.rd-week-note {
  font-size: 0.8125rem;
  opacity: 0.8;
}

.rd-week-led {
  flex: none;
}

@media (min-width: 700px) {
  .rd-says {
    grid-template-columns: 140px minmax(0, 1fr);
  }

  .rd-tape {
    flex-basis: 130px;
    width: 130px;
  }

  .rd-card-title {
    font-size: 1.5rem;
  }
}

/* The reveal: the clerk's pitch under the film, and "Night drop". */
.rv-pitch {
  margin: 14px 0 0;
  padding: 10px 0 0 14px;
  border-left: 4px solid var(--receipt-edge);
}

.rv-pitch-line {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 600;
  font-style: italic;
  line-height: 1.4;
}

.rv-pitch-sign {
  margin: 4px 0 0;
  font-size: 0.8125rem;
  font-weight: 800;
}

/* Night: paper goes lamp-lit and keeps its own ink; the dark strip and
   the counter take the rim. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .rd-card {
    background: var(--dark-receipt-bg);
  }

  :root:not([data-theme="light"]) .rd-balloon {
    border-color: var(--dark-rim);
    background: var(--dark-card-stock);
  }

  :root:not([data-theme="light"]) .rd-says .rd-balloon::before {
    border-right-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .rd-says .rd-balloon::after {
    border-right-color: var(--dark-card-stock);
  }

  :root:not([data-theme="light"]) .rd-card .ra-where-stamp {
    border-color: var(--dark-stamp-on-paper);
    color: var(--dark-stamp-on-paper);
  }

  :root:not([data-theme="light"]) .rd-week {
    border-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .rv-pitch {
    border-left-color: var(--dark-receipt-muted);
  }
}

:root[data-theme="dark"] .rd-card {
  background: var(--dark-receipt-bg);
}

:root[data-theme="dark"] .rd-balloon {
  border-color: var(--dark-rim);
  background: var(--dark-card-stock);
}

:root[data-theme="dark"] .rd-says .rd-balloon::before {
  border-right-color: var(--dark-rim);
}

:root[data-theme="dark"] .rd-says .rd-balloon::after {
  border-right-color: var(--dark-card-stock);
}

:root[data-theme="dark"] .rd-card .ra-where-stamp {
  border-color: var(--dark-stamp-on-paper);
  color: var(--dark-stamp-on-paper);
}

:root[data-theme="dark"] .rd-week {
  border-color: var(--dark-rim);
}

:root[data-theme="dark"] .rv-pitch {
  border-left-color: var(--dark-receipt-muted);
}

/* ================================================================
   Rental Agreement — big screens (js/rental*.js, `wide`). From 900px,
   where the content area fits two comfortable columns (the laptop with
   its sidebar, an iPad sideways with the rail), each screen draws a
   two-column layout; the classes below only ever appear in that markup,
   so they need no media query of their own. Under 900px (phone, iPad
   portrait) the markup and look are the phone's, unchanged: one column,
   centred, capped at 560px. The strip runs the full width of the content
   area at every size. Same tilt rules: only the tapes, the form's stamp
   and handwritten names lean.
   ================================================================ */

/* The screen spans the content area so the strip can; the body under it
   keeps the phone column unless it's drawn wide. */
.ra-screen {
  max-width: none;
}

.ra-body {
  display: flex;
  flex-direction: column;
  gap: 18px;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
}

.ra-body--wide {
  max-width: none;
}

.ra-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px;
  align-items: start;
}

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

/* ---------- Start: the Pull from panel, list always open ---------- */

.ra-pull-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 18px 18px;
}

.ra-pull-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.ra-pull-head .ra-panel-title {
  margin: 0;
}

/* The summary — a yellow clip-on label, straight, dark ink. */
.ra-pull-summary {
  max-width: 60%;
  overflow: hidden;
  padding: 4px 10px;
  border: 2px solid var(--strip-edge);
  border-radius: var(--r-paper);
  background: var(--yellow);
  color: var(--ink);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ra-aisle-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 24px;
}

.ra-aisle-list--open .ra-aisle-row,
.ra-aisle-list--open .ra-aisle-row + .ra-aisle-row {
  color: var(--on-blue);
  border-top: 2px dashed color-mix(in srgb, var(--on-blue) 35%, transparent);
}

.ra-aisle-list--open .ra-aisle-row:nth-child(-n + 2) {
  border-top: 0;
}

.ra-aisle-list--open .ra-aisle-check {
  accent-color: var(--yellow);
}

.ra-aisle-list--open:disabled .ra-aisle-row,
.ra-aisle-list--open:disabled .ra-aisle-check {
  cursor: default;
}

.ra-pull-panel .ra-pull-note {
  color: var(--on-blue);
}

.ra-pull-panel .ra-send {
  align-self: flex-start;
}

/* ---------- Round one: the tape alone on the left ---------- */

.ra-cols--tape {
  align-items: center;
}

.ra-tape-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 440px;
  padding: 40px 24px;
}

.ra-tape.ra-tape--big {
  flex: none;
  width: 250px;
  padding: 8px 8px 11px;
}

.ra-tape-side {
  gap: 14px;
}

.ra-kicker {
  margin: 0;
  color: var(--text-muted);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.ra-tape-heading {
  margin: -4px 0 0;
  color: var(--text);
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-weight: 400;
  font-size: 2.25rem;
  line-height: 1.08;
  overflow-wrap: anywhere;
}

.ra-tape-side .ra-tape-meta {
  color: var(--text);
  font-size: 1rem;
}

.ra-tape-side .ra-where {
  margin-top: 0;
  color: var(--text);
}

.ra-tape-side .ra-yeses {
  margin-top: 6px;
}

/* ---------- The reveal: one wide form ---------- */

.rv-form--wide {
  padding: 28px 32px 30px;
}

.rv-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 32px;
  align-items: start;
}

.rv-cols--single {
  grid-template-columns: minmax(0, 1fr);
}

.rv-col--how {
  align-self: stretch;
  padding-left: 32px;
  border-left: 2px dashed var(--paper-dash, var(--receipt-edge));
}

/* Every member's signature line in one row, spread evenly. */
.rv-sign-row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 28px;
  margin-top: 24px;
}

.rv-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 20px;
}

.rv-actions .rv-new {
  margin-top: 0;
}

.rv-actions .key--commit {
  min-width: 260px;
}

.rv-actions .rv-rank {
  width: auto;
  min-height: 52px;
  padding: 0 22px;
}

/* ---------- The front desk: one wide navy panel ---------- */

.rd-wide {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px;
  padding: 18px 20px 20px;
}

.rd-wide-left {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

.rd-wide-left .ra-panel-title {
  margin: 0;
}

.rd-wide .rd-clerks {
  margin-top: 0;
}

.rd-wide-right {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  min-width: 0;
}

.rd-clerk.is-on .rd-clerk-spec {
  color: var(--yellow);
  opacity: 1;
}

.rd-pick-keys {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.rd-pick-keys.is-single {
  grid-template-columns: minmax(0, 1fr);
}

.rd-pick-keys .key {
  width: 100%;
  min-height: 52px;
  padding: 0 10px;
}

/* The balloon under the name tags, its tail pointing up at them. */
.rd-balloon--up::before,
.rd-balloon--up::after {
  content: "";
  position: absolute;
  border-style: solid;
  border-color: transparent;
}

.rd-balloon--up::before {
  top: -14px;
  left: 36px;
  border-width: 0 8px 14px;
  border-bottom-color: var(--ink);
}

.rd-balloon--up::after {
  top: -10px;
  left: 38px;
  border-width: 0 6px 10px;
  border-bottom-color: var(--card-stock);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .rd-balloon--up::before {
    border-bottom-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .rd-balloon--up::after {
    border-bottom-color: var(--dark-card-stock);
  }
}

:root[data-theme="dark"] .rd-balloon--up::before {
  border-bottom-color: var(--dark-rim);
}

:root[data-theme="dark"] .rd-balloon--up::after {
  border-bottom-color: var(--dark-card-stock);
}

/* ---------- Cleanup: Start over, and the called-off notice ---------- */

.ra-deal-error {
  text-align: center;
}

/* "Tonight's rental agreement was called off" — the .mr-toast look; on
   phone it sits above the round drawer trigger, like the invite card. */
@media (max-width: 699px) {
  .ra-toast {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 88px);
  }
}

/* ---------- Stage R-4: the Rewind panel, rewinding ----------
   js/year-header.js's playRewindPanel adds .is-rewinding for the ~1.1s
   before the Rewind opens. The key sits pressed in, the LED blinks once
   a second (the kit's "under 1 blink per second" limit is met at the
   edge: one full on/off cycle per second), and the reels turn
   counter-clockwise. A reel is a plain ring, so while it spins its top
   edge takes the hub's colour — otherwise a turning circle looks still. */
.year-screen .rental-rewind-button.is-rewinding {
  cursor: default;
}

.rental-rewind-button.is-rewinding .rr-key {
  transform: translateY(2px);
  box-shadow: inset 0 3px 0 rgba(0, 0, 0, 0.35);
}

.rental-rewind-button.is-rewinding .rr-led {
  animation: rr-led-blink 1s steps(1, end) infinite;
}

.rental-rewind-button.is-rewinding .rr-reel {
  border-top-color: var(--vcr-key-text);
  animation: rr-reel-back 0.7s linear infinite;
}

@keyframes rr-led-blink {
  0% { opacity: 1; }
  50% { opacity: 0.15; }
}

@keyframes rr-reel-back {
  to { transform: rotate(-360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .rental-rewind-button.is-rewinding .rr-led,
  .rental-rewind-button.is-rewinding .rr-reel {
    animation: none;
  }
}

/* ---------- The avatar (js/avatar.js) — Junior Members Stage 4a ----------
   Moved here from css/photo-booth.css so it loads on every screen.
   Every avatar gets a thin outline so no circle vanishes into its
   background: ink by day, the rim colour at Night. */

.avatar {
  display: inline-block;
  flex-shrink: 0;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 0 0 2px var(--ink);
}

.avatar svg {
  display: block;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .avatar {
    box-shadow: 0 0 0 2px var(--dark-rim);
  }
}

:root[data-theme="dark"] .avatar {
  box-shadow: 0 0 0 2px var(--dark-rim);
}

/* ===== Junior Members Stage 6b — Neither, and "Who else watched?" =====
   The return slip's fourth tile (2x2 like RankNeither.dc.html), the No rank
   stamp, and the keys under the send panel. The panel itself is sf-* in
   css/junior-members.css. */
.slip-tiles-four {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.neither-part:not([hidden]) {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.neither-norank {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.neither-stamp {
  flex: none;
  margin-top: 2px;
  padding: 2px 7px;
  border: 2px solid var(--stamp-red);
  border-radius: 2px;
  color: var(--stamp-red);
  font-family: "Archivo Black", "Archivo", sans-serif;
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transform: rotate(-4deg);
}

.neither-line {
  font-size: 0.875rem;
  line-height: 1.4;
}

.neither-help {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.8125rem;
  line-height: 1.4;
}

.neither-skip,
.who-else-continue {
  align-self: center;
  min-height: 44px;
}

.neither-close {
  min-height: 52px;
}

.who-else-screen {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 560px;
}

.who-else-ranked {
  margin: 0;
  font-size: 0.9375rem;
}

/* Keys and slip parts set their own display, which would beat the plain
   hidden attribute Neither toggles. */
.return-screen [hidden] {
  display: none !important;
}

/* ================================================================
   Your Card — narrow-window overflow fix. The two-column card
   (@container cardscreen) only fits its desktop-size text once the card
   has its full laptop room; between about 790px and 1000px the name, the
   bottom row and the punch card's back ran off the card. The members'
   screen now joins "cardscreen" only from 1100px, the same gate the
   junior Card uses (css/junior.css); below it the card keeps its phone
   layout, which fits at every width. 1100px and up is unchanged.
   ================================================================ */

.card-screen:not(.jr-card-screen) {
  container-name: none;
}

@media (min-width: 1100px) {
  .card-screen:not(.jr-card-screen) {
    container-name: cardscreen;
  }
}


/* ---------- A member's face (js/members.js) — Stage F-5d ----------
   A grown-up member with no mascot shows the avatar they made in the
   Photo Booth. It fills its slot edge to edge, the way the Fox and Owl
   images do; a slot sized by its own class (the Rewind's badges) wins
   over the 100% here because its stylesheet loads later. */

.member-face {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  overflow: hidden;
}

.member-face .avatar {
  display: block;
}

/* ---------- Your Card: Retake photo (Stage F-5e) ----------
   Members with no mascot get the junior Card's "Retake photo" key
   (css/junior.css's .jr-card-retake) under their card, above the
   Employees Only plaque. On phone it takes its own grid row. */

.cc-retake {
  grid-area: retake;
  width: 100%;
  max-width: 350px;
  min-height: 52px;
  margin-top: 20px;
  padding: 0 24px;
}

@container cardscreen (max-width: 619.98px) {
  .cc-layout {
    grid-template-areas:
      "card"
      "retake"
      "receipt"
      "signout"
      "plaque";
  }
}

@container cardscreen (min-width: 620px) {
  .cc-retake {
    width: auto;
    max-width: none;
    padding: 0 36px;
    margin-top: 64px;
  }

  .cc-retake + .door-sign {
    margin-top: 24px;
  }
}

/* ---------- Store tickets and the franchise line (Stage F-5f follow-up) ----------
   A 4-character ticket ("Kino", "AB&C") drops its letters a step so they
   sit inside the notches; 1 to 3 characters keep the ticket's own size.
   Every store but J&A Video carries "A J&A Entertainment franchise" in
   the membership card's bottom margin — the front's 18px padding — so
   nothing else on the card moves. */

.ticket-text--long {
  font-size: 0.8em;
  letter-spacing: -0.01em;
}

.cc-card-franchise {
  position: absolute;
  left: 18px;
  right: 18px;
  bottom: 4px;
  color: rgba(255, 255, 255, 0.72);
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.14em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

/* The bigger card's front has 30px of padding: the line sits a little
   higher in it, and in from the same edges. */
@container cardscreen (min-width: 620px) {
  .cc-card-franchise {
    left: 30px;
    right: 30px;
    bottom: 10px;
  }
}

/* ================================================================
   Stage F-7a: passwords only — the sign-in card, Choose a new password,
   and Your Card's Change password / Change email. From the Franchising
   canvas's "F-7 — Passwords & emails" row.

   The sign-in card is the plastic member card (--r-card), navy with
   white type, fixed in both store lights like Your Card's own card
   (--card-navy); at Night it only gains the dark-object rim. Its keys
   and links sit on navy, so their focus ring is always yellow. The
   older .membership-card styles near the top of this file are left
   for the junior card sign-in (js/junior.js), which is unchanged.
   ================================================================ */

.pw-screen {
  flex-direction: column;
  gap: 22px;
  padding: 40px 16px 32px;
}

.pw-screen > .pw-card,
.pw-screen > .pw-junior,
.pw-screen > .pw-note {
  width: 100%;
  max-width: 380px;
}

.pw-card {
  display: flex;
  flex-direction: column;
  border: 2px solid var(--ink);
  border-radius: var(--r-card);
  background: var(--card-navy);
  color: var(--paper-white);
  box-shadow: var(--shadow-ink);
  overflow: hidden;
}

.pw-card-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 4px 12px;
  padding: 18px 20px 12px;
}

.pw-card-title {
  margin: 0;
  font-family: "Archivo Black", "Archivo", system-ui, sans-serif;
  font-size: 18px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.pw-card-chain {
  flex-shrink: 0;
  color: var(--yellow);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.pw-card-body {
  padding: 6px 20px 20px;
}

.pw-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.pw-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: var(--card-navy-muted);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.pw-field input {
  width: 100%;
  min-height: 46px;
  box-sizing: border-box;
  padding: 0 12px;
  border: 2px solid var(--ink);
  border-radius: var(--r-paper);
  background: var(--paper-white);
  color: var(--ink);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 16px;
  letter-spacing: 0;
  text-transform: none;
}

.pw-card button:focus-visible,
.pw-card input:focus-visible {
  outline: 3px solid var(--yellow);
}

.pw-text {
  margin: 0;
  font-size: 15px;
  line-height: 1.45;
}

.pw-text--muted {
  color: var(--card-navy-muted);
  font-size: 13px;
  line-height: 1.4;
}

.pw-status {
  margin: 0;
  color: var(--card-navy-muted);
  font-size: 14px;
  line-height: 1.4;
}

.pw-status:empty {
  display: none;
}

/* Yellow on navy, never on a light background. */
.pw-status--error {
  color: var(--yellow);
  font-weight: 700;
}

.pw-commit {
  width: 100%;
  font-size: 15px;
}

.pw-link {
  align-self: center;
  min-height: 44px;
  padding: 0 8px;
  border: none;
  background: none;
  color: var(--yellow);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 14px;
  font-weight: 800;
  text-decoration: underline;
  text-underline-offset: 4px;
  cursor: pointer;
}

/* Link sent / All set: the Courier receipt slip on the card. */
.pw-slip {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px;
  border-radius: var(--r-paper);
  background: var(--receipt-bg);
  color: var(--receipt-ink);
  font-family: "Courier New", Courier, monospace;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.45;
  text-align: center;
  overflow-wrap: anywhere;
}

.pw-slip-rule {
  border-top: 2px dashed var(--receipt-ink);
}

.pw-junior {
  min-height: 48px;
  font-size: 14px;
}

.pw-note {
  margin: 0;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.4;
  text-align: center;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pw-card {
    border-color: var(--dark-rim);
  }

  :root:not([data-theme="light"]) .pw-slip {
    background: var(--dark-receipt-bg);
  }
}

:root[data-theme="dark"] .pw-card {
  border-color: var(--dark-rim);
}

:root[data-theme="dark"] .pw-slip {
  background: var(--dark-receipt-bg);
}

/* Your Card: Change password / Change email, under the receipt's
   Account line. The receipt leans 1deg; this block leans back so its
   keys and fields sit straight. Everything here is printed on the
   receipt, so it uses the receipt's own fixed ink and --card-navy for
   links, never the theme's --link (yellow at Night). */
.cc-account {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0 0 10px;
  transform: rotate(-1deg);
}

.cc-account-links {
  display: flex;
  flex-wrap: wrap;
  column-gap: 14px;
}

.cc-account-links[hidden] {
  display: none;
}

.cc-account-link,
.cc-account-cancel {
  padding: 0;
  color: var(--card-navy);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 0.8rem;
}

.cc-account-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 6px 0 4px;
}

.cc-account-field {
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: var(--receipt-ink);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.cc-account-field input {
  width: 100%;
  min-height: 44px;
  box-sizing: border-box;
  padding: 6px 2px;
  border: none;
  border-bottom: 2px solid var(--receipt-ink);
  border-radius: 0;
  background: transparent;
  color: var(--receipt-ink);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 16px;
  letter-spacing: 0;
  text-transform: none;
}

.cc-account input:focus-visible,
.cc-account button:focus-visible {
  outline: 3px solid var(--card-navy);
  outline-offset: 2px;
}

.cc-account-hint,
.cc-account-status {
  margin: 0;
  color: var(--receipt-ink);
  font-size: 0.78rem;
  line-height: 1.4;
}

.cc-account-status:empty {
  display: none;
}

.cc-account-status--error {
  font-weight: 700;
}

.cc-account-buttons {
  display: flex;
  align-items: center;
  gap: 14px;
}

.cc-account-save {
  padding: 0 24px;
  font-size: 0.9rem;
}
