/* ============================================================================
   25 — SHADOWING STUDIO  (/shadowing)
   Hub (filterable clip catalog) + Studio (extract player + karaoke rail + dock).
   Theme-aware: uses the shared --bg/--text/--card-* vars; the studio itself is
   deliberately cinematic-dark in both themes (video reads best on dark).
   ============================================================================ */

/* dvh, not vh: `100vh` is the viewport with the mobile URL bar retracted, so a
   100vh shell is taller than what the phone actually shows. vh line first as
   the fallback for browsers without dvh. */
#shadowing-page{ min-height:100vh; min-height:100dvh; }

/* Full-page takeover: hide the homepage + every other top-level section/footer
   so only the studio shows (mirrors reading-list-mode / articles-mode). The
   site header stays for the hub; the studio hides it via body.sh-immersive. */
body.shadowing-mode #home,
body.shadowing-mode > footer,
body.shadowing-mode > section:not(#shadowing-page){ display:none !important; }

/* shadowing accent duo */
:root{ --sh-a:#4ee0f2; --sh-b:#8b6dff; --sh-c:#c6f24e; }

/* immersive studio hides the site chrome for a focused, full-screen feel */
body.sh-immersive > header{ display:none !important; }
body.sh-immersive{ overflow:hidden; }

/* ============================ HUB ============================ */
.sh-hub{ position:relative; padding:0 20px 90px; overflow:hidden; }

/* drifting aurora backdrop */
/* `inset:-20%` resolved against .sh-hub's height — which is ~320,000px with
   939 clips — so this landed 64,000px above the page and never rendered. */
.sh-aurora{ position:absolute; inset:-144px -10% auto; height:720px; z-index:0; pointer-events:none;
  filter:blur(70px); opacity:var(--aurora-opacity); }
.sh-aurora span{ position:absolute; border-radius:50%; mix-blend-mode:screen; }
.sh-aurora span:nth-child(1){ width:520px; height:520px; left:8%;  top:-60px; background:radial-gradient(circle,var(--sh-a),transparent 65%); animation:shDrift1 20s ease-in-out infinite; }
.sh-aurora span:nth-child(2){ width:600px; height:600px; right:6%; top:-120px; background:radial-gradient(circle,var(--sh-b),transparent 65%); animation:shDrift2 26s ease-in-out infinite; }
.sh-aurora span:nth-child(3){ width:420px; height:420px; left:44%; top:40px;  background:radial-gradient(circle,var(--sh-c),transparent 62%); animation:shDrift1 30s ease-in-out infinite reverse; }
@keyframes shDrift1{ 0%,100%{ transform:translate(0,0) scale(1);} 50%{ transform:translate(60px,40px) scale(1.12);} }
@keyframes shDrift2{ 0%,100%{ transform:translate(0,0) scale(1.05);} 50%{ transform:translate(-70px,30px) scale(.95);} }

/* hero */
.sh-hero{ position:relative; z-index:1; max-width:1120px; margin:0 auto; padding:64px 8px 40px; text-align:center; }
.sh-eyebrow{ display:inline-flex; align-items:center; gap:10px; font-size:12.5px; font-weight:800; letter-spacing:.22em;
  color:var(--muted); text-transform:uppercase; margin-bottom:20px; }
.sh-hero-title{ font-size:clamp(34px,6vw,66px); line-height:1.02; font-weight:800; letter-spacing:-.02em; margin:0 0 18px; }
.sh-grad{ background:linear-gradient(100deg,var(--sh-a),var(--sh-b) 55%,var(--sh-c)); -webkit-background-clip:text; background-clip:text; color:transparent; }
.sh-hero-sub{ max-width:640px; margin:0 auto; color:var(--muted); font-size:16.5px; line-height:1.6; }
.sh-hero-sub em{ color:var(--text); font-style:normal; font-weight:600; }
/* Equal-width tiles on an auto-fitting grid rather than a centred flex-wrap.
   As a flex row each tile sized to its own label (86px for "CLIPS" vs 127px
   for "FREE TO TRY") and every wrapped row centred itself independently, so
   the 2×2 a phone gets came out ragged — rows offset from each other and no
   two tiles the same width. A fixed track equalises the tiles and lines the
   rows up; justify-content:center keeps the centred look on wide screens.
   132px = the widest label (127px) plus breathing room, so nothing wraps. */
.sh-hero-stats{ display:grid; grid-template-columns:repeat(auto-fit, 132px); justify-content:center; gap:14px; margin-top:30px; }
.sh-stat{ display:flex; flex-direction:column; align-items:center; min-width:92px; padding:14px 20px;
  background:var(--card-bg-soft); border:1px solid var(--card-border); border-radius:16px; backdrop-filter:blur(12px); }
.sh-stat b{ font-size:26px; font-weight:800; background:linear-gradient(120deg,var(--sh-a),var(--sh-b)); -webkit-background-clip:text; background-clip:text; color:transparent; }
.sh-stat span{ font-size:11.5px; text-transform:uppercase; letter-spacing:.14em; color:var(--muted); margin-top:2px; }

/* animated equalizer */
.sh-eq{ display:inline-flex; align-items:flex-end; gap:3px; height:14px; }
.sh-eq i{ width:3px; height:100%; border-radius:2px; background:linear-gradient(var(--sh-a),var(--sh-b)); transform-origin:bottom;
  animation:shEq 1s ease-in-out infinite; }
.sh-eq i:nth-child(2){ animation-delay:.15s; } .sh-eq i:nth-child(3){ animation-delay:.3s; }
.sh-eq i:nth-child(4){ animation-delay:.45s; } .sh-eq i:nth-child(5){ animation-delay:.6s; }
.sh-eq.big{ height:40px; gap:5px; } .sh-eq.big i{ width:6px; }
@keyframes shEq{ 0%,100%{ transform:scaleY(.28);} 50%{ transform:scaleY(1);} }

/* filter bar */
.sh-filters{ position:sticky; top:12px; z-index:5; max-width:1560px; margin:0 auto 26px; display:flex; flex-direction:column; gap:12px;
  padding:14px; background:var(--card-bg); border:1px solid var(--card-border); border-radius:18px;
  backdrop-filter:blur(18px) saturate(140%); box-shadow:var(--shadow-lg); }
.sh-search{ position:relative; display:flex; align-items:center; }
.sh-search svg{ position:absolute; left:14px; width:18px; height:18px; color:var(--muted); }
.sh-search input{ width:100%; padding:12px 14px 12px 42px; border-radius:12px; border:1px solid var(--card-border);
  background:var(--input-bg); color:var(--text); font:inherit; font-size:15px; outline:none; transition:border-color .2s, box-shadow .2s; }
.sh-search input:focus{ border-color:var(--sh-a); box-shadow:0 0 0 3px var(--ring-cyan); }
.sh-chips{ display:flex; flex-wrap:wrap; gap:8px; }
.sh-chip{ padding:7px 14px; border-radius:999px; border:1px solid var(--card-border); background:var(--chip-bg);
  color:var(--muted); font:inherit; font-size:13px; font-weight:600; cursor:pointer; transition:all .18s; white-space:nowrap; }
.sh-chip:hover{ background:var(--chip-bg-hover); color:var(--text); }
.sh-chip.on{ color:var(--on-lime); background:linear-gradient(120deg,var(--sh-a),var(--sh-b)); border-color:transparent;
  box-shadow:0 6px 18px -6px var(--sh-b); }

/* ---- free shelf -------------------------------------------------------------
   Above the filter bar, so the first thing a locked visitor sees is a row of
   clips they can actually play — not 939 padlocks they have to filter through.
   Rendered only while something IS locked (renderHub gates on `gated`), so a
   premium account never sees a shelf that says "free" about everything. */
.sh-free{ position:relative; z-index:1; max-width:1560px; margin:0 auto 30px; padding:22px 22px 26px;
  border:1px solid color-mix(in srgb, var(--sh-b) 30%, var(--card-border));
  border-radius:22px; background:var(--card-bg); backdrop-filter:blur(18px) saturate(140%);
  box-shadow:var(--shadow-lg); overflow:hidden; }
/* brand wash on a pseudo-element: a gradient *background* on the panel itself
   would sit under the cards and muddy every thumbnail. */
.sh-free::before{ content:''; position:absolute; inset:0; pointer-events:none; z-index:-1;
  background:radial-gradient(120% 150% at 0% 0%, color-mix(in srgb, var(--sh-a) 16%, transparent), transparent 60%),
             radial-gradient(120% 150% at 100% 0%, color-mix(in srgb, var(--sh-b) 16%, transparent), transparent 60%); }
.sh-free-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
  flex-wrap:wrap; margin-bottom:18px; }
.sh-free-title{ display:flex; align-items:center; gap:9px; margin:0 0 6px;
  font-size:clamp(19px,2.3vw,24px); font-weight:800; letter-spacing:-.01em; color:var(--text); }
.sh-free-key{ font-size:.95em; line-height:1;
  animation:shKey 2.6s ease-in-out infinite; transform-origin:60% 60%; }
@keyframes shKey{ 0%,88%,100%{ transform:rotate(0);} 92%{ transform:rotate(-13deg);} 96%{ transform:rotate(9deg);} }
.sh-free-sub{ margin:0; max-width:62ch; font-size:14px; line-height:1.55; color:var(--muted); }
.sh-free-count{ flex:none; padding:6px 13px; border-radius:999px; font-size:12px; font-weight:800;
  letter-spacing:.06em; text-transform:uppercase; color:var(--on-lime);
  background:linear-gradient(120deg,var(--sh-a),var(--sh-b)); box-shadow:0 6px 18px -8px var(--sh-b); }
/* Flex-wrap + justify-content:center, NOT a grid. The free count is data (5
   today, 6 if someone unlocks another from the admin panel), and a grid with
   auto-fit columns strands the remainder: at 1280px five cards laid out 4 + 1,
   leaving a lone card hard against the left edge with three empty tracks beside
   it — which reads as broken rather than deliberate. Flex centres whatever is
   left on the last row, so every count from 1 to 9 looks intentional.
   flex-basis 200px (not 232) so all five still fit on one row at 1280. */
.sh-free-row{ display:flex; flex-wrap:wrap; justify-content:center; gap:18px; }
.sh-free-row > .sh-card{ flex:1 1 200px; max-width:300px; }
@media (max-width:560px){
  .sh-free{ padding:18px 14px 20px; border-radius:18px; }
  .sh-free-row{ gap:14px; }
  .sh-free-row > .sh-card{ flex-basis:100%; max-width:none; }
}
@media (prefers-reduced-motion:reduce){ .sh-free-key{ animation:none; } }

/* grid */
.sh-grid{ max-width:1560px; margin:0 auto; display:grid; gap:20px;
  grid-template-columns:repeat(auto-fill,minmax(260px,1fr)); position:relative; z-index:1; }
.sh-card{ position:relative; text-align:left; padding:0;
  border:1px solid var(--card-border); background:var(--card-bg); color:var(--text);
  border-radius:18px; overflow:hidden; isolation:isolate; cursor:pointer; font:inherit; display:flex; flex-direction:column;
  transition:transform .34s cubic-bezier(.2,.8,.25,1), box-shadow .34s ease, border-color .34s;
  animation:shRise .6s cubic-bezier(.2,.8,.25,1) both;
  animation-delay:calc(min(var(--i),16) * 42ms); }
/* The hidden start state lives INSIDE the keyframes (not as `opacity:0` on
   .sh-card) so that a rule which overrides `animation` can never leave a card
   permanently invisible — it would still occupy its grid cell and read as a
   hole in the catalog. `both` keeps it hidden through the stagger delay. */
@keyframes shRise{ from{ opacity:0; transform:translateY(22px) scale(.975); } to{ opacity:1; transform:none;} }
.sh-card:hover{ transform:translateY(-8px) scale(1.012);
  border-color:color-mix(in srgb,var(--sh-a) 55%, var(--card-border-hi));
  box-shadow:0 30px 60px -28px rgba(6,8,20,.68),
             0 16px 46px -20px color-mix(in srgb,var(--sh-b) 52%, transparent),
             0 0 0 1px color-mix(in srgb,var(--sh-a) 30%, transparent); }
.sh-card.feat{ border-color:color-mix(in srgb,var(--sh-b) 45%, var(--card-border)); }
.sh-card-thumb{ position:relative; aspect-ratio:16/9; background:#0a0b10; overflow:hidden; }
.sh-card-thumb img{ width:100%; height:100%; object-fit:cover; transition:transform .4s ease; }
.sh-card:hover .sh-card-thumb img{ transform:scale(1.07); }
.sh-card-dur{ position:absolute; right:8px; bottom:8px; padding:2px 8px; border-radius:7px; font-size:12px; font-weight:700;
  color:#fff; background:rgba(6,8,14,.82); backdrop-filter:blur(4px); }
.sh-card-feat{ position:absolute; left:8px; top:8px; padding:3px 9px; border-radius:7px; font-size:11px; font-weight:800; letter-spacing:.03em;
  color:var(--on-lime); background:linear-gradient(120deg,var(--sh-a),var(--sh-b)); }
.sh-card-done{ position:absolute; right:8px; top:8px; width:26px; height:26px; display:grid; place-items:center; border-radius:50%;
  font-size:14px; font-weight:900; color:#062; background:var(--sh-c); box-shadow:0 4px 12px -3px rgba(0,0,0,.5); }
.sh-card-play{ position:absolute; inset:0; display:grid; place-items:center; opacity:0; transition:opacity .22s;
  background:radial-gradient(circle at center,rgba(10,11,16,.35),rgba(10,11,16,.62)); }
.sh-card-play svg{ width:56px; height:56px; color:#fff; filter:drop-shadow(0 6px 18px rgba(0,0,0,.6)); transform:scale(.8); transition:transform .22s; }
.sh-card:hover .sh-card-play{ opacity:1; } .sh-card:hover .sh-card-play svg{ transform:scale(1); }
.sh-card-body{ padding:14px 16px 16px; display:flex; flex-direction:column; gap:8px; }
.sh-card-meta{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.sh-badge{ padding:2px 9px; border-radius:6px; font-size:11px; font-weight:800; letter-spacing:.02em; }
.sh-badge.lv-beg{ color:#0a3; background:rgba(40,220,120,.16); }
.sh-badge.lv-int{ color:#e8930a; background:rgba(255,170,60,.16); }
.sh-badge.lv-adv{ color:#c05bff; background:rgba(160,110,255,.18); }
.sh-cat{ font-size:12px; color:var(--muted); font-weight:600; }
.sh-card-title{ font-size:16.5px; font-weight:700; line-height:1.3; margin:0; }
.sh-card-src{ font-size:13px; color:var(--muted); }

/* ---- premium gating ----------------------------------------------------
   A few clips stay open; the rest are paid. A locked card still shows its
   thumbnail and every bit of metadata — the point is to make the library look
   worth buying — but the artwork is dimmed and the play affordance is replaced
   by the lock, so nothing promises a clip that will not open. */
.sh-card-free{ position:absolute; left:8px; top:8px; padding:3px 9px; border-radius:7px;
  font-size:11px; font-weight:800; letter-spacing:.06em; color:#07130a; background:var(--sh-c);
  box-shadow:0 4px 14px -6px var(--sh-c); }
/* FREE sits under ★ Featured when a clip is both (markup order: feat → free). */
.sh-card-feat + .sh-card-free{ top:37px; }

.sh-card--locked .sh-card-thumb img{ filter:grayscale(.6) brightness(.5); }
.sh-card--locked .sh-card-play{ display:none; }         /* no false "playable" cue */
.sh-card--locked .sh-card-thumb::before{ opacity:.55; } /* keep the vignette on */
.sh-card-lock{ position:absolute; inset:0; z-index:2; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:6px; pointer-events:none;
  background:radial-gradient(circle at center,rgba(10,11,16,.28),rgba(10,11,16,.6)); }
.sh-card-lock-ico{ font-size:23px; filter:drop-shadow(0 4px 10px rgba(0,0,0,.55));
  transition:transform .28s cubic-bezier(.2,.8,.25,1); }
.sh-card-lock-txt{ padding:3px 11px; border-radius:8px; font-size:11px; font-weight:800;
  letter-spacing:.1em; text-transform:uppercase; color:#fff;
  background:rgba(8,10,18,.72); border:1px solid rgba(255,255,255,.16); backdrop-filter:blur(6px);
  transition:background .28s, border-color .28s, color .28s; }
.sh-card--locked:hover .sh-card-lock-ico{ transform:translateY(-3px) scale(1.12); }
.sh-card--locked:hover .sh-card-lock-txt{ color:var(--on-lime); border-color:transparent;
  background:linear-gradient(120deg,var(--sh-a),var(--sh-b)); }
.sh-card--locked:hover .sh-card-thumb img{ filter:grayscale(.25) brightness(.66); }
/* the lock veil spans the whole thumb, so lift the corner pills above it */
.sh-card--locked .sh-card-feat,
.sh-card--locked .sh-card-dur,
.sh-card--locked .sh-card-done{ z-index:3; }

/* hero: how much is open, and the way out of the wall */
.sh-stat--free b{ background:linear-gradient(120deg,var(--sh-c),var(--sh-a));
  -webkit-background-clip:text; background-clip:text; }
.sh-hero-unlock{ display:inline-flex; align-items:center; gap:14px; flex-wrap:wrap; justify-content:center;
  margin-top:22px; padding:10px 10px 10px 18px; border-radius:999px;
  background:var(--card-bg-soft); border:1px solid var(--card-border); backdrop-filter:blur(12px);
  font-size:13.5px; color:var(--muted); }
.sh-unlock-btn{ padding:9px 18px; border-radius:999px; border:0; font:inherit; font-size:13px; font-weight:800;
  color:var(--on-lime); background:linear-gradient(120deg,var(--sh-a),var(--sh-b)); cursor:pointer;
  box-shadow:0 12px 26px -14px var(--sh-b); transition:transform .18s, filter .18s, box-shadow .18s; }
.sh-unlock-btn:hover{ transform:translateY(-2px); filter:brightness(1.06);
  box-shadow:0 18px 32px -14px var(--sh-b); }

/* ---- the wall itself (studio route, clip not owned) --------------------- */
.sh-locked{ position:relative; min-height:70vh; padding:44px 20px 90px; display:grid; place-items:center; overflow:hidden; }
.sh-locked-card{ position:relative; z-index:1; width:min(940px,100%);
  display:grid; grid-template-columns:minmax(0,40%) minmax(0,1fr);
  background:var(--card-bg); border:1px solid var(--card-border); border-radius:22px; overflow:hidden;
  box-shadow:0 40px 90px -50px rgba(6,8,20,.8), 0 0 0 1px color-mix(in srgb,var(--sh-b) 16%, transparent);
  animation:shRise .6s cubic-bezier(.2,.8,.25,1) both; }
/* overflow:hidden is load-bearing — the artwork below is scaled up past these
   bounds, and only this panel (not the card) may clip it. */
.sh-locked-art{ position:relative; background:#0a0b10; min-height:230px; overflow:hidden; }
/* YouTube's hqdefault is a 4:3 canvas with the 16:9 frame letterboxed into it.
   `cover` crops those bars away in the 16:9 card thumbs, but this panel is
   portrait, so it would keep them as black bands. 360/270 zooms past them.
   The long selector is deliberate: `img:not([width]):not([height]){height:auto}`
   in 31-responsive-global scores (0,2,1) and that file loads LAST, so anything
   up to two classes loses the tie and leaves the artwork 281px tall in a 379px
   panel — a black strip under it. Three classes wins outright. */
.sh-locked .sh-locked-card .sh-locked-art img{ position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; transform:scale(1.34); filter:grayscale(.55) brightness(.46); }
.sh-locked-ico{ position:absolute; inset:0; display:grid; place-items:center; font-size:44px;
  filter:drop-shadow(0 8px 20px rgba(0,0,0,.6)); }
.sh-locked-tag{ position:absolute; left:12px; top:12px; padding:4px 11px; border-radius:8px;
  font-size:11px; font-weight:800; letter-spacing:.06em; color:var(--on-lime);
  background:linear-gradient(120deg,var(--sh-a),var(--sh-b)); }
.sh-locked-body{ padding:28px 30px 26px; display:flex; flex-direction:column; gap:11px; min-width:0; }
.sh-locked-eyebrow{ font-size:11.5px; font-weight:800; letter-spacing:.2em; text-transform:uppercase; color:var(--muted); }
.sh-locked-title{ margin:0; font-size:clamp(21px,2.7vw,30px); font-weight:800; line-height:1.16; letter-spacing:-.015em; }
.sh-locked-src{ font-size:13.5px; color:var(--muted); }
.sh-locked-facts{ display:flex; flex-wrap:wrap; gap:7px; }
.sh-locked-facts span{ padding:4px 10px; border-radius:8px; font-size:12px; font-weight:700;
  color:var(--muted); background:var(--card-bg-soft); border:1px solid var(--card-border); }
.sh-locked-text{ margin:3px 0 0; font-size:14.5px; line-height:1.6; color:var(--muted); }
.sh-locked-cta{ display:flex; flex-wrap:wrap; gap:10px; margin-top:8px; }
.sh-lock-btn{ padding:12px 20px; border-radius:12px; border:1px solid transparent; font:inherit;
  font-size:14px; font-weight:800; cursor:pointer; color:var(--on-lime);
  background:linear-gradient(135deg,var(--sh-a),var(--sh-b));
  box-shadow:0 14px 30px -16px var(--sh-b); transition:transform .18s, filter .18s, box-shadow .18s; }
.sh-lock-btn:hover{ transform:translateY(-2px); filter:brightness(1.06); box-shadow:0 20px 36px -16px var(--sh-b); }
.sh-lock-btn.ghost{ color:var(--text); background:var(--card-bg-soft); border-color:var(--card-border); box-shadow:none; }
.sh-lock-btn.ghost:hover{ border-color:color-mix(in srgb,var(--sh-a) 45%, var(--card-border)); filter:none; }
.sh-locked-foot{ display:flex; flex-wrap:wrap; align-items:center; gap:12px; margin-top:14px;
  padding-top:14px; border-top:1px solid var(--card-border); font-size:12.5px; color:var(--muted); }
.sh-locked-back{ padding:0; border:0; background:none; font:inherit; font-size:12.5px; font-weight:800;
  color:color-mix(in srgb,var(--sh-b) 72%, var(--text)); cursor:pointer; }
.sh-locked-back:hover{ text-decoration:underline; }
@media (max-width:760px){
  .sh-locked{ padding:22px 14px 70px; }
  .sh-locked-card{ grid-template-columns:1fr; }
  .sh-locked-art{ min-height:0; aspect-ratio:16/9; }
  .sh-locked-body{ padding:22px 20px 20px; }
  .sh-hero-unlock{ padding:12px; flex-direction:column; gap:10px; border-radius:18px; }
}

.sh-empty{ grid-column:1/-1; text-align:center; padding:70px 20px; color:var(--muted); }
.sh-empty-ico{ font-size:44px; margin-bottom:10px; }
.sh-empty h3{ margin:0 0 6px; color:var(--text); }
.sh-loading,.sh-studio-loading{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:16px;
  min-height:60vh; color:var(--muted); position:relative; z-index:1; }

/* ============================ STUDIO ============================ */
.sh-studio{ position:relative; min-height:100vh; min-height:100dvh; padding:0 0 40px;
  background:radial-gradient(1200px 600px at 50% -10%, #171a26 0%, #0a0b10 60%), #07080c; color:#eef0f5;
  display:flex; flex-direction:column; }

.sh-studio-bar{ position:sticky; top:0; z-index:8; display:flex; align-items:center; gap:16px; padding:14px 20px;
  background:linear-gradient(180deg,rgba(8,9,14,.92),rgba(8,9,14,.55)); backdrop-filter:blur(14px);
  border-bottom:1px solid rgba(255,255,255,.07); }
.sh-back{ display:inline-flex; align-items:center; gap:6px; padding:9px 14px; border-radius:11px; cursor:pointer;
  border:1px solid rgba(255,255,255,.14); background:rgba(255,255,255,.05); color:#eef0f5; font:inherit; font-weight:600; font-size:14px;
  transition:background .18s, transform .18s; }
.sh-back:hover{ background:rgba(255,255,255,.12); transform:translateX(-2px); }
.sh-back svg{ width:18px; height:18px; }
.sh-studio-title{ flex:1; min-width:0; }
.sh-studio-title h2{ margin:0; font-size:18px; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sh-studio-sub{ font-size:13px; color:#9aa0b0; margin-top:2px; display:flex; align-items:center; gap:8px; min-width:0; }
/* The channel name used to be a bare text node, i.e. an anonymous flex item —
   it collapsed to its min-content width and stacked into a ragged 2-3 line
   column while the level badge sat marooned beside it. As a real element it
   can take the leftover space and truncate on one line instead. */
.sh-studio-src{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.sh-studio-sub .sh-badge{ flex:0 0 auto; background:rgba(255,255,255,.08); color:#dfe3ee; }
.sh-studio-prog{ font-size:13px; font-weight:700; color:var(--sh-c); white-space:nowrap; }

.sh-stage{ flex:1; width:100%; max-width:1140px; margin:0 auto; padding:26px 20px 0;
  display:grid; grid-template-columns:minmax(0,1.35fr) minmax(300px,.9fr); gap:26px; align-items:start; }

/* player */
.sh-player-wrap{ position:sticky; top:84px; }
.sh-player-frame{ position:relative; aspect-ratio:16/9; width:100%; border-radius:18px; overflow:hidden;
  background:#000; box-shadow:0 30px 80px -30px rgba(0,0,0,.9), 0 0 0 1px rgba(255,255,255,.06);
  outline:1px solid transparent; transition:outline-color .3s; }
body.sh-playing .sh-player-frame{ outline-color:color-mix(in srgb,var(--sh-a) 55%, transparent); box-shadow:0 30px 80px -30px rgba(0,0,0,.9), 0 0 40px -10px var(--sh-a); }
.sh-player-frame iframe,.sh-player-frame #shYtMount{ position:absolute; inset:0; width:100%; height:100%; border:0; }
.sh-player-veil{ position:absolute; inset:0; z-index:2; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px;
  background:radial-gradient(circle at center,rgba(8,9,14,.35),rgba(8,9,14,.72)); color:#fff; transition:opacity .3s; cursor:pointer; }
.sh-player-veil.hidden{ opacity:0; pointer-events:none; }
.sh-player-veil span{ font-size:13.5px; color:#cfd3e0; letter-spacing:.02em; }
.sh-bigplay{ width:84px; height:84px; border-radius:50%; border:0; cursor:pointer; display:grid; place-items:center;
  background:linear-gradient(135deg,var(--sh-a),var(--sh-b)); color:#07080c; box-shadow:0 12px 40px -8px var(--sh-b);
  animation:shPulse 2.4s ease-in-out infinite; transition:transform .2s; }
.sh-bigplay:hover{ transform:scale(1.06); } .sh-bigplay svg{ width:38px; height:38px; margin-left:4px; }
.sh-bigplay.replay svg{ margin-left:0; }
@keyframes shPulse{ 0%,100%{ box-shadow:0 12px 40px -8px var(--sh-b), 0 0 0 0 rgba(78,224,242,.4);} 50%{ box-shadow:0 12px 40px -8px var(--sh-b), 0 0 0 16px rgba(78,224,242,0);} }

.sh-timeline{ position:relative; height:8px; margin-top:14px; border-radius:6px; background:rgba(255,255,255,.10); cursor:pointer; }
.sh-timeline-fill{ position:absolute; left:0; top:0; height:100%; width:0; border-radius:6px; background:linear-gradient(90deg,var(--sh-a),var(--sh-b)); }
.sh-timeline-knob{ position:absolute; top:50%; left:0; width:15px; height:15px; border-radius:50%; background:#fff;
  transform:translate(-50%,-50%); box-shadow:0 2px 8px rgba(0,0,0,.5); transition:left .05s linear; }
.sh-hint{ margin-top:9px; text-align:center; font-size:12px; color:#7d8296; }
.sh-hint span{ opacity:.8; } .sh-hint b{ color:#aab0c0; font-weight:700; }

/* transcript rail */
.sh-rail-wrap{ background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.08); border-radius:18px; padding:6px 6px 6px; display:flex; flex-direction:column; min-height:340px; }
.sh-rail-head{ display:flex; align-items:center; justify-content:space-between; padding:12px 14px 8px; }
.sh-rail-label{ font-size:12px; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:#8b90a2; }
.sh-rail-label em{ font-style:normal; letter-spacing:0; text-transform:none; font-weight:500; color:#6d7284; }
.sh-linecount{ font-size:12px; color:#6d7284; }
.sh-rail{ overflow-y:auto; max-height:min(58vh,560px); padding:4px 8px 12px; scroll-behavior:auto; }
.sh-rail::-webkit-scrollbar{ width:8px; } .sh-rail::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.12); border-radius:8px; }
.sh-line{ position:relative; display:flex; gap:12px; align-items:flex-start; width:100%; text-align:left; padding:12px 14px; margin:3px 0;
  border-radius:12px; border:1px solid transparent; background:transparent; color:#aab0c0; font:inherit; font-size:17px; line-height:1.5; cursor:pointer;
  transition:background .18s, color .18s, transform .18s; overflow:hidden; }
.sh-line:hover{ background:rgba(255,255,255,.05); color:#e6e9f2; }
.sh-line-num{ flex:none; width:22px; height:22px; margin-top:2px; display:grid; place-items:center; border-radius:6px; font-size:11px; font-weight:800;
  background:rgba(255,255,255,.06); color:#7d8296; }
.sh-line-txt{ position:relative; z-index:1; transition:filter .25s; }
.sh-line-sweep{ position:absolute; left:0; top:0; bottom:0; width:0; z-index:0;
  background:linear-gradient(90deg,rgba(78,224,242,.16),rgba(139,109,255,.14)); pointer-events:none; }
.sh-line.active{ color:#fff; background:rgba(255,255,255,.06); border-color:rgba(255,255,255,.12); font-weight:600;
  box-shadow:inset 3px 0 0 var(--sh-a); transform:translateX(2px); }
.sh-line.active .sh-line-num{ background:linear-gradient(135deg,var(--sh-a),var(--sh-b)); color:#07080c; }
.sh-line.looped{ box-shadow:inset 3px 0 0 var(--sh-c); }
.sh-line.looped .sh-line-num::after{ content:'↻'; }
.hide-subs .sh-line-txt{ filter:blur(7px); opacity:.55; }
.hide-subs .sh-line.active .sh-line-txt{ filter:blur(5px); }
.hide-subs .sh-line:hover .sh-line-txt{ filter:none; opacity:1; }
.sh-rail-empty{ padding:30px 16px; text-align:center; color:#7d8296; font-size:14.5px; }

/* control dock */
.sh-dock{ position:sticky; bottom:0; z-index:8; margin-top:26px; padding:14px 20px calc(14px + env(safe-area-inset-bottom,0px));
  display:flex; flex-direction:column; align-items:center; gap:12px;
  background:linear-gradient(0deg,rgba(8,9,14,.96),rgba(8,9,14,.55)); backdrop-filter:blur(16px); border-top:1px solid rgba(255,255,255,.07); }
.sh-dock-row{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; justify-content:center; }
.sh-ctl{ width:46px; height:46px; border-radius:50%; border:1px solid rgba(255,255,255,.14); background:rgba(255,255,255,.06);
  color:#eef0f5; cursor:pointer; display:grid; place-items:center; transition:background .18s, transform .12s, border-color .18s; }
.sh-ctl:hover{ background:rgba(255,255,255,.13); } .sh-ctl:active{ transform:scale(.93); }
.sh-ctl svg{ width:20px; height:20px; }
.sh-ctl.big{ width:60px; height:60px; background:linear-gradient(135deg,var(--sh-a),var(--sh-b)); border-color:transparent; color:#07080c;
  box-shadow:0 10px 30px -8px var(--sh-b); }
.sh-ctl.big svg{ width:26px; height:26px; }
.sh-ctl.big .ic-pause{ display:none; } .sh-ctl.big.playing .ic-play{ display:none; } .sh-ctl.big.playing .ic-pause{ display:block; }

.sh-seg{ display:inline-flex; align-items:center; gap:2px; padding:4px; border-radius:12px; background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.10); }
.sh-seg-label{ font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:#7d8296; padding:0 8px 0 6px; }
.sh-seg button{ padding:6px 12px; border-radius:9px; border:0; background:transparent; color:#c3c8d6; font:inherit; font-size:13px; font-weight:700; cursor:pointer; transition:all .16s; }
.sh-seg button:hover{ color:#fff; } .sh-seg button.on{ background:linear-gradient(135deg,var(--sh-a),var(--sh-b)); color:#07080c; }
.sh-toggle{ display:inline-flex; align-items:center; gap:8px; padding:9px 14px; border-radius:11px; cursor:pointer;
  border:1px solid rgba(255,255,255,.12); background:rgba(255,255,255,.05); color:#c3c8d6; font:inherit; font-size:13px; font-weight:600; transition:all .16s; }
.sh-toggle:hover{ color:#fff; } .sh-toggle svg{ width:18px; height:18px; }
.sh-toggle.on{ background:rgba(198,242,78,.16); border-color:rgba(198,242,78,.4); color:var(--sh-c); }
/* Precision (on-device AI) toggle — distinct cyan→violet identity */
.sh-prec svg{ width:16px; height:16px; }
.sh-prec.on{ color:#eafcff; background:linear-gradient(120deg,rgba(78,224,242,.24),rgba(139,109,255,.24));
  border-color:color-mix(in srgb,var(--sh-a) 55%, transparent); box-shadow:0 0 0 1px rgba(78,224,242,.25), 0 6px 18px -8px var(--sh-b); }
.sh-prec.on svg{ color:var(--sh-a); filter:drop-shadow(0 0 5px rgba(78,224,242,.6)); }
.sh-prec.loading{ position:relative; overflow:hidden; }
.sh-prec.loading::after{ content:""; position:absolute; inset:0; border-radius:inherit;
  background:linear-gradient(90deg,transparent,rgba(78,224,242,.22),transparent); animation:shPrecScan 1.1s linear infinite; }
@keyframes shPrecScan{ from{ transform:translateX(-100%); } to{ transform:translateX(100%); } }

/* record panel */
.sh-record{ max-width:1140px; width:100%; margin:20px auto 0; padding:0 20px; display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.sh-rec-left{ display:flex; align-items:center; gap:14px; }
/* bright mic button — a glowing coral→magenta puck that flips to a red pulsing
   stop while recording */
.sh-rec-btn{ position:relative; width:56px; height:56px; border-radius:50%; border:0; cursor:pointer;
  display:grid; place-items:center; color:#fff; transition:transform .16s, box-shadow .2s, filter .2s;
  background:radial-gradient(circle at 32% 24%,#ffb072,#ff3d77 52%,#c02be0);
  box-shadow:0 9px 24px -7px rgba(255,61,119,.62), inset 0 0 0 2px rgba(255,255,255,.2); }
.sh-rec-btn:hover{ transform:translateY(-1px); filter:brightness(1.06);
  box-shadow:0 13px 30px -7px rgba(255,61,119,.8), inset 0 0 0 2px rgba(255,255,255,.3); }
.sh-rec-btn:active{ transform:scale(.95); }
.sh-rec-btn > svg{ position:relative; z-index:1; filter:drop-shadow(0 1px 2px rgba(0,0,0,.35)); }
.sh-rec-mic{ width:23px; height:23px; }
.sh-rec-stop{ width:20px; height:20px; display:none; }
.sh-rec-ring{ position:absolute; inset:-3px; border-radius:50%; pointer-events:none; }
.sh-rec-btn.rec{ background:radial-gradient(circle at 32% 24%,#ff7a7a,#ff2d55 58%,#e0104a); }
.sh-rec-btn.rec .sh-rec-mic{ display:none; }
.sh-rec-btn.rec .sh-rec-stop{ display:block; }
.sh-rec-btn.rec .sh-rec-ring{ animation:shRecPulse 1.15s ease-in-out infinite; }
@keyframes shRecPulse{ 0%,100%{ box-shadow:0 0 0 0 rgba(255,45,85,.55);} 50%{ box-shadow:0 0 0 13px rgba(255,45,85,0);} }
.sh-rec-copy{ display:flex; flex-direction:column; }
.sh-rec-copy b{ font-size:14.5px; } .sh-rec-copy span{ font-size:12.5px; color:#8b90a2; }
.sh-rec-right{ display:flex; align-items:center; gap:8px; }
.sh-btn{ padding:9px 15px; border-radius:11px; border:1px solid rgba(255,255,255,.14); background:rgba(255,255,255,.06); color:#eef0f5;
  font:inherit; font-size:13.5px; font-weight:700; cursor:pointer; transition:all .16s; }
.sh-btn:hover{ background:rgba(255,255,255,.13); }
.sh-btn.primary{ background:linear-gradient(135deg,var(--sh-a),var(--sh-b)); border-color:transparent; color:#07080c; }
.sh-btn.score{ background:linear-gradient(120deg,var(--sh-c),var(--sh-a)); border-color:transparent; color:#07130a;
  box-shadow:0 6px 16px -6px var(--sh-a); }
.sh-btn.score:hover{ filter:brightness(1.05); }
.sh-btn.ghost{ background:rgba(255,255,255,.05); }
.sh-btn.ghost.danger{ color:#ff8a98; border-color:rgba(255,90,110,.3); padding:9px 12px; }

/* ============================ RESPONSIVE ============================ */
@media (max-width:900px){
  .sh-stage{ grid-template-columns:1fr; gap:18px; padding-top:18px; }
  .sh-player-wrap{ position:static; }
  .sh-rail{ max-height:44vh; }
  .sh-hero{ padding:44px 6px 30px; }
}
/* Below ~640px there is no longer room for [Library][title][toggle] on one
   line — the title box got squeezed to ~230px, clipping the clip name and
   crushing the channel + badge. Give the title its own full-width row under
   the two controls; everything gets its natural size back. */
@media (max-width:640px){
  .sh-studio-bar{ flex-wrap:wrap; row-gap:6px; gap:10px; padding:10px 14px; }
  .sh-back{ order:1; }
  /* `.sh-studio-bar` prefix is load-bearing: a later `.sh-theme{margin-left:6px}`
     (further down this file) outranks a bare `.sh-theme` here on source order. */
  .sh-studio-bar .sh-theme{ order:2; margin-left:auto; }
  .sh-studio-prog{ order:3; }
  .sh-studio-title{ order:4; flex:1 0 100%; }
  .sh-studio-title h2{ font-size:16.5px; }
  .sh-studio-sub{ margin-top:1px; }
}
@media (max-width:560px){
  .sh-hub{ padding:0 14px 70px; }
  .sh-grid{ grid-template-columns:1fr; }
  /* The filter bar is sticky and holds THREE wrapping chip rows (4 levels,
     7 types, N accents) plus the search field. On a 390px phone those chips
     wrap to ~8 rows, so the pinned bar measured ~370px — over half the visible
     viewport, permanently, while scrolling a 939-clip catalog. Let it scroll
     away here; it is still the first thing above the grid. */
  .sh-filters{ position:static; }
  .sh-studio-prog{ display:none; }
  .sh-dock-row.tools{ gap:8px; }
  .sh-seg-label{ display:none; }
  .sh-record{ flex-direction:column; align-items:stretch; }
  .sh-rec-right{ justify-content:center; }
}

/* ============================ LIGHT THEME (hub only; studio stays cinematic) ============================ */
:root[data-theme="light"] .sh-badge.lv-beg{ color:#0a7a3d; background:rgba(16,185,90,.14); }
:root[data-theme="light"] .sh-badge.lv-int{ color:#b45309; background:rgba(245,158,11,.16); }
:root[data-theme="light"] .sh-badge.lv-adv{ color:#7c3aed; background:rgba(124,58,237,.14); }
:root[data-theme="light"] .sh-card-thumb{ background:#e2e6ef; }

/* homepage tile icon accent (loaded globally, used by the /shadowing tile) */
/* The homepage tile's plate and glyph colour both live with its siblings in
   02-homepage.css — a rule here at (0,1,1) could never beat the base
   `.tile .ico svg` at (0,2,1) anyway, which is exactly how the row's
   "dark icon on bright bg" rule sat dead for so long. */

/* ============================================================================
   ENHANCEMENTS — custom player controls, per-word karaoke, richer motion
   (appended so the cascade overrides the base rules above where needed)
   ============================================================================ */

/* ---- player frame layering: veil sits above the custom control bar ------- */
.sh-player-veil{ z-index:8; }
.sh-player-frame{ isolation:isolate; }

/* click-to-play catcher (fills the video; the bar + veil sit above it) */
.sh-click{ position:absolute; inset:0; z-index:2; cursor:pointer; background:transparent; }

/* ---- custom control bar (bottom of the video) ---------------------------- */
.sh-pbar{ position:absolute; left:0; right:0; bottom:0; z-index:3;
  display:flex; align-items:center; gap:9px; padding:40px 12px 11px;
  background:linear-gradient(0deg,rgba(4,5,9,.86),rgba(4,5,9,.28) 55%,transparent);
  opacity:0; transform:translateY(6px); transition:opacity .24s ease, transform .24s ease; pointer-events:none; }
.sh-player-frame:hover .sh-pbar,
.sh-player-frame:focus-within .sh-pbar,
body:not(.sh-playing) .sh-pbar,
.sh-pbar.menu-open{ opacity:1; transform:none; pointer-events:auto; }
.sh-pbar-spacer{ flex:1; }
.sh-pbar-time{ font-size:12.5px; font-weight:700; color:#dfe3ee; font-variant-numeric:tabular-nums; letter-spacing:.01em;
  text-shadow:0 1px 3px rgba(0,0,0,.6); padding-left:2px; }
.sh-pbar-btn{ display:inline-flex; align-items:center; gap:7px; height:34px; padding:0 12px; border-radius:10px;
  border:1px solid rgba(255,255,255,.16); background:rgba(12,14,22,.5); color:#eef0f5; font:inherit; font-size:12.5px; font-weight:700;
  cursor:pointer; backdrop-filter:blur(8px); transition:background .16s, border-color .16s, transform .12s; }
.sh-pbar-btn:hover{ background:rgba(30,34,48,.72); border-color:rgba(255,255,255,.32); }
.sh-pbar-btn:active{ transform:scale(.94); }
.sh-pbar-btn.icon{ width:36px; padding:0; justify-content:center; }
.sh-pbar-btn svg{ width:18px; height:18px; }
.sh-pbar-btn .chev{ width:13px; height:13px; opacity:.65; transition:transform .2s; }
#shGear[aria-expanded="true"] .chev{ transform:rotate(180deg); }
#shGear b{ font-weight:800; min-width:34px; text-align:left; }
/* play/pause icon swap on the bar button */
.sh-pbar-btn.play .ic-pause{ display:none; }
.sh-pbar-btn.play.playing .ic-play{ display:none; }
.sh-pbar-btn.play.playing .ic-pause{ display:block; }
/* fullscreen icon swap */
.sh-pbar-btn .ic-fsx{ display:none; }
.sh-player-frame.is-fs .ic-fs{ display:none; }
.sh-player-frame.is-fs .ic-fsx{ display:block; }

/* ---- quality menu -------------------------------------------------------- */
.sh-qwrap{ position:relative; display:inline-flex; }
.sh-qmenu{ position:absolute; right:0; bottom:calc(100% + 10px); z-index:6; min-width:200px; padding:6px;
  max-height:300px; overflow-y:auto; overscroll-behavior:contain;
  border-radius:14px; background:rgba(12,14,22,.97); border:1px solid rgba(255,255,255,.12);
  box-shadow:0 24px 60px -18px rgba(0,0,0,.85); backdrop-filter:blur(18px) saturate(150%);
  opacity:0; transform:translateY(8px) scale(.96); transform-origin:bottom right; pointer-events:none;
  transition:opacity .17s ease, transform .17s cubic-bezier(.2,.8,.3,1); }
.sh-qmenu.open{ opacity:1; transform:none; pointer-events:auto; }
.sh-qmenu::-webkit-scrollbar{ width:7px; } .sh-qmenu::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.14); border-radius:7px; }
.sh-qmenu-h{ font-size:10.5px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color:#8288a0; padding:7px 10px 5px; }
.sh-qmenu-h em{ font-style:normal; letter-spacing:.02em; font-weight:600; text-transform:none; color:#6a7086; }
.sh-qmenu-sep{ height:1px; margin:6px 8px; background:rgba(255,255,255,.09); }
/* subtle "CC on" cue on the gear button */
#shGear.cc-on{ border-color:color-mix(in srgb,var(--sh-a) 55%, rgba(255,255,255,.16)); }
#shGear.cc-on b{ color:var(--sh-a); }
.sh-qopt{ display:flex; align-items:center; justify-content:space-between; gap:10px; width:100%; padding:9px 10px; border-radius:9px;
  border:0; background:transparent; color:#cdd2e2; font:inherit; font-size:13.5px; font-weight:600; cursor:pointer; text-align:left;
  transition:background .14s, color .14s; }
.sh-qopt:hover{ background:rgba(255,255,255,.08); color:#fff; }
.sh-qopt.on{ color:#fff; }
.sh-qopt-l{ display:flex; flex-direction:column; line-height:1.25; }
.sh-qopt-l em{ font-style:normal; font-size:11px; font-weight:500; color:#7d8296; margin-top:1px; }
.sh-qopt .tick{ width:16px; height:16px; flex:none; opacity:0; color:var(--sh-a); transform:scale(.6); transition:opacity .14s, transform .14s; }
.sh-qopt.on .tick{ opacity:1; transform:none; }
.sh-qmenu-note{ padding:8px 10px 6px; margin-top:2px; font-size:11px; line-height:1.45; color:#7d8296; border-top:1px solid rgba(255,255,255,.07); }

/* ---- fullscreen: let the frame fill the screen -------------------------- */
.sh-player-frame:fullscreen{ aspect-ratio:auto; width:100vw; height:100vh; border-radius:0; box-shadow:none; background:#000; }
.sh-player-frame:-webkit-full-screen{ aspect-ratio:auto; width:100vw; height:100vh; border-radius:0; }
.sh-player-frame.is-fs .sh-pbar{ padding:52px 26px 20px; }

/* ---- timeline: a little more premium + scrubbable feel ------------------ */
.sh-timeline{ height:6px; transition:height .18s ease; }
.sh-timeline:hover{ height:10px; }
.sh-timeline-fill{ box-shadow:0 0 12px -2px color-mix(in srgb,var(--sh-a) 65%, transparent); }
.sh-timeline-knob{ opacity:0; transition:opacity .18s ease, left .05s linear, transform .12s ease; }
.sh-timeline:hover .sh-timeline-knob{ opacity:1; }
body.sh-playing .sh-timeline-knob{ opacity:1; }

/* keyboard-hint strip (replaces the old "tap the gear" hint) */
.sh-tip{ margin-top:11px; display:flex; align-items:center; justify-content:center; gap:7px; flex-wrap:wrap;
  font-size:12px; color:#7d8296; }
.sh-tip-key{ display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 6px; border-radius:6px;
  background:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.12); color:#aab0c0; font-size:11px; font-weight:700; }
.sh-tip-dot{ opacity:.4; margin:0 2px; }

/* ---- per-word karaoke highlight ----------------------------------------- */
.sh-line-txt{ display:inline; }
.sh-w{ transition:color .16s ease, opacity .16s ease, text-shadow .16s ease; }
.sh-line.active .sh-w{ opacity:.42; }
.sh-line.active .sh-w.spoken{ opacity:1; color:#fff; }
.sh-line.active .sh-w.now{ opacity:1; color:var(--sh-a);
  text-shadow:0 0 18px color-mix(in srgb,var(--sh-a) 65%, transparent); }
:root[data-theme="light"] .sh-line.active .sh-w.now{ color:#0aa; }

/* ---- transcript rail: staggered entrance + smoother active state -------- */
.sh-rail .sh-line{ animation:shLineIn .45s cubic-bezier(.2,.7,.3,1) both;
  animation-delay:calc(min(var(--li,0),22) * 26ms); }
/* Start state in the keyframes, not on .sh-line — same reason as shRise above:
   an `animation` override on a line state must not be able to hide the line. */
@keyframes shLineIn{ from{ opacity:0; transform:translateY(7px); } to{ opacity:1; transform:none; } }
.sh-line{ transition:background .2s ease, color .2s ease, transform .2s cubic-bezier(.2,.7,.3,1), box-shadow .2s ease; }
.sh-line.active{ box-shadow:inset 3px 0 0 var(--sh-a), 0 8px 26px -16px var(--sh-a); }
.sh-line.active .sh-line-num{ animation:shNumPop .3s ease; }
@keyframes shNumPop{ 0%{ transform:scale(.7); } 60%{ transform:scale(1.12); } 100%{ transform:scale(1); } }

/* ---- dock big-play: glow while playing ---------------------------------- */
.sh-ctl.big{ transition:background .18s, transform .12s, box-shadow .25s; }
body.sh-playing .sh-ctl.big{ box-shadow:0 10px 30px -8px var(--sh-b), 0 0 0 6px color-mix(in srgb,var(--sh-a) 16%, transparent); }

/* ---- hub: card sheen sweep on hover ------------------------------------- */
.sh-card-thumb::after{ content:''; position:absolute; inset:0; z-index:1; pointer-events:none; opacity:0;
  background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.22) 48%,transparent 66%);
  transform:translateX(-120%); transition:opacity .2s; }
.sh-card:hover .sh-card-thumb::after{ opacity:1; animation:shSheen .9s ease forwards; }
@keyframes shSheen{ to{ transform:translateX(120%); } }
.sh-card:focus-visible{ outline:2px solid var(--sh-a); outline-offset:3px; }

/* ---- hub hero: gentle gradient shimmer + glow on the accent line -------- */
.sh-grad{ background-size:200% auto; animation:shShimmer 6s linear infinite;
  filter:drop-shadow(0 4px 30px color-mix(in srgb,var(--sh-b) 45%, transparent)); }
@keyframes shShimmer{ to{ background-position:200% center; } }
.sh-eyebrow{ position:relative; }
.sh-hero-stats .sh-stat{ transition:transform .25s cubic-bezier(.2,.8,.25,1), box-shadow .25s, border-color .25s; }
.sh-hero-stats .sh-stat:hover{ transform:translateY(-4px);
  border-color:color-mix(in srgb,var(--sh-a) 40%, var(--card-border));
  box-shadow:0 16px 34px -18px color-mix(in srgb,var(--sh-b) 70%, transparent); }

/* ---- filter chips: active glow + hover lift ----------------------------- */
.sh-chip{ transition:background .18s, color .18s, box-shadow .2s, transform .16s cubic-bezier(.2,.8,.25,1); }
.sh-chip:hover{ transform:translateY(-2px); }
.sh-chip:active{ transform:scale(.96); }
.sh-chip.on{ box-shadow:0 8px 22px -6px var(--sh-b), 0 0 0 1px color-mix(in srgb,var(--sh-a) 30%, transparent) inset; }

/* ============ hub premium polish: glow · depth · motion ============ */
/* thumbnail: cinematic bottom scrim so overlays read on any frame */
.sh-card-thumb::before{ content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(180deg,transparent 52%,rgba(6,8,18,.5)); opacity:.9; transition:opacity .35s; }
.sh-card:hover .sh-card-thumb::before{ opacity:.5; }

/* play overlay: glowing, breathing ring behind the triangle */
.sh-card-play::after{ content:''; position:absolute; top:50%; left:50%; width:64px; height:64px; margin:-32px 0 0 -32px;
  border-radius:50%; border:2px solid color-mix(in srgb,var(--sh-a) 75%, transparent);
  box-shadow:0 0 26px 3px color-mix(in srgb,var(--sh-a) 45%, transparent),
             inset 0 0 18px color-mix(in srgb,var(--sh-b) 42%, transparent); }
/* animate the ring only while hovered — never 265 pulses running at once */
.sh-card:hover .sh-card-play::after{ animation:shPlayPulse 1.9s ease-in-out infinite; }
.sh-card-play svg{ position:relative; z-index:1;
  filter:drop-shadow(0 4px 14px rgba(0,0,0,.55)) drop-shadow(0 0 10px color-mix(in srgb,var(--sh-a) 60%, transparent)); }
@keyframes shPlayPulse{ 0%,100%{ transform:scale(.88); opacity:.5; } 50%{ transform:scale(1.06); opacity:1; } }

/* featured card: permanent breathing brand halo.
   ⚠️ The animation MUST live on the ::before pseudo-element. Putting an
   `animation` on .sh-card itself REPLACES the shRise entrance animation, and
   the card then never fades in — it renders as an empty gap in the grid. */
.sh-card.feat{ border-color:color-mix(in srgb,var(--sh-b) 40%, var(--card-border)); }
.sh-card.feat::before{ content:''; position:absolute; inset:0; z-index:3; pointer-events:none;
  border-radius:inherit;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--sh-b) 28%, transparent);
  animation:shFeatBreathe 3.6s ease-in-out infinite; }
.sh-card.feat:hover::before{ animation:none; }
@keyframes shFeatBreathe{
  0%,100%{ box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--sh-b) 28%, transparent); }
  50%{ box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--sh-c) 52%, transparent),
                  inset 0 0 26px -6px color-mix(in srgb,var(--sh-b) 45%, transparent); } }

/* level badges: soft colored glow */
.sh-badge.lv-beg{ box-shadow:0 0 15px -5px rgba(40,220,120,.55); }
.sh-badge.lv-int{ box-shadow:0 0 15px -5px rgba(255,170,60,.55); }
.sh-badge.lv-adv{ box-shadow:0 0 15px -5px rgba(160,110,255,.55); }

/* duration pill picks up the brand on hover; title nudges toward the accent */
.sh-card-dur{ transition:background .3s, color .3s; }
.sh-card:hover .sh-card-dur{ color:#fff;
  background:linear-gradient(120deg,color-mix(in srgb,var(--sh-a) 88%,#043),color-mix(in srgb,var(--sh-b) 88%,#203)); }
.sh-card-title{ transition:color .25s; }
.sh-card:hover .sh-card-title{ color:color-mix(in srgb,var(--text) 82%, var(--sh-a)); }
.sh-card-done{ animation:shDonePop .4s cubic-bezier(.2,1.5,.4,1) both; }
@keyframes shDonePop{ from{ transform:scale(0); } }

/* ---- mobile: keep the control bar visible (no hover on touch) ----------- */
@media (max-width:900px){
  .sh-pbar{ opacity:1; transform:none; pointer-events:auto;
    padding-top:30px; background:linear-gradient(0deg,rgba(4,5,9,.9),transparent); }
  .sh-timeline{ height:8px; }
  .sh-timeline-knob{ opacity:1; }
}
@media (max-width:560px){
  .sh-pbar-time{ display:none; }
  .sh-pbar{ gap:7px; }
  #shGear b{ min-width:0; }
}

/* ---- respect reduced-motion --------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .sh-aurora span, .sh-eq i, .sh-grad, .sh-bigplay, .sh-rec-btn.rec .sh-rec-ring,
  .sh-card, .sh-rail .sh-line, .sh-card:hover .sh-card-thumb::after,
  .sh-card-play::after, .sh-card.feat::before, .sh-card-done,
  .sh-line.active .sh-line-num{ animation:none !important; }
  .sh-card{ opacity:1; transform:none; }
  .sh-rail .sh-line{ opacity:1; transform:none; }
  * { scroll-behavior:auto !important; }
}

/* ============================================================================
   STUDIO LAYOUT v2 — one cohesive control console under the video, a tall
   transcript beside it, everything reachable without scroll-hunting.
   Grid areas let the DOM stay simple while desktop/mobile place things well.
   (Appended last so it overrides the base studio layout.)
   ============================================================================ */
.sh-studio{ height:100vh; height:100dvh; min-height:0; padding:0; }
.sh-studio-bar{ flex:0 0 auto; }

.sh-stage{
  flex:1 1 auto; min-height:0; width:100%; max-width:1300px; margin:0 auto;
  padding:16px 24px 22px; gap:16px 28px;
  grid-template-columns:minmax(0,1.5fr) minmax(340px,.94fr);
  grid-template-rows:auto minmax(0,1fr);
  grid-template-areas:
    "video   rail"
    "console rail";
  align-items:start;
}

/* video cell — no longer sticky; sized to fit the viewport height */
.sh-player-wrap{ grid-area:video; position:static; top:auto; display:flex; }
.sh-player-frame{ width:100%; aspect-ratio:16/9; max-height:min(56vh,60vh); margin:0 auto; }

/* the unified console */
.sh-console{ grid-area:console; align-self:start; position:relative; display:flex; flex-direction:column; gap:13px;
  padding:14px 16px 16px; border-radius:18px;
  background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.018));
  border:1px solid rgba(255,255,255,.09); box-shadow:0 20px 54px -34px rgba(0,0,0,.85); }

/* scrubber row */
.sh-scrub{ display:flex; align-items:center; gap:14px; }
.sh-scrub .sh-timeline{ flex:1; margin-top:0; }
.sh-scrub-time{ flex:none; min-width:92px; text-align:right; font-size:12.5px; font-weight:700;
  color:#cfd3e0; font-variant-numeric:tabular-nums; letter-spacing:.02em; }

/* main controls row: transport + speed + loop */
.sh-console-main{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.sh-transport{ display:flex; align-items:center; gap:9px; }
.sh-console-main #shLoop{ margin-left:auto; }

/* primary play button (the anchor of the console) */
.sh-play{ width:56px; height:56px; border-radius:50%; border:0; cursor:pointer; display:grid; place-items:center;
  background:linear-gradient(135deg,var(--sh-a),var(--sh-b)); color:#07080c;
  box-shadow:0 12px 30px -8px var(--sh-b); transition:transform .12s, box-shadow .25s; }
.sh-play:hover{ transform:scale(1.05); } .sh-play:active{ transform:scale(.94); }
.sh-play svg{ width:26px; height:26px; }
.sh-play .ic-pause{ display:none; }
.sh-play.playing .ic-play{ display:none; } .sh-play.playing .ic-pause{ display:block; }
body.sh-playing .sh-play{ box-shadow:0 12px 30px -8px var(--sh-b), 0 0 0 6px color-mix(in srgb,var(--sh-a) 18%, transparent); }
.sh-ctl.subtle{ width:42px; height:42px; opacity:.82; } .sh-ctl.subtle:hover{ opacity:1; }

/* practice row: hide-subtitles + inline recorder */
.sh-console-foot{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.sh-rec{ display:flex; align-items:center; gap:11px; margin-left:auto;
  padding:6px 12px 6px 6px; border-radius:14px; background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.08); }
.sh-rec .sh-rec-btn{ width:44px; height:44px; }
.sh-rec .sh-rec-mic{ width:19px; height:19px; }
.sh-rec .sh-rec-stop{ width:16px; height:16px; }
.sh-rec-copy{ display:flex; flex-direction:column; min-width:0; }
.sh-rec-copy b{ font-size:13px; line-height:1.2; }
/* This is the recorder's status line, and it carries real error copy
   ("Microphone blocked. Allow mic access to record yourself."). A hard
   190px + nowrap + ellipsis cut that to "Microphone blocked. Allow mic ac…"
   at EVERY width — the actionable half never reached the user. Let it wrap. */
.sh-rec-copy span{ font-size:11.5px; color:#8b90a2; max-width:min(320px, 100%); line-height:1.4; }
.sh-rec .sh-btn{ padding:7px 11px; font-size:12.5px; }
.sh-rec .sh-btn.ghost.danger{ padding:7px 10px; }
/* the compare buttons stay hidden until a take exists ([hidden] must beat the
   base .sh-rec-right{display:flex}) */
.sh-rec-right[hidden]{ display:none !important; }

/* live spectrum meter — reacts to the learner's voice while recording */
.sh-meter{ display:none; align-items:flex-end; gap:2px; height:24px; }
.sh-rec.live .sh-meter{ display:flex; }
.sh-meter i{ width:3px; height:24px; border-radius:2px; transform:scaleY(0.12); transform-origin:bottom;
  background:linear-gradient(to top,var(--sh-a),var(--sh-c)); transition:transform .05s linear; }

/* ============================================================================
   PRONUNCIATION REPORT — a focused overlay that pops after a take: a score
   ring, the scored line coloured word-by-word (clear / unclear, stress words
   marked), a "focus on" list, and compare / retry controls. Fixed-position so
   it floats over the studio grid (which is overflow-hidden / 100vh).
   ============================================================================ */
.sh-report-modal{ position:fixed; inset:0; z-index:1200; display:flex; align-items:center; justify-content:center; padding:20px; }
.sh-report-modal[hidden]{ display:none; }
.sh-report-backdrop{ position:absolute; inset:0; background:rgba(4,5,10,.66); backdrop-filter:blur(6px); animation:shFadeIn .18s ease both; }
.sh-report{ position:relative; z-index:1; width:min(560px,100%); max-height:calc(100vh - 40px); max-height:calc(100dvh - 40px); overflow-y:auto;
  border-radius:22px; border:1px solid rgba(255,255,255,.1); background:linear-gradient(180deg,#14161f,#0d0f16);
  box-shadow:0 40px 100px -30px rgba(0,0,0,.85); padding:18px 20px 22px; animation:shReportPop .3s cubic-bezier(.2,.8,.3,1) both; }
@keyframes shFadeIn{ from{ opacity:0; } }
@keyframes shReportPop{ from{ opacity:0; transform:translateY(16px) scale(.97); } }
.sh-report-bar{ display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
.sh-report-kicker{ font-size:11px; font-weight:800; letter-spacing:.14em; text-transform:uppercase;
  background:linear-gradient(100deg,var(--sh-a),var(--sh-c)); -webkit-background-clip:text; background-clip:text; color:transparent; }
.sh-report-x{ width:30px; height:30px; border-radius:9px; border:1px solid rgba(255,255,255,.12); background:rgba(255,255,255,.05);
  color:#c7ccda; font-size:14px; cursor:pointer; transition:all .16s; }
.sh-report-x:hover{ background:rgba(255,255,255,.13); color:#fff; }

.sh-report-head{ display:flex; align-items:center; gap:18px; margin:6px 0 16px; }
.sh-ring{ position:relative; width:104px; height:104px; flex:none; }
.sh-ring svg{ width:100%; height:100%; transform:rotate(-90deg); }
.sh-ring circle{ fill:none; stroke-width:9; stroke-linecap:round; }
.sh-ring circle.bg{ stroke:rgba(255,255,255,.09); }
.sh-ring circle.fg{ stroke:var(--sh-a); transition:stroke-dashoffset .9s cubic-bezier(.2,.8,.3,1); }
.sh-ring.good circle.fg{ stroke:var(--sh-c); }
.sh-ring.ok   circle.fg{ stroke:var(--sh-a); }
.sh-ring.low  circle.fg{ stroke:#ff8a5b; }
.sh-ring-num{ position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; }
.sh-ring-num b{ font-size:30px; font-weight:800; line-height:1; color:#f4f6fb; }
.sh-ring-num b i{ font-size:14px; font-weight:700; font-style:normal; color:#9aa0b2; margin-left:1px; }
.sh-ring-num span{ font-size:10.5px; letter-spacing:.12em; text-transform:uppercase; color:#8b90a2; margin-top:3px; }
.sh-report-verdict h3{ margin:0 0 4px; font-size:19px; font-weight:800; color:#f4f6fb; }
.sh-report-verdict p{ margin:0; font-size:13px; color:#aeb3c4; }
.sh-report-verdict p b{ color:var(--sh-c); }
.sh-report-note{ margin-top:6px !important; font-size:11.5px !important; color:#8b90a2 !important; }

.sh-report-line{ font-size:19px; line-height:1.9; padding:14px 15px; border-radius:14px;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.07); margin-bottom:12px; }
.sh-rw{ font:inherit; border:0; background:transparent; padding:1px 3px; border-radius:6px; cursor:pointer;
  color:#dfe3ee; transition:background .14s, color .14s, transform .1s; position:relative; }
.sh-rw:hover{ background:rgba(255,255,255,.1); transform:translateY(-1px); }
.sh-rw.plain{ cursor:default; color:#8b90a2; } .sh-rw.plain:hover{ background:transparent; transform:none; }
.sh-rw.ok{  color:#c6f2b0; }
.sh-rw.bad{ color:#ff9db0; text-decoration:underline wavy rgba(255,90,110,.7); text-underline-offset:4px; }
.sh-rw.key{ font-weight:800; }
.sh-rw.key::after{ content:""; position:absolute; left:50%; top:-3px; width:4px; height:4px; border-radius:50%;
  transform:translateX(-50%); background:var(--sh-c); }
.sh-rw.key.bad::after{ background:#ff5a6e; }

.sh-report-legend{ display:flex; flex-wrap:wrap; gap:14px; font-size:11.5px; color:#9aa0b2; margin-bottom:12px; }
.sh-report-legend span{ display:inline-flex; align-items:center; gap:6px; }
.sh-report-legend .lg{ width:11px; height:11px; border-radius:3px; }
.sh-report-legend .lg.ok{ background:#c6f2b0; } .sh-report-legend .lg.bad{ background:#ff9db0; }
.sh-report-legend .lg.key{ background:var(--sh-c); border-radius:50%; }

.sh-report-focus{ display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:16px; }
.sh-focus-label{ font-size:11px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:#8b90a2; }
.sh-focus-chip{ font-size:13px; font-weight:700; padding:5px 11px; border-radius:9px; color:#ffd9b0;
  background:rgba(255,138,91,.12); border:1px solid rgba(255,138,91,.32); }

/* substituted word: show it was a wrong word (not just unclear) on hover */
.sh-rw.bad{ cursor:help; }

/* "We heard" — the recogniser's transcript, so the learner sees what came across */
.sh-heard{ display:flex; gap:9px; align-items:baseline; margin:-2px 0 14px; padding:10px 13px; border-radius:11px;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.06); }
.sh-heard-lbl{ flex:none; font-size:10.5px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:#8b90a2; }
.sh-heard-txt{ font-size:13.5px; color:#c4c9d6; font-style:italic; line-height:1.45; }

/* "Work on these" — actionable rows, tap any to hear the native word */
.sh-improve{ margin-bottom:16px; }
.sh-improve-h{ font-size:11px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:#8b90a2; margin-bottom:8px; }
.sh-improve-row{ display:flex; align-items:center; gap:10px; width:100%; text-align:left; margin-bottom:7px;
  padding:9px 12px; border-radius:11px; border:1px solid rgba(255,138,91,.28); background:rgba(255,138,91,.08);
  color:#f4f6fb; font:inherit; cursor:pointer; transition:background .15s, transform .1s, border-color .15s; }
.sh-improve-row:last-child{ margin-bottom:0; }
.sh-improve-row:hover{ background:rgba(255,138,91,.16); border-color:rgba(255,138,91,.5); transform:translateX(2px); }
.sh-improve-word{ font-size:15px; font-weight:800; color:#ffd9b0; }
.sh-improve-heard{ font-size:12.5px; color:#9aa0b2; }
.sh-improve-play{ margin-left:auto; font-size:15px; opacity:.85; }

/* sub-score breakdown — Accuracy / Clarity / Fluency / Intonation meters */
.sh-axes-wrap{ margin:2px 0 16px; }
.sh-axes-h{ font-size:10.5px; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:#8b90a2; margin-bottom:9px; }
.sh-axes{ display:flex; flex-direction:column; gap:9px; padding:13px 15px; border-radius:14px;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.07); }
.sh-axis{ display:grid; grid-template-columns:78px 1fr 30px; align-items:center; gap:11px; }
.sh-axis-lbl{ font-size:12px; font-weight:700; color:#c4c9d6; }
.sh-axis-bar{ position:relative; height:7px; border-radius:5px; background:rgba(255,255,255,.08); overflow:hidden; }
.sh-axis-bar i{ position:absolute; left:0; top:0; height:100%; border-radius:5px; width:0;
  animation:shAxisFill .7s cubic-bezier(.2,.8,.3,1) both; }
.sh-axis-val{ font-size:12.5px; font-weight:800; text-align:right; font-variant-numeric:tabular-nums; }
.sh-axis.good .sh-axis-bar i{ background:linear-gradient(90deg,var(--sh-c),#9ee06a); }
.sh-axis.good .sh-axis-val{ color:var(--sh-c); }
.sh-axis.ok   .sh-axis-bar i{ background:linear-gradient(90deg,var(--sh-a),#6fd0e6); }
.sh-axis.ok   .sh-axis-val{ color:var(--sh-a); }
.sh-axis.low  .sh-axis-bar i{ background:linear-gradient(90deg,#ff8a5b,#ff6f8b); }
.sh-axis.low  .sh-axis-val{ color:#ff9db0; }
@keyframes shAxisFill{ from{ width:0; } }

/* delivery tips — actionable, plain-language coaching lines */
.sh-tips{ display:flex; flex-direction:column; gap:7px; margin:-2px 0 16px; }
.sh-tip{ display:flex; gap:9px; align-items:flex-start; font-size:13px; line-height:1.45; color:#d3d7e2;
  padding:9px 12px; border-radius:11px; background:rgba(78,224,242,.06); border:1px solid rgba(78,224,242,.16); }
.sh-tip-dot{ flex:none; color:var(--sh-a); font-weight:900; }

/* Precision Mode (on-device AI) badge + the neural "sounds you made" line */
.sh-prec-badge{ display:inline-flex; align-items:center; gap:5px; margin-top:8px; padding:4px 10px; border-radius:8px;
  font-size:11px; font-weight:800; letter-spacing:.02em; color:#eafcff;
  background:linear-gradient(120deg,rgba(78,224,242,.22),rgba(139,109,255,.22));
  border:1px solid color-mix(in srgb,var(--sh-a) 45%, transparent); }
.sh-heard.neural{ background:linear-gradient(120deg,rgba(78,224,242,.07),rgba(139,109,255,.07));
  border-color:color-mix(in srgb,var(--sh-a) 30%, transparent); }
.sh-heard.neural .sh-heard-lbl{ color:var(--sh-a); }

/* ---- one-time "Turn on Precision Mode?" explainer -------------------- */
.sh-intro-modal{ position:fixed; inset:0; z-index:1300; display:flex; align-items:center; justify-content:center; padding:20px; }
/* NOTE: the visible state is the DEFAULT and the entrance is a CSS animation.
   Never gate visibility on a JS-added class + rAF — if rAF is throttled (background
   tab, headless) the dialog would render fully transparent and trap the student. */
/* backdrop carries a faint accent spotlight so the dialog reads as lit, not pasted on */
.sh-intro-backdrop{ position:absolute; inset:0; background:
    radial-gradient(680px 420px at 50% 42%,color-mix(in srgb,var(--sh-b) 16%,transparent),transparent 70%),
    rgba(4,5,10,.66);
  backdrop-filter:blur(7px); -webkit-backdrop-filter:blur(7px);
  animation:shIntroFade .3s ease both; }
.sh-intro-modal{ perspective:1100px; }
.sh-intro{ position:relative; z-index:1; width:min(432px,100%); max-height:calc(100vh - 40px); max-height:calc(100dvh - 40px); overflow-y:auto;
  padding:28px 26px 20px; border-radius:22px; text-align:center;
  background:linear-gradient(180deg,#171b26,#0f1218); border:1px solid rgba(255,255,255,.1);
  box-shadow:0 34px 90px -26px rgba(0,0,0,.85), inset 0 1px 0 rgba(255,255,255,.06);
  animation:shIntroPop .52s cubic-bezier(.2,.9,.3,1.06) both; }
/* hairline accent along the top edge — catches the eye before the copy does */
.sh-intro::before{ content:""; position:absolute; top:0; left:22%; right:22%; height:1px; pointer-events:none;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--sh-a) 70%,transparent),transparent); }
@keyframes shIntroFade{ from{ opacity:0; } to{ opacity:1; } }
@keyframes shIntroPop{ from{ opacity:0; transform:translateY(14px) scale(.955) rotateX(7deg); } to{ opacity:1; transform:none; } }
.sh-intro-modal.closing .sh-intro-backdrop,
.sh-intro-modal.closing .sh-intro{ opacity:0; animation:none; transition:opacity .18s ease; }
.sh-intro-x{ position:absolute; top:13px; right:13px; width:30px; height:30px; border-radius:9px; cursor:pointer;
  border:1px solid rgba(255,255,255,.12); background:rgba(255,255,255,.05); color:#9aa0b2;
  display:grid; place-items:center; transition:background .15s, color .15s, transform .15s; }
.sh-intro-x svg{ width:13px; height:13px; display:block; }
.sh-intro-x:hover{ background:rgba(255,255,255,.14); color:#fff; transform:rotate(90deg); }

/* hero: gradient tile + a slowly rotating conic halo behind it, a sheen that
   sweeps across the face, and sonar rings pinging outward — "it's listening".
   The rings are ::before/::after so they cost no extra DOM; both are absolutely
   positioned so they stay out of the grid flow. */
.sh-intro-hero{ position:relative; width:68px; height:68px; margin:2px auto 15px; display:grid; place-items:center; }
.sh-intro-hero::before,.sh-intro-hero::after{ content:""; position:absolute; inset:0; z-index:0; border-radius:21px;
  border:1.5px solid color-mix(in srgb,var(--sh-a) 60%,transparent); animation:shHeroPing 3s ease-out infinite; }
.sh-intro-hero::after{ animation-delay:1.5s; }
/* max scale is capped so the ring never grows past .sh-intro's padding box —
   transformed overflow still counts as scrollable area and would flash a scrollbar */
@keyframes shHeroPing{
  0%  { opacity:0; transform:scale(1); }
  18% { opacity:.75; }
  100%{ opacity:0; transform:scale(1.7); } }
.sh-hero-glow{ position:absolute; inset:-9px; border-radius:27px; z-index:0; opacity:.5; filter:blur(11px);
  background:conic-gradient(from 0deg,var(--sh-a),var(--sh-b),var(--sh-c),var(--sh-a));
  animation:shHeroSpin 7s linear infinite; }
.sh-hero-tile{ position:relative; z-index:1; width:100%; height:100%; border-radius:21px; overflow:hidden;
  display:grid; place-items:center; color:#08111a;
  background:linear-gradient(135deg,var(--sh-a),var(--sh-b));
  box-shadow:0 14px 34px -10px var(--sh-b), inset 0 0 0 1px rgba(255,255,255,.18);
  animation:shIntroGlow 2.8s ease-in-out infinite; }
.sh-hero-tile svg{ width:31px; height:31px; display:block; animation:shHeroBolt 2.8s ease-in-out infinite; }
.sh-hero-tile::after{ content:""; position:absolute; top:-60%; bottom:-60%; width:34%; left:-50%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);
  transform:skewX(-18deg); animation:shHeroSheen 4.2s ease-in-out 1s infinite; }
@keyframes shHeroSpin{ to{ transform:rotate(1turn); } }
@keyframes shHeroSheen{ 0%{ left:-50%; } 45%,100%{ left:130%; } }
@keyframes shHeroBolt{ 0%,100%{ transform:scale(1); } 50%{ transform:scale(1.09); } }
@keyframes shIntroGlow{
  0%,100%{ box-shadow:0 14px 34px -10px var(--sh-b), inset 0 0 0 1px rgba(255,255,255,.18); }
  50%    { box-shadow:0 18px 44px -8px  var(--sh-a), inset 0 0 0 1px rgba(255,255,255,.3); } }
.sh-intro-title{ margin:0 0 9px; font-size:21px; font-weight:800; letter-spacing:-.01em; color:#f4f6fb; }
.sh-intro-sub{ margin:0 0 19px; font-size:13.5px; line-height:1.6; color:#a8aebf; }
.sh-intro-sub b{ color:#eafcff; font-weight:700; }
.sh-intro-points{ list-style:none; margin:0 0 20px; padding:0; text-align:left; display:flex; flex-direction:column; gap:11px; }
.sh-intro-points li{ display:flex; gap:12px; align-items:center; padding:7px 9px; margin:0 -9px; border-radius:14px;
  border:1px solid transparent; transition:background .18s ease, border-color .18s ease; }
.sh-intro-points li:hover{ background:rgba(255,255,255,.035); border-color:rgba(255,255,255,.07); }
/* the tile is a <span> — every text rule below MUST stay scoped to .sh-ip-txt,
   or it outranks .sh-ip-ico and flattens the icon into the corner */
.sh-ip-ico{ flex:none; width:38px; height:38px; border-radius:12px; display:grid; place-items:center;
  background:rgba(255,255,255,.05); border:1px solid rgba(255,255,255,.09); color:#c9cfdd;
  transition:transform .22s cubic-bezier(.2,.9,.3,1.2), box-shadow .22s ease, border-color .22s ease; }
.sh-ip-ico svg{ width:19px; height:19px; display:block; transition:transform .22s cubic-bezier(.2,.9,.3,1.2); }
.sh-intro-points li:hover .sh-ip-ico{ transform:translateY(-2px); }
.sh-intro-points li:hover .sh-ip-ico svg{ transform:scale(1.1); }
/* each icon draws itself in just after its row lands (pathLength="1" in the
   markup normalises every path, so one keyframe covers all of them) */
.sh-ip-ico svg .d{ stroke-dasharray:1; stroke-dashoffset:1; animation:shIpDraw .55s ease forwards; }
.sh-ip-ico svg .pop{ transform-origin:center; animation:shIpPop .3s cubic-bezier(.2,.9,.3,1.5) both; }
@keyframes shIpDraw{ to{ stroke-dashoffset:0; } }
@keyframes shIpPop{ from{ opacity:0; transform:scale(0); } to{ opacity:1; transform:scale(1); } }
.sh-intro-points li:nth-child(1) svg .d{ animation-delay:.30s; }
.sh-intro-points li:nth-child(1) svg .d:nth-child(2){ animation-delay:.42s; }
.sh-intro-points li:nth-child(1) svg .pop{ animation-delay:.72s; }
.sh-intro-points li:nth-child(2) svg .d{ animation-delay:.37s; }
.sh-intro-points li:nth-child(2) svg .d:nth-child(2){ animation-delay:.62s; }
.sh-intro-points li:nth-child(3) svg .d{ animation-delay:.44s; }
.sh-intro-points li:nth-child(3) svg .d:nth-child(2){ animation-delay:.56s; }
.sh-intro-points li:nth-child(3) svg .d:nth-child(3){ animation-delay:.68s; }
/* one accent per point — cyan / violet / lime, the studio's trio */
.sh-intro-points li:nth-child(1) .sh-ip-ico{ color:var(--sh-a);
  background:color-mix(in srgb,var(--sh-a) 13%,transparent); border-color:color-mix(in srgb,var(--sh-a) 32%,transparent); }
.sh-intro-points li:nth-child(2) .sh-ip-ico{ color:var(--sh-b);
  background:color-mix(in srgb,var(--sh-b) 15%,transparent); border-color:color-mix(in srgb,var(--sh-b) 34%,transparent); }
.sh-intro-points li:nth-child(3) .sh-ip-ico{ color:var(--sh-c);
  background:color-mix(in srgb,var(--sh-c) 12%,transparent); border-color:color-mix(in srgb,var(--sh-c) 30%,transparent); }
.sh-intro-points li:nth-child(1):hover .sh-ip-ico{ box-shadow:0 8px 20px -8px var(--sh-a); }
.sh-intro-points li:nth-child(2):hover .sh-ip-ico{ box-shadow:0 8px 20px -8px var(--sh-b); }
.sh-intro-points li:nth-child(3):hover .sh-ip-ico{ box-shadow:0 8px 20px -8px var(--sh-c); }
.sh-ip-txt{ min-width:0; }
.sh-ip-txt b{ display:block; font-size:13.5px; font-weight:700; color:#e9ecf3; margin-bottom:2px; }
.sh-ip-txt span{ display:block; font-size:12.5px; line-height:1.5; color:#949bad; }
/* the ship/sheep pair is the whole pitch — show the verdict instead of describing it */
.sh-ip-bad,.sh-ip-good,.sh-ip-size{ font-style:normal; font-weight:700; padding:1px 6px; border-radius:6px; white-space:nowrap; }
.sh-ip-bad{ color:#ffa3b2; background:rgba(255,90,110,.13); border:1px solid rgba(255,90,110,.28);
  text-decoration:line-through; text-decoration-color:rgba(255,120,140,.75); }
.sh-ip-good{ color:#bff0c4; background:rgba(90,220,130,.13); border:1px solid rgba(90,220,130,.3); }
.sh-ip-size{ color:#e6f5b8; background:rgba(198,242,78,.11); border:1px solid rgba(198,242,78,.26); }
.sh-intro-actions{ display:flex; gap:10px; }
.sh-intro-actions .sh-btn{ flex:1; display:inline-flex; align-items:center; justify-content:center; gap:7px; }
.sh-intro-actions .sh-btn svg{ width:15px; height:15px; display:block; }
/* the CTA shimmers periodically so the eye lands on it last */
.sh-intro-actions .sh-btn.primary{ position:relative; overflow:hidden; }
.sh-intro-actions .sh-btn.primary::after{ content:""; position:absolute; top:0; bottom:0; width:36%; left:-45%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.5),transparent);
  transform:skewX(-18deg); animation:shBtnSheen 3.6s ease-in-out 1.3s infinite; }
.sh-intro-actions .sh-btn.primary:hover{ filter:brightness(1.06); transform:translateY(-1px); }
.sh-intro-actions .sh-btn.primary:active{ transform:translateY(0) scale(.985); }
@keyframes shBtnSheen{ 0%{ left:-45%; } 50%,100%{ left:125%; } }
/* keyboard focus gets the studio's accent ring, not the UA's default orange box */
.sh-intro :is(.sh-btn,.sh-intro-x):focus-visible{ outline:2px solid var(--sh-a); outline-offset:3px; }
.sh-intro :is(.sh-btn,.sh-intro-x):focus:not(:focus-visible){ outline:none; }
.sh-intro-foot{ margin:13px 0 0; font-size:11.5px; color:#787f93; }
/* staggered entrance — the dialog pops, then its contents rise in sequence */
.sh-intro-title,.sh-intro-sub,.sh-intro-points li,.sh-intro-actions,.sh-intro-foot{
  animation:shIntroRise .42s cubic-bezier(.2,.9,.3,1.04) both; }
.sh-intro-title{ animation-delay:.06s; }
.sh-intro-sub{ animation-delay:.11s; }
.sh-intro-points li:nth-child(1){ animation-delay:.17s; }
.sh-intro-points li:nth-child(2){ animation-delay:.24s; }
.sh-intro-points li:nth-child(3){ animation-delay:.31s; }
.sh-intro-actions{ animation-delay:.38s; }
.sh-intro-foot{ animation-delay:.44s; }
@keyframes shIntroRise{ from{ opacity:0; transform:translateY(9px); } to{ opacity:1; transform:none; } }
@media (max-width:420px){
  .sh-intro{ padding:24px 19px 17px; }
  .sh-intro-actions{ flex-direction:column-reverse; }
}
@media (prefers-reduced-motion:reduce){
  /* animation:none is safe here — the default state is already the visible one */
  .sh-intro,.sh-intro-backdrop,.sh-hero-tile,.sh-hero-tile svg,.sh-hero-tile::after,.sh-hero-glow,
  .sh-intro-hero::before,.sh-intro-hero::after,.sh-ip-ico svg .pop,
  .sh-intro-title,.sh-intro-sub,.sh-intro-points li,.sh-intro-actions,.sh-intro-foot,
  .sh-intro-actions .sh-btn.primary::after{ animation:none; }
  /* the draw-on hides its stroke until it runs, so land it on the drawn state */
  .sh-ip-ico svg .d{ animation:none; stroke-dashoffset:0; }
}

.sh-report-actions{ display:flex; flex-wrap:wrap; gap:9px; }
.sh-report-empty{ font-size:14px; color:#aeb3c4; line-height:1.6; margin:6px 0 16px; }
.sh-report-note-card{ display:flex; flex-direction:column; gap:5px; padding:13px 15px; margin:4px 0 14px;
  border-radius:14px; background:rgba(198,242,78,.07); border:1px solid rgba(198,242,78,.24); }
.sh-report-note-card b{ font-size:15px; color:var(--sh-c); }
.sh-report-note-card span{ font-size:12.5px; color:#aeb3c4; line-height:1.55; }

/* personal-best celebration + prior-best note in the report */
.sh-best-chip{ display:inline-block; margin-top:8px; padding:4px 11px; border-radius:9px; font-size:12px; font-weight:800;
  color:#07130a; background:linear-gradient(120deg,var(--sh-c),var(--sh-a)); box-shadow:0 4px 14px -4px var(--sh-a);
  animation:shBestPop .4s cubic-bezier(.2,.8,.3,1) both; }
.sh-report-best{ display:inline-block; margin-top:8px; font-size:12px; font-weight:700; color:#8b90a2; }
@keyframes shBestPop{ from{ opacity:0; transform:scale(.8) translateY(4px); } }

/* per-line best-score badge on the transcript rail + record spotlight */
.sh-line{ position:relative; }
.sh-line-score{ position:absolute; top:8px; right:10px; font-size:10.5px; font-weight:800; line-height:1;
  padding:3px 6px; border-radius:7px; letter-spacing:.02em; }
.sh-line-score[hidden]{ display:none; }
.sh-line-score.good{ color:#062; background:var(--sh-c); }
.sh-line-score.ok{   color:#04202a; background:var(--sh-a); }
.sh-line-score.low{  color:#3a1a10; background:#ffb072; }
.sh-line.scored .sh-line-txt{ padding-right:44px; }
/* pulse lives on a ::after overlay so it never clobbers the line's own
   shLineIn entrance animation — the house rule for every state animation here. */
.sh-line.rec-target{ outline:2px solid color-mix(in srgb,var(--sh-c) 72%, transparent); outline-offset:-2px; }
.sh-line.rec-target::after{ content:""; position:absolute; inset:0; border-radius:12px; pointer-events:none;
  animation:shTargetPulse 1.2s ease-in-out infinite; }
@keyframes shTargetPulse{ 0%,100%{ box-shadow:0 0 0 0 rgba(198,242,78,.34);} 50%{ box-shadow:0 0 0 7px rgba(198,242,78,0);} }
@media (prefers-reduced-motion:reduce){ .sh-line.rec-target::after{ animation:none; } .sh-best-chip{ animation:none; } }

@media (max-width:560px){
  .sh-report-head{ gap:14px; } .sh-ring{ width:88px; height:88px; }
  .sh-report-line{ font-size:17px; line-height:1.85; }
}

/* transcript fills the full column height, scrolls internally */
.sh-rail-wrap{ grid-area:rail; align-self:stretch; height:100%; min-height:0; margin:0; }
.sh-rail{ flex:1 1 auto; max-height:none; min-height:0; }

/* ---- mobile: stack video + transcript, pin the console to the bottom ---- */
@media (max-width:900px){
  /* `overflow:auto` here restored scrolling but turned <body> into a scroll
     container, which kills `position:sticky` for everything inside it — so the
     console below could never actually pin. `visible` restores normal document
     scrolling; `html{overflow-x:clip}` still guards horizontal overflow. */
  body.sh-immersive{ overflow:visible; }
  .sh-studio{ height:auto; min-height:100vh; min-height:100dvh; }
  .sh-stage{ display:flex; flex-direction:column; align-items:stretch; max-width:none; padding:12px 12px 0; gap:0; }
  .sh-player-wrap{ order:1; width:100%; }
  .sh-player-frame{ max-height:none; width:100%; }
  .sh-rail-wrap{ order:2; margin-top:14px; min-height:44vh; }
  .sh-rail{ max-height:none; }
  .sh-console{ order:3; position:sticky; bottom:0; z-index:9; margin:14px -12px 0; border-radius:18px 18px 0 0;
    padding-bottom:calc(14px + env(safe-area-inset-bottom,0px));
    background:linear-gradient(0deg,rgba(9,10,16,.98),rgba(12,14,22,.94)); backdrop-filter:blur(16px);
    border-color:rgba(255,255,255,.1); }
  .sh-console-main #shLoop{ margin-left:0; }
  .sh-rec{ margin-left:auto; }
}
@media (max-width:560px){
  .sh-console-main, .sh-console-foot{ justify-content:center; }
  .sh-transport{ gap:8px; }
  .sh-rec-copy{ display:none; }
  .sh-rec{ margin-left:0; }
}

/* ============================================================================
   MOTION v3 — a soft "compose-in" when the hub hero and the studio mount, so
   nothing pops in abruptly. Entrance only (settles to transform:none, so it
   never interferes with sticky/grid layout), and fully off under reduced-motion.
   ============================================================================ */
@media (prefers-reduced-motion:no-preference){
  .sh-hero-title{ animation:shComposeIn .62s cubic-bezier(.2,.75,.3,1) both; }
  .sh-hero-sub{   animation:shComposeIn .62s cubic-bezier(.2,.75,.3,1) both .07s; }
  .sh-hero-stats{ animation:shComposeIn .62s cubic-bezier(.2,.75,.3,1) both .15s; }
  .sh-filters{    animation:shComposeIn .55s cubic-bezier(.2,.75,.3,1) both .22s; }

  .sh-studio-bar{ animation:shDropIn  .5s cubic-bezier(.2,.75,.3,1) both; }
  .sh-player-wrap{ animation:shComposeIn .55s cubic-bezier(.2,.75,.3,1) both .06s; }
  .sh-console{    animation:shRiseIn  .52s cubic-bezier(.2,.75,.3,1) both .13s; }
  .sh-rail-wrap{  animation:shComposeIn .55s cubic-bezier(.2,.75,.3,1) both .1s; }
}
@keyframes shComposeIn{ from{ opacity:0; transform:translateY(13px); } }
@keyframes shRiseIn{    from{ opacity:0; transform:translateY(20px); } }
@keyframes shDropIn{    from{ opacity:0; transform:translateY(-10px); } }

/* ============================================================================
   DAY / NIGHT — an in-studio theme toggle.
   ─────────────────────────────────────────────────────────────────────────────
   The studio is dark by default (video reads best on dark). This layer adds a
   polished sun/moon switch to the top bar; toggling puts .sh-day on .sh-studio
   and swaps every surface colour through variable overrides, plus a soft
   full-stage "sweep" transition so the change feels theatrical, not jarring.
   ============================================================================ */

/* studio surfaces animate softly on theme flip */
.sh-studio,
.sh-studio-bar,
.sh-console,
.sh-rail-wrap,
.sh-line,
.sh-ctl,
.sh-back,
.sh-btn,
.sh-toggle,
.sh-seg,
.sh-rec,
.sh-rec-copy b,
.sh-rec-copy span,
.sh-hint,
.sh-scrub-time,
.sh-rail-label,
.sh-rail-label em,
.sh-linecount{
  transition:background .38s ease, color .38s ease, border-color .38s ease,
             box-shadow .38s ease;
}

/* ---- the toggle switch ---------------------------------------------------- */
.sh-theme{
  flex:none; position:relative; margin-left:6px;
  width:78px; height:34px; padding:0; border:0; background:transparent; cursor:pointer;
  border-radius:999px; outline:none;
}
.sh-theme:focus-visible{ box-shadow:0 0 0 3px color-mix(in srgb,var(--sh-a) 55%, transparent); }
.sh-theme-track{
  position:absolute; inset:0; border-radius:999px; overflow:hidden;
  background:linear-gradient(120deg,#0b1030 0%, #1a1748 55%, #241b56 100%);
  border:1px solid rgba(255,255,255,.10);
  box-shadow:inset 0 2px 6px rgba(0,0,0,.55),
             0 6px 20px -10px rgba(80,60,255,.5);
  transition:background .5s ease, border-color .4s ease, box-shadow .4s ease;
}
.sh-theme[data-mode="day"] .sh-theme-track{
  background:linear-gradient(120deg,#7fd0ff 0%, #ffd085 60%, #ffb257 100%);
  border-color:rgba(255,255,255,.55);
  box-shadow:inset 0 2px 6px rgba(255,180,90,.35),
             0 8px 22px -10px rgba(255,170,80,.55);
}
/* twinkling stars — visible only in night mode */
.sh-theme-stars{ position:absolute; inset:0; opacity:1; transition:opacity .35s ease; }
.sh-theme[data-mode="day"] .sh-theme-stars{ opacity:0; }
.sh-theme-stars i{
  position:absolute; width:2px; height:2px; border-radius:50%;
  left:var(--x); top:var(--y);
  background:#fff; box-shadow:0 0 6px #fff;
  animation:shStarTwinkle 2.6s ease-in-out infinite; animation-delay:var(--d);
}
@keyframes shStarTwinkle{ 0%,100%{ opacity:.25; transform:scale(.7);} 50%{ opacity:1; transform:scale(1.3);} }

/* rotating sun rays — visible only in day mode */
.sh-theme-rays{
  position:absolute; left:calc(100% - 30px); top:50%; width:52px; height:52px;
  margin:-26px 0 0 -22px; border-radius:50%; pointer-events:none;
  background:
    conic-gradient(from 0deg,
      rgba(255,220,140,.55) 0deg 10deg, transparent 10deg 45deg,
      rgba(255,220,140,.55) 45deg 55deg, transparent 55deg 90deg,
      rgba(255,220,140,.55) 90deg 100deg, transparent 100deg 135deg,
      rgba(255,220,140,.55) 135deg 145deg, transparent 145deg 180deg,
      rgba(255,220,140,.55) 180deg 190deg, transparent 190deg 225deg,
      rgba(255,220,140,.55) 225deg 235deg, transparent 235deg 270deg,
      rgba(255,220,140,.55) 270deg 280deg, transparent 280deg 315deg,
      rgba(255,220,140,.55) 315deg 325deg, transparent 325deg 360deg);
  opacity:0; filter:blur(1px);
  animation:shRaysSpin 16s linear infinite;
  transition:opacity .5s ease .1s, left .55s cubic-bezier(.55,.2,.2,1.4);
}
.sh-theme[data-mode="day"] .sh-theme-rays{ opacity:.7; left:24px; }
@keyframes shRaysSpin{ to{ transform:rotate(360deg);} }

/* the sliding knob with sun/moon face */
.sh-theme-knob{
  position:absolute; top:3px; left:3px; width:28px; height:28px; border-radius:50%;
  display:grid; place-items:center;
  background:linear-gradient(140deg,#e9ecff 0%, #9aa0d8 100%);
  box-shadow:0 3px 10px rgba(0,0,0,.45), inset 0 -3px 6px rgba(0,0,0,.25),
             inset 0 2px 4px rgba(255,255,255,.75);
  color:#3a3f6a;
  transition:left .55s cubic-bezier(.55,.2,.2,1.4),
             background .5s ease, color .5s ease, box-shadow .5s ease,
             transform .18s ease;
}
.sh-theme:hover .sh-theme-knob{ transform:scale(1.06); }
.sh-theme:active .sh-theme-knob{ transform:scale(.94); }
.sh-theme[data-mode="day"] .sh-theme-knob{
  left:47px;
  background:linear-gradient(140deg,#fff8dc 0%, #ffcb54 100%);
  color:#6b3a05;
  box-shadow:0 3px 10px rgba(255,150,50,.55), inset 0 -3px 6px rgba(180,90,0,.2),
             inset 0 2px 4px rgba(255,255,255,.9);
}
.sh-theme-knob .ti{ position:absolute; width:16px; height:16px; transition:opacity .35s ease, transform .5s cubic-bezier(.55,.2,.2,1.6); }
.sh-theme-knob .ti.sun{ opacity:0; transform:rotate(-120deg) scale(.4); }
.sh-theme-knob .ti.moon{ opacity:1; transform:rotate(0) scale(1); }
.sh-theme[data-mode="day"] .sh-theme-knob .ti.sun{ opacity:1; transform:rotate(0) scale(1); }
.sh-theme[data-mode="day"] .sh-theme-knob .ti.moon{ opacity:0; transform:rotate(120deg) scale(.4); }

/* ---- the "sweep" flash injected on toggle -------------------------------- */
.sh-theme-sweep{
  position:fixed; inset:0; z-index:9999; pointer-events:none;
  opacity:0; will-change:opacity;
  background:radial-gradient(circle at 92% 6%,
    rgba(255,215,140,.85) 0%, rgba(255,180,80,.4) 22%, rgba(0,0,0,0) 55%);
  transition:opacity .34s ease;
}
.sh-theme-sweep.to-night{
  background:radial-gradient(circle at 92% 6%,
    rgba(90,110,255,.85) 0%, rgba(20,10,60,.55) 26%, rgba(0,0,0,0) 60%);
}
.sh-theme-sweep.go{ opacity:1; animation:shSweep .7s ease forwards; }
@keyframes shSweep{
  0%   { opacity:0; transform:scale(.5); }
  30%  { opacity:1; }
  100% { opacity:0; transform:scale(1.8); }
}

/* ============================================================================
   DAY MODE — every studio surface swaps to a soft daylight palette.
   Scoped strictly to .sh-studio.sh-day so nothing leaks to the hub or the
   rest of the site (both retain their own theme handling).
   ============================================================================ */
.sh-studio.sh-day{
  background:
    radial-gradient(1300px 700px at 50% -8%, #f6f8ff 0%, #e6eaf9 55%, #dde3f2 100%),
    #dee4f3;
  color:#0e1226;
}
.sh-studio.sh-day .sh-studio-bar{
  background:linear-gradient(180deg,rgba(248,250,255,.94),rgba(244,247,254,.62));
  border-bottom-color:rgba(13,17,32,.09);
  box-shadow:0 6px 18px -14px rgba(13,17,32,.35);
}
.sh-studio.sh-day .sh-back{
  background:rgba(255,255,255,.72);
  border-color:rgba(13,17,32,.11);
  color:#0e1226;
}
.sh-studio.sh-day .sh-back:hover{ background:rgba(255,255,255,1); border-color:rgba(13,17,32,.18); }
.sh-studio.sh-day .sh-studio-sub{ color:#5b6379; }
.sh-studio.sh-day .sh-studio-sub .sh-badge{ background:rgba(13,17,32,.08); color:#2f3548; }
.sh-studio.sh-day .sh-studio-prog{ color:#367b1e; }

/* video area — the frame surround softens; the iframe interior stays black */
.sh-studio.sh-day .sh-player-frame{
  box-shadow:0 30px 70px -30px rgba(30,42,90,.5), 0 0 0 1px rgba(13,17,32,.08);
}
.sh-studio.sh-day .sh-player-veil{
  background:radial-gradient(circle at center, rgba(245,247,254,.55), rgba(230,236,250,.85));
  color:#0e1226;
}
.sh-studio.sh-day .sh-player-veil span{ color:#3d4459; }
.sh-studio.sh-day .sh-hint{ color:#5b6379; }
.sh-studio.sh-day .sh-hint b{ color:#0e1226; }

/* scrubber */
.sh-studio.sh-day .sh-timeline{ background:rgba(13,17,32,.10); }
.sh-studio.sh-day .sh-timeline-knob{ background:#0e1226; box-shadow:0 2px 8px rgba(13,17,32,.35); }
.sh-studio.sh-day .sh-scrub-time{ color:#2f3548; }

/* console (the big control card under the video) */
.sh-studio.sh-day .sh-console{
  background:linear-gradient(180deg, rgba(255,255,255,.9), rgba(255,255,255,.7));
  border-color:rgba(13,17,32,.09);
  box-shadow:0 20px 50px -30px rgba(30,42,90,.4);
}

/* transport & control buttons */
.sh-studio.sh-day .sh-ctl{
  background:rgba(255,255,255,.85);
  border-color:rgba(13,17,32,.12);
  color:#141a2d;
}
.sh-studio.sh-day .sh-ctl:hover{ background:#fff; border-color:rgba(13,17,32,.22); }

/* segmented pickers (speed / loop) */
.sh-studio.sh-day .sh-seg{
  background:rgba(13,17,32,.05);
  border-color:rgba(13,17,32,.10);
}
.sh-studio.sh-day .sh-seg-label{ color:#5b6379; }
.sh-studio.sh-day .sh-seg button{ color:#3d4459; }
.sh-studio.sh-day .sh-seg button:hover{ color:#0e1226; }

/* Hide-subtitles toggle */
.sh-studio.sh-day .sh-toggle{
  background:rgba(255,255,255,.85);
  border-color:rgba(13,17,32,.12);
  color:#3d4459;
}
.sh-studio.sh-day .sh-toggle:hover{ color:#0e1226; }
.sh-studio.sh-day .sh-toggle.on{
  background:rgba(150,205,60,.20);
  border-color:rgba(126,180,40,.55);
  color:#3f6712;
}

/* record slot */
.sh-studio.sh-day .sh-rec{
  background:rgba(255,255,255,.75);
  border-color:rgba(13,17,32,.10);
}
.sh-studio.sh-day .sh-rec-copy b{ color:#0e1226; }
.sh-studio.sh-day .sh-rec-copy span{ color:#5b6379; }
.sh-studio.sh-day .sh-btn{
  background:rgba(255,255,255,.9);
  border-color:rgba(13,17,32,.12);
  color:#0e1226;
}
.sh-studio.sh-day .sh-btn:hover{ background:#fff; border-color:rgba(13,17,32,.22); }
.sh-studio.sh-day .sh-btn.ghost{ background:rgba(255,255,255,.75); }
.sh-studio.sh-day .sh-btn.ghost.danger{ color:#c1263b; border-color:rgba(200,40,60,.28); }

/* transcript rail */
.sh-studio.sh-day .sh-rail-wrap{
  background:rgba(255,255,255,.82);
  border-color:rgba(13,17,32,.08);
  box-shadow:0 20px 50px -30px rgba(30,42,90,.35);
}
.sh-studio.sh-day .sh-rail-label{ color:#5b6379; }
.sh-studio.sh-day .sh-rail-label em{ color:#818aa1; }
.sh-studio.sh-day .sh-linecount{ color:#818aa1; }
.sh-studio.sh-day .sh-rail::-webkit-scrollbar-thumb{ background:rgba(13,17,32,.18); }
.sh-studio.sh-day .sh-line{ color:#3f465a; }
.sh-studio.sh-day .sh-line:hover{ background:rgba(13,17,32,.05); color:#0e1226; }
.sh-studio.sh-day .sh-line-num{ background:rgba(13,17,32,.07); color:#535d7a; }
.sh-studio.sh-day .sh-line.active{
  color:#0e1226;
  background:linear-gradient(180deg, rgba(139,109,255,.10), rgba(78,224,242,.10));
  border-color:rgba(139,109,255,.35);
  box-shadow:inset 3px 0 0 var(--sh-b), 0 10px 26px -18px rgba(78,224,242,.55);
}
.sh-studio.sh-day .sh-line.active .sh-line-num{ color:#07080c; }
.sh-studio.sh-day .sh-line.active .sh-w{ opacity:.5; }
.sh-studio.sh-day .sh-line.active .sh-w.spoken{ opacity:1; color:#0e1226; }
.sh-studio.sh-day .sh-line.active .sh-w.now{
  color:#7c3aed;
  text-shadow:0 0 14px color-mix(in srgb,#7c3aed 55%, transparent);
}

/* rail entrance animation still runs; empty state and hide-subs adapt */
.sh-studio.sh-day .sh-rail-empty{ color:#5b6379; }
.sh-studio.sh-day.hide-subs .sh-line-txt,
.sh-studio.sh-day .sh-rail-wrap.hide-subs .sh-line-txt{ filter:blur(7px); opacity:.5; }

/* mobile sticky console: match day palette */
@media (max-width:900px){
  .sh-studio.sh-day .sh-console{
    background:linear-gradient(0deg, rgba(250,251,255,.98), rgba(245,247,254,.94));
    border-color:rgba(13,17,32,.12);
  }
}

/* reduced motion: keep the swap instant but skip the sweep animation */
@media (prefers-reduced-motion:reduce){
  .sh-theme-sweep, .sh-theme-rays{ animation:none !important; }
  .sh-theme-sweep.go{ opacity:0; }
}

/* ============ studio glow — carry the hub's brand-glow language across ============
   The studio already glows in places (active line, playing frame, big-play pulse,
   timeline, record button); these add the resting brand halos + accents so the two
   surfaces read as one system. Works in both dark and .sh-day (light). */
/* video frame: keep the deep drop-shadow + hairline, add a resting brand halo
   (the playing state still blooms cyan via body.sh-playing, which wins) */
.sh-player-frame{ box-shadow:0 30px 80px -30px rgba(0,0,0,.9), 0 0 0 1px rgba(255,255,255,.06),
  0 14px 54px -28px color-mix(in srgb,var(--sh-b) 48%, transparent); }
.sh-studio.sh-day .sh-player-frame{ box-shadow:0 26px 64px -30px rgba(13,17,32,.45),
  0 0 0 1px rgba(13,17,32,.06), 0 14px 50px -26px color-mix(in srgb,var(--sh-b) 40%, transparent); }

/* transport play button: soft resting brand glow + a ring on hover (box-shadow so
   it can't be clipped; body.sh-playing's glow is more specific and still wins) */
.sh-play{ box-shadow:0 10px 26px -10px color-mix(in srgb,var(--sh-b) 55%, transparent); }
.sh-play:hover{ box-shadow:0 12px 30px -10px color-mix(in srgb,var(--sh-b) 68%, transparent),
  0 0 0 4px color-mix(in srgb,var(--sh-a) 20%, transparent); }

/* console: a thin brand hairline along the top edge, echoing the hub cards.
   NOTE: do NOT set `position` here. This rule sits after the `@media
   (max-width:900px)` block that pins the console with `position:sticky`, and a
   bare `position:relative` at equal specificity silently un-pinned it at every
   width — the controls ended up stranded at the very bottom of the page. The
   base rule already carries `position:relative` for this ::before to anchor to,
   and `sticky` establishes a containing block just as well. */
.sh-console::before{ content:''; position:absolute; left:16px; right:16px; top:0; height:1.5px; pointer-events:none;
  background:linear-gradient(90deg,transparent,
    color-mix(in srgb,var(--sh-a) 70%,transparent),
    color-mix(in srgb,var(--sh-b) 70%,transparent),transparent); opacity:.5; }

/* speed/loop active pill carries the same glow as the hub's active filter chips */
.sh-seg button.on{ box-shadow:0 6px 16px -6px var(--sh-b); }

/* transport secondary buttons: gentle brand tint on hover to match the hub chips */
.sh-ctl:hover{ box-shadow:0 0 0 3px color-mix(in srgb,var(--sh-a) 14%, transparent); }

/* ============================================================================
   LIGHT THEME — gradient text needs darker stops
   The brand gradient (cyan #4ee0f2 → violet #8b6dff → lime #c6f24e) is tuned
   for the dark studio. Clipped to text on the near-white hub it measured
   1.08:1 (lime) and 1.32:1 (cyan) — the headline was effectively invisible.
   ============================================================================ */
:root[data-theme="light"] .sh-grad{
  background:linear-gradient(100deg,#0e7f93,#5b3fd1 55%,#4f7d18);
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
:root[data-theme="light"] .sh-stat b{
  background:linear-gradient(120deg,#0e7f93,#5b3fd1);
  -webkit-background-clip:text; background-clip:text; color:transparent;
}

/* ============================================================================
   TOUCH TARGETS — the studio controls the shared layer in
   31-responsive-global.css never reached (it only covers `.sh-seg button`).
   Same convention: `pointer:coarse` OR phone/tablet width, sizes nudged to a
   comfortable ~40px minimum rather than padded with pseudo-elements.
   ============================================================================ */
@media (pointer:coarse), (max-width:900px){
  /* The video's own transport bar is 34px tall (36px for the icon-only play
     and fullscreen buttons) and the 900px block above deliberately keeps it
     permanently visible on touch — so these are the primary tap targets. */
  .sh-pbar-btn{ height:40px; }
  .sh-pbar-btn.icon{ width:40px; }

  /* 30px squares were the only way out of two full-screen overlays (the
     pronunciation report, shown after every take, and the Precision Mode
     explainer). */
  .sh-report-x, .sh-intro-x{ width:40px; height:40px; }

  /* Record / compare / retry / report actions sit at ~34px. */
  .sh-btn{ min-height:40px; }
}
