/* Timely Elite pricing page.
   Sits on top of css/individual-home.css and borrows its tokens, so this file
   only describes what the marketing site doesn't already have: the price card,
   the plan toggle, and the feature/FAQ grids.

   Flat colour only — no gradients anywhere in Timely. */

/* --- Header ---------------------------------------------------------------
   The shared .site-header is built for the home page: `1fr auto 1fr` for
   brand / nav / actions, and `color: var(--cream)` because it starts over a
   dark hero and only inks itself once scrolled.

   Neither holds here. With the nav gone the third column strands the button in
   the middle, and this page is cream from the very first pixel — so the
   default cream text and the cream "Get the app" button are both invisible
   until you scroll. It gets its scrolled appearance from the start instead.

   Solid cream rather than the home page's translucent-plus-blur: this header
   never sits over a hero worth seeing through, and the frosted version let the
   price card ghost through it while the blur painted its own misplaced
   rectangle across the bar. Opaque hides what scrolls under it, every time. */

.site-header.is-minimal {
  grid-template-columns: 1fr auto;
  color: var(--ink);
  background: var(--cream);
  box-shadow: 0 1px 0 var(--line);
}
.site-header.is-minimal .button-cream {
  color: var(--cream);
  background: var(--brown);
}
.site-header.is-minimal .button-cream:hover { background: var(--brown-deep); }

/* Clear the fixed header. */
#main { padding-top: 82px; }

.notice {
  width: var(--shell);
  margin: 24px auto -8px;
  padding: 14px 18px;
  border-radius: 14px;
  font-size: 0.9375rem;
  line-height: 1.5;
  background: var(--paper);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line);
}
.notice[data-tone="good"] {
  background: #E8F5EA;
  color: #24603A;
  box-shadow: inset 0 0 0 1px rgba(36, 96, 58, 0.18);
}
.notice[data-tone="bad"] {
  background: #FBEBEA;
  color: #8C2F2A;
  box-shadow: inset 0 0 0 1px rgba(140, 47, 42, 0.18);
}
/* "Back to Timely" after a successful checkout. Inherits the notice's colour
   so it reads as part of the sentence, underlined so it still reads as a link. */
.notice-action {
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}

/* --- Hero + price card ---------------------------------------------------- */

.price-section {
  width: var(--shell);
  margin: 0 auto;
  padding: 72px 0 56px;
  text-align: center;
}

.price-section .eyebrow {
  margin: 0 0 14px;
}

.price-section h1 {
  font-family: var(--display);
  font-size: clamp(2.25rem, 5.5vw, 3.5rem);
  font-weight: 300;
  letter-spacing: -0.035em;
  line-height: 1.04;
  margin: 0 0 18px;
}
.price-section h1 em {
  font-style: normal;
  color: var(--brown);
}

.price-lede {
  max-width: 46ch;
  margin: 0 auto 40px;
  color: var(--muted);
  font-size: 1.0625rem;
  line-height: 1.6;
}

.price-card {
  width: min(100%, 460px);
  margin: 0 auto;
  padding: 30px 28px 26px;
  border-radius: 26px;
  background: var(--paper);
  box-shadow: 0 18px 44px rgba(53, 30, 19, 0.10);
}

.plan-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 4px;
  margin: 0 0 26px;
  border-radius: 999px;
  background: var(--cream-deep);
}

/* One pill that slides, rather than two backgrounds crossfading. The tabs are
   different widths (Yearly carries a badge), so JS measures the active tab and
   sets both offset and width — a CSS-only version would need them equal, and
   forcing that makes "Monthly" sit in a box too wide for it. */
.plan-indicator {
  position: absolute;
  top: 4px;
  left: 0;
  height: calc(100% - 8px);
  border-radius: 999px;
  background: var(--paper);
  box-shadow: 0 2px 6px rgba(53, 30, 19, 0.12);
  transition: transform 380ms cubic-bezier(.34, 1.3, .5, 1),
              width 380ms cubic-bezier(.34, 1.3, .5, 1);
  pointer-events: none;
}
/* No slide on first paint — the pill should already be under Yearly, not
   travel there from the left edge while the page is still settling. */
.plan-toggle:not(.is-ready) .plan-indicator { transition: none; }

.plan-tab {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 20px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: color 260ms ease, transform 140ms ease;
}
.plan-tab:active { transform: scale(0.97); }
.plan-tab.is-active { color: var(--ink); }
.plan-tab:focus-visible {
  outline: 2px solid var(--brown);
  outline-offset: 2px;
}

.save-badge {
  transition: opacity 220ms ease, transform 220ms ease;
}
/* `display: inline-block` beats the `hidden` attribute's `display: none` on
   purpose — a badge that is removed from the box model can't be transitioned,
   it just pops. The negative margin cancels the flex gap it would still claim. */
.save-badge[hidden] {
  display: inline-block;
  opacity: 0;
  transform: scale(0.8);
  width: 0;
  padding: 0;
  margin-left: -8px;
  overflow: hidden;
  white-space: nowrap;
}

.save-badge {
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(88, 209, 116, 0.22);
  color: #1F7A3D;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.price-figure {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  font-variant-numeric: tabular-nums;
  /* Reserved height, so swapping yearly↔monthly doesn't make the card jump. */
  min-height: 3.5rem;
}
.price-amount {
  font-family: var(--display);
  font-size: 3rem;
  font-weight: 300;
  letter-spacing: -0.04em;
  line-height: 1;
}
.price-period {
  color: var(--muted);
  font-size: 1rem;
}

/* The price drop. The figure above is the new price, so this line's job is to
   name the old one next to it — badge, struck "was", arrow, "now". Hidden by
   js/upgrade.js the moment the old figure stops being higher than the charged
   one, which is what keeps it from ageing into a false claim. */
.price-drop {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 12px 0 0;
  font-size: 0.9375rem;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.price-drop[hidden] { display: none; }
.price-drop-badge {
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(88, 209, 116, 0.22);
  color: #1F7A3D;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.price-drop-figures {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}
.price-drop s { color: var(--muted); opacity: 0.75; }
.price-drop-arrow { color: var(--muted); }
.price-drop strong { font-weight: 700; }

.price-compare {
  margin: 10px 0 0;
  font-size: 0.9375rem;
  color: var(--muted);
}
.price-compare s { margin-right: 6px; opacity: 0.75; }
.price-compare[hidden] { display: none; }

.price-effective {
  margin: 6px 0 24px;
  min-height: 1.4em;
  font-size: 0.875rem;
  color: var(--muted);
}

/* Switching plan: the old figure leaves, the new one arrives. Without this the
   number simply teleports, which on the one element the page is *about* reads
   as a glitch rather than a change. The figure block has a reserved height, so
   nothing below it moves while this happens. */
.price-figure,
.price-drop,
.price-compare,
.price-effective {
  transition: opacity 200ms ease, transform 260ms cubic-bezier(.2,.75,.2,1);
}
.price-card.is-swapping .price-figure,
.price-card.is-swapping .price-drop,
.price-card.is-swapping .price-compare,
.price-card.is-swapping .price-effective {
  opacity: 0;
  transform: translateY(6px);
}

.price-cta {
  width: 100%;
  justify-content: center;
}
.price-cta[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}
/* The label swaps to "Opening checkout…" — reserve the room so it can't reflow
   the card at the exact moment someone is committing to pay. */
.price-cta { min-height: 52px; }

.price-note {
  margin: 14px 0 0;
  font-size: 0.8125rem;
  color: var(--muted);
  line-height: 1.5;
}

/* "Not you?" after the account line — a real button (it signs out), dressed as
   the link it reads as, so it sits inside the sentence rather than under it. */
.note-action {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--brown);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
  cursor: pointer;
}
.note-action:disabled { cursor: default; opacity: 0.6; }

.price-fineprint {
  max-width: 52ch;
  margin: 26px auto 0;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--muted);
}
.price-fineprint a { color: var(--brown); }

/* --- Features ------------------------------------------------------------- */

.features {
  /* Narrower than the full shell: at 1216px the cards stretch wide enough that
     two lines of body copy look like a caption under a heading rather than a
     paragraph. */
  width: min(var(--shell), 1040px);
  margin: 0 auto;
  padding: 24px 0 72px;
}
.features h2,
.elite-faq h2 {
  font-family: var(--display);
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: 400;
  letter-spacing: -0.025em;
  margin: 0 0 26px;
  text-align: center;
}

/* Three columns, fixed — not auto-fit. auto-fit gave four columns on a wide
   screen and left the last feature sitting alone on a row of its own. The
   tenth feature ("Timely on the web") reopens that problem by design, and the
   :last-child rule below is the answer to it. */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
/* A last card that would start a new row on its own fills the row instead.
   Ten features into three columns leaves one orphan, which reads as a mistake;
   this makes it read as the closing note it is. Self-correcting — add or
   remove a feature and the rule simply stops applying.

   Scoped to the three-column layout: at two columns ten cards divide evenly,
   so there is no orphan to fix and the rule would stretch a card for nothing. */
@media (min-width: 901px) {
  .feature-grid > .feature:last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
  .feature-grid { grid-template-columns: repeat(2, 1fr); }
  /* Same idea, two columns: only bites on an odd number of cards. */
  .feature-grid > .feature:last-child:nth-child(2n + 1) { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .feature-grid { grid-template-columns: 1fr; }
}

.feature {
  padding: 22px 24px;
  border-radius: 20px;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--line);
}
.feature h3 {
  margin: 0 0 8px;
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.feature p {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--muted);
}

/* --- FAQ ------------------------------------------------------------------
   `elite-faq`, NOT `faq`. individual-home.css already owns `.faq` as a
   two-column grid (`grid-template-columns: .85fr 1.15fr; gap: 9vw`) for the
   home page, and `.faq-list` restyles the summaries on top of that. Reusing
   either name here threw the heading into one column, the questions into the
   other, and 9vw of air between everything. */

.elite-faq {
  width: min(var(--shell), 720px);
  margin: 0 auto;
  padding: 0 0 96px;
}

.elite-faq-item {
  border-radius: 16px;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--line);
  margin-bottom: 8px;
  overflow: hidden;
  transition: box-shadow 240ms var(--ease-soft, cubic-bezier(.2,.75,.2,1));
}
.elite-faq-item[open] {
  box-shadow: inset 0 0 0 1px rgba(53, 30, 19, 0.24);
}

.elite-faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 17px 20px;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: -0.005em;
  list-style: none;
}
.elite-faq-item summary::-webkit-details-marker { display: none; }

/* A plus that becomes a minus by rotating, rather than swapping glyphs. */
.elite-faq-item summary::after {
  content: '';
  flex: none;
  width: 11px;
  height: 11px;
  background:
    linear-gradient(var(--brown-soft), var(--brown-soft)) center/100% 1.5px no-repeat,
    linear-gradient(var(--brown-soft), var(--brown-soft)) center/1.5px 100% no-repeat;
  transition: transform 260ms cubic-bezier(.2,.75,.2,1);
}
.elite-faq-item[open] summary::after {
  transform: rotate(135deg);
}

.elite-faq-item p {
  margin: 0;
  padding: 0 20px 18px;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--muted);
}

/* Height animation without a fixed height: the wrapper row goes 0fr → 1fr.
   `<details>` has no transitionable open state on its own, so the content is
   animated instead and the element only ever holds its natural size. */
.elite-faq-item p {
  display: block;
}
@supports (grid-template-rows: 1fr) {
  .elite-faq-item > p {
    display: grid;
    grid-template-rows: 1fr;
    animation: faq-open 300ms cubic-bezier(.2,.75,.2,1);
  }
}
@keyframes faq-open {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* --- Entry ---------------------------------------------------------------
   The hero rises on load; the cards below rise as they are scrolled to
   (individual-home.js observes `.reveal`). One curve and one distance for
   both, so the page reads as a single movement rather than two effects.
   `--i` staggers each item without a per-element rule. */

.rise {
  opacity: 0;
  transform: translateY(14px);
  animation: rise 620ms cubic-bezier(.2,.75,.2,1) forwards;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@keyframes rise {
  to { opacity: 1; transform: none; }
}

/* Scroll reveal, hidden ONLY once scripting has announced itself. `.has-anim`
   is set by an inline script in <head>, so this never applies to a browser
   that can't undo it — the failure mode of an animation must not be a blank
   section. `[data-reveal]` rather than `.reveal` so individual-home.js's own
   observer (which owns `.reveal`) doesn't fight over these. */
.has-anim [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 620ms cubic-bezier(.2,.75,.2,1),
              transform 620ms cubic-bezier(.2,.75,.2,1);
  transition-delay: calc(var(--i, 0) * 60ms);
}
.has-anim [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

@media (max-width: 640px) {
  .price-section { padding: 48px 0 40px; }
  .price-card { padding: 26px 20px 22px; }
  .price-amount { font-size: 2.5rem; }
  .elite-faq { padding-bottom: 64px; }
}

/* Everything above is decoration. Someone who has asked for less movement gets
   the page with none of it — including the entry animation, which must resolve
   to visible rather than being skipped mid-way and leaving content at opacity 0. */
@media (prefers-reduced-motion: reduce) {
  .plan-tab,
  .plan-indicator,
  .price-figure,
  .price-drop,
  .price-compare,
  .price-effective,
  .elite-faq-item,
  .elite-faq-item summary::after { transition: none; }
  .plan-tab:active { transform: none; }
  .rise { animation: none; opacity: 1; transform: none; }
  .elite-faq-item > p { animation: none; }
  .price-card.is-swapping .price-figure,
  .price-card.is-swapping .price-drop,
  .price-card.is-swapping .price-compare,
  .price-card.is-swapping .price-effective { opacity: 1; transform: none; }
}
