/* /stories as one printed object: a riso-printed sheet in two inks, Fluorescent Pink and a deep Medium Blue, on grained
   paper, carrying the header, the controls, the Calendar's almanac and the footnotes; and, set into it, the photos' own
   surfaces in the language of the darkroom: the Player as a length of film enlarged, the Contact sheet as strips on a
   light table. Type is Oswald for words and a monospace for anything stamped, counted or edge-printed. */
:root {
  --paper: #f2ede2;
  --ink: #284690;
  --pink: #ff48b0;
  --base: #131210;
  --edge: #c9b98f;
  --grease: #cf2a1e;
  --stamp: #ff9a1f;
  --white: #fff;
  --black: #000;
  --yellow: #fe0;
  --mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  /* How the inks overprint: riso inks are translucent, so on light paper they multiply. */
  --blend: multiply;
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .45 0 0 0 0 .42 0 0 0 0 .36 0 0 0 -1.1 .62'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  --grain-opacity: 0.5;
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23284690' stroke-width='1.5'/%3E%3C/svg%3E");
  /* The light table: lit from below the middle, and what's printed on it. */
  --table-hot: #fcfcf9;
  --table-mid: #efeee9;
  --table-edge: #dddcd5;
  --table-type: #57554f;
  --table-type-hover: var(--black);
  --table-rim: rgb(40 70 144 / 0.18);
  /* Masking tape, and the stamp-pad ink on it. */
  --tape: rgb(236 226 196 / 0.92);
  --tape-ink: #2b2924;
  --tape-ink-soft: #6c685d;
  --shadow: rgb(19 18 16 / 0.45);
  /* A pressed control's fill, and the type on it. */
  --pressed-fill: var(--pink);
  --pressed-ink: var(--ink);
  /* The moon on the 1st: on light paper the ink prints its dark part over a hairline disc. */
  --moon-disc: none;
  --moon-dark: currentColor;
  --moon-blend: var(--blend);
  /* The date stamp's glow. */
  --stamp-glow: rgb(255 110 0 / 0.9);
  --stamp-halo: rgb(255 80 0 / 0.55);
}
/* On a dark device, the same sheet printed on dark stock: deep navy paper, the blue lifted out of it as an opaque pale
   blue ink, the pink kept. Opaque inks on dark paper lighten what they print over, so they overprint with screen, and the grain
   shows as light flecks. The light table is turned down to a low glow, still the brightest thing on the page. */
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #131a2b;
    --ink: #c3d3f4;
    --base: #07090f;
    --grease: #ff5a3c;
    --blend: screen;
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .8 0 0 0 0 .86 0 0 0 0 1 0 0 0 -1.1 .62'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
    --grain-opacity: 0.18;
    --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23c3d3f4' stroke-width='1.5'/%3E%3C/svg%3E");
    --table-hot: #5d6476;
    --table-mid: #454c5d;
    --table-edge: #2f3544;
    --table-type: #dde5f6;
    --table-type-hover: var(--white);
    --table-rim: rgb(195 211 244 / 0.16);
    --tape: rgb(206 196 168 / 0.86);
    --shadow: rgb(0 0 0 / 0.7);
    --pressed-ink: var(--paper);
    /* A pale ink prints the moon's lit part instead: the disc inked in, its dark part left as paper on top. */
    --moon-disc: currentColor;
    --moon-dark: var(--paper);
    --moon-blend: normal;
    color-scheme: dark;
  }
}
/* The Dark Room: the page under a darkroom safelight, on a light device or a dark one. One light, an amber-red, prints
   everything: the type and rules in it, the halftone in a deeper red, and the grease pencil, the date stamps and the
   masking tape redrawn in it. No grain; the light table is off, its strips lit by the safelight alone. The photos keep
   their own colours. */
:root[data-room='dark'] {
  --paper: #0a0504;
  --ink: #ff4a1c;
  --pink: #8c1d0c;
  --base: #000;
  --edge: #b8341a;
  --stamp: #ff4a1c;
  --stamp-glow: rgb(255 74 28 / 0.7);
  --stamp-halo: rgb(255 40 0 / 0.35);
  --grease: #ff4a1c;
  --yellow: #ff4a1c;
  --white: #ff4a1c;
  --blend: screen;
  --grain: none;
  --grain-opacity: 0;
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23ff4a1c' stroke-width='1.5'/%3E%3C/svg%3E");
  --table-hot: #120807;
  --table-mid: #0f0706;
  --table-edge: #0c0605;
  --table-type: #ff4a1c;
  --table-type-hover: #ff7a52;
  --table-rim: rgb(255 74 28 / 0.28);
  --tape: rgb(120 30 14 / 0.9);
  --tape-ink: #ff6a40;
  --tape-ink-soft: #d2421f;
  --shadow: rgb(0 0 0 / 0.8);
  /* The deep red is too dark to read type on, so a pressed control is filled with the safelight itself. */
  --pressed-fill: var(--ink);
  --pressed-ink: var(--paper);
  --moon-disc: currentColor;
  --moon-dark: var(--paper);
  --moon-blend: normal;
  color-scheme: dark;
}
/* Switching the Dark Room on or off fades the whole page across, as a room's lights go. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.5s;
}
* {
  box-sizing: border-box;
}
html {
  background: var(--paper);
}
body {
  position: relative;
  min-height: 100vh;
  margin: 0;
  color: var(--ink);
  font: 18px/1.4 'Oswald', sans-serif;
  letter-spacing: 0.5px;
}
/* Paper grain behind everything printed; the photo surfaces cover it. */
body::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: var(--grain-opacity);
  background: var(--grain);
}
button,
select {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
[hidden] {
  display: none !important;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
a,
a:visited {
  color: var(--ink);
  text-decoration: underline 2px var(--pink);
  text-underline-offset: 0.2em;
  text-decoration-skip-ink: none;
}
a:hover {
  text-decoration-thickness: 0.5em;
  text-underline-offset: -0.25em;
}
@media (prefers-reduced-motion: no-preference) {
  a {
    transition: text-decoration-thickness 0.15s, text-underline-offset 0.15s;
  }
}

/* ---------- masthead: the title printed in blue over a pink pass a hair off register ---------- */
.mast {
  max-width: 60rem;
  margin: 0 auto 1.1rem;
  padding: 1.6rem 16px 0;
  text-align: center;
}
h1 {
  margin: 0;
  font-size: clamp(1.6rem, 7vw, 2.6rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-shadow: 0.035em 0.03em 0 color-mix(in srgb, var(--pink) 75%, transparent);
}
h1 a,
h1 a:visited {
  text-decoration: none;
}
h1 a:hover {
  text-decoration: underline 0.08em var(--ink);
  text-underline-offset: 0.12em;
}
.bolt {
  width: 0.42em;
  height: 0.68em;
  fill: var(--pink);
  mix-blend-mode: var(--blend);
  vertical-align: -0.02em;
}
.mast p {
  margin: 0;
}
.subtitle {
  margin-top: 0.35rem !important;
  font-size: 1.05rem;
  letter-spacing: 0.03em;
}
/* The imprint line between a blue rule and a pink one. */
.imprint {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.2rem 1.5rem;
  margin-top: 0.9rem !important;
  padding: 0.45rem 0 0.4rem;
  font: 0.68rem/1.4 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background:
    linear-gradient(var(--ink), var(--ink)) 0 0 / 100% 1px no-repeat,
    linear-gradient(var(--ink), var(--ink)) 0 100% / 100% 1px no-repeat,
    linear-gradient(var(--pink), var(--pink)) 1px calc(100% - 3px) / 100% 2px no-repeat;
}
.imprint a {
  text-decoration-thickness: 1.5px;
}
.imprint .album {
  margin-left: auto;
}
/* The Dark Room switch: a stamped toggle with a safelight lamp that lights when it's on. */
.room {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.05rem 0.5rem;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: 1px solid currentColor;
  border-radius: 0;
  cursor: pointer;
}
.room:hover {
  background: radial-gradient(circle, color-mix(in srgb, var(--pink) 55%, transparent) 0.9px, transparent 1.4px) 0 0 / 4px 4px;
}
.room i {
  width: 0.75em;
  height: 0.75em;
  border: 1px solid currentColor;
  border-radius: 50%;
}
.room[aria-pressed='true'] i {
  background: #ff4a1c;
  border-color: #ff4a1c;
  box-shadow: 0 0 4px 1px rgb(255 74 28 / 0.8), 0 0 10px 2px rgb(255 40 0 / 0.4);
}
@media (max-width: 600px) {
  .imprint {
    justify-content: center;
  }
}

/* ---------- controls: stamped in ink; the one pressed is inked in pink and outlined ---------- */
main {
  max-width: 60rem;
  margin: 0 auto 3rem;
  padding: 0 16px;
}
.controls {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-end;
  gap: 0.6rem 1.4rem;
  margin: 0 0 1.4rem;
}
.field {
  display: grid;
  gap: 0.2rem;
}
.cap {
  font: 0.58rem/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.seg {
  display: inline-flex;
}
.seg button,
.chip,
.controls select {
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.2;
  background: none;
  border: 1.5px solid var(--ink);
  border-radius: 0;
  padding: 0.38rem 0.8rem 0.34rem;
  cursor: pointer;
}
.seg button + button {
  border-left-width: 0;
}
.seg button:hover,
.chip:hover,
.controls select:hover {
  background: radial-gradient(circle, color-mix(in srgb, var(--pink) 55%, transparent) 0.9px, transparent 1.4px) 0 0 / 4px 4px;
}
/* Pressed: a pink fill, the ink outline doubled inside it. */
.seg button[aria-pressed='true'] {
  background: var(--pressed-fill);
  color: var(--pressed-ink);
  box-shadow: inset 0 0 0 1.5px var(--ink);
}
.controls select {
  appearance: none;
  min-width: 8.5rem;
  padding-right: 1.8rem;
  text-transform: none;
  letter-spacing: 0.04em;
  background: var(--chevron) right 0.6rem center / 0.6rem no-repeat;
}
.controls select:hover {
  background:
    var(--chevron) right 0.6rem center / 0.6rem no-repeat,
    radial-gradient(circle, color-mix(in srgb, var(--pink) 55%, transparent) 0.9px, transparent 1.4px) 0 0 / 4px 4px;
}
.controls select option {
  color: var(--ink);
  background: var(--paper);
}
/* On a desktop the filters sit inline in the bar; the Filters button and its Done are for phones. */
.filter-sheet {
  display: contents;
}
.filters-toggle,
.filters-done {
  display: none;
}

/* ---------- phones: the photo first ----------
   A one-line masthead, then one stamped bar: the view switch and a Filters button that opens the sort and filters
   as a small printed sheet under it. */
@media (max-width: 600px) {
  .mast {
    margin-bottom: 0.6rem;
    padding-top: 0.7rem;
  }
  h1 {
    font-size: clamp(1rem, 5.2vw, 1.3rem);
    white-space: nowrap;
  }
  .subtitle,
  .imprint .updated {
    display: none;
  }
  .imprint {
    align-items: center;
    margin-top: 0.4rem !important;
    padding: 0.3rem 0 0.5rem;
    font-size: 0.58rem;
  }
  .controls {
    position: relative;
    flex-wrap: nowrap;
    justify-content: space-between;
    align-items: stretch;
    gap: 0.6rem;
    margin-bottom: 0.6rem;
  }
  .controls .cap {
    display: none;
  }
  .controls > .field {
    flex: 1;
  }
  .seg button {
    flex: 1;
  }
  .filters-toggle {
    display: block;
    flex: none;
    font-size: 0.78rem;
    line-height: 1.2;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    background: none;
    border: 1.5px solid var(--ink);
    padding: 0.38rem 0.7rem;
    cursor: pointer;
  }
  .filters-toggle[aria-expanded='true'] {
    background: var(--pressed-fill);
    color: var(--pressed-ink);
    box-shadow: inset 0 0 0 1.5px var(--ink);
  }
  .filter-sheet {
    display: none;
  }
  /* The sheet: a slip of the same paper, laid over the page under the bar, with a pink pass along its edge. */
  .filter-sheet.open {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 10;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.8rem;
    padding: 0.9rem 0.9rem 0.8rem;
    background: var(--paper);
    border: 1.5px solid var(--ink);
    box-shadow: 3px 3px 0 var(--pink), 0 14px 30px -12px var(--shadow);
  }
  .filter-sheet .cap {
    display: block;
  }
  .filter-sheet .field:first-child {
    grid-column: 1 / -1;
  }
  .controls select {
    width: 100%;
    min-width: 0;
  }
  .filters-done {
    display: block;
    grid-column: 2;
    justify-self: end;
    font: 0.72rem/1.2 var(--mono);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    background: none;
    border: 0;
    padding: 0.3rem 0;
    cursor: pointer;
    text-decoration: underline 2px var(--pink);
    text-underline-offset: 0.25em;
  }
  .player-view {
    gap: 0.6rem;
  }
  .rings {
    gap: 0.55rem;
    padding: 0.2rem 0.2rem 0.3rem;
  }
  .ring {
    gap: 0.2rem;
    font-size: 0.52rem;
  }
  .ring span {
    width: 2.6rem;
    height: 2.6rem;
    padding: 2px;
    border-width: 2px;
  }
  .ring.seen span {
    padding: 3px;
  }
  .ring[aria-current='true'] span {
    border-width: 2px;
  }
  .gate-edge {
    height: 22px;
  }
}
.status {
  text-align: center;
  font: 0.75rem/1.5 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.keys {
  max-width: 32rem;
  margin: 0;
  text-align: center;
  font: 0.66rem/1.6 var(--mono);
  letter-spacing: 0.04em;
}

/* ---------- Player: a length of the film enlarged, its controls above it ---------- */
.player-view {
  display: grid;
  justify-items: center;
  gap: 0.9rem;
}
/* Month rings: each month's first story in a circle, ringed in pink until it's been watched, then in a hairline of
   ink; the month playing gets a heavy ink ring with the pink pass off register behind it. */
.rings {
  position: relative;
  display: flex;
  gap: 0.9rem;
  overflow-x: auto;
  max-width: 100%;
  padding: 0.4rem 0.3rem 0.5rem;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  scrollbar-color: var(--ink) transparent;
}
.ring {
  flex: none;
  display: grid;
  justify-items: center;
  gap: 0.3rem;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font: 0.6rem/1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  scroll-snap-align: center;
}
.ring span {
  display: block;
  width: 3.4rem;
  height: 3.4rem;
  border-radius: 50%;
  padding: 3px;
  border: 2.5px solid var(--pink);
}
.ring img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: var(--base);
}
.ring.seen span {
  border: 1px solid var(--ink);
  padding: 4.5px;
}
.ring[aria-current='true'] span {
  border: 2.5px solid var(--ink);
  box-shadow: 2px 1.5px 0 0 var(--pink);
}
.ring[aria-current='true'] {
  font-weight: 700;
}
.ring:focus-visible {
  outline-offset: 3px;
}
/* The deck: the controls printed on the paper, and under them the Gate, so nothing sits on a photo. --frame is the
   story playing's width: as tall as the screen leaves room for, up to 24rem. */
.deck {
  width: 100%;
  display: grid;
  justify-items: center;
}
.player {
  --frame: min(24rem, (100dvh - 7.5rem) * 9 / 16);
  width: min(100%, var(--frame) * 2.2);
  display: grid;
  justify-items: center;
  gap: 0.7rem;
  color: var(--ink);
  user-select: none;
}
.player:focus-visible {
  outline: 2px solid var(--yellow);
  outline-offset: 4px;
}
.player :focus-visible {
  outline: 2px solid var(--yellow);
}
/* In full screen, the deck alone on black, its controls printed light. */
.player:fullscreen {
  --frame: calc((100dvh - 8rem) * 9 / 16);
  width: 100%;
  align-content: center;
  padding: 1rem;
  background: var(--black);
  color: var(--white);
}
.p-top {
  width: min(var(--frame), 100%);
}
/* A taller hit area than the 2px bars, so they're easy to click or drag along. */
.p-bars {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 19px;
  margin: -6px 0 -8px;
  cursor: pointer;
  touch-action: none;
}
.p-bars i {
  flex: 1;
  height: 2px;
  transition: height 0.15s;
  background: color-mix(in srgb, currentColor 25%, transparent);
  position: relative;
  overflow: hidden;
}
.p-bars:hover i {
  height: 4px;
}
.p-bars i b {
  position: absolute;
  inset: 0;
  background: currentColor;
  transform-origin: left;
  transform: scaleX(var(--f, 0));
}
.p-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.5rem;
}
.p-head .p-month,
.p-head .p-month:visited {
  color: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: underline 1.5px var(--pink);
  text-underline-offset: 0.25em;
}
.p-head .p-month:hover {
  text-decoration-thickness: 3px;
}
/* The position as a frame counter. */
.p-head .p-pos {
  font: 0.66rem/1 var(--mono);
  letter-spacing: 0.12em;
}
.p-head .spacer {
  flex: 1;
}
.p-head button {
  color: inherit;
  border-color: currentColor;
}
.p-head .p-pause {
  width: 2rem;
  height: 2rem;
  padding: 0;
  background: none;
  border: 1.5px solid currentColor;
  cursor: pointer;
  font: 0.7rem/1 var(--mono);
}
.p-head .p-pause:hover {
  background: radial-gradient(circle, color-mix(in srgb, var(--pink) 55%, transparent) 0.9px, transparent 1.4px) 0 0 / 4px 4px;
}
/* The Gate: a window onto the roll, the story playing whole and up to six tenths of a frame either side, or as much
   as leaves each neighbour 1.5rem on a phone. */
.gate {
  width: min(100%, var(--frame) * 2.2);
  container-type: inline-size;
  color: var(--edge);
}
.roll {
  --fw: min(var(--frame), 100cqw - 3rem);
  /* Wider than a phone, the film's ends fade into the paper as a narrow halftone, the dots shrinking to nothing at the
     Gate's sides. */
  --fade: 48px;
  position: relative;
  overflow: hidden;
  touch-action: pan-y;
  mask:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 12'%3E%3Ccircle cx='3' cy='3' r='0.48'/%3E%3Ccircle cx='6' cy='9' r='0.83'/%3E%3Ccircle cx='9' cy='3' r='1.15'/%3E%3Ccircle cx='12' cy='9' r='1.45'/%3E%3Ccircle cx='15' cy='3' r='1.74'/%3E%3Ccircle cx='18' cy='9' r='2.01'/%3E%3Ccircle cx='21' cy='3' r='2.27'/%3E%3Ccircle cx='24' cy='9' r='2.53'/%3E%3Ccircle cx='27' cy='3' r='2.78'/%3E%3Ccircle cx='30' cy='9' r='3.02'/%3E%3Ccircle cx='33' cy='3' r='3.26'/%3E%3Ccircle cx='36' cy='9' r='3.5'/%3E%3Ccircle cx='39' cy='3' r='3.73'/%3E%3Ccircle cx='42' cy='9' r='3.95'/%3E%3Ccircle cx='45' cy='3' r='4.18'/%3E%3Ccircle cx='48' cy='9' r='4.4'/%3E%3C/svg%3E") left top / var(--fade) 12px repeat-y,
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 12'%3E%3Ccircle cx='45' cy='3' r='0.48'/%3E%3Ccircle cx='42' cy='9' r='0.83'/%3E%3Ccircle cx='39' cy='3' r='1.15'/%3E%3Ccircle cx='36' cy='9' r='1.45'/%3E%3Ccircle cx='33' cy='3' r='1.74'/%3E%3Ccircle cx='30' cy='9' r='2.01'/%3E%3Ccircle cx='27' cy='3' r='2.27'/%3E%3Ccircle cx='24' cy='9' r='2.53'/%3E%3Ccircle cx='21' cy='3' r='2.78'/%3E%3Ccircle cx='18' cy='9' r='3.02'/%3E%3Ccircle cx='15' cy='3' r='3.26'/%3E%3Ccircle cx='12' cy='9' r='3.5'/%3E%3Ccircle cx='9' cy='3' r='3.73'/%3E%3Ccircle cx='6' cy='9' r='3.95'/%3E%3Ccircle cx='3' cy='3' r='4.18'/%3E%3Ccircle cx='0' cy='9' r='4.4'/%3E%3C/svg%3E") right top / var(--fade) 12px repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--fade) + 2px) 100% no-repeat;
  cursor: pointer;
}
@media (max-width: 600px) {
  /* A phone has no room for the fade: the Gate bleeds through main's gutter and the film runs square off the screen's
     sides. */
  .gate {
    width: calc(100% + 32px);
    margin-inline: -16px;
  }
  .roll {
    mask: none;
  }
}
/* The roll's five frames, the story playing in the middle; --dx carries it along under a drag or as it winds on. */
.track {
  display: flex;
  width: max-content;
  margin-left: calc(50% - var(--fw) * 2.5);
  transform: translateX(var(--dx, 0px));
}
.track.gliding {
  transition: transform 0.25s cubic-bezier(0.25, 0.8, 0.35, 1);
}
.p-frame {
  flex: none;
  width: var(--fw);
}
.gate-edge {
  display: flex;
  justify-content: space-between;
  height: 26px;
  margin: 0;
  padding: 0 0.8rem;
  font: 0.58rem/1 var(--mono);
  letter-spacing: 0.16em;
  white-space: nowrap;
  overflow: hidden;
  background: var(--base);
  /* Sprocket holes, eight to a frame so they run on unbroken from frame to frame, cut through to the paper. */
  mask:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 7'%3E%3Crect x='2.5' width='5' height='7' rx='1.2'/%3E%3C/svg%3E") 0 4px / 12.5% 8px repeat-x,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
}
.gate-edge.top {
  align-items: flex-end;
  padding-bottom: 3px;
}
.gate-edge.bottom {
  align-items: flex-start;
  padding-top: 3px;
  mask-position: 0 calc(100% - 4px), 0 0;
}
/* The story's date stamp in the edge printing, in the data back's orange. */
.gate-taken {
  color: var(--stamp);
}
/* The film's frame line either side of the photo. */
.shot {
  aspect-ratio: 9 / 16;
  background: var(--black);
  border-inline: 2px solid var(--base);
}
.shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* The stories either side, dimmed so the eye stays on the one playing. */
.p-frame:not(.current) img {
  filter: brightness(0.5);
}
/* Leader: film past either end of the roll, with nothing on it. */
.p-frame.leader .shot {
  background: var(--base);
}
.empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 1rem;
  text-align: center;
  color: var(--edge);
  font: 0.75rem/1.5 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ---------- Calendar: a riso-printed almanac, a year per row and a month per cell ----------
   Two spot inks on paper. Fluorescent Pink prints the shading, as a halftone whose dots grow with the month's stories;
   a deep Medium Blue prints the type, the rules and the moons. The pink plate sits a hair off register, and both overprint
   (multiply) as riso inks do. */
.calendar-view {
  --pitch: 5px;
  position: relative;
  isolation: isolate;
  color: var(--ink);
}
.cal-mast {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin: 0 0 0.6rem;
  padding-bottom: 0.35rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  /* A blue rule with the pink one printed under it, a little out of register. */
  background:
    linear-gradient(var(--ink), var(--ink)) 0 100% / 100% 1px no-repeat,
    linear-gradient(var(--pink), var(--pink)) 1px calc(100% - 3px) / 100% 2px no-repeat;
}
.cal-mast b {
  font-size: 1rem;
  letter-spacing: 0.1em;
}
.cal-table {
  border-collapse: separate;
  border-spacing: 3px;
  width: 100%;
  table-layout: fixed;
}
.cal-table th {
  font-weight: 400;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  line-height: 1.15;
  vertical-align: bottom;
  padding-bottom: 0.2rem;
}
.cal-table thead small {
  display: block;
  font-size: 0.62rem;
  text-transform: none;
  letter-spacing: 0.03em;
  opacity: 0.8;
}
.cal-table abbr {
  text-decoration: none;
}
.cal-table th[scope='row'] {
  text-align: left;
  font-size: 1rem;
  vertical-align: middle;
  padding: 0;
}
.cal-table .corner {
  width: 3.8rem;
}
.cal-table th[scope='row'] small {
  display: block;
  font-size: 0.65rem;
}
/* The zodiac year, as an almanac's aside. */
.cal-table th[scope='row'] em {
  display: block;
  font-style: normal;
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  opacity: 0.75;
}
.cal-table td {
  padding: 0;
  height: 3.3rem;
}
.cell,
.cell-empty {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
}
.cell {
  border: 0;
  padding: 0;
  cursor: pointer;
  background: none;
  color: var(--ink);
  text-align: left;
}
/* The pink plate: a 45° halftone, two offset dot screens, each dot's radius from the month's shade --v (0.12–1), so
   its area grows with it; at 1 the dots run together. Nudged off register. */
.cell::before,
.cal-key i {
  --r: calc(var(--pitch) * 0.39 * sqrt(var(--v)));
  background:
    radial-gradient(circle, var(--pink) var(--r), transparent calc(var(--r) + 0.5px)) 0 0 / var(--pitch) var(--pitch),
    radial-gradient(circle, var(--pink) var(--r), transparent calc(var(--r) + 0.5px)) calc(var(--pitch) / 2) calc(var(--pitch) / 2) / var(--pitch) var(--pitch);
  mix-blend-mode: var(--blend);
}
.cell::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  translate: 1px -1px;
}
.cell:hover::before {
  --r: calc(var(--pitch) * 0.6);
}
.cell .n {
  position: absolute;
  left: 0.3rem;
  bottom: 0.1rem;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.2;
  mix-blend-mode: var(--blend);
}
.cell-empty {
  border: 1px dotted color-mix(in srgb, var(--ink) 45%, transparent);
  color: color-mix(in srgb, var(--ink) 72%, var(--paper));
}
/* The moon on the 1st: its dark part in ink over a hairline disc. */
.moon {
  position: absolute;
  top: 0.3rem;
  left: 0.3rem;
  width: 0.7rem;
  height: 0.7rem;
  overflow: visible;
  mix-blend-mode: var(--moon-blend);
}
.moon circle {
  fill: var(--moon-disc);
  stroke: currentColor;
  stroke-width: 0.8;
}
.moon path {
  fill: var(--moon-dark);
}
/* The days of the month's full moons, each after an open ring; a blue moon's ring is inked in. */
.fm {
  position: absolute;
  top: 0.22rem;
  right: 0.3rem;
  font-size: 0.6rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  line-height: 1;
  mix-blend-mode: var(--blend);
}
.fm:not(:empty)::before {
  content: '';
  display: inline-block;
  width: 0.42em;
  height: 0.42em;
  margin-right: 0.22em;
  border: 1px solid currentColor;
  border-radius: 50%;
  vertical-align: 0.1em;
}
.fm.blue::before {
  background: currentColor;
}
.cal-foot {
  display: grid;
  gap: 0.35rem;
  margin-top: 0.6rem;
  font-size: 0.7rem;
}
.cal-foot p {
  margin: 0;
}
.cal-key,
.cal-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 1rem;
}
.cal-key {
  gap: 0.4rem;
}
.cal-key i {
  display: inline-block;
  width: 1.4rem;
  height: 0.9rem;
}
.cal-legend span {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.cal-legend .moon,
.cal-legend .fm {
  position: static;
}
.cal-imprint {
  max-width: 44rem;
  font-size: 0.62rem;
  line-height: 1.5;
  opacity: 0.8;
}
@media (max-width: 600px) {
  .calendar-view {
    --pitch: 4px;
  }
  .cal-mast {
    font-size: 0.55rem;
    letter-spacing: 0.1em;
  }
  .cal-mast b {
    font-size: 0.8rem;
    white-space: nowrap;
  }
  .cal-table {
    border-spacing: 2px;
  }
  .cal-table .corner {
    width: 2.6rem;
  }
  .cal-table th[scope='row'] {
    font-size: 0.8rem;
  }
  /* The moon names stand on end to fit a phone's narrow columns, hanging from their month's letter. */
  .cal-table thead th {
    vertical-align: top;
  }
  .cal-table thead small {
    writing-mode: vertical-rl;
    text-orientation: sideways;
    margin: 0.2rem auto 0;
    font-size: 0.56rem;
    line-height: 1;
  }
  .cal-table td {
    height: 2.5rem;
  }
  .cell .n {
    left: 0.2rem;
    font-size: 0.68rem;
  }
  .moon {
    top: 0.2rem;
    left: 0.2rem;
    width: 0.5rem;
    height: 0.5rem;
  }
  .cell .fm,
  .cell-empty .fm {
    display: none;
  }
}

/* ---------- Contact sheet: one month as strips of 35mm film on a light table ----------
   Each row of frames is a strip: a dark rebate above and below, its sprocket holes cut out so the table's light shows
   through, the stock, roll and frame numbers printed along it, and each frame's negative number under the strip. */
.sheet-head {
  display: grid;
  justify-items: center;
  gap: 0.3rem;
  margin: 0 0 0.8rem;
}
.sheet-head a {
  justify-self: start;
  font: 0.7rem/1.4 var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}
.sheet-head h2 {
  margin: 0;
  font-size: 1.2rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-align: center;
}
.sheet-head button {
  background: none;
  border: 0;
  padding: 0 0.4rem;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
}
.sheet-head button:disabled {
  color: color-mix(in srgb, var(--ink) 30%, var(--paper));
  cursor: default;
}
.light-table {
  --rebate: 22px;
  /* Lit from below the middle, falling off toward the edges as a real table's does. */
  background: radial-gradient(120% 90% at 50% 45%, var(--table-hot) 0%, var(--table-mid) 55%, var(--table-edge) 100%);
  color: var(--table-type);
  padding: 1rem 1rem 1.2rem;
  border-radius: 2px;
  /* A lit panel on the paper: brighter than it, its edge catching a little shadow. */
  box-shadow: 0 0 0 1px var(--table-rim), 0 10px 24px -14px var(--shadow);
}
/* The darkroom label: masking tape with the roll's details stamped on it. */
.slate {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.2rem 1.1rem;
  margin: 0 0 1rem;
  padding: 0.35rem 0.9rem 0.4rem;
  background: var(--tape);
  color: var(--tape-ink);
  rotate: -0.6deg;
  box-shadow: 0 1px 1px rgb(0 0 0 / 0.08);
  /* Torn ends. */
  clip-path: polygon(0 4%, 2% 0, 98% 3%, 100% 0, 99% 38%, 100% 70%, 98.5% 100%, 1% 96%, 0 62%, 1.2% 30%);
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  line-height: 1.1;
  text-transform: uppercase;
}
.slate:empty {
  display: none;
}
.slate small {
  display: block;
  font: 0.55rem/1.4 ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: 0.12em;
  color: var(--tape-ink-soft);
}
/* 6.5rem columns: three on a phone, eight across the 60rem page. No gap between columns, so a row reads as one strip. */
.sheet {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
  gap: 1rem 0;
}
.thumb {
  position: relative;
  display: block;
  border: 0;
  padding: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  text-align: center;
}
.rebate {
  display: flex;
  justify-content: space-around;
  height: var(--rebate);
  padding: 0 0.3rem;
  background: var(--base);
  color: var(--edge);
  font: 0.5rem/1 ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: 0.14em;
  white-space: nowrap;
  overflow: hidden;
  /* Sprocket holes, eight to a frame so they line up from frame to frame, cut out of the rebate. */
  mask:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 7'%3E%3Crect x='2.5' width='5' height='7' rx='1.2'/%3E%3C/svg%3E") 0 3px / 12.5% 7px repeat-x,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
}
.rebate.top {
  align-items: flex-end;
  padding-bottom: 2px;
}
.rebate.bottom {
  align-items: flex-start;
  padding-top: 2px;
  mask-position: 0 calc(100% - 3px), 0 0;
}
/* The frame number under the frame, and its "A" half-number at the frame line. */
.rebate.bottom span:last-child {
  margin-right: -0.9rem;
}
.frame {
  position: relative;
  display: block;
  aspect-ratio: 9 / 16;
  padding: 0 2px;
  background: var(--base);
}
.frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 1.5px;
  background: #2a2925;
}
.neg {
  display: block;
  padding-top: 0.25rem;
  font: 0.6rem/1 ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: 0.1em;
}
/* A camera data back's date stamp, burned into the corner of the frame in glowing orange. */
.stamp {
  position: absolute;
  right: 7px;
  bottom: 5px;
  z-index: 1;
  font: 600 0.62rem/1 var(--mono);
  letter-spacing: 0.04em;
  color: var(--stamp);
  text-shadow:
    0 0 2px var(--stamp-glow),
    0 0 6px var(--stamp-halo);
  pointer-events: none;
}
/* The picked frame: a red grease-pencil box drawn round it by hand. */
.grease {
  position: absolute;
  inset: -6px -5px;
  width: calc(100% + 10px);
  height: calc(100% + 12px);
  overflow: visible;
  pointer-events: none;
  z-index: 2;
}
.grease path {
  fill: none;
  stroke: var(--grease);
  stroke-width: 4.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.9;
}
/* In the Calendar, round the month of the Player's last story, a little closer in than round a frame. */
.cell .grease {
  inset: -3px;
  width: calc(100% + 6px);
  height: calc(100% + 6px);
}
/* Focus: a yellow ring with a black one inside it, plain on the dark film and on any photo. */
.thumb:focus-visible {
  outline: none;
  z-index: 3;
}
.thumb:focus-visible .frame {
  outline: 2px solid var(--yellow);
  outline-offset: 1px;
  box-shadow: inset 0 0 0 2px var(--black);
}
.thumb:focus-visible img {
  outline: 2px solid var(--black);
  outline-offset: -2px;
}
.thumb:hover .neg {
  color: var(--table-type-hover);
}
.sheet .empty {
  grid-column: 1 / -1;
  position: static;
}
.sheet-view .keys {
  margin: 0.8rem auto 0;
}
@media (max-width: 600px) {
  .light-table {
    --rebate: 19px;
    padding: 0.8rem 0.5rem 1rem;
    margin: 0 -8px;
  }
  .rebate {
    font-size: 0.45rem;
    letter-spacing: 0.08em;
  }
}
