/* ══════════════════════════════════════════════════════════════════
   INTRO OVERLAY — full-screen opening sequence
   Rebuilt from the StudyIMS reel as real DOM + CSS (no video).

   Three beats, <= 6s total, then it waits for the user to swipe up /
   click / press a key, and slides away.

   Fail-open contract (important):
   index.html inlines `.ims-intro{display:none}` in <head>. The rule that
   SHOWS the overlay lives in THIS file, so if this stylesheet ever fails
   to load the overlay stays hidden and the site is still usable. Never
   move the show rule into the inline block.
   ══════════════════════════════════════════════════════════════════ */

/* Armed by the inline <head> script (skips /u/* profile links, and picks
   full vs. short mode from the localStorage view counter). */
html.ims-intro-armed .ims-intro { display: block; }
html.ims-intro-armed,
html.ims-intro-armed body { overflow: hidden; }

.ims-intro {
  position: fixed;
  inset: 0;
  z-index: 100000;            /* above the skip-link (10000) and toasts (9999) */
  /* Fills the viewport even when mobile browser chrome is showing. */
  height: 100dvh;
  overscroll-behavior: none;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  cursor: pointer;
}
/* The dialog holds focus so screen readers announce it, but it is not
   keyboard-reachable, so an outline here would only ever be visual noise. */
.ims-intro:focus { outline: none; }

/* Screen-reader summary: the beats reveal over ~6s, so the whole gist is
   also exposed as one block that assistive tech can read immediately. */
.ims-intro-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── The sheet: everything that slides away on exit ────────────── */
.ims-intro-sheet {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background:
    radial-gradient(120% 75% at 50% 8%,  rgba(53,200,255,0.07), transparent 62%),
    radial-gradient(105% 65% at 50% 100%, rgba(155,109,255,0.07), transparent 60%),
    linear-gradient(168deg, #030913 0%, #050d1e 46%, #01040a 100%);
  will-change: opacity, transform;
}

/* Faint starfield — two offset dot layers, no image request. */
.ims-intro-sheet::before {
  content: '';
  position: absolute;
  inset: -10%;
  background-image:
    radial-gradient(1.4px 1.4px at 18% 22%, rgba(180,220,255,0.42), transparent 100%),
    radial-gradient(1.2px 1.2px at 72% 14%, rgba(180,220,255,0.30), transparent 100%),
    radial-gradient(1.6px 1.6px at 41% 63%, rgba(180,220,255,0.26), transparent 100%),
    radial-gradient(1.2px 1.2px at 87% 48%, rgba(180,220,255,0.34), transparent 100%),
    radial-gradient(1.3px 1.3px at 29% 85%, rgba(180,220,255,0.24), transparent 100%),
    radial-gradient(1.1px 1.1px at 62% 92%, rgba(180,220,255,0.30), transparent 100%),
    radial-gradient(1.5px 1.5px at 8%  57%, rgba(180,220,255,0.22), transparent 100%),
    radial-gradient(1.2px 1.2px at 94% 78%, rgba(180,220,255,0.26), transparent 100%);
  opacity: 0.6;
  pointer-events: none;
}

/* ── ECG rails (static — the animated pulse was the one expensive paint) ── */
.ims-intro-ecg {
  position: absolute;
  left: -2%;
  width: 104%;
  height: clamp(46px, 9vh, 92px);
  pointer-events: none;
}
.ims-intro-ecg-top    { top: 6%; }
.ims-intro-ecg-bottom { bottom: 6%; }

.ims-intro-ecg .ecg-base {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ims-intro-ecg-top    .ecg-base { stroke: rgba(120, 90, 200, 0.22); }
.ims-intro-ecg-bottom .ecg-base { stroke: rgba(40, 150, 200, 0.22); }

/* ── Panel stage ───────────────────────────────────────────────── */
.ims-intro-stage {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 620px;
  padding: 0 1.5rem;
  /* Reserve the tallest panel's height so nothing jumps between beats. */
  min-height: 66vh;
  display: grid;
}

.ims-intro-panel {
  grid-area: 1 / 1;          /* all panels stacked in one cell */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s ease, visibility 0s linear 0.5s;
}
.ims-intro-panel.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.55s ease, visibility 0s;
}

/* Every child of an active panel plays this once. Per-element delays below
   are what actually choreograph each beat — the JS only flips .is-active. */
@keyframes imsIntroRise {
  from { opacity: 0; transform: translate3d(0, 16px, 0); }
  to   { opacity: 1; transform: none; }
}
@keyframes imsIntroFade {
  from { opacity: 0; transform: scale(0.94); }
  to   { opacity: 1; transform: none; }
}

/* ═══ BEAT 1 — brand, revealed slowly over ~3s, then the message ═══ */
.ims-intro-logo {
  width: clamp(96px, 26vw, 132px);
  height: auto;
  border-radius: 26%;
  margin-bottom: clamp(1rem, 3vh, 1.5rem);
  box-shadow: 0 10px 44px rgba(0, 0, 0, 0.55);
  opacity: 0;
}
.ims-intro-wordmark {
  font-family: 'DM Sans', sans-serif;
  font-weight: 700;
  font-size: clamp(2.1rem, 9.5vw, 3.1rem);
  letter-spacing: -0.035em;
  line-height: 1;
  color: #fff;
  margin: 0;
  opacity: 0;
}
.ims-intro-url {
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(0.74rem, 3vw, 0.9rem);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: #35C8FF;
  margin: 0.5rem 0 0;
  opacity: 0;
}

.ims-intro-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.3rem, 1.2vh, 0.5rem);
  margin-top: clamp(1.5rem, 5vh, 2.4rem);
}
.ims-intro-msg-line {
  font-family: 'DM Sans', sans-serif;
  font-weight: 600;
  font-size: clamp(1.15rem, 5.2vw, 1.6rem);
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: #eaf3ff;
  text-wrap: balance;
  margin: 0;
  opacity: 0;
}
.ims-intro-msg-welcome {
  color: #35C8FF;
  margin-top: clamp(0.35rem, 1.4vh, 0.6rem);
}

/* Beat 1 choreography: logo → wordmark → url across ~3s, then the three
   message lines float in and hold. */
.ims-intro-panel[data-panel="brand"].is-active .ims-intro-logo     { animation: imsIntroFade 1.3s ease both 0.15s; }
.ims-intro-panel[data-panel="brand"].is-active .ims-intro-wordmark { animation: imsIntroRise 1.2s ease both 0.95s; }
/* The URL and all three message lines land together at 1.85s and hold ~1.5s. */
.ims-intro-panel[data-panel="brand"].is-active .ims-intro-url,
.ims-intro-panel[data-panel="brand"].is-active .ims-intro-msg-line { animation: imsIntroRise 0.9s ease both 1.85s; }

/* ═══ BEAT 2 — how to navigate, revealed one row at a time ═══════ */
.ims-intro-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(0.56rem, 2.1vw, 0.66rem);
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(120, 190, 255, 0.62);
  margin-bottom: clamp(1rem, 3.5vh, 1.6rem);
  opacity: 0;
}
.ims-intro-eyebrow::before,
.ims-intro-eyebrow::after {
  content: '';
  width: clamp(14px, 4vw, 26px);
  height: 1px;
  background: rgba(120, 190, 255, 0.42);
}

.ims-intro-list {
  list-style: none;
  margin: 0 0 clamp(1rem, 3.4vh, 1.5rem);
  padding: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: clamp(0.5rem, 2vh, 0.8rem);
}
.ims-intro-row {
  display: flex;
  align-items: center;
  gap: clamp(0.7rem, 3vw, 1rem);
  padding: clamp(0.6rem, 2.6vw, 0.8rem) clamp(0.75rem, 3.2vw, 1rem);
  border: 1px solid rgba(90, 150, 220, 0.2);
  border-radius: 14px;
  background: rgba(10, 22, 44, 0.72);
  text-align: left;
  opacity: 0;
}
/* Same phone-style app icon as the mobile Menu sheet: 1:1 rounded square,
   inset bevel, and a soft per-section halo (--ims-glow, set inline per row). */
.ims-intro-row-icon {
  position: relative;
  isolation: isolate;
  width: clamp(42px, 12vw, 52px);
  height: clamp(42px, 12vw, 52px);
  flex-shrink: 0;
  border-radius: 22%;
  background: #0d1526;
  box-shadow:
    inset 0 1.5px 0 rgba(255,255,255,0.35),
    inset 0 -2px 3px rgba(0,0,0,0.55),
    0 3px 8px rgba(0,0,0,0.45);
}
.ims-intro-row-icon img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 22%;
  display: block;
}
.ims-intro-row-icon::before {
  content: '';
  position: absolute; inset: -9%;
  border-radius: 30%;
  background: var(--ims-glow, var(--ims-brand));
  filter: blur(11px);
  opacity: 0.3;
  z-index: -1;
  pointer-events: none;
}
/* Bevel highlight over the artwork. */
.ims-intro-row-icon::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: 22%;
  background: linear-gradient(160deg, rgba(255,255,255,0.24) 0%, rgba(255,255,255,0.05) 34%, rgba(0,0,0,0.16) 100%);
  pointer-events: none;
}
.ims-intro-row-text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.ims-intro-row-name {
  font-family: 'DM Sans', sans-serif;
  font-weight: 600;
  font-size: clamp(0.9rem, 3.6vw, 1.02rem);
  line-height: 1.2;
  color: #eaf3ff;
}
.ims-intro-row-desc {
  font-family: 'DM Sans', sans-serif;
  font-size: clamp(0.7rem, 2.8vw, 0.79rem);
  line-height: 1.35;
  color: rgba(150, 190, 240, 0.62);
}

.ims-intro-more {
  font-family: 'DM Sans', sans-serif;
  font-size: clamp(0.68rem, 2.7vw, 0.78rem);
  color: rgba(150, 190, 240, 0.55);
  margin: 0 0 clamp(0.8rem, 2.6vh, 1.1rem);
  text-wrap: balance;
  opacity: 0;
}
.ims-intro-where {
  margin: 0;
  padding: 0.55rem 1rem;
  border: 1px solid rgba(53, 200, 255, 0.3);
  border-radius: 99px;
  background: rgba(53, 200, 255, 0.08);
  font-family: 'DM Sans', sans-serif;
  font-size: clamp(0.74rem, 3vw, 0.85rem);
  color: #cfe9ff;
  text-wrap: balance;
  opacity: 0;
}
.ims-intro-where strong { font-weight: 700; }

.ims-intro-panel[data-panel="navigate"].is-active .ims-intro-eyebrow          { animation: imsIntroRise 0.45s ease both 0.05s; }
.ims-intro-panel[data-panel="navigate"].is-active .ims-intro-row:nth-child(1) { animation: imsIntroRise 0.5s ease both 0.30s; }
.ims-intro-panel[data-panel="navigate"].is-active .ims-intro-row:nth-child(2) { animation: imsIntroRise 0.5s ease both 0.55s; }
.ims-intro-panel[data-panel="navigate"].is-active .ims-intro-row:nth-child(3) { animation: imsIntroRise 0.5s ease both 0.80s; }
.ims-intro-panel[data-panel="navigate"].is-active .ims-intro-row:nth-child(4) { animation: imsIntroRise 0.5s ease both 1.05s; }
.ims-intro-panel[data-panel="navigate"].is-active .ims-intro-more             { animation: imsIntroRise 0.5s ease both 1.35s; }
.ims-intro-panel[data-panel="navigate"].is-active .ims-intro-where            { animation: imsIntroRise 0.5s ease both 1.60s; }

/* ── Stats band ────────────────────────────────────────────────── */
/* Sits between the panel stage and the enter prompt, so it stays put while
   the beats change behind it. Amber lead line borrows the app's existing
   "at risk" colour, so the urgency reads the same here as it does on the
   Ward timer. */
.ims-intro-stats {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: 620px;
  margin-top: -2.5rem;
  padding: 0.62rem 1.25rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.24rem;
  text-align: center;
  border-top: 1px solid rgba(120, 90, 200, 0.16);
  border-bottom: 1px solid rgba(120, 90, 200, 0.16);
  background: linear-gradient(90deg, transparent, rgba(155, 109, 255, 0.07), transparent);
  animation: imsIntroFade 0.6s ease both 0.35s;
}
.ims-intro-stats[hidden] { display: none; }

.ims-intro-stats-lead {
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(0.76rem, 3.4vw, 0.94rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #FFAA00;
  text-shadow: 0 0 18px rgba(255, 170, 0, 0.22);
}
.ims-intro-stats-sub {
  font-family: 'DM Sans', sans-serif;
  font-size: clamp(0.67rem, 2.9vw, 0.79rem);
  line-height: 1.35;
  color: rgba(200, 220, 255, 0.62);
}

/* ── Enter prompt ──────────────────────────────────────────────── */
.ims-intro-foot {
  position: absolute;
  left: 0;
  right: 0;
  bottom: max(1.4rem, env(safe-area-inset-bottom, 0px));
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  padding: 0 1.25rem;
}

.ims-intro-enter {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.5rem 1.1rem;
  border: 0;
  border-radius: 14px;
  background: none;
  color: rgba(190, 225, 255, 0.92);
  font-family: 'DM Sans', sans-serif;
  font-size: clamp(0.75rem, 3vw, 0.85rem);
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  opacity: 0;
  transform: translate3d(0, 8px, 0);
  transition: opacity 0.45s ease, transform 0.45s ease;
  pointer-events: none;
}
.ims-intro-enter.is-ready {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.ims-intro-enter:focus-visible {
  outline: 2px solid #35C8FF;
  outline-offset: 3px;
}
.ims-intro-chev {
  width: 24px;
  height: 24px;
  color: #35C8FF;
  animation: imsIntroNudge 1.8s ease-in-out infinite;
}
@keyframes imsIntroNudge {
  0%, 100% { transform: translateY(3px);  opacity: 0.55; }
  50%      { transform: translateY(-4px); opacity: 1; }
}

/* Beat progress — decorative only, so a stray tap can't hit it. */
.ims-intro-dots {
  display: flex;
  gap: 0.4rem;
  pointer-events: none;
}
.ims-intro-dots span {
  width: 5px;
  height: 5px;
  border-radius: 99px;
  background: rgba(150, 190, 240, 0.28);
  transition: background 0.35s ease, width 0.35s ease;
}
.ims-intro-dots span.is-on {
  width: 16px;
  background: #35C8FF;
}

/* ── Exit ──────────────────────────────────────────────────────── */
/* The whole sheet slides up and fades — one compositor-only transition, no
   canvas and no per-frame JS. `IMS_INTRO_EXIT_MS` in intro-overlay.js must
   stay >= this duration, since that timer is what removes the overlay. */
.ims-intro.is-leaving { pointer-events: none; cursor: default; }
.ims-intro.is-leaving .ims-intro-foot { opacity: 0; transition: opacity 0.18s ease; }
.ims-intro.is-leaving .ims-intro-sheet {
  transform: translateY(-100%);
  opacity: 0;
  transition: transform 0.52s cubic-bezier(0.5, 0, 0.2, 1), opacity 0.52s ease-in;
}

/* ── Short mode (6th visit onward): brand beat only ────────────── */
html.ims-intro-short .ims-intro-stage { min-height: 40vh; }
html.ims-intro-short .ims-intro-dots  { display: none; }
/* Short mode shows the brand only, and fast: the message lines are dropped
   and the logo/wordmark/url reveal compresses from ~3s into ~0.8s. */
html.ims-intro-short .ims-intro-msg { display: none; }
html.ims-intro-short .ims-intro-panel[data-panel="brand"].is-active .ims-intro-logo     { animation: imsIntroFade 0.45s ease both 0s; }
html.ims-intro-short .ims-intro-panel[data-panel="brand"].is-active .ims-intro-wordmark { animation: imsIntroRise 0.45s ease both 0.2s; }
html.ims-intro-short .ims-intro-panel[data-panel="brand"].is-active .ims-intro-url      { animation: imsIntroRise 0.45s ease both 0.4s; }

/* ── Reduced motion ────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .ims-intro-chev { animation: none; }
  .ims-intro-panel,
  .ims-intro-panel.is-active { transform: none; transition: opacity 0.2s linear, visibility 0s; }
  /* Content still reveals in order, just without the travel. */
  .ims-intro-panel.is-active * { animation-name: imsIntroNoMove !important; animation-duration: 0.01s !important; }
  @keyframes imsIntroNoMove { from { opacity: 1; transform: none; } to { opacity: 1; transform: none; } }
  .ims-intro-enter { transition: opacity 0.2s linear; transform: none; }
  /* The stats band sits outside the panels, so the panel-scoped rule above
     does not reach it — kill its entrance animation explicitly. */
  .ims-intro-stats { animation: none; }
  .ims-intro.is-leaving .ims-intro-sheet {
    transform: none;
    opacity: 0;
    transition: opacity 0.2s linear;
  }
}

/* ── Short viewports (landscape phones) ────────────────────────── */
@media (max-height: 560px) {
  .ims-intro-stage  { min-height: 0; padding-top: 2.5rem; padding-bottom: 4.5rem; }
  .ims-intro-ecg    { height: 34px; }
  .ims-intro-ecg-top    { top: 2%; }
  .ims-intro-ecg-bottom { bottom: 2%; }
  .ims-intro-msg    { margin-top: 0.9rem; }
  .ims-intro-row    { padding: 0.45rem 0.6rem; }
}
