/* Paywall / plan picker — pw-* ---------------------------------------------
   Consumes the shared tokens declared in timeline.css (:root). Like account.css
   and integrations.css this file redefines its own primitives (alert, skeleton,
   sr-only) rather than importing across stylesheets, so it stays independently
   loadable.

   ONE COLUMN, EVERY WIDTH. The screen is a single centred sheet that grows its
   padding and type with the viewport and never changes shape. The previous
   version was a two-column card — product pitch on the left, purchase on the
   right — which reflowed into a different reading order on a phone and pushed
   the legal links and the "already subscribed" escape a screen and a half down.
   A column that is identical on a 320px phone, a tablet, a desktop browser and
   a Windows shell is one arrangement to design, to test and to get right.

   CAPPED, NOT FLUID. The sheet stops at 31rem however wide the window gets.
   A paywall is read, decided and left; stretching it to a 1600px monitor buys
   nothing and costs the measure.

   TOUCH FIRST. Every control clears 44px whether or not the pointer is coarse.
   The plan rows are the primary control here and they are much taller than that,
   which is deliberate: they are what most people press first.

   Sections
     1. Page shell and sheet
     2. Header
     3. Alerts
     4. Plan picker
     5. Trial steps
     6. Terms, calls to action, aside
     7. Assurances and footer
     8. Empty state
     9. Skeleton
    10. Responsive
    11. Accessibility and motion
--------------------------------------------------------------------------- */

/* 1. Page shell and sheet -------------------------------------------------- */

/* app.css sets no global border-box reset, so a sheet with this much padding
   would overflow its track and scroll the whole page sideways. Scoped here
   rather than fixed globally — a global change would silently resize every
   other screen in the app. */
.pw-screen,
.pw-screen * {
  box-sizing: border-box;
}

.pw-screen {
  display: flex;
  justify-content: center;
  /* Left and right insets as well as bottom: this screen is the entire viewport
     on a gated phone (the shell hides the tab bar), so it owns the cutout on a
     landscape notch too. */
  padding:
    clamp(1rem, 4vh, 3.5rem)
    calc(1rem + env(safe-area-inset-right, 0px))
    calc(2rem + env(safe-area-inset-bottom, 0px))
    calc(1rem + env(safe-area-inset-left, 0px));
  color: var(--ink-primary);
  font-family: 'DM Sans', system-ui, sans-serif;
}

.pw-sheet {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  width: 100%;
  max-width: 31rem;
  padding: 1.5rem 1.25rem;
  border: 1px solid var(--stone-200);
  border-radius: 1.25rem;
  background: var(--surface-elev);
  box-shadow:
    0 14px 38px rgba(74, 62, 46, 0.09),
    0 2px 8px rgba(74, 62, 46, 0.04);
}

/* 2. Header ---------------------------------------------------------------- */

.pw-head {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

/* Small, quiet, and load-bearing: it is what proves this screen belongs to the
   app the user just signed up to rather than being an interstitial that has
   grabbed their card details. The mark is the real lockup at the base 17px —
   never letterspaced, never uppercased, both of which the brand kit lists under
   misuse — and the margin below is the kit's clear space. */
.pw-mark {
  margin: 0 0 0.75rem;
}

.pw-heading {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.15;
  color: var(--ink-primary);
}

/* The only sentence on the screen that is not a price, a term or a control, and
   it is about the offer rather than the product. Nothing here explains what
   Headwayflow does: the reader has an account, and a pitch at this point reads
   as a stall between them and the button. */
.pw-subheading {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

/* 3. Alerts ---------------------------------------------------------------- */

.pw-alert-slot:empty {
  display: none;
}

.pw-alert {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid rgba(146, 106, 34, 0.32);
  border-radius: 12px;
  background: rgba(217, 176, 106, 0.16);
}

.pw-alert-msg {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.5;
  /* amber-600 rather than the 300/400 pair used on fills: this sits on a light
     wash and needs the dark end of the ramp to clear 4.5:1. */
  color: var(--amber-600);
}

/* The paywall while a checkout it launched is still outstanding. The pulse answers a real
   complaint — the page promised it would unlock on its own and then showed nothing at all for
   fifteen seconds, which reads as broken. Covered by the reduced-motion rule at the foot. */
.pw-alert-dot {
  flex: 0 0 auto;
  width: 0.5rem;
  height: 0.5rem;
  margin-top: 0.4rem;
  border-radius: 50%;
  background: var(--amber-500);
  animation: pw-pulse 1.4s ease-in-out infinite;
}

@keyframes pw-pulse {
  0%, 100% { opacity: 0.25; transform: scale(0.8); }
  50%      { opacity: 1;    transform: scale(1); }
}

/* 4. Plan picker ----------------------------------------------------------- */

.pw-plans {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

/* --ink-muted rather than --ink-faint, here and on every other small label on
   this sheet. --ink-faint (#8A8578) measures 3.7:1 on white — fine for the
   "doesn't compete" role it has elsewhere in the app, and short of 4.5:1 for
   text stating what something costs. Hierarchy on this screen is carried by
   size and weight instead, which survives both a bright phone outdoors and a
   reader who has turned contrast up. */
.pw-plans-legend {
  padding: 0;
  margin: 0 0 0.5rem;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.pw-plan-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  /* Room for the saving ribbon, which is half outside the first row's top edge.
     No overflow:hidden anywhere on this chain, for the same reason. */
  padding-top: 0.55rem;
}

.pw-plan {
  appearance: none;
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
  padding: 0.95rem 1rem;
  /* Always two pixels of border, so selecting a row cannot shift the layout by
     the one pixel a 1px→2px swap would cost. */
  border: 2px solid var(--stone-200);
  border-radius: 14px;
  background: var(--surface-elev);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    border-color 140ms ease,
    background-color 140ms ease,
    box-shadow 140ms ease;
}

.pw-plan:hover:not(:disabled):not(.is-selected) {
  border-color: var(--stone-300);
  background: var(--stone-50);
}

.pw-plan.is-selected {
  border-color: var(--stone-700);
  background: var(--stone-50);
}

.pw-plan:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.pw-plan:focus-visible {
  outline: 2px solid var(--stone-700);
  outline-offset: 3px;
}

/* Drawn rather than a real radio input: the whole row is the control, and a
   native input inside it would add a second focus stop to the same choice. The
   button carries role="radio" and aria-checked, so this is not information the
   screen reader needs — but it is the only thing a sighted reader has, which is
   why the ring is --stone-500 (4.4:1 on white) and not the softer --stone-300
   the row's own border uses. WCAG 1.4.11 wants 3:1 on whatever identifies a
   control's state, and this is it. */
.pw-plan-mark {
  position: relative;
  flex: 0 0 auto;
  width: 1.2rem;
  height: 1.2rem;
  border: 2px solid var(--stone-500);
  border-radius: 50%;
  background: var(--surface-elev);
  transition: border-color 140ms ease;
}

.pw-plan.is-selected .pw-plan-mark {
  border-color: var(--stone-700);
}

.pw-plan.is-selected .pw-plan-mark::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--stone-700);
}

.pw-plan-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.pw-plan-name {
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink-primary);
}

/* Wraps rather than truncates. A clipped price comparison is worse than a
   two-line one, and this line is the yearly plan's whole argument. */
.pw-plan-rate {
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

.pw-plan-figure {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.05rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.pw-plan-price {
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
  color: var(--ink-primary);
}

.pw-plan-period {
  font-size: 0.75rem;
  color: var(--ink-muted);
}

/* Shown when neither the store nor the catalogue could supply a number. It is
   narrow on purpose — it occupies the price column and must not push the plan
   name into a ragged wrap. */
.pw-plan-pending {
  max-width: 7.5rem;
  font-size: 0.72rem;
  line-height: 1.35;
  color: var(--ink-muted);
}

/* Half outside the row's top edge, which is why nothing on this chain clips.
   Right-aligned but inset past the price column's own padding so it reads as a
   ribbon on the card rather than a label on the number. */
.pw-plan-save {
  position: absolute;
  top: -0.6rem;
  right: 0.85rem;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--amber-400);
  color: var(--stone-800);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 5. Trial steps ----------------------------------------------------------- */

.pw-steps {
  list-style: none;
  margin: 0;
  padding: 0.95rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  border-radius: 14px;
  background: var(--stone-50);
}

.pw-step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding-left: 1.3rem;
}

/* Dot + connector, drawn rather than imaged so they inherit the token ramp. */
.pw-step::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.4rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--stone-300);
}

/* Amber is the app's one "time passing" signal, and the first step of a trial
   countdown is exactly that. It is not used as a generic highlight anywhere on
   this screen. */
.pw-step.is-now::before {
  background: var(--amber-400);
}

.pw-step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0.22rem;
  top: 1.02rem;
  bottom: -0.55rem;
  width: 1px;
  background: var(--stone-200);
}

.pw-step-when {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--ink-primary);
  font-variant-numeric: tabular-nums;
}

.pw-step-what {
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

/* 6. Terms, calls to action, aside ----------------------------------------- */

/* Sits immediately above the button and holds nothing else. Kept at readable
   size and above 4.5:1: the amount, the date and how to cancel are the terms of
   the commitment, not fine print. */
.pw-terms {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--ink-muted);
}

.pw-cta {
  appearance: none;
  width: 100%;
  min-height: 3.25rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.12rem;
  padding: 0.85rem 1.25rem;
  border: 0;
  border-radius: 14px;
  /* The darkest surface in the app, and the only thing on this sheet painted
     with it. Amber is reserved for live / time-passing signals — the saving
     ribbon and the trial's first dot — so it is not spent on the button. */
  background: var(--stone-800);
  color: var(--surface-base);
  font-family: inherit;
  cursor: pointer;
  transition: background-color 140ms ease;
}

.pw-cta:hover:not(:disabled) {
  background: var(--stone-700);
}

.pw-cta:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* The button that is actually running. It is disabled like its neighbour — pressing
   either one twice must not open two checkouts — but it is not unavailable, it is
   working, and its label is the only thing telling the reader so. 0.45 makes that
   label the hardest text on the sheet to read at precisely the moment it matters,
   and on the outlined variant, whose fill is already the sheet's own white, it
   nearly erases it. Progress reads as progress; the other button still dims. */
.pw-cta.is-busy:disabled {
  opacity: 1;
}

.pw-cta:focus-visible {
  outline: 2px solid var(--stone-700);
  outline-offset: 3px;
}

.pw-cta-main {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-align: center;
}

.pw-cta-sub {
  font-size: 0.78rem;
  font-weight: 600;
  opacity: 0.75;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* THE SECOND COMMITMENT — the free trial, on the Stripe channel, where the sheet
   offers both. It is a real button of the same footprint as the primary above it,
   not the text link it used to be. Buried under "Prefer to skip the trial?" the
   trial was invisible to the people who actually wanted one, and an offer nobody
   can find is not a softer offer, it is a missing one.

   EMPHASIS IS CARRIED BY WEIGHT, NOT BY HIDING. Filled versus outlined, first
   versus second, and the price on the filled one — that is the whole hierarchy.
   Both clear the same 3.25rem, both state what they charge and when, and neither
   is disguised as the other.

   An outline rather than a paler fill: a tint would put a second painted block on
   a sheet whose one painted block is meant to be the answer, and the two would
   then be told apart only by shade. A boundary survives greyscale, a bright phone
   outdoors and forced-colors; a shade does not. */
.pw-cta-alt {
  /* The filled button has no border, so matching its outer height means giving
     those 2px back out of the padding. Without this the two differ by 4px — small
     enough to read as a mistake rather than as a hierarchy. */
  padding: calc(0.85rem - 2px) calc(1.25rem - 2px);
  /* --stone-500 (4.4:1 on white), not the softer --stone-400 (2.9:1). This outline is
     the ONLY thing identifying the button as a control — its fill is the same white as
     the sheet behind it — so WCAG 1.4.11 applies to it at 3:1, and stone-400 misses.
     Same reasoning and same token as .pw-plan-mark above. */
  border: 2px solid var(--stone-500);
  background: var(--surface-elev);
  color: var(--ink-primary);
  transition:
    border-color 140ms ease,
    background-color 140ms ease;
}

.pw-cta-alt:hover:not(:disabled) {
  border-color: var(--stone-700);
  background: var(--stone-50);
}

/* The primary's caption is white at 0.75 opacity on --stone-800, which still
   clears 4.5:1. The same 0.75 applied to --ink-primary on a white sheet does not,
   and this caption states a price and a charge date. A real token instead. */
.pw-cta-alt .pw-cta-sub {
  opacity: 1;
  color: var(--ink-muted);
}

/* "or", on a rule, between the two. Not a bare gap: with one the second button
   reads as a second step of the first — press Subscribe, then press this — rather
   than as the alternative to it. Left audible, because that is exactly what it
   tells a screen reader too. */
.pw-or {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  /* Pulls the rule in from the sheet's own 1.25rem gap so it reads as sitting
     between the two buttons rather than floating equidistant from everything. */
  margin: -0.3rem 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.pw-or::before,
.pw-or::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--stone-200);
}

.pw-aside {
  margin: -0.5rem 0 0;
  text-align: center;
  font-size: 0.83rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

/* Shared quiet link, used for the skip path and every escape hatch. A raw
   button where the action is not a navigation, so it is keyboard-reachable and
   announced as an action, styled flat so it costs no attention next to the CTA.

   The colour is load-bearing rather than decorative: app.css sets a global
   violet `a { color: #594ae2 }`, so anchors using this class must override it. */
.pw-link {
  appearance: none;
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: var(--stone-700);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.pw-link:hover:not(:disabled) {
  color: var(--ink-primary);
}

.pw-link:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.pw-link:focus-visible {
  outline: 2px solid var(--stone-700);
  outline-offset: 2px;
  border-radius: 3px;
}

/* 7. Assurances and footer ------------------------------------------------- */

.pw-assurances {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.3rem 0.9rem;
  font-size: 0.75rem;
  color: var(--ink-muted);
}

.pw-assurances li {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.pw-assurances li::before {
  content: "";
  width: 0.28rem;
  height: 0.28rem;
  border-radius: 50%;
  background: var(--stone-300);
}

.pw-foot {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  /* margin-top:auto keeps the footer at the bottom of a sheet that is taller
     than its content, which is what the loading and empty states produce. */
  margin-top: auto;
  padding-top: 0.9rem;
  border-top: 1px solid var(--stone-200);
}

.pw-foot-row {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8rem;
  color: var(--ink-muted);
}

/* These are standalone controls, not links inside a sentence, so WCAG 2.5.8's
   24px minimum target applies to them and a bare 0.8rem line box is 19px.
   inline-block rather than vertical padding on an inline element: padding on an
   inline box grows the hit area without growing the line, which would leave two
   stacked rows with overlapping targets — worse than the small ones. */
.pw-foot .pw-link {
  display: inline-block;
  padding: 0.4rem 0.2rem;
}

.pw-foot-sep {
  color: var(--stone-300);
}

/* 8. Empty state ----------------------------------------------------------- */

.pw-empty {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.1rem 1rem;
  border: 1px solid var(--stone-200);
  border-radius: 14px;
  background: var(--stone-50);
}

.pw-empty-msg {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--ink-muted);
}

/* 9. Skeleton -------------------------------------------------------------- */

.pw-skeleton {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.pw-skel {
  display: block;
  border-radius: 12px;
  background: linear-gradient(
    90deg,
    rgba(138, 118, 89, 0.11) 25%,
    rgba(138, 118, 89, 0.19) 37%,
    rgba(138, 118, 89, 0.11) 63%
  );
  background-size: 400% 100%;
  animation: pw-shimmer 1.4s ease infinite;
}

/* Sized to the real thing, so the sheet does not resize when the plans land. */
.pw-skel-row  { height: 4.6rem; }
.pw-skel-note { height: 3.2rem; }
.pw-skel-cta  { height: 3.25rem; border-radius: 14px; }

@keyframes pw-shimmer {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* 10. Responsive ----------------------------------------------------------- */

/* Phones narrow enough that the price column and the plan's own supporting line
   would fight for the same row. The figure drops under the text instead of
   either one wrapping mid-number. */
@media (max-width: 22.5rem) {
  .pw-plan {
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: 0.4rem;
  }

  .pw-plan-figure {
    grid-column: 2;
    flex-direction: row;
    align-items: baseline;
    gap: 0.3rem;
    text-align: left;
  }

  .pw-plan-pending {
    max-width: none;
  }
}

@media (min-width: 30rem) {
  .pw-sheet {
    gap: 1.4rem;
    padding: 2rem 1.75rem;
    border-radius: 1.5rem;
  }

  .pw-heading {
    font-size: 1.85rem;
  }

  .pw-plan {
    padding: 1.05rem 1.15rem;
  }

  .pw-plan-price {
    font-size: 1.55rem;
  }
}

@media (min-width: 48rem) {
  .pw-sheet {
    padding: 2.35rem 2.25rem;
  }

  .pw-heading {
    font-size: 2rem;
  }
}

/* 11. Accessibility and motion --------------------------------------------- */

.pw-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Windows high contrast strips background colours, which would leave the
   selected plan row and the unselected ones identical — the one piece of state
   on the screen. Borders survive, so the selection is restated as one. */
@media (forced-colors: active) {
  .pw-plan {
    border-color: ButtonBorder;
  }

  .pw-plan.is-selected {
    border-color: Highlight;
  }

  .pw-plan.is-selected .pw-plan-mark::after {
    background: Highlight;
  }

  /* Both buttons are repainted in the same system pair, so the fill that separates
     the primary from the alternative is gone. The outline is all that is left of
     the distinction, and it has to be restated to survive. */
  .pw-cta-alt {
    border-color: ButtonBorder;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pw-screen * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
