/* Read waiting-room ownership: loading, failure, and the initial dark room. */

/* #error-panel adopts the kit .cl-notice (box + left-rule). These journey-only
   rules keep what the atom does not carry: the roomier read-view padding, the
   failed-state red border, and the .waiting state-class border recolor (toggled by
   read-loading-shell.js). */
.error-panel.cl-notice {
  border-color: rgba(179, 54, 42, 0.4);
  border-left: 4px solid var(--red);
  margin: 0 0 18px;
  padding: 30px;
  text-align: left;
}

.error-panel.cl-notice.waiting {
  border-color: rgba(176, 129, 38, 0.38);
  border-left-color: var(--yellow);
}

.error-panel .decision-actions {
  margin-top: 16px;
}

/* ===========================================================================
   THE DARK WAITING ROOM — the full-screen "lights dim" threshold (body.read-waiting)
   Brand law: the in-progress read is a THRESHOLD, so before the first phase lands
   the whole page FADES DOWN to a dark room (like the marketing set) and the living
   reader roster shows on it. read-loading-shell.js adds body.read-waiting and
   injects #read-waiting-room (the dark backdrop with the rotating marketing-set
   images). The existing inline #stage-reading card is LIFTED (position:fixed) onto
   that backdrop and centered — it keeps every engine hook id, so the roster /
   progress / elapsed render unchanged. When the first verdict lands the JS drops
   read-waiting and adds reading-room-live ("lights up"): the card snaps back to its
   inline grid slot beside the revealed phase (the LIVING READ STATE block below).
   Depth = hard ink offset, never blur; lamp gold (--gold-soft) is legal — dark room.
   Every fade/rotation is held under prefers-reduced-motion (bottom of this block).
   =========================================================================== */

body.read-waiting {
  overflow: hidden;
}

/* The full-screen dark ground. It sits below the sticky app-header; the header is
   re-toned by 02-header.css and must remain a real navigation surface during the
   wait. The --screen ground + a dark gradient is the FLOOR: even if the marketing
   set images are missing (different deploy root), the room still reads as a
   tasteful dark room. */
.read-waiting-room {
  background:
    radial-gradient(ellipse 120% 90% at 70% 30%, rgba(201, 168, 106, 0.05) 0%, transparent 55%),
    linear-gradient(160deg, #141815 0%, var(--screen) 45%, #0b0d0c 100%);
  inset: 0;
  opacity: 0;
  pointer-events: none;
  position: fixed;
  z-index: calc(var(--z-dialog) - 1);
}

/* The backdrop only paints while the lights are dimmed. Scoping its visibility to
   body.read-waiting (rather than only removing the node) means the lit inline read
   can never be left under a stray full-screen overlay if the node lingers. */
body.read-waiting .read-waiting-room {
  animation: read-room-in 0.6s ease forwards;
}
body:not(.read-waiting) .read-waiting-room:not(.lights-up) { display: none; }
/* Lights up (read finished): the dark backdrop fades out over ~3s, revealing the
   finished read underneath; liftLightsUp removes the node when the fade ends. */
.read-waiting-room.lights-up { opacity: 0; transition: opacity 3s ease; pointer-events: none; }

/* The two rotating marketing-set layers. Each is the dark-gradient-over-image
   composite the marketing pages use (darken left, image right), masked to a soft
   focus so it reads as a lit set edge, not a flat photo. They cross-fade on a slow
   loop so the room SUBTLY rotates between the two set images. Background images are
   referenced at the app's same-origin /brand/ path (served from the marketing
   dist root); if absent the layers are simply invisible over the dark floor. */
.read-waiting-set {
  background-position: center, 74% 38%;
  background-repeat: no-repeat;
  background-size: cover;
  filter: grayscale(0.14) saturate(0.6) contrast(0.92) brightness(0.72);
  inset: 0;
  -webkit-mask-image: radial-gradient(ellipse 92% 74% at 76% 40%, #000 0%, rgba(0, 0, 0, 0.6) 42%, transparent 82%);
  mask-image: radial-gradient(ellipse 92% 74% at 76% 40%, #000 0%, rgba(0, 0, 0, 0.6) 42%, transparent 82%);
  opacity: 0;
  position: absolute;
}

.read-waiting-set-a {
  background-image:
    linear-gradient(90deg, rgba(11, 13, 12, 0.98) 0%, rgba(11, 13, 12, 0.78) 42%, rgba(11, 13, 12, 0.3) 100%),
    url("/brand/physical-script-stack.webp");
  animation: read-set-rotate-a 26s ease-in-out infinite;
}

.read-waiting-set-b {
  background-image:
    linear-gradient(90deg, rgba(11, 13, 12, 0.98) 0%, rgba(11, 13, 12, 0.78) 42%, rgba(11, 13, 12, 0.3) 100%),
    url("/brand/physical-marked-page.webp");
  animation: read-set-rotate-b 26s ease-in-out infinite;
}

/* The room's own grain — texture on the dark floor so it is never a flat black. */
.read-waiting-grain {
  background-image: var(--grain);
  inset: 0;
  opacity: 0.05;
  pointer-events: none;
  position: absolute;
}

/* Fade the read shell DOWN behind the room (the "lights dim"); the lifted card is
   re-raised above it below, so only the surrounding read chrome dims. */
body.read-waiting #report-body,
body.read-waiting .report-toc {
  opacity: 0.12;
  transition: opacity 0.5s ease;
}

/* Lift the inline card onto the dark backdrop while it keeps its read-shell slot. */
body.read-waiting #stage-reading:not(.hidden) {
  align-items: center;
  display: grid;
  inset: 0;
  justify-items: center;
  margin: 0;
  padding: clamp(24px, 6vw, 64px);
  position: fixed;
  z-index: var(--z-dialog);
  animation: read-room-in 0.7s ease 0.05s both;
}

/* Drop the inline-walk sticky pin while lifted (it would otherwise fight fixed). */
body.read-waiting[data-read-mode="walking"] #stage-reading:not(.hidden) {
  top: 0;
}

/* MODAL ABOVE THE READING ROOM. The lifted reading shell sits at --z-dialog (1000)
   and the header at --z-dialog + 1 (1001) — the SAME tier as a .cl-dialog, so any
   modal opened during the read (e.g. "How this works") would tie on z-index and lose
   to the later DOM sibling, painting BEHIND the dark room. Raise every dialog opened
   while the reading room is up to --z-dialog + 2 (1002) so it clears both. */
body.read-waiting .cl-dialog:not(.hidden) {
  z-index: calc(var(--z-dialog) + 2);
}

/* In the full-screen room the card is the dark-room panel itself: same --screen
   ground + grain + ink offset as the inline lit card, sized as a centered slab. */
body.read-waiting .stage-reading-card {
  background: var(--screen);
  border: 2px solid var(--screen);
  box-shadow: var(--offset);
  color: var(--on-screen);
  gap: clamp(16px, 3vw, 24px);
  grid-template-columns: minmax(0, 1fr);
  max-width: 680px;
  padding: clamp(28px, 6vw, 56px);
  position: relative;
  width: min(100%, 680px);
}

body.read-waiting .stage-reading-card::before {
  background-image: var(--grain);
  content: "";
  inset: 0;
  opacity: 0.05;
  pointer-events: none;
  position: absolute;
}

body.read-waiting .stage-reading-card > * { position: relative; z-index: 1; }

/* Re-tone the room copy/roster onto the dark ground (mirrors the inline lit card
   so the lights-up handoff is seamless — same dark room, just docked inline). */
body.read-waiting .stage-reading-kicker { color: var(--gold-soft); }
body.read-waiting .stage-reading-line { color: var(--on-screen); }
body.read-waiting .stage-reading-copy { color: var(--screen-dim); }
body.read-waiting .stage-reading-meta { color: var(--screen-dim); }
body.read-waiting .stage-reading-dot {
  background: var(--gold-soft);
  animation: room-pulse 1.4s ease-in-out infinite;
}

body.read-waiting .stage-reading-steps {
  background:
    radial-gradient(circle at 50% 50%, rgba(201, 168, 106, 0.28), transparent 36%),
    linear-gradient(120deg, rgba(240, 237, 226, 0.04), rgba(201, 168, 106, 0.14), rgba(240, 237, 226, 0.04));
  border: 1px solid var(--screen-hairline);
  min-height: clamp(138px, 20vw, 176px);
  overflow: hidden;
  padding: 0;
  position: relative;
}
body.read-waiting .stage-reading-steps::before {
  background:
    linear-gradient(90deg, transparent 0 14%, rgba(201, 168, 106, 0.2) 50%, transparent 86%),
    repeating-linear-gradient(
      to bottom,
      rgba(240, 237, 226, 0.08) 0,
      rgba(240, 237, 226, 0.08) 1px,
      transparent 1px,
      transparent 9px
    );
  border: 1px solid rgba(201, 168, 106, 0.5);
  box-shadow:
    0 0 0 1px rgba(16, 20, 18, 0.72),
    0 0 34px rgba(201, 168, 106, 0.22);
  content: "";
  inset: 24px clamp(34px, 10vw, 82px);
  position: absolute;
  transform: rotate(-1.5deg);
  animation: reveal-breathe 3.8s ease-in-out infinite;
}
body.read-waiting .stage-reading-steps::after {
  background:
    linear-gradient(90deg, transparent, rgba(240, 237, 226, 0.2), transparent),
    linear-gradient(180deg, transparent 0 46%, rgba(201, 168, 106, 0.18) 50%, transparent 54% 100%);
  content: "";
  inset: 0;
  position: absolute;
  transform: translateX(-100%);
  animation: reveal-sweep 4.6s ease-in-out infinite;
}

@keyframes reveal-breathe {
  0%, 100% { opacity: 0.72; transform: rotate(-1.5deg) scale(0.985); }
  50% { opacity: 1; transform: rotate(-1.5deg) scale(1.015); }
}

@keyframes reveal-sweep {
  0%, 22% { transform: translateX(-100%); opacity: 0; }
  45% { opacity: 1; }
  78%, 100% { transform: translateX(100%); opacity: 0; }
}
body.read-waiting .stage-reading-steps li.room-row {
  align-content: center;
  align-items: center;
  border-top: 0;
  display: grid;
  gap: 8px 14px;
  grid-template-columns: minmax(0, 1fr) auto;
  inset: 22px clamp(34px, 10vw, 82px);
  justify-items: center;
  overflow: hidden;
  padding: 0;
  position: absolute;
  text-align: center;
  z-index: 1;
}
body.read-waiting .room-num {
  color: var(--screen-dim);
  font-family: var(--brand);
  font-size: var(--fs-slug);
  font-weight: var(--fw-bold);
  grid-column: 1 / -1;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
body.read-waiting .room-name {
  color: var(--on-screen);
  font-family: var(--brand);
  font-size: clamp(0.82rem, 1.6vw, 1rem);
  font-weight: var(--fw-bold);
  grid-column: 1 / -1;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
body.read-waiting .room-status {
  color: var(--gold-soft);
  font-family: var(--brand);
  font-size: var(--fs-micro);
  grid-column: 1 / -1;
  letter-spacing: 0.14em;
  text-align: center;
  text-transform: uppercase;
}
body.read-waiting .room-tick {
  background: var(--gold-soft);
  border-radius: 0;
  box-shadow: 0 0 16px rgba(201, 168, 106, 0.62);
  display: inline-block;
  grid-column: 1 / -1;
  height: 9px;
  justify-self: center;
  transform: rotate(45deg);
  width: 9px;
}
body.read-waiting .room-row.is-waiting .room-name { color: var(--on-screen); }
body.read-waiting .room-row.is-reading .room-num,
body.read-waiting .room-row.is-reading .room-name,
body.read-waiting .room-row.is-reading .room-status { color: var(--gold-soft); }

body.read-waiting .room-row.is-waiting .room-num,
body.read-waiting .room-row.is-waiting .room-status { color: var(--gold-soft); }

body.read-waiting .room-row.is-waiting .room-name { color: var(--on-screen); }

/* ---------- The SSE roster (read-v2) ----------
   Once the stream's roster event lands, #stage-reading-steps flips to [data-roster]
   and paints one quiet row per pass — the server's label + a lifecycle word
   (waiting / reading / done / did-not-finish). Rows stack as a normal ruled list
   (the pre-roster single suspense object above stays absolutely centered). No
   verdict colors ever: the only lit row is the one reading. */
body.read-waiting .stage-reading-steps[data-roster] {
  background: none;
  min-height: 0;
  padding: 6px 0;
}
body.read-waiting .stage-reading-steps[data-roster]::before,
body.read-waiting .stage-reading-steps[data-roster]::after { display: none; }
body.read-waiting .stage-reading-steps[data-roster] li.room-row {
  border-top: 1px solid var(--screen-hairline);
  display: grid;
  gap: 0 14px;
  grid-template-columns: minmax(0, 1fr) auto;
  inset: auto;
  justify-items: start;
  overflow: visible;
  padding: 9px 14px;
  position: static;
  text-align: left;
}
body.read-waiting .stage-reading-steps[data-roster] li.room-row:first-child { border-top: 0; }
body.read-waiting .stage-reading-steps[data-roster] .room-name {
  font-size: var(--fs-slug);
  grid-column: 1;
  letter-spacing: 0.08em;
}
body.read-waiting .stage-reading-steps[data-roster] .room-status {
  color: var(--screen-dim);
  grid-column: 2;
  justify-self: end;
  text-align: right;
}
body.read-waiting .stage-reading-steps[data-roster] .room-row.is-waiting .room-name { color: var(--screen-dim); }
body.read-waiting .stage-reading-steps[data-roster] .room-row.is-reading .room-name,
body.read-waiting .stage-reading-steps[data-roster] .room-row.is-reading .room-status { color: var(--gold-soft); }

/* The P.A.S.S. panel (Dan V2 UX #4): the single static state that REPLACES the
   per-pass roster — one centered block, a calm headline over the rooms as a spaced
   marquee, with no lit "reading" row for the writer to watch advance toward a verdict. */
body.read-waiting .stage-reading-steps[data-roster] li.room-row--pass {
  border-top: 0;
  gap: 10px 0;
  grid-template-columns: 1fr;
  justify-items: center;
  padding: 20px 16px;
  text-align: center;
}
body.read-waiting .stage-reading-steps[data-roster] .room-row--pass.is-reading .room-status {
  color: var(--screen-dim);
  grid-column: 1;
  justify-self: center;
  letter-spacing: 0.16em;
  text-align: center;
  text-transform: uppercase;
}
/* Each room's initial lit in the mark's lamp gold, bold against the dim marquee,
   so the P.A.S.S. acronym resolves on sight. Scoped to the marquee element (not
   the body state) so the same treatment holds through the lights-up fade. */
.stage-reading-steps .room-row--pass .room-status .room-initial {
  color: var(--gold-soft);
  font-weight: var(--fw-bold);
}
body.read-waiting .stage-reading-steps[data-roster] .room-row.is-reading {
  animation: active-step-pulse-dark 2.8s ease-in-out infinite;
}
body.read-waiting .stage-reading-steps[data-roster] .room-row.is-done .room-name { color: var(--on-screen); }
body.read-waiting .stage-reading-steps[data-roster] .room-row.is-failed .room-name,
body.read-waiting .stage-reading-steps[data-roster] .room-row.is-failed .room-status {
  color: var(--screen-dim);
  text-decoration: line-through;
}
@keyframes active-step-pulse-dark {
  0%, 100% { background: transparent; }
  50% { background: rgba(201, 168, 106, 0.10); }
}
@media (prefers-reduced-motion: reduce) {
  body.read-waiting .stage-reading-steps[data-roster] .room-row.is-reading { animation: none; }
}

/* The lifted room fades back DOWN as the lights come up — when read-waiting drops
   and reading-room-live takes over, the inline block paints the docked lit card. */
body.reading-room-live:not(.read-waiting) .stage-reading-card {
  animation: read-room-in 0.5s ease both;
}

/* Lights down + rotation are MOTION: hold them all under reduced-motion. The room
   is still a legible dark room (one static set image, full opacity, no fades). */
@media (prefers-reduced-motion: reduce) {
  body.read-waiting .read-waiting-room { animation: none; opacity: 1; }
  .read-waiting-set-a { animation: none; opacity: 0.16; }
  .read-waiting-set-b { animation: none; opacity: 0; }
  body.read-waiting #report-body,
  body.read-waiting .report-toc { transition: none; }
  body.read-waiting #stage-reading:not(.hidden) { animation: none; }
  body.read-waiting .stage-reading-dot { animation: none; }
  body.read-waiting .stage-reading-steps::before,
  body.read-waiting .stage-reading-steps::after { animation: none; }
  body.reading-room-live:not(.read-waiting) .stage-reading-card { animation: none; }
}

@keyframes read-room-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Slow cross-fade between the two marketing set images so the room subtly rotates
   (offset phases: while A holds lit, B is dark, and they trade). */
@keyframes read-set-rotate-a {
  0%, 42% { opacity: 0.16; }
  50%, 92% { opacity: 0; }
  100% { opacity: 0.16; }
}
@keyframes read-set-rotate-b {
  0%, 42% { opacity: 0; }
  50%, 92% { opacity: 0.16; }
  100% { opacity: 0; }
}
