/* ==========================================================================
   /practice/  Bob, your AI customer.

   Loaded after css/style.css, which supplies the brand tokens, the type scale
   and .btn. Nothing here redefines a token; if a colour is needed that the
   brand sheet does not have, it is derived from one that it does.

   The page is dark end to end on purpose. This is a call, not a form, and the
   one moment that goes light is the scorecard, because that is the moment the
   learner is meant to read carefully.
   ========================================================================== */

[hidden]{display:none !important}

.p-page{
  min-height:100vh; display:flex; flex-direction:column;
  background:
    radial-gradient(900px 620px at 78% -8%, rgba(34,119,170,.30), transparent 62%),
    radial-gradient(700px 520px at 8% 106%, rgba(239,179,96,.13), transparent 60%),
    linear-gradient(168deg, var(--ink-900), var(--blue-900) 44%, var(--ink-950));
  color:var(--white);
}
.p-page h1,.p-page h2,.p-page h3{color:var(--white)}

/* ---------- Top bar ---------- */
.pbar{
  position:sticky; top:0; z-index:60;
  background:rgba(8,31,53,.72); backdrop-filter:blur(14px) saturate(150%);
  border-bottom:1px solid rgba(255,255,255,.10);
}
.pbar__in{display:flex; align-items:center; gap:1rem; min-height:62px}
.pbar img{height:22px; width:auto; filter:brightness(0) invert(1)}
.pbar__rule{width:1px; height:22px; background:rgba(255,255,255,.2)}
.pbar__name{
  font-family:var(--font-display); font-weight:700; font-size:.8125rem;
  letter-spacing:.14em; text-transform:uppercase; color:var(--gold-500);
}
.pbar__sp{flex:1}
.pbar__back{
  font-size:.9375rem; font-weight:600; color:#BDD1E4; display:inline-flex;
  align-items:center; gap:.45rem; padding:.45rem .8rem; border-radius:100px;
  transition:background-color .2s var(--ease), color .2s var(--ease);
}
.pbar__back:hover{background:rgba(255,255,255,.09); color:var(--white)}
.credits{
  display:inline-flex; align-items:center; gap:.5rem; font-size:.8125rem; font-weight:700;
  padding:.42rem .85rem; border-radius:100px; white-space:nowrap;
  background:rgba(239,179,96,.14); border:1px solid rgba(239,179,96,.42); color:var(--gold-500);
}

.pbar__back,.pbar__name{white-space:nowrap}
@media (max-width:760px){
  .pbar__name,.pbar__rule{display:none}
  .pbar__in{gap:.65rem}
  .pbar__back{font-size:.875rem; padding:.45rem .5rem}
}
/* A phone keeps the way back and the account; the test chip gives way. */
@media (max-width:520px){
  .credits{display:none}
}

/* ---------- Shared shell ---------- */
.p-page .btn--ghost{--btn-fg:var(--white); --btn-bd:rgba(255,255,255,.3)}
.p-page .btn--ghost:hover{--btn-bg:rgba(255,255,255,.1); --btn-bd:rgba(255,255,255,.62); box-shadow:none}

.p-main{flex:1; padding-block:clamp(2rem,4.5vw,3.75rem)}
.p-view[hidden]{display:none}
/* Same three block treatment as the landing section, and for the same reason:
   stacked as two columns, the phone put Bob below the brief, the buttons and
   the privacy note. He belongs directly under the challenge title. */
.p-intro{
  display:grid; gap:clamp(1.75rem,3.5vw,3.25rem); align-items:start;
  grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  grid-template-areas:"head media" "body media";
}
.p-intro__head{grid-area:head}
.p-intro__body{grid-area:body}
.p-intro__media{grid-area:media; align-self:center}
@media (max-width:920px){
  .p-intro{
    grid-template-columns:minmax(0,1fr);
    grid-template-areas:"head" "media" "body";
    gap:clamp(1.5rem,4vw,2.25rem);
  }
}
.p-intro__body .p-steps{margin-top:0}

.p-eyebrow{
  display:inline-flex; align-items:center; gap:.6rem; font-weight:600;
  font-size:var(--t-label); letter-spacing:.16em; text-transform:uppercase;
  color:var(--gold-500);
}
.p-eyebrow::before{content:""; width:26px; height:2px; background:var(--gold-500); border-radius:2px}
.p-lead{font-size:clamp(1.0625rem,1rem + .3vw,1.2rem); line-height:1.6; color:#BDD1E4}
.p-note{font-size:.875rem; line-height:1.55; color:#8FAAC3}
.p-note b{color:#BDD1E4; font-weight:600}

/* ---------- Bob ---------- */
/* The portrait is the anchor of the whole page, so it is treated as a photo in
   a frame rather than an avatar in a circle: the ring belongs to the call, and
   it only appears once the call is running. */
.bob{
  position:relative; border-radius:var(--r-lg); overflow:hidden;
  border:1px solid rgba(255,255,255,.14); box-shadow:var(--shadow-lg);
  background:var(--ink-950);
}
.bob img{width:100%; aspect-ratio:16/9; object-fit:cover; object-position:50% 34%}
.bob--tall img{aspect-ratio:4/5; object-position:50% 26%}
.bob__grad{position:absolute; inset:0; background:linear-gradient(to top,rgba(8,31,53,.94) 4%,rgba(8,31,53,.10) 58%)}
.bob__id{position:absolute; left:1.25rem; right:1.25rem; bottom:1.1rem; display:flex; align-items:flex-end; gap:.8rem}
.bob__name{font-family:var(--font-display); font-weight:800; font-size:1.375rem; line-height:1.1}
.bob__role{display:block; font-family:var(--font-body); font-weight:600; font-size:.8125rem;
  letter-spacing:.11em; text-transform:uppercase; color:var(--gold-500); margin-top:.3rem}
.bob__ai{
  margin-left:auto; flex:0 0 auto; font-size:.6875rem; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; color:#BDD1E4; background:rgba(8,31,53,.68);
  border:1px solid rgba(255,255,255,.22); padding:.32rem .6rem; border-radius:100px;
}
.bob__q{
  padding:1.1rem 1.35rem 1.25rem; background:rgba(255,255,255,.05);
  border-top:1px solid rgba(255,255,255,.12);
}
.bob__q p{font-size:1.0625rem; line-height:1.5; color:var(--white); font-weight:600}
.bob__q p::before{content:"\201C"; color:var(--gold-500); font-size:1.6em; line-height:0; vertical-align:-.28em; margin-right:.1em}
.bob__q p::after{content:"\201D"; color:var(--gold-500); font-size:1.6em; line-height:0; vertical-align:-.28em; margin-left:.06em}

/* ---------- Intro: what happens ---------- */
.p-steps{margin:1.75rem 0 0; display:grid; gap:.9rem}
.p-steps li{display:grid; grid-template-columns:26px 1fr; gap:.9rem; align-items:start;
  font-size:1rem; line-height:1.55; color:#CBDAEA}
.p-steps .n{
  width:26px; height:26px; border-radius:8px; display:grid; place-items:center;
  font-family:var(--font-display); font-weight:800; font-size:.75rem;
  background:rgba(239,179,96,.16); border:1px solid rgba(239,179,96,.4); color:var(--gold-500);
}
.p-ctas{display:flex; flex-wrap:wrap; gap:.85rem; margin-top:2rem}
.p-speech{margin-top:1rem; max-width:60ch}
.p-speech a{color:#BDD1E4; text-decoration:underline; text-underline-offset:2px}

.p-warn{
  margin-top:1.5rem; display:flex; gap:.75rem; align-items:flex-start;
  padding:.9rem 1.05rem; border-radius:var(--r-md); font-size:.9375rem; line-height:1.5;
  background:rgba(239,179,96,.10); border:1px solid rgba(239,179,96,.32); color:#EBD9BC;
}
.p-warn svg{flex:0 0 auto; margin-top:.15rem; color:var(--gold-500)}

/* ==========================================================================
   The call
   ========================================================================== */
.call{display:grid; gap:clamp(1.5rem,3vw,2.5rem); grid-template-columns:minmax(0,340px) minmax(0,1fr)}
@media (max-width:920px){ .call{grid-template-columns:1fr} }

.call__side{display:flex; flex-direction:column; gap:1.25rem}

/* The orb. A real analyser drives --level from 0 to 1, so the ring is the
   learner's own voice and not a canned animation. When the microphone is
   unavailable the ring simply sits at rest, which is honest. */
.orb{position:relative; width:min(240px,62vw); margin-inline:auto; aspect-ratio:1}
.orb__ring{position:absolute; inset:-14px; border-radius:50%;
  border:2px solid rgba(255,255,255,.14); transition:border-color .3s var(--ease)}
.orb__pulse{
  position:absolute; inset:-14px; border-radius:50%; border:2px solid var(--gold-500);
  opacity:calc(.18 + var(--level,0) * .82);
  transform:scale(calc(1 + var(--level,0) * .12));
  transition:transform .09s linear, opacity .09s linear;
}
.orb__face{position:absolute; inset:0; border-radius:50%; overflow:hidden;
  border:1px solid rgba(255,255,255,.2); box-shadow:0 18px 44px rgba(0,0,0,.45)}
.orb__face img{width:100%; height:100%; object-fit:cover; object-position:50% 30%}
.orb.is-speaking .orb__ring{border-color:rgba(34,119,170,.85); animation:orb-breathe 1.9s var(--ease) infinite}
.orb.is-speaking .orb__pulse{opacity:0}
@keyframes orb-breathe{0%,100%{transform:scale(1)} 50%{transform:scale(1.045)}}

.status{text-align:center}
.status__dot{
  display:inline-flex; align-items:center; gap:.5rem; font-size:.8125rem; font-weight:700;
  letter-spacing:.1em; text-transform:uppercase; padding:.4rem .85rem; border-radius:100px;
  background:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.16); color:#BDD1E4;
}
.status__dot i{width:8px; height:8px; border-radius:50%; background:var(--blue-500); flex:0 0 auto}
.status.is-live .status__dot{background:rgba(199,11,22,.16); border-color:rgba(199,11,22,.5); color:#F6B9BD}
.status.is-live .status__dot i{background:var(--red-500); animation:blink 1.15s steps(1,end) infinite}
.status.is-bob .status__dot{background:rgba(34,119,170,.2); border-color:rgba(34,119,170,.55); color:#AFD6EC}
.status.is-bob .status__dot i{background:var(--blue-700)}
.status.is-done .status__dot{background:rgba(77,179,99,.16); border-color:rgba(77,179,99,.5); color:#BDE8C7}
.status.is-done .status__dot i{background:var(--green-500)}
@keyframes blink{0%,60%{opacity:1} 61%,100%{opacity:.25}}
.status__hint{margin-top:.65rem; font-size:.9375rem; color:#8FAAC3; min-height:1.4em}

/* Countdown. A ring rather than a number, so it reads as pressure without
   turning into a stopwatch the learner starts racing. */
.timer{display:flex; align-items:center; justify-content:center; gap:.7rem}
.timer svg{transform:rotate(-90deg)}
.timer circle{fill:none; stroke-width:3.5; stroke-linecap:round}
.timer .bg{stroke:rgba(255,255,255,.14)}
.timer .fg{stroke:var(--gold-500); transition:stroke-dashoffset .3s linear, stroke .3s var(--ease)}
.timer.is-low .fg{stroke:var(--red-500)}
.timer b{font-family:var(--font-display); font-size:1rem; font-variant-numeric:tabular-nums; color:#CBDAEA}

.call__controls{display:flex; flex-direction:column; gap:.7rem}
.call__controls .btn{width:100%}
.linkbtn{
  background:none; border:0; padding:.4rem; cursor:pointer; font-family:var(--font-body);
  font-size:.9375rem; font-weight:600; color:#8FAAC3; text-decoration:underline;
  text-underline-offset:3px; text-decoration-thickness:1px;
}
.linkbtn:hover{color:var(--gold-500)}

/* ---------- Transcript ---------- */
.tr{
  display:flex; flex-direction:column; min-height:420px; overflow:hidden;
  background:rgba(255,255,255,.045); border:1px solid rgba(255,255,255,.13);
  border-radius:var(--r-lg); backdrop-filter:blur(6px);
}
.tr__head{
  display:flex; align-items:center; gap:.7rem; padding:.85rem 1.15rem;
  border-bottom:1px solid rgba(255,255,255,.11); background:rgba(8,31,53,.35);
}
.tr__head b{font-family:var(--font-display); font-size:.75rem; letter-spacing:.14em;
  text-transform:uppercase; color:#BDD1E4}
.tr__head .sp{flex:1}
.tr__wc{font-size:.8125rem; color:#8FAAC3; font-variant-numeric:tabular-nums}
.tr__body{flex:1; overflow-y:auto; padding:1.15rem; display:flex; flex-direction:column; gap:1rem;
  max-height:min(52vh,460px); scrollbar-width:thin}
.tr__empty{margin:auto; text-align:center; color:#6D89A5; font-size:.9375rem; max-width:32ch; line-height:1.55}

.line{display:grid; gap:.35rem; animation:line-in .34s var(--ease-out) both}
@keyframes line-in{from{opacity:0; transform:translateY(9px)} to{opacity:1; transform:none}}
.line__who{
  display:flex; align-items:center; gap:.5rem;
  font-size:.6875rem; font-weight:700; letter-spacing:.13em; text-transform:uppercase; color:#7D9CBB;
}
.line__who time{font-weight:600; letter-spacing:.04em; color:#5F7C99; font-variant-numeric:tabular-nums}
.line__txt{
  font-size:1rem; line-height:1.6; padding:.75rem 1rem; border-radius:14px;
  background:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.09); color:#E6EEF7;
}
.line--bob .line__who{color:var(--blue-500)}
.line--bob .line__txt{background:rgba(34,119,170,.19); border-color:rgba(34,119,170,.34); color:#EAF4FB}
.line--you .line__who{color:var(--gold-500)}
.line--you .line__txt{background:rgba(239,179,96,.13); border-color:rgba(239,179,96,.3); color:#F7EEDF}
.line--live .line__txt{color:#F7EEDF; border-style:dashed}
/* Your words, one at a time: a recognised word fades in once and stays; the
   recogniser's current guess trails after it, lighter, until it is settled. */
.line--live .w.in{animation:w-in .28s var(--ease-out) both}
.line--live .guess{color:#9DB5CC; font-style:italic}
@keyframes w-in{from{opacity:0; filter:blur(2px)} to{opacity:1; filter:none}}
/* Bob's words light up as he says them (karaoke() in js/practice.js). */
.line--words .w{opacity:.26; transition:opacity .16s linear}
.line--words .w.on{opacity:1}
@media (prefers-reduced-motion:reduce){
  .line--live .w.in{animation:none}
  .line--words .w{transition:none}
}
.line__caret{display:inline-block; width:2px; height:1em; background:var(--gold-500);
  vertical-align:-.15em; margin-left:2px; animation:blink .9s steps(1,end) infinite}

/* Bob thinking. The wait shown where the wait is, rather than only in the
   status panel the learner is not looking at - a conversation that stops dead
   for six seconds reads as broken, and a turning ring reads as working. */
.line--thinking .line__txt{
  display:inline-flex; align-items:center; gap:.6rem;
  color:#A9C0D6; font-style:italic; border-style:dashed;
}
.spin{
  flex:0 0 auto; width:14px; height:14px; border-radius:50%;
  border:2px solid rgba(255,255,255,.22);
  border-top-color:var(--blue-500);
  animation:spin .8s linear infinite;
}
@keyframes spin{ to{ transform:rotate(360deg) } }

/* A ring that never stops is worse than no ring for anyone who needs motion
   kept still, so it becomes a slow pulse instead of spinning. */
@media (prefers-reduced-motion:reduce){
  .spin{ animation:pulse 1.6s ease-in-out infinite; border-top-color:var(--blue-500) }
  @keyframes pulse{ 0%,100%{ opacity:.35 } 50%{ opacity:1 } }
}

.typed{display:grid; gap:.75rem; padding:1.15rem; border-top:1px solid rgba(255,255,255,.11)}
.typed textarea{
  width:100%; min-height:120px; resize:vertical; font-family:var(--font-body); font-size:1rem;
  line-height:1.6; padding:.9rem 1rem; border-radius:14px; color:var(--white);
  background:rgba(8,31,53,.5); border:1.5px solid rgba(255,255,255,.18);
}
.typed textarea:focus{outline:0; border-color:var(--gold-500)}
.typed textarea::placeholder{color:#6D89A5}

/* ==========================================================================
   The scorecard
   ========================================================================== */
.report{max-width:940px; margin-inline:auto}
.score{
  display:grid; grid-template-columns:auto minmax(0,1fr); gap:clamp(1.25rem,3vw,2.25rem);
  align-items:center; padding:clamp(1.4rem,3vw,2rem);
  background:rgba(255,255,255,.055); border:1px solid rgba(255,255,255,.14);
  border-radius:var(--r-lg); backdrop-filter:blur(6px);
}
@media (max-width:640px){ .score{grid-template-columns:1fr; text-align:center; justify-items:center} }

/* Four segments, not a percentage. The learner has to see which of four,
   because "75%" hides the fact that one named step is missing. */
.dial{position:relative; width:132px; height:132px; flex:0 0 auto}
.dial svg{transform:rotate(-90deg)}
.dial .seg{fill:none; stroke-width:9; stroke-linecap:round; stroke:rgba(255,255,255,.13)}
.dial .seg.on{stroke:var(--green-500); transition:stroke .45s var(--ease)}
.dial .seg.off{stroke:rgba(199,11,22,.55)}
.dial__mid{position:absolute; inset:0; display:grid; place-content:center; text-align:center}
.dial__mid b{font-family:var(--font-display); font-weight:800; font-size:2.5rem; line-height:1;
  color:var(--white); font-variant-numeric:tabular-nums}
.dial__mid span{display:block; font-size:.6875rem; font-weight:700; letter-spacing:.15em;
  text-transform:uppercase; color:#8FAAC3; margin-top:.35rem}
.score h2{font-size:clamp(1.5rem,1.1rem + 1.4vw,2.1rem); line-height:1.12}
.score p{margin-top:.7rem; color:#BDD1E4; font-size:1.0625rem; line-height:1.6}

.crits{margin-top:clamp(1.25rem,2.5vw,1.75rem); display:grid; gap:.9rem}
.crit{
  display:grid; grid-template-columns:auto minmax(0,1fr); gap:1.1rem;
  padding:clamp(1.1rem,2.2vw,1.5rem); border-radius:var(--r-lg);
  background:var(--white); color:var(--blue-900);
  border:1px solid var(--border); border-left:4px solid var(--grey-500);
  box-shadow:var(--shadow-md);
  opacity:0; transform:translateY(16px);
  transition:opacity .5s var(--ease-out), transform .5s var(--ease-out);
  transition-delay:calc(var(--i,0) * 130ms);
}
.crit.is-in{opacity:1; transform:none}
.crit--pass{border-left-color:var(--green-500)}
.crit--fail{border-left-color:var(--red-500)}

/* The tick and the cross draw themselves. It is one line of CSS worth of
   showmanship and it makes four verdicts land one at a time instead of
   arriving as a wall. */
.mark{width:38px; height:38px; border-radius:11px; display:grid; place-items:center; flex:0 0 auto}
.crit--pass .mark{background:rgba(77,179,99,.14); color:var(--green-500)}
.crit--fail .mark{background:rgba(199,11,22,.10); color:var(--red-500)}
.mark path{stroke-dasharray:40; stroke-dashoffset:40}
.crit.is-in .mark path{animation:draw .45s var(--ease-out) forwards;
  animation-delay:calc(var(--i,0) * 130ms + 220ms)}
.crit.is-in .mark path:nth-child(2){animation-delay:calc(var(--i,0) * 130ms + 340ms)}
@keyframes draw{to{stroke-dashoffset:0}}

.crit__num{
  font-family:var(--font-display); font-weight:800; font-size:.75rem; letter-spacing:.14em;
  color:var(--blue-500); display:block; margin-bottom:.3rem;
}
.crit h3{font-size:1.1875rem; line-height:1.25; color:var(--content-title)}
.crit__desc{margin-top:.35rem; font-size:.9375rem; line-height:1.55; color:var(--content-subtle)}
.crit__verdict{margin-top:.85rem; font-size:1.0625rem; line-height:1.55; font-weight:600}
.crit--pass .crit__verdict{color:#2E7D45}
.crit--fail .crit__verdict{color:var(--red-600)}

/* Verbatim. The learner's own sentence, cut from the transcript and not
   rewritten, is the only thing in the panel they cannot argue with. */
.crit__quote{
  margin-top:.85rem; padding:.75rem 1rem; border-radius:12px;
  background:var(--blue-100); border-left:3px solid var(--gold-500);
  font-size:1rem; line-height:1.6; color:var(--content-body);
}
.crit__quote b{
  display:block; font-family:var(--font-display); font-size:.6875rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--blue-700); margin-bottom:.3rem; font-weight:800;
}
.crit__quote i{font-style:italic}
.crit__tip{
  margin-top:.8rem; display:flex; gap:.6rem; align-items:flex-start;
  font-size:.9688rem; line-height:1.55; color:var(--content-body);
}
.crit__tip svg{flex:0 0 auto; margin-top:.22rem; color:var(--gold-600)}
.crit__meta{margin-top:.7rem; font-size:.8125rem; color:var(--content-subtle)}

.report__actions{display:flex; flex-wrap:wrap; gap:.85rem; margin-top:1.75rem; align-items:center}
.report__actions .sp{flex:1}

/* ---------- Challenge strip ---------- */
.chal{margin-top:clamp(2rem,4vw,3rem); padding-top:1.75rem; border-top:1px solid rgba(255,255,255,.13)}
.chal h3{font-size:1.0625rem; letter-spacing:0}
.chal__grid{margin-top:1.1rem; display:grid; gap:.75rem;
  grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.chip-chal{
  display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:.7rem; align-items:center;
  text-align:left; padding:.85rem 1rem; border-radius:14px; cursor:pointer;
  background:rgba(255,255,255,.05); border:1px solid rgba(255,255,255,.13); color:#CBDAEA;
  font-family:var(--font-body); transition:.2s var(--ease);
}
.chip-chal:hover{background:rgba(255,255,255,.1); border-color:rgba(255,255,255,.28); transform:translateY(-2px)}
.chip-chal .n{font-family:var(--font-display); font-weight:800; font-size:.75rem; color:var(--blue-500)}
.chip-chal b{display:block; font-size:.9375rem; font-weight:700; color:var(--white); line-height:1.25}
.chip-chal small{display:block; font-size:.8125rem; color:#8FAAC3; margin-top:.15rem}
.chip-chal .lock{color:var(--gold-500); opacity:.85}
.chip-chal.is-current{border-color:var(--gold-500); background:rgba(239,179,96,.13)}
.chip-chal.is-free .lock{color:var(--green-500)}

/* ==========================================================================
   Overlays: the paywall and the checkout
   ========================================================================== */
.ov{
  position:fixed; inset:0; z-index:120; overflow-y:auto; padding:clamp(1rem,3vw,2.5rem);
  background:rgba(6,20,34,.74); backdrop-filter:blur(7px);
  animation:fade .2s var(--ease) both;
}
.ov[hidden]{display:none}
@keyframes fade{from{opacity:0} to{opacity:1}}
/* No overflow:hidden here, deliberately. It clipped the card, which made the
   card the sticky banner's containing block, which meant the banner scrolled
   away with it: on a phone the checkout is 1,700px tall and the "this is not
   real" notice was gone after one flick. The rounding moves to the two
   children instead, and the banner now sticks against the overlay itself. */
.ov__card{
  max-width:960px; margin-inline:auto; background:var(--white); color:var(--blue-900);
  border-radius:var(--r-xl); box-shadow:0 40px 110px rgba(0,0,0,.5);
  animation:rise .28s var(--ease-out) both;
}
.co,.paywall__body{border-radius:0 0 var(--r-xl) var(--r-xl); overflow:hidden}
@keyframes rise{from{opacity:0; transform:translateY(18px) scale(.985)} to{opacity:1; transform:none}}

/* ---------- The demo banner ----------
   Red, sticky, and present on both overlays. Everything below it is a
   mock-up of a checkout, and there must be no screen or scroll position at
   which that is not being said out loud. */
.fake{
  position:sticky; top:0; z-index:4; border-radius:var(--r-xl) var(--r-xl) 0 0; display:flex; gap:.7rem; align-items:flex-start;
  padding:.85rem clamp(1.1rem,3vw,1.75rem); background:var(--red-500); color:var(--white);
  font-size:.9375rem; line-height:1.5;
}
.fake svg{flex:0 0 auto; margin-top:.14rem}
.fake b{font-weight:700}
/* Closing the overlay. It lives in the banner rather than floating over the
   card because the banner is sticky and sits above everything else in the
   overlay: a button anywhere else was either underneath it or scrolled off
   the top. */
.fake__x{
  margin-left:auto; flex:0 0 auto; width:30px; height:30px; border-radius:50%;
  display:grid; place-items:center; cursor:pointer; color:var(--white);
  background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.5);
  transition:background-color .2s var(--ease);
}
.fake__x:hover{background:rgba(255,255,255,.32)}

/* ---------- Plans ---------- */
.paywall__body{padding:clamp(1.5rem,3.5vw,2.5rem); position:relative}
.paywall__body h2{font-size:clamp(1.5rem,1.1rem + 1.4vw,2rem); line-height:1.14; color:var(--content-title)}
.paywall__body > p{margin-top:.7rem; color:var(--content-body); font-size:1.0625rem; line-height:1.6; max-width:60ch}
.plans{margin-top:1.75rem; display:grid; gap:1rem; grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.plan{
  text-align:left; cursor:pointer; padding:1.35rem 1.4rem 1.4rem; border-radius:var(--r-lg);
  background:var(--white); border:2px solid var(--border); font-family:var(--font-body);
  display:flex; flex-direction:column; gap:.5rem; position:relative;
  transition:.2s var(--ease);
}
.plan:hover{border-color:var(--blue-700); transform:translateY(-3px); box-shadow:var(--shadow-md)}
.plan--best{border-color:var(--gold-500); background:linear-gradient(180deg,#FFFCF6,var(--white))}
.plan--best:hover{border-color:var(--gold-600)}
.plan__tag{
  position:absolute; top:-11px; left:1.4rem; font-size:.6875rem; font-weight:800; letter-spacing:.12em;
  text-transform:uppercase; background:var(--gold-500); color:var(--blue-900);
  padding:.25rem .6rem; border-radius:100px;
}
.plan__price{font-family:var(--font-display); font-weight:800; font-size:2.25rem; line-height:1;
  color:var(--content-title); letter-spacing:-.03em}
.plan__price sup{font-size:.9rem; vertical-align:super; margin-right:.1em; font-weight:700}
.plan__calls{font-weight:700; font-size:1.0625rem; color:var(--blue-900)}
.plan__per{font-size:.875rem; color:var(--content-subtle)}
.plan__go{
  margin-top:.6rem; display:inline-flex; align-items:center; gap:.4rem; font-weight:700;
  font-size:.9375rem; color:var(--blue-700);
}
.paywall__why{
  margin-top:1.5rem; padding:1rem 1.15rem; border-radius:var(--r-md);
  background:var(--blue-100); border:1px solid var(--border);
  font-size:.9375rem; line-height:1.6; color:var(--content-body);
}
.paywall__why b{color:var(--content-title)}

/* ---------- Checkout ----------
   Laid out the way a hosted checkout is laid out, because that is what makes
   it read as one at a glance. Every input is disabled: this page can be
   screenshotted and shown around, and it must not be possible to type a real
   card number into it even by accident. */
.co{display:grid; grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr); min-height:520px}
@media (max-width:820px){ .co{grid-template-columns:1fr} }
.co__left{padding:clamp(1.6rem,3.5vw,2.5rem); background:var(--blue-100); border-right:1px solid var(--border)}
@media (max-width:820px){ .co__left{border-right:0; border-bottom:1px solid var(--border)} }
.co__merchant{display:flex; align-items:center; gap:.7rem; font-weight:700; color:var(--content-title)}
.co__merchant img{height:19px; width:auto}
.co__back{
  display:inline-flex; align-items:center; gap:.45rem; margin-bottom:1.35rem; cursor:pointer;
  background:none; border:0; padding:0; font-family:var(--font-body); font-size:.9375rem;
  font-weight:600; color:var(--content-subtle);
}
.co__back:hover{color:var(--blue-700)}
.co__amt{margin-top:1.6rem}
.co__amt small{display:block; font-size:.9375rem; color:var(--content-body)}
.co__amt b{display:block; font-family:var(--font-display); font-weight:800; font-size:2.5rem;
  line-height:1.1; letter-spacing:-.03em; color:var(--content-title); margin-top:.2rem}
.co__lines{margin-top:1.75rem; border-top:1px solid var(--border)}
.co__line{display:flex; gap:1rem; padding:.8rem 0; border-bottom:1px solid var(--border); font-size:.9688rem}
.co__line .g{flex:1; color:var(--content-body)}
.co__line .g b{display:block; color:var(--blue-900); font-weight:700}
.co__line .g small{color:var(--content-subtle)}
.co__line .v{font-weight:700; white-space:nowrap; color:var(--blue-900)}
.co__line--tot{border-bottom:0; padding-top:1rem; font-size:1.0625rem}
.co__line--tot .v{font-family:var(--font-display); font-weight:800; font-size:1.25rem}
.co__gets{margin-top:1.5rem; display:grid; gap:.55rem}
.co__gets li{display:grid; grid-template-columns:16px 1fr; gap:.6rem; align-items:start;
  font-size:.9375rem; line-height:1.5; color:var(--content-body)}
.co__gets svg{margin-top:.28rem; color:var(--green-500)}

.co__co{margin-top:1.75rem; font-size:.8125rem; line-height:1.65; color:var(--content-subtle)}
.co__co b{display:block; color:var(--blue-900); font-size:.875rem; margin-bottom:.2rem}

.co__right{padding:clamp(1.6rem,3.5vw,2.5rem); position:relative}
.co__right h3{font-size:1.25rem; color:var(--content-title)}
.co__pay{
  margin-top:1.25rem; width:100%; display:flex; align-items:center; justify-content:center; gap:.6rem;
  padding:.95rem 1rem; border-radius:10px; border:1px solid #2B2E3A; background:#30313D; color:#fff;
  font-family:var(--font-body); font-weight:700; font-size:.9688rem; cursor:pointer;
}
.co__pay:hover{background:#3d3f4d}
.co__or{display:flex; align-items:center; gap:.9rem; margin:1.25rem 0; color:var(--content-subtle); font-size:.8125rem}
.co__or::before,.co__or::after{content:""; flex:1; height:1px; background:var(--border)}
.fld{margin-top:1rem}
.fld label{display:block; font-size:.8125rem; font-weight:600; color:#4b5563; margin-bottom:.35rem}
.fld input,.fld select{
  width:100%; padding:.72rem .8rem; border-radius:7px; border:1px solid #d4d8de;
  background:#fff; font-size:1rem; color:#1f2937;
  box-shadow:0 1px 1px rgba(16,24,40,.04);
}
.fld input:disabled,.fld select:disabled{background:#fbfbfc; color:#40495a; cursor:not-allowed; opacity:1}
.fld__row{display:grid; grid-template-columns:1fr 1fr; gap:.7rem}
.fld__card{position:relative}
.fld__card .brand{position:absolute; right:.7rem; top:2.05rem; display:flex; gap:.3rem; align-items:center}
.fld__card .brand span{
  font-size:.5625rem; font-weight:800; letter-spacing:.02em; color:#fff; background:#1a1f71;
  padding:.16rem .3rem; border-radius:3px;
}
.co__submit{
  margin-top:1.5rem; width:100%; padding:.95rem 1rem; border-radius:7px; border:0;
  background:#0570de; color:#fff; font-family:var(--font-body); font-weight:700; font-size:1rem;
  cursor:pointer; transition:background-color .2s var(--ease);
}
.co__submit:hover{background:#0461c4}
.co__foot{margin-top:1.25rem; display:flex; align-items:center; justify-content:center; gap:.5rem;
  font-size:.75rem; color:#6b7280}
.co__foot em{font-style:normal; font-weight:800; color:#4b5563; letter-spacing:-.01em}
.co__foot a{color:#6b7280; text-decoration:underline; text-underline-offset:2px}

/* ---------- Toast ---------- */
.toast{
  position:fixed; left:50%; bottom:1.75rem; transform:translate(-50%,220%); z-index:200;
  opacity:0; pointer-events:none;
  max-width:min(38rem,92vw); padding:.9rem 1.25rem; border-radius:100px;
  background:var(--ink-950); color:var(--white); font-size:.9375rem; font-weight:600;
  box-shadow:0 18px 44px rgba(0,0,0,.45); border:1px solid rgba(255,255,255,.16);
  transition:transform .35s var(--ease-out), opacity .25s var(--ease); text-align:center;
}
.toast.is-up{transform:translate(-50%,0); opacity:1; pointer-events:auto}

/* ---------- Footer ---------- */
.pfoot{
  border-top:1px solid rgba(255,255,255,.11); padding-block:1.5rem;
  font-size:.875rem; color:#8FAAC3;
}
.pfoot .wrap{display:flex; flex-wrap:wrap; gap:1rem; justify-content:space-between; align-items:center}
.pfoot a{color:#BDD1E4; text-decoration:underline; text-underline-offset:3px}
.pfoot a:hover{color:var(--gold-500)}

@media (prefers-reduced-motion:reduce){
  .crit{transition:none; opacity:1; transform:none}
  .crit .mark path{stroke-dashoffset:0; animation:none}
  .orb.is-speaking .orb__ring{animation:none}
  .ov,.ov__card,.line{animation:none}
  .status.is-live .status__dot i{animation:none}
}

/* ==========================================================================
   The two extra criteria

   From the challenge sheet, and not steps: a credible technical or operational
   detail of the rep's own, and the link from the positive difference to the
   value. No word list could ever check either - which is why they only became
   markable when the judge became a language model. They sit after the four
   steps and outside the dial, because missing one is not failing a step.
   ========================================================================== */
.p-extras{margin-top:2rem; padding-top:1.75rem; border-top:1px solid rgba(255,255,255,.12)}
.p-extras .p-eyebrow{margin-bottom:1rem}
.crit--extra{opacity:.92}
.crit--extra h3{font-size:1rem}

/* ==========================================================================
   The call on a phone (Oct 2026). Tested by hand on an iPhone: the old
   layout stacked a 240px Bob, the status, the buttons and then the
   transcript, so the newest line was always below the fold and the learner
   scrolled to read what Bob had just said. Now the call is one screen: a
   compact header row, the transcript filling the middle and always showing
   the newest line, and the buttons fixed at the bottom within thumb reach.
   body.in-call is set by show() in js/practice.js, on entering the call.
   ========================================================================== */
@media (max-width:760px){
  body.in-call .pfoot{display:none}
  body.in-call .p-main{padding:0}
  body.in-call #viewCall{padding-inline:12px}
  body.in-call .call{
    display:flex; flex-direction:column; gap:10px;
    height:calc(100dvh - 62px);
    padding:10px 0 calc(118px + env(safe-area-inset-bottom));
  }
  body.in-call .call__side{
    display:grid; grid-template-columns:52px minmax(0,1fr) auto; align-items:center; gap:2px 12px;
  }
  body.in-call .orb{width:52px; margin:0}
  body.in-call .orb__ring, body.in-call .orb__pulse{inset:-5px}
  body.in-call .orb__face{box-shadow:none}
  body.in-call .status{text-align:left; min-width:0}
  body.in-call .status__dot{font-size:.6875rem; padding:.3rem .65rem}
  body.in-call .status__hint{margin-top:.3rem; font-size:.8125rem; line-height:1.35; min-height:0}
  body.in-call .timer{gap:.4rem}
  body.in-call .timer svg{width:34px; height:34px}
  body.in-call .timer b{font-size:.875rem}
  body.in-call .call__controls{
    position:fixed; left:0; right:0; bottom:0; z-index:70;
    flex-direction:row; flex-wrap:wrap; justify-content:center; align-items:center; gap:.35rem .9rem;
    padding:.75rem 12px calc(.75rem + env(safe-area-inset-bottom));
    background:rgba(8,31,53,.94); backdrop-filter:blur(12px);
    border-top:1px solid rgba(255,255,255,.12);
  }
  body.in-call .call__controls .btn{flex:1 1 100%; min-height:52px}
  body.in-call .call__controls .linkbtn{padding:.25rem .4rem; font-size:.875rem}
  body.in-call .tr{flex:1; min-height:0}
  body.in-call .tr__head{padding:.6rem .9rem}
  body.in-call .tr__body{max-height:none; padding:.85rem; gap:.75rem}
  body.in-call .line__txt{font-size:.9375rem; padding:.6rem .8rem}
  body.in-call .typed textarea{min-height:110px}
}

/* The brief on a phone: a shorter Bob, so "Start practising" is on the
   first screen rather than below a portrait taller than the screen. */
@media (max-width:760px){
  .p-intro{gap:1.25rem}
  .bob--tall img{aspect-ratio:16/10; object-position:50% 22%}
  .p-intro__body .p-steps li{font-size:.9375rem}
}

/* The reviewer comment button (js/feedback.js, preview only) sat on top of
   "End the call" on a phone. During a call, lift it above the button bar:
   the transform makes this box the containing block of its fixed button. */
@media (max-width:760px){
  body.in-call tkn-feedback{position:fixed; left:0; right:0; top:auto; bottom:122px; height:0; transform:translateZ(0)}
}
