/* ============================================================
   PulseWave — Pulse Spotlight
   Styles for /tools/pulse-spotlight/.

   Built entirely on the design tokens in styles.css (--cyan,
   --panel, --muted, --head, --body) and the .tools-page /
   .tools-badge / .btn language in tools.css, so the page reads
   as part of the same site rather than a second design system.

   The metaphor is a stage spotlight: a cone of light, a soft
   sweep and a pulsing ring behind the name. There is no wheel,
   no reel and no chance/odds language anywhere in this file.
   ============================================================ */

/* The tool needs more room than the shared 52rem reading column.
   Two classes of specificity (.ps-page .doc) match tools.css and
   this sheet loads after it, so the wider column wins here only. */
.ps-page .doc{max-width:64rem}
@media (max-width:760px){.ps-page .doc{max-width:100%}}

.ps-tool{
  margin-top:2.6rem;padding:1.5rem;border-radius:24px;
  border:1px solid rgba(120,200,255,.26);
  background:linear-gradient(150deg,rgba(17,38,64,.95),rgba(7,14,28,.98));
  box-shadow:0 18px 44px rgba(0,0,0,.38),0 0 0 1px rgba(4,10,22,.6)
}

/* ---------- the stage ---------- */
.ps-stage{
  position:relative;isolation:isolate;overflow:hidden;
  min-height:19rem;padding:2.4rem 1.4rem 2.6rem;border-radius:18px;
  border:1px solid var(--line-soft);background:#04070e;
  display:grid;place-items:center
}
.ps-stage-bg{
  position:absolute;inset:0;z-index:-3;
  background:radial-gradient(760px 340px at 50% -10%,rgba(21,101,232,.34),transparent 62%),
             radial-gradient(520px 300px at 50% 112%,rgba(53,199,255,.2),transparent 68%)
}
/* Two soft cones of light from above — a stage rig, never a wheel. */
.ps-beams{position:absolute;inset:-40% -20% auto;height:150%;z-index:-2;pointer-events:none}
.ps-beam{
  position:absolute;top:0;left:50%;width:min(46rem,78%);height:100%;
  transform:translateX(-50%);
  background:linear-gradient(180deg,rgba(159,233,255,.2),rgba(159,233,255,.05) 46%,transparent 82%);
  clip-path:polygon(42% 0,58% 0,100% 100%,0 100%);filter:blur(6px)
}
.ps-beam--wide{
  width:min(68rem,96%);
  background:linear-gradient(180deg,rgba(53,199,255,.13),transparent 74%);
  clip-path:polygon(46% 0,54% 0,100% 100%,0 100%);filter:blur(14px)
}
/* The travelling highlight line. Idle it is parked and invisible. */
.ps-sweep{
  position:absolute;left:-30%;right:-30%;top:0;height:100%;z-index:-1;opacity:0;
  background:linear-gradient(100deg,transparent 34%,rgba(53,199,255,.16) 50%,transparent 66%);
  pointer-events:none
}
.ps-stage[data-state="cycling"] .ps-sweep{opacity:1;animation:ps-sweep 2.4s linear infinite}
@keyframes ps-sweep{from{transform:translate3d(-42%,0,0)}to{transform:translate3d(42%,0,0)}}

/* Pulsing ring behind the final name. */
.ps-ring{position:absolute;left:50%;top:50%;z-index:-1;width:min(30rem,84%);aspect-ratio:1;transform:translate(-50%,-50%);pointer-events:none;opacity:0}
.ps-ring span{position:absolute;inset:0;border-radius:50%}
.ps-ring__a{border:1px solid rgba(53,199,255,.4);box-shadow:0 0 44px rgba(53,199,255,.2) inset,0 0 30px rgba(53,199,255,.18)}
.ps-ring__b{inset:12%;border:1px dashed rgba(120,200,255,.22)}
.ps-stage[data-state="done"] .ps-ring{opacity:1}
.ps-stage[data-state="done"] .ps-ring__a{animation:ps-pulse 3.4s ease-in-out infinite}
@keyframes ps-pulse{0%,100%{transform:scale(1);opacity:.85}50%{transform:scale(1.045);opacity:1}}

/* Light motes drifting like dust in a studio beam. Purely decorative. */
.ps-motes{position:absolute;inset:0;z-index:-1;pointer-events:none;overflow:hidden}
.ps-mote{position:absolute;bottom:-6px;width:3px;height:3px;border-radius:50%;background:rgba(159,233,255,.7);box-shadow:0 0 8px rgba(53,199,255,.8);opacity:0;animation-name:ps-drift}
@keyframes ps-drift{
  0%{opacity:0;transform:translate3d(0,0,0)}
  14%{opacity:.75}
  70%{opacity:.5}
  100%{opacity:0;transform:translate3d(18px,-120%,0)}
}

.ps-stage-inner{position:relative;text-align:center;width:100%;min-width:0}
.ps-kicker{
  display:inline-flex;align-items:center;gap:.5rem;margin:0 0 1.1rem;
  font:800 .7rem/1 var(--body);letter-spacing:.24em;text-transform:uppercase;color:var(--cyan-soft)
}
.ps-kicker-dot{width:7px;height:7px;border-radius:50%;background:var(--cyan);box-shadow:0 0 10px rgba(53,199,255,.9)}
.ps-stage[data-state="cycling"] .ps-kicker-dot{animation:ps-blink 1.05s ease-in-out infinite}
@keyframes ps-blink{0%,100%{opacity:1}50%{opacity:.25}}

.ps-label{
  margin:0 0 .6rem;font:800 clamp(.7rem,1.6vw,.85rem)/1 var(--body);
  letter-spacing:.34em;text-transform:uppercase;color:#9fe9ff;
  opacity:0;transition:opacity .3s ease
}
.ps-stage[data-state="done"] .ps-label{opacity:1}

.ps-name{
  margin:0;font:900 clamp(2rem,8.4vw,4.6rem)/1.06 var(--head);
  letter-spacing:-.02em;color:#fff;
  /* Long handles wrap and scale down instead of overflowing the stage. */
  overflow-wrap:anywhere;word-break:break-word;
  text-shadow:0 0 34px rgba(53,199,255,.4)
}
.ps-stage[data-state="done"] .ps-name{animation:ps-reveal .55s cubic-bezier(.2,.8,.3,1) both}
@keyframes ps-reveal{from{opacity:0;transform:translateY(14px) scale(.94)}to{opacity:1;transform:none}}
.ps-stage[data-state="cycling"] .ps-name{opacity:.92}

.ps-idle{margin:0;color:var(--muted);font-size:.92rem;line-height:1.6}
.ps-idle strong{color:#cfe6f5;font-weight:800}
.ps-stage:not([data-state="idle"]) .ps-idle{display:none}

/* Screen-reader announcement of the result. The name itself is already the
   hero of the stage, so this is visually hidden and exists purely to give
   assistive tech a live region to announce the pick. */
.ps-live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;border:0;overflow:hidden;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%)}


/* ---------- controls ---------- */
.ps-actions{display:flex;flex-wrap:wrap;gap:.6rem;margin:1.1rem 0 0}
.ps-actions button{flex:1 1 12rem;justify-content:center}
.ps-go{min-height:54px}
.ps-go[disabled]{opacity:.45;cursor:not-allowed;box-shadow:none;transform:none}
.ps-btn-ghost{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  min-height:48px;padding:.75rem 1.2rem;border-radius:999px;cursor:pointer;
  border:1px solid rgba(120,200,255,.3);background:rgba(255,255,255,.03);
  color:#cfe6f5;font:700 .88rem/1 var(--body);
  transition:border-color .2s ease,color .2s ease,background .2s ease
}
.ps-btn-ghost:hover{border-color:var(--cyan);color:#fff;background:rgba(53,199,255,.1)}
.ps-btn-ghost:focus-visible{outline:2px solid var(--cyan);outline-offset:3px}
/* The .ps-btn-ghost and .ps-exit rules above set display:inline-flex, which
   beats the browser's [hidden]{display:none}. Without this the hidden
   Spotlight Another / Remove Selected Name / Exit controls would all show. */
.ps-btn-ghost[hidden],.ps-exit[hidden],.ps-history[hidden]{display:none}
.ps-btn-plain{
  border:0;background:none;cursor:pointer;padding:.35rem .1rem;
  color:#7fe3ff;font:700 .82rem/1 var(--body);text-decoration:underline;
  text-underline-offset:3px
}
.ps-btn-plain:hover{color:#fff}
.ps-btn-plain:focus-visible{outline:2px solid var(--cyan);outline-offset:3px;border-radius:6px}
.ps-note{margin:1.2rem 0 0;color:var(--muted);font-size:.88rem;line-height:1.6}

/* ---------- entry + settings panels ---------- */
.ps-grid{display:grid;grid-template-columns:minmax(0,1.45fr) minmax(0,1fr);gap:1.25rem;margin-top:1.5rem}
.ps-panel{min-width:0}
.ps-field{display:flex;flex-direction:column;gap:.5rem}
.ps-label-text{font:800 .72rem/1.3 var(--body);letter-spacing:.16em;text-transform:uppercase;color:#9fe9ff}
.ps-textarea{
  width:100%;min-height:13.5rem;padding:1rem 1.05rem;border-radius:14px;
  border:1px solid rgba(120,200,255,.22);background:rgba(3,8,17,.75);
  color:var(--ink);font:500 1rem/1.6 var(--body);resize:vertical;
  transition:border-color .2s,box-shadow .2s
}
/* A tall box at a 16px base size, so pasting hundreds of usernames on a
   phone does not trigger the iOS zoom-on-focus. */
.ps-textarea:focus{outline:none;border-color:var(--cyan);box-shadow:0 0 0 3px rgba(53,199,255,.16)}
.ps-textarea::placeholder{color:#5d7288}
.ps-count{margin:0;font:800 .85rem/1.4 var(--body);color:var(--cyan-soft)}
.ps-help{margin:0;color:var(--muted);font-size:.82rem;line-height:1.55}
.ps-tools{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1rem}

.ps-h3{font:800 1.02rem/1.3 var(--head);color:#fff;margin:0 0 .9rem}
.ps-switch{display:flex;gap:.8rem;align-items:flex-start;padding:.95rem 1.05rem;border-radius:14px;border:1px solid var(--line-soft);background:rgba(255,255,255,.02);cursor:pointer;margin-bottom:.7rem}
.ps-switch:last-child{margin-bottom:0}
.ps-switch:hover{border-color:rgba(53,199,255,.4)}
/* The native checkbox stays in the tab order (clipped, not display:none)
   so keyboard users reach it and the focus ring shows on its track. */
.ps-switch input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;border:0;overflow:hidden;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%)}
.ps-switch-ui{position:relative;flex:none;width:42px;height:24px;margin-top:.1rem;border-radius:999px;background:rgba(3,8,17,.9);border:1px solid rgba(120,200,255,.3);transition:background .2s,border-color .2s}
.ps-switch-ui::after{content:"";position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#6f8598;transition:transform .2s,background .2s}
.ps-switch input:checked + .ps-switch-ui{background:rgba(53,199,255,.32);border-color:var(--cyan)}
.ps-switch input:checked + .ps-switch-ui::after{transform:translateX(18px);background:var(--cyan)}

/* ---------- stream mode ---------- */
/* A clean capture surface: the stage, the branding and one button. The page
   chrome, the entry box and the advert are all taken out of view. */
.ps-page.ps-stream{overflow:hidden}
/* The reading content is hidden element-by-element so the stage keeps the
   page's own spacing language. That alone leaves it taking up space and
   scrollable, so the reading wrapper is collapsed outright as well. */
.ps-page.ps-stream .doc > *:not(.ps-tool){display:none}
/* The tool fills exactly one viewport, and the site chrome below it (the ad
   and the footer) is taken out of flow, so a captured frame can never show a
   scrollbar or a slice of the footer. */
.ps-page.ps-stream .seo-main{position:fixed;inset:0;overflow:hidden;padding:0}
.ps-page.ps-stream .site-footer{display:none}
.ps-page.ps-stream .site-header{display:none}
.ps-page.ps-stream .seo-main{padding:0}
.ps-page.ps-stream .ps-tool{
  min-height:100vh;min-height:100dvh;margin:0;padding:1.1rem;border-radius:0;
  display:flex;flex-direction:column;justify-content:center;border:0
}
.ps-page.ps-stream .ps-stage{flex:1 1 auto;min-height:0}
/* Stream Mode is a capture surface, so only the branding, the stage and the
   controls survive. The h1/eyebrow are inside .doc and are pulled out with
   the rest of the reading content, keeping the frame clean for a stream. */
.ps-page.ps-stream .doc{padding-top:0}
/* Everything inside the reading column except the tool itself is removed:
   h1, lede, the SEO sections, the FAQ and the noscript note. The page footer
   is the site's own and is left alone below the full-height tool. */
.ps-page.ps-stream .ps-grid,
.ps-page.ps-stream .ps-history,
.ps-page.ps-stream .ps-btn-plain,
.ps-page.ps-stream #ps-go,
.ps-page.ps-stream #ps-remove,
.ps-page.ps-stream #ps-stream{display:none}
.ps-page.ps-stream .tools-badge{display:none}
.ps-page.ps-stream .ps-actions{margin-top:.9rem;justify-content:center}
.ps-page.ps-stream .ps-name{font-size:clamp(2.4rem,9vw,6rem)}
/* "Spotlight Another" becomes the single primary control in the capture view,
   and it is what Stream Mode shows on entry (it runs an initial pick). */
.ps-page.ps-stream #ps-again{
  display:inline-flex;flex:0 1 auto;min-width:14rem;min-height:54px;
  background:linear-gradient(180deg,var(--cyan-soft),var(--cyan));
  color:#000;font-weight:900;border-color:transparent;
  box-shadow:0 8px 30px rgba(28,180,242,.25)
}
.ps-page.ps-stream #ps-exit{display:inline-flex;position:absolute;top:.9rem;right:.9rem;z-index:5;
  min-height:40px;padding:.55rem .95rem;border-radius:999px;cursor:pointer;font:700 .8rem/1 var(--body);
  border:1px solid rgba(120,200,255,.3);background:rgba(4,10,22,.75);color:#cfe6f5;opacity:.55;transition:opacity .2s}
.ps-page.ps-stream #ps-exit:hover,.ps-page.ps-stream #ps-exit:focus-visible{opacity:1}
.ps-exit svg{width:15px;height:15px}
.ps-exit:focus-visible{outline:2px solid var(--cyan);outline-offset:3px}

/* ---------- supporting page content ---------- */
.ps-page .ps-faq{padding:0;margin-top:3.4rem}
.ps-page .ps-faq .faq-inner{max-width:none;margin-top:1.2rem}
.ps-uses{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.85rem;margin:1.4rem 0 0;padding:0;list-style:none}
.ps-uses li{padding:1rem 1.1rem;border-radius:14px;border:1px solid var(--line-soft);background:rgba(255,255,255,.02);color:#b6c6d6;font-size:.9rem;line-height:1.55}
.ps-uses strong{display:block;color:#fff;font-weight:800;margin-bottom:.25rem}
.ps-steps{margin:1.2rem 0 0;padding-left:1.2rem}
.ps-steps li{margin-bottom:.55rem}

/* ---------- responsive ---------- */
@media (max-width:900px){
  .ps-grid{grid-template-columns:1fr;gap:1.1rem}
  .ps-tool{padding:1.15rem}
  .ps-stage{min-height:16.5rem}
}
@media (max-width:560px){
  .ps-tool{padding:.9rem;border-radius:20px}
  .ps-uses{grid-template-columns:1fr}
  .ps-textarea{min-height:11.5rem;font-size:16px}
  /* One full-width control per row keeps every target finger-sized and
     keeps the on-screen keyboard from covering the primary buttons. */
  .ps-actions{flex-direction:column}
  .ps-actions button{width:100%;flex:none}
  .ps-tools{flex-direction:column}
  .ps-tools .ps-btn-ghost{width:100%}
  .ps-stage{min-height:14rem;padding:1.8rem 1rem 2rem}
  .ps-exit{top:.6rem;right:.6rem}
}

/* ---------- reduced motion ----------
   The cycling itself is driven by JS, which skips it under this preference
   too; this only neutralises the decorative CSS: sweep, ring and motes. */
@media (prefers-reduced-motion:reduce){
  .ps-stage[data-state="cycling"] .ps-sweep{animation:none;opacity:.35}
  .ps-stage[data-state="done"] .ps-ring__a{animation:none}
  .ps-stage[data-state="done"] .ps-name{animation:ps-fade .3s ease both}
  .ps-stage[data-state="cycling"] .ps-kicker-dot{animation:none}
  .ps-motes{display:none}
}
@keyframes ps-fade{from{opacity:0}to{opacity:1}}

.ps-switch input:focus-visible + .ps-switch-ui{outline:2px solid var(--cyan);outline-offset:3px}
.ps-switch-text{display:block;min-width:0}
.ps-switch-text strong{display:block;color:#e8f2fb;font-weight:800;font-size:.9rem;line-height:1.4}
.ps-switch-hint{display:block;margin-top:.3rem;color:var(--muted);font-size:.79rem;line-height:1.5}

/* ---------- recently spotlighted ---------- */
.ps-history{margin-top:1.5rem;padding:1.1rem 1.25rem 1.25rem;border-radius:16px;border:1px solid var(--line-soft);background:rgba(255,255,255,.02)}
.ps-history-head{display:flex;align-items:center;justify-content:space-between;gap:1rem}
.ps-history-head .ps-h3{margin:0}
.ps-history-list{display:flex;flex-wrap:wrap;gap:.45rem;margin:.95rem 0 0;padding:0;list-style:none}
.ps-history-list li{
  padding:.42rem .8rem;border-radius:999px;font-size:.84rem;font-weight:700;
  border:1px solid rgba(120,200,255,.2);background:rgba(53,199,255,.06);color:#cfe6f5;
  overflow-wrap:anywhere;max-width:100%
}
.ps-history-list li:first-child{border-color:rgba(53,199,255,.6);background:rgba(53,199,255,.15);color:#fff}
