/* ================= saying what to do =================
   One plain sentence per phase, in the same place every time. The first build
   had none, and a player watched screens replace each other with a clock
   draining and could not tell what was being asked of them. */
.os-instruct {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
}

/* Your word, for the whole round, held rather than shown. */
.os-peek {
  display: flex;
  align-items: center;
  gap: 10px;
  align-self: flex-start;
  padding: 8px 14px;
  border-radius: 20px;
  border: 1px dashed var(--rule);
  background: transparent;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.os-peek .k {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.os-peek .v {
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 0.08em;
  color: var(--signal);
}
.os-peek:not(.is-open) .v { filter: blur(6px); }
.os-peek.is-open { border-style: solid; border-color: var(--signal); }
.os-peek.is-outsider .v { color: var(--outsider); }
.os-peek.is-outsider.is-open { border-color: var(--outsider); }

/* ================= the intro =================
   Three cards, once. It sits over everything because it is the first thing a
   first-time player must read, and under a skip because it is the last thing a
   fifth-time player wants. */
.os-intro {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  /* Opaque rather than a backdrop-filter. A full-screen blur has to composite
     everything behind it every frame, which is a real cost on the phone this
     is aimed at — and it froze screenshot capture outright while the page
     itself stayed responsive, which is a good sign of how much work it was
     asking for. There is nothing behind this worth seeing anyway. */
  background: color-mix(in srgb, var(--bg) 96%, transparent);
}
.os-intro[hidden] { display: none; }
.os-intro-card {
  width: min(100%, 420px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 24px 22px;
  border-radius: 18px;
  border: 1px solid var(--rule);
  background: var(--panel);
  box-shadow: var(--shadow-card);
}
.os-intro-h {
  font-family: var(--font-display);
  font-size: clamp(24px, 7vw, 32px);
  letter-spacing: 0.04em;
  margin: 0;
  line-height: 1.1;
}
.os-intro-p { margin: 0; color: var(--muted); font-size: 15.5px; line-height: 1.6; }
.os-intro-dots { display: flex; gap: 6px; margin: 2px 0 4px; }
.os-intro-dots i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--rule);
}
.os-intro-dots i.on { background: var(--signal); }

/* ================= the theme control =================
   Same corner and same size as WordCrew's, so the control does not move when
   somebody goes from one game to the other. The sound button will sit to its
   left when Outsider has sounds to mute; it is absent rather than greyed until then,
   because a mute button with nothing to mute advertises something you cannot
   have. */
.page-open-secret .theme-cycle {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--panel);
  color: var(--ink);
  font-size: 15px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  flex: 0 0 auto;
  transition: border-color 0.15s ease, color 0.15s ease;
}
/* The glyph is a half-filled circle drawn in CSS, exactly as WordCrew does it.
   site.css expects an inline SVG inside this button and every other page has
   one; the two game pages carry an empty button instead, so without this rule
   the control renders as a blank disc — which is precisely how it first
   shipped here. */
.page-open-secret .theme-cycle svg { display: none; }
.page-open-secret .theme-cycle::before { content: "\25D0"; }
.page-open-secret .theme-cycle:hover {
  border-color: var(--signal);
  color: var(--signal);
  transform: none;
}
.page-open-secret .theme-cycle:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

/* ================= arriving by a link =================
   The tabs are hidden entirely in this case rather than pre-selected. Somebody
   who followed an invite has already chosen; offering "create a room" beside
   the room they were invited to is a question they did not ask, and the wrong
   answer to it loses them the game they were joining. */
.os-invited {
  font-size: 15px;
  color: var(--ink);
  background: color-mix(in srgb, var(--signal) 12%, transparent);
  border: 1px solid var(--signal);
  border-radius: 12px;
  padding: 11px 14px;
  margin: 0;
}
.os-invited b {
  font-family: var(--font-mono);
  letter-spacing: 0.16em;
  color: var(--signal);
}

/* ================= the toast =================
   Overlaid and self-dismissing. The first version said "Link copied" into a
   visually-hidden live region only, so on the one device where copying
   actually fails — a phone on plain http, where the clipboard API is absent —
   a sighted player pressed the button and nothing whatsoever happened. */
.os-toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translate(-50%, 12px);
  z-index: 60;
  max-width: min(92vw, 420px);
  padding: 12px 18px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid var(--signal);
  color: var(--ink);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  font-size: 14.5px;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease, transform 180ms ease;
}
.os-toast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* ================= plumbing ================= */

/* SPACING IS A LAYOUT, NOT A COLLECTION OF MARGINS.
   The stage had a gap and the screens inside it did not, so every control
   inside a screen sat directly against the next one — a button touching a pill
   touching a note. One rule per level, so nothing depends on whichever element
   happens to carry a margin of its own. */
.os-screen { display: flex; flex-direction: column; gap: 14px; }
.os-screen[hidden] { display: none; }
.os-phase { display: flex; flex-direction: column; gap: 12px; }
.os-phase[hidden] { display: none; }
/* A heading or an eyebrow belongs to the thing under it, so it sits closer to
   it than the gap would put it. */
.os-screen .os-eyebrow + *, .os-phase .os-eyebrow + * { margin-top: -6px; }
.os-note { font-size: 13px; color: var(--muted); margin: 0; line-height: 1.5; }
.os-error { color: var(--outsider); font-size: 14px; margin: 0; min-height: 1.2em; }

/* Announcements for screen readers only — the roster changes as people arrive
   and a sighted player sees it; a blind one is told. */
.os-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .page-open-secret, .page-open-secret * { transition: none !important; animation: none !important; }
}

/* The rule an answer has to obey, under the question and staying there. */
.os-rule {
  margin: 6px 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

