/* The home page: one game night at the table, then the free series. Without scripts, or held still, every moment is
   a full screen of its own picture with its words over it; html.living turns the same markup into the world: one
   stage held on screen while the words of each moment scroll over it. */
.story { position: relative; background: var(--fog); overflow-x: clip; }
.stage { display: none; }

/* A moment, held still: its picture fills the screen and its words lie over it. */
.beat { position: relative; min-height: 100vh; min-height: 100svh; display: flex; overflow: clip; }
.beat .still { position: absolute; inset: 0; z-index: 0; margin: 0; }
.beat .still img { width: 100%; height: 100%; object-fit: cover; }
.words { position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 18px;
  padding: calc(var(--bar) + 4vh) 4vw calc(var(--buybar) + 5vh); }
.beat .words { background: linear-gradient(180deg, rgba(25,24,29,0.78) 0, rgba(25,24,29,0) 32%, rgba(25,24,29,0) 62%, rgba(25,24,29,0.8) 100%); }
html.living .beat .words { background: none; }

/* The words. */
.eyebrow { font: 700 1rem/1.2 var(--body); color: var(--ash); margin: 0 0 10px; }
.lede, .aside, .offer-card { position: relative; color: var(--white); }
.lede { max-width: 34rem; }
.lede::before, .aside::before, .offer-card::before { content: ""; position: absolute; z-index: -1; inset: -48px -64px; background: radial-gradient(closest-side, rgba(25,24,29,0.86), rgba(25,24,29,0.62) 55%, rgba(25,24,29,0)); pointer-events: none; }
.lede h1 { font-size: clamp(2.4rem, 4.4vw, 4.2rem); }
.lede .sum { font-size: 1.15rem; line-height: 1.45; max-width: 30rem; }
.buyline { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; margin: 18px 0 12px; }
.sum .more { display: inline-block; padding: 10px 0; min-height: 44px; }
.buyline .more, .buy .more, .sum .more { color: var(--white); font-weight: 700; padding: 10px 0; }
.soon-note { flex-basis: 100%; color: var(--white); font-size: 1rem; }
.soon-note a { font-weight: 700; }
.lede .small, .offer-card .small { font-size: 0.95rem; color: var(--ash); }
.aside { max-width: 24rem; }
.aside h2 { font-size: clamp(1.8rem, 2.9vw, 2.75rem); }
.aside p { font-size: 1.05rem; }
.aside .dry { color: var(--ash); font-style: italic; }
.aside .read-sheet { font-weight: 700; color: var(--white); }

/* Notes from the kit: the chest key card shows one line at a time once the world runs. */
.chest-note .key { list-style: none; margin: 0; padding: 0; }
.chest-note .key li { font-size: 0.98rem; line-height: 1.42; margin: 0 0 6px; }
.chest-note .key b { display: inline-grid; place-items: center; min-width: 1.6em; height: 1.6em; padding: 0 0.3em; margin-right: 6px; border-radius: 1em; background: var(--fog); color: var(--white); font: 900 0.85rem/1 var(--head); vertical-align: 0.1em; }
.chest-note .rule { display: block; margin-top: 4px; }
html.living .chest-note .key li { display: none; margin: 0; }
html.living .chest-note .key li.on { display: block; font-size: 1.02rem; }
.chest-note.pop { animation: note-pop 260ms cubic-bezier(.2,.9,.3,1.2); }
@keyframes note-pop { from { transform: translateY(6px) rotate(-0.6deg); } to { transform: none; } }

/* The labels: tape strips with the kit's part names. */
.labels { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; max-width: 40rem; }
.labels a { display: block; text-align: left; text-decoration: none; background: var(--tape); color: var(--fog); border-radius: 1px; padding: 5px 10px 6px; font: 400 0.84rem/1.2 var(--body); box-shadow: 0 1px 0 rgba(0,0,0,0.35); -webkit-tap-highlight-color: transparent; }
.labels a b { display: block; font-family: var(--head); font-weight: 900; font-size: 0.92rem; }
.labels a:hover { background: #55a7f2; }
.labels .lab-short { display: none; }

/* The offer. */
.offer-card { max-width: 31rem; }
@media (min-width: 900px) {
  .offer-card { background: rgba(25,24,29,0.94); padding: 26px 30px 22px; margin: -4vh -4vw -5vh 0; max-width: 35rem; align-self: stretch; display: flex; flex-direction: column; justify-content: center; }
  .offer-card::before { display: none; }
  html:not(.living) .b7 .offer-card { margin-top: calc(-1 * (var(--bar) + 4vh)); padding-top: calc(var(--bar) + 26px); }
}
/* Held still on a phone, the ending shows its whole picture first (Owen, the puff and the blue tent), and the offer
   follows under it, so no words lie over them. */
@media (max-width: 899px) {
  html:not(.living) .b7 { flex-direction: column; }
  html:not(.living) .b7 .still { position: relative; inset: auto; }
  html:not(.living) .b7 .still img { height: auto; }
  html:not(.living) .b7 .words { background: var(--fog); padding-top: 20px; }
  html:not(.living) .b7 .next-note { margin-bottom: 8px; }
}
.offer-card .offer-title { font-size: clamp(2.4rem, 3.8vw, 3.6rem); }
.offer-card > p { font-size: 1.05rem; }
.contents { list-style: none; margin: 14px 0 18px; padding: 0; display: grid; gap: 9px; }
.contents li { position: relative; padding-left: 26px; font-size: 1rem; line-height: 1.38; }
.contents li::before { content: ""; position: absolute; left: 0; top: 0.42em; width: 16px; height: 7px; background: var(--tape); transform: rotate(-4deg); }
.buy { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; margin: 6px 0 10px; }
.buy .price { font-size: 2.4rem; }
.buy.soon p { flex-basis: 100%; margin: 0; font-size: 1rem; }

@media (min-width: 900px) {
  .b2 .words, .b3 .words { flex-direction: row; align-items: flex-end; justify-content: space-between; }
  /* The key card stacks above the words on the left, so it never sits on the chest that was tapped. */
  .b2 .words { flex-direction: column; align-items: flex-start; justify-content: flex-end; gap: 22px; }
  .b2 .chest-note { order: -1; width: 25rem; }
  .b4 .words, .b5 .words { justify-content: flex-start; }
  .b6 .words { flex-direction: row; justify-content: space-between; align-items: flex-start; }
  .b6 .note { align-self: flex-end; width: 25rem; }
  .b6 .aside { max-width: 21rem; }
  /* Owen's end of the table keeps the left of the screen: the offer stands at the right, the puff button and the next
     note under Owen, so nothing covers him, the bowl or the blue tent. */
  .b7 .words { display: grid; grid-template-columns: 1fr auto; grid-template-rows: 1fr auto auto; gap: 14px 24px; align-items: end; }
  .b7 .offer-card { grid-column: 2; grid-row: 1 / -1; }
  .b7 .puff { grid-column: 1; grid-row: 2; justify-self: start; }
  .b7 .next-note { grid-column: 1; grid-row: 3; width: 21rem; }
  html.living .b7 .offer-card { max-width: 31rem; }
  .b1 .words { justify-content: center; }
  .chest-note { width: 28rem; }
  .b3 .note { width: 27rem; }
}
@media (max-width: 899px) {
  .words { padding: calc(var(--bar) + 18px) 18px calc(var(--buybar) + 16px); gap: 12px; }
  .lede h1 { font-size: clamp(1.9rem, 8.4vw, 2.6rem); margin-bottom: 0.25em; }
  .lede .sum { font-size: 1rem; margin: 0; }
  .lede::before, .aside::before, .offer-card::before { inset: -30px -40px; }
  .aside h2 { font-size: 1.6rem; margin-bottom: 0.2em; }
  .aside p { font-size: 0.98rem; margin-bottom: 0; }
  .words > .aside:not(.up) { margin-top: auto; }
  .b6 .words > .aside { margin-top: 0; }
  .b2 .words, .b3 .words { justify-content: flex-end; }
  .b2 .aside h2, .b3 .aside h2 { font-size: 1.35rem; margin: 0; }
  .note { width: 100%; max-width: none; padding: 14px 14px 10px; }
  .note p { font-size: 0.92rem; }
  .b3 .words > .note { margin-top: auto; }
  /* In the cellar and at the break the note is a strip of tape under the words, so the heroes, the run sheet and the
     hands holding it stay clear. */
  .b4 .words > .note, .b6 .words > .note { width: auto; max-width: 19rem; padding: 7px 12px 6px; background: var(--tape); border: 0; transform: rotate(-1.5deg); }
  .b4 .words > .note::before, .b6 .words > .note::before { display: none; }
  .b4 .note .note-from, .b4 .note p, .b6 .note .note-from, .b6 .note p { color: var(--fog); margin: 0; font-size: 0.82rem; }
  .b4 .note .note-title, .b6 .note .note-title { font-size: 0.95rem; margin: 0; }
  .b7 .words { justify-content: flex-end; }
  .b7 .next-note { order: -1; margin-bottom: auto; width: auto; padding: 8px 12px 6px; max-width: 17rem; }
  .b7 .next-note::before { display: none; }
  .b7 .next-note { background: var(--tape); border: 0; transform: rotate(-2deg); }
  .b7 .next-note .note-from, .b7 .next-note p { color: var(--fog); margin: 0; font-size: 0.82rem; }
  .b7 .next-note .note-title { font-size: 0.95rem; margin: 0; }
  .offer-card { width: 100%; }
  html.living .offer-card { background: rgba(25,24,29,0.94); margin: 0 -18px calc(-16px - var(--buybar)); padding: 14px 18px calc(12px + var(--buybar)); width: auto; align-self: stretch; }
  /* On a phone the offer is a short sheet under Owen's end of the table; the kit's contents are on its page. */
  html.living .offer-card .contents { display: none; }
  html.living .offer-card .offer-title { font-size: 1.8rem; }
  html.living .offer-card .buy { margin: 2px 0 4px; }
  html.living .offer-card .buy.soon p { font-size: 0.95rem; line-height: 1.4; flex: 1 1 12rem; }
  html.living .b7 .offer-card { order: 1; }
  html.living .offer-card .buy .more { padding: 12px 0; }
  html.living .offer-card .eyebrow { display: none; }
  html.living .b7 .puff { align-self: flex-start; margin-bottom: 4px; }
  /* A button's words stay on one line only where the line fits; at very large text or zoom they wrap inside it. */
  @media (min-width: 22em) { .buy .btn { white-space: nowrap; } }
  .buy .btn { max-width: 100%; }
  html.living .b7 .next-note { max-width: 15rem; }
  html.living .offer-card::before { display: none; }
  .offer-card .eyebrow { margin-bottom: 4px; }
  .offer-card .offer-title { font-size: 2.1rem; margin-bottom: 0.2em; }
  .offer-card > p { font-size: 0.95rem; margin-bottom: 6px; }
  .contents { margin: 8px 0 12px; gap: 5px; }
  .contents li { font-size: 0.92rem; }
  .buy .price { font-size: 2rem; }
  .buy[data-sale="open"] .btn { flex: 1; }
  .labels { gap: 6px; }
}

/* The world, once it runs. */
/* The world sits under the bar, edge to edge, so the bar never covers the lamp and the bar's layer never cuts into the
   canvas. */
html.living .story { padding-top: var(--bar); }
html.living .stage { display: block; position: sticky; top: var(--bar); z-index: 0; height: calc(100vh - var(--bar)); height: calc(100lvh - var(--bar)); overflow: hidden; overflow: clip; background: var(--fog); touch-action: pan-y; }
html.living .stage-poster, html.living .stage-poster img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
html.living .stage-poster { z-index: 0; transition: visibility 0s 0.5s; }
html.living .stage:has(canvas.table.on) .stage-poster { visibility: hidden; }
html.living .stage canvas.table { position: absolute; z-index: 1; inset: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.45s ease; }
html.living .stage canvas.table.on { opacity: 1; }
html.living .beats { position: relative; z-index: 2; margin-top: calc(var(--bar) - 100vh); margin-top: calc(var(--bar) - 100lvh); pointer-events: none; }
html.living .beat { display: block; min-height: 0; height: calc(var(--len) * 100vh); height: calc(var(--len) * 100lvh); overflow: visible; }
html.living .beat .still { display: none; }
html.living .words { position: sticky; top: var(--bar); height: calc(100vh - var(--bar)); height: calc(100svh - var(--bar)); padding-top: 4vh; }
@media (max-width: 899px) { html.living .words { padding-top: 16px; } }
html.living .words > * { pointer-events: auto; }
/* With large text a phone's screen holds fewer lines: the vault's notes become strips of tape, and the ending keeps
   its title, price and way to buy, so the map, the GM's hand and Owen's end of the table stay in view. */
@media (max-width: 899px) and (max-height: 44em) {
  html.living .b2 .chest-note, html.living .b3 .words > .note { width: auto; max-width: 21rem; padding: 7px 12px 6px; background: var(--tape); border: 0; rotate: -1.2deg; }
  html.living .b2 .chest-note::before, html.living .b3 .words > .note::before { display: none; }
  html.living .b2 .chest-note .note-from, html.living .b3 .note .note-from { display: none; }
  html.living .b2 .chest-note .key li, html.living .b3 .note p { color: var(--fog); margin: 0; font-size: 0.85rem; line-height: 1.35; }
  html.living .b2 .chest-note .key b { background: var(--fog); }
  html.living .b3 .note .note-title { font-size: 0.95rem; margin: 0 0 2px; }
  html.living .b7 .next-note { display: none; }
  /* The break's labels stay small strips of tape on the things they name. */
  html.living .labels.live a { padding: 3px 8px 4px; }
  html.living .labels.live a b { font-size: 0.78rem; }
  /* The 1:45 note repeats the row the pencil has ringed on the sheet the GM holds up; it gives way to the sheet. */
  html.living .b6 .words > .note { display: none; }
  /* The puff button is a small strip of tape at the table's edge, so the blue tent stays in view. */
  html.living .b7 .puff { padding: 4px 10px; min-height: 44px; font-size: 0.85rem; }
  /* The ending reads in order: Owen, the blue tent and the puff first, then the whole offer comes up over the table
     as the visitor reads on, so nothing of it is cut and nothing covers the joke. */
  html.living .b7 { height: auto; min-height: calc(var(--len) * 100lvh); }
  html.living .b7 .words { position: relative; top: auto; height: auto; justify-content: flex-start; padding-top: 0; }
  html.living .b7 .puff { order: 0; margin-top: 50svh; margin-bottom: 14px; }
  html.living .b7 .offer-card { margin-bottom: 0; }
}
/* The vault's headings hold no links: a finger on a chest under one, as it scrolls past, still reaches the chest. */
html.living .b2 .aside, html.living .b3 .aside { pointer-events: none; }
/* In the vault on a phone, the heading sits over the kitchen above the players and the key card in a slot at the
   bottom, so the map between them stays clear for a finger. */
@media (max-width: 899px) {
  html.living .b2 .words > .aside, html.living .b3 .words > .aside { margin-top: 0; margin-bottom: auto; }
  html.living .b3 .words > .note { margin-top: 0; }
}
html.living .b5 .labels:not(.live) { display: none; }
.b1 { --len: 1.15; } .b2 { --len: 1.6; } .b3 { --len: 1.5; } .b4 { --len: 1.5; } .b5 { --len: 1.8; } .b6 { --len: 1.5; } .b7 { --len: 1.6; }

/* The story's cellar, under its fog-sheet cuts. */
.cellar { display: none; }
html.living .cellar { position: absolute; inset: 0; z-index: 3; background: #120e0b; }
html.living .cellar.on { display: block; }
html.living .cellar > picture, html.living .cellar > picture > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cellar-things { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
.cellar-things > * { position: absolute; left: 0; top: 0; will-change: transform; }
.cellar-things .cheese, .cellar-things .kettle { width: 100px; height: 100px; object-fit: cover; opacity: 0; }
.cellar-things .cheese { object-position: 0 50%; }
.cellar-things .arm { height: auto; opacity: 0; }
.cellar-things .kettle { object-position: 100% 50%; }
.mimic { pointer-events: auto; padding: 0; border: 0; background: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.mimic img { width: 100%; height: auto; }
.mimic .open { position: absolute; inset: 0; opacity: 0; }
.mimic.gape .open { opacity: 1; } .mimic.gape .shut { opacity: 0; }

/* Things laid over the table: hands, labels, the run sheet, the fog-sheet cut. */
.overlay { display: none; }
html.living .overlay { display: block; position: absolute; inset: 0; z-index: 6; pointer-events: none; overflow: hidden; }
.overlay .hand { position: absolute; left: 0; top: 0; width: 200px; height: auto; transform-origin: 45% 6%; will-change: transform; opacity: 0; }
.labels.live { position: absolute; inset: 0; display: block; max-width: none; pointer-events: none; }
.labels.live li { position: absolute; left: 0; top: 0; opacity: 0; will-change: transform, opacity; }
.labels.live a { max-width: 15rem; min-height: 44px; }
/* On a phone each strip carries its name only, so the kit under them stays in view; the rest is still its link's name. */
@media (max-width: 899px), (max-height: 560px) { .labels.live a { display: flex; align-items: center; max-width: 9.5rem; font-size: 0; line-height: 1.15; padding: 6px 9px; } .labels.live a b { font-size: 0.8rem; } }
/* The layer for things pinned to the table that a visitor can reach: the break's labels and the twelve chests. */
html.living .pins { position: absolute; inset: 0; z-index: 7; pointer-events: none; }
.chest-pin { position: absolute; left: 0; top: 0; width: 48px; height: 48px; padding: 0; border: 0; border-radius: 10px; background: transparent; cursor: pointer; pointer-events: auto; visibility: hidden; -webkit-tap-highlight-color: transparent; }
.chest-pin:focus-visible { outline: 3px solid var(--tape); outline-offset: 2px; background: rgba(47,147,238,0.18); }
.labels.live li.l { --pin: -100%; }
/* A screen too small for every strip at full length (a small phone, a phone on its side): each is a short strip of tape
   on one line, its whole name still the link's name, and its tap reaching a little above and below it (44 px). */
.labels.live.compact a { display: flex; align-items: center; position: relative; max-width: none; min-height: 34px; padding: 3px 9px; white-space: nowrap; font-size: 0; line-height: 1.1; }
.labels.live.compact a b { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.labels.live.compact a .lab-short { display: inline; font: normal 900 0.8rem/1.1 var(--head); }
.labels.live.compact a::after { content: ""; position: absolute; left: 0; right: 0; top: -5px; bottom: -5px; }

.runsheet { display: none; }
/* Sized so its lower corners and the GM's hands holding them are always on screen, the arms running off the bottom. */
html.living .runsheet { display: block; position: absolute; z-index: 8; left: 50%; top: 0; margin: 0; width: min(40vw, 52lvh); transform: translate(-50%, 120lvh); will-change: transform; visibility: hidden; }
@media (max-width: 899px) { html.living .runsheet { width: min(72vw, 44lvh); } }
.runsheet-page { position: relative; display: block; width: 100%; padding: 0; border: 3px solid var(--fog); background: var(--white); cursor: zoom-in; box-shadow: 0 30px 60px rgba(0,0,0,0.55); -webkit-tap-highlight-color: transparent; }
.runsheet-page img { width: 100%; height: auto; }
.runsheet .pencil { position: absolute; inset: 0; width: 100%; height: 100%; fill: none; stroke: #6e6c76; stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; }
.runsheet .pencil path { stroke-dasharray: 1; stroke-dashoffset: 1; }
.runsheet.drawn .pencil path { stroke-dashoffset: 0; transition: stroke-dashoffset 0.28s cubic-bezier(.5,0,.3,1); }
.runsheet.drawn .pencil .t2 { transition-delay: 0.32s; }
.runsheet.drawn .pencil .ring { transition-duration: 0.55s; transition-delay: 0.7s; }
/* The GM's hands pinch the sheet's lower corners, thumbs on the front, their arms running off the bottom. */
.runsheet .hold { position: absolute; width: 26%; height: auto; top: 91%; pointer-events: none; transform-origin: 50% 7.2%; }
.runsheet .hold-l { left: -13.6%; transform: scaleX(-1) rotate(-6deg); }
.runsheet .hold-r { right: -13.6%; transform: rotate(-6deg); }

.cut { display: none; }
html.living .cut { display: block; position: absolute; z-index: 20; left: -6%; right: -6%; top: 0; height: 118%; background: #17161b; transform: translateY(110%); visibility: hidden; pointer-events: none;
  box-shadow: 0 -2px 0 #3a3842, 0 -40px 80px rgba(0,0,0,0.55); border-radius: 2px; }
.cut-hand { position: absolute; width: min(24vw, 190px); height: auto; bottom: 2%; }
.cut-hand.l { left: 16%; transform: scaleX(-1) rotate(10deg); }
.cut-hand.r { right: 16%; transform: rotate(10deg); }

/* The offer's puff: Owen holds out another, and the blue tent answers. Only where the world runs. */
.puff { display: none; }
html.living .puff { display: inline-flex; align-items: center; min-height: 46px; padding: 6px 16px; font: 900 1rem/1.1 var(--head); color: var(--fog); background: var(--tape); border: 0; border-radius: 2px; transform: rotate(-1.5deg); box-shadow: 0 2px 0 rgba(0,0,0,0.4); cursor: pointer; -webkit-tap-highlight-color: transparent; }
html.living .puff:focus-visible { outline: 3px solid var(--white); outline-offset: 3px; }
html.living .puff:active { transform: rotate(-1.5deg) translateY(1px); }

/* After the story. */
.after { padding: 12vh 5vw 10vh; display: grid; justify-items: center; background: var(--fog); }
.after .credit { margin: 44px 0 0; max-width: 40rem; font-size: 0.85rem; line-height: 1.5; color: var(--ash); }
.after .credit a { color: var(--white); }

