/* The room page: one WebGL canvas, plus the words that sit over it. Shared OSD and chapter styles come from tv.css. */
@font-face { font-family: Saira; src: url("fonts/SairaExtraCondensed_700Bold.ttf") format("truetype"); font-weight: 700; font-display: swap; }
.stage { position: fixed; inset: 0; width: 100%; height: 100%; display: block; background: #010102; outline: none; opacity: 0; transition: opacity 0.6s; touch-action: manipulation; }
.ready .stage { opacity: 1; }
.subtitle { position: fixed; z-index: 6; }

.scrim { position: fixed; inset: 0; z-index: 7; pointer-events: none; opacity: 0; transition: opacity 0.8s; }
.scrim--left { background: linear-gradient(90deg, rgba(0, 0, 0, 0.78) 0%, rgba(0, 0, 0, 0.45) 30%, transparent 52%); }
.scrim--right { background: linear-gradient(270deg, rgba(0, 0, 0, 0.78) 0%, rgba(0, 0, 0, 0.45) 30%, transparent 52%); }
.in-tv .scrim.is-on { opacity: 1; }

.room-copy { position: fixed; z-index: 8; top: 50%; left: clamp(20px, 5vw, 80px); width: min(430px, 36vw); translate: 0 -50%; text-shadow: 0 2px 12px #000; }
.room-copy[hidden] { display: none; }
.room-copy--right { left: auto; right: clamp(20px, 5vw, 80px); }
.room-copy .ch-h { font-size: clamp(56px, 6.4vw, 108px); text-shadow: 0 0 18px rgba(255, 120, 80, 0.35), 4px 4px 0 rgba(0, 0, 0, 0.6); }
.room-copy .osd-k { color: #ffb59a; text-shadow: 0 0 10px rgba(255, 90, 50, 0.6); }
.room-copy .ch-deck { color: #f3e6de; }
.room-meta { margin: 0 0 1rem; font: clamp(20px, 1.6vw, 26px)/1.1 var(--osd-font); color: #ffcfb8; }
.room-copy .osd-link:hover, .room-copy .osd-link:focus-visible { color: #1a0703; background: #ffe6da; }

.room-bar { position: fixed; z-index: 9; top: max(14px, env(safe-area-inset-top)); left: clamp(14px, 4vw, 52px); font: clamp(22px, 1.9vw, 30px)/1 var(--osd-font); text-shadow: 0 0 10px rgba(0, 0, 0, 0.9); }
.room-bar[hidden] { display: none; }
.room-bar .osd-btn { color: #ffe6da; }
.room-bar .osd-btn:hover, .room-bar .osd-btn:focus-visible { background: #ffe6da; color: #1a0703; }

.hover-label { position: fixed; z-index: 8; left: 50%; bottom: max(18px, 4vh); translate: -50% 0; margin: 0; padding: 0.2em 0.6em; white-space: nowrap; font: clamp(20px, 1.7vw, 28px)/1 var(--osd-font); color: #fff; background: rgba(0, 0, 0, 0.55); letter-spacing: 0.03em; }
.hover-label[hidden] { display: none; }
.hover-label:empty { display: none; }

/* Films: the disc you took out. */
.disc-card .ch-h { font-size: clamp(44px, 4.6vw, 80px); }
.disc-actions { display: flex; flex-wrap: wrap; gap: 0.6rem 1.4rem; align-items: center; font: clamp(22px, 1.8vw, 28px)/1 var(--osd-font); }
.disc-actions .osd-btn { color: #ffe6da; }
.disc-actions .osd-btn:hover, .disc-actions .osd-btn:focus-visible { background: #ffe6da; color: #1a0703; }

/* In Print: the paper you took out of the box. The headline is the paper's own, so it's set smaller than a title. */
.paper-h { margin: 0 0 1rem; font: clamp(32px, 2.9vw, 46px)/0.98 var(--osd-font); letter-spacing: 0.005em; color: var(--osd); text-shadow: 0 0 18px rgba(255, 120, 80, 0.35), 4px 4px 0 rgba(0, 0, 0, 0.6); text-wrap: balance; }
.paper-meta { margin: 0 0 1.3rem; font: 400 14px/1.45 var(--cap-font); color: #f3e6de; opacity: 0.85; }
.paper-card .disc-actions { gap: 0.5rem 1.4rem; }
.paper-card .osd-btn { margin-left: -0.45em; }
@media (max-width: 760px), (max-aspect-ratio: 21/20) {
  .paper-card { padding-top: 2.2rem; }
  .paper-h { font-size: 28px; margin-bottom: 0.5rem; }
  .paper-meta { font-size: 13px; margin-bottom: 0.7rem; }
  .paper-card .disc-actions { font-size: 21px; gap: 0.3rem 1.2rem; }
}

.site-frame { position: fixed; inset: 0; z-index: 11; visibility: hidden; pointer-events: none; }
.site-frame.is-on { visibility: visible; }
.site-frame.is-live { pointer-events: auto; }
/* On the tube the page is a 4:3 frame mapped onto the glass with a matrix3d; live, it's the window. */
.site-view { position: absolute; left: 0; top: 0; width: 100vw; height: 100vh; transform-origin: 0 0; overflow: hidden; background: #f2efe8; opacity: 0; will-change: transform; }
.site-view.is-fold { background: transparent; }
/* Trifold's logo unfolding into its page: the board's outline, glow and folds, and shade on the wings till they're
   flat, drawn in the title card's own pixels (960 by 720) so it sits exactly on the card's mark. */
.site-fold { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
.site-fold svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.site-fold path { fill: none; stroke: #ffbb99; stroke-linejoin: round; stroke-linecap: round; }
.site-fold .fold-shade { fill: rgb(12, 28, 40); stroke: none; }
.site-fold .fold-glow { stroke-opacity: 0.55; filter: url(#tf-glow); }
/* While the board unfolds the page is cut to the board, so the fill round it is never seen: leaving it out keeps the
   page's layer the size it was made at, not half as big again. */
.site-view.is-fold .site-fill { display: none; }
.site-page, .site-tube { will-change: transform; }
/* The glass's glow round the page, on its own layer at the tube's size: placeOnTube maps it onto the glass with the
   page and only its opacity changes, so it's never repainted while the page moves. The glow itself (two soft shadows
   round the rounded box, 80 px and 16 px) is painted into a canvas in it (paintGlow, room.js): as a box-shadow, the
   browser drew it the first time the page came onto the glass, a dropped frame in the opening on a large window. */
.site-glow { position: absolute; left: 0; top: 0; width: calc(100vh * 4 / 3); height: 100vh; transform-origin: 0 0; border-radius: 12vh; opacity: 0; pointer-events: none; will-change: transform, opacity; }
.site-glow canvas { position: absolute; }
/* What the page shows of itself: the band wipe shortens this instead of clipping the page, so the page is never repainted. */
.site-clip { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: hidden; }
.site-page { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.site-fill { position: absolute; z-index: -1; pointer-events: none; }
.site-page iframe { display: block; width: 100%; height: 100%; border: 0; background: #f2efe8; }
/* The tube: scanlines, a slightly cool phosphor cast, darker curved edges and the glass's sheen. */
/* (a fixed 4:3 box, centred, so the page's frame changing size never repaints it; the frame clips it) */
/* It's painted into a canvas in it (paintTube, room.js), once per size, from what were these: a radial sheen
   (70% 45% at 28% 14%, white .22 to clear at 70%), scanlines (0deg, rgba(10, 14, 30, .2) 0-2px, clear 2-6px), a
   vignette (115% 100%, clear at 48% to rgba(8, 10, 20, .7)), a cool cast (rgba(150, 175, 255, .07)), and inset
   shadows of 90px/28px rgba(6, 8, 16, .55) and 14px/6px rgba(0, 0, 0, .6). As CSS the browser drew them the first
   time the page came onto the glass, a dropped frame in the opening on a large window. */
.site-tube { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
.site-tube canvas { display: block; width: 100%; height: 100%; }
/* Snow over the page while the set finds it. */
.site-snow { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0; }
.site-snow[hidden] { display: none; }
/* The site's controls, at the bottom (its own menus sit at the top), in the set's OSD: the way back, the write-up (the
   one lit, as the set's chosen chip is) and a new tab as an arrow, all one height. The site's own App Store button
   stands for ours. ?sitebar=1 (the default): one strip in the middle. ?sitebar=2: the way back bottom left, the
   write-up and the arrow bottom right. The room's own bar stands aside on the site. */
.site-acts { position: absolute; bottom: max(12px, env(safe-area-inset-bottom)); display: flex; align-items: stretch; gap: 3px; opacity: 0; transition: opacity 0.4s; font: clamp(20px, 1.6vw, 26px)/1 var(--osd-font); }
.site-frame.is-live .site-acts { opacity: 1; }
.site-acts > * { all: unset; box-sizing: border-box; display: block; padding: 0.3em 0.72em; cursor: pointer; white-space: pre; text-align: center; color: var(--osd); }
.site-acts > :hover, .site-acts > :focus-visible { background: var(--osd); color: var(--blue); text-shadow: none; }
.site-acts > [hidden], .site-acts > [data-site-store] { display: none; }
.site-case { background: var(--blue); text-shadow: 0 0 6px rgba(150, 200, 255, 0.75); }
.site-tab { padding-inline: 0.6em; color: var(--osd-dim); }
.sitebar-1 .site-acts { left: 50%; translate: -50% 0; padding: 3px; background: rgba(6, 8, 18, 0.86); box-shadow: 0 0 0 1px rgba(169, 198, 255, 0.16); }
.sitebar-2 .site-acts { left: max(12px, env(safe-area-inset-left)); right: max(12px, env(safe-area-inset-right)); pointer-events: none; }
.sitebar-2 .site-acts > * { pointer-events: auto; }
.sitebar-2 .site-acts > :not(.site-case):not(:hover):not(:focus-visible) { background: rgba(6, 8, 18, 0.86); }
.sitebar-2 .site-back { margin-right: auto; }
.on-site .room-bar { display: none; }
@media (max-width: 600px) {
  .site-long { display: none; }
  /* The page stops short of the strip (38 px tall, its gap to the edge, 6 px clear), so its last lines aren't under it. */
  .site-page iframe { height: calc(100% - 44px - max(12px, env(safe-area-inset-bottom))); }
  .sitebar-1 .site-acts { left: max(10px, env(safe-area-inset-left)); right: max(10px, env(safe-area-inset-right)); translate: none; }
  .sitebar-1 .site-case { flex: 1; }
}
/* The Nearbuy logo on its way from the TV into the demo. */
.nb-fly { position: fixed; z-index: 45; left: 0; top: 0; width: 0; height: 0; pointer-events: none; transform-origin: 0 0; will-change: transform; }
.nb-fly[hidden] { display: none; }
/* Covers the N in the demo's first frame until the flying one lands on it (header colour #0e0e12). */
.nb-patch { position: absolute; z-index: 1; left: calc(27 / 720 * 100%); top: calc(143 / 1566 * 100%); width: calc(53 / 720 * 100%); height: calc(51 / 1566 * 100%); background: #0e0e12; }
.nb-patch[hidden] { display: none; }
.vhs { position: fixed; inset: 0; z-index: 20; width: 100%; height: 100%; pointer-events: none; }
.vhs[hidden] { display: none; }
.room-bar { z-index: 14; }

@media (max-width: 760px), (max-aspect-ratio: 21/20) {
  .room-copy, .room-copy--right { top: auto; bottom: 0; left: 0; right: 0; width: auto; translate: none; padding: 3.5rem 18px 4.2rem; background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.82) 28%); }
  .room-copy .ch-h { font-size: 56px; margin-bottom: 0.6rem; }
  .room-copy .ch-deck { font-size: 16px; margin-bottom: 0.8rem; }
  .scrim { display: none; }
  .hover-label { bottom: 14px; font-size: 18px; max-width: 92vw; overflow: hidden; text-overflow: ellipsis; }
}

/* Nearbuy page (refined) */
/* On a phone the page scrolls under the OSD bar, and the lit phone would run through its labels, so the bar gets a shade while Nearbuy is up. */
@media (max-width: 760px) {
  .inside:has(.ch--nearbuy:not([hidden])) .osd-bar::before { content: ""; position: absolute; inset: 0 0 -22px; z-index: -1; pointer-events: none; background: linear-gradient(rgba(1, 4, 26, 0.94) 50%, rgba(1, 4, 26, 0)); }
}
/* The taps in the demo, drawn over the video; an action being shown takes the caption over in yellow. */
.nb-taps { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; pointer-events: none; }

/* The sound switch: top right, as the way back is top left, everywhere but on the sites (their own menus sit there). */
.sound-btn { position: fixed; z-index: 14; top: max(14px, env(safe-area-inset-top)); right: clamp(14px, 4vw, 52px); font: clamp(22px, 1.9vw, 30px)/1 var(--osd-font); color: #ffe6da; text-shadow: 0 0 10px rgba(0, 0, 0, 0.9); }
.sound-btn:hover, .sound-btn:focus-visible { background: #ffe6da; color: #1a0703; text-shadow: none; }
.sound-btn[aria-pressed="false"] { opacity: 0.7; }
.on-site .sound-btn { display: none; }

/* Play All (assets/playall.js): the line under what's playing, and a strip saying which chapter it's on, how many
   there are, and STOP. Bottom centre; on a site, above the site's own buttons; on a phone, under the top buttons. */
.pa { position: fixed; z-index: 30; left: 50%; bottom: max(16px, env(safe-area-inset-bottom)); translate: -50% 0; width: min(92vw, 820px); display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; opacity: 0; transition: opacity 0.35s; }
.pa.is-on { opacity: 1; }
.pa[hidden] { display: none; }
.pa-cap { margin: 0; padding: 0.3em 0.7em; max-width: 100%; text-align: center; text-wrap: balance; font: 600 clamp(15px, 1.25vw, 20px)/1.35 var(--cap-font); color: #fff; background: rgba(0, 0, 0, 0.74); }
.pa-cap:empty { display: none; }
/* The keys for going between spots, quiet beside the bar for a moment (at the start, and when one's pressed). */
.pa-hint { margin: 0; padding: 0.2em 0.6em; white-space: nowrap; font: clamp(15px, 1.1vw, 18px)/1 var(--osd-font); letter-spacing: 0.04em; color: var(--osd-dim); background: rgba(0, 0, 0, 0.5); opacity: 0; transition: opacity 0.3s; }
.pa-hint.is-on { opacity: 1; }
.pa-bar { display: flex; align-items: center; gap: 0.75em; max-width: 100%; padding: 0.2em 0.25em 0.2em 0.75em; white-space: nowrap; font: clamp(19px, 1.45vw, 24px)/1 var(--osd-font); color: var(--osd); background: rgba(0, 0, 0, 0.66); pointer-events: auto; }
.pa-k { color: var(--osd-dim); letter-spacing: 0.03em; }
.pa-tape { display: flex; gap: 3px; }
.pa-tape i { position: relative; width: 15px; height: 9px; overflow: hidden; background: rgba(169, 198, 255, 0.24); }
.pa-tape b { position: absolute; inset: 0; background: var(--osd); transform: scaleX(0); transform-origin: 0 50%; }
.pa-tape .is-done b, .pa-tape .is-now b { transform: none; }
.pa-tape .is-now b { animation: pa-blink 1.1s steps(2, jump-none) infinite; }
@keyframes pa-blink { 50% { opacity: 0.35; } }
.pa-where { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pa-stop { color: #fff; }
.on-site .pa { bottom: calc(max(12px, env(safe-area-inset-bottom)) + 52px); }
/* While it plays, the room's pointing hints (bottom centre too) and the local preview tag stand aside. */
.playing-all .hover-label, .playing-all .preview-tag { visibility: hidden; }
.still .pa, .still .pa-tape b { transition: none; animation: none; }
@media (max-width: 760px) {
  .pa { top: calc(max(14px, env(safe-area-inset-top)) + 40px); bottom: auto; flex-direction: column-reverse; }
  .pa-k, .pa-tape { display: none; }
  .on-site .pa { top: auto; bottom: 120px; flex-direction: column; }
}

/* Words for the pointer you have: a mouse points and clicks, a finger taps (the same test as the room's hints). */
.by-touch { display: none; }
@media (pointer: coarse) { .by-mouse { display: none; } .by-touch { display: inline; } }
/* A finger dragged on the room is the mouse's hover (room.js), so the browser doesn't take it for a pan. */
@media (pointer: coarse) { .stage { touch-action: none; } }

/* The set's chapters as pages, where the set doesn't play them (a phone): Booking the Show's A&O line, its artists
   in the set page's yellow, and the crew photo's caption. */
.stub-meta { margin: -0.5rem 0 1.2rem; font: clamp(20px, 1.6vw, 26px)/1.1 var(--osd-font); color: var(--osd-dim); }
.stub-list { margin: 0 0 1.4rem; font: clamp(28px, 2.2vw, 34px)/1.1 var(--osd-font); color: #ffe46a; text-shadow: 0 0 10px rgba(255, 228, 106, 0.45); }
.stub-fig { margin: 0; }
.stub-cap { margin: 0.7rem 0 0; font: clamp(18px, 1.4vw, 22px)/1.2 var(--osd-font); color: var(--osd-dim); text-align: center; }

/* A phone on its side (short, wide, a finger): the copy goes back beside the room as on a wide screen, a size down so it
   fits the height, standing under the top bar and scrolling if it must; the scrim comes back behind it. Play All's
   strip sits at the foot, under the TV. (html raises it over rotation.css's centring, which uses !important.) */
@media (orientation: landscape) and (max-height: 520px) and (pointer: coarse) {
  html .room-copy, html .room-copy[data-room-copy] { top: calc(max(14px, env(safe-area-inset-top)) + 38px) !important; bottom: 8px !important; translate: none !important; transform: none !important; }
  html .room-copy { left: max(16px, env(safe-area-inset-left)); right: auto; width: min(360px, 42vw); padding: 0; background: none; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
  html .room-copy--right { left: auto; right: max(16px, env(safe-area-inset-right)); }
  html .room-copy:not([hidden]) { display: flex; flex-direction: column; justify-content: safe center; }
  .room-copy .ch-h { font-size: 38px; margin-bottom: 0.35rem; }
  .room-copy .ch-deck { font-size: 15px; line-height: 1.45; margin-bottom: 0.6rem; }
  .room-copy .osd-k { font-size: 18px; margin-bottom: 0.2rem; }
  .room-meta { font-size: 17px; margin-bottom: 0.6rem; }
  .scrim { display: block; }
  .hover-label { bottom: 6px; font-size: 16px; }
  .pa { top: auto; bottom: max(8px, env(safe-area-inset-bottom)); flex-direction: column; }
  .site-page iframe { height: calc(100% - 44px - max(12px, env(safe-area-inset-bottom))); }   /* (the strip's room, as upright) */
}
