/* unlock: ordered source sections, combined by the asset build. */
/* The course offer is a sheet over the tab bar. */
#unlock {
  position: fixed;
  inset: 0;
  z-index: 26;
  display: none;
  overflow-y: auto;
  overflow-anchor: none;
  background: var(--paper);
  color: var(--ink);
  border-top: var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) solid var(--paper);
  padding: 24px 18px calc(100px + var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)));
}
#unlock.show {
  display: block;
  animation: panel-enter 0.26s ease both;
}
.unlock-inner {
  display: grid;
  gap: 28px;
  max-width: 620px;
  margin: 0 auto;
}
.unlock-inner > * {
  min-width: 0;
}
/* ---------- the offer: a sheet over the tab bar ---------- */
/* Laid out like the store upgrade page the owner chose: a cross, four slides
   of what the full course holds with dots beneath, then "Choose your plan"
   (unlock-plans.css). It covers the phone's tab bar, as a store's upgrade page
   does, and its cross goes back to the tab you came from; on a laptop the side
   rail stays beside it. */
#unlock.is-offer {
  z-index: 40;
  padding: 0;
  border-top: 0;
}
/* A set width, so the slide strip's own length never widens the column. */
.unlock-offer {
  --offer-top: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 60px);
  position: relative;
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
  padding: var(--offer-top) 16px calc(var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)) + 28px);
  text-align: center;
}
.unlock-close {
  position: absolute;
  top: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 9px);
  right: 7px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink-3);
}
.unlock-close svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
}
.unlock-close:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}
/* One slide to a screen width, snapping, with the scroll bar hidden: the dots
   say where you are. */
.unlock-slide-track {
  display: flex;
  margin: 0 -16px;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  list-style: none;
}
.unlock-slide-track::-webkit-scrollbar {
  display: none;
}
.unlock-slide-track:focus-visible {
  border-radius: 12px;
  outline: 3px solid var(--focus-ring);
  outline-offset: -3px;
}
.unlock-slide {
  flex: 0 0 100%;
  padding: 0 20px;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}
/* Each slide's picture floats free, stickers on the page, with no disc. */
.unlock-slide-art {
  position: relative;
  display: block;
  width: 220px;
  height: 220px;
  margin: 0 auto;
}
.unlock-slide-art img {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.unlock-slide :is(h1, h2) {
  margin: 18px 0 0;
  color: var(--ink);
  font-size: 24px;
  font-weight: 900;
  line-height: 1.2;
  outline: none;
}
.unlock-slide p {
  min-height: 44px;
  margin: 8px 14px 0;
  color: var(--ink-2);
  font-size: 15.5px;
  font-weight: 700;
  line-height: 22px;
  text-wrap: balance;
}
/* Each dot is a 24px target that shows its slide. */
.unlock-dots {
  display: flex;
  justify-content: center;
  margin: 12px 0 0;
}
.unlock-dot {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
}
.unlock-dot::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line-2);
}
.unlock-dot[aria-current="true"]::before {
  background: var(--brand);
}
.unlock-dot:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: -2px;
}
/* A shorter screen starts the offer nearer the top. */
@media (max-height: 900px) {
  .unlock-offer {
    --offer-top: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 48px);
  }
}
@media (max-height: 700px) {
  .unlock-offer {
    --offer-top: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 40px);
  }
}
/* ---------- choose your plan ---------- */
/* Store plans stack, one compact row each (the owner, 1 Oct 2026): the name,
   its pill and terms on the left, the price and tick on the right; the
   selected plan wears blue and a green tick. */
.unlock-plans {
  display: grid;
  min-width: 0;
  gap: 10px;
  text-align: left;
}
.unlock-plan {
  position: relative;
  display: grid;
  min-width: 0;
  grid-template-columns: auto 1fr auto auto;
  grid-template-areas:
    "name pill price mark"
    "note note price mark";
  align-items: center;
  column-gap: 10px;
  padding: 12px 14px;
  border: 2px solid var(--line-2);
  border-radius: 18px;
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
}
.unlock-plan:has(:checked) {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--paper) 94%, var(--brand));
}
.unlock-plan:has(:focus-visible) {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}
.unlock-plan:has(:disabled) {
  cursor: default;
}
.unlock-plan-name {
  grid-area: name;
  font-size: 17px;
  font-weight: 800;
  line-height: 1.3;
}
.unlock-plan-price {
  grid-area: price;
  font-size: 24px;
  font-weight: 900;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
/* No label on a fill is dark: white on gold takes the gold drop (unlock-cta). */
.unlock-plan-pill {
  grid-area: pill;
  justify-self: start;
  padding: 3px 10px;
  border-radius: 999px;
  background: linear-gradient(150deg, #ffe25b, #ffc21b 55%, #ffb300);
  color: #fff;
  text-shadow: 0 1.5px 0 #b8790a;
  font-size: 12.5px;
  font-weight: 900;
  white-space: nowrap;
}
.unlock-plan-note {
  grid-area: note;
  padding-top: 2px;
  color: var(--ink-3);
  font-size: 12.5px;
  font-weight: 800;
  line-height: 1.3;
}
.unlock-plan-tag {
  position: absolute;
  top: -12px;
  right: 12px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--on-brand);
  font-size: 12px;
  font-weight: 900;
}
.unlock-plan-mark {
  grid-area: mark;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--line-2);
}
.unlock-plan-tick {
  width: 12px;
  height: 10px;
  fill: none;
  stroke: #fff;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  visibility: hidden;
}
.unlock-plan:has(:checked) .unlock-plan-mark {
  background: var(--correct);
}
.unlock-plan:has(:checked) .unlock-plan-tick {
  visibility: visible;
}
/* ---------- what it means, the action, the terms ---------- */
.unlock-fine {
  margin: 20px 14px 0;
  color: var(--ink-3);
  font-size: 13px;
  font-weight: 700;
  line-height: 18px;
  text-wrap: balance;
}
.unlock-fine b {
  color: var(--ink-2);
  font-weight: 900;
}
.unlock-offer .unlock-cta-wrap {
  margin-top: 18px;
}
/* The reference's blue button, pressed like the lesson buttons: only the face
   sinks into its base. */
.unlock-cta.is-blue {
  color: var(--on-brand);
  text-shadow: none;
  font-size: 18px;
}
.unlock-cta.is-blue::before {
  background: var(--brand-lip);
  box-shadow: none;
}
.unlock-cta.is-blue .unlock-cta-face {
  background: var(--brand);
  box-shadow: none;
}
.unlock-offer .unlock-checkout-status {
  margin: 12px 0 0;
}
/* The chosen plan's billing terms sit under the button, so their length never
   moves it. */
.unlock-offer .unlock-disclosure {
  margin-top: 14px;
}
.unlock-sandbox {
  width: fit-content;
  margin: 8px auto 0;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--ink-2);
  font-size: 12px;
  font-weight: 800;
}
.unlock-terms {
  margin: 16px 14px 0;
  color: var(--ink-3);
  font-size: 12.5px;
  font-weight: 700;
  line-height: 17px;
}
.unlock-terms a {
  color: var(--brand-ink);
}
.unlock-offer .unlock-questions {
  margin-top: 36px;
  text-align: left;
}
@media (max-width: 359px) {
  .unlock-plan {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "name price mark" "pill price mark" "note note note";
    padding: 12px;
  }
  .unlock-plan-price {
    font-size: 22px;
  }
  .unlock-plan-pill {
    padding: 3px 8px;
    font-size: 11px;
  }
}
@media (max-height: 700px) {
  .unlock-plans {
    gap: 8px;
  }
  .unlock-plan {
    padding: 10px 14px;
  }
  .unlock-fine {
    margin-top: 14px;
  }
  .unlock-offer .unlock-cta-wrap {
    margin-top: 14px;
  }
}
/* A quiet, wrapping row with comfortable touch targets, including Restore. */
.unlock-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 14px;
  margin-top: 12px;
}
.unlock-footer :is(a, button) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 4px 0;
  background: none;
  color: var(--brand-ink);
  font-size: 13px;
  font-weight: 700;
  line-height: 18px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.unlock-footer button:disabled {
  opacity: 0.55;
  cursor: wait;
}
.unlock-footer :focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: 4px;
}
.unlock-footer + .unlock-terms {
  margin-top: 4px;
}
/* The app's offer keeps its one action at the foot of the screen for the
   whole scroll, as store paywalls do (the owner, 1 and 3 Oct 2026): the
   chosen plan's billing terms, the button, any status under it and one quiet
   row of Restore, Terms and Privacy, which App Review needs beside a purchase.
   Nothing follows the bar, so it never lets go: the first screen is at least
   the phone's height, with the bar at its foot, and the plans scroll beneath
   it. */
.unlock-offer:not(.unlock-web) {
  padding-bottom: 0;
}
/* The cross stays put at the top as the bar does at the foot: it rests where it
   always has and sticks there, taking no room in the page, with the page's
   paper behind it so the offer scrolls beneath it. */
.unlock-offer:not(.unlock-web) > .unlock-close {
  position: sticky;
  top: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 9px);
  right: auto;
  z-index: 3;
  margin: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 9px - var(--offer-top)) -9px
    calc(var(--offer-top) - var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) - 53px) auto;
  background: var(--paper);
}
.unlock-screen {
  display: flex;
  flex-direction: column;
  min-height: calc(100dvh - var(--offer-top));
}
.unlock-body {
  padding-bottom: 20px;
}
.unlock-body > .unlock-terms {
  margin-top: 12px;
}
.unlock-bar {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: auto -16px 0;
  padding: 12px 16px calc(var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)) + 4px);
  border-top: 1px solid var(--line-2);
  background: var(--paper);
}
/* What scrolls beneath the bar fades into it rather than being cut. */
.unlock-bar::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: calc(100% + 1px);
  left: 0;
  height: 16px;
  background: linear-gradient(transparent, var(--paper));
  pointer-events: none;
}
.unlock-offer .unlock-bar .unlock-cta-wrap {
  margin-top: 0;
}
/* Only Weekly needs this line. Put it above the button so showing it does
   not move the button or leave an empty row below the test-purchase badge. */
.unlock-offer .unlock-bar .unlock-disclosure {
  margin: 0 8px 8px;
  font-size: 12px;
  line-height: 16px;
}
.unlock-bar .unlock-footer {
  margin-top: 0;
}
.unlock-bar .unlock-footer :is(a, button) {
  min-height: 36px;
}
/* The app's offer starts nearer the top, and its picture gives way on shorter
   phones, so the headline, ticks and plans all sit above the pinned button. */
.unlock-offer:not(.unlock-web) {
  --offer-top: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 44px);
}
.unlock-summary > img {
  display: block;
  width: 200px;
  height: 200px;
  margin: 0 auto 8px;
  object-fit: contain;
}
/* The app's offer leads with a big outcome headline, its last word in gold
   with a glimmer and no shadow (the owner, 1 Oct 2026). The word rests at the
   brightest gold that clears 3:1 on white for this large text; a bright band
   crosses it twice as the page opens, like the purchase button's sheen, and
   it is still within five seconds (WCAG 2.2.2). A browser that cannot paint
   text with a gradient shows the resting gold. */
.unlock-summary h1 {
  margin: 0 auto 12px;
  font:
    900 40px/1.08 Nunito,
    sans-serif;
  letter-spacing: -0.6px;
  max-width: 24ch;
  text-wrap: balance;
}
.unlock-key {
  color: #c38600;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .unlock-key {
    background: linear-gradient(105deg, #c38600 38%, #fff1b8 50%, #c38600 62%) 100% 0 / 300% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: unlock-key-glimmer 2.2s linear 0.4s 2 both;
  }
}
@keyframes unlock-key-glimmer {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .unlock-key {
    animation: none;
  }
}
.unlock-summary .unlock-list {
  margin: 0 auto;
  text-align: left;
  width: fit-content;
}
/* The plans sit at the foot of the first screen, just above the pinned button
   (the owner, 1 Oct 2026), however tall the phone; no heading sits over them. */
.unlock-screen > .unlock-body {
  display: flex;
  flex-direction: column;
  flex: 1;
}
.unlock-summary {
  margin-bottom: 16px;
}
.unlock-summary .unlock-list li {
  padding: 6px 0;
}
.unlock-screen .unlock-plans {
  margin-top: auto;
}
/* The website adds its terms above the button, so its picture is smaller on a
   tall phone and goes sooner on a shorter one, keeping the button on the first
   screen (a desktop keeps it whole, unlock-desktop.css). */
@media (min-height: 840px) {
  .unlock-web .unlock-summary > img {
    width: 160px;
    height: 160px;
  }
}
@media (max-height: 779px) {
  .unlock-web .unlock-summary > img {
    display: none;
  }
}
/* Shorter phones keep the plans above the pinned button: the picture shrinks
   (an iPhone 13 mini, then an iPhone 8 Plus), then goes (an iPhone SE), and the headline,
   ticks and plans close up. */
@media (max-height: 839px) {
  .unlock-summary > img {
    width: 120px;
    height: 120px;
  }
  .unlock-summary h1 {
    font-size: 36px;
  }
  .unlock-summary .unlock-list li {
    padding: 5px 0;
  }
}
@media (max-height: 779px) {
  .unlock-summary > img {
    width: 88px;
    height: 88px;
  }
}
@media (max-height: 700px) {
  .unlock-summary > img {
    display: none;
  }
  .unlock-summary h1 {
    margin-bottom: 8px;
    font-size: 34px;
  }
}
/* ---------- the purchase button's shine ---------- */
/* A soft light crosses the purchase button twice as the offer opens, and
   again when the full course is chosen once more, as store buttons invite a
   tap. It sits under the label, moves with the face when pressed, and is
   done inside five seconds, so it never keeps moving on the page (WCAG
   2.2.2). Reduced motion keeps the button still. */
.unlock-cta.is-shine .unlock-cta-face {
  overflow: hidden;
}
.unlock-cta.is-shine .unlock-cta-label {
  position: relative;
  z-index: 1;
}
.unlock-cta.is-shine .unlock-cta-face::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 40%;
  background: linear-gradient(100deg, transparent 0%, rgb(255 255 255 / 34%) 50%, transparent 100%);
  transform: translateX(-130%) skewX(-18deg);
  animation: unlock-cta-shine 2s ease-in-out 0.8s 2 both;
  pointer-events: none;
}
@keyframes unlock-cta-shine {
  0% {
    transform: translateX(-130%) skewX(-18deg);
  }
  55%,
  100% {
    transform: translateX(330%) skewX(-18deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .unlock-cta.is-shine .unlock-cta-face::after {
    display: none;
  }
}
/* ---------- the questions a buyer asks ---------- */
/* Below the offer's terms, on the web only. Each opens on tap, so the page
   scans as questions. */
.unlock-questions {
  margin-top: 32px;
}
.unlock-questions h2 {
  margin: 0 0 6px;
  color: var(--ink);
  font-size: 19px;
  font-weight: 900;
  line-height: 1.3;
  letter-spacing: -0.2px;
}
.unlock-questions details {
  border-bottom: 1px solid var(--line-1);
}
.unlock-questions summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 52px;
  padding: 12px 0;
  color: var(--ink);
  font-size: 16px;
  font-weight: 800;
  line-height: 1.35;
  list-style: none;
  cursor: pointer;
}
.unlock-questions summary::-webkit-details-marker {
  display: none;
}
.unlock-questions summary::after {
  content: "";
  flex: none;
  width: 9px;
  height: 9px;
  margin: 0 6px 4px 0;
  border-right: 3px solid var(--ink-3);
  border-bottom: 3px solid var(--ink-3);
  border-radius: 1px;
  rotate: 45deg;
  transition: rotate 0.2s var(--ease);
}
.unlock-questions details[open] > summary::after {
  margin-bottom: -4px;
  rotate: -135deg;
}
.unlock-questions details p {
  margin: 0 0 14px;
  color: var(--ink-2);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.5;
}
.unlock-questions a {
  color: var(--brand-ink);
  font-weight: 800;
}
/* The ticked list the gate a locked lesson opens shows. */
.unlock-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.unlock-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 0;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink);
}
.unlock-tick {
  flex: 0 0 22px;
  width: 22px;
  height: 22px;
  color: #d52b3a;
}
/* The gold button, on the Unlock tab and the gate. The hit area contains the
   face at both heights. Only the face sinks; the base stays below it, just
   like the lesson buttons. */
.unlock-cta-wrap {
  position: relative;
  margin-top: 20px;
  isolation: isolate;
}
.unlock-cta {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  padding: 0 0 6px;
  border-radius: 16px;
  /* No button label is dark: white, with the gold drop a passed paper's number
     wears (practice.css), which keeps it readable on the bright gold. */
  color: #fff;
  text-shadow: 0 2px 0 #b8790a;
  font-size: 17px;
  font-weight: 900;
  line-height: 1.3;
  touch-action: pan-y;
}
.unlock-cta::before {
  content: "";
  position: absolute;
  inset: 6px 0 0;
  border-radius: inherit;
  background: #efb315;
  box-shadow: 0 2px 0 #ce9209;
  pointer-events: none;
}
/* Moving descendants must not change the hit target near the upper edge. */
.unlock-cta * {
  pointer-events: none;
}
.unlock-cta-face {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  padding: 12px 16px;
  border-radius: inherit;
  background:
    linear-gradient(134deg, transparent 0 20%, #fff39470 20% 28%, transparent 28%) padding-box,
    linear-gradient(150deg, #ffe25b, #ffc21b 48%, #ffd139 80%, #ffbf12);
  box-shadow: inset 0 2px 0 #fff49a;
  transition:
    transform 0.1s var(--ease),
    filter 0.1s var(--ease);
}
.unlock-cta:not(:disabled):hover .unlock-cta-face {
  filter: brightness(1.05);
}
.unlock-cta.is-pressed:not(:disabled) .unlock-cta-face,
.unlock-cta:not(:disabled):active .unlock-cta-face {
  transform: translateY(6px);
}
.unlock-cta-label {
  min-width: 0;
  overflow-wrap: anywhere;
  text-align: center;
}
/* The website's plans share one button: it names the weekly price while
   Weekly is chosen (unlock-page.html). */
.unlock-cta-weekly,
.unlock-offer:has(#unlockPlanWeekly:checked) #unlockBuyLabel {
  display: none;
}
.unlock-offer:has(#unlockPlanWeekly:checked) .unlock-cta-weekly {
  display: inline;
}
.unlock-cta:disabled {
  cursor: default;
}
.unlock-cta:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 4px;
}
/* The native preview's way back to learning reads as a link, not a second offer. */
.unlock-keep {
  display: block;
  min-height: 48px;
  margin: 10px auto 0;
  padding: 12px 20px;
  border-radius: 12px;
  color: var(--brand-ink);
  font-size: 15px;
  font-weight: 800;
}
.unlock-keep:hover {
  background: var(--panel);
}
.unlock-checkout-status {
  margin: 12px 0 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--panel-2);
  color: var(--ink-2);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.45;
}
/* ---------- the gate ---------- */
.unlock-gate {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: end center;
  background: rgb(7 24 39 / 55%);
  animation: unlock-gate-in 0.2s ease both;
}
.unlock-gate-card {
  width: 100%;
  max-width: 540px;
  max-height: 100%;
  overflow-y: auto;
  padding: 22px 20px calc(22px + var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)));
  border-radius: 24px 24px 0 0;
  background: var(--paper);
  color: var(--ink);
  text-align: center;
  box-shadow: 0 -8px 30px rgb(0 0 0 / 18%);
  animation: unlock-gate-rise 0.26s var(--ease) both;
}
.unlock-gate-moose {
  display: block;
  width: 130px;
  height: 130px;
  margin: 0 auto 4px;
  object-fit: contain;
}
.unlock-gate-lock {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  margin: 4px auto 10px;
  border-radius: 50%;
  background: #e6ecf2;
  color: #46566a;
}
.unlock-gate-lock svg {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.unlock-gate-card h2 {
  margin: 0 0 6px;
  font-size: 22px;
  font-weight: 900;
  letter-spacing: -0.2px;
  line-height: 1.2;
  text-wrap: balance;
}
.unlock-gate-card > p {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.45;
  color: var(--ink-2);
}
.unlock-gate-card .unlock-list {
  text-align: left;
  margin: 8px auto 16px;
  max-width: 320px;
}
.unlock-gate-card .unlock-list li {
  padding: 5px 0;
  font-size: 14px;
}
.unlock-gate-card .unlock-cta-face {
  min-height: 64px;
}
.unlock-gate-secondary {
  display: block;
  width: 100%;
  min-height: 48px;
  margin-top: 12px;
  padding: 12px 16px;
  border: 2px solid var(--line-2);
  border-radius: 16px;
  background: var(--paper);
  color: var(--brand-ink);
  font-size: 14px;
  font-weight: 900;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  box-shadow: 0 4px 0 var(--line-2);
}
.unlock-gate-secondary:active {
  transform: translateY(4px);
  box-shadow: none;
}
body.unlock-gate-open {
  overflow: hidden;
}
@keyframes unlock-gate-in {
  from {
    opacity: 0;
  }
}
@keyframes unlock-gate-rise {
  from {
    transform: translateY(24px);
    opacity: 0;
  }
}
@media (min-width: 720px) {
  .unlock-gate {
    place-items: center;
    padding: 24px;
  }
  .unlock-gate-card {
    border-radius: 24px;
    padding-bottom: 22px;
  }
}
@media (min-width: 960px) {
  #unlock {
    left: var(--desktop-rail, 0px);
    padding: clamp(28px, 3.4vw, 64px) clamp(24px, 3.4vw, 64px) 36px;
  }
  .unlock-inner {
    max-width: none;
  }
}
@media (max-width: 359px) {
  .unlock-cta-wrap .unlock-cta {
    font-size: 14px;
    letter-spacing: 0.02em;
  }
}
@media (prefers-reduced-motion: reduce) {
  #unlock.show,
  .unlock-gate,
  .unlock-gate-card {
    animation: none;
  }
  .unlock-cta-face,
  .unlock-questions summary::after {
    transition: none;
  }
  .unlock-cta.is-pressed:not(:disabled) .unlock-cta-face,
  .unlock-cta:not(:disabled):active .unlock-cta-face {
    transform: translateY(0);
    filter: brightness(0.94);
  }
}
/* After a purchase: a full-screen tour on Practice tests' own blue
   (purchase-success.html), laid out as the owner's reference. Each slide is a
   big picture over one short line; the gold purchase button, with its sheen,
   and a quiet link stay put at the foot while the slides swipe. White on this
   blue clears only 3:1, so every white line is large text (19px bold or
   more), and the one small note sits on the deeper blue that clears 4.5:1. */
.purchase-success {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100dvh;
  padding: calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 24px) 16px
    calc(var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)) + 12px);
  background: var(--topic-banner);
  color: #fff;
  text-align: center;
}
/* A set width, as on the offer, so the strip never widens the column. */
.purchase-success > * {
  width: 100%;
  max-width: 440px;
}
.purchase-success .unlock-slide-track {
  flex: 1;
  align-items: center;
  margin: 0;
}
.purchase-success .unlock-slide-art {
  width: 240px;
  height: 240px;
}
/* Soft light rays behind the trophy, as in the reference. They stay still. */
.purchase-success .is-trophy .unlock-slide-art::before {
  content: "";
  position: absolute;
  inset: -48px;
  border-radius: 50%;
  background: repeating-conic-gradient(rgb(255 255 255 / 22%) 0deg 9deg, transparent 9deg 24deg);
  mask: radial-gradient(closest-side, #000 35%, transparent);
}
.purchase-success .unlock-slide :is(h1, h2) {
  margin: 28px 8px 0;
  color: #fff;
  font-size: 26px;
  line-height: 1.25;
  text-wrap: balance;
}
.purchase-success .unlock-slide b {
  text-decoration: underline 4px #ffc83a;
  text-underline-offset: 6px;
  text-decoration-skip-ink: none;
}
.purchase-success-note {
  margin: 16px 8px 0;
  padding: 8px 12px;
  border-radius: 12px;
  background: #a32f36;
  color: #fff;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.4;
}
.purchase-success .unlock-dot::before {
  background: rgb(255 255 255 / 45%);
}
.purchase-success .unlock-dot[aria-current="true"]::before {
  background: #fff;
}
/* The gold purchase button, in capitals like the practice tab's START. */
.purchase-success .unlock-cta {
  margin-top: 10px;
  letter-spacing: 0.8px;
  text-transform: uppercase;
}
/* The reference's quiet second action, large enough to clear 3:1 in white. */
.purchase-success-settings {
  min-height: 48px;
  margin-top: 6px;
  padding: 0;
  border: 0;
  background: none;
  color: #fff;
  font: inherit;
  font-size: 19px;
  font-weight: 800;
  cursor: pointer;
}
.purchase-success-settings:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 2px;
  border-radius: 8px;
}
/* The website offer uses its desktop space: the summary the app shows sits on
   the left and the plans and checkout in a card on the right. The native
   purchase sheet keeps its compact layout and its store-provided prices. */
@media (min-width: 1100px) {
  .unlock-offer.unlock-web {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
    column-gap: 64px;
    max-width: 1040px;
    padding: clamp(40px, 7vh, 80px) 32px 40px;
  }
  #unlock:not(.is-contextual) .unlock-web > .unlock-close {
    display: none;
  }
  .unlock-web .unlock-summary {
    margin-bottom: 0;
    text-align: left;
  }
  /* The artwork has 19px of transparent space above it and 7px to its left;
     these margins take that space up so its visible edges line up with the
     text. However short the window, a desktop keeps it whole. */
  .unlock-web .unlock-summary > img {
    display: block;
    width: 172px;
    height: 172px;
    margin: -19px 0 18px -7px;
  }
  .unlock-web .unlock-summary h1 {
    max-width: 13ch;
    margin: 0;
    font-size: clamp(32px, 2.7vw, 40px);
  }
  .unlock-web .unlock-summary .unlock-list {
    margin: 24px 0 0;
  }
  /* Status messages grow the card below its action without moving the button. */
  .unlock-web .unlock-checkout {
    align-self: start;
    min-width: 0;
    padding: 28px 24px;
    border: 2px solid var(--line-1);
    border-radius: 26px;
  }
  .unlock-web .unlock-fine {
    margin: 22px 0 0;
    line-height: 1.5;
  }
  .unlock-web .unlock-terms {
    margin: 18px 0 0;
    line-height: 1.5;
  }
  .unlock-web .unlock-questions {
    grid-column: 1 / -1;
    margin-top: 56px;
    padding-top: 28px;
    border-top: 2px solid var(--line-1);
  }
  .unlock-web .unlock-questions h2 {
    margin-bottom: 12px;
    font-size: 22px;
  }
}
