/* =====================================================================
   The arc's dialogs

   Every window js/apps/sacrifice.js creates used to be given
   `height: <n>px` as an inline style with a `.content` set to `height: 100%`
   underneath it, so a content box asking for the full 100% was always taller
   than the space the title bar left it. It overflowed behind that bar and
   `.window .content`'s `overflow: auto` turned that into a scrollbar.
   The pre-install warning was the worst of the six — 400x180 holding about
   223px of text — and it is the one a player meets first.

   The fix is the idiom #trash already uses: the window is a flex column, the
   content is a `flex: 1 1 auto` child with `min-height: 0`, and the height
   comes from the text. That kills the scrollbar and the strip of window
   background an explicit height leaves at the bottom, in one move.

   Where a stable size genuinely matters — a progress window must not grow a
   line at a time while it fills — it is spelt `min-height`, never `height`.
   The window can then still grow rather than clip if the copy is ever edited.

   Geometry lives here rather than inline because an inline style cannot be
   overridden by a stylesheet at all, and these dialogs were sitting at
   400px wide at `left: 40%` on a phone with most of themselves off the side.
   The colours are deliberately left inline where they already were: the yellow
   System Alert bar is the safeguard's whole disguise, and inline is what keeps
   it yellow under both desktop themes, which restyle `.window .title` with
   more specificity than anything in this file has.
   ===================================================================== */

.window.purge-dialog {
  display: flex;
  flex-direction: column;
}

/* The whole bug, in three declarations. */
.window.purge-dialog > .content {
  height: auto;
  flex: 1 1 auto;
  min-height: 0;
}

/* --- The two door dialogs, which are one window wearing two faces --- */
#purge-pre-warning,
#purge-invitation {
  width: 400px;
  top: 35%;
  left: 40%;
}
#purge-pre-warning > .content,
#purge-invitation > .content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 20px;
  text-align: center;
}
.purge-door-lines {
  margin: 0 0 15px 0;
  font-family: "VT323", monospace;
  font-size: 18px;
  font-weight: bold;
}
.purge-actions {
  display: flex;
  gap: 15px;
}
/* Unchanged from the inline padding these buttons already carried. Cancel and
   Install are the same button but for the weight, which is the one place PURGE
   is allowed to lean on the visitor. */
.purge-actions button {
  padding: 6px 16px;
}
.purge-actions button.purge-btn-strong {
  font-weight: bold;
}

/* --- RootBeer's cheerful five seconds --- */
#rootbeer-installer {
  width: 420px;
  top: 30%;
  left: 38%;
  /* Holds the four steps, the bar, and the finish block that unhides at the
     end, so nothing moves while it runs. */
  min-height: 330px;
}
#rootbeer-installer > .content {
  display: flex;
  flex-direction: column;
  padding: 18px;
}

/* --- PURGE's nine and a half seconds --- */
#purge-installer {
  width: 400px;
  top: 30%;
  left: 40%;
  min-height: 260px;
}
#purge-installer > .content {
  display: flex;
  flex-direction: column;
  padding: 15px;
}
/* The log is meant to clip its oldest lines and keep the newest at the bottom,
   and it never did: a `flex-grow: 1` child still has `min-height: auto`, so
   twenty lines pushed the box past its parent instead of scrolling inside it.
   That is what put a scrollbar on the horror sequence. */
#install-logs {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}

/* --- The eighteen fake crash windows --- */
/* Position and colour stay inline on these: both are randomised per window, so
   they are values rather than styling. Size is not, and belongs here. */
.window.purge-popup {
  width: 300px;
  min-height: 140px;
}
.window.purge-popup > .content {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 15px;
  text-align: center;
}

/* --- The post-install alarm, and PURGE asking for the dog --- */
#purge-warning {
  width: 400px;
  top: 35%;
  left: 42%;
}
#purge-warning > .content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 20px;
  text-align: center;
}
#purge-evil {
  width: 420px;
  top: 40%;
  left: 45%;
  /* A floor rather than a height, so the typewriter fills a box that is
     already the right size instead of growing the window three times. */
  min-height: 220px;
}
#purge-evil > .content {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 24px;
}

/* Both breakpoints in css/responsive.css place `.window` by class, and
   `.window.purge-dialog` outranks that, so the shared mobile placement has to
   be restated here — the same thing css/responsive.css itself has to do by id
   for #internet, #community and #journal. Nothing restates a height: every one
   of these is content-sized or floored, and `.window`'s own `max-height: 80vh`
   at this breakpoint is the backstop. */
@media (max-width: 768px) {
  #purge-pre-warning,
  #purge-invitation,
  #purge-warning,
  #purge-evil,
  #rootbeer-installer,
  #purge-installer {
    left: 7.5%;
    top: 60px;
    width: 85%;
  }
}

@media (max-width: 600px) {
  #purge-pre-warning,
  #purge-invitation,
  #purge-warning,
  #purge-evil,
  #rootbeer-installer,
  #purge-installer {
    left: 3%;
    top: 50px;
    width: 94%;
  }
  /* The one place a floor has to come off. 330px plus a wrapped RootBeer
     paragraph is taller than a short phone allows, and `.window`'s
     `min-height: 200px` at this width is floor enough. */
  #rootbeer-installer,
  #purge-installer,
  #purge-evil {
    min-height: 0;
  }

  /* RootBeer's four steps are dot leaders with a fixed number of dots, and the
     longest is 53 characters. At the inline 16px they were laid out in, that is
     339px of text in the 259px this window has at 320px, so the tail of every
     line — including `granted`, which is the safeguard coming down and the one
     word in the four that matters — sat outside the window and turned .content
     into a horizontal scroller.

     Both declarations need !important because js/apps/sacrifice.js writes the
     font and the white-space inline on #rootbeer-steps, and an inline style is
     unreachable from a stylesheet otherwise.

     12px is small, and it is the right kind of small: at 0.4em a character is
     4.8px, so 53 of them come to 254px inside the 267px this padding leaves,
     and all four leaders land whole with their results in one column. That
     column is the entire visual joke and half its point — `granted` has to be
     readable as the odd one out. Wrapping instead, at any larger size, breaks
     the alignment and pushes the results onto lines of their own. pre-wrap is
     kept anyway as the backstop, the same trade .secret-content now makes in
     css/trash.css: a line that wraps has still been read, and a line that
     overflows has not. */
  #rootbeer-installer > .content {
    padding: 14px;
  }

  #rootbeer-steps {
    font-size: 12px !important;
    white-space: pre-wrap !important;
  }
}

/* =====================================================================
   🩸 Sacrifice Ritual Animation
   ===================================================================== */

.sacrifice-icon { transition: filter 0.3s ease; }
.sacrifice-icon.sacrifice-receiving { filter: drop-shadow(0 0 15px rgba(255,0,0,0.8)); }

#sacrifice-overlay {
  position: fixed;
  top: 0; left: 0;
  width: 100vw; height: 100vh;
  z-index: 99999;
  pointer-events: all;
  background: rgba(80,0,0,0);
  transition: background 1s ease;
  overflow: hidden;
}
#sacrifice-overlay.active    { background: rgba(80,0,0,0.7); }
#sacrifice-overlay.aftermath { background: rgba(0,0,0,0.95); transition: background 1.5s ease; }
#sacrifice-overlay.fade-out  { opacity: 0; transition: opacity 2s ease; }

.sacrifice-blood-rain {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  overflow: hidden;
}
.blood-drop {
  position: absolute;
  top: -40px;
  background: linear-gradient(to bottom, rgba(139,0,0,0.9), rgba(200,0,0,0.6));
  border-radius: 0 0 50% 50%;
  animation: bloodFall linear forwards;
}
@keyframes bloodFall {
  from { top: -40px; opacity: 1; }
  to   { top: 110vh;  opacity: 0.4; }
}

.sacrifice-vignette {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  box-shadow: inset 0 0 150px rgba(139,0,0,0.8), inset 0 0 300px rgba(80,0,0,0.5);
}

.sacrifice-glitch-text {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%,-50%);
  font-family: "VT323", monospace;
  font-size: 48px;
  color: #ff0000;
  text-shadow: 3px 3px 0 #8b0000, -2px -2px 0 #ff4444, 0 0 20px rgba(255,0,0,0.6);
  letter-spacing: 4px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
  text-align: center;
}

.sacrifice-final-message {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%,-50%);
  font-family: "VT323", monospace;
  font-size: 24px;
  color: #8b0000;
  text-align: center;
  line-height: 1.8;
  opacity: 0;
  transition: opacity 1s ease;
  white-space: pre-wrap;
}

/* Phase three quotes Dash. Dropping the blood red for a pale grey changes
   the voice before the words are even readable: this line is a person. */
.sacrifice-final-message.sacrifice-quote {
  color: #c9c9c9;
  text-shadow: 0 0 12px rgba(255,255,255,0.25);
}

/* The fake install popups and the post-install SYSTEM WARNING carry this class
   from js/apps/sacrifice.js. It had no rule at all, so the alarm never landed.
   steps(2, end) keeps it a hard on/off rather than a soft pulse, and only the
   framing flashes so eighteen of these at once stay readable. */
@keyframes warningBlink {
  0%, 100% {
    border-color: #000;
    box-shadow: 5px 5px 0 rgba(0,0,0,0.9);
  }
  50% {
    border-color: #ff3b30;
    box-shadow: 5px 5px 0 rgba(0,0,0,0.9), 0 0 22px rgba(255,59,48,0.85);
  }
}
.window.warning-blink { animation: warningBlink 0.7s steps(2, end) infinite; }

@keyframes sacrificeShake {
  0%, 100% { transform: translate(0,0); }
  10%  { transform: translate(-4px, 2px); }
  20%  { transform: translate(3px, -3px); }
  30%  { transform: translate(-2px, 4px); }
  40%  { transform: translate(4px, -1px); }
  50%  { transform: translate(-3px, -3px); }
  60%  { transform: translate(2px, 4px); }
  70%  { transform: translate(-4px, -2px); }
  80%  { transform: translate(3px, 3px); }
  90%  { transform: translate(-1px, -4px); }
}
body.sacrifice-shake { animation: sacrificeShake 0.15s infinite; }

/* The fight is css/duel.css now, and the box across the foot of it is
   css/dialogue.css. Two things in this file are still borrowed by both:
   .sacrifice-vignette above and the .blood-drop keyframes, which is why neither
   may be moved out of here or scoped to the ritual's own overlay. */
