/* The House: quiet neutral-grey UI chrome over a 3D house (owner: integrator).
   Tokens, the stage, boxes (header, primary button, track list, waveform scrubber), the control bar and
   its stop list, the now-playing chip, phone sheets and the dock, and the reduced-motion / no-WebGL
   layouts. Room-specific rules live in css/rooms/<room>.css, loaded after this. */
:root {
  /* surfaces: a pure neutral grey (no tint), so the rooms and the covers carry all the colour */
  /* (opaque: a translucent box let the room's shapes show through its rows, and the scene moves under it) */
  --surface: #262626;               /* boxes, sheets, the bar, the chip */
  --surface-solid: #262626;         /* the phone band behind the dock */
  --raise-1: #2f2f2f;               /* a row under the pointer, office tiles, the stop list */
  --raise-2: #343434;               /* the current track's card */
  --raise-3: #404040;               /* button hover, pressed */
  --rule: rgb(255 255 255 / .09);   /* hairlines (decorative) */
  --edge: rgb(255 255 255 / .09);   /* the 1px inner edge of a surface (decorative) */
  /* greys: contrast in NOTES.md (worst case: the current card, or the box over a white room) */
  --ink: #ececec;      /* text: 10.5:1 or more */
  --ink-2: #b3b3b3;    /* secondary text, numbers, durations: 5.9:1 or more */
  --ink-3: #8a8a8a;    /* UI parts: unplayed waveform, outlines, placeholder glyphs: 3.6:1 or more */
  --ink-hi: #f5f5f5;   /* played waveform, primary buttons, equaliser, focus ring */
  --ink-hover: #c4c4c4;/* waveform between the playhead and the pointer (a seek preview) */
  --on-hi: #1f1f1f;    /* text and icons on --ink-hi (15:1) */
  --halo: #0f0f0f;     /* dark ring outside a focus ring; the waveform's time chips */
  --placeholder: #383838; /* a cover still to come */
  --badge: #d4d4d4;    /* "Out now" */
  --off: #6b6b6b;      /* an arrow at an end of the journey (inactive) */
  --shadow: 0 18px 44px -18px rgb(0 0 0 / .6);
  --curtain: #171717;  /* the jump-cut curtain (also the sessions app's curtain layer, office.css) */
  --ease: cubic-bezier(.2, .7, .2, 1);
  --panel-w: clamp(352px, 33vw, 392px); /* (352: the theater's widest label on one line, at 1024 and narrower) */
  --bar-x: clamp(12px, 1.4vw, 24px);
  --bar-y: clamp(12px, 2.4vh, 24px);
  font-family: "Jost", "Futura", "Avenir Next", system-ui, sans-serif;
  color: var(--ink);
  background: var(--curtain);
  -webkit-text-size-adjust: 100%;
}
* { box-sizing: border-box; }
html { scroll-behavior: auto; }
body { margin: 0; background: var(--curtain); overflow-x: hidden; }
button, input { font: inherit; color: inherit; }
a { color: inherit; }
/* focus: a light ring with a dark halo, so it reads on a box, on the bar and over any room */
:focus-visible { outline: 2px solid var(--ink-hi); outline-offset: 2px; box-shadow: 0 0 0 5px var(--halo); border-radius: 6px; }
/* (a heading the keyboard was moved to after a click and a scroll: no ring, as the click showed none) */
[data-quiet]:focus-visible { outline: none; box-shadow: none; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.skip { position: fixed; left: 16px; top: 12px; z-index: 50; padding: 10px 16px; background: var(--ink-hi); color: var(--on-hi); border-radius: 999px; font-weight: 600; text-decoration: none; transform: translateY(-160%); transition: transform .2s; }
.skip:focus { transform: none; }

/* ---------- stage ---------- */
.stage { position: fixed; inset: 0; z-index: 0; background: #5aa3ec; }
#scene { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.veil { position: absolute; inset: 0; background: var(--curtain); opacity: 0; pointer-events: none; transition: opacity .28s ease; z-index: 1; }
/* a jump-cut (keyboard focus far away, long trips): the curtain covers the scene and the boxes */
.is-cutting .veil { transition-duration: .18s; }
.is-cutting main .panel, .is-cutting #sessions, .is-cutting .hello__inner { opacity: 0 !important; transition: opacity .18s ease; }

/* a link straight into a room: no greeting over the first paint (app.js takes the greeting over at once) */
.is-deep .hello__inner { opacity: 0; pointer-events: none; }

/* ---------- rooms + boxes ---------- */
main { position: relative; z-index: 3; }
.room { position: relative; }
/* a room's steps (the office's sessions): empty sections that give them their scroll length */
.room--step { pointer-events: none; }
/* (no overscroll-behavior: contain. A box keeps a wheel, trackpad or swipe gesture only while its own
   list can scroll; the next gesture at the list's end, and every one over a box with nothing to scroll,
   moves the journey wherever the pointer is. Chrome stops chaining at a contain box even when it fits.) */
.panel {
  position: fixed; right: clamp(16px, 2.6vw, 40px); top: 50%;
  width: var(--panel-w); max-height: calc(100vh - 120px); overflow: auto;
  /* (--nudge: a box easing back to its place after a press pinned it, ui/common.js hold) */
  transform: translateY(calc(-50% + var(--nudge, 0px)));
  padding: 20px 16px 14px; border-radius: 16px;
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--edge), var(--shadow);
  opacity: 0; pointer-events: none;
  scrollbar-width: thin; scrollbar-color: #4a4a4a transparent;
}
.panel.is-on { pointer-events: auto; }
/* pinned while a pointer's press settles (ui/common.js hold): the box's top stays where it stood and it grows
   downwards, to --pin-foot above the foot of the screen, then its list scrolls (a phone's sheet keeps its foot too) */
.panel.is-held { top: var(--pin); transform: translateY(var(--nudge, 0px)); max-height: calc(100vh - var(--pin) - var(--pin-foot, 8px)); max-height: calc(100svh - var(--pin) - var(--pin-foot, 8px)); }
.panel h2 { margin: 0; font-size: 1.5rem; line-height: 1.12; font-weight: 600; letter-spacing: -.01em; color: var(--ink); }
.panel h2 em { font-style: italic; font-weight: 500; }
.panel .lede { margin: 14px 4px 0; font-size: .875rem; line-height: 1.45; color: var(--ink-2); max-width: 46ch; }
.panel .small { margin: 12px 4px 0; color: var(--ink-2); font-size: .8125rem; line-height: 1.45; }
.panel a { color: var(--ink); text-decoration-color: var(--ink-3); text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
@media (hover: hover) { .panel a:hover { color: #fff; text-decoration-color: var(--ink); } }

/* the box's header: a cover beside the title, a byline and one action row */
.box__head { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 16px; align-items: center; padding: 0 4px; }
.box__head--plain { display: block; }
.cover { position: relative; width: 88px; height: 88px; border-radius: 6px; overflow: hidden; background: var(--placeholder); box-shadow: 0 8px 20px -10px rgb(0 0 0 / .7), inset 0 0 0 1px var(--edge); display: grid; place-items: center; color: var(--ink-3); }
.cover img, .cover canvas { display: block; width: 100%; height: 100%; object-fit: cover; }
.cover > svg { width: 50%; height: 50%; }
.box__by { margin: 3px 0 0; font-size: .875rem; line-height: 1.35; color: var(--ink-2); }
.box__actions { display: flex; align-items: center; gap: 8px 12px; margin-top: 10px; flex-wrap: wrap; }
.box__aside { font-size: .8125rem; line-height: 1.35; color: var(--ink-2); }

/* the primary button: one per box (Play / Pause, the theater's sound, "Open the sessions") */
.primary {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 16px 0 12px;
  border: 0; border-radius: 999px; background: var(--ink-hi); color: var(--on-hi);
  font-size: .875rem; font-weight: 600; line-height: 1.2; cursor: pointer; text-align: left;
  transition: transform .12s var(--ease), background-color .12s;
}
.primary--text { padding: 0 16px; }
.primary svg { width: 18px; height: 18px; flex: none; }
@media (hover: hover) { .primary:hover { background: #fff; transform: scale(1.03); } }
.primary:active { transform: scale(.98); }
.primary .i-pause { display: none; }
.primary[data-playing] .i-pause { display: block; }
.primary[data-playing] .i-play { display: none; }

/* ---------- track lists (ui/common.js: trackList, bindTracks) ---------- */
.tracks { list-style: none; margin: 14px 0 0; padding: 8px 0 0; border-top: 1px solid var(--rule); display: grid; gap: 2px; }
.row { border-radius: 10px; }
/* (position: relative: the play button's hit area, ::after, covers this line; never the waveform or a link) */
.row__line {
  position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; column-gap: 12px; align-items: center;
  min-height: 56px; padding: 6px 10px 6px 6px; border-radius: 10px; cursor: pointer;
}
.row.has-art .row__line { grid-template-columns: 32px 40px minmax(0, 1fr) auto; }
.row.is-current { background: var(--raise-2); }
@media (hover: hover) { .row:not(.is-current) .row__line:hover { background: var(--raise-1); } }

/* the number becomes play on hover or focus; the playing (or paused) row has a solid round button */
.num { display: grid; place-items: center; width: 32px; height: 32px; }
.num > * { grid-area: 1 / 1; }
.num__n { font-size: .9375rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* (no transform here, ever: it would make the button the hit area's containing block and shrink it) */
.num__btn { width: 32px; height: 32px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--ink); cursor: pointer; opacity: 0; }
.num__btn::after { content: ""; position: absolute; inset: 0; border-radius: 10px; }
.num__btn svg { width: 16px; height: 16px; }
.num__btn .i-pause { display: none; }
.num__btn:focus-visible { opacity: 1; border-radius: 50%; }
.num:has(.num__btn:focus-visible) .num__n { visibility: hidden; }
@media (hover: hover) {
  .row__line:hover .num__btn { opacity: 1; }
  .row__line:hover .num__n { visibility: hidden; }
}
.row.is-current .num__n { color: var(--ink-hi); font-weight: 600; }
.row.is-playing .num__n, .row.is-paused .num__n { visibility: hidden; }
.row.is-playing .num__btn, .row.is-paused .num__btn { opacity: 1; background: var(--ink-hi); color: var(--on-hi); }
.row.is-playing .num__btn .i-play { display: none; }
.row.is-playing .num__btn .i-pause { display: block; }
.num__btn svg { transition: transform .12s var(--ease); }
@media (hover: hover) { .row.is-playing .row__line:hover .num__btn svg, .row.is-paused .row__line:hover .num__btn svg { transform: scale(1.12); } }

.thumb { width: 40px; height: 40px; border-radius: 4px; overflow: hidden; background: var(--placeholder); display: grid; place-items: center; box-shadow: inset 0 0 0 1px var(--edge); color: var(--ink-3); }
.thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.thumb svg { width: 18px; height: 18px; }

.row__text { min-width: 0; }
.row__head { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px; }
.row__title { font-size: .9375rem; line-height: 1.3; font-weight: 500; color: var(--ink); }
.row.is-current .row__title { color: var(--ink-hi); font-weight: 600; }
/* the equaliser after the title while the row plays; "Paused" there while it is paused */
.row__eq { display: none; align-items: flex-end; gap: 2px; height: 12px; }
.row__eq i { width: 3px; height: 100%; border-radius: 1px; background: var(--ink-hi); transform-origin: 50% 100%; transform: scaleY(.45); }
.row.is-playing .row__eq { display: inline-flex; }
.row.is-playing .row__eq i { animation: eq .9s ease-in-out infinite alternate; }
.row.is-playing .row__eq i:nth-child(2) { animation-delay: -.35s; animation-duration: .7s; }
.row.is-playing .row__eq i:nth-child(3) { animation-delay: -.6s; animation-duration: 1.1s; }
@keyframes eq { from { transform: scaleY(.3); } to { transform: scaleY(1); } }
/* (an equaliser in a box that is out of sight does not animate; it scales, so it never needs a layout) */
main .panel[data-w="0.000"] .row__eq i { animation-play-state: paused; }
.row__paused { font-size: .75rem; font-weight: 500; line-height: 1; padding: 3px 6px; border-radius: 4px; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink-3); }
.row__paused[hidden] { display: none; }
.row__sub { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; margin-top: 2px; font-size: .8125rem; line-height: 1.35; color: var(--ink-2); }
.row__sub--wrap { display: block; }
.badge { flex: none; display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: 4px; font-size: .75rem; font-weight: 500; line-height: 1; }
.badge--out { background: var(--badge); color: var(--on-hi); }
.badge--soon { box-shadow: inset 0 0 0 1px var(--ink-3); color: var(--ink-2); }
.row__dur { font-size: .8125rem; color: var(--ink-2); font-variant-numeric: tabular-nums; min-width: 2.6em; text-align: right; }
/* a row's own links (YouTube, Spotify): quiet pills, always visible, above the row's hit area */
.panel a.ext { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 4px; min-height: 28px; padding: 0 10px; border-radius: 999px; font-size: .78rem; font-weight: 500; color: var(--ink); text-decoration: none; box-shadow: inset 0 0 0 1px var(--ink-3); cursor: pointer; }
.ext svg { width: 11px; height: 11px; color: var(--ink-2); }
@media (hover: hover) { .panel a.ext:hover { background: var(--raise-3); box-shadow: inset 0 0 0 1px var(--ink-2); color: var(--ink); } }
.ext:focus-visible { border-radius: 999px; }

/* ---------- the waveform scrubber: the current row only ---------- */
.scrub { padding: 2px 12px 12px; }
.scrub[hidden] { display: none; }
.wave { position: relative; height: 46px; --p: 0%; --h: 0%; }
.wave svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.wave .top { fill: var(--ink-3); }
.wave .ref { fill: var(--ink-3); opacity: .42; }
.wave .done { clip-path: inset(0 calc(100% - var(--p)) 0 0); }
.wave .done .top, .wave .done .ref { fill: var(--ink-hi); }
.wave .hov { display: none; clip-path: inset(0 calc(100% - max(var(--p), var(--h))) 0 min(var(--p), var(--h))); }
.wave .hov .top, .wave .hov .ref { fill: var(--ink-hover); }
.wave.is-hover .hov { display: block; }
/* the control: a native range laid over the bars (Left / Right step a second; Page keys ten) */
.wave input { position: absolute; inset: -4px 0; width: 100%; height: calc(100% + 8px); margin: 0; background: transparent; -webkit-appearance: none; appearance: none; cursor: pointer; opacity: 0; }
.wave input::-webkit-slider-runnable-track { height: 100%; background: transparent; }
.wave input::-moz-range-track { height: 100%; background: transparent; }
.wave input::-webkit-slider-thumb { -webkit-appearance: none; width: 2px; height: 54px; background: transparent; }
.wave input::-moz-range-thumb { width: 2px; height: 54px; border: 0; background: transparent; }
.wave input:focus-visible { outline: none; box-shadow: none; }
/* keyboard focus: a ring round the whole waveform and a visible playhead */
.wave:has(input:focus-visible) { outline: 2px solid var(--ink-hi); outline-offset: 4px; border-radius: 4px; box-shadow: 0 0 0 7px var(--halo); }
.wave__head { position: absolute; top: -3px; bottom: -3px; left: var(--p); width: 2px; margin-left: -1px; border-radius: 1px; background: var(--ink-hi); opacity: 0; pointer-events: none; }
.wave:has(input:focus-visible) .wave__head, .wave.is-hover .wave__head { opacity: 1; }
.wave__t { position: absolute; bottom: 6px; padding: 2px 5px; border-radius: 3px; background: rgb(15 15 15 / .86); color: var(--ink); font-size: .75rem; line-height: 1.1; font-variant-numeric: tabular-nums; pointer-events: none; }
.wave__t--cur { left: 0; }
.wave__t--dur { right: 0; color: var(--ink-2); }
.wave__tip { position: absolute; z-index: 1; bottom: 5px; left: var(--h); transform: translateX(-50%); padding: 2px 5px; border-radius: 3px; background: var(--ink-hi); color: var(--on-hi); font-size: .75rem; line-height: 1.1; font-weight: 600; font-variant-numeric: tabular-nums; pointer-events: none; display: none; }
.wave.is-hover .wave__tip { display: block; }
/* (the time chip the pointer's time reaches gives way to it; Escape hides the pointer's time until it leaves) */
.wave.tip-cur .wave__t--cur, .wave.tip-dur .wave__t--dur { visibility: hidden; }
.wave.is-hover.tip-off .wave__tip { display: none; }
.scrub__note { margin: 8px 0 0; display: flex; gap: 2px 8px; align-items: baseline; flex-wrap: wrap; font-size: .8125rem; line-height: 1.35; color: var(--ink-2); }
.scrub__state { color: var(--ink); font-weight: 500; }
.scrub__state:empty, .scrub__more:empty { display: none; }

/* touch (no hover): a tap anywhere on the row's upper part plays it; the number stays a number */
@media (hover: none) {
  .row__line { cursor: default; }
}

/* ---------- the control bar (Slides' presentation controls): Previous, where you are, Next ---------- */
.bar {
  /* (above the now-playing chip: the stop list opens over it) */
  position: fixed; z-index: 7; left: var(--bar-x); bottom: var(--bar-y); width: 248px; height: 52px;
  display: grid; grid-template-columns: 40px minmax(0, 1fr) 40px; align-items: center; gap: 2px; padding: 6px 4px;
  border-radius: 14px; background: var(--surface); box-shadow: inset 0 0 0 1px var(--edge), var(--shadow);
}
.bar__btn {
  position: relative; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 10px;
  display: grid; place-items: center; background: transparent; color: var(--ink); cursor: pointer;
}
.bar__btn > svg { width: 22px; height: 22px; }
@media (hover: hover) { .bar__btn:hover, .bar__place:hover { background: var(--raise-3); } }
.bar__btn:active { background: #4a4a4a; }
/* the ring stays inside the bar, on its own surface */
.bar__btn:focus-visible, .bar__place:focus-visible { outline-offset: -2px; box-shadow: none; border-radius: 10px; }
/* an end: still focusable (aria-disabled), so the focus a visitor just used stays on the button */
.bar__btn[aria-disabled="true"], .bar__btn[aria-disabled="true"]:hover, .bar__btn[aria-disabled="true"]:active { color: var(--off); cursor: default; background: transparent; }
.bar__where { position: relative; min-width: 0; height: 40px; }
.bar__place {
  width: 100%; height: 100%; display: grid; grid-template-columns: minmax(0, 1fr) 14px; align-items: center; gap: 2px;
  /* (the left padding balances the caret's column, so the words sit in the middle; 116 px for the name:
     every stop's name fits, and app.js fitName sets a long one a little smaller under wider text spacing) */
  padding: 0 4px 0 20px; border: 0; border-radius: 10px; background: transparent; cursor: pointer; text-align: center;
}
.bar__place[aria-expanded="true"] { background: var(--raise-3); }
.bar__text { display: grid; min-width: 0; line-height: 1.2; }
.bar__name { font-size: .875rem; font-weight: 500; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar__count { font-size: .75rem; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar__caret { width: 14px; height: 14px; color: var(--ink-2); transition: transform .15s var(--ease); }
.bar__place[aria-expanded="true"] .bar__caret { transform: rotate(180deg); }
/* the stop list behind the readout (Slides' slide-number menu): opaque, so no box shows through it */
.bar__list { position: absolute; z-index: 1; left: -50px; right: -50px; bottom: calc(100% + 12px); max-height: calc(100vh - 110px); max-height: calc(100svh - 110px); overflow-y: auto; margin: 0; padding: 6px; list-style: none; border-radius: 12px; background: var(--raise-1); box-shadow: inset 0 0 0 1px var(--edge), 0 18px 40px -12px rgb(0 0 0 / .7); }
.bar__list[hidden] { display: none; }
.bar__list a { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; align-items: center; gap: 8px; min-height: 38px; padding: 0 12px 0 8px; border-radius: 8px; color: var(--ink); text-decoration: none; font-size: .875rem; }
@media (hover: hover) { .bar__list a:hover { background: #4a4a4a; } .bar__list a:hover span:last-child { color: var(--ink); } }
.bar__list a span:last-child { color: var(--ink-2); font-size: .75rem; font-variant-numeric: tabular-nums; }
.bar__list svg { width: 14px; height: 14px; visibility: hidden; }
.bar__list a[aria-current="location"] { font-weight: 600; }
.bar__list a[aria-current="location"] svg { visibility: visible; }
.bar__list a:focus-visible { outline-offset: -2px; box-shadow: none; }
.bar__list .bar__apart { margin-top: 5px; padding-top: 5px; border-top: 1px solid #4a4a4a; }
/* tooltips, as Slides shows on its arrows (wide screens with a pointer; visual only). app.js shows one 0.4 s
   into a hover (.is-tip) and keeps it while the pointer is on the arrow, on the tip or on the way between
   them (WCAG 1.4.13); keyboard focus shows it at once; Escape hides it */
.tip {
  position: absolute; z-index: 7; bottom: calc(100% + 12px); left: 0;
  display: none; align-items: center; gap: 8px; padding: 6px 8px 6px 10px; border-radius: 8px;
  background: var(--ink-hi); color: var(--on-hi); font-size: .8125rem; font-weight: 500; white-space: nowrap; line-height: 1.2;
  box-shadow: 0 8px 18px -8px rgb(0 0 0 / .5); pointer-events: none;
}
.bar__btn--next .tip { left: auto; right: 0; }
.tip kbd { font: 600 .75rem/1 inherit; font-family: inherit; padding: 3px 5px; border-radius: 4px; background: rgb(31 31 31 / .1); box-shadow: inset 0 -1px 0 rgb(31 31 31 / .25); }
@media (hover: hover) and (pointer: fine) {
  .bar__btn.is-tip .tip, .bar__btn:focus-visible .tip { display: inline-flex; }
  .bar.tips-off .tip, .bar:has(.bar__list:not([hidden])) .tip { display: none !important; }
}
/* above the now-playing chip while it shows, never over its button or its words */
body:has(#now:not([hidden])) .tip { bottom: calc(100% + 76px); }

/* ---------- now playing (a track from another room): above the bar ---------- */
.now {
  /* (the bar's width; a longer title widens it rather than being cut short: "Fusabowl Rewards promo score",
     also under wider text spacing, WCAG 1.4.12) */
  position: fixed; z-index: 6; left: var(--bar-x); bottom: calc(var(--bar-y) + 60px); width: max-content; min-width: 248px; max-width: min(400px, calc(100vw - 2 * var(--bar-x))); height: 52px;
  display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 10px; align-items: center; padding: 6px 12px 6px 6px;
  border-radius: 14px; background: var(--surface); box-shadow: inset 0 0 0 1px var(--edge), var(--shadow); overflow: hidden;
}
.now[hidden] { display: none; }
.now__btn { width: 40px; height: 40px; border: 0; border-radius: 50%; padding: 0; display: grid; place-items: center; background: var(--ink-hi); color: var(--on-hi); cursor: pointer; }
.now__btn svg { width: 16px; height: 16px; }
.now__text { min-width: 0; display: grid; line-height: 1.2; }
.now__title { font-size: .875rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.now__from { font-size: .75rem; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.now__line { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: rgb(255 255 255 / .1); }
.now__line i { display: block; height: 100%; width: 100%; background: var(--ink-hi); transform-origin: 0 0; transform: scaleX(var(--p, 0)); }

/* the band behind the phone dock (only while a room's sheet is up: app.js sets its opacity) */
.band { display: none; }

.noscript { position: relative; z-index: 9; margin: 40vh auto; width: min(30rem, calc(100% - 32px)); padding: 1rem; background: var(--surface-solid); border-radius: 12px; line-height: 1.45; }

/* ---------- phones: boxes become bottom sheets; the bar docks at the bottom ---------- */
@media (max-aspect-ratio: 4/5), (max-width: 760px) and (min-height: 501px) {
  :root { --panel-w: 100%; }
  /* the dock: 12 px above the foot (and the safe area), 56 high, the band 10 px above it; with the chip, 60 more
     (on the root, so the stacked page's own scroll padding can use it too) */
  :root { --dock: calc(78px + env(safe-area-inset-bottom)); }
  :root:has(#now:not([hidden])) { --dock: calc(138px + env(safe-area-inset-bottom)); }
  /* a sheet's own list scrolls first; at its end a swipe carries on along the journey. It ends in the band:
     no row ever sits under the dock once scrolled to the end */
  .panel { left: 0; right: 0; top: auto; bottom: 0; width: auto; transform: translateY(var(--nudge, 0px)); max-height: calc(44svh + var(--dock)); padding: 8px 12px calc(var(--dock) + 6px); border-radius: 18px 18px 0 0; box-shadow: inset 0 1px 0 var(--edge), 0 -10px 30px -14px rgb(0 0 0 / .6); }
  /* (the sheet's foot lies under the band, the bar and the chip: a row the keyboard reaches there is scrolled
     clear of them, WCAG 2.4.11. The padding alone left it "in view" behind them) */
  .panel { scroll-padding: 8px 0 calc(var(--dock) + 8px); }
  .panel.is-held { max-height: none; }
  .panel::before { content: ""; display: block; width: 36px; height: 4px; margin: 0 auto 12px; border-radius: 2px; background: #4a4a4a; }
  .panel h2 { font-size: 1.3rem; }
  .box__head { grid-template-columns: 64px minmax(0, 1fr); gap: 14px; }
  .cover { width: 64px; height: 64px; border-radius: 5px; }
  .box__by { font-size: .8125rem; margin-top: 1px; }
  .box__actions { margin-top: 8px; }
  .primary { min-height: 34px; }
  .panel .lede { font-size: .84rem; margin-top: 12px; }
  .bar { left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); width: auto; height: 56px; grid-template-columns: 48px minmax(0, 1fr) 48px; padding: 4px; border-radius: 14px; background: #2f2f2f; box-shadow: inset 0 0 0 1px #4a4a4a, var(--shadow); }
  .bar__btn { width: 48px; height: 48px; border-radius: 11px; }
  .bar__where { height: 48px; justify-self: center; width: min(100%, 220px); }
  .bar__list { left: 50%; right: auto; width: min(280px, calc(100vw - 24px)); transform: translateX(-50%); }
  .band { display: block; position: fixed; z-index: 5; left: 0; right: 0; bottom: 0; height: var(--dock); background: var(--surface-solid); opacity: 0; pointer-events: none; }
  .now { left: 12px; right: 12px; width: auto; max-width: none; bottom: calc(12px + env(safe-area-inset-bottom) + 56px + 8px); }
  /* over the office's sessions app the band is the window's own footer (its teal), so no words show round the dock */
  body:has(#sessions.is-open:not(.is-static):not(.is-signoff)) .band { opacity: 1 !important; background: #10282f; box-shadow: 0 -1px 0 #2c5560; }
  .tip { display: none !important; }
}

/* ---------- short landscape screens (a phone on its side): compact boxes on the right, the bar bottom left,
   in the sessions app too (it keeps its place under the thumb; the app's session scrolls clear of it) ---------- */
@media (max-height: 500px) and (min-aspect-ratio: 4/5) {
  :root { --panel-w: min(360px, 46vw); --bar-x: 12px; --bar-y: 12px; }
  .panel { right: 12px; max-height: calc(100vh - 24px); max-height: calc(100svh - 24px); padding: 12px 12px 10px; }
  .panel h2 { font-size: 1.2rem; }
  .box__head { grid-template-columns: 56px minmax(0, 1fr); gap: 12px; }
  .cover { width: 56px; height: 56px; }
  .box__actions { margin-top: 6px; }
  .primary { min-height: 32px; }
  .panel .lede { font-size: .8125rem; margin-top: 10px; }
  .bar { height: 48px; padding: 4px; }
  .now { bottom: calc(var(--bar-y) + 56px); }
}
/* narrower still (a laptop at 300 to 400% zoom: 320 x 256 to 600 x 375 CSS px): a box of 46% of the width
   left its rows and the office's projects running off its edge (WCAG reflow). It takes the width its one
   column needs (all of it at 320), at the top, clear of the bar below */
@media (max-height: 500px) and (min-aspect-ratio: 4/5) and (max-width: 600px) {
  :root { --panel-w: min(300px, calc(100vw - 24px)); }
  main .panel { top: 12px; transform: translateY(var(--nudge, 0px)); max-height: calc(100vh - 84px); max-height: calc(100svh - 84px); }
  body:has(#now:not([hidden])) main .panel { max-height: calc(100vh - 140px); max-height: calc(100svh - 140px); }
  main .panel { --pin-foot: 72px; }
  body:has(#now:not([hidden])) main .panel { --pin-foot: 128px; }
}

/* ---------- reduced motion: the same boxes over still views; every move is a curtain cut ---------- */
.reduced .row__eq i, .reduced .row.is-playing .row__eq i { animation: none; }
.reduced .row.is-playing .row__eq i:nth-child(1) { transform: scaleY(.55); }
.reduced .row.is-playing .row__eq i:nth-child(2) { transform: scaleY(1); }
.reduced .row.is-playing .row__eq i:nth-child(3) { transform: scaleY(.75); }
.reduced .primary, .reduced .primary:hover, .reduced .primary:active { transform: none; transition: none; }
.reduced .bar__caret, .reduced .num__btn svg { transition: none; }
.reduced .row.is-playing .row__line:hover .num__btn svg { transform: none; }
/* the curtain's fade (a cut, or a still changing under reduced motion): boxes come back softly */
.is-revealing main .panel, .is-revealing #sessions, .is-revealing .hello__inner { transition: opacity .26s ease; }

/* ---------- no WebGL (or ?flat): stacked rooms, boxes in flow over the still of the house ---------- */
.no-webgl .room { min-height: 100vh; min-height: 100svh; display: flex; align-items: center; justify-content: flex-end; padding: 10vh clamp(16px, 2.6vw, 40px); height: auto !important; }
.no-webgl .panel { position: relative; inset: auto; transform: none; opacity: 1; pointer-events: auto; max-height: none; transition: opacity .3s ease; }
.no-webgl .room--step { display: none; }
.no-webgl #scene { display: none; }
.no-webgl .stage { background: linear-gradient(#2a74d6, #5aa3ec 55%, #cfe7fb); } /* the vector sky (world/style/palette.js PAL.sky) */
/* the bar stays at the bottom left (the rooms' boxes sit on the right); a focused control scrolls clear of it,
   and of the now-playing chip above it while that shows */
.no-webgl { scroll-padding-bottom: calc(var(--bar-y) + 64px); }
.no-webgl:has(#now:not([hidden])) { scroll-padding-bottom: calc(var(--bar-y) + 124px); }
.no-webgl .bar, .no-webgl .now { background: var(--surface-solid); }
.no-webgl main { padding-bottom: 72px; }
@media (max-aspect-ratio: 4/5), (max-width: 760px) and (min-height: 501px) {
  .no-webgl .room { align-items: flex-end; padding: 46vh 0 0; }
  /* (full width: in the flex row a box would otherwise shrink to its content, as the theater's did) */
  .no-webgl .panel { width: 100%; border-radius: 18px 18px 0 0; max-height: none; padding-bottom: 16px; }
  .no-webgl .bar { background: #2f2f2f; }
  .no-webgl main { padding-bottom: calc(80px + env(safe-area-inset-bottom)); }
  /* (the dock, with the chip when it shows) */
  .no-webgl, .no-webgl:has(#now:not([hidden])) { scroll-padding-bottom: calc(var(--dock) + 8px); }
}
@media (prefers-reduced-motion: reduce) { .veil { transition: opacity .2s linear; } }

/* ---------- the still of the house: first paint, and the backdrop without WebGL ---------- */
/* the 3D lawn view itself (index.html #drawn), centred and cropped like the camera's own view, so the 3D
   picture fades in over it in place. A tiny placeholder of the same picture per shape (blurred) shows until it arrives. */
.drawn { position: absolute; inset: 0; z-index: 1; overflow: hidden; pointer-events: none; transition: opacity .3s ease; }
.drawn img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: cover; object-position: 50% 50%; }
.drawn::before { content: ""; position: absolute; inset: -32px; background: url("data:image/webp;base64,UklGRmYBAABXRUJQVlA4IFoBAACQBwCdASowABQAPtFUo0uoJKMhsAgBABoJbAC7L/DAM95OfQZgF0BKge1x7sIylTHFNDIPlKjP5VIwe8kMjg4rgpENpAAA/t/+ChmvQcoB4t9oejHQHgjL6bxQvHRlczkEY3GQ4aktyXCbOPXxqhd4lMIUA/6MvMwFM6QOgGbCKXJ3lXuiUQABV4TOXJ6UYj/xyQv7syjCrz2X2TuPeLy7BHu7xzlGryA7BK1CKy7NqF9yZu/oD48YaYZDG49uQJlwrsDs6YHnwp6IrTsEqxY1WAMo4hv+Z9nmd5zOT9BainQKP/i3t0eP8dK3SM5CyqIf0lax8MEI+vFTZnyU9174zPkVSJpRiuowwyfw2fUtKzv5OsVgfqq8ux8ujZbaw+dpCT5cNprHMvPI8igp5cqKAdVBf2wwzsMR2GHUS2E+dK0MykNch5GtBtBwoyefBQjqIBUTATHQHaAA") 50% 50% / cover no-repeat; filter: blur(12px); }
@media (max-aspect-ratio: 1599/1000) { .drawn::before { background-image: url("data:image/webp;base64,UklGRgQBAABXRUJQVlA4IPgAAABwBQCdASodABQAPtFUo0uoJKMhsAgBABoJbAB34cQMXVsj1GvZANXK9mEE0deT4hEOQXSOAP5n24u7zMnzAlPC3IqKzSpf0YTlalKv4ORgwrvbb5TFgT0Y1KOciEJwTWwX5bJ7EG/AT5JOvDDsWxRSmkdSicbRxu7Iy0GX/3hOhq08z2dyCNE9KFUxmbnm/ZfFE1ns1wdxy0iT33Ykjwq+DzkYpKminvw+ccScSJ5n7YK6FDonHCKIiO2IB6JtQut8tI08KT2iHCaWh6V5JI/Jr3wWVzGibURoGrroeMj4nbhjak9f/cUHa5jCjFXjNcKBKni/ygAAAA=="); } }
@media (max-aspect-ratio: 799/1000) { .drawn::before { background-image: url("data:image/webp;base64,UklGRqYAAABXRUJQVlA4IJoAAADQAwCdASoQABQAPtFUo0uoJKMhsAgBABoJbACdAYqMz0un6itdSAAA/R+Metnaq5uCeHBlboJlZwFiDQdXFbz7lEepdwtNIklXeU+ORJRx7/uy8polf/LVH/LXP0CgP7V3z66WGvQiXbmS+Jx22OPzRzq9/j9/hYxol0IMYV37NsjB+Gmoenm4ZVUksjr0Z/Pyt8g4Q5lHTgAA"); } }
.world-shown .drawn { opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility 0s linear .3s; }
.no-webgl .drawn { opacity: 1; visibility: visible; }
/* the canvas screens draw the film's title in Jost italic: ask for that face with the page's own text */
.stage::after { content: "a"; position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); font: italic 500 16px "Jost", sans-serif; }
/* no JavaScript: the drawing, the greeting and the <noscript> note; nothing that would need scripts to work */
html:not(.js) .hello__hint, html:not(.js) .bar, html:not(.js) .skip { display: none; }
